ORB_SLAM2 中包含三个并行的线程:
tracking线程
LocalMapping线程
LoopClosing线程
首先记录几个标志位:
mbStopRequested:外部线程调用,为true,表示外部线程请求停止LocalMapping线程。
mbStopped:为true表示可以并终止LocalMapping线程。
mbNotStopped:true表示不要停止LocalMapping线程,因为要插入关键帧了,需要和mbStopped结合使用。
mbAcceptKeyFrame:true表示允许接受关键帧,tracking和LocalMapping线程之间的调度。
mbAbortBA:是否中止BA优化的标志位。
mbFinishRequested:请求中止当前线程的标志,注意知识请求,不一定中止,中止要要mbFinished。
mbResetRequested:请求当前线程复位的标志,true表示一直请求复位,但复位还未完成;表示复位完成为false。
mbFinished:判断最终LocalMapping::Run()是否完成标志。
接下来详细介绍各个线程过程中的运用标志位进行调度:单目
tracking线程
因为tracking线程在主函数中,所以我按照代码的流程,来讲解一下,里面的线程调度并不多
tracking线程运行在主线程中:
(1)main()函数:
- 加载图像
- 创建SLAM系统
- TrackMonocular()函数
(2)通过GrabImageMonocular()函数进入tracking线程;
(3)track()讲解三种跟踪模式:
TrackReferenceKeyFrame():参考关键帧跟踪模式
TrackWithMotionModel():恒速模型跟踪模式
Relocalization():重定位跟踪模式
(4)TrackLocalMap():对(3)中得到的位姿进一步优化;
(5)上述过程成功运行,接下来就是判断是否将当前帧作为关键帧插入关键帧队列:
- 若为纯跟踪模式mbOnlyTracking,则不需要插入关键帧;
- 如果mdStopped=true,即LocalMapping线程被终止,则不需要插入关键帧;
- 如果LocalMapping线程被LoopClosing线程请求中止,即mbStopRequested=true,则不需要插入关键帧;
- 当上述条件均没有,则需要插入关键帧,接下来代码,就是常规判断当前帧是都满足是关键帧的条件,这里不讲了。。。
(6)将关键帧插入关键帧序列,并将:
mbAbortBA=true
mbNotStop=false
LocalMapping线程
(1)首先需要设置mbFinished=false 表示当前线程正在运行并为结束;
(2)然后需要设置 mbAcceptKeyFrame=false ,目的:告诉tracking线程,LocalMapping线程正在繁忙状态,不要再往关键帧队列中插入关键帧了;
(3)接下来就是对关键帧队列中的关键帧进行操作;
(4)处理完成后,进行局部的BA优化,将标志位设置为:mbAbortBA=false;
(5)在进行局部BA优化之前,需要检查标志位mbStopRequested的状态:
mbStopRequested=true,说明LoopClosing线程请求中止LocalMapping线程,则不能继续进行BA优化;
mbStopRequested=false,说明LoopClosing线程并没有请求中止LocalMapping线程,继续进行局部BA优化;
(6)进行完上述的过程,最后将mbAcceptKeyFrame=true,表示可以接受tracking线程的关键帧了。
(7)上述过程都在while(1)主循环中进行的。最后检查当前线程是否结束,若结束,设置
mbFinished=true
mbStopped=true
LoopClosing线程
(1)首先需要设置mbFinished=false 表示当前线程正在运行并为结束;
(2)主要有三个函数:
DetectLoop():检测回环
ComputeSim3():计算相似变换
CorrectLoop():闭环矫正
(3)在CorrectLoop()中,需要
a.先请求LocalMapping线程中止运行,即mbStopRequested=true,目的是防止在闭环矫正的时候LocalMapping线程中的InsertKeyFrame函数插入新的关键帧(在LocalMapping代码中可以看到);
b.还需要判断全局BA优化是否在运行,如果运行免责终止掉,即mbStopBA=true;
c.还需要判断局部线程是否结束,即标志位:mbStopped=true/false,若为true,则进行闭环矫正,若为false,则等待。
(4)当整个LoopClosing线程结束,将mbStopRequested=false,此时LocalMapping线程就可以正常运行了。