ROS2에서 URDF를 다루는 방법

URDF 파일 구조와 기본 개념

ROS2에서 로봇을 표현하기 위한 주요 방법 중 하나로 URDF(Universal Robot Description Format)를 사용한다. URDF 파일은 XML 기반의 포맷으로, 로봇의 링크(link)와 조인트(joint)를 계층적으로 서술하며, 각 부품의 물리적 특성(질량, 관성, 충돌 모델 등)도 함께 기술할 수 있다.

  • 링크(link): 로봇을 구성하는 하나의 부품을 의미한다. 모델에서 실제 로봇 부품에 해당하는 물리적 형태(시각적, 충돌, 관성 요소)와 특징들이 정의된다.

  • 조인트(joint): 링크 간의 연결 방법(회전, 슬라이딩 등)을 정의한다. 조인트는 URDF에서 매우 중요한 요소이며, 조인트의 타입(revolute, continuous, prismatic 등)에 따라 제한 각도, 초기 각도, 축(axis) 등이 기술된다.

다음은 URDF 파일 구조의 가장 간단한 예시이다.

<robot name="my_robot">
  <link name="base_link">
    <visual>
      <geometry>
        <box size="0.5 0.5 0.2"/>
      </geometry>
    </visual>
  </link>
</robot>

위 예시는 "my_robot"이라는 이름의 로봇에 "base_link"라는 링크를 1개 정의한 것이다. URDF의 확장된 기능을 사용하면 재질, 텍스처, 관성 텐서 등 다양한 요소를 추가 기술할 수 있다.

URDF에서의 좌표계 정의

URDF에서 링크와 조인트의 위치와 방향은 주로 부모-자식 관계로 정의된다. 예컨대, 어떤 부모 링크에 대해 자식 링크가 어떻게 배치되는지를 변환 행렬로 표현할 수 있다. URDF 파일에서 이 변환은 origin 태그로 정의되며, 위치와 회전(roll, pitch, yaw)에 대한 정보를 갖는다.

예를 들어, $\mathbf{T}\text{base_link}$가 $\mathbf{R}\text{base_link}$와 $\mathbf{p}_\text{base_link}$로 구성된 좌표계 변환일 때, 이를 URDF에서는 다음과 같이 표현한다.

  • xyz="0.3 0.0 0.1"은 부모 링크 기준으로 자식 링크의 위치 벡터 $\mathbf{p}_\text{base_link}$를 의미한다.

  • rpy="0.0 0.0 1.5708"은 롤, 피치, 요 계열의 회전각을 라디안 단위로 표현하여 회전 행렬 $\mathbf{R}_\text{base_link}$를 간접적으로 정의한다.

  • axis xyz="0 0 1"은 조인트 회전축 혹은 이동축을 의미한다.

ROS2에서 URDF 파일 로드 방법

ROS1에서는 launch 파일 내에서 robot_description 파라미터로 URDF를 로드하고, ROS2에서도 크게 유사한 방식으로 진행한다. 그러나 ROS2의 Launch 시스템은 Python 스크립트나 XML 포맷 등 다양한 방식을 지원하므로, URDF를 파라미터로 전달하는 과정에서 노드 파라미터를 명시적으로 선언해주어야 한다.

예시로, ROS2 Python Launch 파일에서 URDF를 robot_description 파라미터로 로드하는 코드를 살펴보자.

  • Command를 이용해 Xacro나 URDF 파일을 파이프라인으로 넣어 문자열로 변환한다.

  • robot_state_publisher 노드에 robot_description 파라미터를 넘겨줌으로써 이 노드는 URDF 데이터를 해석하여 토픽으로 로봇 상태를 퍼블리시한다.

robot_state_publisher 노드의 역할

ROS2에서 robot_state_publisher는 로봇의 조인트 상태(joint states)를 입력받아, 각 링크의 좌표 변환 정보를 주기적으로 계산하여 TF(Transform) 정보를 퍼블리시하는 역할을 한다. 이는 RViz2와 같은 시각화 툴에서 로봇 모델을 표시하기 위해 필수적이다.

  • 입력: /joint_states 토픽 (또는 파라미터 서버에서 초기 화 등으로 전달받은 조인트 상태)

  • 출력: TF 트리 (예: /tf, /tf_static 토픽)

로봇에 포함된 모든 조인트를 위해 변환을 계산하려면, URDF로부터 조인트와 링크 계층 정보를 읽어올 필요가 있다. 이 과정을 내부적으로 자동으로 처리하여, 사용자는 별도의 좌표계 변환 계산 없이도 TF 트리를 손쉽게 얻을 수 있다.

