ORBSLAM3 的改进

周六看到了ORBSLAM3的源码,安装运行后看了一下其代码结构,因为加IMU的部分是针对之前的ORB-VI, 因此大家可以参考jinpang的LearnORBVI可以更纯粹地学习视觉+IMU的组合;

这篇文章主要是针对其在Tracking线程做出的改动,尤其是添加Atlas后对Tracking部分的影响,LoopClosing和MapMerging的部分会在后面的分析中讲到,有错误也欢迎各位指正。

各部分的流程图整理好之后,稍后发出。

ORBSLAM3相对于ORBSLAM2做出的主要改动:

1. Atlas: 用于保存很多琐碎的地图;主要的作用发挥在Tracking线程Lost时,之前Lost后需要回到原先的位置进行Relocalization(),但是现在,如果tracking线程丢失,ORBSLAM3会在之前的所有小地图中进行查询匹配,如果匹配成功,则tracking线程继续; 如果匹配不成功,则重新开辟一个小的地图;

2. 也是因为这种情况,ORBSLAM3中还有很多小的地图(类似于carto中的submap)

Localmapping 线程只发生在当下active的map中

3.新增最大后验概率,用于初始化并且refine IMU数据;

4. loop and map merging 线程: 因为有了很多琐碎的地图,因此新增了map merging的部分,如果两个地图有重合部分,且重合处属于当前Active的Map,则对其进行LoopCorrection,类似于之前的检测到回环。如果两个地图重合的部分属于别的地图,这就类似于找到了其他两个地图的重合点,因此就将他们merge到一起。

If the common area belongs to the active map, it performs loop correction; if it belongs to a different map, both maps are seamlessly merged into a single one, that becomes the active map.

 1. 相机模型:

新增了基于KB鱼眼模型的追踪;这个模型与OpenCV的cv::fisheye标定的时候所使用的模型是一样的,因此大家可以使用opencv直接进行标定,建议使用size较大的标定板,这是注意很有可能你的标定板检测不需要subpixel即可很准确。

鱼眼模型带来的改变:

a. 重定位:ORBSLAM2通过求解PnP问题进行重定位后的计算,但是因为新增了鱼眼模型,因此需要新建一个可以不基于相机模型的Pnp算法,因此也就有了最大似然PnP算法;

b. 鱼眼模型带来的另一个改变是双目匹配时,这里对比一下两个项目在这里的区别:

ORBSLAM2: 采用双目去畸变后的图像,去畸变的remap过程发生在进入system之前,ComputeStereoMatches() 所采用的双目匹配方法是在极线上搜索,是一个很小的带状区域;搜索到匹配点之后直接根据视差d计算深度z

ORBSLAM3: 采用暴力匹配的方式,在全局使用knn搜索,只查找与当前左目描述子距离最近和次近的右目描述子,只要满足Lowe's Law就可以送去三角化计算关键点所对应的地图点。

三角化的这部分在ORBSLAM2中只用于跟踪,根据两帧匹配好的图像进行计算地图点的坐标,这里把他用于双目匹配计算深度;我在EUCM双目鱼眼中计算深度的方法也是如此,但是因为没有加入前面的最优与次优筛选的条件outliner就会比较多

 2. 新添加了一种状态RECENTLY_LOST,因此主要的状态分为以下:

NO_IMAGE_YET

NOT_INITIALIZED

OK

RECENTLY_LOST: 当前地图中的KF>10,且丢失时间<5秒

个人认为,这个状态其实就是相当于原先的LOST,在这里,如果激活了IMU则通过IMU数据进行预测,也就是 calculate current  pose by IMU data,

但如果丢失时间,超过五秒,则由当前state切换为LOST;如果是非IMU,即纯视觉状态,则直接进行重定位Relocalization();

