4. <link>标签详解:惯性、碰撞、视觉属性,以及 <geometry> 的四种基本形状

说到 URDF 里的 <link>,我脑子里第一反应就是「机器人的骨头」。每个刚体部件,不管是一个轮子、一块底盘,还是一根手指,都得靠 <link> 来定义。今天咱们就把这个标签彻底拆开,看看它肚子里到底装了啥。

我个人习惯把 <link> 分成三大块:视觉(长什么样)、碰撞(怎么撞)、惯性(多重、多难推动)。另外还有一个核心子标签 <geometry>,它决定了形状。嗯,咱们一个一个来。

<link> 标签 视觉 visual 碰撞 collision 惯性 inertial geometry + 材质 geometry (简化) mass + inertia box / cylinder / sphere / mesh box / cylinder / sphere / mesh box / cylinder / sphere / mesh 四种基本形状贯穿 visual / collision / inertial

4.1 视觉属性 —— 让机器人「看起来」像样

<visual> 负责定义这个 link 在 Rviz 或 Gazebo 里长什么样。说白了就是给人看的。里面必须有一个 <geometry>,还可以加 <origin> 和 <material>。

我记得刚学 URDF 那会儿,总以为 visual 会影响碰撞,其实它俩完全独立。你 visual 画一个巨大的球,碰撞用一个小方块,完全合法。但仿真的时候物理引擎只认碰撞,视觉就是个皮囊。

💡 我的习惯: 视觉几何尽量和碰撞几何保持一致,除非你想做「视觉欺骗」——比如用精细的 mesh 显示,但碰撞用简单的盒子提升性能。

4.2 碰撞属性 —— 物理引擎的「硬骨头」

<collision> 才是仿真里真正干活的。Gazebo 和 MoveIt 用碰撞几何计算接触、摩擦、关节限位。如果你不写 collision,很多仿真器会直接报错,或者干脆不生成这个 link。

我曾经在一个四足机器人项目里偷懒,没给腿部连杆加 collision,结果 Gazebo 里四条腿直接陷进地面。嗯,从那以后我再也不敢省略 collision 了。

⚠️ 注意:碰撞几何的形状越简单,仿真计算越快。能用 box 就别用 mesh,能用 cylinder 就别用 sphere 以外的复杂形状。

4.3 惯性属性 —— 质量与转动惯量

<inertial> 包含 <mass> 和 <inertia>。质量好理解,单位千克。转动惯量 ixx, ixy, ixz, iyy, iyz, izz 这六个值,很多人一看到就头大。

其实你想想看,一个均匀的立方体,绕中心旋转的惯量有公式。我一般用在线计算器或者写个 Python 脚本算,手算容易错。有一次我手动填了一个数量级不对的惯量,机械臂仿真直接抖成筛子……

形状ixx (kg·m²)iyyizz其他惯性积
实心球 (半径0.1m, 质量1kg)0.0040.0040.0040
实心圆柱 (半径0.05m, 高0.2m, 质量0.5kg)0.00210.00210.0006250
立方体 (0.1×0.1×0.1, 质量0.8kg)0.001330.001330.001330

↑ 这些是我常用的快速参考值,实际项目里最好根据真实密度计算。

4.4 <geometry> 的四种基本形状

不管 visual、collision 还是 inertial 里的几何,都靠 <geometry> 定义。URDF 原生支持四种:

  • <box> —— 长方体,用 size="x y z" 指定长宽高。我最常用,简单粗暴。
  • <cylinder> —— 圆柱,参数 radius 和 length。适合轮子、关节连杆。
  • <sphere> —— 球体,只需 radius。做万向轮或者装饰球很方便。
  • <mesh> —— 网格文件,支持 STL、DAE。用 filename 指定路径,还可以用 scale 缩放。
🛠️ 避坑指南:我曾经用了一个单位是英寸的 STL 文件,没加 scale,结果模型在 Rviz 里大得像一栋楼。记得检查 mesh 的单位,通常 URDF 默认米。

来看一个完整的 link 例子,把视觉、碰撞、惯性都揉在一起:

<link name="base_link">
  <visual>
    <origin xyz="0 0 0" rpy="0 0 0"/>
    <geometry>
      <box size="0.4 0.3 0.1"/>
    </geometry>
    <material name="blue">
      <color rgba="0 0.4 0.8 1"/>
    </material>
  </visual>
  <collision>
    <origin xyz="0 0 0" rpy="0 0 0"/>
    <geometry>
      <box size="0.4 0.3 0.1"/>
    </geometry>
  </collision>
  <inertial>
    <mass value="2.5"/>
    <inertia ixx="0.01" ixy="0" ixz="0" iyy="0.02" iyz="0" izz="0.01"/>
  </inertial>
</link>

你看,结构很清晰。origin 可以微调几何中心,但一般我习惯把 link 的原点设在几何中心,省事。

最后说一句,<geometry> 里的 mesh 虽然强大,但尽量控制面数。我见过有人把 10 万面的雕塑直接丢进 URDF,Gazebo 卡成 PPT。优化 mesh 或者用简化碰撞体,是仿真调优的第一步。