Cartographer源码篇:源码分析(1)

在安装编译cartographer-1.0.0的时候,我们可以看到代码主要包括cartorgarpher_ros、cartographer、ceres-sover三个部分。其中,ceres-solver用于非线性优化,求解最小二乘问题;cartographer_ros为ROS平台的封装,获取传感器数据,显示和保存处理结果;cartographer为算法的底层实现,处理传感器数据,构建地图。作为ROS平台的封装,cartographer_ros没做实质性的工作,但是其充当了cartographer程序的守门人的角色,包含通往cartographer的钥匙,故本次先针对cartographer_ros作一个简单快速的分析。

cartographer_ros文件结构

首先看下cartographer_ros的文件结构,如下图所示:

Cartographer源码篇:源码分析(1)Cartographer源码篇:源码分析(1)
cartographer_ros目录

然后我们具体分析下各目录的内容:

cartographer_ros_msgs:部分msg、srv文件;

cartographer_rviz:与rviz显示相关的文件;

cartographer_ros/cartographer_ros:基于ROS实现的主要程序,包含各节点的实现文件,入口节点cartographer_node的实现文件node_mian.cc就在这里;

Cartographer源码篇:源码分析(1)
configuration_files目录

cartographer_ros/configuration_files:参数配置文件,包括机器人参数、建图参数、定位参数、文件保存参数等;

Cartographer源码篇:源码分析(1)
launch目录

cartographer_ros/launch:节点启动文件,包括机器人、建图、定位、文件保存等节点;

cartographer_ros节点关系

通过实际运行,分析一下ros节点的情况:

Cartographer源码篇:源码分析(1)
cartographer_ros节点图

cartographer_node

cartographer_ros的主节点,主要负责订阅传感器数据、发布显示数据。

occupancy_grid_node

主要负责订阅子图与发布栅格地图。

pbstream_map_publisher

主要负责发布地图文件。

offline_node

主要用于离线运行的节点,功能类似cartographer_node节点。

cartographer_ros代码结构

正如前面说的那样,cartographer_ros主要有两部分功能:

1.订阅传感器数据与结果展示;

2.cartographer api的ros封装;

故针对cartographer_ros,我们主要作简单的梳理,将大部分的时间放到以后对cartographer算法底层的研究,代码流程如图所示:

原图: https://github.com/yinqijun/img/blob/master/20200721205145.png

Cartographer源码篇:源码分析(1)
cartographer_ros代码结构

简单说明一下,蓝线是cartographer_ros的主流程,紫线是新建轨迹的流程,绿线是结束轨迹、优化的流程,黑线是发布显示所需数据的流程。黑色填充的文件在cartographer_ros目录下的,绿色与紫色填充的文件在cartographer目录下。

沿着每个流程去理代码,一层层剥开封装,最后发现都是通过map_builder_bridgesensor_bridge进入cartographer目录下,去做实质的数据处理、建图的底层工作。给人一种感觉,就是看完cartographer_ros发现还没看到真正的程序,全是花里胡哨的层层封装以及C++的高级用法,也给阅读源码的新手很大的压力。但是,作为一个产品级的源码,还是可以从背后多琢磨一下谷歌工程师的意图,这就是仁者见仁智者见智的事情了。总之,从全局结构去看,cartographer_ros的代码结构就是这样啦。

接下来,具体看一下主程序的流程:

Cartographer源码篇:源码分析(1)
node_main.cc
  1. 通过launch文件启动节点

    Cartographer源码篇:源码分析(1)Cartographer源码篇:源码分析(1)
    backpack_3d.launch & backpack_3d.lua

    backpack_3d.launch为例,主要做了以下工作:

    启动cartographer_node、cartographer_occupancy_grid_node节点;

    导入.urdf文件、.lua配置文件路径;

    其中,.urdf文件定义了机器人的坐标变换,.lua文件定义了建图算法的配置,包括传感器的种类、采样率、发布频率,以及位姿优化的参数等。

  2. 订阅tf,使用.lua配置cartographer算法参数、ros订阅发布参数

  3. 定时发布submap/trajectory/landmark_pose/constraint/scan_matched_point_cloud

  4. 新建轨迹

    代码流程:AddTrajectory()\rightarrowAddExtrapolator() + AddSensorSampler() + LaunchSubscriber()\rightarrowHandle…Message()

    文件流程:node_main.cc\rightarrownode.cc\rightarrowmap_builder_bridge\rightarrow{map_builder_interface.h(cartographer) + sensor_bridge\rightarrowtrajectory_builder_interface.h(cartographer)}

  5. 结束轨迹

  6. 优化

  7. 保存


参考资料:

[1]. Cartographer ROS Integration