3. URDF与机器人建模:使用URDF描述机械臂与AGV底盘、xacro宏定义、在Rviz2中可视化模型

好,咱们进入第三章。这一章我打算聊聊机器人建模,也就是怎么用URDF把机械臂和AGV底盘“画”出来。你可能会觉得,建模不就是写点XML嘛,有啥好讲的?嗯,我刚开始也这么想,直到我在一个项目里,因为一个坐标轴写反了,整个机械臂在Rviz里拧成了麻花……那场面,真是哭笑不得。

说白了,URDF就是机器人的“骨架描述文件”。它告诉ROS2你的机器人长什么样,关节在哪,能怎么动。咱们这一章,就把它彻底搞明白。

3.1 URDF基础:link和joint

URDF的核心就两个东西:link和joint。link是刚体部件,比如底盘、连杆、末端执行器。joint是连接两个link的关节,定义了它们之间的相对运动关系。

我习惯把link想象成骨头,joint想象成关节。骨头本身不会动,是关节让骨头动起来的。这个类比很直观,你想想看。

一个最简单的link定义长这样:

<link name="base_link">
  <visual>
    <geometry>
      <box size="0.5 0.3 0.1"/>
    </geometry>
    <material name="blue">
      <color rgba="0 0 1 1"/>
    </material>
  </visual>
</link>

这里我定义了一个叫base_link的底盘,形状是个长方体,涂成蓝色。注意,visual标签只负责显示,不影响碰撞检测。如果你要做物理仿真,还得加一个collision标签,内容通常和visual一样。

joint的定义稍微复杂一点:

<joint name="arm_joint" type="fixed">
  <parent link="base_link"/>
  <child link="arm_link"/>
  <origin xyz="0.2 0 0.1" rpy="0 0 0"/>
</joint>

这个joint把arm_link固定在base_link上,偏移了(0.2, 0, 0.1)米。注意rpy是欧拉角,顺序是绕X、Y、Z轴旋转。我在项目中吃过亏,rpy的顺序千万别搞错,否则模型会歪得你怀疑人生。

注意: URDF中所有坐标都是相对于父link的。写错坐标系,模型就会“飘”到天上去。我曾经调试一个AGV,底盘和激光雷达死活对不上,最后发现是joint的origin写反了符号。

3.2 用xacro简化模型描述

写URDF最痛苦的是什么?重复劳动。一个六轴机械臂,六个link、六个joint,每个都得写一遍。而且如果你要改尺寸,得挨个改。这时候,xacro就派上用场了。

xacro是URDF的宏扩展工具。你可以定义变量、写宏、做数学运算。说白了,就是给URDF加上了编程能力。

举个例子,定义一个通用的连杆宏:

<xacro:macro name="link_box" params="name length width height color">
  <link name="${name}">
    <visual>
      <geometry>
        <box size="${length} ${width} ${height}"/>
      </geometry>
      <material name="${color}">
        <color rgba="0 0 1 1"/>
      </material>
    </visual>
  </link>
</xacro:macro>

然后你只需要一行就能生成一个link:

<xacro:link_box name="arm_link_1" length="0.1" width="0.05" height="0.3" color="red"/>

是不是清爽多了?我个人习惯把机械臂的每个连杆长度、关节限位都定义成xacro变量,放在一个单独的config.xacro文件里。这样改参数时,只需要改一个地方,所有地方自动更新。

小技巧: 用xacro的数学运算功能,可以自动计算关节位置。比如根据连杆长度和角度,算出下一个关节的坐标。这样你就不用手动算每个joint的origin了,省心不少。

3.3 机械臂与AGV底盘的联合建模

咱们这个课程的主题是“协同”,所以机械臂和AGV底盘得放在一个URDF里。怎么做?很简单,把AGV底盘作为根link,机械臂作为子link挂上去。

我一般这样组织文件结构:

  • robot.urdf.xacro:主文件,包含所有部件
  • chassis.urdf.xacro:AGV底盘定义
  • arm.urdf.xacro:机械臂定义
  • sensors.urdf.xacro:激光雷达、相机等传感器
  • config.xacro:全局参数

