ORB_SLAM2代码阅读(4)——LoopClosing线程
1.说明
在前几篇博客介绍完tracking和localmaping线程后,本文接着介绍闭环检测(LoopClosing)线程中的内容。该部分内容中有很多细节部分还没有弄清楚,暂时先将整体思路捋顺,更多细节内容以后再补充。
2.简介
LoopClosing线程整体思路比较简介清晰,主要分为三大部分:检测回环、计算Sim3和回环校正。该线程的入口为Run()
函数(相当于主函数)。
首先从流程图中看看LoopClosing线程的整体逻辑(该流程图对应Run()
函数中的内容):
其中较为重要的变量有:
变量名 | 变量类型 | 说明 |
---|---|---|
mpCurrentKF | KeyFrame* | 当前关键帧 |
mpMatchedKF | KeyFrame* | 匹配关键帧 |
mvConsistentGroups | vector< ConsistentGroup > | 所有的连续关键帧组集 |
mvpEnoughConsistentCandidates | vector<KeyFrame*> | 充分连接的候选关键帧组 |
mlpLoopKeyFrameQueue | list<KeyFrame*> | 待回环检测的关键帧队列 |
接下来,分别介绍检测回环、计算Sim3和回环校正三部分内容。
3.检测回环
检测回环部分对应代码中的bool LoopClosing::DetectLoop()
函数,该函数整体逻辑较为清晰,但是一致性检测部分有点不好理解,并且相关资料较少。有些内容是我自己的理解,正确性有待商榷。
检测回环的主要思想:
- 在关键帧队列中提取队首元素作为当前关键帧。关键帧队列中的元素是局部建图线程添加的。
- 获取当前关键帧的共视关键帧,并计算当前关键帧与每个共视关键帧之间的BOW向量得分,记录最小得分minScore。
- 根据最小得分minScore在关键帧数据库mpKeyFrameDB中查找当前关键帧的回环候选关键帧vpCandidateKFs。
- 对每个候选关键帧进行一致性检测。
- 经过一致性检测后,如果存在充分连接的候选关键帧,则证明检测到了回环;否则,回环检测失败。
该过程的具体流程如下图所示:
对于计算最小得分和获取候选回环关键帧等操作并不难理解,根据最小得分查找候选回环关键帧的原理以后在进行介绍。这里主要说一下一致性检测的原理。
一致性检测部分是检测回环的关键,光看代码的话有点难理解,而且网上关于这部分介绍的也不多。接下来的内容是我自己的理解,可能不完全正确,姑且述之。
先说一下该部分涉及的变量。
变量名 | 变量类型 | 说明 |
---|---|---|
vpCandidateKFs | vector<KeyFrame*> | 候选回环关键帧向量 |
pCandidateKF | KeyFrame* | 当前候选关键帧 |
spCandidateGroup | set<KeyFrame*> | 候选关键帧的共视关键帧以及候选关键帧构成了"子候选组"——当前子候选组 |
vCurrentConsistentGroups | vector<ConsistentGroup | 当前连续关键帧组构成的向量 |
mvConsistentGroups | vector<ConsistentGroup | 由当前关键帧的前一关键帧确定的子连续组向量 |
mvpEnoughConsistentCandidates | vector<KeyFrame*> | 充分连接的候选关键帧组成的向量 |
nCurrentConsistency | int | 用于记录当前子候选组的一致性 |
一致性检测的过程:
- 在候选关键帧向量中选取一个候选关键帧pCandidateKF,将候选关键帧的共视关键帧和候选关键帧组成当前子候选组spCandidateGroup。
- 遍历
mvConsistentGroups
中的子连续组。如果mvConsistentGroups
中的子连续组sPreviousGroup
包含当前子候选组中的关键帧,则说明该子连续组sPreviousGroup
与当前子候选组是相连的。 - 如果当前子候选组与之前的子连续组是相连的,则将当前子候选组添加到
vCurre