fix some comments
							parent
							
								
									3fd2fcccb7
								
							
						
					
					
						commit
						a1174f1df8
					
				|  | @ -202,9 +202,9 @@ public: | |||
|     long unsigned int mnMergeQuery; | ||||
|     int mnMergeWords; | ||||
|     float mMergeScore; | ||||
|     long unsigned int mnPlaceRecognitionQuery; | ||||
|     long unsigned int mnPlaceRecognitionQuery; //标记该关键帧被当前关键帧访问到(也就是有公共单词),防止重复添加
 | ||||
|     int mnPlaceRecognitionWords; | ||||
|     float mPlaceRecognitionScore; | ||||
|     float mPlaceRecognitionScore; //记录该候选帧与当前帧的相似度
 | ||||
| 
 | ||||
|     bool mbCurrentPlaceRecognition; | ||||
| 
 | ||||
|  |  | |||
|  | @ -141,8 +141,8 @@ protected: | |||
| 
 | ||||
|     System *mpSystem; | ||||
| 
 | ||||
|     bool mbMonocular; | ||||
|     bool mbInertial; | ||||
|     bool mbMonocular;   //mSensor==MONOCULAR || mSensor==IMU_MONOCULAR
 | ||||
|     bool mbInertial;    //mSensor==IMU_MONOCULAR || mSensor==IMU_STEREO
 | ||||
| 
 | ||||
|     void ResetIfRequested(); | ||||
|     bool mbResetRequested; | ||||
|  | @ -178,10 +178,11 @@ protected: | |||
| 
 | ||||
|     bool mbAcceptKeyFrames; | ||||
|     std::mutex mMutexAccept; | ||||
| 
 | ||||
|     // IMU初始化函数,通过控制不同的参数来表示不同阶段
 | ||||
|     void InitializeIMU(float priorG = 1e2, float priorA = 1e6, bool bFirst = false); | ||||
|     // 单目惯性模式下优化尺度和重力方向
 | ||||
|     void ScaleRefinement(); | ||||
| 
 | ||||
|     //跟踪线程使用,如果为true,暂不添加关键帧
 | ||||
|     bool bInitializing; | ||||
| 
 | ||||
|     Eigen::MatrixXd infoInertial; | ||||
|  |  | |||
|  | @ -179,7 +179,7 @@ protected: | |||
|     int mnLoopNumCoincidences; | ||||
|     int mnLoopNumNotFound; | ||||
|     KeyFrame* mpLoopLastCurrentKF; | ||||
|     g2o::Sim3 mg2oLoopSlw; | ||||
|     g2o::Sim3 ; | ||||
|     g2o::Sim3 mg2oLoopScw; | ||||
|     KeyFrame* mpLoopMatchedKF; | ||||
|     std::vector<MapPoint*> mvpLoopMPs; | ||||
|  |  | |||
|  | @ -63,18 +63,20 @@ public: | |||
|     ~Tracking(); | ||||
| 
 | ||||
|     // Parse the config file
 | ||||
|     // 提取配置文件数据
 | ||||
|     bool ParseCamParamFile(cv::FileStorage &fSettings); | ||||
|     bool ParseORBParamFile(cv::FileStorage &fSettings); | ||||
|     bool ParseIMUParamFile(cv::FileStorage &fSettings); | ||||
| 
 | ||||
|     // Preprocess the input and call Track(). Extract features and performs stereo matching.
 | ||||
|     // 输入图像输出位姿Tcw
 | ||||
|     cv::Mat GrabImageStereo(const cv::Mat &imRectLeft,const cv::Mat &imRectRight, const double ×tamp, string filename); | ||||
|     cv::Mat GrabImageRGBD(const cv::Mat &imRGB,const cv::Mat &imD, const double ×tamp, string filename); | ||||
|     cv::Mat GrabImageMonocular(const cv::Mat &im, const double ×tamp, string filename); | ||||
|     // cv::Mat GrabImageImuMonocular(const cv::Mat &im, const double ×tamp);
 | ||||
| 
 | ||||
|     // 放置IMU数据
 | ||||
|     void GrabImuData(const IMU::Point &imuMeasurement); | ||||
| 
 | ||||
|     // 设置线程指针
 | ||||
|     void SetLocalMapper(LocalMapping* pLocalMapper); | ||||
|     void SetLoopClosing(LoopClosing* pLoopClosing); | ||||
|     void SetViewer(Viewer* pViewer); | ||||
|  | @ -82,23 +84,27 @@ public: | |||
| 
 | ||||
|     // Load new settings
 | ||||
|     // The focal lenght should be similar or scale prediction will fail when projecting points
 | ||||
|     // 更换新的标定参数,未使用
 | ||||
|     void ChangeCalibration(const string &strSettingPath); | ||||
| 
 | ||||
|     // Use this function if you have deactivated local mapping and you only want to localize the camera.
 | ||||
|     // 设置是否仅定位模式还是SLAM模式
 | ||||
|     void InformOnlyTracking(const bool &flag); | ||||
| 
 | ||||
|     // localmapping中更新了关键帧的位姿后,更新普通帧的位姿,通过IMU积分更新速度。localmapping中初始化imu中使用
 | ||||
|     void UpdateFrameIMU(const float s, const IMU::Bias &b, KeyFrame* pCurrentKeyFrame); | ||||
|     KeyFrame* GetLastKeyFrame() | ||||
|     { | ||||
|         return mpLastKeyFrame; | ||||
|     } | ||||
| 
 | ||||
|     // 新建地图
 | ||||
|     void CreateMapInAtlas(); | ||||
|     std::mutex mMutexTracks; | ||||
| 
 | ||||
|     //--
 | ||||
|     // 更新数据集
 | ||||
|     void NewDataset(); | ||||
|     // 获得数据集总数
 | ||||
|     int GetNumberDataset(); | ||||
|     // 获取匹配内点总数
 | ||||
|     int GetMatchesInliers(); | ||||
| public: | ||||
| 
 | ||||
|  | @ -122,7 +128,7 @@ public: | |||
| 
 | ||||
|     // Current Frame
 | ||||
|     Frame mCurrentFrame; | ||||
|     Frame mLastFrame; | ||||
|     Frame mLastFrame; //跟踪成功后,保存当前帧数据
 | ||||
| 
 | ||||
|     cv::Mat mImGray; | ||||
| 
 | ||||
|  | @ -135,6 +141,7 @@ public: | |||
| 
 | ||||
|     // Lists used to recover the full camera trajectory at the end of the execution.
 | ||||
|     // Basically we store the reference keyframe for each frame and its relative transformation
 | ||||
|     // 代码结束后保存位姿用的列表
 | ||||
|     list<cv::Mat> mlRelativeFramePoses; | ||||
|     list<KeyFrame*> mlpReferences; | ||||
|     list<double> mlFrameTimes; | ||||
|  | @ -145,6 +152,7 @@ public: | |||
|     bool mbStep; | ||||
| 
 | ||||
|     // True if local mapping is deactivated and we are performing only localization
 | ||||
|     // true表示仅定位模式,此时局部建图线程和闭环线程关闭
 | ||||
|     bool mbOnlyTracking; | ||||
| 
 | ||||
|     void Reset(bool bLocMap = false); | ||||
|  | @ -156,7 +164,7 @@ public: | |||
|     double t0vis; // time-stamp of first inserted keyframe
 | ||||
|     double t0IMU; // time-stamp of IMU initialization
 | ||||
| 
 | ||||
| 
 | ||||
|     // 获取局部地图点
 | ||||
|     vector<MapPoint*> GetLocalMapMPS(); | ||||
| 
 | ||||
|     bool mbWriteStats; | ||||
|  | @ -186,40 +194,41 @@ public: | |||
| protected: | ||||
| 
 | ||||
|     // Main tracking function. It is independent of the input sensor.
 | ||||
|     void Track(); | ||||
|     void Track();   //主要的跟踪函数
 | ||||
| 
 | ||||