LOST: 这个状态就是ORBSLAM3的一个新加的状态(虽然名字与之前的一样),因为新增了atlas,如果当前地图中的关键帧数量<10个,可以认为当前地图中没有重要信息,直接ResetActiveMap(),这个思路相当于之前的Reset(), 即如果初始化刚刚成功就丢失,可以认为当前map并不重要,直接重新初始化,这里也是一样的思路,这个部分最终发挥作用是在函数Tracking::ResetActiveMap()中。但如果当前的地图已经有很多关键帧(大于10帧),则调用CreateNewMap() 暂存该地图,再新建一个空的地图。

接下来对比一下Tracking::ResetActiveMap() 与ORBSLAM2中的Reset(),方便更清楚这个函数的作用

ORBSLAM3 中 Tracking::ResetActiveMap() 部分功能:

 Map* pMap = mpAtlas->GetCurrentMap();
 mpLocalMapper->RequestResetActiveMap(pMap);
 mpLoopClosing->RequestResetActiveMap(pMap);
 mpKeyFrameDB->clearMap(pMap);
 mpAtlas->clearMap();

ORBSLAM2 中Reset()函数:

 mpLocalMapper->RequestReset();
 // Reset Loop Closing
 mpLoopClosing->RequestReset();
    
 cout << "Reseting Database...";
 mpKeyFrameDB->clear();
 cout << " done" << endl;

 // Clear Map (this erase MapPoints and KeyFrames)
 mpMap->clear();

 可以看到该函数的主要作用相对于之前的Reset() ,不变的部分是对一些Tracking所用到的类成员变量进行reset,如mCurrentFrame, mLastFrame等,同时,通知其他几个线程需要reset的消息。 但是变化的部分要是Atlas的加入,每一个线程的reset都是只针对currentMap,并不会影响其他的Map,新建的线程mpAltas也会将目前的地图清除,

CreateMapInAtlas(),用于新建一个submap,而atlas就是用于管理这些small map的。

接下来主要说一下ATLAS, atlas是新建的线程,主要用于管理地图,既然有了地图管理者,就会有几个随之而来的类成员变量,最主要的是mspMaps,用于存放小地图,同时一个重要的函数createNewMap()用于新建地图

强调一下 createNewMap(): 主要作用如下:

1. 保存当前地图 mpCurrentMap->SetStoredMap(); 主要通过设置变量IsInUse为False,方便后面进行判断;

2. 设定新地图的初始帧的KFid:mnLastInitKFidMap = mpCurrentMap->GetMaxKFid()+1;

3. 接下来一切准备就绪,

mpCurrentMap = new Map(mnLastInitKFidMap); //初始化一个地图
mpCurrentMap->SetCurrentMap(); //将其设置为正在使用,也就是active
mspMaps.insert(mpCurrentMap); //将此地图插入到mspMaps,也就是地图管理变量中

就此,创建新的小地图完成;

接下来最主要的一个问题就是ORBSLAM3会在什么时候创建新的地图:

1. 初始化:

 Map* pCurrentMap = mpAtlas->GetCurrentMap();

a. 如果是带有IMU的初始化,则在IMU初始化完成后就直接调用 CreateMapInAtlas();(结合IMU的第一点作用,即在视觉初始化成功之前进行位置追踪,这里不难理解)

b. 如果是不带有IMU的Tracking,初始化的过程和ORBSLAM2一样,在初始化时进行新建地图,以双目为例,在

StereoInitialization() 中,若有特征点足够,则

 KeyFrame* pKFini = new KeyFrame(mCurrentFrame,mpAtlas->GetCurrentMap(),mpKeyFrameDB); 

而这里GetCurrentMap()也会调用createNewMap()来新建地图; 

2. 如果当前状态设定为LOST,且当前地图中的关键帧数量已经多余10帧,则调用createNewMap()保存当前地图,创建新地图;

下面是Tracking部分的流程图,排除IMU的添加,蓝色的字体是纯视觉来讲,与之前ORBSLAM2的主要差别。

如有疑问,欢迎交流: wx: baobaohaha_ 欢迎对SLAM有兴趣的小伙伴一起交流学习~~

  • 17
    点赞
  • 115
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值