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 插件。流程如下:

  1. 在SolidWorks里建好装配体。每个零件对应一个link。
  2. 定义基准轴和坐标系。每个joint的位置要提前设好。
  3. 运行sw_urdf_exporter插件。选择base_link,然后逐个配置joint。
  4. 导出。插件会自动生成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 知识体系总览

下面这张图概括了本章的核心逻辑:

URDF建模与可视化流程 CAD模型 / 手写URDF link(刚体 + 视觉/碰撞/惯性) joint(连接 + 类型 + 轴 + 限位) sw_urdf_exporter / robot_state_publisher Rviz2 + joint_state_publisher_gui 可验证的机器人模型 ⚠️ 常见错误 坐标轴反了 / 路径不对

从CAD到Rviz,每一步都有坑。但只要你掌握了link和joint的定义规则,再配合工具链,整个流程其实很顺畅。

最后提醒一句:URDF文件里不要写中文注释。ROS2的XML解析器在某些版本下会崩溃。我因为这个bug浪费过两个小时,后来全部改成英文注释就没事了。