ROS官方教程[翻译]---xacro的介绍与使用

ROS官方教程[翻译]—xacro的介绍与使用

本教程基于ROS官方xacro教程中jade版本ROS翻译

功能包综述

Xacro(XML Macros)Xacro是一种XML宏语言。 使用xacro,您可以通过使用宏命令构建更精悍短小但又具有更高可读性的XML文件,这种宏命令可以扩展达到更大的XML表达范围。
- 维护状态:正在开发中
- 维护方:Morgan Quigley
- 作者:Stuart Glaser, William Woodall, Robert Haschke
- 许可证:BSD
- 漏洞和特征汇报链接:https://github.com/ros/xacro/issues
- 源:git https://github.com/ros/xacro.git (branch: jade-devel)

目录

  • 1.案例
  • 2.属性和属性块
  • 3.数学表达式
  • 4.条件块
  • 5.Rospack命令
  • 6.宏命令
    • 6.1默认参数
    • 6.2局部属性
  • 7.包含其他xacro文件
  • 8.YAML语言支持
  • 9.用CMakeLists.txt进行构建
  • 10.元素和属性
  • 11.处理订单
  • 12.已弃用的语法

此包在处理大型XML文档(如机器人说明)时最为有用。 它在如urdf的包中大量使用。 通过看下面的例子,本教程教您如何使用xacro来简化urdf文件。

1.案例

参考以下的Xacro XML片段:

<xacro:macro name="pr2_arm" params="suffix parent reflect">
  <pr2_upperarm suffix="${suffix}" reflect="${reflect}" parent="${parent}" />
  <pr2_forearm suffix="${suffix}" reflect="${reflect}" parent="elbow_flex_${suffix}" />
</xacro:macro>

<xacro:pr2_arm suffix="left" reflect="1" parent="torso" />
<xacro:pr2_arm suffix="right" reflect="-1" parent="torso" />

上面的片段扩展成为下面的样子:

<pr2_upperarm suffix="left" reflect="1" parent="torso" />
<pr2_forearm suffix="left" reflect="1" parent="elbow_flex_left" />
<pr2_upperarm suffix="right" reflect="-1" parent="torso" />
<pr2_forearm suffix="right" reflect="-1" parent="elbow_flex_right" />

如果我们还定义了pr2_upperarm和pr2_forearm的宏,那么这个片段可以扩展以描述整个机器人臂。
本页的其余部分描述了xacro的功能。

2.属性和属性块

属性是可以插入到XML文档中的任何位置的值。 属性块是XML的名称片段,可以插入允许XML的任何位置。 两者都使用属性标签来定义值。属性标记不能在xacro:宏中声明。以下示例将显示如何声明和使用属性:

<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}" />

