3. 单线激光雷达数据接入 Cartographer
任务目标
本案例以Cartographer官方2D示例配置为基础,解读backpack_2d.lua及其引用的map_builder.lua、trajectory_builder_2d.lua中与建图质量最相关的参数,并实际修改栅格分辨率与子图更新频率,通过重新建图对比效果差异。
配置结构与关键参数
Cartographer的配置采用Lua脚本,分为三层:
- map_builder.lua:全局地图构建器配置(是否使用2D/3D、是否启用回环检测)
- trajectory_builder_2d.lua:前端扫描匹配与运动滤波参数
- 具体机器人配置(如backpack_2d.lua):调用上述模板并覆盖参数,同时设置地图帧、发布频率等
以下为官方backpack_2d.lua的完整内容,标注了本案例将修改的两个关键参数:
-- backpack_2d.lua(完整文件)
include "map_builder.lua"
include "trajectory_builder_2d.lua"
options = {
map_builder = MAP_BUILDER,
trajectory_builder = TRAJECTORY_BUILDER_2D,
map_frame = "map",
tracking_frame = "base_link",
published_frame = "base_link",
odom_frame = "odom",
provide_odom_frame = true,
publish_frame_projected_to_2d = false,
use_odometry = false,
use_nav_sat = false,
use_landmarks = 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, -- ★ 子图发布周期(秒),影响RViz中子图刷新频率
pose_publish_period_sec = 5e-3,
trajectory_publish_period_sec = 30e-3,
rangefinder_sampling_ratio = 1.,
odometry_sampling_ratio = 1.,
fixed_frame_pose_sampling_ratio = 1.,
imu_sampling_ratio = 1.,
use_constant_odometry_variance = false,
constant_odometry_variance = 1e-4,
}
TRAJECTORY_BUILDER_2D.use_imu_data = false
TRAJECTORY_BUILDER_2D.min_range = 0.3
TRAJECTORY_BUILDER_2D.max_range = 30.
TRAJECTORY_BUILDER_2D.missing_data_ray_length = 5.
TRAJECTORY_BUILDER_2D.use_online_correlative_scan_matching = true
TRAJECTORY_BUILDER_2D.motion_filter.max_angle_radians = math.rad(0.1)
TRAJECTORY_BUILDER_2D.motion_filter.max_distance_m = 0.15
MAP_BUILDER.use_trajectory_builder_2d = true
MAP_BUILDER.num_background_threads = 4
MAP_BUILDER.pose_graph.optimize_every_n_nodes = 90
-- ★ 关键修改1:栅格分辨率(米/像素),默认0.05,改为0.10观察地图变粗糙
MAP_BUILDER.map_builder_2d.submaps.resolution = 0.10
-- ★ 关键修改2:子图插入频率(每N帧激光数据插入一次子图),默认1,改为5降低更新频率
MAP_BUILDER.map_builder_2d.submaps.num_range_data = 5
return options
参数含义与调整方法
| 参数路径 | 默认值 | 作用 | 调整方向与预期效果 |
|---|---|---|---|
MAP_BUILDER.map_builder_2d.submaps.resolution | 0.05 | 每个栅格像素代表的物理尺寸(米)。决定地图精细度与内存占用 | 增大到0.10:地图变粗糙、细节丢失,但建图计算量下降、内存占用减少 |
MAP_BUILDER.map_builder_2d.submaps.num_range_data | 1 | 累积多少帧激光数据后插入一次子图(即子图更新频率) | 增大到5:子图更新变慢,局部地图刷新频率降低,但前端计算压力减小 |
submap_publish_period_sec | 0.3 | RViz中已完成的子图发布间隔(秒) | 仅影响可视化刷新率,不影响建图算法本身 |
运行与对比验证
使用官方2D示例数据集(cartographer_paper_deutsches_museum.bag)进行验证:
# 1. 启动离线建图(默认配置)
roslaunch cartographer_ros demo_backpack_2d.launch bag_filename:=/path/to/cartographer_paper_deutsches_museum.bag
# 2. 修改配置后重新建图
# 编辑 backpack_2d.lua 中的 resolution 和 num_range_data 后,重新执行上述命令
对比方法:分别用默认参数与修改后参数运行建图,保存生成的PGM地图文件,观察:
- 分辨率0.05→0.10:地图中墙体边缘出现明显锯齿/方块感,窄通道可能断裂,走廊宽度失真
- num_range_data 1→5:在RViz中观察子图(绿色方块)出现频率降低,回环检测修正时地图跳变幅度增大
通过条件:
- 修改参数后Cartographer能正常启动且不报配置错误
- 生成的地图文件尺寸随分辨率变化(0.10分辨率地图像素尺寸约为0.05时的1/2)
- 肉眼可分辨两种参数下地图细节的明显差异
常见问题
- 修改后无法启动:检查Lua语法,注意
math.rad()需要完整写法;确认修改的是MAP_BUILDER.map_builder_2d.submaps下的字段而非其他层级 - 地图出现重影:
num_range_data调大后子图插入间隔变长,若机器人转弯过快可能导致局部地图匹配漂移,此时应配合增大motion_filter.max_distance_m - 分辨率调大后内存反而不足:确认是否同时调整了
MAP_BUILDER.map_builder_2d.submaps.resolution与num_range_data,两者共同决定内存占用,分辨率增大时建议同步增大num_range_data以控制子图数量