1. 基本结构System类是ORB-SLAM2的主调度类也是ORB-SLAM2系统的入口。把关键代码提取出来进行标注。mpVocabulary new ORBVocabulary();//读取ORB词袋 mpKeyFrameDatabase new KeyFrameDatabase(*mpVocabulary);//创建关键帧数据库 mpMap new Map();//创建地图对象 mpFrameDrawer new FrameDrawer(mpMap);//创建显示关键帧的窗口 mpMapDrawer new MapDrawer(mpMap, strSettingsFile);//创建显示地图的窗口 mpTracker new Tracking(this, mpVocabulary, mpFrameDrawer, mpMapDrawer, mpMap, mpKeyFrameDatabase, strSettingsFile, mSensor);//初始化Tracking线程该线程在主循环中 mpLocalMapper new LocalMapping(mpMap, mSensorMONOCULAR);//初始化Local Mapping线程 mptLocalMapping new thread(ORB_SLAM2::LocalMapping::Run,mpLocalMapper);//启动线程 mpLoopCloser new LoopClosing(mpMap, mpKeyFrameDatabase, mpVocabulary, mSensor!MONOCULAR);//初始化LoopClosing线程 mptLoopClosing new thread(ORB_SLAM2::LoopClosing::Run, mpLoopCloser);//启动线程 mpViewer new Viewer(this, mpFrameDrawer,mpMapDrawer,mpTracker,strSettingsFile);//初始化窗口 mptViewer new thread(Viewer::Run, mpViewer);//启动前面会有一个是否可视化的判断从上面的代码来看构造函数system()主要对SLAM系统初始化。下面看看System.cc中的函数接口。cv::Mat System::TrackStereo(const cv::Mat imLeft, const cv::Mat imRight, const double timestamp)//追踪双目数据返回mpTracker-GrabImageStereo(imLeft,imRight,timestamp) cv::Mat System::TrackRGBD(const cv::Mat im, const cv::Mat depthmap, const double timestamp)//追踪深度相机数据返回mpTracker-GrabImageRGBD(im,depthmap,timestamp) cv::Mat System::TrackMonocular(const cv::Mat im, const double timestamp)//追踪单目相机数据返回mpTracker-GrabImageMonocular(im,timestamp) void System::ActivateLocalizationMode()//mbActivateLocalizationMode true激活 mbActivateLocalizationMode void System::DeactivateLocalizationMode()// mbDeactivateLocalizationMode true激活 mbDeactivateLocalizationMode void System::Shutdown()//判断运行是否结束结束则关闭系统 void System::SaveTrajectoryTUM(const string filename)//求数据集中每一帧的位姿 void System::SaveKeyFrameTrajectoryTUM(const string filename)//求数据集中每一关键帧的位姿 void System::SaveTrajectoryKITTI(const string filename)//求数据集中每一帧的位姿TrackStereo()、TrackRGBD()、TrackMonocular()判断输入传感器类型是否正确判断模式如果是mbActivateLocalizationMode则休眠1000ms直到停止局部建图。如果是mbDeactivateLocalizationMode则重新开启局部建图的线程。然后调用GrabImageStereo(imRectLeft, imRectRight)、GrabImageRGBD(im, depthmap)、GrabImageMonocular(im)开启tracking线程2. 构造函数//构建函数 /* input: 字典 类型monorgbdstereo,参数mapfile 是否导入地图 */ System::System(const string strVocFile, const eSensor sensor, ORBParameters parameters, const std::string map_file, bool load_map): // map serialization addition mSensor(sensor), mbReset(false),mbActivateLocalizationMode(false), mbDeactivateLocalizationMode(false), map_file(map_file), load_map(load_map)system构造函数参数包括离线训练的词袋字典文件名camera类型ORB特征点提取参数也可以增加已知地图纯定位功能。//Load ORB Vocabulary cout endl Loading ORB Vocabulary. endl; // 创建字典 mpVocabulary new ORBVocabulary(); //try to load from the binary file导入2进制文件 bool bVocLoad mpVocabulary-loadFromBinFile(strVocFile.bin);原始开源代码调用词典为txt文本众所周知读入txt的文本的速度十分耗时导致slam启动较慢。已有人将其改进为bin文件存储和读取以此可提高启动速度。// begin map serialization addition // load serialized map // 是否载入已有地图 if (load_map LoadMap(map_file)) { std::cout Using loaded map with mpMap-MapPointsInMap() points\n std::endl; } else { // 新建地图则需创建一个空的地图对象 //Create KeyFrame Database // 初始化关键帧数据对象主要存储字典里包含的值用于重定位和闭环 mpKeyFrameDatabase new KeyFrameDatabase(*mpVocabulary); //Create the Map // 创建map数据应该是特征点和对应的keypose mpMap new Map(); } // end map serialization additionorb-slam2开始slam时需创建一个新的空的map对象。同时更为重要创建一个KeyFrameDatabase对象此对象用于存储关键帧的在词典中的词袋向量后续的闭环和重定位也是基于此词袋数据进行搜索匹配。//Initialize the Tracking thread //(it will live in the main thread of execution, the one that called this constructor) // 初始化前端线程 mpTracker new Tracking(this, mpVocabulary, mpFrameDrawer, mpMap, mpKeyFrameDatabase, mSensor, parameters);初始化三个线程中tracking线程//Initialize the Local Mapping thread and launch // 初始化建图线程 mpLocalMapper new LocalMapping(mpMap, mSensorMONOCULAR); mptLocalMapping new thread(ORB_SLAM2::LocalMapping::Run,mpLocalMapper);初始化三个线程中Local Mapping线程//Initialize the Loop Closing thread and launch // 初始化闭环线程 mpLoopCloser new LoopClosing(mpMap, mpKeyFrameDatabase, mpVocabulary, mSensor!MONOCULAR); mptLoopClosing new thread(ORB_SLAM2::LoopClosing::Run, mpLoopCloser);初始化三个线程中loop closing线程//Set pointers between threads // 三个线程间存在联系 mpTracker-SetLocalMapper(mpLocalMapper); mpTracker-SetLoopClosing(mpLoopCloser); mpLocalMapper-SetTracker(mpTracker); mpLocalMapper-SetLoopCloser(mpLoopCloser); mpLoopCloser-SetTracker(mpTracker); mpLoopCloser-SetLocalMapper(mpLocalMapper); currently_localizing_only_ false; }3. 输出接口SaveTrajectoryTUM() void System::SaveTrajectoryTUM(const string filename) { ......//部分代码省略 vectorKeyFrame* vpKFs mpMap-GetAllKeyFrames();//获得所有关键帧vpKFs sort(vpKFs.begin(),vpKFs.end(),KeyFrame::lId);//对关键帧排序闭环检测后第一关键帧可能就不在起始位置了 cv::Mat Two vpKFs[0]-GetPoseInverse();//获得第一帧相对于世界坐标系的位姿 //遍历所有帧 ofstream f; f.open(filename.c_str()); f fixed; listORB_SLAM2::KeyFrame*::iterator lRit mpTracker-mlpReferences.begin();//参考关键帧迭代器 listdouble::iterator lT mpTracker-mlFrameTimes.begin();//时间戳迭代器 listbool::iterator lbL mpTracker-mlbLost.begin();//标志当追踪失败为true for(listcv::Mat::iterator litmpTracker-mlRelativeFramePoses.begin(), lendmpTracker-mlRelativeFramePoses.end();lit!lend;lit, lRit, lT, lbL) { if(*lbL) continue;//如果当前帧追踪失败则丢弃继续追踪下一帧 KeyFrame* pKF *lRit; cv::Mat Trw cv::Mat::eye(4,4,CV_32F); // If the reference keyframe was culled, traverse the spanning tree to get a suitable keyframe. while(pKF-isBad())//追踪成功但是关键帧不好则获取当前关键帧相对于上一帧的位姿并将上//一帧设为关键帧依次不断的判断关键帧的质量直到选取合适的关键帧 { Trw Trw*pKF-mTcp; pKF pKF-GetParent(); } Trw Trw*pKF-GetPose()*Two;//将关键帧的位姿乘第一帧相对于世界坐标的位姿得到关键帧相//对于世界坐标的位姿 cv::Mat Tcw (*lit)*Trw;//在将关键帧相对于世界坐标的位姿乘当前帧相对于关键帧的位姿得//到当前帧相对于世界坐标的位姿 cv::Mat Rwc Tcw.rowRange(0,3).colRange(0,3).t();//求旋转矩阵R cv::Mat twc -Rwc*Tcw.rowRange(0,3).col(3);//求t vectorfloat q Converter::toQuaternion(Rwc);//求四元数q f setprecision(6) *lT setprecision(9) twc.atfloat(0) twc.atfloat(1) twc.atfloat(2) q[0] q[1] q[2] q[3] endl; } f.close();//关闭文件 }SaveKeyFrameTrajectoryTUM()与SaveTrajectoryTUM()类似。4. 存在问题System类甚至整个ORB-SLAM代码中大量使用动态指针这是比较危险的因为动态指针需要手动释放内存较难管理如果想要进行工程化建议将其换为智能指针。在System类初始化的一些动态指针都没有在System的析构函数中释放内存。参考文献ORB-SLAM2从理论到代码实现二System.cc程序分析_波波菠菜的博客-CSDN博客ORB-slam2源码分析2- 程序入口system类_jiajiading的博客-CSDN博客