URDF模型基础:文件结构、link与joint定义、标准格式与常见错误
URDF,全称是Unified Robot Description Format。说白了,它就是机器人的「身份证」加「骨架图」。你要让MoveIt认识你的机器人,第一步就得把URDF写好。
我记得刚入行那会儿,总觉得URDF就是个简单的XML文件,随便写写就行。结果呢?模型加载出来,机械臂在空中乱飘,关节转反方向……嗯,从那以后我再也不敢小看这个文件了。
核心认知:URDF不是给人类看的说明书,而是给ROS和MoveIt吃的「结构化数据」。格式错一个标签,模型就废了。
2.1 URDF文件整体结构
一个标准的URDF文件,长什么样?我直接给你看个最简框架:
<robot name="my_robot">
<link name="base_link">
<visual>
<geometry>
<box size="0.4 0.4 0.1"/>
</geometry>
</visual>
</link>
<joint name="joint1" type="revolute">
<parent link="base_link"/>
<child link="arm_link"/>
<origin xyz="0 0 0.1" rpy="0 0 0"/>
<axis xyz="0 0 1"/>
</joint>
<link name="arm_link">
<visual>
<geometry>
<cylinder length="0.3" radius="0.05"/>
</geometry>
</visual>
</link>
</robot>
你看,结构其实很清晰:<robot>是根节点,里面交替出现<link>和<joint>。每个link代表一个刚体部件,每个joint描述两个link之间的连接关系。
我个人习惯把URDF想象成一棵「树」:base_link是树根,关节是树枝的分叉点,link是树枝本身。你想想看,如果树根没定义好,整棵树都是歪的。
2.2 link的定义与属性
link代表机器人的一个刚体部件。每个link可以包含三部分:visual(视觉)、collision(碰撞)和inertial(惯性)。
我在项目中遇到过最坑的事:只写了visual,没写collision。结果MoveIt做运动规划时,机械臂直接「穿模」了——因为碰撞检测根本没生效。
| 子标签 | 作用 | 是否必填 | 常见坑点 |
|---|---|---|---|
<visual> |
定义显示用的几何形状 | 推荐 | 原点偏移导致模型显示错位 |
<collision> |
定义碰撞检测用的几何体 | 强烈推荐 | 形状比visual大太多,规划器误判 |
<inertial> |
定义质量、惯性矩阵 | 运动学仿真必填 | 惯性矩阵不填,仿真直接崩 |
我的习惯:visual和collision用完全相同的几何体和原点位置。除非你有特殊需求(比如为了简化碰撞计算),否则保持一致最安全。
来看一个完整的link示例:
<link name="forearm_link">
<visual>
<origin xyz="0 0 0.15" rpy="0 0 0"/>
<geometry>
<cylinder length="0.3" radius="0.04"/>
</geometry>
<material name="blue">
<color rgba="0 0 1 1"/>
</material>
</visual>
<collision>
<origin xyz="0 0 0.15" rpy="0 0 0"/>
<geometry>
<cylinder length="0.3" radius="0.04"/>
</geometry>
</collision>
<inertial>
<mass value="0.5"/>
<inertia ixx="0.001" ixy="0" ixz="0"
iyy="0.001" iyz="0"
izz="0.001"/>
</inertial>
</link>
2.3 joint的定义与类型
joint是URDF的灵魂。它决定了两个link之间怎么动。ROS一共支持6种joint类型,但常用的其实就4种。
| 类型 | 运动方式 | 自由度 | 典型应用 |
|---|---|---|---|
revolute |
绕轴旋转(有限角度) | 1 | 机械臂关节 |
continuous |
绕轴旋转(无限角度) | 1 | 车轮、转台 |
prismatic |
沿轴直线移动 | 1 | 滑轨、升降台 |
fixed |
固定连接,不能动 | 0 | 传感器支架、末端工具 |
floating |
6自由度自由运动 | 6 | 移动机器人基座(少用) |
planar |
平面内2平移+1旋转 | 3 | AGV底盘(少用) |
joint的核心属性有三个:parent、child和origin。origin定义了child link相对于parent link的位姿偏移。这个偏移量一旦写错,整个运动学链就全歪了。
曾经踩过的坑:我写一个六轴机械臂的URDF,第五个关节的origin.rpy写反了符号。结果仿真时机械臂末端轨迹画了个「8」字形,查了整整两天才找到问题。记住:rpy的顺序是绕固定轴X→Y→Z,不是绕自身轴!
2.4 标准格式与命名规范
URDF本身不强制命名规则,但ROS社区有约定俗成的规范。我个人建议你从一开始就遵守:
- link命名:使用小写+下划线,如
base_link、shoulder_link、forearm_link - joint命名:与对应的child link对应,如
shoulder_joint连接shoulder_link - 坐标系:每个link的坐标系原点尽量放在关节轴线上
- 单位:长度用米,角度用弧度,质量用千克
你想想看,如果命名乱七八糟,link_1、jnt_a、part_03混着用,后期调试MoveIt的时候,你根本分不清哪个是哪个。
2.5 常见错误与避坑指南
这部分是我最想跟你分享的。URDF的错误,90%都集中在下面几个地方:
错误排行榜:
- joint的parent/child写反——模型加载后link乱飞
- origin的xyz/rpy算错——关节位置偏移,运动学链断裂
- collision漏写——MoveIt规划时无视障碍物
- inertial缺失——Gazebo仿真直接报错
- axis方向错误——关节转动方向与预期相反
我曾经接手过一个项目,同事写的URDF里,所有joint的parent和child都写反了。结果base_link成了最末端的叶子节点,整个树结构倒过来了。MoveIt加载后,机械臂的末端执行器「长」在了基座上。
调试小技巧:用check_urdf命令检查语法,用urdf_to_graphiz生成结构图。这两个工具能帮你快速定位90%的格式错误。
还有一个容易忽略的点:浮点数精度。URDF里不要写0.0000001这种极小的值,MoveIt的数值求解器可能会因为精度问题卡住。我一般把小于1e-6的值直接写成0。
嗯,URDF的基础就这些。记住一句话:URDF写得越规范,后面MoveIt调得越省心。别图省事跳过collision或inertial,后面补的代价比一开始写好要大得多。