3. Xacro优化机械臂模型
任务目标
在ROS中,直接编写URDF描述多关节机械臂时,连杆尺寸、关节原点等参数散落各处,修改一处尺寸往往需要同步调整多个坐标,极易出错。本案例使用Xacro宏定义重构机械臂URDF,将连杆长度、半径等尺寸参数化,通过宏调用生成完整模型,实现“改一处参数、全模型联动更新”。
实现原理
Xacro(XML Macros)是URDF的预处理工具,支持属性定义、数学表达式和宏调用。核心思路:
- 用
<xacro:property>定义全局尺寸参数(如连杆长度、关节偏移) - 用
<xacro:macro>封装重复的连杆+关节结构,通过参数传入不同尺寸 - 用
${}语法进行数学运算,自动计算关节原点坐标
完整代码
创建 arm.xacro 文件,内容如下:
<?xml version="1.0"?>
<robot name="xacro_arm" xmlns:xacro="http://www.ros.org/wiki/xacro">
<!-- 全局尺寸参数 -->
<xacro:property name="base_radius" value="0.05" />
<xacro:property name="link1_len" value="0.3" />
<xacro:property name="link2_len" value="0.25" />
<xacro:property name="link_radius" value="0.03" />
<xacro:property name="joint_gap" value="0.02" />
<!-- 材料定义 -->
<material name="base_mat">
<color rgba="0.8 0.2 0.2 1.0"/>
</material>
<material name="link_mat">
<color rgba="0.2 0.4 0.8 1.0"/>
</material>
<!-- 宏:生成一个连杆+其末端旋转关节 -->
<xacro:macro name="link_with_joint" params="prefix len parent_link origin_xyz origin_rpy axis">
<link name="${prefix}_link">
<visual>
<geometry>
<cylinder length="${len}" radius="${link_radius}"/>
</geometry>
<origin xyz="0 0 ${len/2}" rpy="0 0 0"/>
<material name="link_mat"/>
</visual>
<collision>
<geometry>
<cylinder length="${len}" radius="${link_radius}"/>
</geometry>
</collision>
</link>
<joint name="${prefix}_joint" type="revolute">
<parent link="${parent_link}"/>
<child link="${prefix}_link"/>
<origin xyz="${origin_xyz}" rpy="${origin_rpy}"/>
<axis xyz="${axis}"/>
<limit lower="-3.14" upper="3.14" effort="10" velocity="1.0"/>
</joint>
</xacro:macro>
<!-- 基座 -->
<link name="base_link">
<visual>
<geometry>
<cylinder length="0.06" radius="${base_radius}"/>
</geometry>
<origin xyz="0 0 0.03" rpy="0 0 0"/>
<material name="base_mat"/>
</visual>
<collision>
<geometry>
<cylinder length="0.06" radius="${base_radius}"/>
</geometry>
</collision>
</link>
<!-- 调用宏生成两个连杆 -->
<xacro:link_with_joint prefix="link1" len="${link1_len}" parent_link="base_link"
origin_xyz="0 0 0.06" origin_rpy="0 0 0" axis="0 0 1"/>
<xacro:link_with_joint prefix="link2" len="${link2_len}" parent_link="link1_link"
origin_xyz="0 0 ${link1_len + joint_gap}" origin_rpy="0 0 0" axis="0 1 0"/>
</robot>
运行与验证
环境依赖:ROS(Noetic或Melodic均可),需安装 ros-noetic-xacro(或对应版本)。
步骤1:将上述代码保存为 arm.xacro,然后执行Xacro展开为URDF:
rosrun xacro xacro arm.xacro > arm.urdf
步骤2:检查生成的URDF是否完整且无报错:
check_urdf arm.urdf
步骤3:在RViz中可视化验证模型结构:
roslaunch urdf_tutorial display.launch model:=arm.urdf
验证通过条件:
check_urdf输出显示Successfully parsed URDF,且列出3个link(base_link、link1_link、link2_link)和2个joint,无警告或错误。- RViz中显示红色基座和两节蓝色连杆,关节呈串联结构,拖动关节滑块时对应连杆绕轴旋转。
- 修改
arm.xacro顶部link1_len的值为0.4,重新执行步骤1和2,确认arm.urdf中link1的cylinder长度变为0.4,且link2_joint的z坐标自动更新为0.4 + 0.02 = 0.42,无需手动修改坐标。
关键说明
- 宏参数
origin_xyz和origin_rpy以字符串形式传入,Xacro会将其原样写入joint的origin标签,因此调用时需给出完整的三元组。 - 第二个关节的z坐标使用
${link1_len + joint_gap}表达式,验证了参数化联动效果——修改全局参数后,所有依赖它的坐标自动重算。 - 本例未包含末端执行器,如需扩展,只需再调用一次宏并传入新的prefix和尺寸即可,无需重复编写link/joint结构。