目录

一.前言

二.代码分析

2.1 引用头文件

2.2 静态成员变量

2.3 System函数


一.前言

    这部分代码介绍引用头文件以及System类的函数定义文件。

二.代码分析

2.1 引用头文件

#include "System.h"
#include "Converter.h"
#include <thread>
#include <pangolin/pangolin.h>
#include <iomanip>
#include <openssl/md5.h>
#include <boost/serialization/base_object.hpp>
#include <boost/serialization/string.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/xml_iarchive.hpp>
#include <boost/archive/xml_oarchive.hpp>
  1. #include "System.h"

    • 这是一个自定义头文件,可能包含了与系统相关的功能或类定义。
  2. #include "Converter.h"

    • 这也是一个自定义头文件,可能包含了转换功能或类定义。
  3. #include <thread>

    • 这是C++标准库中的线程头文件,提供了多线程编程的支持。
  4. #include <pangolin/pangolin.h>

    • Pangolin 是一个轻量级的 C++ 库,用于3D可视化和用户界面。此头文件是其主要接口。
  5. #include <iomanip>

    • 这是C++标准库中的一个输入输出流操作的头文件,提供了格式化输入输出的功能。
  6. #include <openssl/md5.h>

    • OpenSSL 是一个强大的安全套接字层密码库,此头文件提供了MD5哈希算法的支持。
  7. #include <boost/serialization/base_object.hpp>

    • Boost 是一个广泛使用的C++库,提供了许多实用的功能。这个头文件与序列化相关,用于支持对象的序列化。
  8. #include <boost/serialization/string.hpp>

    • 这是Boost库中关于字符串序列化的头文件。
  9. #include <boost/archive/text_iarchive.hpp>#include <boost/archive/text_oarchive.hpp>

    • 这两个头文件与Boost的文本存档相关,分别用于从文本文件中反序列化和序列化对象。
  10. #include <boost/archive/binary_iarchive.hpp>#include <boost/archive/binary_oarchive.hpp>

  • 这两个头文件与Boost的二进制存档相关,分别用于从二进制文件中反序列化和序列化对象。
  1. #include <boost/archive/xml_iarchive.hpp>#include <boost/archive/xml_oarchive.hpp>
  • 这两个头文件与Boost的XML存档相关,分别用于从XML文件中反序列化和序列化对象。

2.2 静态成员变量

  1. Verbose::eLevel Verbose::th = Verbose::VERBOSITY_NORMAL; 这行代码的意思是,声明一个类型为Verbose::eLevel的静态成员变量th,并将其初始化为Verbose::VERBOSITY_NORMAL。这通常是在类的定义外部进行的初始化,通常在源文件(.cpp文件)中而不是头文件(.h或.hpp文件)中。

这样的设置通常用于控制程序的日志记录或输出详细程度。例如,如果程序中有多个详细级别(如“简洁”、“正常”和“详细”),则可以通过更改th变量的值来轻松地在这些级别之间进行切换。

2.3 System函数

