ORB_SLAM2代码阅读(3)——LocalMapping线程

1.说明

本文介绍ORB_SLAM2中的LocalMapping线程。相对而言,LoaclMapping线程要比tracking线程简练整洁一些。整体思路比较清晰,没有那么多情况需要讨论。该部分内容中有很多细节部分还没有弄清楚,暂时先将整体思路捋顺,更多细节内容以后再补充。

2.简介

在学习ORB_SLAM2系统的过程中,我们需要紧紧抓住两样东西:帧(关键帧)和地图点,只要把握好这两样东西,就很容易理清整个系统的脉络。而在LoaclMapping线程中,大部分都是对地图点进行处理,只有少部分内容是处理关键帧。

先来看一下LoaclMapping线程的主要思路

  1. 检测在队列中是否存在新的关键帧,如果存在进行局部地图构建。
  2. 处理关键帧。在该过程中,计算关键帧特征点的BoW映射,将关键帧插入地图。
  3. 剔除冗余地图点。该部分内容遍历当前关键帧的所有地图点,对于不满足条件的地图点将其剔除。
  4. 添加新的地图点。相机运动过程中与相邻关键帧可以通过三角化恢复出一些MapPoints。
  5. 如果当前关键帧是关键帧队列中的最后一帧,则进行局部BA,然后剔除冗余关键帧。
  6. 将关键帧加入到回环检测线程。

具体流程如下图:
在这里插入图片描述
接下来,从 处理关键帧地图点剔除创建新的地图点局部搜索剔除多余关键帧这5部分分别展开介绍。

3.处理关键帧

处理关键帧这部分内容相当于局部建图线程中的第一步,该步骤主要的操作是:

  1. 从缓冲队列中取出一帧关键帧 。
  2. 计算该关键帧特征点的Bow向量。
  3. tracking线程中局部地图跟踪过程中新匹配上的MapPoints和当前关键帧绑定。
  4. 更新关键帧间的连接关系。
  5. 将该关键帧插入到地图中。

在处理关键帧过程中,有一个问题需要搞清楚(我自己开始理解的不清楚,导致这个问题想了很久)。这个问题是:在获取当前关键帧的地图点之后,为什么还要判断地图点是否在当前关键帧中?

要弄清这个问题还要从tracking线程中的局部地图跟踪过程说起。局部地图跟踪过程中首先将能够观测到当前帧地图点的关键帧及这些关键帧的共视关键帧和父子关键帧作为局部地图跟踪过程中的关键帧,然后将这些关键帧的所有地图点作为局部地图跟踪过程中的地图点。有了关键帧和地图点之后,需要将这些地图点与当前帧的地图点进行投影匹配,然后进行当前帧的位姿优化。这是局部地图跟踪的大致过程。由于局部地图(此处的局部地图是tracking线程中的局部地图)中的地图点与当前帧的地图点进行了投影匹配。所有可以认为当前帧的匹配地图点分为两部分:当前帧自己生成的地图点非当前帧(局部地图中其他关键帧)生成的地图点。而非当前帧生成的地图点未与当前帧进行关联,所以在局部建图线程的关键帧处理部分需要为这些非当前帧(局部地图中其他关键帧)生成的地图点更新属性。

4. 地图点剔除

地图点剔除过程是指剔除局部地图中的某些不合乎要求的地图点。具体来说,要剔除的不合乎要求的地图点是 处理关键帧过程中的 当前帧自己生成的地图点中的一部分。

剔除原则是:

  1. 已经是坏点的MapPoints直接从检查链表中删除
  2. 跟踪到该地图点的Frame数与预计可观测到该地图点的Frame数的比例小于25%,则剔除
  3. 从该点建立开始,到现在已经过了不小于2个关键帧但是观测到该点的关键帧数却不超过cnThObs帧,则剔除
  4. 从建立该点开始,已经过了3个关键帧而没有被剔除,则仅从队列中删除,放弃继续对该MapPoint的检测而不将其设为bad点。

