前言: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 :机器人的骨骼与零件
Link 代表机器人每一个独立、刚性、不变形的物理部件。
底盘、机壳、大腿、小腿、车轮、雷达、相机、轴承、转轴,只要是真实硬件,在 URDF 中必须定义为 Link。
2.1 Link 三大必备物理属性
完整可仿真的 Link 必须包含三类子标签,分工完全不同:
-
<visual> 可视化模块:仅 RViz 显示用,定义外形、尺寸、颜色,不参与物理计算,可使用精细模型提升观感。
-
<collision> 碰撞模块:Gazebo 仿真碰撞检测专用,工程上一般用简单几何体简化,降低算力消耗。
-
<inertial> 惯性模块:动力学核心,定义质量、惯性矩阵,决定机器人重力、加速、碰撞的物理表现。
2.2 Link 局部 Origin
Link 内部 <origin xyz rpy>:
作用 :几何体相对于自身 Link 坐标系原点的局部偏移。
特点 :只改零件外观位置,不改变机器人全局 TF 坐标树。
2.3 Link 本质总结
Link 是 URDF 中唯一承载物理信息、唯一拥有坐标系的单元,是 TF 坐标树的基石。没有 Link,机器人就没有实体、没有坐标。
三、Joint :只是虚拟,无任何实体
最大误区:新手以为 Joint 是转轴、轴承、机械关节零件。
URDF 中 所有 Joint 全部没有实体。
fixed、revolute、continuous、prismatic、floating,统统都是纯数学约束规则,不是硬件、不会显示、没有质量、没有碰撞。
3.1 Joint 只做两件事
-
坐标绑定:定义 child(子连杆)相对 parent(父连杆)的空间位置姿态;
-
运动约束:限制两个刚体之间允许的运动自由度。
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
<link>内部(visual/collision/inertial)的<origin>:局部偏移 ,参照物是自身link坐标系 ,只调整零件外形在本连杆内部的摆放,不改变TF坐标树。<joint>内部的<origin>:全局装配偏移 ,参照物是父link坐标系 ,直接定义子连杆整体在整机中的安装位置,决定TF坐标变换关系。
5.1 参照物完全不同
- Link内origin
基准 = 当前这个link自带的坐标系原点(xxx_linkframe)。
作用:把几何体盒子/圆柱/网格,挪到该连杆坐标系下指定位置。 - Joint内origin
基准 = joint标签中parent父连杆的坐标系原点。
作用:把整个child子连杆(包含它全部visual/collision/inertial)整体挪到父连杆空间的指定位置。
5.2 影响范围天差地别
Link origin(仅影响外观/碰撞几何,坐标不变)
仅修改当前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 对动力学/传感器的影响
- Link内
<inertial origin>:仅调整刚体质量中心相对link原点的位置,不改变连杆全局安装位; - 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内origin ,laser_link整体向前偏移,所有激光相关TF、点云同步偏移。
场景2:车轮模型看起来和转轴错位
修改wheel link的visual origin,仅修正模型显示,不改动轮子转轴坐标系。
场景3:轮子整体装在车身侧面,距离底盘中心太远
修改continuous joint的origin,整体移动轮子连杆在底盘上的安装点位。
总之,URDF 的设计精髓是虚实分离、刚束分离:实体刚体全部交由 Link 承载,运动与装配约束全部交由 Joint 实现。