3、Gazebo仿真环境配置:创建自己的仿真世界
说实话,很多初学者一上来就急着让机械臂动起来,结果发现仿真环境乱七八糟——要么地面是透明的,要么光照暗得看不清,要么模型卡在半空中。我当年也踩过这个坑,后来才明白:一个靠谱的仿真世界,是后面所有抓取实验的基础。
这一节,我们就来亲手搭建一个属于自己的仿真世界。你会学到:
- world文件的完整结构
- 如何添加地面、光照、障碍物
- 用SDFormat描述自定义模型
3.1 world文件长什么样?
先看一个最简单的world文件。我习惯把它放在 worlds/ 目录下,命名规则是 my_robot.world。
<?xml version="1.0" ?>
<sdf version="1.6">
<world name="my_world">
<include>
<uri>model://sun</uri>
</include>
<include>
<uri>model://ground_plane</uri>
</include>
</world>
</sdf>
嗯,就这么几行。但别小看它——<world> 标签里可以塞进物理参数、重力、磁力、甚至风。我个人建议,刚开始不要贪多,先把基础结构跑通。
3.2 添加地面和光照
地面是必须的,不然你的机械臂会掉进虚空里。Gazebo自带的 ground_plane 模型够用,但如果你想自定义地面纹理,可以这样写:
<model name="ground">
<static>true</static>
<link name="link">
<collision name="collision">
<geometry>
<box>
<size>20 20 0.1</size>
</box>
</geometry>
</collision>
<visual name="visual">
<geometry>
<box>
<size>20 20 0.1</size>
</box>
</geometry>
<material>
<ambient>0.8 0.8 0.8 1</ambient>
<diffuse>0.8 0.8 0.8 1</diffuse>
</material>
</visual>
</link>
</model>
光照呢?Gazebo默认有一个太阳光,但你可以调整它的角度和颜色。我在项目中遇到过一个问题:光照太强导致相机仿真图像过曝。后来我把 <intensity> 从1.0降到了0.6,问题就解决了。
<light name="sun" type="directional">
<pose>0 0 10 0 0 0</pose>
<diffuse>0.8 0.8 0.8 1</diffuse>
<specular>0.2 0.2 0.2 1</specular>
<direction>-0.5 0.1 -1</direction>
<attenuation>
<range>100</range>
<constant>0.9</constant>
<linear>0.01</linear>
<quadratic>0.001</quadratic>
</attenuation>
<cast_shadows>true</cast_shadows>
</light>
3.3 添加障碍物
障碍物是让仿真变得真实的关键。你想想看,真实场景里哪有空荡荡的桌面?总得有几个箱子、柱子、或者别的机器人吧。
下面是一个简单的箱子障碍物:
<model name="obstacle_box">
<static>true</static>
<pose>1.5 0.5 0.05 0 0 0</pose>
<link name="link">
<collision name="collision">
<geometry>
<box>
<size>0.4 0.4 0.4</size>
</box>
</geometry>
</collision>
<visual name="visual">
<geometry>
<box>
<size>0.4 0.4 0.4</size>
</box>
</geometry>
<material>
<ambient>1 0 0 1</ambient>
<diffuse>1 0 0 1</diffuse>
</material>
</visual>
</link>
</model>
注意 <static>true</static>——这意味着这个箱子不会被撞飞。如果你想让障碍物可以被推动,改成 false 就行。我曾经犯过一个错误:把障碍物设成非静态,结果机械臂一碰,箱子满世界乱滚,仿真直接崩了。
3.4 使用SDFormat描述模型
SDFormat是Gazebo的亲儿子格式。它比URDF更强大,支持物理属性、传感器、甚至插件。说白了,URDF是给ROS看的,SDF是给Gazebo看的。
一个完整的SDF模型包含:
- link:刚体,包含碰撞、视觉、惯性
- joint:连接两个link,定义运动副
- model:把link和joint打包成一个整体
下面是一个自定义桌子的SDF模型:
<?xml version="1.0" ?>
<sdf version="1.6">
<model name="table">
<static>true</static>
<pose>0 0 0.4 0 0 0</pose>
<link name="table_top">
<pose>0 0 0.02 0 0 0</pose>
<collision name="collision">
<geometry>
<box>
<size>1.2 0.8 0.04</size>
</box>
</geometry>
</collision>
<visual name="visual">
<geometry>
<box>
<size>1.2 0.8 0.04</size>
</box>
</geometry>
<material>
<ambient>0.5 0.3 0.1 1</ambient>
<diffuse>0.5 0.3 0.1 1</diffuse>
</material>
</visual>
</link>
<link name="leg_1">
<pose>-0.5 -0.3 -0.38 0 0 0</pose>
<collision name="collision">
<geometry>
<box>
<size>0.04 0.04 0.76</size>
</box>
</geometry>
</collision>
<visual name="visual">
<geometry>
<box>
<size>0.04 0.04 0.76</size>
</box>
</geometry>
</visual>
</link>
<!-- 其他三条腿类似,省略 -->
</model>
</sdf>
gz sim 预览一下,别等到最后才发现。
3.5 知识体系一览
下面这张图帮你理清本章的核心逻辑:
3.6 完整world文件示例
把上面所有元素拼起来,就是一个完整的仿真世界:
<?xml version="1.0" ?>
<sdf version="1.6">
<world name="grasping_world">
<!-- 光照 -->
<include>
<uri>model://sun</uri>
</include>
<!-- 自定义地面 -->
<model name="ground">
<static>true</static>
<link name="link">
<collision name="collision">
<geometry>
<box>
<size>20 20 0.1</size>
</box>
</geometry>
</collision>
<visual name="visual">
<geometry>
<box>
<size>20 20 0.1</size>
</box>
</geometry>
<material>
<ambient>0.9 0.9 0.9 1</ambient>
<diffuse>0.9 0.9 0.9 1</diffuse>
</material>
</visual>
</link>
</model>
<!-- 桌子 -->
<model name="table">
<static>true</static>
<pose>0 0 0.4 0 0 0</pose>
<link name="table_top">
<pose>0 0 0.02 0 0 0</pose>
<collision name="collision">
<geometry>
<box>
<size>1.2 0.8 0.04</size>
</box>
</geometry>
</collision>
<visual name="visual">
<geometry>
<box>
<size>1.2 0.8 0.04</size>
</box>
</geometry>
<material>
<ambient>0.5 0.3 0.1 1</ambient>
<diffuse>0.5 0.3 0.1 1</diffuse>
</material>
</visual>
</link>
<!-- 桌腿省略 -->
</model>
<!-- 障碍物箱子 -->
<model name="obstacle">
<static>true</static>
<pose>0.6 0.3 0.42 0 0 0</pose>
<link name="link">
<collision name="collision">
<geometry>
<box>
<size>0.2 0.2 0.2</size>
</box>
</geometry>
</collision>
<visual name="visual">
<geometry>
<box>
<size>0.2 0.2 0.2</size>
</box>
</geometry>
<material>
<ambient>0 0 1 1</ambient>
<diffuse>0 0 1 1</diffuse>
</material>
</visual>
</link>
</model>
<!-- 物理参数 -->
<physics type="ode">
<real_time_update_rate>1000</real_time_update_rate>
<max_step_size>0.001</max_step_size>
</physics>
</world>
</sdf>
my_world.world 后,用 gazebo --verbose my_world.world 启动。如果一切正常,你会看到一个带桌子、箱子和光照的仿真环境。
嗯,到这里你已经掌握了创建仿真世界的核心技能。别小看这些基础配置——我见过不少项目,最后出问题都是因为world文件里某个参数写错了。多花点时间把环境搭扎实,后面做运动规划、抓取仿真的时候,你会感谢自己的。
可可精品资料库