3. 使用cartographer构建高精度地图
任务目标
使用Cartographer算法融合2D激光雷达与IMU数据,在ROS环境中构建高精度二维栅格地图,并通过调整关键参数观察地图质量变化,掌握参数调优的基本方法。
环境与依赖
- Ubuntu 20.04 + ROS Noetic(或Ubuntu 18.04 + ROS Melodic)
- 已安装
cartographer_ros与cartographer(sudo apt install ros-noetic-cartographer-ros) - 激光雷达驱动(如rplidar、velodyne等)或使用公开数据集bag
- IMU驱动(或使用bag中录制的IMU数据)
实现方案
本案例采用最小可复现方式:使用公开的2D激光SLAM数据集(如Cartographer官方推荐的 cartographer_paper_deutsches_museum.bag)完成建图,避免硬件驱动差异带来的干扰。核心工作分为三部分:编写Cartographer的Lua配置文件、编写启动文件、运行建图并对比参数效果。
关键完整代码
1. Lua配置文件(my_2d.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 = false,
num_laser_scans = 1,
num_multi_echo_laser_scans = 0,
num_subdivisions_per_laser_scan = 1,
num_point_clouds = 0,
lookup_transform_timeout_sec = 0.2,
submap_publish_period_sec = 0.3,
pose_publish_period_sec = 5e-3,
trajectory_publish_period_sec = 30e-3,
}
MAP_BUILDER.use_trajectory_builder_2d = true
TRAJECTORY_BUILDER_2D.use_imu_data = true
TRAJECTORY_BUILDER_2D.use_online_correlative_scan_matching = true
TRAJECTORY_BUILDER_2D.min_range = 0.3
TRAJECTORY_BUILDER_2D.max_range = 30.
TRAJECTORY_BUILDER_2D.missing_data_ray_length = 5.
TRAJECTORY_BUILDER_2D.num_accumulated_range_data = 1
-- 关键参数:影响地图质量
TRAJECTORY_BUILDER_2D.ceres_scan_matcher.translation_weight = 1.
TRAJECTORY_BUILDER_2D.ceres_scan_matcher.rotation_weight = 1.
TRAJECTORY_BUILDER_2D.motion_filter.max_time_sec = 0.5
TRAJECTORY_BUILDER_2D.motion_filter.max_distance_m = 0.2
TRAJECTORY_BUILDER_2D.motion_filter.max_angle_rad = math.rad(0.5)
-- 回环检测参数
MAP_BUILDER.pose_graph.optimize_every_n_nodes = 90
MAP_BUILDER.pose_graph.constraint_builder.min_score = 0.55
MAP_BUILDER.pose_graph.constraint_builder.global_localization_min_score = 0.6
return options
2. 启动文件(my_cartographer.launch)——加载配置并启动建图节点:
<launch>
<node name="cartographer_node" pkg="cartographer_ros"
type="cartographer_node" args="
-configuration_directory $(find cartographer_ros)/configuration_files
-configuration_basename my_2d.lua"
output="screen">
</node>
<node name="cartographer_occupancy_grid_node" pkg="cartographer_ros"
type="cartographer_occupancy_grid_node" args="-resolution 0.05" />
</launch>
3. 播放数据包并保存地图(终端命令):
# 终端1:启动Cartographer
roslaunch cartographer_ros my_cartographer.launch
# 终端2:播放bag数据(需先下载deutsches_museum.bag)
rosbag play --clock cartographer_paper_deutsches_museum.bag
# 终端3:建图完成后保存地图
rosrun map_server map_saver -f my_map
参数对比实验
为验证参数对地图质量的影响,分别修改以下参数并重新建图,对比生成的 my_map.pgm:
| 参数项 | 默认值 | 调整方向 | 预期影响 |
|---|---|---|---|
min_score | 0.55 | 提高至0.7 | 回环约束更严格,减少误匹配,但可能漏检回环 |
optimize_every_n_nodes | 90 | 降低至30 | 后端优化更频繁,地图更一致,但CPU占用升高 |
translation_weight | 1.0 | 提高至5.0 | 更信任激光匹配的平移约束,直线走廊更平直 |
use_imu_data | true | 改为false | 失去IMU姿态预测,快速旋转时地图易出现漂移 |
验证方法与判定标准
- 运行验证:执行上述三个终端命令后,在Rviz中订阅
/map话题,应能看到栅格地图随bag播放逐步构建;bag播放结束后地图不再更新。 - 地图保存:bag播放完毕后,在终端3执行
map_saver,当前目录生成my_map.pgm与my_map.yaml,说明建图流程闭环成功。 - 质量对比:用图像查看器打开不同参数下生成的
.pgm文件,观察以下指标:- 墙体是否连续、无重影或错位;
- 直线走廊是否平直,转角是否为直角;
- 回环闭合处是否对齐(无双重墙壁);
- 地图整体是否存在漂移导致的模糊区域。
- 通过条件:默认参数下地图无明显断裂或错位;调高
min_score后若回环处仍能闭合,则说明原参数偏松;调低optimize_every_n_nodes后地图边缘应更锐利(对比像素级重影减少)。
常见问题
- TF树报错:确认bag中提供了
odom→base_link与base_link→laser的TF;若缺少IMU帧,需将use_imu_data设为false。 - 地图保存为全黑/全白:等待bag播放结束后再执行
map_saver,且确保cartographer_occupancy_grid_node已收到完整子图。 - CPU占用过高:降低
optimize_every_n_nodes会显著增加计算量,若实时性不足可适当调回默认值。