4. SLAM建图:激光SLAM原理、Cartographer使用、地图保存
在机器人路径规划中,地图是决策的基础。没有一张可用的栅格地图,全局路径规划与局部避障都无从谈起。本章聚焦于激光SLAM建图,重点讲解其核心原理、Cartographer工具的实际使用流程,以及地图的保存与格式转换。
4.1 激光SLAM核心原理:从扫描到占据栅格
激光SLAM(Simultaneous Localization and Mapping)的核心任务可以概括为:机器人在未知环境中,一边利用激光雷达感知周围障碍物,一边估计自身位姿,同时增量式地构建环境地图。其本质是一个“先有鸡还是先有蛋”的循环问题——定位需要地图,建图需要位姿,因此SLAM算法必须联合求解。
在ROS2中,最常用的激光SLAM算法是Cartographer,它由Google开源,采用图优化(Graph-based SLAM)框架。其核心思想分为两个层级:
- 局部匹配(前端):利用当前激光帧与最近一段时间的子图(Submap)进行扫描匹配,得到相对位姿。Cartographer采用非线性最小二乘优化(如Ceres Solver)来求解帧与子图间的刚体变换,从而获得高频、低精度的局部轨迹。
- 全局闭环(后端):当机器人回到曾经访问过的区域时,通过分支定界(Branch and Bound)搜索算法在历史子图中寻找匹配,一旦检测到闭环,则触发一次全局的位姿图优化,消除累积漂移,得到全局一致的轨迹与地图。
最终生成的地图是占据栅格地图(Occupancy Grid Map)。每个栅格存储一个概率值,表示该位置被障碍物占据的可能性。在ROS2中,该值通常以0~100表示占据概率,-1表示未知区域。
4.2 Cartographer在ROS2中的安装与配置
在ROS2环境中使用Cartographer,通常通过二进制安装或源码编译。以Humble版本为例,推荐使用apt安装:
sudo apt install ros-humble-cartographer
sudo apt install ros-humble-cartographer-ros
安装完成后,需要准备两个关键配置文件:Lua脚本(用于定义算法参数)和URDF模型(用于描述机器人底盘与雷达的外参)。一个典型的Lua配置片段如下:
include "map_builder.lua"
include "trajectory_builder.lua"
options = {
map_builder = MAP_BUILDER,
trajectory_builder = TRAJECTORY_BUILDER,
map_frame = "map",
tracking_frame = "base_link",
published_frame = "odom",
odom_frame = "odom",
provide_odom_frame = true,
use_odometry = true,
num_laser_scans = 1,
num_subdivisions_per_laser_scan = 1
}
return options
启动建图时,通常需要同时启动三个节点:激光雷达驱动、Cartographer节点以及可视化节点RViz2。可以使用如下命令:
ros2 launch cartographer_ros cartographer.launch.py \
configuration_basename:="my_robot.lua"
map → odom → base_link → laser 的TF链路完整且频率稳定。如果雷达外参标定不准,会导致地图出现“重影”或“拖尾”现象。
4.3 实操案例:使用Cartographer构建室内地图
以下是一个典型的建图流程,假设你已有一个发布/scan话题的2D激光雷达,以及一个可遥控的差速底盘。
- 启动底盘与雷达驱动:确保
/odom与/scan话题正常输出。 - 启动Cartographer:加载Lua配置,开始接收数据并构建子图。
- 遥控机器人运动:缓慢平移并旋转,避免原地高速旋转,确保激光帧有足够重叠。
- 观察RViz2中的实时地图:检查是否有明显错位或漂移。
- 触发闭环:让机器人回到起点附近,观察地图是否自动校正对齐。
下表总结了建图过程中的关键参数与建议值:
| 参数名 | 建议值 | 作用说明 |
|---|---|---|
use_odometry |
true | 融合轮式里程计,提高短时精度 |
num_laser_scans |
1 | 单雷达配置为1 |
map_resolution |
0.05 | 栅格分辨率(米/像素) |
tracking_frame |
base_link | 机器人本体坐标系 |
loop_closure_automatic |
true | 自动闭环检测 |
4.4 地图保存与格式转换
建图完成后,需要将Cartographer的当前地图快照保存为静态地图文件,供后续导航使用。Cartographer本身不直接保存pgm/yaml,而是通过map_saver节点来订阅/map话题并保存。
ros2 run nav2_map_server map_saver_cli -f ~/map/my_room
执行后,会生成两个文件:my_room.pgm(图像文件)和my_room.yaml(元数据文件)。其中yaml内容类似:
image: my_room.pgm
resolution: 0.050000
origin: [-10.0, -10.0, 0.0]
negate: 0
occupied_thresh: 0.65
free_thresh: 0.196
在保存地图前,务必在RViz2中确认/map话题的显示正常,且地图边界完整。如果地图存在大量黑色噪点,可以先用map_editor工具或图像处理软件清理后再保存。
4.5 常见误区与复盘
在实际建图过程中,初学者常犯以下错误,导致地图质量不佳:
- 误区一:雷达频率过低。如果雷达扫描频率低于5Hz,机器人运动稍快就会造成帧间匹配失败,地图出现断裂。建议使用10Hz以上的雷达。
- 误区二:忽略IMU的作用。对于不平坦地面或底盘打滑明显的情况,仅靠轮式里程计无法提供足够的运动约束,此时应配置IMU并设置
use_imu = true。 - 误区三:建图时速度过快。Cartographer虽然鲁棒,但过快的角速度会导致激光帧变形,建议线速度不超过0.5m/s,角速度不超过0.5rad/s。
- 误区四:保存地图前未等待闭环完成。如果地图还在漂移中就保存,会导致导航时定位失败。正确做法是观察地图稳定后再保存。
复盘一个典型失败案例:某次建图时,地图在走廊尽头出现明显的“分叉”现象。排查后发现,原因是雷达的安装位置与URDF中描述的偏移量不一致,导致前端匹配时引入了系统性误差。修正外参后,重新建图,地图恢复正常。这提醒我们:外参标定是SLAM建图的前提,任何微小的安装偏差都会在长时间建图中被放大。
通过本章的学习,你已经掌握了激光SLAM的核心原理、Cartographer的配置与使用、地图保存方法以及常见问题的排查思路。在下一阶段,你将基于这张静态地图,开展机器人的自主定位与路径规划实验。