ROS2Lab Chapter 08
Ch.08

URDF — 로봇 모델링 입문

로봇 모양을 XML로 표현

⏱ 35분 #URDF#모델링

🎯 이 챕터의 목표

지금까지는 소프트웨어(노드/토픽/메시지)만 다뤘어요. 이번 챕터부턴 로봇의 모양 — 어떤 부품이 어떻게 연결되고 어디서 회전하는지를 코드로 표현해봐요. ROS2에서는 이 표현을 URDF라고 불러요.

약어
URDF = Unified Robot Description Format · 통일된 로봇 기술 형식. XML로 로봇의 부품(링크)과 관절(조인트)을 정의하는 표준. 시뮬레이터/시각화/내비게이션이 모두 이 파일을 보고 로봇을 이해해요.

🧱 핵심 단어 2개 — Link & Joint

🧊
Link (링크)
로봇의 부품 하나. 변형되지 않는 강체. 바퀴, 본체, 팔 한 마디.
🔗
Joint (조인트)
두 링크 사이의 연결. 회전하거나 미끄러지는 축. 어깨, 팔꿈치, 바퀴 축.
🦴 인체로 비유하면:
· Link = 뼈 (대퇴골, 정강이뼈)
· Joint = 관절 (무릎, 발목)

"관절"이 두 "뼈"를 연결하면서 움직임의 방향과 한계를 정해줘요.

📐 좌표계 (frame) 이해

모든 링크는 자기 자신의 좌표계를 가져요. 보통 이름은 base_link, wheel_left_link 같은 식. 한 링크의 위치는 부모 링크의 좌표계 기준으로 표현해요.

        z (위쪽)
         ↑
         |    
         |   y (왼쪽)
         |  ↗
         | ↗
         o ─────→ x (앞)
       base_link

ROS2의 기본 좌표계 규칙(REP 103):

  • x = 앞 (전진 방향)
  • y = 왼쪽
  • z = 위쪽
  • 각도 단위는 라디안 (radian), 거리 단위는 미터 (meter)
약어
REP = ROS Enhancement Proposal · ROS 개선안. 표준을 정해놓은 문서들. REP 103이 좌표계 규약.

📄 첫 URDF — 막대 하나

아주 단순한 직육면체 로봇부터. ~/ros2_ws/src/에 새 패키지를 만들어요.

cd ~/ros2_ws/src
ros2 pkg create --build-type ament_cmake --license Apache-2.0 my_robot_description
cd my_robot_description
mkdir urdf
nano urdf/box_bot.urdf
<?xml version="1.0"?>
<robot name="box_bot">

  <link name="base_link">
    <visual>
      <geometry>
        <box size="0.4 0.3 0.2"/>
      </geometry>
      <material name="blue">
        <color rgba="0.2 0.4 0.9 1.0"/>
      </material>
    </visual>
  </link>

</robot>

한 줄씩 풀어보기

  • <robot name="box_bot"> — 로봇 이름. URDF의 최상위 태그.
  • <link name="base_link"> — 첫 링크. "base_link"는 관례적인 첫 링크 이름.
  • <visual> — 시각화용 표현 (실제 충돌이나 물리는 따로).
  • <box size="0.4 0.3 0.2"/> — 0.4m × 0.3m × 0.2m 직육면체 (x, y, z).
  • <material> <color rgba="..."/> — 색깔. RGBA 0~1.

URDF가 받아주는 geometry 4종

<box size="x y z"/>                       <!-- 직육면체 -->
<sphere radius="r"/>                       <!-- 구 -->
<cylinder length="l" radius="r"/>          <!-- 원기둥 -->
<mesh filename="package://my_pkg/meshes/x.dae"/>  <!-- 3D 모델 -->

🔗 두 번째 — 관절 추가하기

본체 위에 회전하는 머리(센서 헤드)를 얹어봐요. 링크 1개 + 조인트 1개 추가.

