659.95 Xacro를 이용한 매개변수화된 프레임 정의

1. 개요

Xacro(XML Macros)는 URDF의 확장 포맷으로, 매크로(macro), 매개변수(parameter), 조건문(conditional), 수식(expression) 등의 기능을 제공하여 복잡한 로봇 모델을 효율적으로 기술할 수 있게 한다. Xacro를 사용하면 반복적인 코드를 매크로로 추상화하고, 치수와 물리 특성을 매개변수로 관리하여, 유지보수성과 재사용성이 높은 로봇 모델을 작성할 수 있다.

2. Xacro의 기본 문법

2.1 네임스페이스 선언

<?xml version="1.0" encoding="UTF-8"?>
<robot name="my_robot" xmlns:xacro="http://www.ros.org/wiki/xacro">
  <!-- Xacro 코드 -->
</robot>

2.2 속성(Property) 정의

속성은 상수 값을 이름에 바인딩하여 반복 사용을 가능하게 한다.

<!-- 속성 정의 -->
<xacro:property name="wheel_radius" value="0.05"/>
<xacro:property name="wheel_width" value="0.02"/>
<xacro:property name="wheel_separation" value="0.34"/>
<xacro:property name="base_length" value="0.5"/>
<xacro:property name="base_width" value="0.3"/>
<xacro:property name="base_height" value="0.15"/>
<xacro:property name="pi" value="3.14159265359"/>

<!-- 속성 사용 -->
<geometry>
  <box size="${base_length} ${base_width} ${base_height}"/>
</geometry>

2.3 수식 평가

${} 구문 내에서 Python 수식을 사용할 수 있다.

<xacro:property name="half_separation" value="${wheel_separation / 2}"/>
<origin xyz="0 ${wheel_separation / 2} ${-base_height / 2 - wheel_radius}"
        rpy="${-pi / 2} 0 0"/>

2.4 매크로(Macro) 정의

매크로는 매개변수를 받아 URDF 코드를 생성하는 재사용 가능한 템플릿이다.

<!-- 바퀴 매크로 정의 -->
<xacro:macro name="wheel" params="name parent reflect">
  <link name="${name}_wheel_link">
    <visual>
      <geometry>
        <cylinder radius="${wheel_radius}" length="${wheel_width}"/>
      </geometry>
      <material name="black">
        <color rgba="0.1 0.1 0.1 1.0"/>
      </material>
    </visual>
    <collision>
      <geometry>
        <cylinder radius="${wheel_radius}" length="${wheel_width}"/>
      </geometry>
    </collision>
    <inertial>
      <mass value="0.5"/>
      <inertia ixx="0.001" ixy="0" ixz="0"
               iyy="0.001" iyz="0" izz="0.001"/>
    </inertial>
  </link>

  <joint name="${name}_wheel_joint" type="continuous">
    <parent link="${parent}"/>
    <child link="${name}_wheel_link"/>
    <origin xyz="0.0 ${reflect * wheel_separation / 2} ${-wheel_radius}"
            rpy="${-pi / 2} 0 0"/>
    <axis xyz="0 0 1"/>
  </joint>
</xacro:macro>

<!-- 매크로 호출 -->
<xacro:wheel name="left" parent="base_link" reflect="1"/>
<xacro:wheel name="right" parent="base_link" reflect="-1"/>

2.5 조건문

<xacro:if value="${use_lidar}">
  <xacro:include filename="$(find my_robot)/urdf/lidar.urdf.xacro"/>
</xacro:if>

<xacro:unless value="${use_simulation}">
  <!-- 실제 하드웨어 전용 요소 -->
</xacro:unless>

2.6 파일 포함

<!-- 외부 Xacro 파일 포함 -->
<xacro:include filename="$(find my_robot)/urdf/sensors.urdf.xacro"/>
<xacro:include filename="$(find my_robot)/urdf/wheels.urdf.xacro"/>

3. 매개변수화된 센서 프레임 정의

3.1 카메라 매크로

<xacro:macro name="camera_sensor" params="name parent xyz rpy">
  <link name="${name}_link">
    <visual>
      <geometry><box size="0.04 0.08 0.04"/></geometry>
    </visual>
  </link>

  <joint name="${name}_joint" type="fixed">
    <parent link="${parent}"/>
    <child link="${name}_link"/>
    <origin xyz="${xyz}" rpy="${rpy}"/>
  </joint>

  <link name="${name}_optical_frame"/>

  <joint name="${name}_optical_joint" type="fixed">
    <parent link="${name}_link"/>
    <child link="${name}_optical_frame"/>
    <origin xyz="0 0 0" rpy="${-pi/2} 0 ${-pi/2}"/>
  </joint>
</xacro:macro>

<!-- 다중 카메라 배치 -->
<xacro:camera_sensor name="front_camera" parent="base_link"
                     xyz="0.25 0.0 0.3" rpy="0 0.1 0"/>
