3、编写第一个机械臂URDF:定义基座、关节与连杆、添加颜色与材质、使用xacro优化模型
好,咱们正式开始动手写代码了。
URDF,全称是 Unified Robot Description Format。说白了,就是用一个 XML 文件,把你的机器人长什么样、关节怎么动,一五一十告诉 Gazebo 和 ROS。我刚开始接触时,觉得这东西不就是个配置文件嘛,有啥难的?结果第一次写完,模型在 Rviz 里直接飞了——嗯,坐标写反了。
核心思想:URDF 用「连杆」和「关节」来描述机器人。连杆是刚体,关节是连接点。一个机械臂,就是一堆连杆通过关节串起来。
3.1 定义基座:从地面开始
基座是机械臂的根。它通常固定在地面或台面上。我个人习惯,先把基座定义成一个简单的圆柱体,后面再换复杂的。
<link name="base_link">
<visual>
<geometry>
<cylinder length="0.1" radius="0.15"/>
</geometry>
<origin xyz="0 0 0" rpy="0 0 0"/>
</visual>
</link>
这里要注意 origin 标签。xyz 是位置,rpy 是旋转(roll, pitch, yaw)。我遇到过一个问题:基座明明放在原点,但模型却悬空了。后来发现是 length 和 origin 的 z 值没配合好。圆柱体的中心在几何中心,所以如果长度是 0.1,底部其实在 z=-0.05 处。想让底部贴地,origin 的 z 要设成 0.05。
小技巧:调试时,先用简单的几何体(圆柱、立方体)代替复杂的 mesh 文件。加载快,问题也容易定位。
3.2 关节与连杆:让机械臂动起来
基座有了,接下来加第一个关节。关节连接基座和第一个活动连杆。我一般用旋转关节(revolute),因为它最符合真实机械臂的转动。
<joint name="joint1" type="revolute">
<parent link="base_link"/>
<child link="link1"/>
<origin xyz="0 0 0.1" rpy="0 0 0"/>
<axis xyz="0 0 1"/>
<limit effort="100" velocity="1.0" lower="-3.14" upper="3.14"/>
</joint>
这里 axis 定义了旋转轴。xyz="0 0 1" 表示绕 Z 轴旋转。我刚开始写时,把轴设成了 xyz="1 0 0",结果机械臂像风车一样横着转,完全不对。后来才意识到,关节的旋转轴是相对于父连杆的坐标系。
然后定义连杆 link1:
<link name="link1">
<visual>
<geometry>
<box size="0.05 0.05 0.3"/>
</geometry>
<origin xyz="0 0 0.15" rpy="0 0 0"/>
</visual>
</link>
这个连杆是一个长条盒子,长 0.3 米。origin 的 z 设成 0.15,是因为盒子的中心在几何中心,要让底部刚好在关节位置,就得向上偏移一半高度。
注意:关节的 origin 和连杆的 origin 是两回事。关节的 origin 是关节在父连杆坐标系中的位置。连杆的 origin 是连杆几何体在连杆坐标系中的位置。搞混了,模型就会「脱臼」。
3.3 添加颜色与材质:让模型看得清
纯白色的模型在 Rviz 里很难分辨方向。加颜色很简单,在 visual 标签里加一个 material:
<material name="blue">
<color rgba="0 0 1 1"/>
</material>
<link name="base_link">
<visual>
<geometry>
<cylinder length="0.1" radius="0.15"/>
</geometry>
<material name="blue"/>
</visual>
</link>
rgba 四个值:红、绿、蓝、透明度。范围 0 到 1。我习惯把基座涂成深灰色,第一个连杆蓝色,第二个连杆绿色,这样一眼就能看出哪个关节在动。
材质可以定义在文件顶部,然后多个连杆引用同一个材质名。这样改颜色时,只改一处就行。
3.4 使用 xacro 优化模型:告别重复劳动
写几个连杆还好,要是写六轴机械臂,每个关节都要重复写 origin、axis、limit,你会疯掉的。这时候 xacro 就派上用场了。
xacro 是 URDF 的宏扩展工具。说白了,就是让你定义变量和函数,然后复用。
举个例子,定义一个宏来生成关节:
<?xml version="1.0"?>
<robot name="my_arm" xmlns:xacro="http://www.ros.org/wiki/xacro">
<xacro:macro name="joint_arm" params="name parent child origin_xyz origin_rpy axis_xyz">
<joint name="${name}" type="revolute">
<parent link="${parent}"/>
<child link="${child}"/>
<origin xyz="${origin_xyz}" rpy="${origin_rpy}"/>
<axis xyz="${axis_xyz}"/>
<limit effort="100" velocity="1.0" lower="-3.14" upper="3.14"/>
</joint>
</xacro:macro>
<xacro:joint_arm name="joint1" parent="base_link" child="link1"
origin_xyz="0 0 0.1" origin_rpy="0 0 0" axis_xyz="0 0 1"/>
<xacro:joint_arm name="joint2" parent="link1" child="link2"
origin_xyz="0 0 0.3" origin_rpy="0 0 0" axis_xyz="0 1 0"/>
</robot>
你看,关节的定义被抽象成了一个宏。每次调用只传参数就行。我项目中有一个六轴机械臂,用 xacro 后,URDF 文件从 500 行缩到了 80 行。维护起来也轻松多了。
建议:把颜色、尺寸、关节限位都定义成 xacro 属性(property),放在文件头部。这样后期调整参数,不用翻遍整个文件。
3.5 本章知识结构图
下面这张图,帮你理清 URDF 的核心逻辑:
这张图展示了 URDF 的骨架。从 robot 根节点出发,分出三个方向:link 定义外观和碰撞,joint 定义连接和运动,xacro 帮你把重复劳动降到最低。
3.6 避坑指南
- 坐标轴方向:我曾经把关节的 axis 写反了,结果机械臂往反方向转。检查时用 Rviz 的「显示坐标系」功能,一目了然。
- 单位统一:URDF 默认单位是米和弧度。如果你从 SolidWorks 导出的模型是毫米,记得除以 1000。我见过有人直接导进去,机械臂大得像摩天大楼。
- 闭合链:URDF 不支持闭环结构。如果你要做并联机械臂,得用其他方式(比如 SDF 或自定义插件)。
- 文件编码:URDF 文件必须是 UTF-8 编码。用 Windows 记事本保存的 ANSI 编码,ROS 会报错。我推荐用 VS Code 或 Sublime Text。
好了,这一章的内容就到这里。写 URDF 就像搭积木,一块一块拼起来。刚开始可能觉得繁琐,但用上 xacro 后,你会发现效率提升不止一个档次。