系统状态mState
<font color="#FF00FF"><b>NO_IMAGES_YET</b></font>(默认状态)<br>初次和Reset后的系统状态<br>
<font color="#FF00FF"><b>NOT_INITIALIZED</b></font>(系统[视觉]未初始化状态)<br>只由<font color="#FF00FF"><b>NO_IMAGES_YET</b></font>转变而来<br>
<font color="#FF00FF"><b>OK</b></font>(系统初始化完成状态)<br>单目初始化完成<br>or跟踪成功<font color="#388E3C"><b>bOK</b></font>==true<br>
<font color="#FF00FF"><b>RECENTLY_LOST</b></font>(刚跟踪丢失)<br>当系统中有IMU,视觉初始化成功mState==<font color="#FF00FF"><b>OK</b></font>且跟踪失败<font color="#388E3C"><b>bOK</b></font>==false<br>
<font color="#FF00FF"><b>LOST</b></font>(跟踪失败)
跟踪线程track()
判断mState==<font color="#FF00FF"><b>NO_IMAGES_YET</b></font><br>
<font color="#B71C1C"><b>是</b></font>
执行mState=<font color="#FF00FF"><b>NO_INITIALIZED</b></font>
判断mState==<font color="#FF00FF"><b>NO_INITIALIZED</b></font><br>
<font color="#B71C1C"><b>是</b></font><br>此时情况为:1.还未获得初始帧<br>2.已经获得初始帧,但还未初始化成功<br>
执行单目初始化<font color="#E65100"><b>MonocularInitialization</b></font>()
判断mState!=<font color="#FF00FF"><b>OK</b></font>
<font color="#B71C1C"><b>是</b></font>
<br>执行<font color="#0D47A1"><b>return</b></font><br>此时情况为:1.刚获得初始帧,初始化未完成<br>2.已经获得初始帧,但当前帧不符合条件,重新寻找初始帧<br>3.当前帧不满足初始帧,重新寻找初始帧<br>
<font color="#B71C1C"><b>否</b></font><br>此时情况为:1.初始化成功,此时系统开始进行跟踪<br>
bool <font color="#388E3C"><b>bOK</b></font>;<font color="#FF0000"><b>//用于判断跟踪状态</b></font>
判断!mbOnlyTracking<font color="#FF0000"><b>//该bool变量表示是否设置为只跟踪,默认值为false</b></font>
<font color="#B71C1C"><b>是</b></font><br>非“只跟踪”情况<br>
判断mState==<font color="#FF00FF"><b>OK</b></font><font color="#FF0000"><b>//判断是否为初始化成功状态</b></font>
<font color="#B71C1C"><b>是</b></font><br>此时情况为:初始化成功<br>
判断(mVelocity.empty() && !pCurrentMap->isImuInitialized()) || mCurrentFrame.mnId<mnLastRelocFrameId+2<br>//判断是否有当前帧<font color="#FF0000"><b>速度</b></font>,<font color="#FF0000"><b>imu初始化</b></font>是否成功或者当前帧是否刚进行<font color="#FF0000"><b>重定位(不超过2帧)</b></font><br>
<b><font color="#B71C1C">是</font></b>
<font color="#388E3C"><b>bOK</b></font> = <font color="#E65100"><b>TrackReferenceKeyFrame</b></font>()<br>//此时没有当前帧速度,且刚重定位,所以参考关键帧精度较高,用其进行跟踪<br>
<font color="#B71C1C"><b>否</b></font>
<font color="#388E3C"><b>bOK</b></font> = <font color="#E65100"><b>TrackWithMotionModel</b></font>()<br>//此时有当前帧速度,根据速度模型进行恒速跟踪<br>
判断!<font color="#388E3C"><b>bOK</b></font><br>//判断恒速跟踪是否成功<br>
<font color="#B71C1C"><b>是</b></font>
<font color="#388E3C"><b>bOK</b></font> = <font color="#E65100"><b>TrackReferenceKeyFrame</b></font>()<br>//恒速跟踪失败,继而用参考关键帧进行跟踪<br>
判断<font color="#388E3C"><font color="#212121">!</font><b>bOK</b></font><br>//判断上述跟踪是否成功<br>
<font color="#B71C1C"><b>是</b></font><br>跟踪失败,分情况判断,将系统状态设为<font color="#FF00FF"><b>LOST</b></font>或者 <font color="#FF00FF"><b>RECENTLY_LOST</b></font>
<font color="#B71C1C"><b>否</b></font><br>此时情况为:初始化失败<br>
对mState状态分情况判断,并进行相关操作
<font color="#B71C1C"><b>否</b></font><br>定位模式,局部建图已禁用<br>
根据系统状态mState判断是执行单目里程计或是重定位,将单目里程计结果赋值到<font color="#388E3C"><b>mbVO</b></font>
再次判断!mbOnlyTracking
<font color="#B71C1C"><b>是</b></font>
判断<font color="#388E3C"><b>bOK</b></font><font color="#FF0000"><b>//判断之前是否跟踪成功</b></font>
<font color="#B71C1C"><b>是</b></font><br>跟踪成功<br>
<font color="#388E3C"><b>bOK</b></font> = <font color="#E65100"><b>TrackLocalMap</b></font>()<br>将当前帧跟踪局部地图,并将结果反馈到bOK中<br>
判断!<font color="#388E3C"><b>bOK</b></font><br>判断跟踪局部地图是否成功<br>
<font color="#B71C1C"><b>是</b></font><br>跟踪局部地图失败<br>
cout << "Fail to track local map!" << endl
<font color="#B71C1C"><b>否</b></font><br>
判断bOK && !mbVO<br><b><font color="#FF0000">//判断:跟踪成功且视觉里程计失败</font></b><br>
<font color="#388E3C"><b>bOK</b></font> = <font color="#E65100"><b>TrackLocalMap</b></font>()
判断bOK<br><font color="#FF0000"><b>//判断上述的跟踪是否成功</b></font><br>
<font color="#B71C1C"><b>是</b></font>
mState = <font color="#FF00FF"><b>OK</b></font><br>//将系统状态设定为初始化成功状态<br>
else判断mState == <font color="#FF00FF"><b>OK</b></font>
<font color="#B71C1C"><b>是</b></font><br>此时情况:初始化成功,且此次跟踪失败<br>
如果系统中有IMU,决定是将mState设置为<font color="#FF00FF"><b>RECENTLY_LOST</b></font>还是<font color="#FF00FF"><b>LOST</b></font>
判断<font color="#388E3C"><b>bOK</b></font> || mState==<font color="#FF00FF"><b>RECENTLY_LOST</b></font>
<font color="#B71C1C"><b>是</b></font><br>//跟踪成功,或者刚丢失跟踪<br>
设置当前帧位姿和速度<br>清除VO匹配点<br>清除temporal MapPoints
bool <font color="#388E3C"><b>bNeedKF</b></font> = <font color="#E65100"><b>NeedNewKeyFrame</b></font>()<br>//判断是否需要新插入关键帧,将判断结果赋予bNeedKF<br>
判断<font color="#388E3C"><b>bNeedKF</b></font> && (<font color="#388E3C"><b>bOK</b></font>|| (mState==<font color="#FF00FF"><b>RECENTLY_LOST</b></font>)<br>//跟踪成功/刚跟踪丢失,且需要插入新关键帧<br>
<font color="#B71C1C"><b>是</b></font>
<font color="#E65100"><b>CreateNewKeyFrame</b></font>()<br>//将当前帧做为新关键帧插入<br>
<font color="#FF00FF"><b>关键帧是LocalMapping的输入,用来局部建图,进行BA优化,将关键帧插入局部地图中,当IMU未初始化时,用于IMU初始化</b></font>
单目初始化<br>MonocularInitialization()
判断!<font color="#388E3C"><b>mpInitializer</b></font><br><font color="#FF0000"><b>//判断初始帧标志,默认为false</b></font><br>
<font color="#B71C1C"><b>是<br>//还没有初始帧<br></b></font>
判断mCurrentFrame.mvKeys.size()>100<br><font color="#FF0000"><b>//判断当前帧的关键点是否大于100</b></font><br>
<font color="#B71C1C"><b>是</b></font><br>//满足初始帧要求<br>
mInitialFrame = Frame(mCurrentFrame);<br>mLastFrame = Frame(mCurrentFrame);<br><font color="#FF0000"><b>//将当前帧设为初始帧和前一帧</b></font><br>
mpInitializer = new Initializer(mCurrentFrame,1.0,200);<br><font color="#FF0000"><b>//更新标志位</b></font><br>
mpImuPreintegratedFromLastKF = new IMU::Preintegrated(IMU::Bias(),*mpImuCalib);<br>mCurrentFrame.mpImuPreintegrated = mpImuPreintegratedFromLastKF;<br><font color="#FF0000"><b>//初始化关键帧IMU预积分,并赋给当前帧</b></font><br>
<font color="#0D47A1"><b>return<br>//得到视觉初始化的第一帧(初始帧)后直接返回<br></b></font>
<font color="#B71C1C"><b>否</b></font><br>//已经存在初始帧,此时为第二帧<br>
判断mCurrentFrame.mvKeys.size()<=100||((mSensor == System::IMU_MONOCULAR)&&(mLastFrame.mTimeStamp-mInitialFrame.mTimeStamp>1.0))<br><font color="#FF0000"><b>//判断当前帧关键点小于100,或者系统中有IMU且前一帧与初始帧的时间差大于1s</b></font><br>
<font color="#B71C1C"><b>是</b></font><br>//不满足初始化第二帧的条件<br>
delete <font color="#388E3C"><b>mpInitializer</b></font>;<br>mpInitializer = static_cast<Initializer*>(NULL);<br><font color="#0D47A1"><b>return</b></font>;<br>//删除初始帧标志位,并直接返回<br>
ORBmatcher matcher(0.9,true);<br>int <font color="#4CAF50"><b>nmatches</b></font> = matcher.SearchForInitialization(mInitialFrame,mCurrentFrame,mvbPrevMatched,mvIniMatches,100);<br><font color="#FF0000"><b>//构建ORB匹配器,将初始帧和当前帧(第二帧)匹配,将匹配数量赋予nmatches</b></font><br>
判断nmatches<100<br>//初始帧和当前帧匹配点数小于100<br>
<font color="#B71C1C"><b>是</b></font><br>//不满足初始化条件<br>
delete <font color="#388E3C"><b>mpInitializer</b></font>;<br>mpInitializer = static_cast<Initializer*>(NULL);<br><font color="#0D47A1"><b>return</b></font>;<br>//删除初始帧标志位,并直接返回<br>
判断(mpCamera-><font color="#E65100"><b>ReconstructWithTwoViews</b></font>(mInitialFrame.mvKeysUn,mCurrentFrame.mvKeysUn,mvIniMatches,Rcw,tcw,mvIniP3D......)<br><font color="#FF0000"><b>//利用两帧做重建,计算帧间位姿变换</b></font><br>
<font color="#B71C1C"><b>是</b></font><br>//重建成功<br>
mInitialFrame.SetPose(cv::Mat::eye(4,4,CV_32F));<br>cv::Mat Tcw = cv::Mat::eye(4,4,CV_32F);<br>Rcw.copyTo(Tcw.rowRange(0,3).colRange(0,3));<br>tcw.copyTo(Tcw.rowRange(0,3).col(3));<br>mCurrentFrame.SetPose(Tcw);<br><font color="#FF0000"><b>//设置初始帧位姿为单位阵,将计算结果作为当前帧位姿</b></font><br>
<font color="#E65100"><b>CreateInitialMapMonocular</b></font>()<br>//创建初始化单目地图<br>
创建初始化单目地图<br>CreateInitialMapMonocular()
KeyFrame* <font color="#388E3C"><b>pKFini</b></font> = new KeyFrame(mInitialFrame,mpAtlas->GetCurrentMap(),mpKeyFrameDB);<br>KeyFrame* <font color="#388E3C"><b>pKFcur</b></font> = new KeyFrame(mCurrentFrame,mpAtlas->GetCurrentMap(),mpKeyFrameDB);<br><font color="#FF0000"><b>//将初始帧和当前帧建为关键帧</b></font><br>
<font color="#388E3C"><b>mpAtlas</b></font>->AddKeyFrame(pKFini);<br>mpAtlas->AddKeyFrame(pKFcur);<br><font color="#FF0000"><b>//将初始帧和当前帧添加到mpAtlas地图中</b></font><br>
pKFini->AddMapPoint(pMP,i);<br>pKFcur->AddMapPoint(pMP,mvIniMatches[i]);<br>pMP->AddObservation(pKFini,i);<br>pMP->AddObservation(pKFcur,mvIniMatches[i]);<br>pMP->ComputeDistinctiveDescriptors();<br>pMP->UpdateNormalAndDepth();<br><font color="#388E3C"><b>mpAtlas</b></font>->AddMapPoint(pMP);<br><font color="#FF0000"><b>//将地图点和观测值加入到mpAtlas地图中</b></font><br>
pKFini->UpdateConnections();<br>pKFcur->UpdateConnections();<br><font color="#FF0000"><b>//更新初始帧和当前帧的地图点connection</b></font><br>
Optimizer::GlobalBundleAdjustemnt(mpAtlas->GetCurrentMap(),20);<br>//对MpAtlas地图的两帧关键帧进行<font color="#FF0000"><b>全局BA</b></font><br><font color="#9C27B0"><b>//节点:两帧相机位姿、地图点坐标<br>//边:视觉重投影误差</b></font><br>
float medianDepth = pKFini->ComputeSceneMedianDepth(2);<br>float invMedianDepth;<br>if(mSensor == System::IMU_MONOCULAR)<br> invMedianDepth = 4.0f/medianDepth; // 4.0f<br>else<br> invMedianDepth = 1.0f/medianDepth;<br><font color="#FF0000"><b>//计算场景深度</b></font><br>
cv::Mat Tc2w = pKFcur->GetPose();<br>Tc2w.col(3).rowRange(0,3) = Tc2w.col(3).rowRange(0,3)*invMedianDepth;<br>pKFcur->SetPose(Tc2w);<br><font color="#FF0000"><b>//利用深度更新当前帧的相机位姿</b></font><br>
vector<MapPoint*> vpAllMapPoints = pKFini->GetMapPointMatches();<br> for(size_t iMP=0; iMP<vpAllMapPoints.size(); iMP++)<br> {<br> if(vpAllMapPoints[iMP])<br> {<br> MapPoint* pMP = vpAllMapPoints[iMP];<br> pMP->SetWorldPos(pMP->GetWorldPos()*invMedianDepth);<br> pMP->UpdateNormalAndDepth();<br> }<br> }<br><font color="#FF0000"><b>//利用深度更新当前地图点的世界坐标</b></font><br>
if (mSensor == System::IMU_MONOCULAR)<br> {<br> pKFcur->mPrevKF = pKFini;<br> pKFini->mNextKF = pKFcur;<br> pKFcur->mpImuPreintegrated = mpImuPreintegratedFromLastKF;<br><br> mpImuPreintegratedFromLastKF = new IMU::Preintegrated(pKFcur->mpImuPreintegrated->GetUpdatedBias(),pKFcur->mImuCalib);<br> }<br><font color="#FF0000"><b>//将两帧关键帧进行链接,并初始化当前关键帧与前一关键帧的IMU预积分</b></font><br>
mState=<font color="#FF00FF"><b>OK</b></font>;<br><font color="#FF0000"><b>//将系统状态设为OK,视觉初始化完成</b></font><br>