4. SLAM建图工具:使用SLAM Toolbox进行在线建图、保存地图、地图的加载与可视化

说到建图,很多新手第一反应就是「跑个gmapping不就行了?」。嗯,gmapping确实经典,但说实话,我在实际项目里已经很少用它了。今天要聊的SLAM Toolbox,才是目前Nav2生态里最趁手的建图工具。

为什么我偏爱它?因为SLAM Toolbox不仅支持在线建图,还能做地图的序列化保存、增量更新,甚至支持纯定位模式。说白了,它把建图这件事从「一次性买卖」变成了「可持续迭代」的过程。

传感器数据 /scan + /odom SLAM Toolbox 在线建图核心 占用栅格地图 /map 话题输出 保存地图 加载已有地图 继续建图 / 纯定位 地图可视化 SLAM Toolbox 支持三种模式:建图模式、本地化模式、继续建图模式 通过 launch 参数 slam_mode 切换:mapping / localization / continue

4.1 启动SLAM Toolbox在线建图

先说说最基础的操作——在线建图。你只需要一个带激光雷达的机器人,能发布/scan和/odom话题就行。

我个人习惯用下面这个launch文件启动SLAM Toolbox:

# 启动SLAM Toolbox建图
ros2 launch slam_toolbox online_async_launch.py \
  slam_params_file:=./slam_params.yaml \
  use_sim_time:=false

这里有个关键点——参数文件。我见过太多人直接跑默认参数,结果地图建得一塌糊涂。下面是我常用的参数配置:

# slam_params.yaml
slam_toolbox:
  ros__parameters:
    # 核心参数
    mode: mapping                # 建图模式
    min_laser_range: 0.2         # 最小激光距离,防止机器人自身干扰
    max_laser_range: 12.0        # 最大有效距离
    resolution: 0.05             # 地图分辨率,5厘米一格

    # 回环检测
    loop_search_maximum_distance: 4.0
    loop_match_minimum_chain_size: 10
    loop_match_maximum_variance_coarse: 0.5

    # 地图更新
    map_update_interval: 5.0     # 每5秒更新一次地图
    max_laser_range: 12.0
    minimum_time_interval: 0.5
我的经验:分辨率设0.05看起来精细,但如果你的激光雷达噪声大,反而容易建出「毛刺地图」。我在一个仓库项目里吃过这个亏,后来改成0.08,地图平滑多了,定位精度反而提升了。

4.2 保存地图——别让努力白费

建好图之后,第一件事就是保存。别笑,我真见过有人建了一下午图,结果忘记保存,断电后一切归零。

保存地图用map_saver_cli工具,非常简单:

# 保存当前地图
ros2 run nav2_map_server map_saver_cli -f my_warehouse_map

# 指定保存路径
ros2 run nav2_map_server map_saver_cli -f ~/maps/office_floor1

执行后会生成两个文件:

  • my_warehouse_map.yaml —— 地图元数据文件
  • my_warehouse_map.pgm —— 栅格图像文件

YAML文件的内容大概长这样:

image: my_warehouse_map.pgm
resolution: 0.050000
origin: [-10.000000, -10.000000, 0.000000]
negate: 0
occupied_thresh: 0.65
free_thresh: 0.196
注意:origin参数表示地图左下角在真实世界坐标系中的位置。如果你后续要加载地图做定位,这个值必须和建图时保持一致。我曾经因为手改了这个值,导致机器人定位直接飘到地图外面去了。

4.3 加载地图——让机器人认识路

地图保存好了,怎么加载呢?Nav2提供了map_server节点来做这件事:

# 加载已有地图
ros2 run nav2_map_server map_server --ros-args -p yaml_filename:=my_warehouse_map.yaml

# 别忘了启动生命周期节点
ros2 run nav2_util lifecycle_bringup map_server

加载成功后,你可以通过/map话题看到地图数据:

# 查看地图话题
ros2 topic echo /map --once

# 用RViz2可视化
ros2 run rviz2 rviz2

在RViz2里添加Map显示,选择/map话题,你就能看到之前建好的地图了。

4.4 地图可视化——不只是看看而已

可视化这一步,很多人觉得「不就是显示个图嘛」。但我想说,可视化其实是调试建图质量最直观的手段。

在RViz2中,我通常会同时添加这几个显示项:

显示项 话题 作用
Map /map 显示占用栅格地图
LaserScan /scan 实时激光数据,看建图是否对齐
TF /tf 查看机器人位姿与地图的变换关系
Path /plan (可选)查看规划路径是否合理
判断建图质量的小技巧:把LaserScan叠加在地图上,如果激光点云和地图边缘完美贴合,说明建图质量很好。如果出现重影或偏移,那就要检查里程计或者回环检测参数了。

4.5 避坑指南——我踩过的那些坑

最后分享几个我在项目中实际遇到的问题:

  • 地图边缘出现「鬼影」:通常是激光雷达的安装角度有偏差,或者机器人震动太大。我建议先检查tf树,确保base_link到laser的变换准确。
  • 回环检测不触发:检查loop_search_maximum_distance参数,如果设得太小,机器人走远了就认不出之前的地方了。我一般设4-6米。
  • 保存的地图加载后是黑的:大概率是pgm文件路径不对,或者YAML里的image路径写成了路径。建议用相对路径,把地图文件和YAML放一起。

嗯,建图这部分内容其实挺多的,但掌握了SLAM Toolbox这套流程,后面做导航定位就会顺手很多。记住一个原则:地图质量决定了导航上限,别在建图阶段偷懒。