1. 项目概述
最近在机器人定位导航项目中尝试使用Cartographer进行2D纯定位(Pure Localization)实验时,遇到了一些意料之外的坑。虽然Cartographer官方文档看起来相当完善,但在实际将ROS1环境下的示例迁移到ROS2(Humble)时,还是踩了不少雷。本文将详细记录整个实验过程,特别是那些官方文档没有明确说明的细节问题。
Cartographer作为Google开源的SLAM(同步定位与地图构建)系统,在机器人领域有着广泛应用。其纯定位模式特别适合在已有地图的情况下进行精准定位,比如仓储机器人、服务机器人等场景。不过官方示例主要基于ROS1,对于ROS2用户来说直接照搬会遇到各种兼容性问题。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 环境准备与数据获取
2.1 基础环境配置
我的实验环境如下:
- 操作系统:Ubuntu 22.04 LTS
- 虚拟化平台:VirtualBox 7.0
- ROS版本:ROS2 Humble
首先需要安装Cartographer相关的ROS2包:
bash复制sudo apt-get install ros-humble-cartographer \
ros-humble-cartographer-ros-msgs \
ros-humble-cartographer-ros \
ros-humble-cartographer-rviz
注意:很多教程会漏装cartographer-rviz,这会导致后续无法在RVIZ2中显示子地图(submaps)。
2.2 数据集准备
官方提供了两个背包2D扫描的示例数据集:
- b2-2016-04-05-14-44-52.bag (用于建图)
- b2-2016-04-27-12-31-41.bag (用于定位)
由于这些数据是ROS1格式的bag文件,需要转换为ROS2格式。我使用rosbags工具进行转换:
bash复制pip3 install rosbags>=0.9.11
rosbags-convert --src ~/Downloads/b2-2016-04-05-14-44-52.bag \
--dst ~/Downloads/b2-ros2-2016-04-05-14-44-52
rosbags-convert --src ~/Downloads/b2-2016-04-27-12-31-41.bag \
--dst ~/Downloads/b2-ros2-2016-04-27-12-31-41
转换完成后,目录结构应该是:
code复制~/Downloads/
├── b2-ros2-2016-04-05-14-44-52
│ ├── b2-ros2-2016-04-05-14-44-52.db3
│ └── metadata.yaml
└── b2-ros2-2016-04-27-12-31-41
├── b2-ros2-2016-04-27-12-31-41.db3
└── metadata.yaml
3. 建图与定位实验
3.1 离线建图过程
使用第一个数据集进行建图:
bash复制ros2 launch cartographer_ros offline_backpack_2d.launch.py \
bag_filenames:=$HOME/Downloads/b2-ros2-2016-04-05-14-44-52/b2-ros2-2016-04-05-14-44-52.db3
这个命令会运行较长时间,完成后会在原数据目录生成一个.pbstream文件,这就是我们构建的地图。建图结果如图1所示:

图1:使用第一个数据集构建的2D地图
3.2 纯定位实验
有了地图后,使用第二个数据集进行纯定位:
bash复制ros2 launch cartographer_ros demo_backpack_2d_localization.launch.py \
load_state_filename:=${HOME}/Downloads/b2-ros2-2016-04-05-14-44-52/b2-ros2-2016-04-05-14-44-52.db3.pbstream \
bag_filename:=${HOME}/Downloads/b2-ros2-2016-04-27-12-31-41/b2-ros2-2016-04-27-12-31-41.db3
定位过程中发现了一些匹配问题(图2-4),特别是在环境特征相似区域:

图2:定位初期出现的匹配偏差

图3:走廊区域的定位漂移

