第三章:URDF与机器人建模
说到机器人建模,URDF 是绕不开的第一道坎。我最早接触它的时候,觉得不就是个 XML 文件嘛,写起来应该不难。结果第一次在 Rviz 里看到自己的机器人像个散架的积木,那感觉,嗯,记忆犹新。
URDF 的全称是 Unified Robot Description Format,统一机器人描述格式。说白了,它就是用来告诉 ROS:你的机器人长什么样,关节在哪,能怎么动。今天我们就把它彻底讲透。
URDF 文件结构详解
一个标准的 URDF 文件,核心就两个东西:link 和 joint。link 是刚体部件,joint 是连接它们的关节。我习惯把 link 想象成骨头,joint 想象成关节,这样好理解。
link 的定义
每个 link 需要描述三部分:视觉外观、碰撞模型、惯性参数。来看一个最简单的例子:
<link name="base_link">
<visual>
<geometry>
<box size="0.4 0.3 0.1"/>
</geometry>
<origin xyz="0 0 0" rpy="0 0 0"/>
<material name="blue">
<color rgba="0 0 1 1"/>
</material>
</visual>
<collision>
<geometry>
<box size="0.4 0.3 0.1"/>
</geometry>
<origin xyz="0 0 0" rpy="0 0 0"/>
</collision>
<inertial>
<mass value="2.0"/>
<inertia ixx="0.01" ixy="0" ixz="0"
iyy="0.01" iyz="0"
izz="0.01"/>
</inertial>
</link>
这里有个坑,我刚开始做项目时经常忽略 <collision> 和 <inertial>。结果在 Gazebo 里仿真,机器人要么直接穿透地面,要么物理行为完全不对。记住,visual 只是给人看的,collision 和 inertial 才是给物理引擎用的。
joint 的定义
joint 决定了两个 link 之间的运动关系。常用的关节类型有:
| 类型 | 说明 | 自由度 |
|---|---|---|
| revolute | 旋转关节,有限角度 | 1 |
| continuous | 连续旋转关节,无角度限制 | 1 |
| prismatic | 平移关节 | 1 |
| fixed | 固定连接,不能动 | 0 |
写 joint 的时候,<parent> 和 <child> 的层级关系一定要理清楚。我曾经把 parent 和 child 搞反了,结果整个机械臂的运动学链全乱了,排查了半天才发现是这里的问题。
<joint name="shoulder_joint" type="revolute">
<parent link="base_link"/>
<child link="shoulder_link"/>
<origin xyz="0 0 0.1" rpy="0 0 0"/>
<axis xyz="0 0 1"/>
<limit lower="-1.57" upper="1.57" effort="10" velocity="1.0"/>
</joint>
你想想看,<origin> 定义的是 joint 相对于 parent link 的位置,<axis> 定义的是旋转轴。这两个参数写错了,机器人动起来就会像喝醉了酒一样。
使用 SolidWorks 导出 URDF
手写 URDF 对于简单模型还行,但遇到复杂的机械臂,比如六轴协作机器人,手写就太痛苦了。这时候就需要用 SolidWorks 的 URDF 导出插件。
我个人习惯的流程是这样的:
- 在 SolidWorks 里建好装配体,每个零件作为一个独立的 part
- 定义好配合关系,确保关节的运动副正确
- 安装 sw2urdf 插件,这个插件是 ROS 社区开发的
- 运行导出向导,逐个指定每个 joint 的类型和轴方向
小技巧:导出前,把每个零件的坐标系原点对齐到关节旋转中心。这样导出的 URDF 里 <origin> 参数会更干净,后期调试省很多事。
导出完成后,你会得到一个文件夹,里面包含 URDF 文件、meshes 文件夹(存放 STL 文件)、以及一个 launch 文件。我建议你打开 URDF 文件检查一下,特别是 <inertial> 部分的数值。SolidWorks 导出的惯性参数有时候会偏大,需要手动调整。
注意:SolidWorks 导出的 URDF 默认使用 STL 格式的网格文件。STL 文件比较大,会影响加载速度。我一般会用 meshlab 或者 Blender 把网格简化一下,在不影响外观的前提下减少面数。
在 Rviz 中可视化机器人模型
模型建好了,怎么验证对不对?Rviz 就是最好的工具。你只需要一个 launch 文件,把 robot_description 参数加载到参数服务器,然后启动 Rviz 就行。
<launch>
<param name="robot_description"
textfile="$(find my_robot_description)/urdf/my_robot.urdf"/>
<node name="robot_state_publisher"
pkg="robot_state_publisher"
type="robot_state_publisher"/>
<node name="rviz" pkg="rviz" type="rviz"
args="-d $(find my_robot_description)/config/display.rviz"/>
</launch>
启动后,在 Rviz 里添加 RobotModel 显示插件,你应该就能看到自己的机器人了。如果模型显示不出来,最常见的原因是:
- URDF 文件路径不对,robot_description 没加载成功
- mesh 文件路径是相对路径,但 Rviz 找不到
- joint 的 parent 和 child 命名有拼写错误
我记得有一次,模型死活显示不出来,折腾了两个小时。最后发现是 URDF 文件里一个 link 的名字多了一个空格。这种低级错误,排查起来真的很崩溃。
为了让模型动起来,你还需要发布 joint states。可以用 joint_state_publisher 这个节点,它会弹出一个 GUI 滑块,让你手动拖动每个关节。或者用 joint_state_publisher_gui,效果一样但界面更友好。
核心要点:URDF 建模的本质是建立一棵树状的 kinematics chain。每个 joint 连接两个 link,从 base_link 开始,一直延伸到末端执行器。这棵树的结构决定了机器人的运动学行为。
下面这张图展示了 URDF 建模的核心逻辑,从 SolidWorks 模型到 Rviz 可视化的完整链路:
最后说一句,URDF 建模这件事,看起来简单,但真正做好需要耐心。我见过太多人一上来就想写复杂的模型,结果被各种小问题折磨得放弃。我的建议是:从最简单的两连杆开始,先在 Rviz 里跑通,再逐步增加复杂度。这样每一步都能验证,出了问题也知道从哪里排查。
嗯,URDF 的内容就讲到这里。记住,模型是仿真的基础,基础打牢了,后面的运动学、轨迹规划才能顺利进行。