第二章:机器人URDF模型基础

URDF,全称是Unified Robot Description Format。说白了,它就是机器人的“身份证”和“骨架说明书”。没有它,MoveIt根本不知道你的机器人长什么样、胳膊往哪转。

我个人习惯,拿到一个新机器人,第一件事就是看它的URDF文件。这比看图纸还直观。你想想看,一个几百行的XML文件,就能描述一个复杂的机械臂,是不是很神奇?

URDF文件结构

URDF本质上是一个XML文件。它的根节点是<robot>,里面包含两大核心元素:<link>和<joint>。

我刚开始学的时候,总把link和joint搞混。后来我总结了一句话:link是骨头,joint是关节。骨头不会动,关节负责连接骨头并让它们动起来。

核心原则:一个完整的机器人模型,必须至少有一个base_link作为根,然后通过joint串联起所有link。

来看一个最简单的URDF骨架:

<robot name="my_robot">
    <link name="base_link">
        <visual>
            <geometry>
                <box size="0.2 0.2 0.1"/>
            </geometry>
        </visual>
    </link>

    <joint name="joint1" type="revolute">
        <parent link="base_link"/>
        <child link="arm_link"/>
        <origin xyz="0 0 0.05" rpy="0 0 0"/>
        <axis xyz="0 0 1"/>
    </joint>
</robot>

嗯,这里要注意:origin定义的是子link相对于父link的位置和姿态。我曾经在这里栽过跟头,坐标写反了,结果模型在RViz里直接飞出去了。

link与joint的详细定义

link:机器人的“骨头”

每个link可以包含三个部分:

  • visual:可视化用的几何形状,不影响物理碰撞
  • collision:碰撞检测用的形状,越简单越好
  • inertial:惯性参数,包括质量、惯性矩阵

我的经验:collision几何体尽量用简单的形状(盒子、圆柱、球体)。复杂的mesh虽然好看,但会让碰撞检测变得很慢。我在做AGV项目时,把轮子的collision从mesh改成了圆柱体,性能提升了3倍。

joint:机器人的“关节”

joint的类型决定了机器人的运动方式:

类型 说明 自由度
revolute 旋转关节,有角度限制 1
continuous 连续旋转关节,无限制 1
prismatic 平移关节 1
fixed 固定连接,不能动 0
floating 6自由度浮动关节 6

为什么会有fixed关节?说白了,有些零件虽然物理上是分开的,但为了建模方便,我们把它拆成两个link,然后用fixed关节焊死。我在做协作机器人时,把末端执行器拆成了三个link,用fixed关节连接,这样更换夹爪时只需要改一个link就行。

坐标系与变换

URDF里最让人头疼的就是坐标系。每个link都有自己的坐标系,joint的origin定义了父子link之间的变换关系。

记住这个原则:子link的坐标系原点,是在父link坐标系下描述的。

举个例子:

<joint name="shoulder" type="revolute">
    <parent link="base_link"/>
    <child link="upper_arm"/>
    <origin xyz="0 0 0.3" rpy="0 0 0"/>
    <axis xyz="0 0 1"/>
</joint>

这表示:upper_arm的坐标系原点,在base_link坐标系下是(0, 0, 0.3)的位置。旋转顺序是RPY(Roll-Pitch-Yaw),也就是绕X、Y、Z轴依次旋转。

避坑指南:我曾经在定义关节时,把rpy写成了0 0 90(度),但URDF里用的是弧度!结果模型在RViz里歪了90度,找了半天才发现是单位问题。记住:URDF里角度一律用弧度。

使用SolidWorks导出URDF

手动写URDF太累了,尤其是复杂机器人。我推荐用SolidWorks的SW2URDF插件。流程很简单:

  1. 在SolidWorks里建好装配体
  2. 安装SW2URDF插件
  3. 为每个零件定义坐标系和关节轴
  4. 导出URDF和mesh文件

导出后你会得到:一个.urdf文件,一个meshes文件夹(里面是STL文件),以及一个launch文件夹。

嗯,这里有个坑:SW2URDF导出的坐标系可能不符合ROS的惯例(Z轴向上)。我一般会在导出后手动检查一下origin的数值,尤其是rpy部分。

在RViz中可视化模型

有了URDF,我们就能在RViz里看到机器人了。用display.launch文件启动:

<launch>
    <param name="robot_description" textfile="$(find my_robot)/urdf/my_robot.urdf"/>
    <node name="robot_state_publisher" pkg="robot_state_publisher" type="robot_state_publisher"/>
    <node name="joint_state_publisher" pkg="joint_state_publisher" type="joint_state_publisher"/>
    <node name="rviz" pkg="rviz" type="rviz" args="-d $(find my_robot)/config/display.rviz"/>
</launch>

启动后,你会看到:

  • 机器人模型显示在RViz中
  • 可以通过滑动条调节关节角度
  • 坐标系显示为红绿蓝三色箭头

如果模型显示不出来,八成是robot_description参数没加载成功。用rosparam get /robot_description检查一下。

调试技巧:在RViz里添加TF显示,可以看到每个link的坐标系。如果某个link的坐标系位置不对,那肯定是joint的origin定义错了。我排查URDF问题时,90%的情况都是靠看TF坐标系找到的。

知识体系结构图

下面这张图总结了URDF的核心知识脉络,我建议你保存下来,写URDF时对照着看:

URDF 模型 文件结构 <robot> 根节点 <link> + <joint> 核心 link 定义 visual / collision / inertial 几何体:box/cylinder/sphere/mesh joint 定义 类型:revolute/prismatic/fixed origin + axis + limit 坐标系与变换 父子link坐标变换 origin xyz + rpy 工具与可视化 SolidWorks + SW2URDF RViz + robot_state_publisher 常见避坑 角度单位:弧度 vs 度 坐标系方向:Z轴向上

这张图把URDF的核心知识点串起来了。你写URDF时,从上到下、从左到右过一遍,基本不会漏掉什么。

好了,URDF的基础就这些。说白了,它就是一套描述机器人“骨头”和“关节”的规则。掌握了这些,你就能让机器人在RViz里动起来了。