<xacro:camera_sensor name="rear_camera" parent="base_link"
                     xyz="-0.25 0.0 0.3" rpy="0 0 ${pi}"/>

3.2 LiDAR 매크로

<xacro:macro name="lidar_2d" params="name parent xyz rpy">
  <link name="${name}_link">
    <visual>
      <geometry><cylinder radius="0.035" length="0.05"/></geometry>
    </visual>
  </link>

  <joint name="${name}_joint" type="fixed">
    <parent link="${parent}"/>
    <child link="${name}_link"/>
    <origin xyz="${xyz}" rpy="${rpy}"/>
  </joint>
</xacro:macro>

3.3 관성 매크로

관성 텐서 계산을 매크로로 자동화할 수 있다.

<!-- 상자 형상의 관성 텐서 -->
<xacro:macro name="box_inertia" params="mass x y z">
  <inertial>
    <mass value="${mass}"/>
    <inertia ixx="${mass * (y*y + z*z) / 12}" ixy="0" ixz="0"
             iyy="${mass * (x*x + z*z) / 12}" iyz="0"
             izz="${mass * (x*x + y*y) / 12}"/>
  </inertial>
</xacro:macro>

<!-- 원통 형상의 관성 텐서 -->
<xacro:macro name="cylinder_inertia" params="mass r l">
  <inertial>
    <mass value="${mass}"/>
    <inertia ixx="${mass * (3*r*r + l*l) / 12}" ixy="0" ixz="0"
             iyy="${mass * (3*r*r + l*l) / 12}" iyz="0"
             izz="${mass * r*r / 2}"/>
  </inertial>
</xacro:macro>

4. Xacro에서 URDF로의 변환

4.1 명령행에서의 변환

# Xacro를 URDF로 변환
xacro my_robot.urdf.xacro > my_robot.urdf

# 매개변수를 전달하여 변환
xacro my_robot.urdf.xacro use_lidar:=true sensor_height:=0.3 > my_robot.urdf

4.2 런치 파일에서의 동적 변환

import xacro
from launch import LaunchDescription
from launch_ros.actions import Node

def generate_launch_description():
    # Xacro를 동적으로 처리
    xacro_file = os.path.join(
        get_package_share_directory('my_robot'),
        'urdf', 'my_robot.urdf.xacro')

    robot_description = xacro.process_file(
        xacro_file,
        mappings={'use_lidar': 'true'}
    ).toxml()

    return LaunchDescription([
        Node(
            package='robot_state_publisher',
            executable='robot_state_publisher',
            parameters=[{'robot_description': robot_description}],
        ),
    ])

5. Xacro 파일 구성 패턴

5.1 모듈화 패턴

대규모 로봇 모델은 다음과 같이 모듈화하여 관리한다.

urdf/
  ├── my_robot.urdf.xacro        # 최상위 파일
  ├── properties.urdf.xacro       # 공통 속성 정의
  ├── materials.urdf.xacro        # 재질 정의
  ├── base.urdf.xacro             # 본체 정의
  ├── wheels.urdf.xacro           # 바퀴 매크로
  ├── sensors.urdf.xacro          # 센서 매크로
  └── gazebo.urdf.xacro           # 시뮬레이션 플러그인

최상위 파일에서 각 모듈을 포함한다.

<robot name="my_robot" xmlns:xacro="http://www.ros.org/wiki/xacro">
  <xacro:include filename="properties.urdf.xacro"/>
  <xacro:include filename="materials.urdf.xacro"/>
  <xacro:include filename="base.urdf.xacro"/>
  <xacro:include filename="wheels.urdf.xacro"/>
  <xacro:include filename="sensors.urdf.xacro"/>
  <xacro:include filename="gazebo.urdf.xacro"/>
</robot>

6. 요약

Xacro는 URDF의 매크로 확장으로, 속성, 수식, 매크로, 조건문, 파일 포함 기능을 통하여 복잡한 로봇 모델을 효율적으로 기술한다. 센서 프레임, 바퀴, 관성 텐서 등의 반복적 요소를 매크로로 추상화하고, 치수와 구성을 매개변수로 관리함으로써 유지보수성과 재사용성을 향상시킨다. Xacro 파일은 빌드 시 또는 런치 시에 순수 URDF로 변환되어 robot_state_publisher에 전달된다.


참고 문헌 및 출처

  • ROS2 공식 문서, “Using Xacro to Clean Up Your URDF File”, https://docs.ros.org/en/humble/Tutorials/Intermediate/URDF/Using-Xacro-to-Clean-Up-a-URDF-File.html (ROS2 Humble Hawksbill)
  • Xacro 패키지 문서, http://wiki.ros.org/xacro
  • ROS2 공식 문서, “Building a Visual Robot Model from Scratch”, https://docs.ros.org/en/humble/Tutorials/Intermediate/URDF/ (ROS2 Humble Hawksbill)