|     // Map initialization for stereo and RGB-D
 | ||||
|     void StereoInitialization(); | ||||
|     void StereoInitialization();    //双目初始化
 | ||||
| 
 | ||||
|     // Map initialization for monocular
 | ||||
|     void MonocularInitialization(); | ||||
|     void CreateNewMapPoints(); | ||||
|     void MonocularInitialization(); //单目初始化
 | ||||
|     void CreateNewMapPoints();      //创建新的地图点
 | ||||
|     cv::Mat ComputeF12(KeyFrame *&pKF1, KeyFrame *&pKF2); | ||||
|     void CreateInitialMapMonocular(); | ||||
|     void CreateInitialMapMonocular();   //单目模式下创建初始化地图
 | ||||
| 
 | ||||
|     void CheckReplacedInLastFrame(); | ||||
|     bool TrackReferenceKeyFrame(); | ||||
|     void UpdateLastFrame(); | ||||
|     bool TrackWithMotionModel(); | ||||
|     bool PredictStateIMU(); | ||||
|     void CheckReplacedInLastFrame();//检查上一帧中的地图点是否需要被替换
 | ||||
|     bool TrackReferenceKeyFrame();  // 参考关键帧跟踪
 | ||||
|     void UpdateLastFrame();         //更新上一帧位姿,在上一帧中生成临时地图点
 | ||||
|     bool TrackWithMotionModel();    //恒速模型跟踪
 | ||||
|     bool PredictStateIMU();         //用IMU预测位姿
 | ||||
| 
 | ||||
|     bool Relocalization(); | ||||
|     bool Relocalization();          //重定位
 | ||||
| 
 | ||||
|     void UpdateLocalMap(); | ||||
|     void UpdateLocalPoints(); | ||||
|     void UpdateLocalKeyFrames(); | ||||
|     void UpdateLocalMap();          //更新局部地图
 | ||||
|     void UpdateLocalPoints();       //更新局部地图点
 | ||||
|     void UpdateLocalKeyFrames();    //更新局部地图里的关键帧
 | ||||
| 
 | ||||
|     bool TrackLocalMap(); | ||||
|     bool TrackLocalMap_old(); | ||||
|     void SearchLocalPoints(); | ||||
|     bool TrackLocalMap();           //局部地图跟踪
 | ||||
|     bool TrackLocalMap_old();       //未定义
 | ||||
|     void SearchLocalPoints();       //搜索局部地图点
 | ||||
| 
 | ||||
|     bool NeedNewKeyFrame(); | ||||
|     void CreateNewKeyFrame(); | ||||
|     bool NeedNewKeyFrame();         //判断是否需要插入关键帧
 | ||||
|     void CreateNewKeyFrame();       //创建关键帧
 | ||||
| 
 | ||||
|     // Perform preintegration from last frame
 | ||||
|     void PreintegrateIMU(); | ||||
|     void PreintegrateIMU();         //IMU预积分
 | ||||
| 
 | ||||
|     // Reset IMU biases and compute frame velocity
 | ||||
|     // 重置并重新计算IMU偏置。未使用
 | ||||
|     void ComputeGyroBias(const vector<Frame*> &vpFs, float &bwx,  float &bwy, float &bwz); | ||||
|     void ComputeVelocitiesAccBias(const vector<Frame*> &vpFs, float &bax,  float &bay, float &baz); | ||||
| 
 | ||||
|  | @ -230,14 +239,14 @@ protected: | |||
|     IMU::Preintegrated *mpImuPreintegratedFromLastKF; | ||||
| 
 | ||||
|     // Queue of IMU measurements between frames
 | ||||
|     std::list<IMU::Point> mlQueueImuData; | ||||
|     std::list<IMU::Point> mlQueueImuData;   //存放两帧之间的IMU数据
 | ||||
| 
 | ||||
|     // Vector of IMU measurements from previous to current frame (to be filled by PreintegrateIMU)
 | ||||
|     std::vector<IMU::Point> mvImuFromLastFrame; | ||||
|     std::mutex mMutexImuQueue; | ||||
| 
 | ||||
|     // Imu calibration parameters
 | ||||
|     IMU::Calib *mpImuCalib; | ||||
|     IMU::Calib *mpImuCalib;     //IMU标定参数
 | ||||
| 
 | ||||
|     // Last Bias Estimation (at keyframe creation)
 | ||||
|     IMU::Bias mLastBias; | ||||
|  | @ -249,10 +258,11 @@ protected: | |||
|     bool mbVO; | ||||
| 
 | ||||
|     //Other Thread Pointers
 | ||||
|     // 其他线程的指针
 | ||||
|     LocalMapping* mpLocalMapper; | ||||
|     LoopClosing* mpLoopClosing; | ||||
| 
 | ||||
|     //ORB
 | ||||
|     //ORB特征提取器
 | ||||
|     ORBextractor* mpORBextractorLeft, *mpORBextractorRight; | ||||
|     ORBextractor* mpIniORBextractor; | ||||
| 
 | ||||
|  | @ -297,13 +307,13 @@ protected: | |||
|     // Threshold close/far points
 | ||||
|     // Points seen as close by the stereo/RGBD sensor are considered reliable
 | ||||
|     // and inserted from just one frame. Far points requiere a match in two keyframes.
 | ||||
|     float mThDepth; | ||||
|     float mThDepth;             //近远点阈值,基线的倍数
 | ||||
| 
 | ||||
|     // For RGB-D inputs only. For some datasets (e.g. TUM) the depthmap values are scaled.
 | ||||
|     float mDepthMapFactor; | ||||
|     float mDepthMapFactor;      // RGB-D尺度缩放因子
 | ||||
| 
 | ||||
|     //Current matches in frame
 | ||||
|     int mnMatchesInliers; | ||||
|     int mnMatchesInliers;       //当前帧匹配内点数
 | ||||
| 
 | ||||
|     //Last Frame, KeyFrame and Relocalisation Info
 | ||||
|     KeyFrame* mpLastKeyFrame; | ||||
|  | @ -321,12 +331,12 @@ protected: | |||
| 
 | ||||
| 
 | ||||
|     //Motion Model
 | ||||
|     cv::Mat mVelocity; | ||||
|     cv::Mat mVelocity;      // 恒速模型的速度。通过位姿增量获得或者IMU积分得到
 | ||||
| 
 | ||||
|     //Color order (true RGB, false BGR, ignored if grayscale)
 | ||||
|     bool mbRGB; | ||||
| 
 | ||||
|     list<MapPoint*> mlpTemporalPoints; | ||||
|     list<MapPoint*> mlpTemporalPoints;  // 临时地图点
 | ||||
| 
 | ||||
|     //int nMapChangeIndex;
 | ||||
| 
 | ||||
|  | @ -340,7 +350,7 @@ protected: | |||
|     double mTime_LocalMapTrack; | ||||
|     double mTime_NewKF_Dec; | ||||
| 
 | ||||
|     GeometricCamera* mpCamera, *mpCamera2; | ||||
|     GeometricCamera* mpCamera, *mpCamera2;  //相机类
 | ||||
| 
 | ||||
|     int initID, lastID; | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										
											BIN
										
									
								
								outline.png
								
								
								
								
							
							
						
						
									
										
											BIN
										
									
								
								outline.png
								
								
								
								
							
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 915 KiB After Width: | Height: | Size: 112 KiB | 
|  | @ -1051,7 +1051,7 @@ void Frame::ComputeStereoMatches() | |||
|     // 金字塔顶层(0层)图像高 nRows
 | ||||
|     const int nRows = mpORBextractorLeft->mvImagePyramid[0].rows; | ||||
| 
 | ||||
| 	// 二维vector存储每一行的orb特征点的列坐标,为什么是vector,因为每一行的特征点有可能不一样,例如
 | ||||
| 	// 二维vector存储每一行的orb特征点的列坐标的索引,为什么是vector,因为每一行的特征点有可能不一样,例如
 | ||||
