第四节:配置机器人仿真环境——创建仿真世界、添加静态障碍物、设置光照与物理参数
各位同学,欢迎来到第四节。今天我们要亲手搭建一个完整的仿真世界。
说实话,很多初学者一上来就急着跑导航算法,结果发现机器人要么撞墙、要么飘在空中。为什么?因为仿真环境没配好。我刚开始做项目时也吃过这个亏——在Gazebo里随便拉了个地面就开始调参数,折腾了两天,最后发现是物理引擎的摩擦系数设错了。
所以这一节,我们稳扎稳打,把仿真世界的底子打好。
4.1 创建仿真世界(World)
Gazebo里的世界文件,说白了就是一个描述环境的XML文件。它告诉仿真器:地面长什么样、墙在哪、光照从哪来、重力有多大。
我个人习惯用.world后缀来命名。先看一个最基础的例子:
<?xml version="1.0" ?>
<sdf version="1.6">
<world name="my_robot_world">
<include>
<uri>model://sun</uri>
</include>
<include>
<uri>model://ground_plane</uri>
</include>
</world>
</sdf>
这个文件做了两件事:加了一个太阳光源,加了一个地面。保存为empty.world,然后用gazebo empty.world启动,你就能看到一个空荡荡的世界。
worlds/目录下,方便管理。比如my_robot_bringup/worlds/。
4.2 添加静态障碍物
空世界没什么好玩的。我们要加一些障碍物,让机器人有东西可以绕。
静态障碍物,就是不会动、不会碎的物体。Gazebo里用<model>标签来定义。下面是一个长方体障碍物的例子:
<model name="obstacle_01">
<static>true</static>
<link name="link">
<collision name="collision">
<geometry>
<box>
<size>0.5 0.5 1.0</size>
</box>
</geometry>
</collision>
<visual name="visual">
<geometry>
<box>
<size>0.5 0.5 1.0</size>
</box>
</geometry>
<material>
<ambient>0.8 0.2 0.2 1</ambient>
</material>
</visual>
</link>
<pose>2.0 1.5 0.5 0 0 0</pose>
</model>
注意看,<static>true</static>表示这个物体是固定的,不会被撞飞。<pose>定义了它的位置和朝向。这里我把它放在(2.0, 1.5)处,高度0.5米。
<visual>忘了加<collision>。结果机器人直接穿模过去了,因为Gazebo根本检测不到碰撞。记住:视觉和碰撞是两个独立的部分,都得配。
如果你想加多个障碍物,复制粘贴这个模型块,改个名字和位置就行。比如:
<model name="obstacle_02">
<static>true</static>
<link name="link">
<collision name="collision">
<geometry>
<cylinder>
<radius>0.3</radius>
<length>0.8</length>
</cylinder>
</geometry>
</collision>
<visual name="visual">
<geometry>
<cylinder>
<radius>0.3</radius>
<length>0.8</length>
</cylinder>
</geometry>
<material>
<ambient>0.2 0.8 0.2 1</ambient>
</material>
</visual>
</link>
<pose>-1.0 2.0 0.4 0 0 0</pose>
</model>
这是一个绿色圆柱体,放在(-1.0, 2.0)处。你想想看,如果场景里只有方盒子,导航算法跑起来其实没什么挑战。加一些圆柱、球体,效果会真实很多。
4.3 设置光照参数
光照影响什么?影响传感器的仿真效果,尤其是摄像头和激光雷达。光线太暗,摄像头拍出来全是噪点;光线太强,激光雷达可能被干扰。
Gazebo默认的太阳光其实够用,但如果你想精细控制,可以手动定义光源:
<light name="sun" type="directional">
<cast_shadows>true</cast_shadows>
<pose>0 0 10 0 0 0</pose>
<diffuse>0.9 0.9 0.9 1</diffuse>
<specular>0.2 0.2 0.2 1</specular>
<attenuation>
<range>20</range>
<constant>0.5</constant>
<linear>0.01</linear>
<quadratic>0.001</quadratic>
</attenuation>
<direction>-0.5 0.1 -0.9</direction>
</light>
这里我设置了一个方向光,从斜上方打下来。注意<diffuse>控制光的颜色和强度,<cast_shadows>开启阴影。阴影对视觉SLAM影响很大,建议开启。
<diffuse>的RGB值从0.8调到了1.0,效果好了很多。但别调太高,否则画面过曝。
4.4 设置物理参数
物理参数决定了机器人怎么动、怎么停、会不会打滑。Gazebo的物理引擎基于ODE(Open Dynamics Engine),我们可以调整以下关键参数:
| 参数 | 默认值 | 说明 |
|---|---|---|
| gravity | 0 0 -9.8 | 重力加速度,Z轴负方向 |
| max_step_size | 0.001 | 物理仿真步长,越小越精确 |
| real_time_factor | 1.0 | 实时因子,1.0表示实时仿真 |
| friction | 1.0 | 摩擦系数,影响打滑程度 |
配置方法如下:
<physics type="ode">
<max_step_size>0.002</max_step_size>
<real_time_factor>1.0</real_time_factor>
<real_time_update_rate>500</real_time_update_rate>
<gravity>0 0 -9.81</gravity>
</physics>
这里我把步长设为0.002秒,更新率500Hz。为什么这么设?因为我的机器人运动速度较快,步长太小计算量太大,步长太大又容易穿透障碍物。0.002是个折中值。
<friction>设成了0.1。改成1.0后立刻稳了。
4.5 完整的世界文件示例
把上面所有内容整合起来,就是一个完整的世界文件:
<?xml version="1.0" ?>
<sdf version="1.6">
<world name="nav2_test_world">
<physics type="ode">
<max_step_size>0.002</max_step_size>
<real_time_factor>1.0</real_time_factor>
<real_time_update_rate>500</real_time_update_rate>
<gravity>0 0 -9.81</gravity>
</physics>
<light name="sun" type="directional">
<cast_shadows>true</cast_shadows>
<pose>0 0 10 0 0 0</pose>
<diffuse>1.0 1.0 1.0 1</diffuse>
<specular>0.2 0.2 0.2 1</specular>
<direction>-0.5 0.1 -0.9</direction>
</light>
<include>
<uri>model://sun</uri>
</include>
<include>
<uri>model://ground_plane</uri>
</include>
<model name="obstacle_01">
<static>true</static>
<link name="link">
<collision name="collision">
<geometry>
<box>
<size>0.5 0.5 1.0</size>
</box>
</geometry>
</collision>
<visual name="visual">
<geometry>
<box>
<size>0.5 0.5 1.0</size>
</box>
</geometry>
<material>
<ambient>0.8 0.2 0.2 1</ambient>
</material>
</visual>
</link>
<pose>2.0 1.5 0.5 0 0 0</pose>
</model>
<model name="obstacle_02">
<static>true</static>
<link name="link">
<collision name="collision">
<geometry>
<cylinder>
<radius>0.3</radius>
<length>0.8</length>
</cylinder>
</geometry>
</collision>
<visual name="visual">
<geometry>
<cylinder>
<radius>0.3</radius>
<length>0.8</length>
</cylinder>
</geometry>
<material>
<ambient>0.2 0.8 0.2 1</ambient>
</material>
</visual>
</link>
<pose>-1.0 2.0 0.4 0 0 0</pose>
</model>
</world>
</sdf>
保存为nav2_test.world,启动Gazebo加载它:
gazebo nav2_test.world
你应该能看到一个带阴影的明亮场景,地面上有一个红色方柱和一个绿色圆柱。
4.6 本章知识体系
下面这张图帮你理清今天的内容结构:
嗯,到这里,你的仿真世界已经初具雏形了。下一节我们会把机器人模型放进去,让它在这些障碍物之间跑起来。不过在那之前,我建议你多试试不同的障碍物形状和位置,熟悉一下XML的写法。
可可精品资料库