Booil Jung

ROS2 Humble 완벽 공략 URDF 마스터하기

URDF(Unified Robot Description Format)는 로봇의 물리적 구조를 XML(Extensible Markup Language) 기반 포맷으로 설명하기 위한 표준이다.1 이는 단순히 로봇의 3D 모델을 렌더링하는 것을 넘어, 로봇의 기구학적(kinematic) 및 동역학적(dynamic) 특성을 정의하여 시뮬레이션과 제어에 활용할 수 있도록 하는 디지털 설계도와 같다.4 이 설계도의 핵심을 이루는 두 가지 기본 구성 요소는 바로 링크(Link)조인트(Joint)다.

링크(Link)는 로봇의 개별적인 강체(rigid body) 부품을 의미한다.2 강체란 외부에서 힘이 가해져도 그 모양이나 크기가 변하지 않는 이상적인 물체를 말하며, 로봇의 몸통, 팔의 마디, 다리, 바퀴 등이 모두 링크에 해당한다.1 각 링크는 고유의 질량, 관성, 형태, 색상 등의 물리적 및 시각적 속성을 가질 수 있다.

조인트(Joint)는 이러한 링크들을 서로 연결하는 관절의 역할을 한다.1 조인트는 두 링크가 서로에 대해 어떻게 움직일 수 있는지를 정의하며, 이는 로봇의 움직임을 구현하는 핵심 요소다. 예를 들어, 모터에 의해 회전하는 로봇 팔의 관절이나, 직선 운동을 하는 액추에이터 등이 조인트로 표현된다.2

결론적으로, 로봇의 전체 모델은 하나의 루트 링크(root link)에서 시작하여 여러 개의 링크와 조인트가 번갈아 가며 사슬(chain) 또는 트리(tree) 구조로 연결된 형태로 구성된다. 이 구조를 통해 로봇의 각 부분이 어떻게 연결되어 있고, 각 관절이 움직일 때 전체 로봇의 자세가 어떻게 변하는지를 수학적으로 계산할 수 있게 된다. 이것이 바로 URDF가 로봇의 움직임을 기술하는 기본 원리다.

로봇 모델링을 처음 접하는 개발자들은 종종 URDF를 RViz와 같은 시각화 도구에서 로봇의 3D 모델을 보여주기 위한 파일 정도로만 생각하는 경향이 있다.6 물론 시각화는 URDF의 중요한 기능 중 하나지만, 이는 빙산의 일각에 불과하다. URDF는 시각적 속성(<visual>) 외에도 물리적 충돌 속성(<collision>)과 관성 속성(<inertial>)을 상세히 정의할 수 있다.1 이러한 정보는 Gazebo와 같은 고성능 물리 시뮬레이터에서 로봇이 중력의 영향을 받고, 다른 물체와 충돌하며, 관성에 따라 움직이는 등 실제 세계와 유사한 물리 법칙을 따르도록 하는 데 필수적이다.1 따라서 URDF를 작성하는 행위는 단순히 3D 모델을 만드는 것을 넘어, 실제 로봇의 물리적 특성을 디지털 공간에 정밀하게 복제하여 현실적인 테스트와 검증이 가능한 ‘가상 프로토타입(virtual prototype)’을 제작하는 과정이라고 이해해야 한다. 이 개념을 명확히 인지하고 있어야 <inertial>이나 <collision> 같은 태그의 중요성을 제대로 이해하고, 시뮬레이션의 정확도를 높이는 방향으로 URDF를 설계할 수 있다.

URDF는 로봇의 각 구성 요소의 위치와 방향을 명확하게 기술하기 위해 표준화된 좌표계와 단위를 사용한다. 이를 정확히 이해하지 못하면 로봇이 의도치 않은 위치에 조립되거나 비정상적인 방향으로 움직일 수 있다.

URDF에서 사용하는 좌표계는 3차원 공간상의 위치를 나타내는 직교 좌표계(Cartesian coordinates)와 방향을 나타내는 오일러 각(Euler angles)의 조합으로 이루어진다.2

이 외에도 URDF에서 사용되는 물리량들은 다음과 같은 표준 단위를 따른다 9:

