ORBSLAM2代码阅读-mono-tum.cc

代码:

#include<iostream>
#include<algorithm>
#include<fstream>
#include<chrono>

#include<opencv2/core/core.hpp>
#include <unistd.h>
#include<System.h>

using namespace std;


void LoadImages(const string &strFile, vector<string> &vstrImageFilenames, vector<double> &vTimestamps)
{
    ifstream f;//文件读操作,存储设备读区到内存中
    f.open(strFile.c_str());

    // skip first three lines
    string s0;
    getline(f,s0);
    getline(f,s0);
    getline(f,s0);

    while(!f.eof())
    {
        string s;
        getline(f,s);
        if(!s.empty())
        {
            stringstream ss;
            ss << s;
            double t;//每行格式长这样:1305033527.670034 rgb/1305033527.670034.png
            string sRGB;
            ss >> t;//字符串变成double
            vTimestamps.push_back(t);//把t加到 vTimestamps后面
            ss >> sRGB;
            vstrImageFilenames.push_back(sRGB);//把sRGB 加到vstrImageFilenames 后面
        }
    }
}

int main(int argc, char **argv)
{
    if(argc != 4)
    {
        cerr << endl << "Usage: ./mono_tum path_to_vocabulary path_to_settings path_to_sequence" << endl;
        return 1;
    }

    // Retrieve paths to images
    vector<string> vstrImageFilenames;
    vector<double> vTimestamps;
    string strFile = string(argv[3])+"/rgb.txt";//strFile 指向rgb.txt的路径
    LoadImages(strFile, vstrImageFilenames, vTimestamps);//获取每一幅图片路径

    int nImages = vstrImageFilenames.size();//获取 vstrImageFilenames的元素个数

    // Create SLAM system. It initializes all system threads and gets ready to process frames.
    ORB_SLAM2::System SLAM(argv[1],argv[2],ORB_SLAM2::System::MONOCULAR,true);

// Vector for tracking time statistics
    vector<float> vTimesTrack;
    vTimesTrack.resize(nImages);// vTimesTrack和vstrImageFilenames的元素个数一样


    cout << endl << "-------" << endl;
    cout << "Start processing sequence ..." << endl;
    cout << "Images in the sequence: " << nImages << endl << endl;

    // Main loop
    cv::Mat im;
    for(int ni=0; ni<nImages; ni++)
    {
        // Read image from file
        im = cv::imread(string(argv[3])+"/"+vstrImageFilenames[ni],CV_LOAD_IMAGE_UNCHANGED);
//进入RGB文件夹读取某幅图片的数据
        double tframe = vTimestamps[ni];
//如果某幅图片为空
        if(im.empty())
        {
            cerr << endl << "Failed to load image at: "
                 << string(argv[3]) << "/" << vstrImageFilenames[ni] << endl;
            return 1;
        }

#ifdef COMPILEDWITHC11//如果 COMPILEDWITHC11被定义过,则运行下面内容
        std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
#else
        std::chrono::monotonic_clock::time_point t1 = std::chrono::monotonic_clock::now();
#endif

        // Pass the image to the SLAM system
        SLAM.TrackMonocular(im,tframe);

#ifdef COMPILEDWITHC11
        std::chrono::steady_clock::time_point t2 = std::chrono::steady_clock::now();
#else
        std::chrono::monotonic_clock::time_point t2 = std::chrono::monotonic_clock::now();
#endif

        double ttrack= std::chrono::duration_cast<std::chrono::duration<double> >(t2 - t1).count();

        vTimesTrack[ni]=ttrack;

        // Wait to load the next frame
        double T=0;
        if(ni<nImages-1)
            T = vTimestamps[ni+1]-tframe;
        else if(ni>0)
            T = tframe-vTimestamps[ni-1];

        if(ttrack<T)
            usleep((T-ttrack)*1e6);
    }

    // Stop all threads
    SLAM.Shutdown();

// Tracking time statistics
    sort(vTimesTrack.begin(),vTimesTrack.end());
    float totaltime = 0;
    for(int ni=0; ni<nImages; ni++)
    {
        totaltime+=vTimesTrack[ni];
    }
    cout << "-------" << endl << endl;
    cout << "median tracking time: " << vTimesTrack[nImages/2] << endl;
    cout << "mean tracking time: " << totaltime/nImages << endl;

    // Save camera trajectory
    SLAM.SaveKeyFrameTrajectoryTUM("KeyFrameTrajectory.txt");

return 0;
}

