ORB_SLAM2学习之源码分析六-LocalMapping


这篇文章是有关ORB_SLAM2系统源码分析的内容,主要记录LocalMapping模块部分。

概述

LocalMapping模块作用是将Tracking中送来的关键帧放在mlNewKeyFrame列表中;处理新关键帧、地图点检查剔除、生成新地图点、Local BA、关键帧剔除。主要工作在于维护地图,也就是SLAM中的Map

前面的记录中提到,Tracking模块会将满足一定条件的图像帧加入关键帧,但是其实ORB-SLAM中关键帧的加入是比较密集的,这样确保了定位的精度。同时LocalMapping线程会对关键帧进行剔除,确保了关键帧的数量不会无限增加,不会对large scale的场景造成计算负担。Tracking模块会判断是否需要将当前帧创建为关键帧,对地图中的关键帧、地图点具体的处理,包括如何加入、如何删除的工作是在LocalMapping线程完成的。论文中的图:

具体操作

处理新关键帧

对应LocalMapping::ProcessNewKeyFrame()函数。处理新关键帧与局部地图点之间的关系。具体步骤如下:

  1. 获取关键帧。mlNewKeyFrame队列(待插入的关键帧)中弹出队首的关键帧做为当前帧,并计算该关键帧的BoW,后面三角化恢复地图点有用;
  2. 获取关键帧中与关键点关联的地图点。将TrackLocalMap中跟踪局部地图匹配上的地图点关联到当前关键帧(在Tracking线程中只是利用关键点的匹配关系进行位姿计算,优化当前关键帧姿态)。具体来说,可以分两种情况,地图点没有关联到关键帧,则完成关联(AddObservation),更新地图点normal和描述子,这种地图点是在追踪过程创建并被关键帧关联的,它们在UpdateLastFrame过程就已经有了空间位置;否则记录该地图点为最新添加(这些地图点是在创建关键帧时创建的,已经关联到关键帧),加入mlpRecentAddedMapPoints
  3. 更新共视图连接关系。使用UpdateConnections函数更新加入当前关键帧之后关键帧之间的连接关系,包括更新Covisibility图和Essential图(最小生成树spanning tree);
  4. 关键帧插入地图。

地图点剔除

对应LocalMapping::MapPointCulling()函数。任务是对上一函数获取到的最新加入的局部地图点mlpRecentAddedMapPoints进行检查,每个地图点要被保留,在该地图点被创建后的三个关键帧里必须要经过严格的测试,这样保证其能被正确的跟踪和三角化。满足如下条件之一就被剔除:

  1. 该地图点是坏点,直接从检查列表去掉;
  2. 跟踪(匹配上)到该地图点的普通帧帧数(IncreaseFound)<应该观测到该地图点的普通帧数量(25%*IncreaseVisible),即比值mnFound/mnVisible<0.25,设置为坏点,并从检查列表去掉。比值低说明这样的地图点该地图点虽在视野范围内,但很少被普通帧检测到;
  3. 从添加该地图点的关键帧算起,当前关键帧至少是第三个添加该地图点的关键帧的条件下,看到该地图点的帧数<=2(双目和RGBD模式是帧数<=3),设置为坏点,并从检查列表去掉;因此在地图点刚建立的阶段,要求比较严格,很容易被剔除;而且单目的要求更严格,需要三帧都看到;
  4. 若从添加该地图点的关键帧算起,一共有了大于三个关键帧,还存在列表中,则说明该地图点是高质量的,从检查列表中去掉。

一旦经过了这样比较严格的筛选,地图点只有在观测到它的关键帧<3时才会被剔除,这主要发生在关键帧被剔除(90%以上匹配点可以被其他帧检测到);或者局部捆集优化时,将地图点归为外点从观测中剔除了的情况。因此地图点中的外点是比较少的,所以整套ORB-SLAM中除了重定位和闭环很少去使用RANSAC。

ORB-SLAM中关键帧和地图点的加入和删除秉承的是送入严出的标准,因此在提高了定位建图准确性的前提下又很好地限制了计算量,可以用于large scale的场景。

生成新地图点(三角化方法)

对应LocalMapping::CreateNewMapPoints()函数。任务是根据当前关键帧恢复出一些新的地图点,不包括和当前关键帧匹配的局部地图点(已经在ProcessNewKeyFrame中处理,单目模式除了初始化过程会生成地图点外,其它地图点都在这里生成)。具体步骤如下:

  1. 找出与当前帧有共视关系的10个(单目模式是20个)关键帧,准备使用对极约束搜索匹配并进行三角化,循环进行以下操作,注意是在当前帧和每一帧共视关键帧之间进行;
  2. 检测基线是否过短;
  3. 计算基础矩阵F;
  4. 搜索满足对极约束的匹配;
  5. 通过各种条件判断是不是要三角化这些地图点;
  6. 完成对匹配结果的三角化,创建新的地图点;
  7. 为新的地图点进行一系列配置。

跟论文里面提到的一样。1、三角化的地图点在两帧都有正深度。2、视差、在每个帧的投影误差、尺度一致性都有被检测。三角化过程还要再深入学习。

临近关键帧搜索更多匹配

对应LocalMapping::SearchInNeighbors()函数。如果关键帧队列中还有新的关键帧,则进行该操作,即在临近的关键帧中搜索到更多的匹配,更新并融合当前关键帧以及两级相连(共视关键帧及其共视关键帧)的关键帧的地图点。

Local Bundle Adjustment

对应Optimizer::LocalBundleAdjustment()函数。这里优化的是当前帧,以及与当前帧在covisibility graph里面有连接关系的那些关键帧的位姿,以及这些帧看到的地图点,其实就是对局部地图进行优化。详细分析参见优化部分博客。

冗余关键帧剔除

对应LocalMapping::KeyFrameCulling()函数。候选的pKF是LocalMapping中当前处理的关键帧的共视关键帧,不包括第一帧关键帧与当前关键帧。如果一个关键帧检测到的90%的地图点,在其他不少于三个具有相同或更精确尺度的关键帧里面都被检测到,就认定该关键帧冗余(该关键帧的存在提供的地图点观测信息有限),并剔除。

参考资料

  1. ORB_SLAM(九) LocalMapping
  2. ORB_SLAM2学习6 LocalMapping

本文标题:ORB_SLAM2学习之源码分析六-LocalMapping

文章作者:阿翔

发布时间:2018年08月22日 - 08:08

最后更新:2019年05月28日 - 21:05

原始链接:http://ttshun.com/2018/08/22/ORB-SLAM2学习之源码分析六-LocalMapping/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

点击给我一些鼓励叭!
-------------本文结束感谢您的阅读-------------
0%