图4:定位最终收敛情况
4. 问题排查与解决方案
4.1 常见错误与修复
错误1:无法读取bag文件
code复制[rosbag2 storage] : No storage id specified, and no plugin found that could open URI
原因:直接使用了ROS1格式的bag文件
解决方案:必须先用rosbags-convert转换为ROS2格式
错误2:RVIZ2插件加载失败
code复制[rviz2: PluginlibFactory: The plugin for class 'cartographer viz/SubmapsDisplay' failed to load...
原因:缺少cartographer-rviz包
解决方案:安装ros-humble-cartographer-rviz
4.2 定位精度优化建议
-
调整定位参数:
在demo_backpack_2d_localization.launch.py中,可以调整以下关键参数:trajectory_builder_2d.submaps.num_range_data:控制子地图的更新频率pose_graph.constraint_builder.min_score:提高匹配阈值减少误匹配
-
地图预处理:
bash复制
cartographer_pbstream_to_ros_map \ -pbstream_filename=input.pbstream \ -map_filestem=output \ -resolution=0.05生成的地图可以用图像编辑工具清理噪声点
-
多传感器融合:
在实际应用中,建议结合IMU和里程计数据,在urdf文件中正确定义传感器坐标系关系
5. 深入原理与性能分析
5.1 Cartographer定位核心机制
Cartographer的纯定位模式实际上是其SLAM系统的一个特例。系统会:
- 持续将当前激光扫描与已有子地图进行匹配
- 使用分支定界算法(Branch-and-bound)快速寻找最优位姿
- 通过位姿图优化(Pose Graph Optimization)消除累积误差
在纯定位模式下,系统会冻结已有地图的位姿节点,只优化当前位姿,这大大减少了计算量。
5.2 定位漂移问题分析
实验中观察到的定位漂移主要源于:
- 环境相似性:长走廊等重复结构导致匹配歧义
- 动态障碍物:数据集中可能存在移动物体干扰
- 传感器噪声:低成本激光雷达的测距误差
解决方案对比:
| 方案 | 优点 | 缺点 |
|---|---|---|
| 增加约束 | 提高精度 | 可能增加计算负担 |
| 多传感器融合 | 更鲁棒 | 需要硬件支持 |
| 重检测机制 | 应对短暂丢失 | 实现复杂 |
6. 进阶应用与扩展
6.1 实际部署建议
-
地图分割策略:
对于大场景,建议按区域划分多个子地图,动态加载当前区域地图 -
内存优化:
lua复制POSE_GRAPH.optimize_every_n_nodes = 20 -- 减少优化频率 TRAJECTORY_BUILDER_2D.submaps.num_range_data = 30 -- 增大子地图尺寸 -
实时性调优:
- 使用
--ros-args --log-level warn减少日志输出 - 在
rclcpp中调整QoS策略,优先处理激光数据
- 使用
6.2 与其他系统集成
Cartographer可以很好地与Navigation2集成:
- 将定位结果发布到
/tf和/odom话题 - 通过
nav2_amcl兼容接口提供定位服务 - 使用
lifecycle_manager管理节点状态
典型集成架构:
code复制Cartographer Node → TF Tree → Navigation Stack
↓
Map Server (pbstream)
7. 实验心得与最佳实践
经过多次实验验证,总结出以下实用技巧:
-
数据预处理很重要:
- 使用
ros2 bag reindex修复可能损坏的bag文件 - 用
ros2 bag filter提取关键时间段数据
- 使用
-
参数调试方法论:
python复制# 系统化参数调整流程 for resolution in [0.05, 0.1, 0.2]: for num_laser_scans in [10, 20, 30]: test_localization_accuracy(...) -
可视化调试技巧:
- 在RVIZ2中同时显示
/submaps和/scan话题 - 使用
tf_tools检查坐标系对齐情况
- 在RVIZ2中同时显示
-
性能监控命令:
bash复制ros2 topic hz /scan # 监控数据频率 ros2 run cartographer_ros cartographer_occupancy_grid_node -pbstream_filename=map.pbstream -resolution=0.05
对于想要深入研究的开发者,建议从以下方向入手:
- 分析
.pbstream文件结构,理解内部数据表示 - 修改
pose_graph约束生成策略,适应特定场景 - 集成深度学习特征提取,提升环境识别能力
经过这次实验,我认为Cartographer在ROS2下的纯定位功能已经相当成熟,只要注意数据格式转换和参数调优,完全可以满足大多数室内机器人的定位需求。特别是在已知结构化环境中,定位精度和稳定性都令人满意。