System::System(const string &strVocFile, const string &strSettingsFile, const eSensor sensor,
               const bool bUseViewer, const int initFr, const string &strSequence):
    mSensor(sensor), mpViewer(static_cast<Viewer*>(NULL)), mbReset(false), mbResetActiveMap(false),
    mbActivateLocalizationMode(false), mbDeactivateLocalizationMode(false), mbShutDown(false)
{
    // Output welcome message
    cout << endl <<
    "ORB-SLAM3 Copyright (C) 2017-2020 Carlos Campos, Richard Elvira, Juan J. Gómez, José M.M. Montiel and Juan D. Tardós, University of Zaragoza." << endl <<
    "ORB-SLAM2 Copyright (C) 2014-2016 Raúl Mur-Artal, José M.M. Montiel and Juan D. Tardós, University of Zaragoza." << endl <<
    "This program comes with ABSOLUTELY NO WARRANTY;" << endl  <<
    "This is free software, and you are welcome to redistribute it" << endl <<
    "under certain conditions. See LICENSE.txt." << endl << endl;

    cout << "Input sensor was set to: ";

    if(mSensor==MONOCULAR)
        cout << "Monocular" << endl;
    else if(mSensor==STEREO)
        cout << "Stereo" << endl;
    else if(mSensor==RGBD)
        cout << "RGB-D" << endl;
    else if(mSensor==IMU_MONOCULAR)
        cout << "Monocular-Inertial" << endl;
    else if(mSensor==IMU_STEREO)
        cout << "Stereo-Inertial" << endl;
    else if(mSensor==IMU_RGBD)
        cout << "RGB-D-Inertial" << endl;

    //Check settings file
    cv::FileStorage fsSettings(strSettingsFile.c_str(), cv::FileStorage::READ);
    if(!fsSettings.isOpened())
    {
       cerr << "Failed to open settings file at: " << strSettingsFile << endl;
       exit(-1);
    }

    cv::FileNode node = fsSettings["File.version"];
    if(!node.empty() && node.isString() && node.string() == "1.0"){
        settings_ = new Settings(strSettingsFile,mSensor);

        mStrLoadAtlasFromFile = settings_->atlasLoadFile();
        mStrSaveAtlasToFile = settings_->atlasSaveFile();

        cout << (*settings_) << endl;
    }
    else{
        settings_ = nullptr;
        cv::FileNode node = fsSettings["System.LoadAtlasFromFile"];
        if(!node.empty() && node.isString())
        {
            mStrLoadAtlasFromFile = (string)node;
        }

        node = fsSettings["System.SaveAtlasToFile"];
        if(!node.empty() && node.isString())
        {
            mStrSaveAtlasToFile = (string)node;
        }
    }

    node = fsSettings["loopClosing"];
    bool activeLC = true;
    if(!node.empty())
    {
        activeLC = static_cast<int>(fsSettings["loopClosing"]) != 0;
    }

    mStrVocabularyFilePath = strVocFile;

    bool loadedAtlas = false;

    if(mStrLoadAtlasFromFile.empty())
    {
        //Load ORB Vocabulary
        cout << endl << "Loading ORB Vocabulary. This could take a while..." << endl;

        mpVocabulary = new ORBVocabulary();
        bool bVocLoad = mpVocabulary->loadFromTextFile(strVocFile);
        if(!bVocLoad)
        {
            cerr << "Wrong path to vocabulary. " << endl;
            cerr << "Falied to open at: " << strVocFile << endl;
            exit(-1);
        }
        cout << "Vocabulary loaded!" << endl << endl;

        //Create KeyFrame Database
        mpKeyFrameDatabase = new KeyFrameDatabase(*mpVocabulary);

        //Create the Atlas
        cout << "Initialization of Atlas from scratch " << endl;
        mpAtlas = new Atlas(0);
    }
    else
    {
        //Load ORB Vocabulary
        cout << endl << "Loading ORB Vocabulary. This could take a while..." << endl;

        mpVocabulary = new ORBVocabulary();
        bool bVocLoad = mpVocabulary->loadFromTextFile(strVocFile);
        if(!bVocLoad)
        {
            cerr << "Wrong path to vocabulary. " << endl;
            cerr << "Falied to open at: " << strVocFile << endl;
            exit(-1);
        }
        cout << "Vocabulary loaded!" << endl << endl;

        //Create KeyFrame Database
        mpKeyFrameDatabase = new KeyFrameDatabase(*mpVocabulary);

        cout << "Load File" << endl;

        // Load the file with an earlier session
        //clock_t start = clock();
        cout << "Initialization of Atlas from file: " << mStrLoadAtlasFromFile << endl;
        bool isRead = LoadAtlas(FileType::BINARY_FILE);

        if(!isRead)
        {
            cout << "Error to load the file, please try with other session file or vocabulary file" << endl;
            exit(-1);
        }
        //mpKeyFrameDatabase = new KeyFrameDatabase(*mpVocabulary);


        //cout << "KF in DB: " << mpKeyFrameDatabase->mnNumKFs << "; words: " << mpKeyFrameDatabase->mnNumWords << endl;

        loadedAtlas = true;

        mpAtlas->CreateNewMap();

        //clock_t timeElapsed = clock() - start;
        //unsigned msElapsed = timeElapsed / (CLOCKS_PER_SEC / 1000);
        //cout << "Binary file read in " << msElapsed << " ms" << endl;

        //usleep(10*1000*1000);
    }


    if (mSensor==IMU_STEREO || mSensor==IMU_MONOCULAR || mSensor==IMU_RGBD)
        mpAtlas->SetInertialSensor();

    //Create Drawers. These are used by the Viewer
    mpFrameDrawer = new FrameDrawer(mpAtlas);
    mpMapDrawer = new MapDrawer(mpAtlas, strSettingsFile, settings_);

    //Initialize the Tracking thread
    //(it will live in the main thread of execution, the one that called this constructor)
    cout << "Seq. Name: " << strSequence << endl;
    mpTracker = new Tracking(this, mpVocabulary, mpFrameDrawer, mpMapDrawer,
                             mpAtlas, mpKeyFrameDatabase, strSettingsFile, mSensor, settings_, strSequence);

    //Initialize the Local Mapping thread and launch
    mpLocalMapper = new LocalMapping(this, mpAtlas, mSensor==MONOCULAR || mSensor==IMU_MONOCULAR,
                                     mSensor==IMU_MONOCULAR || mSensor==IMU_STEREO || mSensor==IMU_RGBD, strSequence);
    mptLocalMapping = new thread(&ORB_SLAM3::LocalMapping::Run,mpLocalMapper);
    mpLocalMapper->mInitFr = initFr;
    if(settings_)
        mpLocalMapper->mThFarPoints = settings_->thFarPoints();
    else
        mpLocalMapper->mThFarPoints = fsSettings["thFarPoints"];
    if(mpLocalMapper->mThFarPoints!=0)
    {
        cout << "Discard points further than " << mpLocalMapper->mThFarPoints << " m from current camera" << endl;
        mpLocalMapper->mbFarPoints = true;
    }
    else
        mpLocalMapper->mbFarPoints = false;

    //Initialize the Loop Closing thread and launch
    // mSensor!=MONOCULAR && mSensor!=IMU_MONOCULAR
    mpLoopCloser = new LoopClosing(mpAtlas, mpKeyFrameDatabase, mpVocabulary, mSensor!=MONOCULAR, activeLC); // mSensor!=MONOCULAR);
    mptLoopClosing = new thread(&ORB_SLAM3::LoopClosing::Run, mpLoopCloser);

    //Set pointers between threads
    mpTracker->SetLocalMapper(mpLocalMapper);
    mpTracker->SetLoopClosing(mpLoopCloser);

    mpLocalMapper->SetTracker(mpTracker);
    mpLocalMapper->SetLoopCloser(mpLoopCloser);

    mpLoopCloser->SetTracker(mpTracker);
    mpLoopCloser->SetLocalMapper(mpLocalMapper);

    //usleep(10*1000*1000);

    //Initialize the Viewer thread and launch
    if(bUseViewer)
    //if(false) // TODO
    {
        mpViewer = new Viewer(this, mpFrameDrawer,mpMapDrawer,mpTracker,strSettingsFile,settings_);
        mptViewer = new thread(&Viewer::Run, mpViewer);
        mpTracker->SetViewer(mpViewer);
        mpLoopCloser->mpViewer = mpViewer;
        mpViewer->both = mpFrameDrawer->both;
    }

    // Fix verbosity
    Verbose::SetTh(Verbose::VERBOSITY_QUIET);

}