Xacro와의 연계

URDF 파일이 복잡해질수록, 매번 XML 코드에 일일이 작성하기보다는 반복되는 요소를 매크로(Macro)처럼 간단히 처리하고, 파라미터를 적절히 전달하는 방법이 필요해진다. ROS2에서는 Xacro를 이용해 이러한 기능을 제공한다.

  • Xacro(.xacro) 파일은 실제 URDF(.urdf) 파일로 컴파일되기 전, 매크로 확장과 변수 치환 과정을 거쳐 최종 URDF 형태가 된다.

  • 이를 통해 같은 형상의 링크를 여러 개 정의해야 할 때, 위치나 색상 등 일부 파라미터만 다르게 설정하는 식으로 관리가 가능하다.

아래 예시는 Xacro에서 매크로를 정의하고 호출하는 간단한 구조를 보여준다.

  1. xacro:macro 태그로 매크로를 정의한다. 매크로의 파라미터로 link_name, color_value 등을 지정해두면 호출할 때 다른 값을 넣어서 재활용할 수 있다.

  2. 매크로를 호출할 때는 <xacro:my_link_macro ...> 형태로 사용한다.

  3. 최종 URDF 형태로 변환하기 위해서는 ROS2 Launch 파일에서 Command(['xacro ', '...'])와 같은 방식을 사용해 URDF 문자열을 생성한다.

URDF에서 관성(Inertial) 요소 정의

물리 시뮬레이션이나 역운동학(Forward/Inverse Kinematics) 계산 등에서 링크의 질량과 관성(Inertia)은 매우 중요한 요소다. URDF에서는 <inertial> 태그를 이용해 질량($m$)과 관성 텐서($\mathbf{I}$) 등을 정의할 수 있다.

예시:

  • <mass value="1.0"/>는 링크의 질량을 1.0 kg으로 설정한다.

  • <inertia>에서 관성 텐서의 대각 성분과 오프 대각 성분을 입력한다. 예컨대, 링크가 균질한 형태의 작은 박스나 원기둥이라면 대각 원소가 동일하거나 간단한 형태가 될 수도 있다.

수식으로 관성 텐서를 표현하면 다음과 같다.

I=[IxxIxyIxzIyxIyyIyzIzxIzyIzz]\mathbf{I} = \begin{bmatrix} I_{xx} & I_{xy} & I_{xz} \\ I_{yx} & I_{yy} & I_{yz} \\ I_{zx} & I_{zy} & I_{zz} \end{bmatrix}

시뮬레이션에서 관성 정보를 제대로 구성해야, 물리 엔진(예: Gazebo, Ignition 등)이 정확한 동역학 시뮬레이션을 수행할 수 있다.

Gazebo 등의 시뮬레이터와 연동

URDF만으로는 기본적인 로봇 모델 정보(기하구조, 조인트, 관성 등)만을 정의하며, 센서나 액추에이터 플러그인 같은 보다 시뮬레이션 친화적인 요소들은 추가적인 태그를 통해 확장해야 한다. 주로 <gazebo> 태그와 같은 전용 태그, 혹은 SDF(Simulation Description Format)로의 변환 과정을 거치게 된다.

  • Gazebo 플러그인: URDF 혹은 Xacro 파일에 <gazebo> 내부에 <plugin> 태그를 추가하여 시뮬레이션 시 필요한 기능(카메라 센서, IMU, LIDAR 등)을 설정한다.

  • SDF 변환: Gazebo 상에서 URDF 대신 SDF를 사용하기도 하는데, ROS2에서 제공하는 변환 노드 또는 gz sdf -p urdf_file 같은 명령어를 이용해 URDF를 SDF로 변환할 수 있다.

URDF와 TF 트리 구조

ROS2에서 링크와 조인트의 연결 상태는 곧 TF 트리 구조를 형성한다. 예를 들어, 기본 베이스 링크(base_link)가 뿌리(root)가 되고, 순차적으로 조인트를 통해 다른 링크가 연결된다. 이는 다음과 같은 트리 형태로 시각화할 수 있다.

spinner
  • RViz2에서 TF 트리를 로드하면, 해당 구조를 토대로 로봇 모델이 어떻게 배치되는지 시각적으로 확인할 수 있다.

  • robot_state_publisher 노드는 $\mathbf{T}_{\text{link}i}^{\text{link}{i+1}}$ 변환을 순차적으로 연결하여 전체 TF를 퍼블리시한다.

URDF에서 시각(Visual) 요소 정의

