ROS学习-xacro
Xacro(XML Macros)Xacro 是一种 XML 宏语言. 使用 xacro, 可以通过使用宏命令构建更精悍短小但又具有更高可读性的 XML 文件, 这种宏命令可以扩展达到更大的 XML 表达范围. 此包在处理大型 XML 文档(如机器人说明)时最为有用. 它在如 urdf 的包中大量使用. 本文主要来源于官方教程.
目录
1. 案例
2. 属性和属性块
3. 数学表达式
4. 条件块
5. Rospack
命令
6. 宏命令
6.1 默认参数
6.2 局部属性
7. 包含其他xacro
文件
8. YAML
语言支持
9. 用CMakeLists.txt
进行构建
10. 元素和属性
11. 处理顺序
12. 已弃用的语法
案例
参考以下的Xacro XML
片段:
1 | <xacro:macro name="pr2_arm" params="suffix parent reflect"> |
上面的片段扩展成为下面的样子:
1 | <pr2_upperarm suffix="left" reflect="1" parent="torso" /> |
如果我们还定义了pr2_upperarm
和pr2_forearm
的宏, 那么这个片段可以扩展以描述整个机器人臂.
本文的其余部分描述了xacro
的功能.
属性和属性块
属性是可以插入到XML
文档中的任何位置的值. 属性块是XML
的名称片段, 可以插入允许XML
的任何位置. 两者都使用属性标签来定义值. 属性标签不能在xacro:macro
中声明. 以下示例将显示如何声明和使用属性:
1 | <xacro:property name="the_radius" value="2.1" /> |
通过将名称放在dollared-braces
(${}
)中, 你可以将两个属性值插入到几何表达式中. 如果你想要一个文本"{"
, 你应该将其转义为"$${"
.
下面是使用属性块的示例:
1 | <xacro:property name="front_left_origin"> |
数学表达式
在dollared-braces
(${}
)中, 您还可以编写简单的数学表达式. 目前, 该结构支持基本算术和变量替换. 下面是一个例子:
1 | <xacro:property name="pi" value="3.1415926535897931" /> |
在Jade
版本的ROS
中更新的地方:
自ROS Jade
以来, Xacro
使用python
来评估包含在dollared-braces
(${}
)中的表达式. 这允许用户使用更复杂的算术表达式. 此外, 一些基本常数, 例如pi
, 已经被预定义过了:
1 | <xacro:property name="R" value="2" /> |
条件块
在Hydro
版本的ROS
中更新的地方:
自从ROS Hydro
以来, Xacro
有类似于roslaunch
的条件块. 这对于可配置的机器人或加载不同的Gazebo
插件等事情很有用. 它遵循以下语法:
1 | <xacro:if value="<expression>"> |
表达式需要计算结果为"0"
, "1"
, "true"
或"false"
, 否则将抛出错误.
在Jade
版本的ROS
中更新的地方:ROS Jade
中更强大的评估功能允许使用更复杂的表达式. 几乎任何python
表达式的计算结果都是可行的:
1 | <xacro:property name="var" value="useit"/> |
Rospack
命令
Xacro
允许你使用某些rospack
命令和dollared-braces
(${}
).
1 | <foo value="$(find xacro)" /> |
Xacro
目前支持使用substitution args
的roslaunch
支持的所有rospack
命令. 参数需要在命令行中使用myvar := true
语法指定.
在Indigo
版本的ROS
中更新的地方:
自从ROS Indigo
, 它也可以像如下定义默认值:
1 | <xacro:arg name="myvar" default="false"/> |
通过这种方式, 你可以像下面这样运行xacro
:
1 | <param name="robot_description" command="$(find xacro)/xacro.py $(arg model) myvar:=true" /> |
宏命令
xacro
的主要特性是它对宏的支持. 使用宏标签定义宏, 并指定宏名称和参数列表. 参数列表应以空格分隔. 它们变成macro-local
属性.
1 | <xacro:macro name="pr2_caster" params="suffix *origin **content **anothercontent"> |
该示例声明了一个宏"pr2_caster"
, 它有两个参数: suffix
和origin
. 请注意, “origin”已加星标. 这表明 origin 是一个块参数, 而不是一个简单的文本参数. 看下pr2_caster
的使用. suffix
属性(property
)在pr2_caster
标签中定义为属性(attribute
), 但没有定义origin
属性. 相反, origin
指的是第一个元素("pose"
块). 双星号版本("content"
, "anothercontent"
)允许插入在随后可用的元素(在上面的示例中分别是"container"
, "another"
)中传递的任意数量的元素. 此示例扩展为以下内容:
1 | <joint name="caster_front_left_joint"> |
多个块参数将按指定的顺序处理:
1 | <xacro:macro name="reorder" params="*first *second"> |
宏可能包含其他宏. 外部宏将首先展开, 然后内部宏将展开. 例如:
1 | <a> |
变成:
1 | <a> |
默认参数
Indigo
中更新
宏参数可以有默认值:
1 | <xacro:macro name="foo" params="x:=${x} y:=${2*y} z:=0"/> |
如果默认值包含评估表达式, 则将在实例化时评估它们.
Jade
中更新
通常, 您需要将外部变量传递到本地宏参数(如上面的x
). 要简化此任务, 可以使用^
语法:
1 | <xacro:macro name="foo" params="p1 p2:=expr_a p3:=^ p4:=^|expr_b"> |
插入符号^
表示使用外部scope
属性(具有相同名称). 管道|
表示如果属性未在外部范围中定义, 则使用给定的回退.
局部属性
Jade
中更新
在宏中定义的属性和宏对于该宏来说是局部的, 即在外部不可见. 使用可选属性scope ="parent | global"
, 属性定义可以导出到宏的父作用域(或全局作用域).
包含其他xacro
文件
您可以使用xacro: include
标签来包含其他xacro
文件:
1 | <xacro:include filename="$(find package)/other_file.xacro" /> |
文件"other_file.xacro"
将被xacro
包含和扩展. Jade
中的新功能: 相对文件名相对于当前处理的文件进行解释. 注意: 当在宏中包含文件时, 包含处理不是宏定义, 而是宏调用文件! $(cwd)
显式的允许访问当前工作目录中的文件.
为了避免各种包含文件的属性和宏之间的名称冲突, 可以为包含的文件指定命名空间 - 提供属性ns
:
1 | <xacro:include filename="other_file.xacro" ns="namespace"/> |
访问命名空间宏和属性是通过预先命名空间来实现的, 用点分隔:
1 | ${namespace.property} |
YAML
语言支
Jade
中的新功能
属性可以是用python
语法声明的字典或列表, 如下所示:
1 | <xacro:property name="props" value="${dict(a=1, b=2, c=3)}"/> |
或者从YAML
文件中加载, 如下:
1 | <xacro:property name="props" value="${load_yaml('props.yaml')}"/ |
注意, 通过evaluation brackets ${}
区分评价和纯文本定义. 校准数据是从 YAML 加载的理想候选.
用CMakeLists.txt
进行构建
以下代码段显示如何在程序包的申明期间使用xacro
:
1 | # Generate .world files from .world.xacro files |
Jade
中的新功能:
虽然这个cmake
代码提供了对目标名称和构建顺序的完全控制, 但还有一个更简便的宏:
1 | file(GLOB xacro_files worlds/*.world.xacro) |
元素与属性
Jade
中的新功能:
要使用动态定义的名称添加元素或属性, 可以使用特殊的xacro
标签
1 | <xacro:element xacro:name="${element_name}" [other attributes]> |
处理顺序
Classicly Xacro
首先加载所有包含项, 然后处理所有属性和宏定义, 最后实例化宏并计算表达式. 因此, 后期定义的属性或宏定义将覆盖先前的定义. 此外, 条件标签, <if>
和<unless>
, 对宏或属性定义以及包含的其他文件没有影响.
Jade
中的新功能:
自ROS Jade
以来, Xacro
提供了命令行选项–-inorder
, 允许以读取的顺序来处理整个文档. 因此, 将使用属性或宏的最新定义. 这是一个更直观的评估过程, 提供了一些不错的新功能:
- 如果
<include>
标签分别放置在宏内或条件标签中, 则可以推迟或完全禁止包含文件. - 包含文件名可以通过属性或宏参数指定.
- 通过更改全局范围的属性, 如果在宏中使用这些属性, 则宏的实例化可以产生不同的结果.
- 属性定义可以是有条件的.
- 宏可以在局部范围内定义属性, 而不会影响外部.
因为–-inorder
处理更强大, 在未来Jade
以后的版本, 新的处理风格将成为默认风格, 所以你应该检查你的xacro
文件的兼容性. 通常, 两种加工方式应该给出相同的结果. 你可以很容易地像下面这样检查:
1 | rosrun xacro xacro file.xacro > /tmp/old.xml |
如果结果显示出任何差异, 你应检查并调整您的 xacro 文件. 常见的原因是校准数据后期加载了(作为属性). 在这种情况下, 只需将加载行为向前移动, 即在使用之前进行校准数据的加载. 为了方便搜索错误放置的属性定义, 可以使用选项-–check--order
运行xacro
. 如果任何有问题的属性, 它们将在stderr
上列出:
1 | Document is incompatible to --inorder processing. |
使用命令行选项-vv
或-vvv
, 可以增加详细程度级别以记录属性的所有定义.
已弃用的语法
Jade
中的新功能:
虽然在以前的版本中, 没有命名空间前缀的xacro
标签能够被接受并使用, 但是这种草率的语法是我们应当强烈反对的, 因为它阻止在最终的XML
中使用这些标签. 从Jade
开始, 这种语法已被弃用, 你应该相应地更新你的文件. 以下脚本将为您更新文件:
1 | find . -iname "*.xacro" | xargs sed -i 's#<\([/]\?\)\(if\|unless\|include\|arg\|property\|macro\|insert_block\)#<\1xacro:\2#g' |
参考链接:
本文标题:ROS学习-xacro
文章作者:xwnb
发布时间:2019-10-24
最后更新:2023-04-17
原始链接:https://xwnb.github.io/posts/2389657244/
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!并保留本声明。感谢您的阅读和支持!
分享