第2章 · link与joint详解

各位好,我是你们的老朋友。这一章咱们彻底把 link 和 joint 吃透。你想想看,URDF 里最核心的两个东西就是它俩——一个管“身体”,一个管“关节”。搞懂了它们,机器人模型就搭起了一半。

URDF 核心 link 标签 视觉/碰撞/惯性 joint 标签 类型/坐标系/轴 link 是刚体,joint 是约束 → 树形结构

2.1 link 标签——机器人的每一块骨头

link 就是机器人的一个刚体部件。底盘、手臂连杆、摄像头支架……都是 link。每个 link 有且只有一个坐标系,原点默认在 link 的质心位置。我个人习惯把视觉模型和碰撞模型分开定义,这样仿真更稳定。

link 的核心子标签:
  • <visual> —— 外观几何,决定你看到的样子
  • <collision> —— 碰撞检测几何,物理引擎用这个算接触
  • <inertial> —— 质量、惯性张量,动力学仿真必须

举个例子,一个简单的底盘 link 长这样:

<link name="base_link">
    <visual>
        <geometry>
            <box size="0.4 0.3 0.1"/>
        </geometry>
        <material name="blue"/>
    </visual>
    <collision>
        <geometry>
            <box size="0.4 0.3 0.1"/>
        </geometry>
    </collision>
    <inertial>
        <mass value="2.0"/>
        <inertia ixx="0.01" ixy="0" ixz="0" iyy="0.02" iyz="0" izz="0.01"/>
    </inertial>
</link>

嗯,这里要注意:inertia 矩阵必须对称正定,否则 Gazebo 会报错。我曾经在项目里把 ixx 和 iyy 填反了,仿真时底盘原地转圈……排查了半天。

2.2 joint 标签——连接与运动的灵魂

joint 定义了两个 link 之间的约束关系。每个 joint 有且只有一个父 link 和一个子 link,坐标系原点在 joint 的位置。说白了,joint 就是告诉机器人:“这两块零件怎么相对运动”。

joint 类型自由度典型用途
fixed0刚性连接,如摄像头支架
revolute1 (旋转)电机驱动关节,有角度限位
prismatic1 (平移)线性滑台、升降机构
continuous1 (无限旋转)车轮、转台
floating6自由漂浮,无人机/水下机器人
planar3 (平面运动)全向移动底盘简化

你想想看,revolute 和 continuous 的区别就一个——限位。车轮用 continuous,因为没有角度限制;机械臂关节用 revolute,必须设 limit 防止过转。

我的小习惯: 写 joint 时永远先写 parent 和 child,再写 origin 和 axis。顺序乱了容易漏标签。

2.3 坐标系定义——谁在谁的哪里?

URDF 里坐标系全靠 <origin> 和 <axis> 描述。origin 是子 link 坐标系相对于父 link 坐标系的偏移(xyz + rpy)。axis 定义运动轴,只对 revolute、prismatic 等运动关节有效。

<joint name="arm_joint" type="revolute">
    <parent link="base_link"/>
    <child link="arm_link"/>
    <origin xyz="0.2 0 0.1" rpy="0 0 0"/>
    <axis xyz="0 0 1"/>
    <limit lower="-1.57" upper="1.57" effort="10" velocity="1.0"/>
</joint>

这里 xyz="0.2 0 0.1" 表示 arm_link 的原点相对于 base_link 向右 0.2 米、向上 0.1 米。rpy 是欧拉角,按 ZYX 顺序。我记得刚学 URDF 时总搞混 rpy 顺序,后来每次都在纸上画一遍坐标系才放心。

⚠️ 避坑指南: 我曾经在四足机器人项目里把 axis 写成了 0 1 0,但实际关节轴是绕 X 旋转。结果仿真时大腿前后摆动变成了左右劈叉……所以一定要对照真实机械结构确认轴方向。

2.4 树形结构与根 link

URDF 模型必须是一棵树。有且只有一个根 link(没有父 joint),其他 link 都是通过 joint 挂上去的。为什么是树?因为 ROS 的 tf 树就是这么设计的——每个坐标系只有一个父级。

我个人习惯把 base_link 作为根,所有零件都从它开始延伸。如果你需要多个根,那就不是 URDF 了,得用多机器人模型。

快速检查树结构: 用 check_urdf 命令,它会告诉你是否有环、是否有孤立 link。我每次写完模型都会跑一遍,省得后面调试时抓狂。

好,这一章的内容就是这些。link 和 joint 是 URDF 的砖瓦,把它们的属性吃透,后面搭建任何机器人都不会慌。下一章咱们聊几何与可视化,到时候用 STL 和颜色把模型打扮得漂漂亮亮。