2、URDF基础回顾:文件结构、link与joint、坐标系与变换树
URDF,全称是 Unified Robot Description Format。说白了,它就是用来描述机器人长什么样、关节怎么动的一套 XML 语法。我刚开始接触机器人时,觉得这玩意儿就是个“零件清单”,后来踩了不少坑才明白——它其实是整个机器人系统的“骨架”和“神经”。
这一章,我们快速过一遍 URDF 的核心概念。如果你已经熟悉,可以当复习;如果你是新手,我建议你跟着代码敲一遍。
2.1 URDF 文件结构:从根到叶
一个标准的 URDF 文件,结构其实很清晰。它就像一棵树,根节点是 <robot>,下面挂着 <link> 和 <joint>。我习惯把 link 想象成“骨头”,joint 想象成“关节”。
<robot name="my_robot">
<link name="base_link">
<visual>
<geometry>
<box size="0.4 0.3 0.1"/>
</geometry>
</visual>
</link>
<joint name="base_to_arm" type="fixed">
<parent link="base_link"/>
<child link="arm_link"/>
<origin xyz="0 0 0.15" rpy="0 0 0"/>
</joint>
<link name="arm_link">
<visual>
<geometry>
<cylinder length="0.3" radius="0.05"/>
</geometry>
</visual>
</link>
</robot>
你看,结构就这么简单。但要注意,每个 link 必须有唯一的 name,joint 也一样。我曾经在项目里因为两个 link 重名,Gazebo 直接崩溃,查了半天才发现是命名冲突。
left_wheel_link、arm_joint_1。这样后期维护时,一眼就能看出是哪个零件。
2.2 link 与 joint 的定义
2.2.1 link:机器人的“骨头”
link 描述的是刚体部分。它有三个主要子标签:visual(视觉)、collision(碰撞)、inertial(惯性)。
| 标签 | 作用 | 必填? |
|---|---|---|
visual |
定义外观,用于 Rviz 显示 | 推荐有 |
collision |
定义碰撞模型,用于物理引擎 | 推荐有 |
inertial |
定义质量、惯性矩阵 | 运动学仿真可选,动力学必填 |
嗯,这里要注意:visual 和 collision 可以不一样。比如一个复杂的机械臂,visual 用精细的 STL 模型,collision 用简单的圆柱体或长方体。这样显示好看,碰撞计算又快。
2.2.2 joint:机器人的“关节”
joint 连接两个 link,并定义它们之间的相对运动。URDF 支持 6 种 joint 类型:
| 类型 | 自由度 | 典型用途 |
|---|---|---|
fixed |
0 | 固定连接,比如底座与支架 |
revolute |
1(旋转) | 电机驱动的旋转关节,有角度限制 |
continuous |
1(旋转) | 无限制旋转,比如车轮 |
prismatic |
1(平移) | 直线滑动关节,比如伸缩臂 |
floating |
6 | 完全自由,常用于移动机器人底盘 |
planar |
3(平面运动) | 在平面上移动,比如 AGV |
joint 里最重要的三个子标签:parent、child、origin。parent 是上一级 link,child 是下一级 link。origin 定义了 child link 相对于 parent link 的位置和姿态。
<joint name="arm_joint" type="revolute">
<parent link="base_link"/>
<child link="arm_link"/>
<origin xyz="0.1 0 0.2" rpy="0 0 0"/>
<axis xyz="0 0 1"/>
<limit lower="-1.57" upper="1.57" effort="10" velocity="1.0"/>
</joint>
你看,axis 定义了旋转轴方向,limit 限制了角度范围。我建议你每次写完 joint,都手动算一下 origin 的坐标,别完全依赖可视化工具——有时候工具会骗人。
2.3 坐标系与变换树
URDF 里每个 link 都有自己的坐标系。这些坐标系通过 joint 连接起来,就形成了一棵“变换树”(Transform Tree)。
为什么会这样?因为机器人运动时,每个关节的角度变化,都会影响后续所有 link 的位置。变换树就是用来追踪这种“连锁反应”的。
origin 来调整相对位置。记住,子 link 的坐标是相对于父 link 的。
举个例子:一个两轮差速机器人,base_link 在底盘中心,左轮 left_wheel_link 的 origin 是 xyz="0 0.2 0",意思是左轮中心在 base_link 的 Y 轴正方向 0.2 米处。
嗯,这里要特别提醒:变换树必须是树状结构,不能有环。也就是说,一个 link 只能有一个父 link,不能有两个。我在做多机器人协同抓取时,曾经试图让两个机械臂共享一个末端执行器,结果 TF 树直接报错——因为一个 link 不能有两个爹。
2.4 标准标签详解
除了上面提到的,还有几个标签你一定会用到:
<geometry>:支持 box、cylinder、sphere、mesh。mesh 可以加载 STL 或 DAE 文件。<material>:定义颜色或纹理。比如<color rgba="1 0 0 1"/>就是红色。<inertial>:包含<mass>和<inertia>。惯性矩阵ixx、iyy、izz等,如果不知道怎么算,可以用 SolidWorks 或 Fusion 360 导出。<transmission>:定义关节与执行器之间的传动关系,用于 Gazebo 仿真。
2.5 知识体系总览
下面这张图,帮你把本章的核心逻辑串起来:
这张图把 URDF 的三大核心——link、joint、变换树——以及它们各自的子标签都串起来了。你写 URDF 时,就按这个结构来组织代码,不会乱。
2.6 避坑指南
最后,分享几个我实际项目中遇到的坑:
- 坐标系方向搞反:有一次我把
rpy="1.57 0 0"写成了rpy="0 1.57 0",结果机械臂在 Rviz 里直接“拧麻花”。建议用tf2_echo工具实时查看坐标变换。 - 惯性参数乱填:动力学仿真时,如果惯性矩阵填错,机器人会“飘”起来。我一般用 CAD 软件导出,或者用
urdf_sim_tutorial里的估算脚本。 - joint 类型选错:车轮应该用
continuous,结果我用了revolute,导致车轮只能转 180 度。嗯,这种低级错误,犯过一次就记住了。
fixed joint 加虚拟 link 来近似。