4. <link>标签详解:惯性、碰撞、视觉属性,以及 <geometry> 的四种基本形状
说到 URDF 里的 <link>,我脑子里第一反应就是「机器人的骨头」。每个刚体部件,不管是一个轮子、一块底盘,还是一根手指,都得靠 <link> 来定义。今天咱们就把这个标签彻底拆开,看看它肚子里到底装了啥。
我个人习惯把 <link> 分成三大块:视觉(长什么样)、碰撞(怎么撞)、惯性(多重、多难推动)。另外还有一个核心子标签 <geometry>,它决定了形状。嗯,咱们一个一个来。
4.1 视觉属性 —— 让机器人「看起来」像样
<visual> 负责定义这个 link 在 Rviz 或 Gazebo 里长什么样。说白了就是给人看的。里面必须有一个 <geometry>,还可以加 <origin> 和 <material>。
我记得刚学 URDF 那会儿,总以为 visual 会影响碰撞,其实它俩完全独立。你 visual 画一个巨大的球,碰撞用一个小方块,完全合法。但仿真的时候物理引擎只认碰撞,视觉就是个皮囊。
4.2 碰撞属性 —— 物理引擎的「硬骨头」
<collision> 才是仿真里真正干活的。Gazebo 和 MoveIt 用碰撞几何计算接触、摩擦、关节限位。如果你不写 collision,很多仿真器会直接报错,或者干脆不生成这个 link。
我曾经在一个四足机器人项目里偷懒,没给腿部连杆加 collision,结果 Gazebo 里四条腿直接陷进地面。嗯,从那以后我再也不敢省略 collision 了。
4.3 惯性属性 —— 质量与转动惯量
<inertial> 包含 <mass> 和 <inertia>。质量好理解,单位千克。转动惯量 ixx, ixy, ixz, iyy, iyz, izz 这六个值,很多人一看到就头大。
其实你想想看,一个均匀的立方体,绕中心旋转的惯量有公式。我一般用在线计算器或者写个 Python 脚本算,手算容易错。有一次我手动填了一个数量级不对的惯量,机械臂仿真直接抖成筛子……
| 形状 | ixx (kg·m²) | iyy | izz | 其他惯性积 |
|---|---|---|---|---|
| 实心球 (半径0.1m, 质量1kg) | 0.004 | 0.004 | 0.004 | 0 |
| 实心圆柱 (半径0.05m, 高0.2m, 质量0.5kg) | 0.0021 | 0.0021 | 0.000625 | 0 |
| 立方体 (0.1×0.1×0.1, 质量0.8kg) | 0.00133 | 0.00133 | 0.00133 | 0 |
↑ 这些是我常用的快速参考值,实际项目里最好根据真实密度计算。
4.4 <geometry> 的四种基本形状
不管 visual、collision 还是 inertial 里的几何,都靠 <geometry> 定义。URDF 原生支持四种:
- <box> —— 长方体,用
size="x y z"指定长宽高。我最常用,简单粗暴。 - <cylinder> —— 圆柱,参数
radius和length。适合轮子、关节连杆。 - <sphere> —— 球体,只需
radius。做万向轮或者装饰球很方便。 - <mesh> —— 网格文件,支持 STL、DAE。用
filename指定路径,还可以用scale缩放。
来看一个完整的 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 或者用简化碰撞体,是仿真调优的第一步。