이러한 표준 단위를 일관되게 사용해야만 ROS 시스템 내의 다른 노드들(특히 물리 시뮬레이터)과 데이터를 원활하게 주고받을 수 있으며, 계산 오류를 방지할 수 있다.

<link> 태그는 로봇의 물리적인 부품, 즉 강체(rigid body)를 정의하는 가장 기본적인 블록이다. 각 링크는 고유한 이름을 가지며, 그 안에는 시각적, 물리적, 동역학적 특성을 정의하는 세 가지 중요한 하위 태그, 즉 <visual>, <collision>, <inertial>이 포함될 수 있다.5

<visual> 태그는 RViz와 같은 3D 시각화 도구에서 로봇이 어떻게 보일지를 결정하는 역할을 한다.1 사용자는 이 태그를 통해 링크의 모양, 크기, 색상, 텍스처 등을 정의할 수 있다. 하나의 링크는 여러 개의 <visual> 태그를 가질 수 있는데, 이 경우 각각의 시각적 요소들이 합쳐져서 하나의 복합적인 형태로 보이게 된다. 예를 들어, 몸체와 렌즈로 구성된 카메라를 표현할 때, 몸체용 <visual>과 렌즈용 <visual>을 각각 정의할 수 있다.5

<visual> 태그의 주요 하위 태그는 다음과 같다.

<collision> 태그는 Gazebo와 같은 물리 시뮬레이터에서 해당 링크가 다른 물체와 어떻게 충돌할지를 계산하는 데 사용되는 물리적 경계(collision geometry)를 정의한다.1 이 태그의 구조는 <visual> 태그와 거의 동일하며, <origin><geometry> 하위 태그를 가진다.5

여기서 가장 중요한 개념은 <visual><collision>은 서로 다를 수 있다는 점이다. 시각적으로는 매우 정교하고 복잡한 메쉬 파일을 사용하더라도, 충돌 계산에는 그보다 훨씬 단순한 기본 도형(box, cylinder 등)의 조합을 사용하는 것이 일반적이다. 이는 복잡한 메쉬 간의 충돌 검사가 엄청난 계산 부하를 유발하여 시뮬레이션 속도를 저하시키기 때문이다. 따라서 성능 최적화를 위해 충돌 모델은 로봇의 실제 외형을 충분히 근사하면서도 최대한 단순하게 만드는 것이 모범 사례로 꼽힌다.5 예를 들어, 수만 개의 폴리곤으로 이루어진 로봇 팔 링크의 시각 모델이 있더라도, 충돌 모델은 몇 개의 원기둥과 구의 조합으로 단순화할 수 있다.

<inertial> 태그는 링크의 관성 속성, 즉 질량(mass)과 관성 텐서(inertia tensor)를 정의한다. 이 정보는 동역학 시뮬레이션에서 링크가 힘과 토크에 어떻게 반응할지를 계산하는 데 필수적이다. 만약 이 태그가 생략되면 해당 링크는 질량과 관성이 0인, 즉 물리적으로 존재하지 않는 가상의 링크로 간주된다.2

<inertial> 태그의 하위 태그는 다음과 같다.

URDF를 작성할 때 <origin> 태그의 다중성과 그로 인한 좌표계의 계층 구조를 이해하는 것은 매우 중요하다. 많은 개발자들이 <link><joint> 태그에 각각 <origin>이 있고, 심지어 <visual>, <collision>, <inertial> 내부에도 <origin>이 존재한다는 사실에 혼란을 겪는다.5 이들의 관계를 명확히 파악하는 것이 디버깅의 핵심이다. 먼저, <joint> 태그 내부의 <origin>부모 링크의 좌표계를 기준으로 자식 링크의 좌표계가 어디에 위치하는지를 정의한다. 이것이 바로 로봇의 전체적인 뼈대를 이루는 TF(Transform) 트리의 기본 연결 관계를 설정하는 것이다.10 반면,

