3. 仿真环境概览
好,咱们进入正题。这一章要聊的是机器人建模的基石——URDF。说白了,URDF 就是机器人的「骨架说明书」。你想想看,要让一个虚拟的人形机器人动起来,总得先告诉仿真器它长什么样、胳膊腿怎么连吧?URDF 干的就是这个活。
我个人习惯把 URDF 看作机器人的「身份证」加「户口本」。它用 XML 格式,把机器人拆成一个个零件(连杆),再说明这些零件之间怎么活动(关节)。嗯,这里要注意:URDF 只描述运动学,不涉及动力学参数(那是后面的事)。
核心要点:URDF 是 ROS 生态中机器人建模的标准格式。它定义了机器人的几何外形、碰撞模型、惯性参数以及关节的运动范围。没有它,Rviz2 里就是一片空白。
3.1 URDF 文件结构概览
先看一个最简单的 URDF 骨架。别被 XML 标签吓到,其实结构很清晰:
<robot name="my_robot">
<link name="base_link">
<visual>
<geometry>
<box size="0.5 0.3 0.1"/>
</geometry>
</visual>
</link>
<joint name="base_to_arm" type="fixed">
<parent link="base_link"/>
<child link="arm_link"/>
<origin xyz="0 0 0.2" rpy="0 0 0"/>
</joint>
<link name="arm_link">
<visual>
<geometry>
<cylinder length="0.4" radius="0.05"/>
</geometry>
</visual>
</link>
</robot>
看到没?<robot> 是根标签,里面就两样东西:<link> 和 <joint>。一个连杆配一个关节,像链条一样串起来。我在项目中遇到过新手把连杆和关节搞混——记住:连杆是实体,关节是约束。
3.2 连杆(link)的定义
每个 <link> 描述一个刚体零件。它有三个主要子标签:
| 子标签 | 作用 | 必填? |
|---|---|---|
<visual> |
可视化外观(显示用) | 推荐 |
<collision> |
碰撞检测模型(物理引擎用) | 推荐 |
<inertial> |
惯性参数(质量、转动惯量) | 动力学仿真必填 |
visual 标签里,<geometry> 支持四种基本形状:box、cylinder、sphere、mesh。mesh 可以导入 STL 或 Collada 文件,人形机器人的复杂外形全靠它。
collision 标签我建议尽量用简单几何体代替 mesh。为什么?因为碰撞检测计算量很大,用圆柱体代替手臂,用长方体代替躯干,仿真速度能快不少。我曾经因为用了精细的 STL 做碰撞模型,结果仿真跑起来一卡一卡的……后来全换成基本几何体,流畅多了。
inertial 标签长这样:
<inertial>
<mass value="2.5"/>
<inertia ixx="0.01" ixy="0.0" ixz="0.0"
iyy="0.01" iyz="0.0"
izz="0.005"/>
</inertial>
转动惯量矩阵是对称的,所以只填 6 个独立分量。如果你不确定数值,可以用 CAD 软件算,或者先估一个大概——反正后面还要调。
3.3 关节(joint)的定义
关节决定了两个连杆之间的相对运动。URDF 支持 6 种关节类型:
| 类型 | 自由度 | 典型用途 |
|---|---|---|
fixed |
0 | 固定连接(如摄像头支架) |
revolute |
1(旋转) | 肘关节、膝关节 |
prismatic |
1(平移) | 伸缩机构 |
continuous |
1(无限旋转) | 车轮 |
planar |
2(平面运动) | 少见 |
floating |
6(全自由) | 基座漂浮(如无人机) |
人形机器人最常用的是 revolute 关节。定义时别忘了加 <limit>:
<joint name="left_elbow" type="revolute">
<parent link="left_upper_arm"/>
<child link="left_forearm"/>
<origin xyz="0 0 -0.3" rpy="0 0 0"/>
<axis xyz="0 1 0"/>
<limit lower="-1.57" upper="0.0" effort="30" velocity="3.14"/>
</joint>
这里 <origin> 是子连杆相对于父连杆的位姿,<axis> 是旋转轴。我踩过一个坑:axis 默认是 1 0 0(X 轴),如果忘了写,关节会朝奇怪的方向转。所以每次写关节,我都会检查三遍 axis 和 origin。
避坑指南:我曾经在定义人形机器人的髋关节时,把 origin 的 rpy 写反了顺序。结果模型在 Rviz2 里大腿直接穿模到肚子里……后来养成习惯:先写 xyz,再写 rpy,并且用 rpy="0 0 0" 验证坐标系方向。
3.4 在 Rviz2 中可视化模型
写好了 URDF,怎么看到它?Rviz2 是最直观的工具。步骤很简单:
- 启动 Rviz2:
ros2 run rviz2 rviz2 - 添加 RobotModel 显示插件(Displays 面板左下角 Add → RobotModel)
- 在 RobotModel 属性中设置
Robot Description为你的 URDF 话题(默认/robot_description) - 发布 URDF 到参数服务器:
ros2 param set /robot_description "$(cat my_robot.urdf)"
或者更简单,用 urdf_to_graphiz 工具生成结构图:
urdf_to_graphiz my_robot.urdf
这会生成 my_robot.pdf 和 my_robot.gv,能直观看到连杆和关节的树状结构。
小技巧:如果模型在 Rviz2 里显示不全,检查两点:一是 Fixed Frame 是否设置为你的基座连杆名(比如 base_link);二是 URDF 里所有 link 的 visual 标签是否都有 geometry。我见过有人只写了 collision 没写 visual,结果模型在 Rviz2 里是隐形的。
3.5 本章知识体系
下面这张图总结了 URDF 建模的核心逻辑,从文件结构到可视化验证的完整链路:
从这张图可以看得很清楚:URDF 文件拆成 link 和 joint 两大分支,各自有子属性,最终在 Rviz2 里汇合验证。说白了,建模就是「拆零件 → 定关节 → 看效果」的循环。
3.6 常见问题与调试技巧
- 模型在 Rviz2 里显示为红色问号:通常是 URDF 解析失败。运行
check_urdf my_robot.urdf检查语法错误。 - 关节旋转方向反了:检查
axis的正方向,或者origin的rpy是否与预期一致。 - 连杆位置不对:用
rviz2的TF插件查看坐标系,确认每个 link 的坐标系原点。 - 模型抖动:检查
collision模型是否与visual模型偏差太大,或者惯性参数设置不合理。
调试利器:我习惯在 URDF 里给每个 link 加一个 <material> 颜色标签,这样在 Rviz2 里一眼就能看出哪个连杆对应哪个名字。比如躯干用红色,左臂用蓝色,右臂用绿色——视觉排查效率翻倍。