信息科学与工程学院
人工智能与机器人研究所
ORB-SLAM代码详细解读
吴博 @泡泡机器人
657390323@qq.com
2016.8.29
1
代码主要结构
2
2016/10/9
Tracking.cpp
LocalMapping.cpp
LoopClosing.cpp
Viewer.cpp
变量命名规则:
“p”表示指针数据类型
"n"表示int类型
“b”表示bool类型
"s"表示set类型
“v”表示vector数据类型 'l'表示list数据类型
“m”表示类成员变量
System入口:
GrabImageStero(imRectLeft,imRectRight)
输入图像
GrabImageRGBD(imRectLeft,imRectRight)
GrabImageMonocular(im)
Stero: mImGray,imGrayRight
转为灰度图
RGBD: mImGray,imDepth
Mono: mImGray
构造Frame
Stero: Frame(mImGray,imGrayRight,mpORBextractorLeft,
mpORBextractorRight)
RGBD: Frame(mImGray,imDepth,mpORBextractorLeft)
Mono(未初始化): Frame(mImGray,mpIniORBextractor)
Mono(已初始化): Frame(mImGray,mpORBextractorLeft)
Track
数据流进入Tracking线程
注:mpIniORBextractor相比mpORBextractorLeft提取的特征点多一倍
3
2016/10/9
Tracking线程:
Frame
初始化
相机位姿跟踪
局部地图跟踪
是否生成关键
帧
生成关键帧
SteroInitialization()
MonocularInitialization()
mbOnlyTracking(false)
位姿跟踪
TrackWithMotionModel()
TrackReferenceKeyFrame()
Relocalization()
mbOnlyTracking(true):同时跟踪与定位,不插入关键帧,局部地图不工作
UpdateLocalMap()
UpdateLocalKeyFrames()
UpdateLocalPoints()
SearchLocalPoints():获得局部地图与当前帧的匹配
PoseOptimization():最小化投影误差优化位姿
很长时间没有插入关键帧、局部地图空闲、跟踪快要跪
跟踪地图MapPoints的比例比较少
KeyFrame(mCurrentFrame,mpMap,mpKeyFrameDB)
对于双目或RGBD摄像头构造一些MapPoints,为MapPoints添加属性
注: mbOnlyTracking默认为false,用户可通过运行界面选择仅跟踪定位模式
4
2016/10/9
LocalMapping线程:
mlNewKeyFrames
检查队列
CheckNewKeyFrames()
处理新关键帧
ProcessNewKeyFrame()
更新MapPoints与KeyFrame的关联
UpdateConnections()
剔除MapPoints
剔除地图中新添加的但质量不好的MapPoints:
a.IncreaseFound / IncreaseVisible < 25%
b.观测到该点的关键帧太少
生成MapPoints
运动过程中和共视程度比较高的关键帧通过三角化恢复出一些MapPoints
MapPoints融合
检查当前关键帧与相邻帧(两级相邻)重复的MapPoints
Local BA
和当前关键帧相连的关键帧及MapPoints做局部BA优化
关键帧剔除
其90%以上的MapPoints能被其它共视关键帧(至少3个)观测到的关键帧
5
2016/10/9
LocalClosing线程(闭环检测):
mlploopKeyFrameQueue
队列中取一帧
mpcurrentKF
判断距离上一次闭环检
测是否超过10帧
1、三个阈值都是计算获得,鲁邦性好
minscore mincommons minscoreToRetain
2、通过分组可以将单独得分很高
的无匹配关键帧剔除
计算当前帧与相连关键
帧的Bow最低得分
mpcurrentKF
minscore
检测得到闭环候选帧
vpLoopCandidates
分组示意图:
1
2
10
3
4
如图:1、2、3、4、10都是闭环候选帧。
节点1:与2、3相连,1与2、3分为一组
节点2:与1、3相连,2与1、3分为一组
节点3:与1、2、4相连,3与1、2、4分为一组
节点4:与3相连,4与3分为一组
节点10:10自己单独一组
检测候选帧连续性
连续性检测示意图:
3、for(*sit,spcandidateKFs)
……
1、for(i,vpcandidateKFs)
Result:
……
mvpEnoughConsistentcandidates
SpreviousGroup
2、for(iG,mvConsistentGroup)
6
2016/10/9
vcurrentconsistentGroup
(pKF,minscore)
找出与当前帧有公共单词的关键帧,
但不包括与当前帧相连的关键帧
lKFsharingwords
统计候选帧中与pKF具有共同单词最
多的单词数
maxcommonwords
得到阈值
mincommons=0.8*maxcommonwords
maxcommonwords
mincommons
minscore
筛选共有单词大于mincommons且Bow
得分大于minscore的关键帧
lscoreAndMatch
将存在相连的分为一组,计算组最高
得分bestAccScore,同时得到每组中
得分最高的关键帧
lsAccScoreAndMatch
bestAccScore
得到阈值minScoreToRetain
=0.75*bestAccScore
lsAccScoreAndMatch
minScoreToRetain
vpLoopCandidates
LocalClosing线程(Sim3计算):
mpCurrentKF
for(pKF,mvpEnoughConsistentCandidates)
SearchByBow
vvpMapPointMatches
处构造Sim3求解器,对匹配
成功的关键帧进行Sim3求解
mpCurrentKF,pKF
Scm -->(R,t,s)
vpMapPointMatches
SearchBySim3得到更多匹配
Scm -->gscm
(mpCurrentKF,pKF)
vpMapPointMatches
OptimizeSim3
vpMapPointMatches -->mvpCurrentMatchedPoints
pKF -->MatchedKF
将MatchedKF共视帧取出
vpLoopConnectedKFs
(包括MatchedKF)
将MatchedKF共视帧取出
mvpLoopMapPoints
mpCurrentKF
gscm -->mg2oscw -->mscw
SearchByProjection得到更
7
多匹配点
mvpCurrentMatchedPoints
7
LocalClosing线程(Sim3计算):
X轴:
其中:
右坐标系同理,且令:
4
,
,
,
, ,
三对匹配3D,分别对左右三个3D点建立坐标系:
⁄
= ‖ ‖
其中: = , − ,
1
⁄
Y轴: = ‖ ‖
2
=( , − , )−[( , − , )⋅ ]
Z轴: = ×
3
,
=| |
=| |
可以得到 向量沿着坐标轴的值
如果左边坐标系有一个向量 ,那么:
左乘 可以变换到右坐标系,故可推导出旋转:
5
=
=
质心: =1 ,
=1 ,
= ‖ , −[ ( , )+ ‖
优化函数: ‖ ‖
5
8
, = , −
原点移到质心: , = , −
6
⋅ , − ( , )]+ ‖ ‖
= ‖ , − ( , ‖ −2
与优化量 无关
,
=0
,
=0
‖ , − ( , ‖
= − + ( 7
, = ( , )−
=0
min ‖ ‖
= = − (
9
计算平移量:
8