那么问题又来了。既然该部分处理的是 当前帧自己生成的地图点为什么会考虑这些地图点的跟踪情况呢?

原因是:当前帧自己生成的地图点虽然没有在tracking线程的局部地图跟踪过程中进行匹配和跟踪,但是这些地图点在tracking线程中的位姿估计部分进行了匹配跟踪。换句话说:当前帧自己生成的地图点非当前帧(局部地图中其他关键帧)生成的地图点在tracking线程中都进行了匹配跟踪,只是匹配跟踪的方式和时间不同。

5. 创建新的地图点

目前为止,我们知道当前帧地图点分为两部分:当前帧自己生成的地图点非当前帧(局部地图中其他关键帧)生成的地图点。而创建新的地图点则是根据当前关键帧的共视关键帧和当前帧之间的姿态关系,利用三角化的方式恢复出一些地图点。所以经过创建新的地图点之后,当前帧的地图点分为三部分:当前帧自己生成的地图点非当前帧(局部地图中其他关键帧)生成的地图点当前帧与共视帧通过三角化计算出的地图点

该部分内容的大致思路为:

  1. 在当前关键帧的共视关键帧中找到共视程度最高的nn帧相邻帧vpNeighKFs
  2. 遍历相邻关键帧vpNeighKFs
  3. 判断相机运动的基线是不是足够长
  4. 根据两个关键帧的位姿计算它们之间的基本矩阵。
  5. 通过极线约束限制匹配时的搜索范围,进行特征点匹配
  6. 对每对匹配通过三角化生成3D点。

具体流程:
在这里插入图片描述
这部分的代码,注释的较为详细,以后再上传。

6.相邻搜索

如果当前关键帧是待处理关键帧队列中的最后一帧。则经过创建新的地图点之后要进行相邻搜索。相邻搜索的主要目的是检查并融合当前关键帧与相邻帧(两级相邻)重复的MapPoints。在经过上面几步的处理之后,地图点必然存在冗余,所以需要在此处进行冗余去除。

相邻搜索的主要思路为:

  1. 获得当前关键帧在covisibility图中权重排名前nn的邻接关键帧,找到当前帧一级相邻与二级相邻关键帧并将其存入vpTargetKFs中。
    这里提到的一级相邻关键帧指:与当前关键帧共视程度最高的nn个相邻关键帧,二级相邻关键帧指:与一级相邻关键帧共视程度最高的5个相邻关键帧。
  2. 将当前帧的MapPoints分别与一级二级相邻帧(的MapPoints)进行融合。
    投影当前帧的MapPoints到相邻关键帧pKFi中,并判断是否有重复的MapPoints。如果MapPoint能匹配关键帧的特征点,并且该点有对应的MapPoint,那么将两个MapPoint合并(选择观测数多的);如果MapPoint能匹配关键帧的特征点,并且该点没有对应的MapPoint,那么为该点添加MapPoint。
  3. 将一级二级相邻帧的所有有效的MapPoints分别与当前帧(的MapPoints)进行融合。
  4. 更新当前帧MapPoints的描述子,深度,观测主方向等属性。
  5. 更新covisibility图。

具体步骤如图:
在这里插入图片描述

6.剔除冗余关键帧

如果已经处理完队列中的最后的一个关键帧,并且闭环检测没有请求停止LocalMapping。则进行局部BA,然后剔除冗余关键帧。在此处先不说局部BA(后面单独说),只介绍一下剔除冗余关键帧操作。

剔除冗余关键帧的操作比较简单。其主要思想是:过去当前关键帧的所有共视关键帧。如果这些共视关键帧中的某一帧的地图点有90%能被至少3个关键帧观测到,则认为该帧是冗余的,需要将其设置为bad。

做完这些操作后,便可以将当前帧加入到闭环检测队列中进行闭环检测。


局部建图的过程就介绍到这里,相对来说内容比较少。

  • 8
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值