3、URDF标签详解(下):<joint>、<collision>、<inertial> 标签的使用与物理属性
上一章我们把 <link> 和 <visual> 聊透了。今天咱们继续往下挖——<joint>、<collision>、<inertial> 这三个标签,才是让机器人“动起来”并且“像真的”的关键。
我个人习惯把 joint 比作机器人的“关节”,collision 是“碰撞壳”,inertial 是“质量感”。缺一个,你的模型要么散架,要么飘轻,要么撞墙没反应。你想想看,是不是这个理?
3.1 <joint> —— 让零件“长”在一起,又能动
joint 标签定义了 link 之间的约束关系。说白了,就是告诉机器人:“这块板子焊在底座上,那个轮子绕着轴转。”
我刚开始写 URDF 时,总把 joint 的 parent 和 child 搞反。结果模型一加载,轮子飞到天上去。后来我养成一个习惯:parent 永远是靠近基座的,child 是末端件。你记住这个,基本不会错。
fixed—— 刚性连接,不能动。比如相机支架。revolute—— 旋转关节,有角度限制。像舵机臂。continuous—— 无限旋转,轮子常用。prismatic—— 平移关节,比如升降台。floating—— 6自由度浮动,几乎不用。planar—— 平面运动,少见。
来看一个典型的轮子 joint 怎么写:
<joint name="left_wheel_joint" type="continuous">
<parent link="base_link"/>
<child link="left_wheel"/>
<origin xyz="0.2 -0.15 0" rpy="0 0 0"/>
<axis xyz="0 1 0"/>
</joint>
axis 定义了旋转轴。这里 0 1 0 表示绕 Y 轴旋转。我记得有一次帮同事排查,他轮子死活不转,最后发现 axis 写成了 1 0 0,轮子变成“侧滚翻”。嗯,细节决定成败。
revolute 类型,别忘了加 <limit> 子标签,否则 Gazebo 会报错。我曾经被这个坑过,仿真器直接罢工。
3.2 <collision> —— 给机器人穿上“碰撞感应衣”
很多人觉得 collision 和 visual 用一样的几何体就行了。其实不然。collision 的几何体可以更简化——用更少的顶点,换来更快的碰撞检测。
我做过一个六足机器人,每条腿都用精细的 STL 模型做 visual,但 collision 只用圆柱和方块组合。仿真速度提升了将近一倍。你想想看,导航和避障时,碰撞检测每帧都在跑,能不省吗?
<collision>
<origin xyz="0 0 0" rpy="0 0 0"/>
<geometry>
<cylinder radius="0.05" length="0.2"/>
</geometry>
</collision>
3.3 <inertial> —— 让机器人有“重量感”
没有 inertial 的 link,在 Gazebo 里会被当成“零质量”物体。仿真一启动,直接飞走。我见过不少新手在这卡住。
inertial 包含三个部分:mass(质量)、origin(质心位置)、inertia(惯性张量)。其中惯性张量矩阵的六个分量(ixx, iyy, izz, ixy, ixz, iyz)最容易让人头疼。
| 参数 | 含义 | 典型值(小轮子) |
|---|---|---|
| mass | 质量 (kg) | 0.2 |
| ixx | 绕X轴转动惯量 | 0.0001 |
| iyy | 绕Y轴转动惯量 | 0.0001 |
| izz | 绕Z轴转动惯量 | 0.0002 |
| ixy, ixz, iyz | 惯性积(对称性高时可设为0) | 0.0 |
实际项目中,我一般用 圆柱或立方体近似公式 快速估算惯性张量。比如实心圆柱绕中心轴:I = 0.5 * m * r²。别怕算,大概值就行,物理引擎会帮你平滑。
<inertial>
<mass value="0.5"/>
<origin xyz="0 0 0.02"/>
<inertia ixx="0.0003" ixy="0.0" ixz="0.0"
iyy="0.0003" iyz="0.0" izz="0.0005"/>
</inertial>
urdf_to_graphiz 工具检查模型,inertial 缺失会显示警告。我个人习惯每个 link 都配上 inertial,哪怕质量设很小,也比没有强。
3.4 三者如何配合?—— 一个完整的小例子
下面是一个单轮模块的 URDF 片段,包含了 joint、collision、inertial。你可以看到它们如何协同工作:
<link name="caster_wheel">
<visual>
<geometry><sphere radius="0.03"/></geometry>
</visual>
<collision>
<geometry><sphere radius="0.03"/></geometry>
</collision>
<inertial>
<mass value="0.05"/>
<inertia ixx="0.00001" iyy="0.00001" izz="0.00001"
ixy="0" ixz="0" iyz="0"/>
</inertial>
</link>
<joint name="caster_joint" type="continuous">
<parent link="base_link"/>
<child link="caster_wheel"/>
<origin xyz="0.1 -0.2 -0.05"/>
<axis xyz="0 0 1"/>
</joint>
你看,collision 用了和 visual 一样的球体,因为球体碰撞检测本来就快。inertial 给了很小的质量,但足够让物理引擎认真对待它。
嗯,这一章的内容就到这里。标签虽小,但每个都关系到机器人能不能“好好走路”。下一章我们会聊几何体和材质,到时候再细说 visual 的花样。