前言

12.6开启跟踪线程的学习,2025.2.5进行回顾。 

ORB-SLAM3 中的跟踪线程体流程和ORB-SLAM2 中的一样,主要包括两个阶段:

1.第一阶段包括三种跟踪方式:参考关键帧跟踪、恒速模型跟踪、重定位跟踪,它们的目的是保证能够"跟得上”(指的是跟踪算法能够实时或准确地持续更新并估计出相机或物体的位姿),但估计出来的位姿可能没那么准确。 

2.第二阶段是局部地图跟踪,将当前帧的局部关键帧对应的局部地图点投影到该帧中, 得到更多的特征点匹配关系,对第一阶段的位姿再次进行优化,得到相对准确的位姿。

ORB-SLAM3在2的基础上引入了IMU这使得跟踪线程变得更加复杂。

 新增内容: 

1.新增了一种跟踪状态 RECENTLY_LOST, 它的目的是在视觉+IMU模式下,当短期跟踪丢失后,可以用累积的IMU数据预测一个粗糙的位姿,希望能够把跟丢的位姿重新找回来。

2.在恒速模型跟踪中。如果是IMU 模式且满足一定的条件, 则可以用IMU积分代替位姿差来估计当前帧位姿。

3.在重定位跟踪中。基本流程不变,只不过将位姿估计方法中的EPnP换成了MLPnP (最大似然PnP) 。主要原因是EPnP是根据标定好的针孔相机模型推导而来的, 不具有普适性;而MLPnP 将相机模型解耦合了(内外参分开处理),更加通用。

4.在局部地图跟踪中。在IMU 模式下,使用视觉信息和IMU 信息联合优化当前帧位姿。

5.插入关键帧。如果当前地图未完成IMU 初始化, 且当前帧距离上一帧时间戳超过0.25s, 则直接插入关键帧。 

新增的跟踪状态 

// Tracking states////
    enum eTrackingState{
        SYSTEM_NOT_READY=-1,//系统没有准备好的状态,一般就是在启动后的加载配置文件和词典文件。
        NO_IMAGES_YET=0,//当前无图像状态
        NOT_INITIALIZED=1,//有图像但是没有完成初始化
        OK=2,//正常工作状态
        RECENTLY_LOST=3,//ORB-SLAM3新增的跟踪状态:IMU模式:当前地图中关键帧,且丢失时间小于5s。纯视觉模式:没有该状态。
        LOST=4,//IMU模式:当前帧跟丢超过5s,纯视觉模式:重定位失败
        OK_KLT=5
    };

 为了降低跟踪丢失的可能性。这里将跟踪丢失的状态分为两种。

1.短期跟踪丢失 

RECENTLY_LOST 是为了降低跟踪丢失的可能性而引入的一个过渡状态。它主要出现在 IMU辅助模式下,当前地图中的关键帧大于10 帧,且丢失时间小于5s,当视觉跟踪暂时失败时,系统并不会立即进入完全丢失(LOST)状态,而是通过使用IMU数据来恢复跟踪。当系统在进行参考关键帧跟踪和恒速模型跟踪时都失败了,该状态就会被激活。这种状态说明系统在短期内无法通过视觉数据单独恢复位姿,但系统依然尝试通过 IMU数据来估计相机的位姿。这是为了给系统一个“宽松的缓冲期”,避免一开始就进入 LOST 状态。 

2.长期跟踪丢失 

如果 RECENTLY_LOST 状态下,系统未能在5秒内恢复位姿,就会进入 LOST 状态。此时,系统认为当前跟踪失败,无法继续依赖现有地图来进行位姿估计。在 IMU模式下,若短期丢失后超过5秒没有恢复,系统会进入 LOST 状态;而在纯视觉模式下,如果重定位失败(无法重新定位相机),也会进入 LOST 状态。进入 LOST 状态后,系统需要重新初始化和构建地图。