|     // vRowIndices[0] = [1,2,5,8, 11]   第1行有5个特征点,他们的列号(即x坐标)分别是1,2,5,8,11
 | ||||
|     // vRowIndices[1] = [2,6,7,9, 13, 17, 20]  第2行有7个特征点.etc
 | ||||
|     vector<vector<size_t> > vRowIndices(nRows,vector<size_t>()); | ||||
|  |  | |||
|  | @ -1648,7 +1648,7 @@ int Initializer::CheckRT(const cv::Mat &R, const cv::Mat &t, const vector<cv::Ke | |||
|         if(cosParallax<0.99998) | ||||
|             vbGood[vMatches12[i].first]=true; | ||||
|     } | ||||
| 
 | ||||
|     // Step 7 得到3D点中较小的视差角,并且转换成为角度制表示
 | ||||
|     if(nGood>0) | ||||
|     { | ||||
|         // 从小到大排序,注意vCosParallax值越大,视差越小
 | ||||
|  |  | |||
|  | @ -691,7 +691,7 @@ void KeyFrameDatabase::DetectNBestCandidates(KeyFrame *pKF, vector<KeyFrame*> &v | |||
|                     // 如果该关键帧不是当前关键帧的共视关键帧
 | ||||
|                     if(!spConnectedKF.count(pKFi)) | ||||
|                     { | ||||
|                         // 标记改关键帧被当前关键帧访问到
 | ||||
|                         // 标记该关键帧被当前关键帧访问到(也就是有公共单词)
 | ||||
|                         pKFi->mnPlaceRecognitionQuery=pKF->mnId; | ||||
|                         // 把当前关键帧添加到有公共单词的关键帧列表中
 | ||||
|                         lKFsSharingWords.push_back(pKFi); | ||||
|  | @ -713,7 +713,7 @@ void KeyFrameDatabase::DetectNBestCandidates(KeyFrame *pKF, vector<KeyFrame*> &v | |||
|         return; | ||||
| 
 | ||||
|     // Only compare against those keyframes that share enough words
 | ||||
|     // Step 2 统计所有候选帧中与当前关键帧的公共单词数最多的单词数,并筛选
 | ||||
|     // Step 2 统计所有候选帧中与当前关键帧的公共单词数最多的单词数maxCommonWords,并筛选
 | ||||
|     int maxCommonWords=0; | ||||
|     for(list<KeyFrame*>::iterator lit=lKFsSharingWords.begin(), lend= lKFsSharingWords.end(); lit!=lend; lit++) | ||||
|     { | ||||
|  | @ -738,7 +738,7 @@ void KeyFrameDatabase::DetectNBestCandidates(KeyFrame *pKF, vector<KeyFrame*> &v | |||
|         // 如果当前帧的公共单词数大于minCommonWords
 | ||||
|         if(pKFi->mnPlaceRecognitionWords>minCommonWords) | ||||
|         { | ||||
|             nscores++; | ||||
|             nscores++;  //未使用
 | ||||
|             // 计算相似度
 | ||||
|             float si = mpVoc->score(pKF->mBowVec,pKFi->mBowVec); | ||||
|             // 记录该候选帧与当前帧的相似度
 | ||||
|  | @ -773,12 +773,12 @@ void KeyFrameDatabase::DetectNBestCandidates(KeyFrame *pKF, vector<KeyFrame*> &v | |||
|         for(vector<KeyFrame*>::iterator vit=vpNeighs.begin(), vend=vpNeighs.end(); vit!=vend; vit++) | ||||
|         { | ||||
|             KeyFrame* pKF2 = *vit; | ||||
|             // 如果改关键帧没有被当前关键帧访问过(这里标记的是有没有公共单词)则跳过
 | ||||
|             // 如果该关键帧没有被当前关键帧访问过(也就是没有公共单词)则跳过
 | ||||
|             if(pKF2->mnPlaceRecognitionQuery!=pKF->mnId) | ||||
|                 continue; | ||||
|             // 累加小组总分
 | ||||
|             accScore+=pKF2->mPlaceRecognitionScore; | ||||
|             // 如果大与组内最高分,则重新记录
 | ||||
|             // 如果大于组内最高分,则更新当前最高分记录
 | ||||
|             if(pKF2->mPlaceRecognitionScore>bestScore) | ||||
|             { | ||||
|                 pBestKF=pKF2; | ||||
|  | @ -806,7 +806,7 @@ void KeyFrameDatabase::DetectNBestCandidates(KeyFrame *pKF, vector<KeyFrame*> &v | |||
|     //for(list<pair<float,KeyFrame*> >::iterator it=lAccScoreAndMatch.begin(), itend=lAccScoreAndMatch.end(); it!=itend; it++)
 | ||||
|     int i = 0; | ||||
|     list<pair<float,KeyFrame*> >::iterator it=lAccScoreAndMatch.begin(); | ||||
|     // 遍历lAccScoreAndMatch中所有的pair, 每个pair为<小组总相似度,组内相似度最高的关键帧指针>
 | ||||
|     // 遍历lAccScoreAndMatch中所有的pair, 每个pair为<小组总相似度,组内相似度最高的关键帧指针>,nNumCandidates默认为3
 | ||||
|     while(i < lAccScoreAndMatch.size() && (vpLoopCand.size() < nNumCandidates || vpMergeCand.size() < nNumCandidates)) | ||||
|     { | ||||
|         //cout << "Accum score: " << it->first << endl;
 | ||||
|  |  | |||
|  | @ -174,6 +174,7 @@ void LocalMapping::Run() | |||
|                         // 判断成功跟踪匹配的点数是否足够多
 | ||||
|                         // 条件---------1.1、跟踪成功的内点数目大于75-----1.2、并且是单目--或--2.1、跟踪成功的内点数目大于100-----2.2、并且不是单目             
 | ||||
|                         bool bLarge = ((mpTracker->GetMatchesInliers()>75)&&mbMonocular)||((mpTracker->GetMatchesInliers()>100)&&!mbMonocular); | ||||
|                         // 局部地图+IMU一起优化,优化关键帧位姿、地图点、IMU参数
 | ||||
|                         Optimizer::LocalInertialBA(mpCurrentKeyFrame, &mbAbortBA, mpCurrentKeyFrame->GetMap(),num_FixedKF_BA,num_OptKF_BA,num_MPs_BA,num_edges_BA, bLarge, !mpCurrentKeyFrame->GetMap()->GetIniertialBA2()); | ||||
|                         b_doneLBA = true; | ||||
|                     } | ||||
|  | @ -182,6 +183,7 @@ void LocalMapping::Run() | |||
| 						// Step 6.2 不是IMU模式或者当前关键帧所在的地图还未完成IMU初始化
 | ||||
| 						// 局部地图BA,不包括IMU数据
 | ||||
| 						// 注意这里的第二个参数是按地址传递的,当这里的 mbAbortBA 状态发生变化时,能够及时执行/停止BA
 | ||||
|                         // 局部地图优化,不包括IMU信息。优化关键帧位姿、地图点
 | ||||
|                         Optimizer::LocalBundleAdjustment(mpCurrentKeyFrame,&mbAbortBA, mpCurrentKeyFrame->GetMap(),num_FixedKF_BA,num_OptKF_BA,num_MPs_BA,num_edges_BA); | ||||
|                         b_doneLBA = true; | ||||
|                     } | ||||
|  | @ -233,7 +235,7 @@ void LocalMapping::Run() | |||
|                 timeKFCulling_ms = std::chrono::duration_cast<std::chrono::duration<double,std::milli> >(time_EndKFCulling - time_EndLBA).count(); | ||||
|                 vdKFCullingSync_ms.push_back(timeKFCulling_ms); | ||||
| #endif | ||||
| 				// Step 9 如果距离初始化成功累计时间差小于100s 并且 是IMU模式,进行VIBA
 | ||||
| 				// Step 9 如果距离IMU第一阶段初始化成功累计时间差小于100s,进行VIBA
 | ||||
|                 if ((mTinit<100.0f) && mbInertial) | ||||
|                 { | ||||
|                     // Step 9.1 根据条件判断是否进行VIBA1(IMU第二阶段初始化)
 | ||||
|  | @ -283,6 +285,7 @@ void LocalMapping::Run() | |||
|                                 (mTinit>75.0f && mTinit<75.5f))){ | ||||
|                             cout << "start scale ref" << endl; | ||||
|                             if (mbMonocular) | ||||
|                                 // 使用了所有关键帧,但只优化尺度和重力方向
 | ||||
|                                 ScaleRefinement(); | ||||
|                             cout << "end scale ref" << endl; | ||||
|                         } | ||||
|  | @ -1236,12 +1239,12 @@ void LocalMapping::KeyFrameCulling() | |||
|     vector<KeyFrame*> vpLocalKeyFrames = mpCurrentKeyFrame->GetVectorCovisibleKeyFrames(); | ||||
| 
 | ||||
|     float redundant_th; | ||||
|     // 非IMU时
 | ||||
|     // 非IMU模式时
 | ||||
|     if(!mbInertial) | ||||
|         redundant_th = 0.9; | ||||
|     else if (mbMonocular)	// imu 且单目时
 | ||||
|     else if (mbMonocular)	// 单目+imu 时
 | ||||
|         redundant_th = 0.9; | ||||
|     else	// 其他imu时
 | ||||
|     else	// 双目+imu时
 | ||||
|         redundant_th = 0.5; | ||||
| 
 | ||||
|     const bool bInitImu = mpAtlas->isImuInitialized(); | ||||
|  | @ -1268,7 +1271,7 @@ void LocalMapping::KeyFrameCulling() | |||
|     { | ||||
|         count++; | ||||
|         KeyFrame* pKF = *vit; | ||||
| 
 | ||||
|         // 如果是地图里第1个关键帧或者是标记为坏帧,则跳过
 | ||||
|         if((pKF->mnId==pKF->GetMap()->GetInitKFid()) || pKF->isBad()) | ||||
|             continue; | ||||
|         // Step 2:提取每个共视关键帧的地图点
 | ||||
|  | @ -1291,7 +1294,7 @@ void LocalMapping::KeyFrameCulling() | |||
|                 { | ||||
|                     if(!mbMonocular) | ||||
|                     { | ||||
|                         // 对于双目,仅考虑近处(不超过基线的 35倍 )的地图点
 | ||||
|                         // 对于双目,仅考虑近处(不超过基线的40倍 )的地图点
 | ||||
|                         if(pKF->mvDepth[i]>pKF->mThDepth || pKF->mvDepth[i]<0) | ||||
|                             continue; | ||||
|                     } | ||||
|  | @ -1768,7 +1771,7 @@ void LocalMapping::InitializeIMU(float priorG, float priorA, bool bFIBA) | |||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * @brief 通过BA优化进行尺度更新,关键帧小于100,在这里的时间段内时多次进行尺度更新 | ||||
|  * @brief 通过BA优化进行尺度更新,关键帧小于100,使用了所有关键帧的信息,但只优化尺度和重力方向。每10s在这里的时间段内时多次进行尺度更新 | ||||
|  */ | ||||
| void LocalMapping::ScaleRefinement() | ||||
| { | ||||
|  | @ -1799,6 +1802,8 @@ void LocalMapping::ScaleRefinement() | |||
| 
 | ||||
|     const int N = vpKF.size(); | ||||
|     // 2. 更新旋转与尺度
 | ||||
| 
 | ||||
|     // 待优化变量的初值
 | ||||
|     mRwg = Eigen::Matrix3d::Identity(); | ||||
|     mScale=1.0; | ||||
| 
 | ||||
|  |  | |||
|  | @ -43,7 +43,7 @@ LoopClosing::LoopClosing(Atlas *pAtlas, KeyFrameDatabase *pDB, ORBVocabulary *pV | |||
|     mpLastCurrentKF = static_cast<KeyFrame*>(NULL); | ||||
| } | ||||
| 
 | ||||
| // 设置追踪线程句柄
 | ||||
| // 设置跟踪线程句柄
 | ||||
| void LoopClosing::SetTracker(Tracking *pTracker) | ||||
| { | ||||
|     mpTracker=pTracker; | ||||
|  | @ -393,7 +393,7 @@ bool LoopClosing::NewDetectCommonRegions() | |||
|     // Loop candidates
 | ||||
|     bool bLoopDetectedInKF = false; | ||||
|     bool bCheckSpatial = false; | ||||
|     // Step 3.1 回环的时序几何校验: 这里的判断条件里mnLoopNumCoincidences刚开始为0, 所以可以先跳过看后面
 | ||||
|     // Step 3.1 回环的时序几何校验。注意初始化时mnLoopNumCoincidences=0, 所以可以先跳过看后面
 | ||||
|     // 如果回环的共视几何验证成功帧数目大于0
 | ||||
|     if(mnLoopNumCoincidences > 0) | ||||
|     { | ||||
|  | @ -475,7 +475,7 @@ bool LoopClosing::NewDetectCommonRegions() | |||
| 
 | ||||
|     //Merge candidates
 | ||||
|     bool bMergeDetectedInKF = false; | ||||
|     // Step 3.2 融合的时序几何校验: 这里的判断条件里mnMergeNumCoincidences刚开始为0, 所以可以先跳过看后面
 | ||||
|     // Step 3.2 融合的时序几何校验: 注意初始化时mnMergeNumCoincidences=0, 所以可以先跳过看后面
 | ||||
|     // 如果融合的共视几何验证成功帧数目大于0
 | ||||
|     if(mnMergeNumCoincidences > 0) | ||||
|     { | ||||
|  | @ -550,6 +550,7 @@ bool LoopClosing::NewDetectCommonRegions() | |||
|         } | ||||
|     } | ||||
|     // Step 3.3 若校验成功则把当前帧添加进数据库,且返回true表示找到共同区域
 | ||||
|     // 注意初始化时mbMergeDetected=mbLoopDetected=false
 | ||||
|     if(mbMergeDetected || mbLoopDetected) | ||||
|     { | ||||
|         //f_time_pr << "Geo" << " " << timeGeoKF_ms.count() << endl;
 | ||||
|  | @ -606,6 +607,8 @@ bool LoopClosing::NewDetectCommonRegions() | |||
|     // Step 4.1 若当前关键帧没有被检测到回环,并且候选帧数量不为0,则对回环候选帧进行论文中第8页的2-5步
 | ||||
|     if(!bLoopDetectedInKF && !vpLoopBowCand.empty()) | ||||
|     { | ||||
|         // mnLoopNumCoincidences是成功几何验证的帧数,超过3就认为几何验证成功,不超过继续进行时序验证
 | ||||
|         // mpLoopMatchedKF 最后成功匹配的候选关键帧
 | ||||
|         mbLoopDetected = DetectCommonRegionsFromBoW(vpLoopBowCand, mpLoopMatchedKF, mpLoopLastCurrentKF, mg2oLoopSlw, mnLoopNumCoincidences, mvpLoopMPs, mvpLoopMatchedMPs); | ||||
|     } | ||||
|     // Merge candidates
 | ||||
|  | @ -614,6 +617,7 @@ bool LoopClosing::NewDetectCommonRegions() | |||
|     // Step 4.2 若当前关键帧没有被检测到融合,并且候选帧数量不为0,则对融合候帧进行论文中第8页的2-5步
 | ||||
|     if(!bMergeDetectedInKF && !vpMergeBowCand.empty()) | ||||
|     { | ||||
|         // mnLoopNumCoincidences是成功几何验证的帧数,超过3就认为几何验证成功,不超过继续进行时序验证
 | ||||
|         mbMergeDetected = DetectCommonRegionsFromBoW(vpMergeBowCand, mpMergeMatchedKF, mpMergeLastCurrentKF, mg2oMergeSlw, mnMergeNumCoincidences, mvpMergeMPs, mvpMergeMatchedMPs); | ||||
|     } | ||||
| 
 | ||||
|  | @ -679,17 +683,16 @@ bool LoopClosing::DetectAndReffineSim3FromLastKF(KeyFrame* pCurrentKF, KeyFrame* | |||
| 
 | ||||
|         // 单目情况下不锁定尺度
 | ||||
|         bool bFixedScale = mbFixScale;       // TODO CHECK; Solo para el monocular inertial
 | ||||
|         // 如果是imu模式且地图没成熟,不锁定尺度
 | ||||
|         // 如果是imu模式且未完成初始化,不锁定尺度
 | ||||
|         if(mpTracker->mSensor==System::IMU_MONOCULAR && !pCurrentKF->GetMap()->GetIniertialBA2()) | ||||
|             bFixedScale=false; | ||||
|         // 继续优化 Sim3
 | ||||
|         int numOptMatches = Optimizer::OptimizeSim3(mpCurrentKF, pMatchedKF, vpMatchedMPs, gScm, 10, bFixedScale, mHessian7x7, true); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|         // 若果匹配的数量大于一定的数目
 | ||||
|         // 若匹配的数量大于一定的数目
 | ||||
|         if(numOptMatches > nProjOptMatches) | ||||
|         { | ||||
|             //!bug, 以下gScw_estimation应该通过上述sim3优化后的位姿来更新。以下mScw应该改为 gscm * gswm.t
 | ||||
|             g2o::Sim3 gScw_estimation(Converter::toMatrix3d(mScw.rowRange(0, 3).colRange(0, 3)), | ||||
|                            Converter::toVector3d(mScw.rowRange(0, 3).col(3)),1.0); | ||||
| 
 | ||||
|  | @ -718,14 +721,14 @@ bool LoopClosing::DetectAndReffineSim3FromLastKF(KeyFrame* pCurrentKF, KeyFrame* | |||
|  * 4. 利用地图中的共视关键帧验证(共视几何校验) | ||||
|  *  | ||||
|  * @param[in] vpBowCand bow 给出的一些候选关键帧 | ||||
|  * @param[out] pMatchedKF2 最后成功匹配的关键帧 | ||||
|  * @param[out] pMatchedKF2 最后成功匹配的候选关键帧 | ||||
|  * @param[out] pLastCurrentKF 用于记录当前关键帧为上一个关键帧(后续若仍需要时序几何校验需要记录此信息) | ||||
|  * @param[out] g2oScw 世界坐标系在当前关键帧下的Sim3 | ||||
|  * @param[out] nNumCoincidences 用来记录validation合格的数目 | ||||
|  * @param[out] nNumCoincidences 成功几何验证的帧数,超过3就认为几何验证成功,不超过继续进行时序验证 | ||||
|  * @param[out] vpMPs  所有地图点 | ||||
|  * @param[out] vpMatchedMPs 成功匹配的地图点  | ||||
|  * @return true 检测到一个合格的commen region | ||||
|  * @return false 没检测到一个合格的commen region  | ||||
|  * @return true 检测到一个合格的共同区域 | ||||
|  * @return false 没检测到一个合格的共同区域 | ||||
|  */ | ||||
| bool LoopClosing::DetectCommonRegionsFromBoW(std::vector<KeyFrame*> &vpBowCand, KeyFrame* &pMatchedKF2, KeyFrame* &pLastCurrentKF, g2o::Sim3 &g2oScw, | ||||
|                                              int &nNumCoincidences, std::vector<MapPoint*> &vpMPs, std::vector<MapPoint*> &vpMatchedMPs) | ||||
|  | @ -758,7 +761,7 @@ bool LoopClosing::DetectCommonRegionsFromBoW(std::vector<KeyFrame*> &vpBowCand, | |||
|     int nNumGuidedMatching = 0; | ||||
| 
 | ||||
|     // Varibles to select the best numbe
 | ||||
|     // 一些用与统计最优数据的变量,我们最后返回的是最佳的一个关键帧(几何校验匹配数最高的)
 | ||||
|     // 一些用于统计最优数据的变量,我们最后返回的是最佳的一个关键帧(几何校验匹配数最高的)
 | ||||
| 
 | ||||
|     KeyFrame* pBestMatchedKF; | ||||
|     int nBestMatchesReproj = 0; | ||||
|  | @ -772,10 +775,9 @@ bool LoopClosing::DetectCommonRegionsFromBoW(std::vector<KeyFrame*> &vpBowCand, | |||
|     // 这三个变量是作者为了后面打印观察记录的信息,可以忽略
 | ||||
|     vector<int> vnStage(numCandidates, 0); | ||||
|     vector<int> vnMatchesStage(numCandidates, 0); | ||||
| 
 | ||||
|     int index = 0; | ||||
| 
 | ||||
|     //对于每个候选关键帧
 | ||||
|     //对于每个候选关键帧,进行Sim3计算和检验
 | ||||
|     for(KeyFrame* pKFi : vpBowCand) | ||||
|     { | ||||
|         //cout << endl << "-------------------------------" << endl;
 | ||||
|  | @ -811,7 +813,7 @@ bool LoopClosing::DetectCommonRegionsFromBoW(std::vector<KeyFrame*> &vpBowCand, | |||
| 
 | ||||
|         // 记录在W_km中有最多匹配点的帧的局部index, 这个后面没有用到
 | ||||
|         int nIndexMostBoWMatchesKF=0; | ||||
|         //! bug: 并没有重新赋值pMostBoWMatchesKF, 一直是初始值: 候选关键帧 
 | ||||
|         //! bug: 以下循环中并没有重新赋值pMostBoWMatchesKF, 一直是初始值: 候选关键帧 
 | ||||
|         // 遍历窗口内Wm的每个关键帧
 | ||||
|         // Step 1.1 通过Bow寻找候选帧窗口内的关键帧地图点与当前关键帧的匹配点
 | ||||
|         for(int j=0; j<vpCovKFi.size(); ++j) | ||||
|  | @ -834,7 +836,7 @@ bool LoopClosing::DetectCommonRegionsFromBoW(std::vector<KeyFrame*> &vpBowCand, | |||
|         for(int j=0; j<vpCovKFi.size(); ++j) | ||||
|         {    | ||||
| 
 | ||||
|             // 如果窗口中的帧是当前帧的共视帧帧则结束这个循环
 | ||||
|             // 如果窗口中的帧是当前帧的共视帧则结束这个循环
 | ||||
|             if(spConnectedKeyFrames.find(vpCovKFi[j]) != spConnectedKeyFrames.end()) | ||||
|             { | ||||
|                 bAbortByNearKF = true; | ||||
|  | @ -849,11 +851,11 @@ bool LoopClosing::DetectCommonRegionsFromBoW(std::vector<KeyFrame*> &vpBowCand, | |||
|             { | ||||
|                 // 地图点指针
 | ||||
|                 MapPoint* pMPi_j = vvpMatchedMPs[j][k]; | ||||
|                 // 如果指针为空活地图点被标记为bad,则跳过当前循环
 | ||||
|                 // 如果指针为空或地图点被标记为bad,则跳过当前循环
 | ||||
|                 if(!pMPi_j || pMPi_j->isBad()) | ||||
|                     continue; | ||||
| 
 | ||||
|                 // 窗口内不同关键帧与当前关键帧可能能看到相同的3D点, 利用辅助容器避免重复添加
 | ||||
|                 // 窗口内不同关键帧与当前关键帧可能看到相同的3D点, 利用辅助容器避免重复添加
 | ||||
|                 if(spMatchedMPi.find(pMPi_j) == spMatchedMPi.end()) | ||||
|                 { | ||||
|                     // 利用辅助容器记录添加过的点
 | ||||
|  | @ -871,6 +873,7 @@ bool LoopClosing::DetectCommonRegionsFromBoW(std::vector<KeyFrame*> &vpBowCand, | |||
|         //cout <<"BoW: " << numBoWMatches << " independent putative matches" << endl;
 | ||||
|         // 当窗口内的帧不是当前关键帧的相邻帧且匹配点足够多时
 | ||||
|         // Step 2 利用RANSAC寻找候选关键帧窗口与当前关键帧的相对位姿T_am的初始值(可能是Sim3)
 | ||||
|         // nBoWMatches = 20; // 最低bow匹配特征点数
 | ||||
|         if(!bAbortByNearKF && numBoWMatches >= nBoWMatches) // TODO pick a good threshold
 | ||||
|         { | ||||
|             /*cout << "-------------------------------" << endl;
 | ||||
|  | @ -879,7 +882,7 @@ bool LoopClosing::DetectCommonRegionsFromBoW(std::vector<KeyFrame*> &vpBowCand, | |||
|             // Geometric validation
 | ||||
| 
 | ||||
|             bool bFixedScale = mbFixScale; | ||||
|             //? 如果是单目带imu的模式且地图没有成熟则不固定scale 
 | ||||
|             // 如果是单目带imu的模式且IMU初始化未完成第三阶段,则不固定scale 
 | ||||
|             if(mpTracker->mSensor==System::IMU_MONOCULAR && !mpCurrentKF->GetMap()->GetIniertialBA2()) | ||||
|                 bFixedScale=false; | ||||
| 
 | ||||
|  | @ -887,7 +890,7 @@ bool LoopClosing::DetectCommonRegionsFromBoW(std::vector<KeyFrame*> &vpBowCand, | |||
|             // Sim3Solver 的接口与orbslam2略有不同, 因为现在是1-N的对应关系
 | ||||
|             Sim3Solver solver = Sim3Solver(mpCurrentKF, pMostBoWMatchesKF, vpMatchedPoints, bFixedScale, vpKeyFrameMatchedMP); | ||||
|             //Sim3Solver Ransac 置信度0.99,至少20个inliers 最多300次迭
 | ||||
|             solver.SetRansacParameters(0.99, nBoWInliers, 300); // at least 15 inliers
 | ||||
|             solver.SetRansacParameters(0.99, nBoWInliers, 300); // at least 15 inliers, nBoWInliers = 15
 | ||||
| 
 | ||||
|             bool bNoMore = false; | ||||
|             vector<bool> vbInliers; | ||||
|  | @ -962,17 +965,18 @@ bool LoopClosing::DetectCommonRegionsFromBoW(std::vector<KeyFrame*> &vpBowCand, | |||
|                 // Step 3.1 重新利用之前计算的mScw信息, 通过投影寻找更多的匹配点
 | ||||
|                 int numProjMatches = matcher.SearchByProjection(mpCurrentKF, mScw, vpMapPoints, vpKeyFrames, vpMatchedMP, vpMatchedKF, 8, 1.5); | ||||
| 
 | ||||
|                 // 如果拿到了足够多的匹配点
 | ||||
|                 // 如果拿到了足够多的匹配点, nProjMatches = 50
 | ||||
|                 if(numProjMatches >= nProjMatches) | ||||
|                 { | ||||
|                     // Optimize Sim3 transformation with every matches
 | ||||
|                     Eigen::Matrix<double, 7, 7> mHessian7x7; | ||||
| 
 | ||||
|                     bool bFixedScale = mbFixScale; | ||||
|                     // 在imu模式下没有成熟的地图就不固定scale
 | ||||
|                     // 在imu模式下imu未完成第3阶段初始化就不固定scale
 | ||||
|                     if(mpTracker->mSensor==System::IMU_MONOCULAR && !mpCurrentKF->GetMap()->GetIniertialBA2()) | ||||
|                         bFixedScale=false; | ||||
|                     // Step 3.2 利用搜索到的更多的匹配点优化双向投影误差得到的更好的 gScm (Tam)
 | ||||
|                     // Step 3.2 利用搜索到的更多的匹配点用Sim3优化投影误差得到的更好的 gScm (Tam)
 | ||||
|                     // pKFi是候选关键帧
 | ||||
|                     int numOptMatches = Optimizer::OptimizeSim3(mpCurrentKF, pKFi, vpMatchedMP, gScm, 10, mbFixScale, mHessian7x7, true); | ||||
|                     //cout <<"BoW: " << numOptMatches << " inliers in the Sim3 optimization" << endl;
 | ||||
|                     //cout << "Inliers in Sim3 optimization: " << numOptMatches << endl;
 | ||||
|  | @ -992,8 +996,7 @@ bool LoopClosing::DetectCommonRegionsFromBoW(std::vector<KeyFrame*> &vpBowCand, | |||
|                         // 5 : 半径的增益系数(对比之前下降了)---> 更小的半径, 1.0 , hamming distance 的阀值增益系数---> 允许更小的距离
 | ||||
|                         int numProjOptMatches = matcher.SearchByProjection(mpCurrentKF, mScw, vpMapPoints, vpMatchedMP, 5, 1.0); | ||||
|                         //cout <<"BoW: " << numProjOptMatches << " matches after of the Sim3 optimization" << endl;
 | ||||
|                         // ? 论文中说好的再优化一次呢?只做了搜索并没有再次进行OptimizeSim3
 | ||||
|                         // 当新的投影得到的内点数量大于nProjOptMatches时
 | ||||
|                         // 当新的投影得到的内点数量大于nProjOptMatches=80时
 | ||||
|                         if(numProjOptMatches >= nProjOptMatches) | ||||
|                         { | ||||
|                             // Step 4. 用当前关键帧的相邻关键来验证前面得到的Tam(共视几何校验)
 | ||||
|  | @ -1061,7 +1064,7 @@ bool LoopClosing::DetectCommonRegionsFromBoW(std::vector<KeyFrame*> &vpBowCand, | |||
|     if(nBestMatchesReproj > 0) | ||||
|     { | ||||
|         pLastCurrentKF = mpCurrentKF; | ||||
|         nNumCoincidences = nBestNumCoindicendes; | ||||
|         nNumCoincidences = nBestNumCoindicendes; // 成功几何验证的帧数
 | ||||
|         pMatchedKF2 = pBestMatchedKF; | ||||
|         pMatchedKF2->SetNotErase(); | ||||
|         g2oScw = g2oBestScw; | ||||
|  | @ -1164,7 +1167,7 @@ bool LoopClosing::DetectCommonRegionsFromLastKF(KeyFrame* pCurrentKF, KeyFrame* | |||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * @brief 包装与searchByProjection之上, 只不过是把窗口内的所有地图点往当前关键帧上投影, 寻找匹配点 | ||||
|  * @brief 包装了一下searchByProjection, 把窗口内的所有地图点往当前关键帧上投影, 寻找匹配点 | ||||
|  *  | ||||
|  * @param[in] pCurrentKF 当前关键帧 | ||||
|  * @param[in] pMatchedKFw 候选帧 | ||||
|  |  | |||
|  | @ -42,6 +42,7 @@ ORBmatcher::ORBmatcher(float nnratio, bool checkOri): mfNNratio(nnratio), mbChec | |||
| { | ||||
| } | ||||
| 
 | ||||
| // 用于Tracking::SearchLocalPoints中匹配更多地图点
 | ||||
| int ORBmatcher::SearchByProjection(Frame &F, const vector<MapPoint*> &vpMapPoints, const float th, const bool bFarPoints, const float thFarPoints) | ||||
| { | ||||
|     int nmatches=0, left = 0, right = 0; | ||||
|  |  | |||
|  | @ -4304,7 +4304,7 @@ int Optimizer::OptimizeSim3(KeyFrame *pKF1, KeyFrame *pKF2, vector<MapPoint *> & | |||
|  * @param[in] pKF               //关键帧
 | ||||
|  * @param[in] pbStopFlag        //是否停止的标志
 | ||||
|  * @param[in] pMap              //地图
 | ||||
|  * @param[in] num_fixedKF       //
 | ||||
|  * @param[in] num_fixedKF       //固定不优化关键帧的数目
 | ||||
|  * @param[in] num_OptKF  | ||||
|  * @param[in] num_MPs  | ||||
|  * @param[in] num_edges  | ||||
|  | @ -6027,7 +6027,7 @@ void Optimizer::LocalBundleAdjustment(KeyFrame* pMainKF,vector<KeyFrame*> vpAdju | |||
|     bool bShowImages = false; | ||||
| 
 | ||||
|     vector<MapPoint*> vpMPs; | ||||
| // 1. 构建g2o优化器
 | ||||
|     // 1. 构建g2o优化器
 | ||||
|     g2o::SparseOptimizer optimizer; | ||||
|     g2o::BlockSolver_6_3::LinearSolverType * linearSolver; | ||||
| 
 | ||||
|  |  | |||
|  | @ -1454,7 +1454,7 @@ void Tracking::GrabImuData(const IMU::Point &imuMeasurement) | |||
|     mlQueueImuData.push_back(imuMeasurement); | ||||
| } | ||||
| 
 | ||||
| // ?TODO
 | ||||
| // 对IMU进行预积分
 | ||||
| void Tracking::PreintegrateIMU() | ||||
| { | ||||
|     // Step 1.拿到两两帧之间待处理的预积分数据,组成一个集合 
 | ||||
|  | @ -1838,7 +1838,7 @@ void Tracking::Track() | |||
|                 if(mpAtlas->isImuInitialized()) | ||||
|                 { | ||||
|                     cout << "Timestamp jump detected. State set to LOST. Reseting IMU integration..." << endl; | ||||
|                     // ?TODO BA2标志代表什么?,BA优化成功?
 | ||||
|                     // IMU完成第2阶段BA(在localmapping线程里)
 | ||||
|                     if(!pCurrentMap->GetIniertialBA2()) | ||||
|                     { | ||||
|                         // 如果当前子图中imu没有经过BA2,重置active地图
 | ||||
|  | @ -1862,7 +1862,7 @@ void Tracking::Track() | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // Step 3 IMU模式下设置IMU的Bias参数,还要保证上一帧存在非空
 | ||||
|     // Step 3 IMU模式下设置IMU的Bias参数,还要保证上一帧存在
 | ||||
|     if ((mSensor == System::IMU_MONOCULAR || mSensor == System::IMU_STEREO) && mpLastKeyFrame) | ||||
|         //认为bias在两帧间不变
 | ||||
|         mCurrentFrame.SetNewBias(mpLastKeyFrame->GetImuBias()); | ||||
|  | @ -1873,7 +1873,7 @@ void Tracking::Track() | |||
|     } | ||||
| 
 | ||||
|     mLastProcessedState=mState; | ||||
|     // Step 4 IMU模式下对IMU数据进行预积分:没有创建地图的情况下
 | ||||
|     // Step 4 IMU模式且没有创建地图的情况下对IMU数据进行预积分
 | ||||
|     if ((mSensor == System::IMU_MONOCULAR || mSensor == System::IMU_STEREO) && !mbCreatedMap) | ||||
|     { | ||||
| #ifdef REGISTER_TIMES | ||||
|  | @ -1906,6 +1906,7 @@ void Tracking::Track() | |||
|     if(nCurMapChangeIndex>nMapChangeIndex) | ||||
|     { | ||||
|         // cout << "Map update detected" << endl;
 | ||||
|         // 检测到地图更新了
 | ||||
|         pCurrentMap->SetLastMapChange(nCurMapChangeIndex); | ||||
|         mbMapUpdated = true; | ||||
|     } | ||||
|  | @ -2276,22 +2277,23 @@ void Tracking::Track() | |||
|         } | ||||
| 
 | ||||
|         // Save frame if recent relocalization, since they are used for IMU reset (as we are making copy, it shluld be once mCurrFrame is completely modified)
 | ||||
|         // 如果刚刚发生重定位并且IMU已经初始化,则保存当前帧信息,重置IMU
 | ||||
|         if((mCurrentFrame.mnId<(mnLastRelocFrameId+mnFramesToResetIMU)) &&          // 当前帧距离上次重定位帧小于1s
 | ||||
|         (mCurrentFrame.mnId > mnFramesToResetIMU) &&                                // 当前帧已经运行了超过1s
 | ||||
|         ((mSensor == System::IMU_MONOCULAR) || (mSensor == System::IMU_STEREO)) &&  // IMU模式
 | ||||
|         pCurrentMap->isImuInitialized())                                            // IMU已经成功初始化
 | ||||
|         { | ||||
|             // ?TODO check this situation
 | ||||
|             // 存储指针
 | ||||
|             Verbose::PrintMess("Saving pointer to frame. imu needs reset...", Verbose::VERBOSITY_NORMAL); | ||||
|             Frame* pF = new Frame(mCurrentFrame); | ||||
|             pF->mpPrevFrame = new Frame(mLastFrame); | ||||
| 
 | ||||
|             // Load preintegration
 | ||||
|             // ?构造预积分处理器
 | ||||
|             // IMU重置
 | ||||
|             pF->mpImuPreintegratedFrame = new IMU::Preintegrated(mCurrentFrame.mpImuPreintegratedFrame); | ||||
|         } | ||||
| 
 | ||||
|         if(pCurrentMap->isImuInitialized())     // IMU成功初始化
 | ||||
|         // 下面代码看起来没有用
 | ||||
|         if(pCurrentMap->isImuInitialized())      | ||||
|         { | ||||
|             if(bOK)     // 跟踪成功
 | ||||
|             { | ||||
|  | @ -3223,7 +3225,7 @@ bool Tracking::TrackWithMotionModel() | |||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     // 如果还是不能够获得足够的匹配点,那么就认为跟踪失败
 | ||||
|     // 这里不同于ORB-SLAM2的方式
 | ||||
|     if(nmatches<20) | ||||
|     { | ||||
|         Verbose::PrintMess("Not enough matches!!", Verbose::VERBOSITY_NORMAL); | ||||
|  | @ -3337,13 +3339,14 @@ bool Tracking::TrackLocalMap() | |||
|     // Step 3:前面新增了更多的匹配关系,BA优化得到更准确的位姿
 | ||||
|     int inliers; | ||||
|     if (!mpAtlas->isImuInitialized()) | ||||
|         // IMU未初始化,仅优化位姿
 | ||||
|         Optimizer::PoseOptimization(&mCurrentFrame); | ||||
|     else | ||||
|     { | ||||
|         // 初始化,重定位,重新开启一个地图都会使mnLastRelocFrameId变化
 | ||||
|         if(mCurrentFrame.mnId<=mnLastRelocFrameId+mnFramesToResetIMU) | ||||
|         { | ||||
|             // 如果距离上次重定位时间比较近,积累的IMU数据较少,优化时暂不使用IMU数据
 | ||||
|             // 如果距离上次重定位时间比较近(<1s),积累的IMU数据较少,优化时暂不使用IMU数据
 | ||||
|             Verbose::PrintMess("TLM: PoseOptimization ", Verbose::VERBOSITY_DEBUG); | ||||
|             Optimizer::PoseOptimization(&mCurrentFrame); | ||||
|         } | ||||
|  | @ -3468,13 +3471,15 @@ bool Tracking::TrackLocalMap() | |||
|  */ | ||||
| bool Tracking::NeedNewKeyFrame() | ||||
| { | ||||
|     // 如果是IMU模式并且当前地图中未完成IMU初始化
 | ||||
|     if(((mSensor == System::IMU_MONOCULAR) || (mSensor == System::IMU_STEREO)) && !mpAtlas->GetCurrentMap()->isImuInitialized()) | ||||
|     { | ||||
|         // 如果是IMU模式,当前帧距离上一关键帧时间戳超过0.25s,则说明需要插入关键帧,不再进行后续判断
 | ||||
|         if (mSensor == System::IMU_MONOCULAR && (mCurrentFrame.mTimeStamp-mpLastKeyFrame->mTimeStamp)>=0.25) | ||||
|             return true; | ||||
|         else if (mSensor == System::IMU_STEREO && (mCurrentFrame.mTimeStamp-mpLastKeyFrame->mTimeStamp)>=0.25) | ||||
|             return true; | ||||
|         else | ||||
|         else    // 否则,则说明不需要插入关键帧,不再进行后续判断
 | ||||
|             return false; | ||||
|     } | ||||
| 	// Step 1:纯VO模式下不插入关键帧
 | ||||
|  | @ -3560,7 +3565,7 @@ bool Tracking::NeedNewKeyFrame() | |||
|         thRefRatio = 0.9f; | ||||
| 
 | ||||
|     if(mpCamera2) thRefRatio = 0.75f; | ||||
| 
 | ||||
|     //单目+IMU情况下如果,匹配内点数目超过350,插入关键帧的频率可以适当降低  
 | ||||
|     if(mSensor==System::IMU_MONOCULAR) | ||||
|     { | ||||
|         if(mnMatchesInliers>350) // Points tracked from the local map
 | ||||
|  | @ -3577,13 +3582,14 @@ bool Tracking::NeedNewKeyFrame() | |||
|     const bool c1b = ((mCurrentFrame.mnId>=mnLastKeyFrameId+mMinFrames) && bLocalMappingIdle); | ||||
|     //Condition 1c: tracking is weak
 | ||||
| 	// Step 7.4:在双目,RGB-D的情况下当前帧跟踪到的点比参考关键帧的0.25倍还少,或者满足bNeedToInsertClose
 | ||||
|     const bool c1c = mSensor!=System::MONOCULAR && mSensor!=System::IMU_MONOCULAR && mSensor!=System::IMU_STEREO &&  //只考虑在双目,RGB-D的情况
 | ||||
|     const bool c1c = mSensor!=System::MONOCULAR && mSensor!=System::IMU_MONOCULAR && mSensor!=System::IMU_STEREO &&  //只考虑在纯双目,RGB-D的情况
 | ||||
| 	(mnMatchesInliers<nRefMatches*0.25 || 			//当前帧和地图点匹配的数目非常少
 | ||||
| 	bNeedToInsertClose) ;							//需要插入
 | ||||
|     // Condition 2: Few tracked points compared to reference keyframe. Lots of visual odometry compared to map matches.
 | ||||
|     // Step 7.5:和参考帧相比当前跟踪到的点太少 或者满足bNeedToInsertClose;同时跟踪到的内点还不能太少
 | ||||
|     const bool c2 = (((mnMatchesInliers<nRefMatches*thRefRatio || bNeedToInsertClose)) && mnMatchesInliers>15); | ||||
| 
 | ||||
|     // 新增的条件c3:单目/双目+IMU模式下,并且IMU完成了初始化(隐藏条件),当前帧和上一关键帧之间时间超过0.5秒,则c3=true
 | ||||
|     // Temporal condition for Inertial cases
 | ||||
|     bool c3 = false; | ||||
|     if(mpLastKeyFrame) | ||||
|  | @ -3600,12 +3606,14 @@ bool Tracking::NeedNewKeyFrame() | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // 新增的条件c4:单目+IMU模式下,当前帧匹配内点数在15~75之间或者是RECENTLY_LOST状态,c4=true
 | ||||
|     bool c4 = false; | ||||
|     if ((((mnMatchesInliers<75) && (mnMatchesInliers>15)) || mState==RECENTLY_LOST) && ((mSensor == System::IMU_MONOCULAR))) // MODIFICATION_2, originally ((((mnMatchesInliers<75) && (mnMatchesInliers>15)) || mState==RECENTLY_LOST) && ((mSensor == System::IMU_MONOCULAR)))
 | ||||
|         c4=true; | ||||
|     else | ||||
|         c4=false; | ||||
| 
 | ||||
|     // 相比ORB-SLAM2多了c3,c4
 | ||||
|     if(((c1a||c1b||c1c) && c2)||c3 ||c4) | ||||
|     { | ||||
|         // If the mapping accepts keyframes, insert keyframe.
 | ||||
|  | @ -3621,7 +3629,7 @@ bool Tracking::NeedNewKeyFrame() | |||
|             mpLocalMapper->InterruptBA(); | ||||
|             if(mSensor!=System::MONOCULAR  && mSensor!=System::IMU_MONOCULAR) | ||||
|             { | ||||
|                 // 队列里不能阻塞太多关键帧
 | ||||
|                 // 双目或双目+IMU或RGB-D模式下,如队列里没有阻塞太多关键帧,可以插入
 | ||||
|                 // tracking插入关键帧不是直接插入,而且先插入到mlNewKeyFrames中,
 | ||||
|                 // 然后localmapper再逐个pop出来插入到mspKeyFrames
 | ||||
|                 if(mpLocalMapper->KeyframesInQueue()<3) | ||||
|  | @ -3963,6 +3971,7 @@ void Tracking::UpdateLocalKeyFrames() | |||
|     // Each map point vote for the keyframes in which it has been observed
 | ||||
|     // Step 1:遍历当前帧的地图点,记录所有能观测到当前帧地图点的关键帧
 | ||||
|     map<KeyFrame*,int> keyframeCounter; | ||||
|     // 如果IMU未初始化 或者 刚刚完成重定位
 | ||||
|     if(!mpAtlas->isImuInitialized() || (mCurrentFrame.mnId<mnLastRelocFrameId+2)) | ||||
|     { | ||||
|         for(int i=0; i<mCurrentFrame.N; i++) | ||||
|  | @ -3991,6 +4000,7 @@ void Tracking::UpdateLocalKeyFrames() | |||
|     } | ||||
|     else | ||||
|     { | ||||
|         // ?为什么IMU初始化后用mLastFrame?mLastFrame存储的是上一帧跟踪成功后帧数据。
 | ||||
|         for(int i=0; i<mLastFrame.N; i++) | ||||
|         { | ||||
|             // Using lastframe since current frame has not matches yet
 | ||||
|  | @ -4112,6 +4122,7 @@ void Tracking::UpdateLocalKeyFrames() | |||
|     } | ||||
| 
 | ||||
|     // Add 10 last temporal KFs (mainly for IMU)
 | ||||
|     // IMU模式下增加了临时的关键帧
 | ||||
|     if((mSensor == System::IMU_MONOCULAR || mSensor == System::IMU_STEREO) &&mvpLocalKeyFrames.size()<80) | ||||
|     { | ||||
|         //cout << "CurrentKF: " << mCurrentFrame.mnId << endl;
 | ||||
|  |  | |||
|  | @ -1148,15 +1148,17 @@ int TwoViewReconstruction::CheckRT(const cv::Mat &R, const cv::Mat &t, const vec | |||
|         if (cosParallax < 0.99998) | ||||
|             vbGood[vMatches12[i].first] = true; | ||||
|     } | ||||
|     // 步骤8:得到3D点中较大的视差角
 | ||||
|     // 7 得到3D点中较小的视差角,并且转换成为角度制表示
 | ||||
|     if (nGood > 0) | ||||
|     { | ||||
|         // 从小到大排序
 | ||||
|         // 从小到大排序,注意vCosParallax值越大,视差越小
 | ||||
|         sort(vCosParallax.begin(), vCosParallax.end()); | ||||
| 
 | ||||
|         // trick! 排序后并没有取最大的视差角
 | ||||
|         // 取一个较大的视差角
 | ||||
|         // !排序后并没有取最小的视差角,而是取一个较小的视差角
 | ||||
| 		// 作者的做法:如果经过检验过后的有效3D点小于50个,那么就取最后那个最小的视差角(cos值最大)
 | ||||
| 		// 如果大于50个,就取排名第50个的较小的视差角即可,为了避免3D点太多时出现太小的视差角 
 | ||||
|         size_t idx = min(50, int(vCosParallax.size() - 1)); | ||||
|         //将这个选中的角弧度制转换为角度制
 | ||||
|         parallax = acos(vCosParallax[idx]) * 180 / CV_PI; | ||||
|     } | ||||
|     else | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue