3、URDF标签详解(下):<joint>、<collision>、<inertial> 标签的使用与物理属性

上一章我们把 <link> 和 <visual> 聊透了。今天咱们继续往下挖——<joint>、<collision>、<inertial> 这三个标签,才是让机器人“动起来”并且“像真的”的关键。

我个人习惯把 joint 比作机器人的“关节”,collision 是“碰撞壳”,inertial 是“质量感”。缺一个,你的模型要么散架,要么飘轻,要么撞墙没反应。你想想看,是不是这个理?

URDF 物理与运动核心标签 <joint> 运动学 + 驱动 <collision> 碰撞检测 + 安全 <inertial> 质量 / 惯性 / 质心 type / parent / child origin / axis limit / dynamics mimic / safety_controller geometry (box/cylinder/ sphere/mesh) origin 偏移 (与 visual 可不同) mass (kg) inertia (ixx/iyy/izz ixy/ixz/iyz) origin (质心) 三者配合:joint 决定运动,collision 决定接触,inertial 决定物理响应

3.1 <joint> —— 让零件“长”在一起,又能动

joint 标签定义了 link 之间的约束关系。说白了,就是告诉机器人:“这块板子焊在底座上,那个轮子绕着轴转。”

我刚开始写 URDF 时,总把 joint 的 parent 和 child 搞反。结果模型一加载,轮子飞到天上去。后来我养成一个习惯:parent 永远是靠近基座的,child 是末端件。你记住这个,基本不会错。

joint 的六种类型:
  • 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>
collision 的 origin 可以跟 visual 不同。但如果你用 Gazebo 仿真,碰撞几何体的中心一定要和实际质心大致对齐,否则物理引擎会给出奇怪的反作用力。

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 给了很小的质量,但足够让物理引擎认真对待它。

核心原则: joint 定义运动链,collision 定义接触边界,inertial 定义动力学响应。三者缺一不可,尤其在导航仿真中,错误的碰撞或惯性参数会导致路径规划异常、定位漂移。

嗯,这一章的内容就到这里。标签虽小,但每个都关系到机器人能不能“好好走路”。下一章我们会聊几何体和材质,到时候再细说 visual 的花样。