RECENTLY_LOST 状态是在跟踪线程中的哪个阶段设置的?

在参考关键帧跟踪、恒速模型跟踪都失败时设置的。代码如下:

// Tracking.cc 文件中Track()函数
// 新增了一个状态RECENTLY_LOST,主要是结合IMU看看能不能拽回来
                // Step 6.3 如果经过跟踪参考关键帧、恒速模型跟踪都失败的话,并满足一定条件就要标记为RECENTLY_LOST或LOST
                if (!bOK)
                {
                    // 条件1:如果当前帧距离上次重定位成功不到1s
                    // mnFramesToResetIMU 表示经过多少帧后可以重置IMU,一般设置为和帧率相同,对应的时间是1s
                    // 条件2:单目+IMU 或者 双目+IMU模式
                    // 同时满足条件1,2,标记为LOST
                    if ( mCurrentFrame.mnId<=(mnLastRelocFrameId+mnFramesToResetIMU) &&
                         (mSensor==System::IMU_MONOCULAR || mSensor==System::IMU_STEREO || mSensor == System::IMU_RGBD))
                    {
                        mState = LOST;
                    }
                    else if(pCurrentMap->KeyFramesInMap()>10)
                    {
                        // cout << "KF in map: " << pCurrentMap->KeyFramesInMap() << endl;
                        // 条件1:当前地图中关键帧数目较多(大于10) 
                        // 条件2(隐藏条件):当前帧距离上次重定位帧超过1s(说明还比较争气,值的救)或者非IMU模式
                        // 同时满足条件1,2,则将状态标记为RECENTLY_LOST,后面会结合IMU预测的位姿看看能不能拽回来
                        mState = RECENTLY_LOST;
                        // 记录丢失时间
                        mTimeStampLost = mCurrentFrame.mTimeStamp;
                    }
                    else
                    {
                        mState = LOST;
                    }
                }

第一阶段跟踪变化 

1.参考关键帧跟踪 (TrackReferenceKeyFrame)

跟踪线程是SLAM 中最重要的模块之一,我们不仅要知道每个模块的原理,也要了解在什么情况下使用、怎么用。简单来说,参考关键帧跟踪就是将当前普通帧(位姿未知)和它对应的参考关键帧(位姿已知)进行特征匹配及优化,从而估计当前普通帧的位姿。

在地图初始化之后,把参与初始化的第1 、2 帧都作为关键帧。当第3帧进来之后,使用的第一种跟踪方式就是参考关键帧跟踪。这里总结了参考关键帧跟踪的应用场景和具体流程。

1.应用场景

1.地图刚刚初始化之后,此时恒速模型中的速度为空。这时只能使用参考关键帧,也就是初始化的第1 、2 帧对当前帧进行跟踪。

2.恒速模型跟踪失败后,尝试用最近的参考关键帧跟踪当前普通帧。因为在恒速模型中估计的速度并不准确,可能会导致错误匹配,并且恒速模型只利用了前一帧的信息,信息量也有限,跟踪失败的可能性较大。而参考关键帧可能在局部建图线程中新匹配了更多的地图点并且参考关键帧的位姿是经过多次优化的,更准确。

2.具体流程

1.首先计算当前帧的词袋将当前普通帧的描述子转化为词袋向量。(通过调用函数实现)

2.初始化一个特征器匹配对象,通过词袋来加速匹配特征点,初步匹配点数要大于15个才行。 

3.将上一帧的位姿作为当前帧位姿的初始值(可以加速收敛),通过3D-2D重投影误差来获取优化后的位姿。三维地图点来自第2步匹配成功的参考帧, 二维特征点来自当前普通帧, BA 优化仅优化位姿,不优化地图点坐标。

4.根据优化结果剔除地图点中的外点最后是成功匹配到的内点数目大于10才行。 

此部分代码基本上是一致的,只是在IMU模式下判断标准更宽松了。 

