您正在阅读的是旧版本但仍受支持的 ROS 2 文档。 Jazzy.
使用 Xacro 清理代码
目标 学习一些使用 Xacro 减少 URDF 文件中代码量的技巧
辅导水平: 中级
时间 20 分钟
现在,如果你正在家里按照这些步骤设计自己的机器人,你可能已经厌倦了为了让非常简单的机器人描述正确解析而进行各种数学计算。幸运的是,您可以使用 xacro 软件包,让你的生活更简单。它有三个非常有用的功能。
常数
简单数学
宏
在本教程中,我们将介绍所有这些快捷方式,以帮助减小 URDF 文件的整体大小,使其更易于阅读和维护。
使用 Xacro
顾名思义 xacro 是一种 XML 宏语言。xacro 程序运行所有宏并输出结果。典型用法如下
xacro model.xacro > model.urdf
您还可以在启动文件中自动生成 urdf。这很方便,因为它可以保持更新,而且不会占用硬盘空间。不过,生成需要一定时间,因此请注意启动文件可能需要更长时间才能启动。
要在启动文件中运行 xacro,需要将 指挥
的参数 机器人状态发布者
.
path_too_urdf = 获取软件包共享路径('turtlebot3_description';) / 'urdf'; / 'turtlebot3_burger.urdf';
机器人状态发布节点 = 发射.行动.节点(
包装='robot_state_publisher';,
可执行='robot_state_publisher';,
参数=[{
'robot_description';: 参数值(
指挥(['xacro';, 字符串(path_too_urdf)]), 值类型=字符串
)
}]
)
加载机器人模型的更简便方法是使用 urdf_launch 软件包,以自动加载 xacro/urdf。
从 启动 舶来品 启动说明
从 launch.actions 舶来品 包含启动描述
从 launch.substitutions 舶来品 路径连接替换
从 launch_ros.substitutions 舶来品 查找软件包共享
捍卫 生成发射描述():
ld = 启动说明()
ld.add_action(包含启动描述(
路径连接替换([查找软件包共享('urdf_launch'), 'launch';, 'display.launch.py';]),
启动参数={
'urdf_package': 'turtlebot3_description';,
'urdf_package_path': 路径连接替换(['urdf';, 'turtlebot3_burger.urdf';])}.项目()
))
返回 ld
在 URDF 文件的顶部,您必须指定一个命名空间,以便正确解析文件。例如,这是一个有效 xacro 文件的前两行:
<?xml版本="1.0"?>;
机器人 xmlns:xacro="http://www.ros.org/wiki/xacro"; 名称消防员;>;
常数
让我们快速浏览一下 R2D2 中的 base_link。
链接 名称"base_link";>;
视觉效果
<几何>;
气缸 长度="0.6"; 半径="0.2";/>;
</geometry>;
材料 名称蓝色;/>;
</visual>;
<碰撞>;
<几何>;
气缸 长度="0.6"; 半径="0.2";/>;
</geometry>;
</collision>;
</link>;
这里的信息有点多余。我们两次指定了圆柱体的长度和半径。更糟糕的是,如果我们想要更改,需要在两个不同的地方进行更改。
幸运的是,xacro 允许您指定作为常量的属性。我们可以写这样的代码来代替上述代码。
<xacro:property 名称宽度"; value="0.2"; />;
<xacro:property 名称"bodylen"; value="0.6"; />;
链接 名称"base_link";>;
视觉效果
<几何>;
气缸 半径="${width}"; 长度="${bodylen}";/>;
</geometry>;
材料 名称蓝色;/>;
</visual>;
<碰撞>;
<几何>;
气缸 半径="${width}"; 长度="${bodylen}";/>;
</geometry>;
</collision>;
</link>;
前两行指定了两个值。它们可以定义在任何地方(假设 XML 有效)、任何层级、使用之前或之后。通常它们放在最上面。
我们没有在几何元素中指定实际半径,而是使用美元符号和大括号来表示该值。
该代码将生成与上图相同的代码。
然后,${} 结构的内容值将被用来替换 ${}。这意味着您可以将其与属性中的其他文本结合起来。
<xacro:property 名称"机器人名称" value="马文" />;
链接 名称"${机器人名称}s_腿" />;
这将产生
链接 名称"马文腿" />;
然而,${}中的内容不一定只能是一个属性,这就引出了我们的下一个问题...
数学
在 ${} 结构中,您可以使用四种基本运算(+,-,*,/)、一元减号和括号,建立任意复杂的表达式。例如
气缸 半径="${wheeldiam/2}"; 长度="0.1";/>;
原产地 xyz="${reflect*(width+.02)} 0 0.25"; />;
除基本数学运算外,您还可以使用更多运算,例如 罪过
和 系数
.
宏
这是 xacro 软件包中最大、最有用的组件。
简单宏
让我们来看看一个简单的无用宏。
<xacro:macro 名称"default_origin";>;
原产地 xyz="0 0 0"; rpy="0 0 0";/>;
</xacro:macro>;
<xacro:default_origin />;
(这是无用的,因为如果不指定原点,它的值与此相同)。这段代码将生成以下内容。
原产地 rpy="0 0 0"; xyz="0 0 0";/>;
从技术上讲,名称不是必填元素,但您需要指定名称才能使用它。
每个
<xacro:$NAME />;
的内容替换为xacro:macro
标签请注意,尽管不完全相同(两个属性的顺序互换了),但生成的 XML 是等价的。
如果未找到指定名称的 xacro,则不会展开,也不会产生错误。
参数化宏
您还可以为宏设置参数,这样宏就不会每次都生成完全相同的文本。如果与数学功能相结合,功能会更加强大。
首先,让我们以 R2D2 中使用的一个简单宏为例。
<xacro:macro 名称"默认惯性"; params="质量";>;
<惯性>;
质量 value="${mass}"; />;
惯性 ixx=1e-3"; ixy="0.0"; ixz="0.0";
iyy=1e-3"; iyz="0.0";
izz=1e-3"; />;
</inertial>;
</xacro:macro>;
可与代码
<xacro:default_inertial 质量="10";/>;
参数的作用与属性相同,您可以在表达式中使用它们
您也可以使用整个区块作为参数。
<xacro:macro 名称"blue_shape"; params="名称 *形状";>;
链接 名称"${name}";>;
视觉效果
<几何>;
<xacro:insert_block 名称形状 />;
</geometry>;
材料 名称蓝色;/>;
</visual>;
<碰撞>;
<几何>;
<xacro:insert_block 名称形状 />;
</geometry>;
</collision>;
</link>;
</xacro:macro>;
<xacro:blue_shape 名称"base_link";>;
气缸 半径=".42"; 长度=".01"; />;
</xacro:blue_shape>;
要指定块参数,请在参数名称前加上星号。
可以使用 insert_block 命令插入代码块
插入图块的次数不限。
实际用途
xacro 语言的使用非常灵活。以下是 xacro 在以下应用程序中的几种实用方法 R2D2 模型除了上图所示的默认惯性宏之外。
要查看 xacro 文件生成的模型,请运行与之前教程相同的命令:
ros2 launch urdf_tutorial display.launch.py model:=urdf/08-macroed.urdf.xacro
(启动文件一直在运行 xacro 命令,但由于没有宏要展开,所以这并不重要)。
腿部宏观
您经常需要在不同位置创建多个外观相似的对象。您可以使用宏和一些简单的数学计算来减少您需要编写的代码量,就像我们在 R2 的两条腿上所做的那样。
<xacro:macro 名称"腿"; params="前缀反射";>;
链接 名称"${prefix}_leg";>;
视觉效果
<几何>;
<box size="${leglen} 0.1 0.2";/>;
</geometry>;
原产地 xyz="0 0 -${leglen/2}"; rpy="0 ${pi/2} 0";/>;
材料 名称"白色";/>;
</visual>;
<碰撞>;
<几何>;
<box size="${leglen} 0.1 0.2";/>;
</geometry>;
原产地 xyz="0 0 -${leglen/2}"; rpy="0 ${pi/2} 0";/>;
</collision>;
<xacro:default_inertial 质量="10";/>;
</link>;
<joint 名称"base_to_${prefix}_leg"; type="固定";>;
<parent link="base_link";/>;
孩子 link="${prefix}_leg";/>;
原产地 xyz="0 ${reflect*(width+.02)} 0.25"; />;
</joint>;
<! -- 剪掉了一堆东西 -->;
</xacro:macro>;
<xacro:leg 前缀="右"; 反射=1"; />;
<xacro:leg 前缀="左"; 反射="-1"; />;
常用伎俩 1:使用名称前缀获得两个名称相似的对象。
常用技巧 2:使用数学计算关节原点。在改变机器人尺寸的情况下,使用数学计算来计算关节偏移,可以省去很多麻烦。
常用伎俩 3:使用反射参数,并将其设置为 1 或-1。请看我们是如何使用反射参数,在 base_too_${prefix}_leg 原点中将腿放在身体两侧的。