<link> 태그 내부의, 즉 <visual>, <collision>, <inertial> 태그 안에 있는 <origin>은, 방금 <joint>에 의해 정의된 해당 링크 자신의 좌표계를 기준으로 각 요소(시각적 형상, 충돌 형상, 질량 중심)가 얼마나 떨어져 있는지를 정의하는 로컬 오프셋이다.12

이 계층 구조를 이해하지 못하면 고질적인 문제에 부딪히게 된다. 예를 들어, 로봇의 바퀴를 10cm 옆으로 옮기고 싶을 때, <visual> 내부의 <origin>만 수정했다고 가정해보자. 이 경우 RViz에서는 바퀴가 움직인 것처럼 보일 것이다. 하지만 실제 바퀴 링크의 TF 프레임과 충돌 모델, 관성 중심은 원래 위치에 그대로 남아있게 된다. 그 결과, Gazebo 시뮬레이션에서는 로봇이 공중에서 움직이는 것처럼 보이거나, 충돌이 엉뚱한 곳에서 발생하는 등 비정상적인 동작을 보이게 된다. 따라서 URDF 디버깅의 핵심은 단순히 XML 문법을 확인하는 것을 넘어, tf2_tools나 RViz의 TF 디스플레이 기능을 사용하여 이 보이지 않는 좌표계들의 계층 구조(부모_링크_프레임 -> 자식_링크_프레임 -> visual/collision_프레임)가 자신의 의도대로 정확하게 구성되었는지 시각적으로 확인하는 것이다. 이 점을 명심해야 “RViz에서는 멀쩡한데 시뮬레이션이 이상해요”와 같은 난해한 문제의 근본 원인을 파악하고 해결할 수 있다.

<joint> 태그는 정적인 링크들을 연결하여 움직이는 로봇을 만드는 핵심 요소다. 이 태그는 두 링크 간의 상대적인 운동을 정의하며, 로봇의 자유도(Degrees of Freedom, DoF)를 결정한다.

<joint> 태그의 type 속성은 관절이 어떤 방식으로 움직일지를 결정한다.16 각 타입의 특징과 사용 사례를 정확히 이해하고 선택하는 것이 중요하다.

타입 (Type) 운동 방식 (Motion) 한계 (<limit>) 축 (<axis>) 주요 사용 예시
revolute 축 중심 회전 (한계 있음) 필수 (lower, upper) 필수 로봇 팔 관절, 특정 각도로 여닫는 그리퍼 2
continuous 축 중심 무한 회전 불필요 필수 구동 바퀴, 계속 회전하는 라이다(LIDAR) 센서 2
prismatic 축 방향 직선 운동 (한계 있음) 필수 (lower, upper) 필수 선형 액추에이터, 상하로 움직이는 리프트 메커니즘 2
fixed 움직임 없음 (두 링크를 고정) 불필요 불필요 카메라나 센서를 로봇 몸체에 단단히 부착할 때 6
floating 6-DOF (3D 공간 자유 이동/회전) 불필요 불필요 월드(world) 프레임과 로봇의 베이스 링크를 연결하여 공중에 떠 있는 것처럼 표현할 때 2
planar 평면상 이동 및 회전 불필요 필수 (평면의 법선벡터) 평면 위를 움직이는 로봇 (예: 호버크래프트) 2

모든 조인트는 반드시 두 개의 링크를 연결해야 하며, 이 연결 관계는 명확한 부모-자식 관계로 정의된다. 이는 로봇의 기구학적 구조가 트리(tree) 형태를 이루도록 보장한다.

움직이는 조인트(revolute, continuous, prismatic)는 운동의 방향과 범위를 정의하는 추가적인 정보가 필요하다.

이러한 태그들을 조합하여 로봇의 모든 관절을 정밀하게 정의함으로써, 비로소 디지털 로봇 모델에 생명력을 불어넣을 수 있게 된다.

순수한 XML 형식의 URDF 파일은 로봇이 복잡해질수록 길이가 기하급수적으로 늘어나고, 반복적인 코드가 많아져 가독성과 유지보수성이 급격히 떨어진다. Xacro(XML Macros)는 이러한 문제를 해결하기 위해 등장한 강력한 도구다. Xacro는 URDF 파일 내에서 변수, 수학식, 매크로, 조건문 등을 사용할 수 있게 해주는 전처리기(preprocessor)로, 코드를 더 간결하고, 모듈화하고, 재사용 가능하게 만들어준다.18

