【ROS 2 学习记录】拒绝“幽灵车”!给机器人赋予物理属性并导入 Gazebo 仿真

一、 为什么要进 Gazebo?

在 Rviz 里,机器人是可以穿墙的,悬空的,因为它不受物理定律约束。

但在 Gazebo 里,有重力、有摩擦力、有碰撞。如果我的机器人没有“质量”(Mass)或者“碰撞体积”(Collision),它要么会掉进地心,要么会被物理引擎直接删除。

为了让机器人“活”过来,我主要做了两件事:

  1. Xacro 升级:添加 Inertial(惯性)和 Collision(碰撞)属性。
  2. Launch 编写:编写 Python 脚本把机器人“生”在 Gazebo 里。

二、 详细开发过程

1. 准备“物理作弊小抄” (Inertial Macros)

给轮子算转动惯量太难了(要背微积分公式),所以我利用 Xacro 的宏定义功能,封装了球体、圆柱、方块的惯性计算公式。

.xacro 文件头部添加宏定义:

XML

 <xacro:macro name="inertial_sphere" params="mass radius"> <inertial> <mass value="${mass}"/> <inertia ixx="${(2/5) * mass * (radius*radius)}" ixy="0.0" ixz="0.0" iyy="${(2/5) * mass * (radius*radius)}" iyz="0.0" izz="${(2/5) * mass * (radius*radius)}"/> </inertial> </xacro:macro> <xacro:macro name="inertial_cylinder" params="mass length radius"> <inertial> <mass value="${mass}"/> <inertia ixx="${(1/12) * mass * (3*radius*radius + length*length)}" ixy="0.0" ixz="0.0" iyy="${(1/12) * mass * (3*radius*radius + length*length)}" iyz="0.0" izz="${(1/2) * mass * (radius*radius)}"/> </inertial> </xacro:macro> <xacro:macro name="inertial_box" params="mass x y z"> <inertial> <mass value="${mass}"/> <inertia ixx="${(1/12) * mass * (y*y+z*z)}" ixy="0.0" ixz="0.0" iyy="${(1/12) * mass * (x*x+z*z)}" iyz="0.0" izz="${(1/12) * mass * (x*x+y*y)}"/> </inertial> </xacro:macro> 

2. 给部件穿上“防弹衣”

修改 base_linkwheel_link 等部件,在 <visual>(外观)同级目录下,添加 <collision>(碰撞)和宏调用的 <xacro:inertial...>

以车身为例:

XML

 <link name="base_link"> <visual> <geometry> <box size="${base_length} ${base_width} ${base_height}"/> </geometry> <material name="blue"/> </visual> <collision> <geometry> <box size="${base_length} ${base_width} ${base_height}"/> </geometry> </collision> <xacro:inertial_box mass="1.0" x="${base_length}" y="${base_width}" z="${base_height}"/> </link> 

3. 编写 Gazebo 启动文件

创建 launch/gazebo.launch.py,这个脚本负责:

  1. 启动 Gazebo 服务。
  2. 解析 Xacro 文件。
  3. 调用 spawn_entity 节点把机器人放进去。

(核心代码略,主要是使用了 gazebo_ros 包的 spawn_entity.py)


三、 踩坑与解决方案 (重点!)

在开发过程中,我遇到了几个非常经典的新手 Bug,这里记录一下解决步骤。

现象

运行 Launch 文件时,终端出现警告,提示 KDL 不支持根节点(root link)带有惯性。

(如图)补充一下,如果首次打开像我一样窗口是黑屏的话,不用着急,后台正在下载,耐心等待一会就好。

原因

ROS 的规范建议机器人的“底座”应该是一个没有重量的虚拟点,而我的 base_link 有重量。

✅ 解决

引入 base_footprint(虚拟底座)。

在 xacro 文件最开头添加:

XML

 <link name="base_footprint"/> <joint name="base_joint" type="fixed"> <parent link="base_footprint"/> <child link="base_link"/> <origin xyz="0 0 ${base_height/2.0}" rpy="0 0 0"/> </joint> 

❌ 坑2:机器人在 Gazebo 里是白色的

现象

Rviz 里车是蓝色的,但在 Gazebo 里全是灰白色,像个石膏模型。

原因

Gazebo 根本不认 URDF 里的 <material name="blue">,它只认自己的 <gazebo> 标签。

✅ 解决

在 xacro 文件末尾,专门为 Gazebo 添加颜色标签:

XML

 <gazebo reference="base_link"> <material>Gazebo/Blue</material> </gazebo> <gazebo reference="left_wheel_link"> <material>Gazebo/Black</material> </gazebo> 

❌ 坑3:机器人“卡”在地里或者 XML 解析错误

现象

  1. 机器人生成后只有一半在地上。
  2. 编译报错 mismatched tag✅ 解决
  3. 卡地里:在 Launch 文件的 spawn_entity 节点参数中,添加 -z 0.15,让机器人出生在半空中,自然掉落。
  4. XML 报错:这是因为手误删除了 </link> 闭合标签。使用 Nano 编辑器的行号功能定位并补全即可。

四、 最终成果 (The Drop Test)

经过一顿操作修复,最终效果如下:

  1. 运行 ros2 launch ... 命令。
  2. Gazebo 窗口弹出。
  3. 机器人从空中出现,“啪”的一声稳稳落在地上,四个轮子着地,没有散架,也没有乱飞!

截图展示:


五、 总结

  • Rviz vs Gazebo:Rviz 是“卖家秀”(只负责看),Gazebo 是“买家秀”(负责物理仿真)。
  • 细节决定成败:路径写错、标签没闭合、物理属性缺失,都会导致仿真失败。
  • 下一步计划:现在的车只能推着走,明天我要给它装上 Differential Drive 插件,让它能真正跑起来!

ROS 2 学习之路,我们一起加油!

Could not load content