3. 机器人建模与URDF:从零搭建你的第一个机器人模型
URDF,全称是Unified Robot Description Format。说白了,它就是机器人的「身份证」加「骨架图」。ROS2里所有跟机器人外形、运动学相关的东西——MoveIt规划路径、Nav2做导航、Rviz里显示模型——全都依赖这个文件。
我记得刚入行那会儿,总觉得URDF就是个简单的XML,随便写写就行。结果第一次做六轴机械臂项目,模型在Rviz里关节乱飞,折腾了两天才发现是joint的axis方向写反了。嗯,从那以后我再也不敢小看这个文件了。
3.1 URDF语法核心:link与joint
URDF的结构其实很简单。两个核心元素:link 和 joint。
- link:机器人的刚体部件。比如一个基座、一个连杆、一个轮子。
- joint:连接两个link的关节。定义了它们之间的相对位置和运动方式。
你想想看,一个机器人就是一堆link通过joint串起来的树状结构。根节点通常是 base_link,然后往下分支。
核心原则:每个link只能有一个父joint,但可以有多个子joint。整个URDF必须是一棵树,不能有环。
3.1.1 link的定义
一个典型的link长这样:
<link name="base_link">
<visual>
<geometry>
<box size="0.4 0.3 0.1"/>
</geometry>
<origin xyz="0 0 0" rpy="0 0 0"/>
<material name="blue">
<color rgba="0 0 1 1"/>
</material>
</visual>
<collision>
<geometry>
<box size="0.4 0.3 0.1"/>
</geometry>
</collision>
<inertial>
<mass value="2.0"/>
<inertia ixx="0.01" ixy="0" ixz="0"
iyy="0.01" iyz="0"
izz="0.01"/>
</inertial>
</link>
这里有三块内容:
- visual:显示用的几何形状。Rviz里看到的就是它。
- collision:碰撞检测用的形状。可以比visual简单,提高计算效率。
- inertial:惯性参数。MoveIt做运动规划时必须要有,否则会报错。
我的习惯:collision几何体尽量用box或cylinder代替mesh。我在项目里见过有人直接把高精度的STL文件塞进collision,结果运动规划卡成PPT。简化碰撞模型,性能提升立竿见影。
3.1.2 joint的定义
joint是URDF里最容易出错的地方。来看一个旋转关节的例子:
<joint name="joint1" type="revolute">
<parent link="base_link"/>
<child link="link1"/>
<origin xyz="0 0 0.1" rpy="0 0 0"/>
<axis xyz="0 0 1"/>
<limit lower="-3.14" upper="3.14" effort="10" velocity="1.0"/>
</joint>
joint的type有几种常用类型:
| 类型 | 说明 | 典型用途 |
|---|---|---|
revolute |
旋转关节,有角度限制 | 机械臂关节 |
continuous |
无限旋转关节 | 车轮 |
prismatic |
平移关节 | 伸缩臂、滑轨 |
fixed |
固定连接,无运动 | 传感器支架 |
floating |
6自由度浮动 | 移动机器人基座(不常用) |
这里有个关键点:origin 定义的是child link相对于parent link的位姿。我见过很多新手把坐标搞反,结果模型在Rviz里直接飞出去。
我曾经踩过的坑:axis 向量一定要归一化。如果你写成 xyz="0 0 2",ROS2不会报错,但关节运动会变得很奇怪。排查了整整一下午才发现是这个问题。
3.2 从SolidWorks导出URDF
手写URDF对于简单模型还行。一旦涉及到复杂曲面、多个连杆,手写就是噩梦。这时候就需要从CAD软件导出了。
我个人习惯用SolidWorks + sw_urdf_exporter 插件。流程如下:
- 在SolidWorks里建好装配体。每个零件对应一个link。
- 定义基准轴和坐标系。每个joint的位置要提前设好。
- 运行sw_urdf_exporter插件。选择base_link,然后逐个配置joint。
- 导出。插件会自动生成URDF文件和STL网格文件。
导出后你会得到一个文件夹,结构大概是这样:
my_robot/
├── urdf/
│ └── my_robot.urdf
├── meshes/
│ ├── base_link.STL
│ ├── link1.STL
│ └── link2.STL
├── launch/
│ └── display.launch.py
└── config/
└── joint_names.yaml
避坑指南:导出后一定要检查 origin 和 axis。SolidWorks里的坐标系和ROS里的坐标系可能不一致。我遇到过Z轴方向反了的情况,手动改一下 rpy 就好。
3.3 在Rviz中可视化模型
模型写好了,怎么验证?Rviz就是你的调试利器。
首先,你需要一个launch文件来启动Rviz并加载模型。ROS2里推荐用 robot_state_publisher 节点:
from launch import LaunchDescription
from launch_ros.actions import Node
def generate_launch_description():
return LaunchDescription([
Node(
package='robot_state_publisher',
executable='robot_state_publisher',
name='robot_state_publisher',
output='screen',
arguments=[my_robot.urdf']
),
Node(
package='joint_state_publisher_gui',
executable='joint_state_publisher_gui',
name='joint_state_publisher_gui'
),
Node(
package='rviz2',
executable='rviz2',
name='rviz2'
)
])
启动后,在Rviz里添加 RobotModel 显示项。如果一切正常,你会看到你的机器人模型出现在画面中央。
然后你可以拖动 joint_state_publisher_gui 的滑块,看看关节运动是否正确。
调试技巧:如果模型显示不全,先检查终端有没有报错。常见的错误有:
- STL文件路径不对——用路径先试试
- joint的parent或child名字拼错——URDF是大小写敏感的
- 缺少inertial标签——MoveIt会直接罢工
3.4 知识体系总览
下面这张图概括了本章的核心逻辑:
从CAD到Rviz,每一步都有坑。但只要你掌握了link和joint的定义规则,再配合工具链,整个流程其实很顺畅。
最后提醒一句:URDF文件里不要写中文注释。ROS2的XML解析器在某些版本下会崩溃。我因为这个bug浪费过两个小时,后来全部改成英文注释就没事了。