Xacro의 가장 기본적이면서도 강력한 기능은 반복되는 값을 변수로 만들어 한 곳에서 관리하는 것이다.

매크로는 Xacro의 꽃이라 할 수 있는 기능으로, 코드의 재사용성을 극대화한다. C언어의 함수처럼, 파라미터를 받는 재사용 가능한 XML 코드 블록을 정의할 수 있다.18

Xacro는 조건에 따라 특정 XML 블록을 포함하거나 제외하는 기능도 제공한다. 이는 런치 파일에서 전달된 인자값에 따라 URDF의 구성을 동적으로 변경하고자 할 때 매우 유용하다.15

활용 사례:

런치 파일에서 use_gazebo_plugin이라는 인자를 받아, 이 값이 true일 때만 Gazebo 시뮬레이션에 필요한 센서 플러그인 관련 코드를 URDF에 추가하도록 만들 수 있다.

<xacro:arg name="use_gazebo_plugin" default="false"/>

<xacro:if value="$(arg use_gazebo_plugin)">
  <gazebo reference="camera_link">
    <sensor type="camera" name="camera_sensor">
      </sensor>
  </gazebo>
</xacro:if>

이러한 방식은 실제 로봇을 구동할 때(플러그인이 필요 없을 때)와 시뮬레이션을 할 때(플러그인이 필요할 때) 동일한 Xacro 파일을 사용하면서도, 불필요한 의존성을 제거하고 상황에 맞는 최적의 URDF를 생성할 수 있게 해준다.8

Xacro의 진정한 가치는 단순한 코드 중복 제거를 넘어선다. 속성, 수학식, 매크로, 조건문을 전략적으로 조합하면, 로봇의 모든 핵심 설계 파라미터(치수, 질량, 부품의 유무 등)를 .xacro 파일 상단의 <xacro:property> 블록으로 모두 끌어올릴 수 있다. 이렇게 되면 .xacro 파일 자체가 로봇의 모든 설계 변수를 정의하는 일종의 ‘마스터 설정 파일(Design Configuration File)’ 역할을 하게 된다. 개발자는 더 이상 복잡한 XML 구조를 헤맬 필요 없이, 파일 상단의 설정 값 몇 개만 변경하여 로봇의 다양한 변형(예: 팔 길이 변경, 그리퍼 부착/제거, 센서 추가)을 손쉽게 생성하고 테스트할 수 있다. 이 관점을 적용하면, 단 하나의 잘 설계된 .xacro 파일로부터 실제 로봇 구동용 URDF, Gazebo 시뮬레이션용 URDF, MoveIt! 경로 계획용 URDF 등 목적에 맞는 다양한 버전의 로봇 설명을 효율적으로 생성하는 것이 가능해진다. 이는 단순한 코드 정리를 넘어, 로봇 개발 파이프라인 전체의 생산성을 극대화하는 핵심 전략이 된다.8

URDF 파일을 작성했다면, 이제 이를 ROS2 시스템에 로드하고 3D로 시각화하여 검증하는 과정이 필요하다. 이 워크플로우는 몇 가지 핵심 노드와 런치 파일의 유기적인 연동으로 이루어진다.

URDF 모델을 RViz2에 띄우기 위해서는 최소한 세 개의 노드가 필요하다: robot_state_publisher, joint_state_publisher, 그리고 rviz2. 이들의 역할과 데이터 흐름은 다음과 같다.

이 세 노드의 데이터 흐름을 요약하면 다음과 같다:

  1. joint_state_publisher_gui가 사용자의 슬라이더 조작에 따라 조인트 상태 값을 /joint_states 토픽으로 발행한다.
  2. robot_state_publisher/joint_states 토픽을 구독하여 현재 조인트 값을 얻고, robot_description 파라미터의 URDF 정보와 결합하여 TF 트리를 계산한다.
  3. 계산된 TF 정보는 /tf/tf_static 토픽으로 발행된다.
  4. rviz2/tf 토픽을 구독하여 TF 트리를 수신하고, 이를 바탕으로 robot_description의 시각 정보를 3D 공간에 렌더링한다.

