前言
本文结合其余的ORBSLAM2的资料,对ORBLSAM2源码进行注释,感谢知识星球、泡泡机器人感谢吴博!
源码是知识星球小六等人的带注释版本。
LocalMapping线程主要用来处理从Tracking线程传过来的关键帧。
个人理解是:
Tracking线程只要是完成对当前帧的追踪,以及这个帧的地图点相关信息之类的。
在LocalMapping中只要就是处理这个新的关键帧。
注意:处理新的关键帧是在缓冲队列中处理,处理完了后,要从缓存队列中删掉。
LocalMapping主要流程如下图所示:
上面的流程具体体现在LocalMapping.cpp中的 线程主函数
void LocalMapping::Run()
/**
* 线程主函数:简单说明一下localmapping线程的主函数
* 首先mbFinished为线程主函数运行与否的表示 为false说明在运行
* LocalMapping线程处理的关键帧都是Tracking线程发过的
* 从tracking线程那边传入一个关键帧,现在想把这个新的关键帧放进关键帧队列里面去,所以肯定在处理的时候不想有其他帧加进来
*
*主循环
* Step 1 告诉Tracking,LocalMapping正处于繁忙状态,请不要给我发送关键帧打扰我,只处理队列里的关键帧----SetAcceptKeyFrames(false);//这里就是不接受关键帧
* if---等待处理的关键帧列表不为空----CheckNewKeyFrames()
* Step 2 处理列表中的关键帧,包括计算BoW、更新观测、描述子、共视图,插入到地图等
* ProcessNewKeyFrame() 处理新关键帧---更新mappoints 与keyframes的关联以及UpdataConnections()
*
* Step 3 根据地图点的观测情况剔除质量不好的地图点
* MapPointCulling();
* 剔除地图中新添加的但质量不好的MapPoints:
* a.IncreaseFound / IncreaseVisible < 25%
* b.观测到该点的关键帧太少
* Step 4 当前关键帧与相邻关键帧通过三角化产生新的地图点,使得跟踪更稳---因为上一步踢掉了一些不好的地图点
* CreateNewMapPoints() 运动过程中和共视程度比较高的关键帧通过三角化恢复出一些MapPoints
* 直到 已经处理完队列中的最后的一个关键帧
* Step 5 检查并融合当前关键帧与相邻关键帧帧(两级相邻)中重复的地图点---融合地图点其实就是 ,举个例子,对于当前关键帧之前有两个帧(帧n[更靠近当前关键帧的那个帧] 与 帧m)
* 当前关键帧与帧n匹配的特征点对应的地图点 可能与 当前关键帧与帧m匹配的特征点对应的地图点不是一个地图点(因为误差的累计)
* 所以要融合地图点,我们以 当前关键帧与帧n匹配的特征点对应的地图点为准(说是融合其实就是替换)
* SearchInNeighbors(); 检查并融合当前关键帧与相邻关键帧帧(两级相邻)中重复的地图点
* 如果已经处理完队列中的最后的一个关键帧,并且闭环检测没有请求停止LocalMapping
* Step 6 当局部地图中的关键帧大于2个的时候进行局部地图的BA, 和当前关键帧相连的关键帧(应该就是共视程度比较高的关键帧)及MapPoints做局部BA优化
* Step 7 检测并剔除当前帧相邻的关键帧中冗余的关键帧
* 冗余的判定:该关键帧的90%的地图点可以被其它关键帧观测到(说明这个帧是多余的,因为其他的三个以上的帧看到这个关键帧mappoints的90%了 )
* Step 8 将当前帧加入到闭环检测队列中
* 查看是否有复位线程的请求
* 告诉Tracking,LocalMapping 现在不忙了----SetAcceptKeyFrames(true);//接收关键帧
* 如果当前线程已经结束了就跳出主循环 不然就等---usleep(3000)
*
* else----当要终止当前线程的时候
* 如果还没有结束利索,那么等-------isStopped() && !CheckFinish()
* usleep(3000)
* 然后确定终止了就跳出这个线程的主循环
* if(CheckFinish())
* break;
*跳出主循环后
*设置线程已经终止---SetFinish();
*/
// 线程主函数
void LocalMapping::Run()
{
// 标记状态,表示当前run函数正在运行,尚未结束
mbFinished = false;
// 主循环
while(1)
{
// Tracking will see that Local Mapping is busy
// Step 1 告诉Tracking,LocalMapping正处于繁忙状态,请不要给我发送关键帧打扰我,处理队列;里的关键帧
LocalMapping线程处理的关键帧都是Tracking线程发过的
SetAcceptKeyFrames(false);//这里就是不接受关键帧
// Check if there are keyframes in the queue
// 等待处理的关键帧列表不为空
if(CheckNewKeyFrames())//检查关键帧
{
// BoW conversion and insertion in Map
// Step 2 处理列表中的关键帧,包括计算BoW、更新观测、描述子、共视图,插入到地图等
ProcessNewKeyFrame();//处理新关键帧---更新mappoints 与keyframes的关联、UpdataConnections()
// Check recent MapPoints
// Step 3 根据地图点的观测情况剔除质量不好的地图点
MapPointCulling(); //剔除地图中新添加的但质量不好的MapPoints:
//a.IncreaseFound / IncreaseVisible < 25%
//b.观测到该点的关键帧太少
// Triangulate new MapPoints
// Step 4 当前关键帧与相邻关键帧通过三角化产生新的地图点,使得跟踪更稳
CreateNewMapPoints();//运动过程中和共视程度比较高的关键帧通过三角化恢复出一些MapPoints---增加的地图点 mlpRecentAddedMapPoints
// 已经处理完队列中的最后的一个关键帧
if(!CheckNewKeyFrames())
{
// Find more matches in neighbor keyframes and fuse point duplications
// Step 5 检查并融合当前关键帧与相邻关键帧帧(两级相邻)中重复的地图点
SearchInNeighbors();
}
// 终止BA的标志
mbAbortBA = false;
// 已经处理完队列中的最后的一个关键帧,并且闭环检测没有请求停止LocalMapping
if(!CheckNewKeyFrames() && !stopRequested())
{
// Local BA
// Step 6 当局部地图中的关键帧大于2个的时候进行局部地图的BA, 和当前关键帧相连的关键帧(应该就是共视程度比较高的关键帧)及MapPoints做局部BA优化
if(mpMap->KeyFramesInMap()>2)
// 注意这里的第二个参数是按地址传递的,当这里的 mbAbortBA 状态发生变化时,能够及时执行/停止BA
Optimizer::LocalBundleAdjustment(mpCurrentKeyFrame,&mbAbortBA, mpMap);
// Check redundant local Keyframes
// Step 7 检测并剔除当前帧相邻的关键帧中冗余的关键帧
// 冗余的判定:该相邻关键帧的90%的地图点可以被其它关键帧观测到(说明这个帧是多余的,因为其他的三个以上的帧看到这个关键帧mappoints的90%了 )
KeyFrameCulling();
}
// Step 8 将当前帧加入到闭环检测队列中
// 注意这里的关键帧被设置成为了bad的情况,这个需要注意
mpLoopCloser->InsertKeyFrame(mpCurrentKeyFrame);
}
else if(Stop()) // 当要终止当前线程的时候
{
// Safe area to stop
while(isStopped() && !CheckFinish())
{
// 如果还没有结束利索,那么等
// usleep(3000);
std::this_thread::sleep_for(std::chrono::milliseconds(3));
}
// 然后确定终止了就跳出这个线程的主循环
if(CheckFinish())
break;
}
// 查看是否有复位线程的请求
ResetIfRequested();
// Tracking will see that Local Mapping is not busy
SetAcceptKeyFrames(true);
// 如果当前线程已经结束了就跳出主循环
if(CheckFinish())
break;
//usleep(3000);
std::this_thread::sleep_for(std::chrono::milliseconds(3));
}
// 设置线程已经终止
SetFinish();
}
下面是LocalMapping.cpp的全部内容,能看的下去的话就看吧,感觉比Tracking.cpp简单。
LocalMapping.cpp