/*
 用参考关键帧的地图点来对当前普通帧进行跟踪
 1:将当前普通帧的描述子转化为BoW向量
 2:通过词袋BoW加速当前帧与参考帧之间的特征点匹配
 3: 将上一帧的位姿态作为当前帧位姿的初始值
 4: 通过优化3D-2D的重投影误差来获得位姿
 5:剔除优化后的匹配点中的外点
 return 如果匹配数超10,返回true
*/
bool Tracking::TrackReferenceKeyFrame()
{
    // Compute Bag of Words vector
    // Step 1:将当前帧的描述子转化为BoW向量
    mCurrentFrame.ComputeBoW();

    // We perform first an ORB matching with the reference keyframe
    // If enough matches are found we setup a PnP solver
    // 我们首先执行一个与参考关键帧的ORB特征匹配
	// 如果找到了足够的匹配点,就设置一个PnP求解器
    ORBmatcher matcher(0.7,true);
    vector<MapPoint*> vpMapPointMatches;

    // Step 2:通过词袋BoW加速当前帧与参考帧之间的特征点匹配
    int nmatches = matcher.SearchByBoW(mpReferenceKF,mCurrentFrame,vpMapPointMatches);

    // 匹配数目小于15,认为跟踪失败
    if(nmatches<15)
    {
        cout << "TRACK_REF_KF: Less than 15 matches!!\n";
        return false;
    }

    // Step 3:将上一帧的位姿态作为当前帧位姿的初始值
    mCurrentFrame.mvpMapPoints = vpMapPointMatches;
    mCurrentFrame.SetPose(mLastFrame.GetPose());  // 用上一次的Tcw设置初值,在PoseOptimization可以收敛快一些

    //mCurrentFrame.PrintPointDistribution();


    // cout << " TrackReferenceKeyFrame mLastFrame.mTcw:  " << mLastFrame.mTcw << endl;
    // Step 4:通过优化3D-2D的重投影误差来获得位姿
    Optimizer::PoseOptimization(&mCurrentFrame);

    // Discard outliers
    // Step 5:剔除优化后的匹配点中的外点
    //之所以在优化之后才剔除外点,是因为在优化的过程中就有了对这些外点的标记
    int nmatchesMap = 0;
    for(int i =0; i<mCurrentFrame.N; i++)
    {
        //if(i >= mCurrentFrame.Nleft) break;
        if(mCurrentFrame.mvpMapPoints[i])
        {
            // 如果对应到的某个特征点是外点
            if(mCurrentFrame.mvbOutlier[i])
            {
                // 清除它在当前帧中存在过的痕迹
                MapPoint* pMP = mCurrentFrame.mvpMapPoints[i];

                mCurrentFrame.mvpMapPoints[i]=static_cast<MapPoint*>(NULL);
                mCurrentFrame.mvbOutlier[i]=false;
                if(i < mCurrentFrame.Nleft){
                    pMP->mbTrackInView = false;
                }
                else{
                    pMP->mbTrackInViewR = false;
                }
                pMP->mbTrackInView = false;
                pMP->mnLastFrameSeen = mCurrentFrame.mnId;
                nmatches--;
            }
            else if(mCurrentFrame.mvpMapPoints[i]->Observations()>0)
                // 匹配的内点计数++
                nmatchesMap++;
        }
    }

    if (mSensor == System::IMU_MONOCULAR || mSensor == System::IMU_STEREO || mSensor == System::IMU_RGBD)
        return true;//3中新加入的判断条件
    else
        return nmatchesMap>=10;  // 跟踪成功的数目超过10才认为跟踪成功,否则跟踪失败
}

3在2的基础上最后的判定条件上加入了传感器模式的判断如果存在是三种模式之一则直接判定为跟踪成功。 

if (mSensor == System::IMU_MONOCULAR || mSensor == System::IMU_STEREO || mSensor == System::IMU_RGBD)
        return true;//3中新加入的判断条件
    else
        return nmatchesMap>=10;  // 跟踪成功的数目超过10才认为跟踪成功,否则跟踪失败

