hdl_graph_slam是一套激光slam系统,可融合gps、imu、lidar三种传感器,同时具有闭环检测功能。开源代码地址为:

一、优缺点分析

通过实测和阅读代码,它有如下优缺点:
1. 优点

1)简洁的流程和代码结构。

激光slam虽然相对简单,但是目前开源的算法里,能够同时融合gps、imu、lidar三种传感器的还比较少。cartographer算是一种,但是相对于它来讲,hdl_graph_slam在资源消耗、代码复杂度、建图流程等方面还是有很大优势。

2)增加地面检测。

当所处的环境中地面为平面时,它就可以作为一个很有效的信息去约束高程的误差,而做过激光slam的都知道,在没有gps的情况下,高程误差是主要的误差项。当然在地面为非平面的时候是不能够使用的,但这不能作为它的缺点,而应该在使用时根据环境决定是否开启这项功能。

3)具有闭环检测功能

闭环检测是slam中的重要功能,不只在没有gps参考的情况下能减小累计误差,即便在有gps约束的情况下也能起到有效的作用,而这一点却是很容易被忽略的地方。很多人认为有了gps就可以不使用闭环修正了,而大量的实验结果表明,这是非常错误的想法。

2. 缺点

1)点云匹配精度不高。

这包括前端帧间匹配和闭环检测时的匹配,具体原因我们会在后面介绍到相应的代码时再讲。


二、功能分解

对整套系统的功能进行分解是为了能够更清晰的分析代码。这套系统的内部共包含四个主要功能项,所有的代码也是围绕着这四项功能展开的,它们分别是:

1. 地面平面检测

根据点云检测平面,并拟合平面得到平面的数学描述参数,供构建概率图使用。

2. 点云滤波

处理原始点云,得到稀疏点云

3. 前端里程计

帧间匹配,得到每一帧位姿

4. 后端概率图构建

这一项功能承担了整个系统中的大部分内容,它的主要功能又包括:

1)提取关键帧。

前端里程计得到的是每一帧位姿,而构建概率图只需要每隔一段距离取一帧就行,即关键帧。

2)读取gps、imu信息并加入概率图

即使用gps、imu信息构建对应的边。

3)读取地面检测参数并加入概率图。

同样是构建边,只不过信息变了。

4)检测闭环,若成功,则加入概率图。

同样是构建边。

三、代码结构

完成上面的功能分析,我们就好分析代码了,因为代码是围绕功能展开的,而且代码结构和功能对应的很好,很清晰。

我们看下工程目录中主要文件夹及其内容:

1. apps:节点文件

节点文件就是生成可执行文件的代码文件,相当于整个程序的入口。对应上面四项功能,它也就有了四个.cpp文件,分别是:

  • floor_detection_nodelet.cpp:地面平面检测
  • prefiltering_nodelet.cpp:点云滤波
  • scan_matching_odometry_nodelet.cpp:前端里程计
  • hdl_graph_slam_nodelet.cpp:后端概率图构建

2. include:头文件

头文件又包含两个文件夹:

1)g2o

定义了各信息源对应的g2o中的边。因为很多信息在g2o中没有对应的边,需要自己定义。

具体定义了哪些边,我们会在后面详细介绍。

2)hdl_graph_slam

全部四项功能都在这个文件夹中,它包含以下文件:

  • graph_slam.hpp:管理graph,即负责对概率图添加顶点和边。
  • information_matrix_calculator:计算信息矩阵,信息矩阵即是概率图中边的权重。
  • keyframe_updater:检测关键帧
  • keyframe:关键帧对应的结构
  • loop_detector:检测闭环
  • map_cloud_generator:生成地图点云,即是拼接地图
  • nmea_sentence_parser:处理gps信息,从nmea报文得到经纬高数据
  • registrations:设置点云匹配方法(程序中给了多种方法供选择,此处是指定选择哪一种)
  • ros_time_hash:管理rostime的小工具函数
  • ros_utils:各类位姿矩阵表示形式之间转换的工具函数

3. src:源文件

它包含的所有cpp文件在include中都有对应的头文件,而他们的功能在include中已经介绍过了,所以我们不在此列出了,详细内容后面的文章会介绍。