科普:URDF 中的Link与Joint

前言:URDF(Unified Robot Description Format,统一机器人描述格式)是 ROS/ROS2 机器人建模的核心标准,机器人可视化、TF 坐标变换、物理仿真、传感器外参标定全部依赖 URDF 实现。

新手 90% 的建模问题(模型不显示、坐标歪、姿态颠倒、仿真报错、关节不动),根源只有两个:分不清 Link/Joint 虚实关系、RPY 欧拉角旋转规则记忆混乱

关于RPY 欧拉角旋转规则,请参考我之前写的文章:《科普: ROS/URDF 标准 RPY 欧拉角》


一、URDF核心思想:刚体与约束彻底分离

URDF 为了适配标准化坐标变换与动力学仿真,做了现实世界没有的严格拆分:

  • Link = 实体刚体(机器人硬件零件)

  • Joint = 纯虚拟约束(装配规则 + 运动限制)

URDF 铁律:有实体、有外形、有质量的全部是 Link;管连接、管位置、管运动的全部是 Joint。


Link 代表机器人每一个独立、刚性、不变形的物理部件。

底盘、机壳、大腿、小腿、车轮、雷达、相机、轴承、转轴,只要是真实硬件,在 URDF 中必须定义为 Link。

完整可仿真的 Link 必须包含三类子标签,分工完全不同:

  1. <visual> 可视化模块:仅 RViz 显示用,定义外形、尺寸、颜色,不参与物理计算,可使用精细模型提升观感。

  2. <collision> 碰撞模块:Gazebo 仿真碰撞检测专用,工程上一般用简单几何体简化,降低算力消耗。

  3. <inertial> 惯性模块:动力学核心,定义质量、惯性矩阵,决定机器人重力、加速、碰撞的物理表现。

Link 内部 <origin xyz rpy>

作用 :几何体相对于自身 Link 坐标系原点的局部偏移。

特点 :只改零件外观位置,不改变机器人全局 TF 坐标树

Link 是 URDF 中唯一承载物理信息、唯一拥有坐标系的单元,是 TF 坐标树的基石。没有 Link,机器人就没有实体、没有坐标。


三、Joint :只是虚拟,无任何实体

最大误区:新手以为 Joint 是转轴、轴承、机械关节零件。

URDF 中 所有 Joint 全部没有实体

fixed、revolute、continuous、prismatic、floating,统统都是纯数学约束规则,不是硬件、不会显示、没有质量、没有碰撞。

3.1 Joint 只做两件事

  1. 坐标绑定:定义 child(子连杆)相对 parent(父连杆)的空间位置姿态;

  2. 运动约束:限制两个刚体之间允许的运动自由度。

3.2 五种 Joint 类型(仅运动规则不同)

  • fixed 固定关节:锁死相对位置,零自由度,用于雷达、相机、IMU 等静态传感器;

  • revolute 旋转关节:单轴有限角度旋转(带限位),用于机械臂、舵机;

  • continuous 连续关节:单轴 360° 无限旋转,用于驱动车轮;

  • prismatic 平移关节:单轴直线伸缩(带限位),用于升降、伸缩结构;

  • floating 浮动关节:6 自由度全自由,用于无人机、漂浮刚体。

3.3 Joint 全局 Origin

Joint 内的 <origin xyz rpy> 固定定义:

子连杆坐标系 相对于 父连杆坐标系 的平移 + 旋转偏移

这是机器人整体装配位置、传感器外参标定的核心参数,直接决定 TF 坐标变换结果。


四、概念纠偏:现实关节 ≠ URDF Joint

4.1 人体生物关节(膝盖/手肘)

现实人体关节 = 实体零件 + 运动约束 二合一,既是肉体组织,又负责限制骨骼运动。

4.2 机械行业关节(轴承/转轴/合页)

工程师口中的"机器人膝关节、转轴、轴承"都是硬件实物

👉 在 URDF 中:实物轴承、转轴必须单独建 Link,不是 Joint。

4.3 URDF Joint

只是虚拟运动规则,不对应任何物理零件,只约束两个 Link 的相对运动。

4.4 机械腿标准建模示例

真实结构:大腿 --- 轴承转轴 --- 小腿