2.恒速模型跟踪(TrackWithMotionModel) 

什么是恒速模型跟踪呢?两个图像帧之间一般只有几十毫秒的时间,在这么短的时间内,可以做合理的假设一一在相邻帧间极短的时间内,相机处于匀速运动状态,可以用上一帧的位姿和速度估计当前帧的位姿。所以称为恒速模型跟踪。地图刚刚初始化后,用参考关键帧跟踪是因为”被逼无奈",此时没有速度信息,只能用词袋匹配估计一个粗糙的位姿,再非线性优化该位姿。使用参考关键帧跟踪成功后,就有了速度信息, 此时我们就不需要再用比较复杂的参考关键帧跟踪了,直接用恒速模型跟踪估计位姿更简单、更快,这对实时性要求较高的SLAM 系统来说很有意义。

1.初始化一个匹配器对象。 

2.更新上一帧信息。 

3.用恒速模型来得到当前帧的位姿。 

4.设置特征匹配过程中的搜索半径,进行投影匹配,如果匹配数不够则扩大半径继续搜索。 

5.利用3D-2D投影关系得到当前帧的优化位姿,并根据优化结果来剔除地图点的外点,最后匹配留下来的内点数大于10即跟踪成功。 

新增内容: 

1.在2中我们直接用的位姿差代替速度,而对于3,如果是IMU的模式下,当IMU完成初始化且距离重定位比较久,不需要重置IMU,直接用IMU估计位姿。

2.在2中我们扩大搜索半径后重新搜索,如果成功匹配点对数目小于20,则认为跟踪失败。而对于3,如果是IMU模式则认为是跟踪成功的。 

3.在2中最后位姿优化后,需要成功匹配的内点数超过10才可以。而对于3,如果是IMU模式,就认为是跟踪成功。 

