3、SLAM建图基础:Gmapping算法原理、参数详解、建图实战与地图保存

各位同学,欢迎来到SLAM建图实战环节。

今天咱们聊Gmapping。说实话,这算法有点年头了,但直到现在,很多量产扫地机器人、仓储AGV还在用。为什么?因为它够稳,够快,对算力要求低。我当年刚入行时,第一个落地的SLAM项目就是基于Gmapping做的,踩了不少坑,今天全部分享给你们。

3.1 Gmapping算法核心原理

Gmapping说白了,就是「粒子滤波 + 激光雷达 + 里程计」的组合。它解决的核心问题是:机器人一边动,一边猜自己在哪里,同时把地图画出来。

具体怎么做的?我简单拆解一下:

  • 粒子滤波:每个粒子代表机器人可能的一个位姿(x, y, θ)。一开始撒一堆粒子,随着运动,不断更新粒子的权重。权重高的粒子留下,权重低的淘汰——这就是「重采样」。
  • 激光观测模型:每个粒子会「预测」它看到的激光数据应该长什么样。如果和实际激光数据匹配得好,这个粒子的权重就高。
  • 里程计运动模型:机器人动一步,所有粒子跟着动一步。但里程计有误差,所以粒子会加一点随机噪声。

嗯,这里要注意:Gmapping最聪明的地方在于,它改进了粒子滤波的提议分布。它没有傻傻地用里程计来撒粒子,而是把激光数据也融进去了。这样粒子更集中,需要的粒子数更少。我记得当年用200个粒子就能跑出不错的效果,而普通粒子滤波至少需要1000个。

核心公式(理解即可):

粒子权重 w = 激光观测似然 × 里程计预测概率

说白了就是:激光说「你在这」,里程计说「你在这」,两个都同意,那这个粒子就靠谱。

Gmapping 算法核心流程 初始化粒子群 里程计预测(加噪声) 激光观测更新权重 重采样(淘汰低权重) 更新地图(栅格占用) 循环迭代

3.2 参数详解——这些坑我替你踩过了

Gmapping的参数都在一个叫 gmapping.launch 的文件里。我直接给你们列一张表,哪些参数最要命,我标出来。

参数名 默认值 我的建议值 说明
particles 30 80~200 粒子数。太少容易发散,太多跑不动。我一般先设100试试。
minimumScore 0.0 50~100 激光匹配的最低分数。设太低,错误匹配会毁掉地图。我曾经设0,结果地图全花了。
delta 0.05 0.05 地图分辨率(米/像素)。0.05就是5cm一格。别改太小,否则地图文件巨大。
linearUpdate 1.0 0.5 机器人走多少米更新一次地图。设小点,地图更精细,但计算量也大。
angularUpdate 0.5 0.2 机器人转多少弧度更新一次。转弯多的地方,这个值要小。
maxUrange 80.0 激光雷达最大测距 超过这个距离的激光点会被忽略。我建议设成雷达标称距离的80%。
srr / srt / str / stt 0.01 / 0.02 / 0.01 / 0.02 视底盘而定 里程计噪声模型参数。底盘差就设大点,底盘好就设小点。我调过最差的底盘,这些值要放大10倍。

⚠️ 我曾经踩过的坑:

有一次在工厂调试,地图总是歪的。我查了三天,最后发现是 minimumScore 设成了0。激光匹配到墙上也认为是对的,结果粒子全跑偏了。记住:minimumScore 一定要设一个正数,哪怕50都行。

3.3 建图实战——手把手带你跑起来

好,理论讲完了,咱们直接上手。你想想看,如果只看参数不看实战,那跟没学一样。

第一步:启动底盘和雷达

我假设你已经有了机器人底盘驱动和激光雷达驱动。先跑起来:

# 启动底盘(以差速轮为例)
roslaunch my_robot_base base.launch

# 启动激光雷达(以RPLIDAR为例)
roslaunch rplidar_ros rplidar.launch

# 检查话题
rostopic list | grep -E "scan|odom"

确保你能看到 /scan 和 /odom 这两个话题。没有的话,Gmapping没法干活。

第二步:启动Gmapping

创建一个launch文件,我习惯叫 gmapping_slam.launch:

<launch>
  <node pkg="gmapping" type="slam_gmapping" name="slam_gmapping" output="screen">
    <param name="base_frame" value="base_footprint"/>
    <param name="odom_frame" value="odom"/>
    <param name="map_frame" value="map"/>
    <param name="map_update_interval" value="5.0"/>
    <param name="maxUrange" value="8.0"/>
    <param name="minimumScore" value="80"/>
    <param name="particles" value="100"/>
    <param name="linearUpdate" value="0.5"/>
    <param name="angularUpdate" value="0.2"/>
    <param name="delta" value="0.05"/>
  </node>
</launch>

然后运行:

roslaunch gmapping_slam.launch

第三步:可视化建图过程

打开Rviz,添加 Map 显示,话题选 /map。再添加 LaserScan 和 RobotModel。你会看到地图一点点被画出来。

💡 我的小技巧:

建图时,别让机器人走太快。我一般把线速度控制在0.3m/s以内,角速度0.5rad/s以内。走太快,激光数据会变形,地图容易糊。

3.4 地图保存——别让辛苦白费

地图建好了,怎么存下来?ROS提供了一个工具叫 map_server。

保存命令很简单:

# 安装map_server(如果没装)
sudo apt install ros-noetic-map-server

# 保存地图
rosrun map_server map_saver -f ~/my_map

运行后,你会得到两个文件:

  • my_map.pgm:图片格式的地图。白色是空地,黑色是障碍物,灰色是未知区域。
  • my_map.yaml:地图的元数据文件,包含分辨率、原点坐标、占用阈值等。

打开 my_map.yaml 看看,内容大概长这样:

image: my_map.pgm
resolution: 0.050000
origin: [-10.000000, -10.000000, 0.000000]
negate: 0
occupied_thresh: 0.65
free_thresh: 0.196

这里有个坑:origin 是地图左下角在真实世界中的坐标。如果你建图时机器人起点不在原点,这个值会变。我建议建图前先把机器人放在一个固定起点,这样地图坐标好对齐。

⚠️ 注意:

保存地图时,确保Gmapping还在运行,并且地图已经稳定。我见过有人建到一半就保存,结果地图只有一半。等地图不再变化了再保存,一般走完整个区域后再等10秒。

好了,以上就是Gmapping从原理到实战的全流程。参数调优是个慢功夫,我建议你每次只改一个参数,看看地图变化。别一次改一堆,出了问题都不知道是哪个参数搞的鬼。

记住:建图就像画画,急不得。慢慢来,地图自然会漂亮。

总结一下今天的关键点:

  • Gmapping = 粒子滤波 + 激光 + 里程计
  • particles 和 minimumScore 是最重要的两个参数
  • 建图时速度要慢,转弯要稳
  • 地图保存用 map_saver,等地图稳定再存
可可精品资料库