<?xml version="1.0"?>
<robot name="box_bot">

  <!-- 본체 -->
  <link name="base_link">
    <visual>
      <geometry>
        <box size="0.4 0.3 0.2"/>
      </geometry>
      <material name="blue">
        <color rgba="0.2 0.4 0.9 1.0"/>
      </material>
    </visual>
  </link>

  <!-- 머리 -->
  <link name="head_link">
    <visual>
      <geometry>
        <sphere radius="0.08"/>
      </geometry>
      <material name="red">
        <color rgba="0.9 0.3 0.3 1.0"/>
      </material>
    </visual>
  </link>

  <!-- 본체 ↔ 머리 회전 조인트 -->
  <joint name="head_joint" type="revolute">
    <parent link="base_link"/>
    <child link="head_link"/>
    <origin xyz="0 0 0.15" rpy="0 0 0"/>
    <axis xyz="0 0 1"/>
    <limit lower="-1.57" upper="1.57" effort="10" velocity="1.0"/>
  </joint>

</robot>

joint 태그 풀이

  • type="revolute" — 회전 조인트 (한정된 각도 내). 다른 타입은 잠시 후.
  • parent / child — 어느 링크에 어느 링크가 붙는지 (방향 있음).
  • origin xyz="0 0 0.15" — 부모 좌표계 기준, 머리는 본체 위 0.15m 위치.
  • origin rpy="0 0 0" — Roll/Pitch/Yaw (회전 자세). 0이면 정렬됨.
  • axis xyz="0 0 1" — 회전축. z축 회전 = 좌우 둘러보기.
  • limit lower upper — 라디안 단위 한계 (-π/2 ~ +π/2 = -90° ~ +90°).
약어
RPY = Roll / Pitch / Yaw · 자세를 표현하는 3개 회전. Roll = x축 회전 (옆으로 기울임), Pitch = y축 회전 (앞뒤로 기울임), Yaw = z축 회전 (좌우로 돌림). 비행기에서 유래.

⚙ 조인트 타입 6종

type
의미
예시
revolute
제한된 회전
팔꿈치 (각도 제한)
continuous
제한 없는 회전
바퀴
prismatic
직선 이동
승강기, 슬라이드 그리퍼
fixed
고정 (안 움직임)
센서를 본체에 붙임
floating
6자유도 자유
드론 본체 (거의 안 씀)
planar
평면 위 이동
옴니휠 베이스
💡 가장 자주 쓰는 4개만 외워두면 됨: revolute, continuous, prismatic, fixed.

🏃 빠른 실습 — urdf_tutorial 패키지 활용

내가 만든 URDF를 화면에 띄워보고 싶다면, ROS2에 이미 준비된 urdf_tutorial이 가장 빠른 길.

sudo apt install ros-jazzy-urdf-tutorial -y

이걸 깔면 URDF + RViz + 슬라이더 GUI를 한 번에 띄우는 launch가 들어와요.

ros2 launch urdf_tutorial display.launch.py \
  model:=$HOME/ros2_ws/src/my_robot_description/urdf/box_bot.urdf

실행하면:

  • RViz2 창이 뜨고 박스 + 빨간 구가 보임
  • joint_state_publisher_gui라는 슬라이더 창이 같이 뜸
  • 슬라이더 움직이면 머리가 좌우로 돌아감 🎮
💡 처음 RViz가 뜰 때 아무것도 안 보이면: 좌측 패널 → "Add" → "RobotModel" 추가 → "Fixed Frame"을 base_link로. (다음 챕터 Ch.09에서 RViz 자세히 다룸)

📦 URDF 패키지 구조

실제 프로젝트는 보통 이렇게 구성해요.

my_robot_description/
├── package.xml
├── CMakeLists.txt
├── urdf/                ← .urdf 또는 .xacro 파일
│   └── my_robot.urdf
├── meshes/              ← 3D 모델 (.stl, .dae)
│   ├── base.stl
│   └── wheel.stl
├── launch/              ← 디스플레이용 launch
│   └── display.launch.py
└── config/              ← RViz 설정, joint 매핑 등
    └── view.rviz

이런 패키지를 보통 <로봇이름>_description이라고 부르는 게 ROS2 관례. TurtleBot의 경우 turtlebot4_description.

🧬 inertial — 물리 시뮬레이션에 필요

URDF는 시각화만 위한 게 아니라 물리 엔진(Gazebo)에도 쓰여요. 그러려면 각 링크의 질량과 관성을 적어줘야 해요.

