orb slam2 代码解析1

orb slam 2 代码解析1

orb slam 2 是一个完整的SLAM系统,包括了 VO,跟踪,及回环,是一种基於单目稀疏特征点的slam系统,使用orb 特征 作为视觉slam的特征点,有以下的特点。

  • 使用ORB特征,实时性好
  • 使用词袋模型进行回环检测,g2o图优化
  • 支持多种传感器 单目、双目、RGB-D
  • 支持ROS

我们主要是看看其中的代码实现。

git clone https://github.com/stevenlovegrove/Pangolin.git #下载代码

安装过程忽略,可自行搜索教程

打开下载代码的路径,主要有以下文件夹

  • camke_modules #cmake 相关项,搜索需要的库
  • Examples # 使用示例,包括ros下的示例,注意orbslam2主要代码编译之后只是生成库orb_slam2的动态库
  • include # 主实现代码头文件
  • src #实现代码
  • Thirdparty #第三方依赖库,源码下载及编译
  • Vocabulary #词袋模型

根据这个文件组织结构,代码阅读课从示例代码开始

决定预先看单目实现代码,我们挑选 /Examples/Monocular/mono_kitti.cc 文件作为解析的范例代码,看文件名就知道这个示例是使用kitti 数据集,而不需要使用真正的摄像头。

void LoadImages(const string &strSequence, vector<string> &vstrImageFilenames,
                vector<double> &vTimestamps); //前置声明一个图像加载函数,实现在最后,主要实现读取文件路径及名称到vstrImageFilenames 里

接下来,我们看下main函数,看下整个系统的运行流程,(只挑选核心代码,精简所有主功能无关代码)


LoadImages(string(argv[3]), vstrImageFilenames, vTimestamps); //加载文件名称
ORB_SLAM2::System SLAM(argv[1],argv[2],ORB_SLAM2::System::MONOCULAR,true); //orb slam 核心管理类,所有功能都在这里实现

cv::Mat im;
for(int ni=0; ni<nImages; ni++)  //根据路径一张张读图像
{
    im = cv::imread(vstrImageFilenames[ni],CV_LOAD_IMAGE_UNCHANGED); //读图

    // Pass the image to the SLAM system
    SLAM.TrackMonocular(im,tframe);  //跟踪及解析每张图

}
SLAM.Shutdown(); //关闭slam,释放资源,锁等

SLAM.SaveKeyFrameTrajectoryTUM("KeyFrameTrajectory.txt");  /存取关键帧,主要存储信息为关键帧的 R t矩阵 R转换为四元数表示 

至此,我们看完了,处理流程,但由于主要的处理均在TrackMonocular函数中,所以我们需要再去分析 TrackMonocular 函数的实现,也即去看System.cc文件。

要阅读system文件,可先看头文件,了解大体的数据结构及功能,再看详细的代码实现,我们阅读代码的目的一般有以下几个

  • 分析问题的整体解决及结构
  • 关注实现过程的语言技巧及细节
  • 关注算法实现思路
  • 用来对原有库进行某种修改或扩展

对于orb_slam 这样的库,更重要的是算法实现和整体工程解决思路,所以我们更关注1,3点,第4点也可以关注,我们也会在其中分析如果需要修改时,可以怎么去实现相关功能

//System.h 简化版(数据结构部分,函数下回分解)

class System
{
public:
    enum eSensor{
        MONOCULAR=0,  //传感器类型,单目,双目,RGBD
        STEREO=1,
        RGBD=2
    };
public:
    System(const string &strVocFile, const string &strSettingsFile, const eSensor sensor, const bool bUseViewer = true);    
    cv::Mat TrackStereo(const cv::Mat &imLeft, const cv::Mat &imRight, const double &timestamp);   
    cv::Mat TrackRGBD(const cv::Mat &im, const cv::Mat &depthmap, const double &timestamp);  
    cv::Mat TrackMonocular(const cv::Mat &im, const double &timestamp);   
    void ActivateLocalizationMode();
    void DeactivateLocalizationMode();
    bool MapChanged();  
    void Reset();  
    void Shutdown();
    void SaveTrajectoryTUM(const string &filename);
    void SaveKeyFrameTrajectoryTUM(const string &filename);
    void SaveTrajectoryKITTI(const string &filename);
    int GetTrackingState();
    std::vector<MapPoint*> GetTrackedMapPoints();
    std::vector<cv::KeyPoint> GetTrackedKeyPointsUn();

private:

    eSensor mSensor; //传感器类型定义
    ORBVocabulary* mpVocabulary; //词袋模型,用于位置识别和特征匹配
    KeyFrameDatabase* mpKeyFrameDatabase; //关键帧数据结构,使用vector<keyframe*> 实现,存储关键帧
    Map* mpMap; //地图 存储 mappoint keyframe 所有的指针
    Tracking* mpTracker; //关键类,跟踪帧,并估计变换和相机位置,确定是否为关键帧,创建新的mappoint 并且当跟踪失败时重新定位
    LocalMapping* mpLocalMapper; //局部地图,管理局部地图并执行局部BA(优化)
    LoopClosing* mpLoopCloser; //回环检测,对每一个新的关键帧进行回环搜索,如果发现有回环则在新线程执行图优化和全局BA
    Viewer* mpViewer;//绘制地图和当前相机位置

    FrameDrawer* mpFrameDrawer; //帧绘制
    MapDrawer* mpMapDrawer;//地图绘制

    // System threads: Local Mapping, Loop Closing, Viewer.
    // The Tracking thread "lives" in the main execution thread that creates the System object.
    std::thread* mptLocalMapping; //关键实现,orb采用三线程并行处理,提高实时性能,此为局部绘图线程
    std::thread* mptLoopClosing; //回环检测及处理线程
    std::thread* mptViewer; //展示线程,绘制相关交互界面线程

    // 使用三个锁和一些标志位实现 资源分配及调度 重置/ 模式改变/跟踪

    std::mutex mMutexReset;  
    bool mbReset;

    std::mutex mMutexMode;
    bool mbActivateLocalizationMode;
    bool mbDeactivateLocalizationMode;

    int mTrackingState;
    std::vector<MapPoint*> mTrackedMapPoints;
    std::vector<cv::KeyPoint> mTrackedKeyPointsUn;
    std::mutex mMutexState;
};

至此,本次简单分析就到这里啦。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章