orb_slam代码解析(3)LocalMapping线程
距离写上一片文章已经也过去一段时间了,对之前看过的程序竟是如此陌生,还好在此做注,现在开始看新的线程:LocalMapping
系统有一个map,这个线程就是用来管理这个地图的,这个地图在跟踪线程中被初始化,在ORBSlam2的Tracking线程中,进行相机状态初始化的时候,当使用对极约束时,求解了第一帧和第二帧之间的单应矩阵和基本矩阵,并通过三角测量得到两帧匹配点的三维位置之后,使用了全局BA算法进行了一次细致的位姿优化。再是在locaomapping线程中,不断得向地图里插入关键帧,然后利用插入的关键帧及其相连关键帧及地图点进行局部BA优化。
LocalMapping作用是将Tracking中送来的关键帧放在mlNewKeyFrame列表中;处理新关键帧,地图点检查剔除,生成新地图点,Local BA,关键帧剔除。主要工作在于维护局部地图,也就是SLAM中的Mapping。
LocalMapping线程主要的工作就是通过不断的加入新KeyFrame和新地图点,剔除冗余KeyFrame和冗余地图点,来维护一个稳定的KeyFrame集合,从而可以进行后面的LoopClosing操作。
所以这个线程只是维护地图,没有进行全局优化。
我们知道。线程声明之后就从Run函数开始出发
Function1:LocalMapping::Run()
只要系统没有停止,那么就一直开始执行以下的任务:
Function1.1:SetAcceptKeyFrames(false)
告诉Tracking,LocalMapping正处于繁忙状态, LocalMapping线程处理的关键帧都是Tracking线程发过的,在LocalMapping线程还没有处理完关键帧之前Tracking线程最好不要发送太快。
判断等待处理的关键帧列表不为空。
Function1.2: ProcessNewKeyFrame()
取出等待关键帧,该帧就是处理的当前帧。 计算该关键帧特征点的Bow映射关系。跟踪局部地图过程中新匹配上的MapPoints和当前关键帧绑定(在TrackLocalMap函数中将局部地图中的MapPoints与当前帧进行了匹配, 但没有对这些匹配上的MapPoints与当前帧进行关联),即如果是非当前帧生成的MapPoints,那么就为当前帧在tracking过程跟踪到的MapPoints更新属性,包括为该MapPoint添加观测,说明能够为当前帧观测到,获得该点的平均观测方向和观测距离范围, 加入关键帧后,更新3d点的最佳描述子,最后是更新关键帧间的连接关系,Covisibility图和Essential图(tree),将该关键帧插入到地图中。
由于单目不直接生成一些新的地图点,所以就用不到剔除MapPoints。
Function1.3: CreateNewMapPoints
相机运动过程中和共视程度比较高的关键帧通过三角化恢复出一些MapPoints。
如果在等待处理的关键帧列表为空。
Function1.4: SearchInNeighbors
检查并融合当前关键帧与相邻帧(两级相邻)重复的MapPoints,在单目中,一级相邻帧为其连接关系的前20帧,二级相邻帧为各个一级相邻帧相邻程度最高的5帧。将当前帧的MapPoints分别与一级二级相邻帧(的MapPoints)进 行融合,将一级二级相邻帧的MapPoints分别与当前帧(的MapPoints)进行融合,融合就是指一个3D的地图点转换为关键帧坐标系下,然后反变换为像素坐标,在一定的半径范围内找出描述子距离跟3D的地图点最近 的特征点id,并找到该特征点对应的MapPoint,然后比较两个MapPoint的可被观测的次数多,胜者替代对方,完成融合。最后更新当前帧MapPoints的描述子,深度,观测主方向等属性,更新当前帧的MapPoints后更新与 其它帧的连接关系。
Function1.5: SLocalBundleAdjustment
这是进行和当前帧相连的关键帧及MapPoint做局部BA优化,而不是整个地图库去做全局的优化。在这部分我一直误解是所谓的后端全局地图的优化,但现在的想法是他只不过是为了帮助更加精确得去维护一个地图库,即让库里的关键帧的位姿是优化后的。
Function1.6: KeyFrameCulling
对当前帧与其共视的关键帧进行剔除,90%以上的MapPoint能被其他共视关键帧所观测到,那么该帧就会被剔除。
Function1.7: mpLoopCloser->InsertKeyFrame(mpCurrentKeyFrame)
现在处理的当前帧是跟踪线程送进来的,经过LocalMapping线程送到进行后面的mlploopKeyFrameQueue进行下一个线程的操作。