<link name="base_link">
  <visual>...</visual>

  <collision>
    <geometry>
      <box size="0.4 0.3 0.2"/>
    </geometry>
  </collision>

  <inertial>
    <mass value="5.0"/>
    <inertia ixx="0.1" ixy="0" ixz="0"
             iyy="0.1" iyz="0" izz="0.1"/>
  </inertial>
</link>
  • <visual> — 보이는 모양
  • <collision> — 충돌 판정용 모양 (보통 visual보다 단순하게)
  • <inertial> — 질량 + 관성 텐서 (Gazebo가 사용)
💡 RViz 시각화만 할 거면 collision/inertial은 생략 가능. Gazebo 쓰려면 필수. Ch.10에서 다시 만나요.

🧩 xacro — URDF의 매크로 확장

URDF는 XML이라 반복이 많아져요. 바퀴 4개면 거의 같은 코드 4번 복붙. 그래서 xacro가 만들어졌어요.

약어
xacro = XAcro = XML mAcros · XML 매크로. URDF에 변수, 매크로, include, 계산식을 추가한 확장 문법. 확장자는 .xacro 또는 .urdf.xacro.
<?xml version="1.0"?>
<robot name="box_bot" xmlns:xacro="http://www.ros.org/wiki/xacro">

  <!-- 변수 정의 -->
  <xacro:property name="wheel_radius" value="0.05"/>

  <!-- 매크로 정의 -->
  <xacro:macro name="wheel" params="prefix x y">
    <link name="${prefix}_wheel">
      <visual>
        <geometry>
          <cylinder length="0.04" radius="${wheel_radius}"/>
        </geometry>
      </visual>
    </link>
    <joint name="${prefix}_wheel_joint" type="continuous">
      <parent link="base_link"/>
      <child link="${prefix}_wheel"/>
      <origin xyz="${x} ${y} 0" rpy="1.5708 0 0"/>
      <axis xyz="0 0 1"/>
    </joint>
  </xacro:macro>

  <!-- 매크로 호출 (바퀴 4개를 4번 호출) -->
  <xacro:wheel prefix="fl" x="0.15"  y="0.15"/>
  <xacro:wheel prefix="fr" x="0.15"  y="-0.15"/>
  <xacro:wheel prefix="rl" x="-0.15" y="0.15"/>
  <xacro:wheel prefix="rr" x="-0.15" y="-0.15"/>

</robot>

XML 200줄을 50줄로 줄여줘요. 실전 로봇 모델은 거의 다 xacro.

🔍 URDF 검증 도구

# URDF 문법 체크
check_urdf box_bot.urdf

# xacro → urdf 변환
xacro robot.urdf.xacro > robot.urdf

# URDF의 링크/조인트 트리 보기
urdf_to_graphiz robot.urdf  # PDF 생성됨
💡 check_urdf는 빌드 안 하고 즉시 문법 오류를 잡아줘요. URDF 수정 후 항상 한 번 돌려봐요.
✏️ 퀴즈 1

URDF에서 "변형되지 않는 부품 하나"를 의미하는 단어는?

✏️ 퀴즈 2

한 바퀴가 끝없이 회전해야 한다면 joint type은?

✏️ 퀴즈 3

ROS2의 기본 좌표계 규칙(REP 103)에서 로봇의 "앞 방향"은?

✏️ 퀴즈 4

xacro를 쓰는 가장 큰 이유는?

🎁 정리

  • URDF = 로봇의 모양을 XML로 표현하는 표준
  • 구성 요소: Link(부품) + Joint(연결)
  • 좌표계: x=앞, y=왼, z=위 (REP 103) / 거리=m, 각도=rad
  • geometry: box / sphere / cylinder / mesh
  • joint type 4대 핵심: revolute / continuous / prismatic / fixed
  • RPY = Roll/Pitch/Yaw (자세 표현)
  • xacro로 반복 줄이기 (변수 + 매크로 + include)
  • 패키지 관례: <robot>_description
  • 실습은 urdf_tutorial + RViz로 가장 빠름

다음 챕터는 이걸 실제로 화면에 띄우고 디버깅하는 RViz2입니다. 🎨