主文件里用<xacro:include>把其他文件包含进来:

<?xml version="1.0"?>
<robot name="mobile_manipulator" xmlns:xacro="http://www.ros.org/wiki/xacro">
  <xacro:include file="$(find my_robot_description)/urdf/config.xacro"/>
  <xacro:include file="$(find my_robot_description)/urdf/chassis.urdf.xacro"/>
  <xacro:include file="$(find my_robot_description)/urdf/arm.urdf.xacro"/>
  <xacro:include file="$(find my_robot_description)/urdf/sensors.urdf.xacro"/>
</robot>

这里要注意,包含顺序很重要。先定义底盘,再定义机械臂,因为机械臂的joint要引用底盘的link。如果顺序反了,xacro会报错说找不到父link。

机械臂和底盘的连接,用一个固定joint:

<joint name="base_to_arm" type="fixed">
  <parent link="chassis_link"/>
  <child link="arm_base_link"/>
  <origin xyz="${arm_mount_x} ${arm_mount_y} ${arm_mount_z}" rpy="0 0 0"/>
</joint>

这样,机械臂就稳稳地站在AGV底盘上了。嗯,这里要注意,arm_mount_x这些变量要在config.xacro里定义好,方便后期调整安装位置。

3.4 在Rviz2中可视化模型

模型写好了,怎么验证?当然是放到Rviz2里看看。Rviz2是ROS2的3D可视化工具,能实时显示机器人模型、传感器数据、路径规划结果等。

首先,你得有一个launch文件来启动显示。我常用的launch文件长这样:

import launch
from launch_ros.actions import Node

def generate_launch_description():
    return launch.LaunchDescription([
        Node(
            package='robot_state_publisher',
            executable='robot_state_publisher',
            name='robot_state_publisher',
            output='screen',
            parameters=[{'robot_description': open('robot.urdf.xacro').read()}]
        ),
        Node(
            package='joint_state_publisher_gui',
            executable='joint_state_publisher_gui',
            name='joint_state_publisher_gui',
            output='screen'
        ),
        Node(
            package='rviz2',
            executable='rviz2',
            name='rviz2',
            output='screen'
        )
    ])

这个launch文件启动了三个节点:

  • robot_state_publisher:读取URDF,发布TF变换和机器人模型
  • joint_state_publisher_gui:提供一个滑块界面,让你手动调节关节角度
  • rviz2:可视化界面

启动后,在Rviz2中添加RobotModel显示,选择/robot_description话题,你的机器人就出现了。如果一切正常,你应该能看到AGV底盘上站着一个机械臂。

避坑指南: 我曾经在Rviz里看不到模型,折腾了半天才发现是robot_state_publisher没有正确加载URDF。检查一下launch文件里robot_description参数的路径是否正确。另外,确保你的URDF文件没有语法错误,可以用check_urdf命令检查。

在Rviz2中,你还可以添加TF显示,看看各个坐标系之间的关系是否正确。如果某个link的坐标系飘到了奇怪的地方,那多半是joint的origin写错了。

3.5 本章知识体系

为了让你更直观地理解本章内容,我画了一张流程图,展示URDF建模到Rviz可视化的完整链路:

URDF建模与Rviz可视化流程 定义link 几何、材质、碰撞 定义joint 类型、父子link、原点 xacro宏封装 变量、宏、数学运算 URDF robot_state_publisher 发布TF和模型话题 Rviz2可视化 添加RobotModel、TF显示 图:从link/joint定义到Rviz可视化的完整流程

这张图展示了从定义link和joint,到用xacro封装,再到生成URDF,最后通过robot_state_publisher在Rviz2中可视化的完整链路。每一步都环环相扣,缺一不可。

好了,这一章的内容就到这里。URDF建模是机器人开发的基础,看似简单,但细节很多。我建议你动手写一个自己的URDF,哪怕只是一个底盘加一个连杆,然后在Rviz里看看效果。只有亲手踩过坑,才能真正记住。

可可精品资料库