5.1 URDF与xacro机器人建模


5.1 URDF 与 xacro 机器人建模

本节摘要:URDF 是机器人的身体描述格式:连杆是骨骼,关节是连接方式,一份模型文件同时喂给仿真器、可视化工具与运动学库。本节从两个原子概念写出第一个双轮模型,用 xacro 宏消灭复制粘贴,并讲清模型与 TF 树的对应关系——你写的每一行 URDF,最终都会变成第 5.2 节那棵坐标树上的一条边。

模型不是画图,是给机器看的身体描述

很多初学者把建模理解为"画个像样的机器人图",这是方向性偏差。URDF 的读者是程序:仿真器拿它算物理,RViz 拿它做渲染,运动学库拿它求逆解,TF 系统拿它生成静态坐标关系。所以建模的核心不是"像不像",而是尺寸、原点、轴向三要素是否与物理机器人一致——差一厘米,导航就会差一厘米。

一、连杆与关节:两个原子概念

URDF 的世界只有两种对象。link(连杆):一个刚性部件,带视觉外观、碰撞体、惯性三套描述。joint(关节):连接两个连杆,声明连接类型与相对位姿。所有复杂机器人都是这两类对象的组合。

<!-- 一个最小可用的差速底盘模型 --> <robot name="my_bot"> <!-- 本体连杆:盒形,尺寸单位米 --> <link name="base_link"> <visual> <geometry><box size="0.4 0.3 0.12"/></geometry> <origin xyz="0 0 0.06" rpy="0 0 0"/> <material name="blue"><color rgba="0.2 0.4 0.8 1"/></material> </visual> <!-- 碰撞体与惯性:仿真必须,纯可视化可省 --> <collision> <geometry><box size="0.4 0.3 0.12"/></geometry> <origin xyz="0 0 0.06"/> </collision> <inertial> <mass value="5.0"/> <inertia ixx="0.06" ixy="0" ixz="0" iyy="0.09" iyz="0" izz="0.12"/> </inertial> </link> <!-- 驱动轮:绕 Y 轴连续旋转 --> <link name="left_wheel"> <visual> <geometry><cylinder radius="0.06" length="0.03"/></geometry> <origin rpy="1.5708 0 0"/> <material name="dark"><color rgba="0.1 0.1 0.1 1"/></material> </visual> </link> <joint name="left_wheel_joint" type="continuous"> <parent link="base_link"/> <child link="left_wheel"/> <origin xyz="0 0.165 0.06"/> <axis xyz="0 1 0"/> </joint> </robot>

三处新手易错点都在这段里。origin 的 rpy 是弧度不是角度,90 度要写 1.5708——轮子的圆柱默认轴是 Z,要立起来必须绕 X 转 90 度,漏写这一步轮子会"躺平"。joint 的 parent 与 child 方向:URDF 里关节从父连杆指向子连杆,这与第 5.2 节 TF 变换的方向一致,先在建模期养成方向感。inertial 不能省在仿真场景——没有惯性参数的连杆在物理引擎里行为未定义,仿真会静默出错而非报错。

二、xacro:当复制粘贴开始繁殖

真实机器人的轮子有两个、腿有四条、指节有五根,纯 URDF 的复制粘贴会让模型文件膨胀成灾难,更糟的是改一处半径要同步 N 处。xacro 在 URDF 上加了宏、属性与算术,展开后仍是标准 URDF:

<!-- 轮子定义为宏:参数化的复制粘贴终结者 --> <robot name="my_bot" xmlns:xacro="http://www.ros.org/wiki/xacro"> <xacro:property name="wheel_radius" value="0.06"/> <xacro:property name="wheel_sep" value="0.33"/> <xacro:macro name="wheel" params="side offset"> <link name="${side}_wheel"> <visual> <geometry><cylinder radius="${wheel_radius}" length="0.03"/></geometry> <origin rpy="1.5708 0 0"/> </visual> </link> <joint name="${side}_wheel_joint" type="continuous"> <parent link="base_link"/> <child link="${side}_wheel"/> <origin xyz="0 ${offset} ${wheel_radius}"/> <axis xyz="0 1 0"/> </joint> </xacro:macro> <xacro:wheel side="left" offset="0.165"/> <xacro:wheel side="right" offset="-0.165"/> </robot>

左轮右轮现在共享同一个宏定义,轮距与半径各是一处属性。改轮径只动一行,物理一致性由变量保证——这在后期标定环节价值巨大,因为轮径改了之后碰撞体、惯量、运动学全部要联动。展开与检查一步不离两条命令:

# 展开 xacro 成纯 URDF 并检查语法 ros2 run xacro xacro model.urdf.xacro > model.urdf check_urdf model.urdf # 输出机器人结构树与每条关节的父子关系,语法错误在此显形

三、模型与 TF 树、关节状态的接线

模型写完,它在运行期以三种方式活起来,这正是与 5.2 节的接口处。robot_state_publisher 读入 URDF,把所有 fixed 关节发布成 TF 静态变换,把可动关节按编码器读数发布成动态变换——你的模型文件就是这样变成坐标树的。joint_state_publisher 在没有真实硬件时发布关节角度(比如拖 RViz 滑条),让模型在屏幕上动起来。

ros2 run robot_state_publisher robot_state_publisher --ros-args -p robot_description:="$(xacro model.urdf.xacro)" ros2 run joint_state_publisher_gui joint_state_publisher_gui ros2 run rviz2 rviz2 # Fixed Frame 设为 base_link,添加 RobotModel 显示项

⚠️ 常见坑:robot_description 参数通过命令行内嵌 xacro 展开结果时,引号嵌套在 shell 里极易出错——双引号套双引号会被 shell 吃掉一层。更稳的做法是把展开结果写进启动文件,用第 4 章的 Command substitution 机制注入。

图 5-1:从 URDF 文件到运行期 TF 树

图 5-1:从 URDF 文件到运行期 TF 树

本节要点回顾

  • URDF 只有两个原子对象:连杆带三套描述(视觉、碰撞、惯性),关节声明父子与轴向;
  • rpy 是弧度、origin 是关节系下的位姿,这两处是新手建模错误的密集区;
  • xacro 宏与属性消灭复制粘贴,改一处参数全模型联动,标定期价值巨大;
  • robot_state_publisher 是模型到 TF 的桥,fixed 关节成静态变换,可动关节随编码器更新;
  • 建模三要素纪律:尺寸对实物、原点有物理意义、轴向守右手系——模型不准,导航永远差一截。

身体描述好了,下一节让整台机器人(以及它的每个传感器)对"谁在哪"达成持续共识。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U