ROS2에서는 여러 노드를 동시에 실행하고, 각 노드의 파라미터를 설정하며, 실행 순서를 제어하기 위해 런치 파일 시스템을 사용한다.26 ROS2 Humble에서는 Python 스크립트를 이용한 런치 파일 작성이 표준적인 방법이다.

URDF를 시각화하기 위한 런치 파일 작성 과정은 다음과 같다.

  1. 패키지 및 디렉토리 생성: URDF 관련 파일을 저장할 ROS2 패키지를 생성하고, 그 안에 launch, urdf, meshes, rviz 등의 디렉토리를 만든다.23

    cd ~/ros2_ws/src
    ros2 pkg create my_robot_description --build-type ament_python
    cd my_robot_description
    mkdir launch urdf meshes rviz
    
  2. setup.py 설정: 생성한 패키지의 setup.py 파일을 열어, launch, urdf, meshes, rviz 디렉토리 안의 파일들이 빌드 및 설치 과정에 포함되도록 data_files 항목을 수정해야 한다. 이는 ros2 launch 명령어가 해당 파일들을 찾을 수 있도록 하기 위함이다.13

    # setup.py
    import os
    from glob import glob
    from setuptools import setup
       
    package_name = 'my_robot_description'
       
    setup(
        #... 기타 설정...
        data_files=[
            ('share/ament_index/resource_index/packages',
                ['resource/' + package_name]),
            ('share/' + package_name, ['package.xml']),
            (os.path.join('share', package_name, 'launch'), glob('launch/*.launch.py')),
            (os.path.join('share', package_name, 'urdf'), glob('urdf/*')),
            (os.path.join('share', package_name, 'meshes'), glob('meshes/*')),
            (os.path.join('share', package_name, 'rviz'), glob('rviz/*')),
        ],
    )
    
  3. 런치 파일(display.launch.py) 작성: launch 디렉토리 안에 런치 파일을 생성하고, generate_launch_description() 함수 내에 노드 실행 로직을 작성한다.23

    다음은 robot_state_publisher, joint_state_publisher_gui, rviz2를 실행하는 완전한 런치 파일 예시다.

    import os
    from ament_index_python.packages import get_package_share_directory
    from launch import LaunchDescription
    from launch.substitutions import Command
    from launch_ros.actions import Node
       
    def generate_launch_description():
       
        # 패키지 경로 찾기
        pkg_path = get_package_share_directory('my_robot_description')
       
        # Xacro 파일 경로 설정
        xacro_file = os.path.join(pkg_path, 'urdf', 'my_robot.urdf.xacro')
       
        # Xacro 파일을 로드하여 robot_description 파라미터 생성
        robot_description_config = Command(['xacro ', xacro_file])
       
        # robot_state_publisher 노드
        robot_state_publisher_node = Node(
            package='robot_state_publisher',
            executable='robot_state_publisher',
            name='robot_state_publisher',
            output='screen',
            parameters=[{'robot_description': robot_description_config}]
        )
       
        # joint_state_publisher_gui 노드
        joint_state_publisher_gui_node = Node(
            package='joint_state_publisher_gui',
            executable='joint_state_publisher_gui',
            name='joint_state_publisher_gui',
            output='screen'
        )
       
        # RViz2 노드
        rviz_config_file = os.path.join(pkg_path, 'rviz', 'display.rviz')
        rviz_node = Node(
            package='rviz2',
            executable='rviz2',
            name='rviz2',
            output='screen',
            arguments=['-d', rviz_config_file]
        )
       
        # 런치 설명 반환
        return LaunchDescription([
            robot_state_publisher_node,
            joint_state_publisher_gui_node,
            rviz_node
        ])
    

    이 코드에서 가장 중요한 부분은 robot_state_publisherrobot_description 파라미터를 전달하는 부분이다. launch.substitutions.Command를 사용하여 xacro 명령어를 런치 타임에 실행하고, 그 출력(순수 URDF XML 문자열)을 파라미터 값으로 직접 전달한다.19 이 방식을 사용하면

    .xacro 파일을 수정할 때마다 수동으로 .urdf 파일을 생성할 필요가 없어 매우 편리하다.

    더 나아가, urdf_launch 패키지를 사용하면 위와 같은 런치 파일 작성을 더욱 간소화할 수 있다. 이 패키지는 URDF 시각화에 필요한 일반적인 런치 로직을 재사용 가능한 형태로 제공한다.29

