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_score0.55提高至0.7回环约束更严格,减少误匹配,但可能漏检回环
optimize_every_n_nodes90降低至30后端优化更频繁,地图更一致,但CPU占用升高
translation_weight1.0提高至5.0更信任激光匹配的平移约束,直线走廊更平直
use_imu_datatrue改为false失去IMU姿态预测,快速旋转时地图易出现漂移

验证方法与判定标准

  1. 运行验证:执行上述三个终端命令后,在Rviz中订阅 /map 话题,应能看到栅格地图随bag播放逐步构建;bag播放结束后地图不再更新。
  2. 地图保存:bag播放完毕后,在终端3执行 map_saver,当前目录生成 my_map.pgm 与 my_map.yaml,说明建图流程闭环成功。
  3. 质量对比:用图像查看器打开不同参数下生成的 .pgm 文件,观察以下指标:
    • 墙体是否连续、无重影或错位;
    • 直线走廊是否平直,转角是否为直角;
    • 回环闭合处是否对齐(无双重墙壁);
    • 地图整体是否存在漂移导致的模糊区域。
  4. 通过条件:默认参数下地图无明显断裂或错位;调高 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 会显著增加计算量,若实时性不足可适当调回默认值。