4. URDF建模:机械臂URDF模型创建、可视化与验证
URDF(Unified Robot Description Format,统一机器人描述格式)是ROS2中描述机器人几何结构、关节类型与运动学属性的标准XML格式。对于机械臂而言,URDF不仅是可视化与仿真(RViz、Gazebo)的基础,更是后续运动学求解、碰撞检测与轨迹规划的数据源头。本节将围绕一个六自由度关节型机械臂,讲解URDF的完整创建流程、可视化方法以及验证手段。
4.1 核心原理:URDF的树形结构与关键标签
URDF将机械臂抽象为一棵运动学树:由<link>(刚体杆件)和<joint>(连接杆件的运动副)交替组成。每个link有且仅有一个父joint,但可以拥有多个子joint,从而形成严格的层级关系。机械臂的基座(base_link)是树的根节点,末端执行器(如tool0)是叶子节点。
理解URDF需要抓住三个核心标签:
- <link>:描述杆件的惯性属性(
<inertial>)、视觉几何(<visual>)与碰撞几何(<collision>)。视觉模型用于显示,碰撞模型用于物理仿真,两者可以不同(碰撞模型通常更简化)。 - <joint>:定义父link与子link之间的运动关系。机械臂中常用
revolute(旋转关节,有角度限位)和continuous(无限旋转关节)。必须指定origin(关节在父link坐标系中的位姿)和axis(旋转轴,在关节坐标系中定义)。 - <material>:为视觉几何指定颜色或纹理,便于在RViz中区分不同杆件。
下面是一个典型的关节定义片段,展示了旋转关节的完整写法:
<joint name="shoulder_pan_joint" type="revolute">
<parent link="base_link"/>
<child link="shoulder_link"/>
<origin xyz="0 0 0.15" rpy="0 0 0"/>
<axis xyz="0 0 1"/>
<limit lower="-3.14" upper="3.14" effort="150" velocity="3.2"/>
</joint>
其中origin的xyz表示关节坐标系原点在父link坐标系中的位置,rpy表示旋转(固定轴欧拉角)。axis的xyz是关节的旋转轴方向向量,必须在关节坐标系中归一化。限位参数lower/upper的单位是弧度,effort是最大力矩(N·m),velocity是最大速度(rad/s)。
4.2 方法流程:从零构建六轴机械臂URDF
我们以一款典型的六自由度串联机械臂为例(结构类似UR5e),其关节配置为:肩部偏航(shoulder_pan)、肩部俯仰(shoulder_lift)、肘部俯仰(elbow)、前臂旋转(wrist_1)、腕部俯仰(wrist_2)、腕部翻转(wrist_3)。创建URDF的推荐流程如下:
- 确定运动学链与DH参数:先画出机械臂的关节-连杆简图,标注每个关节的旋转轴方向、连杆长度和偏置。这是URDF中
origin和axis的数据来源。 - 创建包结构与基础文件:使用
ros2 pkg create创建功能包,在urdf/目录下新建arm.urdf文件。 - 编写base_link与第一个关节:从基座开始,逐级向下编写。每个link的视觉几何尽量使用简单的box/cylinder/mesh组合,便于调试。
- 逐级添加后续link与joint:注意每个joint的parent必须是已定义的link,child是新link。保持树形结构不交叉。
- 添加末端执行器坐标系:在最后一个关节后添加
tool0link,用于后续运动学解算与工具坐标标定。
下面给出一个简化的URDF骨架(省略了部分视觉几何细节),展示树形结构的写法:
<robot name="six_axis_arm">
<link name="base_link">
<visual>
<geometry><box size="0.2 0.2 0.1"/></geometry>
<material name="base_mat"/>
</visual>
</link>
<joint name="shoulder_pan_joint" type="revolute">
<parent link="base_link"/>
<child link="shoulder_link"/>
<origin xyz="0 0 0.1" rpy="0 0 0"/>
<axis xyz="0 0 1"/>
<limit lower="-3.14" upper="3.14" effort="150" velocity="3.2"/>
</joint>
<link name="shoulder_link">
<visual>
<geometry><cylinder radius="0.05" length="0.3"/></geometry>
<origin xyz="0 0 0.15" rpy="1.5708 0 0"/>
</visual>
</link>
<!-- 后续关节依次类推 -->
<joint name="shoulder_lift_joint" type="revolute">
<parent link="shoulder_link"/>
<child link="upper_arm_link"/>
<origin xyz="0 0 0.3" rpy="0 0 0"/>
<axis xyz="0 1 0"/>
<limit lower="-2.0" upper="2.0" effort="150" velocity="3.2"/>
</joint>
<!-- ... 其余关节 -->
</robot>
注意:shoulder_link的视觉圆柱体绕x轴旋转了90°(rpy="1.5708 0 0"),这是因为圆柱体默认轴向是z轴,而我们需要它水平放置。这种坐标变换是URDF建模中最容易出错的地方。
4.3 可视化与验证:RViz与check_urdf
完成URDF编写后,必须经过两步验证:静态语法检查和动态可视化检查。
第一步:使用check_urdf工具。该工具会解析URDF文件并输出运动学树结构,同时报告缺失的标签或错误的坐标系引用。
# 安装工具(若未安装)
sudo apt install liburdfdom-tools
# 检查URDF文件
check_urdf arm.urdf
正常输出会显示类似如下的树形结构:
robot name is: six_axis_arm
---------- Successfully Parsed XML ---------------
root Link: base_link has 1 child(ren)
child(1): shoulder_link
child(1): upper_arm_link
child(1): forearm_link
child(1): wrist1_link
child(1): wrist2_link
child(1): wrist3_link
child(1): tool0
如果输出中出现ERROR: Joint ... is not connected to the tree或No default value specified for joint ...,说明树形结构断裂或缺少必要属性,需要返回修改。
第二步:在RViz中可视化。需要先启动一个robot_state_publisher节点,它会读取URDF并发布各link坐标系之间的TF变换。创建launch文件或直接命令行运行:
# 启动robot_state_publisher(假设URDF路径为~/arm_ws/src/arm_description/urdf/arm.urdf)
ros2 run robot_state_publisher robot_state_publisher --ros-args -p robot_description:="$(cat ~/arm_ws/src/arm_description/urdf/arm.urdf)"
# 另开终端启动RViz
ros2 run rviz2 rviz2
在RViz中,将Fixed Frame设置为base_link,添加RobotModel显示组件,即可看到机械臂的三维模型。此时可以拖动关节滑块(通过joint_state_publisher发布关节角度)来验证每个关节的运动方向是否符合预期。
robot_description参数未正确加载,或URDF中引用了不存在的mesh文件。如果模型出现但关节运动方向相反,说明axis方向定义错误——例如绕y轴正方向旋转时,实际关节向负方向运动,需要将axis改为0 -1 0。
4.4 案例:为六轴机械臂添加碰撞模型与惯性参数
在实际工程中,仅有视觉模型是不够的。Gazebo仿真和运动规划(MoveIt)需要碰撞模型和惯性参数。碰撞模型应尽量简化,以降低碰撞检测计算量。惯性参数可以通过CAD软件计算,或使用近似估算。
以下是为upper_arm_link添加碰撞模型和惯性属性的示例:
<link name="upper_arm_link">
<!-- 视觉模型 -->
<visual>
<geometry><box size="0.08 0.08 0.4"/></geometry>
<origin xyz="0 0 0.2" rpy="0 0 0"/>
</visual>
<!-- 碰撞模型:使用更简单的圆柱体 -->
<collision>
<geometry><cylinder radius="0.06" length="0.4"/></geometry>
<origin xyz="0 0 0.2" rpy="0 0 0"/>
</collision>
<!-- 惯性参数:质量、质心位置、惯性张量 -->
<inertial>
<mass value="4.5"/>
<origin xyz="0 0 0.2" rpy="0 0 0"/>
<inertia ixx="0.05" ixy="0.0" ixz="0.0"
iyy="0.05" iyz="0.0"
izz="0.01"/>
</inertial>
</link>
惯性张量矩阵必须是对称正定的,且数值要合理。对于细长杆件,绕长度方向的转动惯量(izz)通常远小于绕垂直方向的转动惯量(ixx、iyy)。如果数值不合理,Gazebo仿真会出现抖动或发散。
4.5 误区与复盘:URDF建模中的典型陷阱
| 误区 | 现象 | 正确做法 |
|---|---|---|
| 关节origin的rpy设置错误 | 模型在RViz中扭曲,相邻link错位 | 牢记rpy是关节坐标系相对于父link坐标系的旋转,按Z-Y-X固定轴顺序理解 |
| axis方向未归一化 | check_urdf不报错,但运动学计算异常 | axis向量长度必须为1,如xyz="0 0 1" |
| 视觉几何与碰撞几何共用同一坐标系 | 碰撞检测不准确或仿真穿透 | 碰撞几何的origin应相对于link坐标系,而非视觉几何坐标系 |
忘记添加<material>定义 |
RViz中模型全白,难以区分关节 | 在<robot>根标签下定义material,并在visual中引用 |
| 惯性参数随意填写 | Gazebo仿真中机械臂剧烈抖动 | 使用CAD软件测量或参考相似规格机械臂的参数 |
复盘建议:在完成URDF编写后,不要急于进入下一步。建议在RViz中手动旋转每个关节,逐一确认:①关节旋转方向与预期一致;②相邻link之间没有错位或穿透;③极限位置(joint limit)是否合理。这一过程虽然耗时,但能避免后续在MoveIt配置或实机调试中花费数倍时间排查问题。
- check_urdf输出无ERROR,树形结构完整
- RViz中模型显示正常,无红色警告
- 每个关节在极限范围内运动时,link之间无干涉
- TF树中所有坐标系均正确发布,无缺失
- 碰撞模型与视觉模型大致吻合,无严重穿透
URDF建模是机械臂控制的基础工程,它直接决定了后续运动学解算、轨迹规划与仿真的准确性。通过本节的学习,你已经掌握了从零构建URDF、使用check_urdf和RViz进行验证的方法,并了解了碰撞模型与惯性参数的重要性。在实际项目中,建议将URDF文件纳入版本管理,并配合xacro宏定义来减少重复代码,提高模型的可维护性。