본문 바로가기
로봇 이야기/ros2

xacro (XML macro)

by 노땅엔진니어 2022. 12. 30.

 1. xacro란?

매크로(macro)란 여러 개의 명령을 묶어 하나의 명령으로 만들어 여러 개의 명령을 수행하거나, 반복적인 작업에서 하나의 매크로 명령만으로 효과적인 작업을 수행 할 수 있습니다.
xacro는 XML + macro의 합성어로써 XML에서 매크로를 사용할 수 있습니다. URDF를 만드는데 XML로도 가능하지만 xacro를 사용하면 좀 더 쉽게 로봇 모델을 만들 수 있습니다.

 2. 속성(Property)와 속성 블럭(Property Blocks)

속성(property)는 XML 문서 어디에나 올 수 있습니다. 속성과 속성 블럭은 <xacro:property> 태그(tag)를 사용하여 값을 정의 합니다. 속성은 달러와 대괄호(${}) 안에 속성 이름을 통해서 사용을 합니다.

<xacro:property name="the_radius" value="2.1" />
<xacro:property name="the_length" value="4.5" />

<geometry type="cylinder" radius="${the_radius}" length="${the_length}" />

속성 블럭(property block)은 속성과 같이 <xacro:property> 태그를 사용해서 정의를 하고 사용은 <xacro:insert_block> 태그를 통해서 사용을 합니다.

  <xacro:property name="red_material">
    <material name="red">
      <color rgba="1.0 0.0 0.0 1.0"/>
    </material>
  </xacro:property>

위는 속성 블럭을 정의한 것이고 아래는 블럭 정의를 사용한 예 입니다.

      <xacro:insert_block name="red_material" />

 3. 수학 함수

XML로 urdf를 표현할 때 가장 부족한 것이 수학 함수나 수학 상수 값을 사용할 수 없는 점입니다. xacro에서는 속성과 같이 달러와 대괄호(${})안에 수학 함수나 수학 상수를 사용할 수 있습니다. 사용할 수 있는 수학 함수는 파이썬(Python) 수학 모듈의 함수와 상수 입니다.

상수 (constant)

  • pi : 원주율로써 3.141592...
  • e : 자연로그 값으로써 2.718281...
  • tau : 원주와 반지름의 비율인 2pi에 해당하는 상수 값으로써 6.283185...
  • inf : 부동 소수점 양의 무한대 값 입니다.
  • nan : Not a Number를 뜻 합니다.

함수 (function)

수학 함수 중에 기본이 되는 함수입니다.

  • fabs(x) : x의 절대값을 반환 합니다.
  • pow(x, y) : 거듭제곱의 값을 구합니다.
  • sqrt(x) : x의 제곱근을 반환 합니다.

다음은 삼각 함수 입니다.

  • acos(x) : x의 아크 코사인(arc cosine)을 라디안으로 반환합니다. 결과는0과 pi 사이입니다.
  • asin(x) : x의 아크 사인(arc sine)을 라디안으로 반환합니다. 결과는 -pi/2와 pi/2 사이입니다.
  • atan(x) : x의아크 탄젠트(arc tangent)를 라디안으로 반환합니다. 결과는 -pi/2와 pi/2 사이입니다.
  • atan2(y, x) : atan(y/x)를 라디안으로 반환합니다. 결과는 -pi와 pi 사이입니다.
  • cos(x) : x 라디안의 코사인(cosine)을 반환합니다.
  • sin(x) : x 라디안의 사인(sine)을 반환합니다.
  • tan(x) : x 라디안의 탄젠트(tangent)를 반환합니다.

다음은 각도 변환 함수 입니다.

  • degrees(x) : 각도 x를 라디안에서 도(degree)로 변환합니다.
  • radians(x) : 각도 x를 도(degree)에서 라디안으로 변환합니다.

다음은 수학함수를 사용한 예 입니다.

    <xacro:property name="circle_revolute_upper" value="${pi/2}"/>
    <xacro:property name="circle_revolute_upper" value="${radians(180)}"/>

      <origin xyz="0.0 0.0 ${height/2+joint_height}" rpy="0.0 0.0 0.0"/>

 4. 조건부 블럭

조건부 블럭(Conditional Blocks)은 변수의 참(true, 1), 거짓(false, 0)에 따라서 다르게 정의를 할 수 있습니다. 다음은 180도 서보모터와 360도 서보모터 일 때 다르게 정의하는 예 입니다.

  <xacro:property name="servo_180" value="1"/>

  <xacro:if value="${servo_180 == 1}">
    <xacro:property name="circle_revolute_lower" value="${-pi/2}"/>
    <xacro:property name="circle_revolute_upper" value="${pi/2}"/>
  </xacro:if>
  <xacro:unless value="${servo_180 == 1}">
    <xacro:property name="circle_revolute_lower" value="${-radians(180)}"/>
    <xacro:property name="circle_revolute_upper" value="${radians(180)}"/>
  </xacro:unless>