通过将名称放在dollared-braces( {”,你应该将其转义为“$$ {”。
下面是使用属性块的示例:

<xacro:property name="front_left_origin">
  <origin xyz="0.3 0 0" rpy="0 0 0" />
</xacro:property>

<pr2_wheel name="front_left_wheel">
  <xacro:insert_block name="front_left_origin" />
</pr2_wheel>

3.数学表达式

在dollared-braces($ {})中,您还可以编写简单的数学表达式。 目前,该结构支持基本算术和变量替换。 下面是一个例子:

<xacro:property name="pi" value="3.1415926535897931" />
<circle circumference="${2.5 * pi}" />

Jade版本的ROS中更新的地方:

自ROS Jade以来,Xacro使用python来评估包含在dollared-braces($ {})中的表达式。 这允许用户使用更复杂的算术表达式。 此外,一些基本常数,例如 pi,已经被预定义过了:

<xacro:property name="R" value="2" />
<xacro:property name="alpha" value="${30/180*pi}" />
<circle circumference="${2 * pi * R}" pos="${sin(alpha)} ${cos(alpha)}" />

4.条件块

Hydro版本的ROS中更新的地方:

自从ROS Hydro以来,Xacro有类似于roslaunch的条件块。 这对于可配置的机器人或加载不同的Gazebo插件等事情很有用。 它遵循以下语法:

<xacro:if value="<expression>">
  <... some xml code here ...>
</xacro:if>
<xacro:unless value="<expression>">
  <... some xml code here ...>
</xacro:unless>

表达式需要计算结果为“0”,“1”,“true”或“false”,否则将抛出错误。

Jade版本的ROS中更新的地方:

ROS Jade中更强大的评估功能允许使用更复杂的表达式。 几乎任何python表达式的计算结果都是可行的:

<xacro:property name="var" value="useit"/>
<xacro:if value="${var == 'useit'}"/>
<xacro:if value="${var.startswith('use') and var.endswith('it')}"/>

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

5.Rospack命令

Xacro允许你使用某些rospack命令和dollared括号($())。

<foo value="$(find xacro)" />
<foo value="$(arg myvar)" />

Xacro目前支持roslaunch使用替换args支持的所有rospack命令。 参数需要在命令行中使用myvar:= true语法指定。

Indigo版本的ROS中更新的地方:

自从ROS Indigo,它也可以定义默认值如下:

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

使用上面的定义语句,你可以像下面这样运行xacro:

<param name="robot_description" command="$(find xacro)/xacro.py $(arg model) myvar:=true" />

6.宏命令

xacro的主要特性是它对宏的支持。 使用宏标签定义宏,并指定宏名称和参数列表。 参数列表应以空格分隔。 它们变成宏观本地属性。

<xacro:macro name="pr2_caster" params="suffix *origin **content **anothercontent">
  <joint name="caster_${suffix}_joint">
    <axis xyz="0 0 1" />
  </joint>
  <link name="caster_${suffix}">
    <xacro:insert_block name="origin" />
    <xacro:insert_block name="content" />
    <xacro:insert_block name="anothercontent" />
  </link>
</xacro:macro>

<xacro:pr2_caster suffix="front_left">
  <pose xyz="0 1 0" rpy="0 0 0" />
  <container>
    <color name="yellow"/>
    <mass>0.1</mass>
  </container>
  <another>
    <inertial>
      <origin xyz="0 0 0.5" rpy="0 0 0"/>
      <mass value="1"/>
      <inertia ixx="100"  ixy="0"  ixz="0" iyy="100" iyz="0" izz="100" />
    </inertial>
  </another>
</xacro:pr2_caster>

该示例声明了一个宏“pr2_caster”,它有两个参数:suffix和origin。 请注意,“origin”已加星标。 这表明origin是一个块参数,而不是一个简单的文本参数。 向前看pr2_caster的使用。 后缀属性在pr2_caster标记中定义为属性,但没有定义origin属性。 相反,origin指的是第一个元素(在这种情况下是“pose”块)。 双星号版本(“content”,“anothercontent”)允许插入在随后可用的元素(在上面的示例中分别是“container”,“another”)中传递的任意数量的元素。 此示例扩展为以下内容:

<joint name="caster_front_left_joint">
  <axis xyz="0 0 1" />
</joint>
<link name="caster_front_left">
  <pose xyz="0 1 0" rpy="0 0 0" />
  <color name="yellow" />
  <mass>0.1</mass>
  <inertial>
    <origin xyz="0 0 0.5" rpy="0 0 0"/>
    <mass value="1"/>
    <inertia ixx="100"  ixy="0"  ixz="0" iyy="100" iyz="0" izz="100" />
  </inertial>
</link>

将按指定的顺序处理多个块参数:

<xacro:macro name="reorder" params="*first *second">
  <xacro:insert_block name="second"/>
  <xacro:insert_block name="first"/>
</xacro:macro>
<reorder>
  <first/>
  <second/>
</reorder>

宏可能包含其他宏。 外部宏将首先展开,然后内部宏将展开。 例如:

<a>
  <xacro:macro name="foo" params="x">
    <in_foo the_x="${x}" />
  </xacro:macro>

  <xacro:macro name="bar" params="y">
    <in_bar>
      <xacro:foo x="${y}" />
    </in_bar>
  </xacro:macro>

  <xacro:bar y="12" />
</a>

变成:

<a>
  <in_bar>
    <in_foo the_x="12.0"/>
  </in_bar>
</a>

6.1默认参数

Indigo中更新

宏参数可以有默认值:

<xacro:macro name="foo" params="x:=${x} y:=${2*y} z:=0"/>

如果默认值包含评估表达式,则将在实例化时评估它们。

Jade中更新

通常,您需要将外部变量传递到本地宏参数(如上面的x)。 要简化此任务,可以使用^语法:

<xacro:macro name="foo" params="p1 p2:=expr_a p3:=^ p4:=^|expr_b">

插入符号^表示使用外部scope属性(具有相同名称)。 管| 表示如果属性未在外部范围中定义,则使用给定的回退。

6.2局部属性

Jade中更新

在宏中定义的属性和宏在此宏的本地,即在外部不可见。 使用可选属性scope =“parent | global”,属性定义可以导出到宏的父作用域(或全局作用域)。

7.包含其他xacro文件

您可以使用xacro:include标记来包含其他xacro文件:

<xacro:include filename="$(find package)/other_file.xacro" />
<xacro:include filename="other_file.xacro" />
<xacro:include filename="$(cwd)/other_file.xacro" />

文件“other_file.xacro”将被xacro包含和扩展。 Jade中的新功能:相对文件名相对于当前处理的文件进行解释。 注意:当在宏中包含文件时,不是宏定义,而是宏调用文件是处理包含! $(cwd)显式允许访问当前工作目录中的文件。
为了避免各种包含文件的属性和宏之间的名称冲突,可以为包含的文件指定命名空间 - 提供属性ns:

<xacro:include filename="other_file.xacro" ns="namespace"/>

访问命名空间宏和属性是通过预先命名空间来实现的,用点分隔:

${namespace.property}

8.YAML语言支

Jade中的新功能

属性可以是用python语法过度声明的字典或列表,如下所示:

<xacro:property name="props" value="${dict(a=1, b=2, c=3)}"/>
<xacro:property name="numbers" value="${[1,2,3,4]}"/>

或者从YAML文件中加载,如下:

<xacro:property name="props" value="${load_yaml('props.yaml')}"/

注意,评估括号$ {}区分评价和纯文本定义。 校准数据是从YAML加载的理想候选。

9.用CMakeLists.txt进行构建

以下代码段显示如何在程序包的申明期间使用xacro:

# Generate .world files from .world.xacro files
find_package(xacro REQUIRED)
# You can also add xacro to the list of catkin packages:
#   find_package(catkin REQUIRED COMPONENTS ... xacro)

# Xacro files
file(GLOB xacro_files ${CMAKE_CURRENT_SOURCE_DIR}/worlds/*.world.xacro)

foreach(it ${xacro_files})
  # remove .xacro extension
  string(REGEX MATCH "(.*)[.]xacro$" unused ${it})
  set(output_filename ${CMAKE_MATCH_1})

  # create a rule to generate ${output_filename} from {it}
  xacro_add_xacro_file(${it} ${output_filename})

  list(APPEND world_files ${output_filename})
endforeach(it)

# add an abstract target to actually trigger the builds
add_custom_target(media_files ALL DEPENDS ${world_files})

Jade中的新功能:

虽然这个cmake代码提供了对目标名称和构建顺序的完全控制,但还有一个easyilities宏:

file(GLOB xacro_files worlds/*.world.xacro)
xacro_add_files(${xacro_files} TARGET media_files)

10.元素与属性

Jade中的新功能:

要使用动态定义的名称添加元素或属性,可以使用特殊的xacro标记

<xacro:element xacro:name="${element_name}" [other attributes]>
 [content]
</xacro:element>
<xacro:attribute name="${attribute_name}" value="${attribute_value}"/>

11.处理订单

Classicly Xacro首先加载所有包含项,然后处理所有属性和宏定义,最后实例化宏并评估表达式。 因此,后期定义的属性或宏定义将覆盖先前的定义。 此外,条件标签和对宏或属性定义以及包含其他文件没有影响。

Jade中的新功能:

自ROS Jade以来,Xacro提供了命令行选项–inorder,允许以读取顺序处理整个文档。 因此,将使用目前为止看到的属性或宏的最新定义。 这是一个更直观的评估过程,提供了一些不错的新功能:

  • 如果标签分别放置在宏内或条件标签中,则可以推迟或完全禁止包含文件。
  • 包含文件名可以通过属性或宏参数指定。
  • 通过更改全局范围的属性,如果在宏中使用这些属性,则宏的实例化可以产生不同的结果。
  • 属性定义可以是有条件的。
  • 宏可以在本地范围内定义属性,而不会影响外部。

因为 - 顺序处理更强大,在未来Jade以后的版本,新的处理风格将成为默认风格,所以你应该检查你的xacro文件的兼容性。 通常,两种加工方式应该给出相同的结果。 你可以很容易地像下面这样检查:

rosrun xacro xacro file.xacro > /tmp/old.xml
rosrun xacro xacro --inorder file.xacro > /tmp/new.xml
diff /tmp/old.xml /tmp/new.xml

如果结果显示出任何差异,你应检查并调整您的xacro文件。 常见的原因是校准数据后期进行了加载(作为属性)。 在这种情况下,只需将加载行为向前移动,即在使用之前进行校准数据的加载。 为了方便搜索错误放置的属性定义,可以使用选项–check-order运行xacro。 如果有任何有问题的属性,它们将在stderr上列出:

Document is incompatible to --inorder processing.
The following properties were redefined after usage:
foo redefined in issues.xacro

使用命令行选项-vv或-vvv,可以增加详细程度级别以记录属性的所有定义。

12.已弃用的语法

Jade中的新功能:

虽然在以前的版本中,没有命名空间前缀的xacro标签能够被接受并使用,但是这种草率的语法是我们应当强烈反对的,因为它阻止在最终的XML中使用这些标签。 从Jade开始,这种语法已被弃用,你应该相应地更新你的文件。 以下脚本将为您更新文件:

find . -iname "*.xacro" | xargs sed -i 's#<\([/]\?\)\(if\|unless\|include\|arg\|property\|macro\|insert_block\)#<\1xacro:\2#g'
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章