ORB_SLAM 源码解析
跟踪线程 深度 双目初始化位姿 运动模型 关键帧模式 重定位 局部地图跟踪 关键帧
mpMap就是我们整个位姿与地图(可以想象成ORB-SLAM运行时的那个界面世界),
MapPoint和KeyFrame都被包含在这个mpMap中。
因此创建这三者对象(地图,地图点,关键帧)时,
三者之间的关系在构造函数中不能缺少。
另外,由于一个关键帧提取出的特征点对应一个地图点集,
因此需要记下每个地图点的在该帧中的编号;
同理,一个地图点会被多帧关键帧观测到,
也需要记下每个关键帧在该点中的编号。
地图点,还需要完成两个运算,第一个是在观测到该地图点的多个特征点中(对应多个关键帧),
挑选出区分度最高的描述子,作为这个地图点的描述子;
pNewMP->ComputeDistinctiveDescriptors();
第二个是更新该地图点平均观测方向与观测距离的范围,这些都是为了后面做描述子融合做准备。
pNewMP->UpdateNormalAndDepth();
跟踪
每一帧图像 Frame —> 提取ORB关键点特征 —–> 根据上一帧进行位置估计计算R t (或者通过全局重定位初始化位置)
——> 跟踪局部地图,优化位姿 ——-> 是否加入 关键帧
1. Tracking线程
帧 Frame
1】初始化
单目初始化 MonocularInitialization()
双目初始化 StereoInitialization
2】相机位姿跟踪P
同时跟踪和定位 同时跟踪与定位,不插入关键帧,局部建图 不工作
跟踪和定位分离 mbOnlyTracking(false)
位姿跟踪 TrackWithMotionModel() TrackReferenceKeyFrame() 重定位 Relocalization()
a 运动模型(Tracking with motion model)跟踪
速率较快 假设物体处于匀速运动
用 上一帧的位姿和速度来估计当前帧的位姿使用的函数为TrackWithMotionModel()。
这里匹配是通过投影来与上一帧看到的地图点匹配,使用的是
matcher.SearchByProjection(Frame &CurrentFrame, const Frame &LastFrame, …)。
b 关键帧模式 TrackReferenceKeyFrame()
当使用运动模式匹配到的特征点数较少时,就会选用关键帧模式。即尝试和最近一个关键帧去做匹配。
为了快速匹配,本文利用了bag of words(BoW)来加速。
首先,计算当前帧的BoW,并设定初始位姿为上一帧的位姿;
其次,根据位姿和BoW词典来寻找特征匹配,使用函数matcher.SearchByBoW(KeyFrame pKF, Frame &F, …);
匹配到的是参考关键帧中的地图点。
最后,利用匹配的特征优化位姿。
c 通过全局重定位来初始化位姿估计 Relocalization()
假如使用上面的方法,当前帧与最近邻关键帧的匹配也失败了,
那么意味着需要重新定位才能继续跟踪。
重定位的入口如下: bOK = Relocalization();
此时,只有去和所有关键帧匹配,看能否找到合适的位置。
首先,计算当前帧的BOW向量,在关键帧词典数据库中选取若干关键帧作为候选。
使用函数如下:vector
其次,寻找有足够多的特征点匹配的关键帧;最后,利用RANSAC迭代,然后使用PnP算法求解位姿。这一部分也在Tracking::Relocalization() 里
3】局部地图跟踪
更新局部地图 UpdateLocalMap() 更新关键帧和 更新地图点 UpdateLocalKeyFrames() UpdateLocalPoints
搜索地图点 获得局部地图与当前帧的匹配
优化位姿 最小化重投影误差 3D点-2D点对 si pi = K T Pi = K exp(f) Pi
4】是否生成关键帧
加入的条件:
很长时间没有插入关键帧
局部地图空闲
跟踪快要跟丢
跟踪地图 的 MapPoints 地图点 比例比较少
5】生成关键帧
KeyFrame(mCurrentFrame, mpMap, mpKeyFrameDB)
对于双目 或 RGBD摄像头构造一些 MapPoints,为MapPoints添加属性
进入LocalMapping线程
设置闭环检测帧 mpLoopCloser->InsertKeyFrame(mpCurrentKeyFrame); // ===