/*
 brief 根据恒定速度模型用上一帧地图点来对当前帧进行跟踪
 1:更新上一帧的位姿;对于双目或RGB-D相机,还会根据深度值生成临时地图点
 2:根据上一帧特征点对应地图点进行投影匹配
 3:优化当前帧位姿
 4:剔除地图点中外点
 return 如果匹配数大于10,认为跟踪成功,返回true
*/
bool Tracking::TrackWithMotionModel()
{
    // 初始化一个特征匹配器的对象它的最近邻匹配率为0.9
    //(某个特征点与所有可能匹配的特征点之间所有距离的最小和次小的比值)。
    // 检查方向(ORB特征具有方向性)
    ORBmatcher matcher(0.9,true);

    // Update last frame pose according to its reference keyframe
    // Create "visual odometry" points if in Localization Mode
    // Step 1:更新上一帧的位姿;对于双目或RGB-D相机,还会根据深度值生成临时地图点
    UpdateLastFrame();//调用的是Tracking.cc文件中定义的函数(上面定义过)

    // Step 2:根据IMU或者恒速模型得到当前帧的初始位姿。
    // 3在2基础上加入了IMU,如果IMU已经初始化了且距离上次重定位时间挺长了,就直接用IMU来估计位姿了。
    if (mpAtlas->isImuInitialized() && (mCurrentFrame.mnId>mnLastRelocFrameId+mnFramesToResetIMU))
    {
        // Predict state with IMU if it is initialized and it doesnt need reset
        PredictStateIMU();
        return true;
    }
    else//否则还是要按照正常的恒速模型的速度进行更新。
    {
        // 根据之前估计的速度,用恒速模型得到当前帧的初始位姿。
        mCurrentFrame.SetPose(mVelocity * mLastFrame.GetPose());
    }

    // 清空当前帧的地图点
    fill(mCurrentFrame.mvpMapPoints.begin(),mCurrentFrame.mvpMapPoints.end(),static_cast<MapPoint*>(NULL));

    // Project points seen in previous frame
    // 设置特征匹配过程中的搜索半径
    int th;

    if(mSensor==System::STEREO)
        th=7;
    else
        th=15;

    // Step 3:用上一帧地图点进行投影匹配,如果匹配点不够,则扩大搜索半径再来一次
    int nmatches = matcher.SearchByProjection(mCurrentFrame,mLastFrame,th,mSensor==System::MONOCULAR || mSensor==System::IMU_MONOCULAR);

    // If few matches, uses a wider window search
    // 如果匹配点太少,则扩大搜索半径再来一次
    if(nmatches<20)
    {
        Verbose::PrintMess("Not enough matches, wider window search!!", Verbose::VERBOSITY_NORMAL);
        fill(mCurrentFrame.mvpMapPoints.begin(),mCurrentFrame.mvpMapPoints.end(),static_cast<MapPoint*>(NULL));

        nmatches = matcher.SearchByProjection(mCurrentFrame,mLastFrame,2*th,mSensor==System::MONOCULAR || mSensor==System::IMU_MONOCULAR);
        Verbose::PrintMess("Matches with wider search: " + to_string(nmatches), Verbose::VERBOSITY_NORMAL);

    }

    // 这里不同于ORB-SLAM2的方式
    if(nmatches<20)
    {
        Verbose::PrintMess("Not enough matches!!", Verbose::VERBOSITY_NORMAL);
        if (mSensor == System::IMU_MONOCULAR || mSensor == System::IMU_STEREO || mSensor == System::IMU_RGBD)
            return true;
        else
            return false;
    }

    // Optimize frame pose with all matches
    // Step 4:利用3D-2D投影关系,优化当前帧位姿
    Optimizer::PoseOptimization(&mCurrentFrame);

    // Discard outliers
    // Step 5:剔除地图点中外点
    int nmatchesMap = 0;
    for(int i =0; i<mCurrentFrame.N; i++)
    {
        if(mCurrentFrame.mvpMapPoints[i])
        {
            if(mCurrentFrame.mvbOutlier[i])
            {
                // 如果优化后判断某个地图点是外点,清除它的所有关系
                MapPoint* pMP = mCurrentFrame.mvpMapPoints[i];

                mCurrentFrame.mvpMapPoints[i]=static_cast<MapPoint*>(NULL);
                mCurrentFrame.mvbOutlier[i]=false;
                if(i < mCurrentFrame.Nleft){
                    pMP->mbTrackInView = false;
                }
                else{
                    pMP->mbTrackInViewR = false;
                }
                pMP->mnLastFrameSeen = mCurrentFrame.mnId;
                nmatches--;
            }
            else if(mCurrentFrame.mvpMapPoints[i]->Observations()>0)
                // 累加成功匹配到的地图点数目
                nmatchesMap++;
        }
    }

    // 纯定位模式下:如果成功追踪的地图点非常少,那么这里的mbVO标志就会置位
    if(mbOnlyTracking)
    {
        mbVO = nmatchesMap<10;
        return nmatches>20;
    }
	// 如果是IMU模式,它对运动有额外的约束则
    if (mSensor == System::IMU_MONOCULAR || mSensor == System::IMU_STEREO || mSensor == System::IMU_RGBD)
        return true;
    else
        return nmatchesMap>=10;  // 匹配超过10个点就认为跟踪成功
}

3.重定位跟踪 

1.计算当前帧特征点的词袋向量

2.找到与当前帧相似的候选关键帧

3.通过BoW进行匹配

4.通过EPnP算法估计姿态

5.通过PoseOptimization对姿态进行优化求解

6.如果内点较少,则通过投影的方式对之前未匹配的点进行匹配,再进行优化求解

新增内容: 

3和2的基本流程基本一样只不过将位姿估计方法中的EPnP(至少需要4对点)换成了MLPnP (至少需要6对点)。 

第二阶段跟踪新变化

局部地图跟踪

在2中仅优化位姿,当跟踪的地图点大于30个时,进认为跟踪成功了。 