위 예에서 servo_180의 값이 1이면 180도 서보모터이고 servo_180의 값이 1이 아니면 360도 서보모터입니다. 위의 조건식 ${servo_180 == 1}의 결과는 true(참)이거나 1이 되어야 하고 false(거짓)이거나 0의 값이 되어야 합니다. 그 결과 값이 그 외의 값이 되면 오류 입니다.

다음은 속성(property)에 배열을 사용할 수 있습니다. 배열로 선언은 다음과 같습니다.

  <xacro:property name="servo_revolute_type" value="${[1,2,3]}"/>

  <xacro:if value="${1 in servo_revolute_type}">
  </xacro:if>

  <xacro:if value="${2 in servo_revolute_type}">
  </xacro:if>

  <xacro:if value="${3 in servo_revolute_type}">
  </xacro:if>

  <xacro:if value="${4 in servo_revolute_type}">
  </xacro:if>

위 예에서 1,2,3은 참(true)이고 ${4 in servo_revolute_type}은 거짓이 됩니다.

다음은 C언어의 switch()문과 같은 형태로 사용을 하는 예 입니다.

  <xacro:property name="servo_revolute_type" value="${[1]}"/>

  <xacro:if value="${1 in servo_revolute_type}">
    <xacro:property name="revolute_lower" value="${0}"/>
    <xacro:property name="revolute_upper" value="${-pi/2}"/>
  </xacro:if>

  <xacro:if value="${2 in servo_revolute_type}">
    <xacro:property name="revolute_lower" value="${pi/2}"/>
    <xacro:property name="revolute_upper" value="${-pi/2}"/>
  </xacro:if>

  <xacro:if value="${3 in servo_revolute_type}">
    <xacro:property name="revolute_lower" value="${pi}"/>
    <xacro:property name="revolute_upper" value="${-pi}"/>
  </xacro:if>

 5. 매크로(macro)

매크로(macro)는 속성 블럭(property block)과 같이 XML문을 대치 합니다. 차이점은 속성 블럭은 인자(parameter)를 받을 수 없으나 매크로는 인자를 받을 수 있습니다. C언어의 함수와 유사 합니다. 다음은 suffix라는 인자 한 개를 받는 예 입니다.

  <xacro:macro name="link_box_macro" params="suffix">
    <link name="link_${suffix}">
      <xacro:insert_block name="link_inertial_box" />
      <xacro:insert_block name="link_visual_box" />
      <xacro:insert_block name="link_collision_box" />
    </link>
  </xacro:macro>

위 매크로(macro)는 URDF에서 링크(link, 몸체)를 정의하는 매크로로써 사용은 다음과 같습니다.

  <xacro:link_box_macro suffix="1"  />

매크로의 인자(parameter)는 여러 개를 받을 수 있으며, 기본값(default value)를 추가하여 정의를 하면 호출할 때 해당 인자를 생략 할 수 있습니다.
다음과 같이 인자 axis에 axis:='0.0 0.0 1.0' 형식으로 정의를 하며, 기본값은 '0.0 0.0 1.0' 됩니다. 기본 값에는 속성(property)와 같이 ${}로 줄 수있고, 수학 함수나 상수 값도 줄 수 있습니다.

  <xacro:macro name="revolute_circle_joint_macro" params="suffix parent child axis:='0.0 0.0 1.0'">
    <joint name="joint_${suffix}" type="revolute">
      <origin xyz="0.0 0.0 ${joint_height+height}" rpy="0.0 0.0 0.0"/>
      <parent link="${parent}"/>
      <child link="${child}"/>
      <axis xyz="${axis}"/>
      <limit lower="${circle_revolute_lower}" upper="${circle_revolute_upper}" effort="30" velocity="1"/>
    </joint>
  </xacro:macro>

당연한 이야기지만, 호출할 때 axis 값을 포함해서 사용할 수도 있고, 생략을 하게 되면 기본값으로 대치가 됩니다. 다음은 위 매크로를 사용하는 예 입니다.

  <xacro:revolute_circle_joint_macro suffix="1" parent="base_link" child="link_1" />

 6. 디버깅 및 URDF 문법 검사

URDF 파일의 문법이 맞는지는 check_urdf 유틸리티를 통해서 할 수 있습니다. 이 문서에서는 xacro urdf 파일이기 때문에 check_urdf 유틸리티로 문법 검사를 하기 전에 xacro 유틸리티를 통해서 xacro urdf를 순수한 urdf로 변환을 한 후에 check_urdf로 검사를 해야 합니다. xacro 유틸리티를 통해 urdf로 변환을 하면 실제 적용된 값을 확인할 수 있습니다. 다음과 같이 한 번에 URDF 문법 검사를 할 수 있습니다.

   $ xacro model.urdf > tmp.urdf && check_urdf tmp.urdf && rm tmp.urdf

xacro wiki 페이지는 http://wiki.ros.org/xacro 입니다.

댓글