런치 파일을 실행하면 RViz2 창이 열린다. 로봇 모델이 정상적으로 표시되게 하려면 몇 가지 설정을 확인해야 한다.31

  1. RViz2 실행 및 설정:

    cd ~/ros2_ws
    colcon build --packages-select my_robot_description
    source install/setup.bash
    ros2 launch my_robot_description display.launch.py
    
  2. RViz2 Displays 패널 설정:

    • Global Options -> Fixed Frame: RViz2 3D 뷰의 기준이 되는 좌표계를 설정하는 항목이다. 일반적으로 로봇의 루트 링크(예: base_link)나, 로봇이 존재하는 가상의 월드 프레임(예: odom 또는 world)으로 설정한다. 만약 여기에 설정된 프레임이 현재 TF 트리에 존재하지 않으면, “Fixed Frame [frame_name] does not exist”라는 오류가 발생하며 아무것도 표시되지 않는다. 따라서 가장 먼저 확인해야 할 부분이다.13
    • RobotModel Display: 왼쪽 하단의 ‘Add’ 버튼을 눌러 ‘RobotModel’ 디스플레이를 추가한다. 추가된 디스플레이의 속성에서 Description Topicrobot_description으로 올바르게 설정되어 있는지 확인한다. 이 토픽을 통해 robot_state_publisher가 발행하는 URDF 정보를 수신한다.32
    • TF Display: 디버깅을 위해 ‘TF’ 디스플레이를 추가하는 것이 매우 유용하다. 이를 통해 로봇의 모든 링크에 해당하는 좌표계(프레임)들이 어떻게 연결되어 있는지, 그리고 실시간으로 어떻게 움직이는지 시각적으로 확인할 수 있다.6

모든 설정이 완료되면, joint_state_publisher_gui 창의 슬라이더를 움직여보자. RViz2 화면의 로봇 모델이 슬라이더의 움직임에 따라 실시간으로 부드럽게 움직인다면, URDF 작성부터 런치 파일 실행까지의 모든 워크플로우가 성공적으로 완료된 것이다.6

URDF를 다루다 보면 다양한 문제에 직면하게 된다. 여기서는 흔히 발생하는 오류들의 원인과 해결책, 그리고 더 나은 URDF 설계를 위한 모범 사례를 다룬다.

check_urdf는 URDF 파일의 XML 문법과 링크-조인트 트리 구조가 유효한지 검사하는 간단하지만 유용한 명령줄 도구다.36 모델이 RViz에 나타나지 않거나 파싱 오류가 발생할 때 가장 먼저 시도해볼 수 있는 방법이다.

URDF를 처음 다룰 때 겪는 대부분의 문제는 RViz2에서 모델이 제대로 보이지 않는 현상이다. 다음은 대표적인 오류 메시지와 그 해결책이다.

효과적인 URDF 트러블슈팅은 단순히 check_urdf를 실행하는 ‘파일 검증’의 차원을 넘어선다. 이는 ROS2 시스템 전체의 데이터 흐름을 이해하고 진단하는 ‘시스템 디버깅’에 가깝다. RViz에서 모델이 보이지 않을 때, URDF 파일 자체의 문법 오류보다는 노드 간의 통신 문제, 빌드 시스템 설정 오류, 런치 파일 구성 오류일 가능성이 훨씬 높다. 따라서 check_urdf는 첫 단추일 뿐, 진짜 문제 해결은 rqt_graph로 노드 연결을 시각화하고, ros2 topic echo로 메시지 내용을 직접 들여다보며, RViz의 TF 디스플레이로 좌표계 트리의 연결 상태를 추적하는 등 ROS2의 강력한 디버깅 도구들을 종합적으로 활용하는 데서 시작된다. 이러한 시스템 수준의 접근 방식이야말로 초보자와 전문가를 가르는 결정적인 차이점이다.