这段代码是一个系统类的构造函数,它主要用于初始化ORB-SLAM3(一个用于视觉SLAM的开源库)的实例。这个构造函数接收一系列参数,并根据这些参数配置系统。

以下是对代码主要部分的详细解释:

  1. 参数解释

    • const string &strVocFile:ORB词汇表的文件路径,用于特征匹配。
    • const string &strSettingsFile:设置文件的路径,包含系统配置。
    • const eSensor sensor:传感器的类型(如单目、双目、RGB-D等)。
    • const bool bUseViewer:是否使用查看器。
    • const int initFr:初始化帧数(在这段代码中未使用)。
    • const string &strSequence:序列的文件路径(在这段代码中未使用)。
  2. 成员变量初始化:初始化一系列成员变量,如传感器类型、查看器指针、各种标志等。

  3. 输出欢迎信息:输出ORB-SLAM3的版权和许可信息。

  4. 检查传感器类型:根据传入的传感器类型,输出相应的信息。

  5. 加载设置文件:使用OpenCV的FileStorage类加载设置文件,并检查文件是否可以打开。然后,检查文件版本,并根据版本加载相应的设置。

  6. 加载或创建地图:根据是否提供了加载地图的文件路径,决定是从文件中加载地图还是从零开始创建地图。

  7. 加载ORB词汇表:从给定的文件路径加载ORB词汇表。如果加载失败,则输出错误信息并退出程序。

  8. 创建关键帧数据库和地图集:创建关键帧数据库和地图集对象。如果提供了加载文件的路径并且成功加载了地图,那么就从加载的文件中恢复这些信息;否则,创建一个新的地图集。

  9. 加载或初始化地图集:如果提供了加载文件并且成功加载了地图集,就使用加载的数据初始化地图集;否则,创建一个新的地图集并从零开始初始化。

  10. 错误处理:在加载地图集或词汇表时,如果遇到错误,程序将输出错误信息并退出。

