4. 机器人URDF模型构建:URDF语法、link与joint定义、xacro优化、可视化检查

好,咱们进入正题。URDF,全称是Unified Robot Description Format,说白了就是机器人的「身份证」。你要让MoveIt认识你的机器人,首先得给它一张清晰的「证件照」——也就是URDF模型。我刚开始接触ROS那会儿,觉得这玩意儿不就是个XML嘛,随便写写就行。结果第一次加载模型,机器人直接在地上劈叉……嗯,从那以后我再也不敢小看URDF了。

核心要点:URDF定义了机器人的运动学树(Kinematic Tree),包括刚体(link)和关节(joint)。MoveIt依赖它来做运动规划、碰撞检测和可视化。

4.1 URDF语法基础

URDF本质上是一个XML文件。它的根元素是<robot>,里面包含两种核心元素:<link>和<joint>。你可以把link想象成机器人的骨头,joint就是连接骨头的关节。

4.1.1 link的定义

一个link至少需要定义视觉(visual)、碰撞(collision)和惯性(inertial)三部分。我见过不少新手只写visual,结果仿真时物理引擎直接报错。为什么?因为没有惯性参数,机器人就像一团空气。

<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>
        <origin xyz="0 0 0" rpy="0 0 0"/>
    </collision>
    <inertial>
        <mass value="2.0"/>
        <inertia ixx="0.01" ixy="0" ixz="0"
                 iyy="0.01" iyz="0"
                 izz="0.02"/>
    </inertial>
</link>

个人经验:惯性矩阵的计算,我建议直接用SolidWorks或Fusion 360导出。手算?别折腾了,我试过一次,算出来的数值和实际差了一个数量级,仿真时机器人抖得像筛糠。

4.1.2 joint的定义

joint定义了link之间的相对运动关系。常见的类型有:fixed(固定)、revolute(旋转)、prismatic(平移)、continuous(连续旋转)。

<joint name="joint1" type="revolute">
    <parent link="base_link"/>
    <child link="arm_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>

这里要注意<origin>和<axis>。origin定义了子link相对于父link的位姿,axis定义了旋转轴。我曾经犯过一个低级错误:把旋转轴写成了xyz="1 0 0",结果机械臂只能左右摆,不能上下抬——你想想看,这还怎么抓东西?

4.2 xacro优化:告别重复劳动

写纯URDF?对于简单机器人还行。但如果你要做一个六轴机械臂,每个link写一遍,每个joint写一遍,光复制粘贴就能让你崩溃。这时候就需要xacro(XML Macros)出场了。

xacro说白了就是给URDF加了个「宏」功能。你可以定义变量、写循环、做数学运算。我个人习惯把所有可变的参数(比如长度、质量、颜色)都抽成xacro属性,这样改参数时只需要改一处。

<?xml version="1.0"?>
<robot xmlns:xacro="http://www.ros.org/wiki/xacro" name="my_robot">

    <xacro:property name="arm_length" value="0.5"/>
    <xacro:property name="arm_mass" value="1.5"/>

    <xacro:macro name="arm_link" params="name length mass color">
        <link name="${name}">
            <visual>
                <geometry>
                    <cylinder length="${length}" radius="0.05"/>
                </geometry>
                <material name="${color}">
                    <color rgba="0 0 1 1"/>
                </material>
            </visual>
            <inertial>
                <mass value="${mass}"/>
                <!-- 惯性矩计算省略 -->
            </inertial>
        </link>
    </xacro:macro>

    <xacro:arm_link name="arm_1" length="${arm_length}" mass="${arm_mass}" color="red"/>
    <xacro:arm_link name="arm_2" length="0.3" mass="1.0" color="blue"/>

</robot>

避坑指南:我曾经在xacro里用了一个未定义的变量,结果模型加载时直接报错,查了半天才发现是拼写错误。建议每次修改xacro后,先用check_urdf命令验证一下。

4.3 可视化检查:眼见为实

模型写完了,怎么知道对不对?别急着跑MoveIt,先用可视化工具看一眼。我推荐两个工具:rviz和urdf_to_graphiz。

4.3.1 使用rviz检查

启动一个空的rviz,添加RobotModel显示插件,然后加载你的URDF文件。如果模型显示正常,恭喜你,至少语法没问题。如果模型缺胳膊少腿,多半是joint的origin定义错了。

4.3.2 使用urdf_to_graphiz生成树状图

这个工具能把URDF转换成一张图,直观展示机器人的运动学树结构。命令很简单:

urdf_to_graphiz my_robot.urdf

它会生成一个PDF文件,里面是树状图。我每次写完新模型都会跑一下这个命令,看看父子关系对不对。有一次我发现一个joint的parent和child写反了,机器人变成了「头朝下」——还好提前发现了。

4.4 本章知识体系

下面这张图总结了URDF模型构建的核心逻辑,你可以把它当作一个快速参考:

URDF模型构建核心流程 URDF 文件 link 定义 joint 定义 xacro 优化 视觉(visual) 碰撞(collision) 惯性(inertial) 类型(type) 父子关系(parent/child) 原点与轴(origin/axis) 宏定义(macro) 属性变量(property) 数学运算 可视化检查 → MoveIt

4.5 常见问题与调试技巧

问题现象 可能原因 解决方法
模型加载后显示不全 joint的origin定义错误,导致link位置偏移 检查<origin>的xyz和rpy值,确保子link在正确位置
关节无法转动 joint类型写成了fixed,或者limit设置不合理 确认type为revolute或continuous,检查limit的lower/upper范围
物理仿真时机器人抖动 惯性参数缺失或数值不合理 补充<inertial>部分,使用CAD工具导出准确数值
xacro文件解析失败 变量未定义或宏调用参数不匹配 使用xacro --check-order检查宏调用顺序

调试小技巧:我习惯在终端里用rosrun tf view_frames查看TF树。如果TF树和你的预期不一致,那肯定是joint的parent/child关系写错了。这个命令能帮你快速定位问题。

好了,URDF模型构建这部分就讲到这里。记住一句话:模型是MoveIt的基石,基础打牢了,后面的导航和规划才能跑得稳。下一节我们会把模型加载到MoveIt中,开始真正的运动规划配置。