단순히 동작하는 것을 넘어, 다른 사람이 이해하기 쉽고, 수정하기 편하며, 확장이 용이한 URDF를 작성하는 것은 전문가의 중요한 덕목이다.

  1. Lesson 9: Introduction to URDF - MiRobot, accessed July 26, 2025, https://www.mirobot.ai/ieee-beginner/chapter2/lesson9
  2. URDF(Unified Robot Description Format)란?, accessed July 26, 2025, https://duvallee.tistory.com/11
  3. URDF - ROS 2 Documentation: Humble documentation, accessed July 26, 2025, https://docs.ros.org/en/humble/Tutorials/Intermediate/URDF/URDF-Main.html
  4. ROS URDF 작성하기. URDF by brewmaster newworld-kim - Medium, accessed July 26, 2025, https://medium.com/newworld-kim/ros-urdf-b6979bfa31aa
  5. urdf/XML/link - ROS Wiki, accessed July 26, 2025, http://wiki.ros.org/urdf/XML/link
  6. ROS2 URDF Tutorial - Describe Any Robot (Links and Joints) - YouTube, accessed July 26, 2025, https://www.youtube.com/watch?v=LsKL8N5Iwkw
  7. Basics of Robot URDF Modeling in ROS2 (Humble Hawksbill) and How to Write Launch Files from Scratch : r/ControlRobotics - Reddit, accessed July 26, 2025, https://www.reddit.com/r/ControlRobotics/comments/1bfz5wf/basics_of_robot_urdf_modeling_in_ros2_humble/
  8. Best Practice: URDF descriptions, real robots, gazebo plugins and dependencies, accessed July 26, 2025, https://robotics.stackexchange.com/questions/37682/best-practice-urdf-descriptions-real-robots-gazebo-plugins-and-dependencies
  9. [ROS] URDF 알아보기, accessed July 26, 2025, https://velog.io/@dazi2_2/ROS-URDF-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0
  10. How is the coordinate system working in URDF - Robotics Stack Exchange, accessed July 26, 2025, https://robotics.stackexchange.com/questions/85761/how-is-the-coordinate-system-working-in-urdf
  11. urdf_example/description/example_robot.urdf.xacro at main - GitHub, accessed July 26, 2025, https://github.com/joshnewans/urdf_example/blob/main/description/example_robot.urdf.xacro
  12. The many origins of URDF - Robotics Stack Exchange, accessed July 26, 2025, https://robotics.stackexchange.com/questions/82452/the-many-origins-of-urdf
  13. HaofeiMa/urdf_ros2_rviz2: Visualize urdf model in ros2 using rviz2, a example ros2 package with modify tutorial. - GitHub, accessed July 26, 2025, https://github.com/HaofeiMa/urdf_ros2_rviz2
  14. Did anybody know how to solve this problem » URDF Errors loading geometries: : r/ROS, accessed July 26, 2025, https://www.reddit.com/r/ROS/comments/1cic4ja/did_anybody_know_how_to_solve_this_problem_urdf/
  15. ros2_control extra bits - Articulated Robotics, accessed July 26, 2025, https://articulatedrobotics.xyz/tutorials/mobile-robot/applications/ros2_control-extra/
  16. urdf/XML/joint - ROS Wiki, accessed July 26, 2025, http://wiki.ros.org/urdf/XML/joint
  17. Help: URDF joint axis : r/ROS - Reddit, accessed July 26, 2025, https://www.reddit.com/r/ROS/comments/s5nlvq/help_urdf_joint_axis/
  18. ROS2 - Create a Xacro Macro - YouTube, accessed July 26, 2025, https://www.youtube.com/watch?v=XH6Fvv7p5n0
  19. Using Xacro to clean up your code - ROS 2 Documentation …, accessed July 26, 2025, https://docs.ros.org/en/humble/Tutorials/Intermediate/URDF/Using-Xacro-to-Clean-Up-a-URDF-File.html
  20. xacro (XML macro) - 노땅엔진니어의 로봇 이야기 - 티스토리, accessed July 26, 2025, https://duvallee.tistory.com/17
  21. URDF, XACRO 마스터 하기 ! (ADDBOT Rviz에서 구현하기) (2/2) - 자동차 설계하기.., accessed July 26, 2025, https://kimbrain.tistory.com/409
  22. URDF improvements - ROS General - Open Robotics Discourse, accessed July 26, 2025, https://discourse.openrobotics.org/t/urdf-improvements/30520
  23. Using URDF with robot_state_publisher (C++) - ROS 2 Documentation, accessed July 26, 2025, https://docs.ros.org/en/humble/Tutorials/Intermediate/URDF/Using-URDF-with-Robot-State-Publisher-cpp.html
  24. ros/robot_state_publisher: Allows you to publish the state of a robot (i.e the position of its base and all joints) via the “tf” transform library - GitHub, accessed July 26, 2025, https://github.com/ros/robot_state_publisher
  25. How to Create URDF and Launch Files in ROS2 and Display Them in Rviz, accessed July 26, 2025, https://aleksandarhaber.com/how-to-create-urdf-and-launch-files-in-ros2-and-display-them-in-rviz/
  26. [ROS2] launch file 작성하기 - velog, accessed July 26, 2025, https://velog.io/@gaebalsebal/ROS2-launch-file-%EC%9E%91%EC%84%B1%ED%95%98%EA%B8%B0
  27. Using URDF with robot_state_publisher (Python) - ROS 2 …, accessed July 26, 2025, https://docs.ros.org/en/humble/Tutorials/Intermediate/URDF/Using-URDF-with-Robot-State-Publisher-py.html
  28. How to use XACRO files with Gazebo in ROS2 - The Construct, accessed July 26, 2025, https://www.theconstruct.ai/how-to-use-xacro-in-ros2-gazebo/
  29. urdf_launch/README.md at main / ros/urdf_launch / GitHub, accessed July 26, 2025, https://github.com/ros/urdf_launch/blob/main/README.md
  30. ros/urdf_launch: Launch files for common URDF operations - GitHub, accessed July 26, 2025, https://github.com/ros/urdf_launch
  31. RViz User Guide - ROS 2 Documentation: Humble documentation, accessed July 26, 2025, https://docs.ros.org/en/humble/Tutorials/Intermediate/RViz/RViz-User-Guide/RViz-User-Guide.html
  32. ROS2 Rviz2 Tutorial - Robot Simulation - YouTube, accessed July 26, 2025, https://www.youtube.com/watch?v=qWoGkPDg4N8
  33. rviz - How to force update after updating urdf file? - Robotics Stack …, accessed July 26, 2025, https://robotics.stackexchange.com/questions/76358/how-to-force-update-after-updating-urdf-file
  34. error in urdf file - rviz - Robotics Stack Exchange, accessed July 26, 2025, https://robotics.stackexchange.com/questions/96118/error-in-urdf-file
  35. Displaying two robots in the same RViz window - ros2 - Stack Overflow, accessed July 26, 2025, https://stackoverflow.com/questions/76276272/displaying-two-robots-in-the-same-rviz-window
  36. 2.2.3 Checking for Correctness - TU Delft OCW, accessed July 26, 2025, https://ocw.tudelft.nl/course-lectures/2-2-3-checking-for-correctness/
  37. urdf - ROS Wiki, accessed July 26, 2025, http://wiki.ros.org/urdf
  38. urdf/Tutorials/Create your own urdf file - ROS Wiki, accessed July 26, 2025, http://wiki.ros.org/urdf/Tutorials/Create%20your%20own%20urdf%20file
  39. ros kinetic - Why does RVIZ complain that I have to transform from …, accessed July 26, 2025, https://robotics.stackexchange.com/questions/93253/why-does-rviz-complain-that-i-have-to-transform-from-right-wheel-to-base-link