而在3中:

1.如果IMU 未初始化或者虽然初始化成功但距离上次重定位时间比较近( 小于1s) , 则仅优化位姿。否则,如果地图未更换, 则使用上一普通帧及当前帧的视觉信息和IMU 信息联合优化当前帧位姿、速度和IMU 零偏;如果地图更换,则使用上一关键帧及当前这的视觉信息和IMU 信息联合优化当前帧位姿、速度和IMU 零偏。

2.定义跟踪成功。在RECENTLY_LOST 状态下, 至少成功跟踪10 个地图点才算成功。在IMU 模式下, 至少成功跟踪15 个地图点才算成功。若以上情况都不满足, 则只要跟踪的地图点大于30个,就认为成功跟踪。

/*
 用局部地图进行跟踪,进一步优化位姿
 1. 更新局部地图,包括局部关键帧和关键点
 2. 对局部MapPoints进行投影匹配
 3. 根据匹配对估计当前帧的姿态
 4. 根据姿态剔除误匹配
 return true if success
 * 
 1:更新局部关键帧mvpLocalKeyFrames和局部地图点mvpLocalMapPoints 
 2:在局部地图中查找与当前帧匹配的MapPoints, 其实也就是对局部地图点进行跟踪
 3:更新局部所有MapPoints后对位姿再次优化
 4:更新当前帧的MapPoints被观测程度,并统计跟踪局部地图的效果
 5:决定是否跟踪成功
 */
