欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

orb slam2 代码解析1

程序员文章站 2024-03-25 19:08:28
...

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;
};

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