总的来说,这个构造函数的主要目的是根据提供的参数和设置文件来初始化ORB-SLAM3系统,包括加载或创建地图集、加载ORB词汇表、设置传感器类型等。它是整个系统运行的起点,为后续的视觉SLAM任务(如定位、建图等)做好准备。

代码的最后对多线程,传感器的数据进行了初始化。

// 如果传感器是IMU_STEREO、IMU_MONOCULAR或IMU_RGBD,则为Atlas设置惯性传感器  
if (mSensor==IMU_STEREO || mSensor==IMU_MONOCULAR || mSensor==IMU_RGBD)  
    mpAtlas->SetInertialSensor();  
  
// 创建绘制器。这些由查看器使用  
mpFrameDrawer = new FrameDrawer(mpAtlas);  // 创建一个帧绘制器  
mpMapDrawer = new MapDrawer(mpAtlas, strSettingsFile, settings_);  // 创建一个地图绘制器  
  
// 初始化跟踪线程  
//(它将在调用此构造函数的主执行线程中运行)  
cout << "Seq. Name: " << strSequence << endl;  
mpTracker = new Tracking(this, mpVocabulary, mpFrameDrawer, mpMapDrawer,  
                         mpAtlas, mpKeyFrameDatabase, strSettingsFile, mSensor, settings_, strSequence);  
  
// 初始化本地映射线程并启动  
mpLocalMapper = new LocalMapping(this, mpAtlas, mSensor==MONOCULAR || mSensor==IMU_MONOCULAR,  
                                 mSensor==IMU_MONOCULAR || mSensor==IMU_STEREO || mSensor==IMU_RGBD, strSequence);  
mptLocalMapping = new thread(&ORB_SLAM3::LocalMapping::Run,mpLocalMapper);  
// ... 一些设置和条件检查 ...  
  
// 初始化闭环线程并启动  
// mSensor!=MONOCULAR && mSensor!=IMU_MONOCULAR  
mpLoopCloser = new LoopClosing(mpAtlas, mpKeyFrameDatabase, mpVocabulary, mSensor!=MONOCULAR, activeLC); // mSensor!=MONOCULAR);  
mptLoopClosing = new thread(&ORB_SLAM3::LoopClosing::Run, mpLoopCloser);  
  
// 在线程之间设置指针,以便它们可以相互通信和访问  
mpTracker->SetLocalMapper(mpLocalMapper);  
mpTracker->SetLoopClosing(mpLoopCloser);  
mpLocalMapper->SetTracker(mpTracker);  
mpLocalMapper->SetLoopCloser(mpLoopCloser);  
mpLoopCloser->SetTracker(mpTracker);  
mpLoopCloser->SetLocalMapper(mpLocalMapper);  
  
// 如果使用查看器,则初始化查看器线程并启动  
if(bUseViewer)  
{  
    mpViewer = new Viewer(this, mpFrameDrawer,mpMapDrawer,mpTracker,strSettingsFile,settings_);  
    mptViewer = new thread(&Viewer::Run, mpViewer);  
    // ... 设置查看器与其他线程的关联 ...  
}  
  
// 设置详细级别为“安静”,即不输出太多信息  
Verbose::SetTh(Verbose::VERBOSITY_QUIET);
12-27 00:47