bool Tracking::TrackLocalMap()
{

    // We have an estimation of the camera pose and some map points tracked in the frame.
    // We retrieve the local map and try to find matches to points in the local map.
    mTrackedFr++;

    // Step 1:更新局部关键帧 mvpLocalKeyFrames 和局部地图点 mvpLocalMapPoints
    UpdateLocalMap();
    // Step 2:筛选局部地图中新增的在视野范围内的地图点,投影到当前帧搜索匹配,得到更多的匹配关系
    SearchLocalPoints();

    // TOO check outliers before PO
    // 查看内外点数目,调试用
    int aux1 = 0, aux2=0;
    for(int i=0; i<mCurrentFrame.N; i++)
        if( mCurrentFrame.mvpMapPoints[i])
        {
            aux1++;
            if(mCurrentFrame.mvbOutlier[i])
                aux2++;
        }

    // 在这个函数之前,在 Relocalization、TrackReferenceKeyFrame、TrackWithMotionModel 中都有位姿优化
    // Step 3:前面新增了更多的匹配关系,BA优化得到更准确的位姿
    int inliers;
    // IMU未初始化,仅优化位姿
    if (!mpAtlas->isImuInitialized())
        Optimizer::PoseOptimization(&mCurrentFrame);
    else
    {
        // 初始化,重定位,重新开启一个地图都会使mnLastRelocFrameId变化
        if(mCurrentFrame.mnId<=mnLastRelocFrameId+mnFramesToResetIMU)
        {
            Verbose::PrintMess("TLM: PoseOptimization ", Verbose::VERBOSITY_DEBUG);
            Optimizer::PoseOptimization(&mCurrentFrame);
        }
        else  // 如果积累的IMU数据量比较多,考虑使用IMU数据优化
        {
            // if(!mbMapUpdated && mState == OK) //  && (mnMatchesInliers>30))
            // mbMapUpdated变化见Tracking::PredictStateIMU()
            // 未更新地图
            if(!mbMapUpdated) //  && (mnMatchesInliers>30))
            {
                Verbose::PrintMess("TLM: PoseInertialOptimizationLastFrame ", Verbose::VERBOSITY_DEBUG);
                // 使用上一普通帧以及当前帧的视觉信息和IMU信息联合优化当前帧位姿、速度和IMU零偏
                inliers = Optimizer::PoseInertialOptimizationLastFrame(&mCurrentFrame); // , !mpLastKeyFrame->GetMap()->GetIniertialBA1());
            }
            else
            {
                Verbose::PrintMess("TLM: PoseInertialOptimizationLastKeyFrame ", Verbose::VERBOSITY_DEBUG);
                // 使用上一关键帧以及当前帧的视觉信息和IMU信息联合优化当前帧位姿、速度和IMU零偏
                inliers = Optimizer::PoseInertialOptimizationLastKeyFrame(&mCurrentFrame); // , !mpLastKeyFrame->GetMap()->GetIniertialBA1());
            }
        }
    }
    // 查看内外点数目,调试用
    aux1 = 0, aux2 = 0;
    for(int i=0; i<mCurrentFrame.N; i++)
        if( mCurrentFrame.mvpMapPoints[i])
        {
            aux1++;
            if(mCurrentFrame.mvbOutlier[i])
                aux2++;
        }

    mnMatchesInliers = 0;

    // Update MapPoints Statistics
    // Step 4:更新当前帧的地图点被观测程度,并统计跟踪局部地图后匹配数目
    for(int i=0; i<mCurrentFrame.N; i++)
    {
        if(mCurrentFrame.mvpMapPoints[i])
        {
            // 由于当前帧的地图点可以被当前帧观测到,其被观测统计量加1
            if(!mCurrentFrame.mvbOutlier[i])
            {
                // 找到该点的帧数mnFound 加 1
                mCurrentFrame.mvpMapPoints[i]->IncreaseFound();
                // 查看当前是否是在纯定位过程
                if(!mbOnlyTracking)
                {
                    // 如果该地图点被相机观测数目nObs大于0,匹配内点计数+1
                    // nObs: 被观测到的相机数目,单目+1,双目或RGB-D则+2
                    if(mCurrentFrame.mvpMapPoints[i]->Observations()>0)
                        mnMatchesInliers++;
                }
                else
                    // 记录当前帧跟踪到的地图点数目,用于统计跟踪效果
                    mnMatchesInliers++;
            }
            // 如果这个地图点是外点,并且当前相机输入还是双目的时候,就删除这个点
            // 原因分析:因为双目本身可以左右互匹配,删掉无所谓
            else if(mSensor==System::STEREO)
                mCurrentFrame.mvpMapPoints[i] = static_cast<MapPoint*>(NULL);
        }
    }

    // Decide if the tracking was succesful
    // More restrictive if there was a relocalization recently
    mpLocalMapper->mnMatchesInliers=mnMatchesInliers;
    // Step 5:根据跟踪匹配数目及重定位情况决定是否跟踪成功
    // 如果最近刚刚发生了重定位,那么至少成功匹配50个点才认为是成功跟踪
    if(mCurrentFrame.mnId<mnLastRelocFrameId+mMaxFrames && mnMatchesInliers<50)
        return false;

    // RECENTLY_LOST状态下,至少成功跟踪10个才算成功
    if((mnMatchesInliers>10)&&(mState==RECENTLY_LOST))
        return true;

    // 单目IMU模式下做完初始化至少成功跟踪15个才算成功,没做初始化需要50个
    if (mSensor == System::IMU_MONOCULAR)
    {
        if((mnMatchesInliers<15 && mpAtlas->isImuInitialized())||(mnMatchesInliers<50 && !mpAtlas->isImuInitialized()))
        {
            return false;
        }
        else
            return true;
    }
    else if (mSensor == System::IMU_STEREO || mSensor == System::IMU_RGBD)
    {
        if(mnMatchesInliers<15)
        {
            return false;
        }
        else
            return true;
    }
    else
    {
        //以上情况都不满足,只要跟踪的地图点大于30个就认为成功了
        if(mnMatchesInliers<30)
            return false;
        else
            return true;
    }
}

结束语

以上就是我学习到的内容,如果对您有帮助请多多支持我,如果哪里有问题欢迎大家在评论区积极讨论,我看到会及时回复。 

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