SLAM---A-LOAM学习笔记---源代码分析1--ROS通讯结构思维导图

790 阅读4分钟

A-LOAM学习笔记---源代码分析1--ROS通讯结构思维导图

此文章是笔者在SLAM学习过程中的知识总结,文中若出现笔者尚未意识到的错误,请读者批评指正!

前言

相信很多像笔者一样的小白,在学习SLAM过程中总是会对其复杂的知识体系充满疑惑,每当解决完一个问题会发现还会有无数个问题排在路上。学习SLAM的过程就像是游戏中升级打怪,SLAM所需的各个知识就像是技能点,我们努力从各个方面扩充知识加点技能,但当遇到像A-LOAM这样完整的SLAM算法时,才发现前面所学似乎像一盘散沙,每个技能看似会用了,实则却没能串联在一起,无法打出一套组合拳,在SLAM算法这个终极boss面前,依然是只可远观。笔者以此文章来记录A-LOAM的学习过程,对错综复杂的算法结构进行梳理,希望能对初学者在A-LOAM学习过程中提供一点帮助,更方便的理清思路。

A-LOAM代码框架

A-LOAM源代码的src文件夹中包含有如下5个文件:

  • kittiHelper.cpp --------------------- 将kitti数据集转为rosbag文件
  • scanRegistration.cpp ------------ 前端lidar点云预处理及特征点提取
  • laserOdometry.cpp -------------- 前端激光里程计
  • laserMapping.cpp ---------------- 后端当前帧到地图的优化
  • lidarFactor.hpp -------------------- Ceres Solver非线性优化结构体

其中算法的核心部分主要集中在scanRegistration.cpp、laserOdometry.cpp、laserMapping.cpp这三个文件中,下文将从这三部分的ROS通讯结构进行梳理。

ROS通讯结构总体思维导图

思维导图阅读说明

为了方便读者理解思维导图所写内容,笔者进行了如下注释:

演示文稿1_022.png

演示文稿1_011.png

总体思维导图

后文中分成了三部分对A-LOAM的ROS通讯结构进行了详细描述:

scanRegistration.cpp

laserOdometry.cpp

laserMapping.cpp

总体.png

scanRegistration.cpp

scanRegistration.cpp.png

图中①:通过订阅"/velodyne_points"话题,将激光雷达的原始数据传输到A-LOAM中,并通过回调函数laserCloudHandler对原始点云数据进行处理,此回调函数主要操作是,通过计算点的曲率提取出特征点,将其分为角点、弱角点、面点和弱面点。

图中②:将点云中的全部点,其中包括特征点和未被提取的非特征点,保存到*laserCloud,转换到ROS数据类型后,通过"/velodyne_cloud_2" 话题发布。

图中③ ④ ⑤ ⑥:将提取出的角点、弱角点、面点和弱面点,分别保存到cornerPointsSharp、cornerPointsLessSharp、surfPointsFlat和surfPointsLessFlat,转换到ROS数据类型后,通过对应的话题发布。

laserOdometry.cpp

laserOdometry.cpp.png

图中①:通过订阅"/velodyne_cloud_2"话题,将scanRegistration.cpp发布的所有点的数据,传递到回调函数laserCloudFullResHandler中,此回调函数是将数据保存到fullPointsBuf队列中。

图中② ③ ④ ⑤ :与①同理,通过订阅对应的话题,将角点、弱角点、面点和弱面点的数据,传递到回调函数,保存到各自的队列中,cornerSharpBuf、cornerLessSharpBuf、surfFlatBuf和surfLessFlatBuf。

图中⑥:通过"/velodyne_cloud_3"话题发布所有点,此处通过skipFrameNum控制发布频率。

图中⑦ ⑧:将②中cornerSharpBuf的角点数据取出,遍历角点,进行点云去畸变,与上一帧的角点进行K近邻搜索,找到两个近邻点,通过Ceres Solver求解非线性优化,完成角点的帧间匹配;面点帧间匹配与角点类似,但匹配的计算方法有所不同,具体请看A-LOAM源代码,此处不再赘述。最后把进行了帧间匹配的角点和面点,分别保存到laserCloudCornerLast和laserCloudSurfLast中,转换数据类型后发布,与⑥发布频率相同。

图中⑨ ⑩:发布前端激光里程计位姿和path。

laserMapping.cpp

laserMapping.cpp.png

图中① ② ③:通过订阅话题"/velodyne_cloud_3"、"/laser_cloud_corner_last"和"/laser_cloud_surf_last",将所有点、角点和面点,传入对应的回调函数laserCloudFullResHandler、laserCloudCornerLastHandler和laserCloudSurfLastHandler,此处三个回调函数的作用都是将点云数据保存到队列中。

图中④ :通过订阅"/laser_odom_to_init"话题,将前端激光里程计位姿传入回调函数laserOdometryHandler,此处先将数据保存到odometryBuf队列中,再将激光里程计坐标系位姿转化为地图坐标系位姿,并通过⑨发布。

图中⑤ ⑥:进行点云地图发布,⑤通过"/laser_cloud_surround"话题发布局部地图,频率为每处理5帧发布一次;⑥通过"/laser_cloud_map"话题发布全局地图,此全局地图是21x21x11栅格内的地图,频率为每处理20帧发布一次。

图中⑧ ⑩:发布建图后的里程计和path。

jing.png