------------------------------------------------------------

总的流程是:

1.加载图片路径

2.启动slam系统

 3.循环{对每张图片:

     ->开始记时

     ->将图片载入入slam

     ->结束记时

        ->计算并保存用时时长

}

4.关闭slam线程

5. 保存关键帧运动轨迹

------------------------------------------------------------

上面代码用到的c++基础知识:

1.文件读写:
#include <fstream>
ofstream f //文件写操作 内存写入存储设备 
ifstream f //文件读操作,存储设备读区到内存中
fstream f //读写操作,对打开的文件可进行读写操作 
参考:https://blog.csdn.net/kingstar158/article/details/6859379

2.getline(f,s0);
//此函数可读取整行,包括前导和嵌入的空格,并将其存储在字符串对象中。f是数据流,s0是要写入的字符串名

3.f.eof
//C++ eof()函数返回true时是读到文件结束符0xFF,而文件结束符是最后一个字符的下一个字符。(f是文件名)

4.stringstream进行流输入输出操作
例如:
#include <string>
#include <sstream>
#include <iostream>
#include <stdio.h>

using namespace std;

int main()
{
stringstream sstream;
string strResult;
int nValue = 1000;

// 将int类型的值放入输入流中
sstream << nValue;
// 从sstream中抽取前面插入的int类型的值,赋给string类型
sstream >> strResult;

cout << "[cout]strResult is: " << strResult << endl;
printf("[printf]strResult is: %s\n", strResult.c_str());

return 0;
}

5.push_back()函数的用法
函数将一个新的元素加到vector的最后面,位置为当前最后一个元素的下一个元素
string str;
str.push_back('d');//在str字符串后面加上一个元素‘d’

6.int main(int argc, char* argv[]) 
int argc
表示你在命令行下输入命令的时候,一共有多少个参数。
比方说你的程序编译后,可执行文件是test.exe
D:\tc2>test ,
argc=1
D:\tc2>test.exe myarg1 myarg2 
argc=3
char *argv[] 
用来取得你所输入的参数
D:\tc2>test
这个时候,argc的值是1,argv[0]的值是 “test”
D:\tc2>test myarg1 myarg2
这个时候,argc的值是3,argc[0]的值是”test”,argc[1]的值是”myarg1”,argc[2]的值是”myarg2”。
这个东东一般用来为程序提供非常重要的信息,如:数据文件名,等等。
如:copy a.c b.txt 这个时候,a.c和b.txt就是所谓的“非常重要的信息”。
7.main函数的return
return 0 代表程序正常退出
return 1代表程序异常退出
8.#ifdef如果标识符被定义过,就会运行后面内容下面为例
    #include <iostream>

    using
    namespace std;

    #define DEBUG

    int
    main( int argc, char  * argv[] )

    {

    #ifdef DEBUG

    cout << "Beginning execution of main()" << endl;

    #endif

    return
    0;

    }

运行结果为:

        Beginning execution of main()

        Press any key to continue
    
9.steady_clock
steady_clock 是单调的时钟,相当于教练手中的秒表;只会增长,适合用于记录程序耗时;
system_clock 是系统的时钟;因为系统的时钟可以修改;甚至可以网络对时; 所以用系统时间计算时间差可能不准。
CLOCK_MONOTONIC:以绝对时间为准,获取的时间为系统重启到现在的时间,更改系统时间对它没有影响。            
View Code

猜你喜欢

转载自www.cnblogs.com/polipolu/p/12926304.html