在cartographer中使用
启动定位程序:
roslaunch cartographer_ros demo_backpack_2d_localization.launch bag_filename:=${HOME}/Downloads/cartographer_paper_deutsches_museum.bag
会启动cartographer的纯定位
对纯定位会覆盖原来地图原因分析:
采用Cartographer进行纯定位模式会出现新地图覆盖先验地图的问题,原因是Cartographer在进行纯定位的时候会进行子图建立,也是一个建图的过程,将建立的子图与先验地图进行匹配来得到机器人的位置信息的,所以会覆盖先验地图很正常,要解决这个问题也很简单。
首先在启动定位的launch文件之后查看以下自己的话题rostopic list;
不出意外会有一个/map的话题,使用rostopic info /map命令去查看它的订阅和发布,它的发布者应该是Cartographer的cartographer_occupancy_grid_node,它同时会订阅submap_list。
总结以下,cartographer_occupancy_grid_node这个节点的订阅里面有submap_list,发布有map,因为submap_list是会改变的,所以map也会改变,那么解决方法就是,map的发布给注释了,也就是注释cartographer_occupancy_grid_node,那么另一个问题又来了,的确不会出现覆盖的情况了,但我原本的先验地图也没有了,我仍然需要发布map这个topic,可以采用map_server这个包来发布。
虽然在纯定位的时候会进行再建图,但是完全不影响对原地图的定位!!!
主要改进实现是将cartographer_occupancy_grid_node替换为map_sever
<node name="map_server" pkg="map_server" type="map_server" args="你的地图绝对路径/地图文件名.yaml" />
步骤1:
原来的demo_backpack_2d_localization.launch改进删除掉cartographer_occupancy_grid_node
改进后的launch
改进后运行纯定位命令,将submaps的Trajectory1的沟去掉(有点掩耳盗铃的意思),就发现不影响原来的地图了,但实际上cartographer是自己启动建图程序的,但是不影响定位!
可以这么理解:cartographer没有真正意义上的纯定位,只是启动建图程序来进行定位!
附录:
其中的地图保存命令:
将cartographer保存为pbstream地图文件
使用下面两个来保存地图 (使用之前记得source一下setup.bash):
rosservice call /finish_trajectory 0
rosservice call /write_state "{filename: '${HOME}/Downloads/b3-2016-04-05-14-14-00.bag.pbstream', include_unfinished_submaps: "true"}"
转换pdstream地图为pgm yaml格式:
rosrun cartographer_ros cartographer_pbstream_to_ros_map -map_filestem=${HOME}/Downloads/mymap -pbstream_filename=${HOME}/Downloads/bbb.pbstream -resolution=0.05
launch文件每个节点的理解:
一: cartographer_node节点作用:
1. 订阅传感器数据:
-
从话题
/scan
接收 激光雷达数据(通过 remap) -
从话题
/imu/data
接收 IMU 数据(如果启用了 use_imu_data)
✅ 2. 调用 SLAM 算法:
-
使用你在
my_lidar.lua
文件中配置的算法参数 -
实时构建地图,估计机器人位姿
✅ 3. 发布结果:
1:发布机器人当前位姿(如 /tf
):输出map
→ odom
,表示从全局地图参考系到机器人里程计参考系的校正(修正累计误差),通常是 Cartographer 里的后端优化器发布这个变换,保持地图和里程计之间的对齐
2:输出子图(submap),用于可视化建图过程
3:若配合 cartographer_occupancy_grid_node
,还能生成占据栅格地图 /map
二: cartographer_occupancy_grid_node节点的作用:
-
它订阅 Cartographer 主节点生成的 submaps(局部子地图),
-
把这些局部子地图整合成一张连续的全局占据栅格地图,
-
并通过
/map
话题实时发布,方便导航栈(如move_base
)使用。