URDF에서 **시각 요소(Visual)**는 실제 로봇의 3D 모델을 어떻게 표현할지 정의한다. 대부분 다음과 같은 태그 구조를 사용한다.

  • <origin>: 시각 요소의 위치와 자세를 링크의 좌표계 기준으로 설정한다.

  • <geometry>: 메쉬 파일(STL, DAE, OBJ 등)이나 기본 형상(box, cylinder, sphere 등)을 사용해 로봇 부품의 형태를 정의한다.

  • <material>: 색상, 텍스처, 셰이더 등의 그래픽적 특성을 설정한다.

    • <color rgba="R G B A"/> 형태로 불투명도(Alpha 채널)까지 함께 기술할 수 있다.

    • 외부 텍스처(이미지 파일)나 머티리얼 라이브러리를 활용하는 것도 가능하다.

시각 요소는 RViz2나 시뮬레이션 툴에서 로봇을 렌더링하는 데 사용된다. 로봇 모델이 복잡할수록 파일 용량도 커질 수 있으므로, 필요에 따라 STL 등의 메쉬 파일을 최적화하거나, 기본 형상을 최대한 재활용하는 것이 성능상 유리하다.

URDF에서 충돌(Collision) 요소 정의

**충돌 요소(Collision)**는 물리 엔진 및 충돌 감지 알고리즘이 로봇의 실제 형태를 얼마나 정밀하게 인식할지를 결정한다. 주로 <collision> 태그를 사용하며, 구조는 <visual> 태그와 비슷하다.

  • 일반적으로 시각 요소에 비해 단순화된 형상(단순 박스, 단순 원기둥 등)을 사용하여 충돌 계산을 빠르게 처리한다.

  • <collision>에 설정된 메쉬나 기본 형상은 시각화 목적이 아니라 물리 충돌 검사용으로 사용된다.

시각 요소와 충돌 요소를 동일하게 설정해도 되지만, 복잡도가 높은 3D 메쉬의 경우 시뮬레이터 성능 저하가 발생할 수 있으므로 적절히 축소·단순화된 메쉬를 쓰는 편이 좋다.

URDF와 Self-Collision Checking

ROS 환경에서 MoveIt2 같은 모션 플래너를 사용할 경우, 로봇이 자기 자신의 부품끼리 부딪히지 않도록 하는 Self-Collision Checking 기능이 필요하다.

  • 로봇의 각 링크마다 충돌 모델을 정의해놓으면, MoveIt2는 URDF에 기반해 서로 충돌 가능성이 있는 링크 쌍을 미리 계산(Allowed Collision Matrix, ACM)하고, 실시간으로 부딪히는지를 판별한다.

  • 실제 실행 시에는 계획 단계(Planning Scene)에서 시각 요소가 아닌 충돌 요소를 바탕으로 충돌 여부를 파악하므로, Collision 모델이 얼마나 정확하느냐가 중요한 영향을 끼친다.

URDF에서 조인트 리미트(Joint Limit) 정의

URDF에서 조인트의 제한 각도(회전 조인트) 혹은 이동 거리(프리스매틱 조인트)를 정의할 수 있다. 이는 <limit> 태그로 설정한다.

  • lowerupper는 하한 및 상한 각도(또는 거리)로, 라디안 기준으로 입력한다.

  • effort는 모터나 액추에이터가 제공할 수 있는 최대 토크(또는 힘) 한계를 나타내며, 가상 시뮬레이션 시에만 주로 활용된다.

  • velocity는 조인트가 움직일 수 있는 최대 속도를 라디안/초 단위(회전 조인트) 또는 m/s 단위(프리스매틱 조인트)로 표기한다.

MoveIt2나 Gazebo 같은 툴에서는 이 정보들을 기반으로 조인트 동작 범위를 인식하고, 계획이나 시뮬레이션 시에 제한을 거는 식으로 활용한다.

URDF와 MoveIt2 연동

로봇 조인트를 활용해 경로계획(Path Planning)이나 Inverse Kinematics (IK) 연산을 수행하려면, MoveIt2 구성을 진행해야 한다. 이때 MoveIt2에서 로봇 모델 정보를 얻는 1차적인 수단이 바로 URDF이며, 충돌 모델과 조인트 제한 값도 함께 참고한다.

  • MoveIt2 Setup Assistant를 이용하면 URDF를 불러와서 자동으로 SRDF(Semantic Robot Description Format) 파일을 생성할 수 있다.

  • SRDF에는 “어떤 조인트 그룹을 정의할 것인지”, “어떤 링크 간의 충돌을 무시할 것인지” 등 로봇의 동작 및 충돌 관련 설정 정보가 들어간다.

URDF 모델 디버깅과 시각화