URDF 建模逻辑:

  • 大腿、小腿、中间轴承 = 三个独立 Link(实体)

  • 大小腿可弯折的规则 = revolute Joint(虚拟约束)

  • 轴承固定在结构上 = fixed Joint(虚拟约束)

一句话:看得见的关节是 Link,管运动的关节是 Joint。

1

五、link内origin 与 joint内origin

  1. <link> 内部(visual/collision/inertial)的 <origin>局部偏移 ,参照物是自身link坐标系 ,只调整零件外形在本连杆内部的摆放,不改变TF坐标树
  2. <joint> 内部的 <origin>全局装配偏移 ,参照物是父link坐标系 ,直接定义子连杆整体在整机中的安装位置,决定TF坐标变换关系

5.1 参照物完全不同

  • Link内origin
    基准 = 当前这个link自带的坐标系原点(xxx_link frame)。
    作用:把几何体盒子/圆柱/网格,挪到该连杆坐标系下指定位置。
  • Joint内origin
    基准 = joint标签中parent父连杆的坐标系原点。
    作用:把整个child子连杆(包含它全部visual/collision/inertial)整体挪到父连杆空间的指定位置。

5.2 影响范围天差地别

仅修改当前link里的3D模型摆放,xxx_link 坐标系原点位置完全不动 ,TF树不会发生任何变化。

举例:车轮link本身坐标系在转轴中心,<visual origin xyz="0 0 -0.05"> 只是把圆柱几何体向下偏移0.05m,wheel_link 坐标系依旧停在转轴位置,雷达、里程计读取的TF坐标不受影响。

Joint origin(改变整机坐标,全局生效)

直接移动整个子连杆坐标系 的全局位置,robot_state_publisher 会根据这个值发布父子frame之间的TF变换,所有传感器、运动学、RViz RobotModel全部依赖该参数。

举例:雷达fixed joint的origin xyz="0.2 0 0.1",会让laser_link整个坐标系出现在底盘前方0.2m、上方0.1m,激光话题的外参、点云坐标全部基于这个偏移计算。

5.3 生效层级区分

  • Link origin:几何体 ↔ 自身连杆(内层局部)
  • Joint origin:子连杆整体 ↔ 父连杆(整机装配外层)

5.4 对动力学/传感器的影响

  1. Link内<inertial origin>:仅调整刚体质量中心相对link原点的位置,不改变连杆全局安装位;
  2. Joint origin:直接改变子连杆在整机空间的挂载点位,IMU、激光、相机等传感器的外参完全由joint origin决定。

5.5 代码示例

link内部origin(局部几何体偏移)
xml 复制代码
<link name="wheel_link">
  <!-- 圆柱几何体相对wheel_link坐标系,Z向下偏移0.05m -->
  <visual>
    <origin xyz="0 0 -0.05" rpy="1.5708 0 0"/>
    <geometry><cylinder radius="0.08" length="0.1"/></geometry>
  </visual>
</link>

解读:wheel_link坐标系原点不变,只是轮子圆柱往下挪一点,TF坐标不受影响。

joint内部origin(全局装配偏移)
xml 复制代码
<joint name="wheel_joint" type="continuous">
  <parent link="base_link"/>
  <child link="wheel_link"/>
  <!-- 整个wheel_link坐标系,在base_link前方0.18m、左侧0.2m处 -->
  <origin xyz="0.18 0.2 0" rpy="0 0 0"/>
  <axis xyz="0 1 0"/>
</joint>

解读:底盘base_link的坐标系为基准,把完整wheel连杆 整体安装到车身左前方,TF树会生成base_link → wheel_link的坐标变换。

5.6 高频易错场景区分

场景1:想调整雷达外壳造型位置

修改 link内visual origin ,雷达laser_link坐标系保持不动,不影响激光点云坐标。

场景2:想把整个雷达支架往前挪一点

修改 fixed joint内originlaser_link整体向前偏移,所有激光相关TF、点云同步偏移。

场景2:车轮模型看起来和转轴错位

修改wheel link的visual origin,仅修正模型显示,不改动轮子转轴坐标系。

场景3:轮子整体装在车身侧面,距离底盘中心太远

修改continuous joint的origin,整体移动轮子连杆在底盘上的安装点位。

总之,URDF 的设计精髓是虚实分离、刚束分离:实体刚体全部交由 Link 承载,运动与装配约束全部交由 Joint 实现。