ORB SLAM2源码解读(一):系统流程

代码解读主要是自己梳理代码过程中的记录,和网上各位大神的解读水平比不了。

ORB SLAM的大名和介绍就不需要在这里多介绍了,直接进入代码解读环节吧。

一、系统代码结构

ORB SLAM的代码结构非常清晰,直接看下面这张图就可以

这张图里可以看出orb一共有三个线程,分别负责跟踪(TRACKING)、局部建图(LOCAL MAPPING)和闭环(LOOP CLOSING)功能,同时又增加了重定位(PLACE RECOGNITION)功能。

二、 系统流程

系统流程的入口在system.cc文件中,这个文件中一共有四个函数:

1) System

2) TrackStereo

3) TrackRGBD

4) TrackMonocular

其中System是SLAM系统的构造函数,包括所有功能模块和所有线程的初始化,而TrackStereo、TrackRGBD和TrackMonocular分别是双目、RGBD和单目的数据入口,使用过程中,先调用System函数生成SLAM系统的对象,然后根据传感器类型,调用相应的入口函数,就可以执行SLAM的流程了。

下面对各个函数分别做介绍

1. 构造函数(System)

先上一张图,看一下构造函数内部的内容

构造函数中和流程相关的一共有四个参数,分别是

1) strVocFile: ORB词袋数据。词袋是在做闭环检测和重定位时候做检索用的,从历史关键帧中检索出和当前帧最相似的一帧,以进行位姿匹配。

2) strSettingsFile: 配置文件的路径。配置文件中存放了相机参数和用户显示界面的设置

3) sensor: 传感器类型,这是一个枚举变量,一共有三种,分别是MONOCULAR、STEREO和RGBD,分别代表单目、双目和RGBD。

4) bUseViewer: true代表启动显示界面,false代表不显示

构造函数中一共初始化了以下内容:

1) 初始化词袋模型

mpVocabulary = new ORBVocabulary(); //初始化词袋对象
mpVocabulary->loadFromTextFile(strVocFile); //从词袋数据文件中读取数据

词袋是在做闭环检测和重定位时候做检索用的,从历史关键帧中检索出和当前帧最相似的一帧,以进行位姿匹配。关于词袋更详细的解释,可以参考文章:

2) 初始化关键帧数据集

mpKeyFrameDatabase = new KeyFrameDatabase(*mpVocabulary); //使用词袋数据创建数据集对象

如果此处只是加载数据就没意思了,前面提到,这个数据主要用来做闭环检测和重定位,所以这个模块除了加载数据以外,还实现了闭环检测和重定位检测。对应的函数分别是

DetectLoopCandidates(KeyFrame* pKF, float minScore) //检测闭环向量
DetectRelocalizationCandidates(Frame *F) //检测重定位向量

这两个函数内部的内容会在讲解闭环模块时再详细讲解。

3) 初始化地图

mpMap = new Map();

地图中主要存放关键帧和特征点。

4) 初始化用户显示界面,并打开对应的线程

mpFrameDrawer = new FrameDrawer(mpMap);  //画关键帧
mpMapDrawer = new MapDrawer(mpMap, strSettingsFile); //画地图
if (bUseViewer) { //根据标志位判断是否需要显示
 mpViewer = new Viewer(this, mpFrameDrawer,mpMapDrawer,mpTracker,strSettingsFile); //显示界面
 mptViewer = new thread(&Viewer::Run, mpViewer);
 mpTracker->SetViewer(mpViewer); //打开显示对应的线程
}

5) 初始化局部地图,并打开对应的线程

mpLocalMapper = new LocalMapping(mpMap, mSensor==MONOCULAR); //初始化局部地图
mptLocalMapping = new thread(&ORB_SLAM2::LocalMapping::Run,mpLocalMapper); //打开局部地图对应的线程

6) 初始化闭环流程,并打开对应的线程

mpLoopCloser = new LoopClosing(mpMap, mpKeyFrameDatabase, mpVocabulary, mSensor!=MONOCULAR); //初始化闭环检测
mptLoopClosing = new thread(&ORB_SLAM2::LoopClosing::Run, mpLoopCloser); //打开对应的线程

7) 给各个线程之间建立关联

mpTracker->SetLocalMapper(mpLocalMapper);
mpTracker->SetLoopClosing(mpLoopCloser);

mpLocalMapper->SetTracker(mpTracker);
mpLocalMapper->SetLoopCloser(mpLoopCloser);

mpLoopCloser->SetTracker(mpTracker);
mpLoopCloser->SetLocalMapper(mpLocalMapper);

2. 双目相机入口(TrackStereo)

该函数主要功能和流程列在下图中

从途中可以看出,每次输入数据以后,会执行三种操作:

1) 判断是否需要进入或者退出纯定位模式,如果需要则执行

2) 判断是否需要重启tracking,如果需要则执行

3) 执行双目的跟踪程序。GrabImageStereo共有三个参数,分别是左目、右目和时间戳

3. RGBD相机入口(TrackRGBD)

整体流程和双目一样,唯一的区别是此处调用的入口是RGB函数的入口,它的三个参数分别是像素图、深度图和时间戳

4. 单目相机入口(TrackMonocular)

整体流程仍然和双目一样,区别是入口变成了单目的入口,它的两个参数分别是像素图和时间戳。