복잡한 URDF나 Xacro 파일을 작성하다 보면, 종종 URDF가 깨지거나(오탈자 등), 링크 변환이 잘못되어 로봇 파츠가 엉뚱한 위치에 뜨는 경우가 생긴다. 이를 확인하려면 다음 방법을 쓸 수 있다.

URDF 검증:

ROS1에서 제공했던 명령어지만, ROS2용으로도 별도의 툴 혹은 urdf_parser_py 라이브러리를 활용하는 방법이 있다. URDF XML 파싱 에러나 불필요한 중복 정의 등을 점검해준다.

RViz2를 활용한 시각화:

  • robot_state_publisher 노드로 URDF를 퍼블리시하고, RViz2에서 “RobotModel” 디스플레이를 추가하여 로봇이 올바르게 렌더링되는지 확인한다.

  • TF 프레임들이 기대했던 구조대로 연결되어 있는지도 “TF” 디스플레이를 통해 확인 가능하다.

단순 Launch로 시각화:

  • URDF 파일을 로드하는 최소 Launch 파일을 만들어 “robot_state_publisher + RViz2” 구성을 실행한다.

  • URDF에 설정된 시각 요소(Visual)와 충돌 요소(Collision)를 모두 점검할 수 있다.

간단한 로봇을 넘어 여러 개의 링크와 여러 개의 조인트로 구성된 복잡한 모델을 작성하려면, 링크와 조인트가 트리 형태로 구조화되어야 한다. 아래 예시는 두 개의 회전 조인트를 포함한 로봇 URDF의 일부분이다.

  1. <link> 태그: 각 링크에 대해 시각(Visual), 충돌(Collision), 관성(Inertial)을 정의한다.

  2. <joint> 태그: 상위(부모) 링크와 하위(자식) 링크를 연결한다. 각 조인트가 어느 축(axis)으로 어떻게 동작(revolute, prismatic, fixed 등)하는지 명시하며, 제한(limit)도 설정한다.

  3. 원점(origin): 자식 링크가 부모 링크로부터 얼마만큼 떨어져 있는지, 어떤 회전(rpy)을 가지는지 나타낸다.

위와 같은 구조를 갖춘 로봇 모델은 RViz2나 Gazebo에서 시각화해보면, 하나의 ‘팔(arm)’ 구조와 비슷하게 동작할 것이다.

URDF 변수 활용 및 관리

URDF에서 직접 모든 수치를 하드코딩하면 관리가 힘들다. 이 때문에 Xacro를 이용해 변수(파라미터)를 정의하고, 이를 재사용하거나 연산하여 최종 URDF를 생성하는 방식을 많이 쓴다. 예:

  • $arm_length$, $arm_radius$ 같은 변수를 활용하여, 손쉽게 로봇 부품 치수를 수정 가능하다.

  • 다른 링크나 조인트에서도 이 변수를 공유함으로써, 로봇 운동학적 변화(예: 팔 길이, 무게 등)를 전체적으로 쉽게 관리할 수 있다.

AR Tags, 텍스처 맵핑 등 시각 확장

로봇 모델에 추가적인 시각적 효과를 주고자 할 때, 텍스처 맵핑이나 AR(Augmented Reality)용 마커 등을 URDF에 넣을 수 있다.

  • 텍스처 맵핑: <material> 내부에서 <texture filename="package://my_robot_description/textures/texture.png"/> 형태로 지정할 수 있다.

  • AR Tag: <visual> 요소에 QR 코드 또는 AR 마커 이미지를 텍스처로 지정하여, 카메라 기반 localization에 활용하기도 한다.

단, RViz2나 Gazebo에서 정상적으로 텍스처를 표시하려면, 패키지 경로 설정과 같은 환경 구성이 올바르게 되어 있어야 한다.

URDF 활용 사례

  1. 로봇 팔(Manipulators) 모델링: 멀티 조인트 매니퓰레이터에 대해 각 조인트 축, 회전 범위, 관성, 충돌 모델 등을 세밀히 기술.

  2. 이동 로봇(Mobile Robots) 모델링: 바퀴(wheel)나 캐스터(caster) 조인트를 정의하여, 실제 이동 메커니즘을 표현.

  3. 인간형(Humanoids) 모델링: 다수의 링크와 복합적인 조인트 구조를 갖는 휴머노이드(머리, 팔, 다리, 허리 등의 세분화) 표현.

  4. 복합 센서 탑재: 카메라, LiDAR, IMU, GPS 등 센서 장치를 링크로 간주해, 별도의 Visual/Collision을 정의하고 TF 트리에 포함.

Last updated