【ORB-SLAM2源码梳理1】以单目mono_tum.cc为例,构建SLAM系统(含mono_tum.cc、System.cc关键代码解析)

文章目录

  • 前言
  • 一、进入mono_tum.cc
    • 1. 导入TUM数据集图片:LoadImages()
    • 2. 构建SLAM系统:System
    • 3. 系统构建结束,开启跟踪线程
      • 1)一帧帧地读取对应路径下的rgb图像:
      • 2)将图像帧传入Tracking线程,开始一系列操作(关键):
  • 二、代码导图


前言

因为对于视觉SLAM而言,单目涉及初始化等步骤,相对于双目和RGBD较为复杂,故从单目学起。
学习记录。


一、进入mono_tum.cc

1. 导入TUM数据集图片:LoadImages()

	void LoadImages(const string &strFile, vector<string> &vstrImageFilenames, 
					vector<double> &vTimestamps);
	
	 * @param[in] strFile                   读入的文件名称
	 * @param[in&out] vstrImageFilenames    彩色图片名称
	 * @param[in&out] vTimestamps           记录时间戳

导入TUM数据集中的图片。
注:每个数据集库的图片/数据形式不同,故此函数的内容略有差异。

笔记简记:

  1. open()函数

笔记来源:CSDN@Ocean&&Star

	#include  
	#include  
	#include  	
	/*
	* 返回:若成功则为新文件描述符,若出错为-1
	*/
	int open( const char * pathname, int oflags);			
	int open(char *filename, int flags, mode_t mode); 

功能:open 函数将 filename 转换为一个文件描述符,并且返回描述符数字。返回的描述符总是在进程中当前没有打开的最小描述符。

参数:
pathname 是待打开/创建文件的路径名
flags 指明了进程打算如何访问这个文件
mode 参数仅当创建新文件时才使用(而且必须用),用于指定文件的访问权限。

  1. c_str()函数

笔记来源:CSDN@繁星蓝雨、@丫丫afc

	const char *c_str(); 

功能:函数c_str()是将C++的string转化为C的字符串数组,c_str()生成一个const char *指针,指向字符串的首地址,内容与string串相同。

目的:为了与c语言兼容,在c语言中没有string类型,故必须通过string类对象的成员函数c_str()把string 对象转换成c中的字符串样式。

① c_str是一个内容为字符串指向字符数组的临时指针;
② c_str返回的是一个可读不可改的常指针;
注:一定要使用strcpy()函数等来操作方法c_str()返回的指针,否则会得到一些垃圾内容。

  1. stringstream类
	stringstream ss;        
	ss << s;
	double t;
	string sRGB;
	ss >> t;                				// 输出时间戳数据,
	vTimestamps.push_back(t);   			// 将时间戳数据放在vTimestamps中
	ss >> sRGB;             				// 输出彩色图片名称的数据
	vstrImageFilenames.push_back(sRGB);     // 将图像名称数据放在vstrImageFilenames中

stringstream类对象在经过抽取运算符给其他类型的对象时,只会留下类型相匹配的内容。

2. 构建SLAM系统:System

mono_tum.cc中的System:

   ORB_SLAM2::System SLAM(argv[1],argv[2],ORB_SLAM2::System::MONOCULAR,true);

System在此处的作用:
1)读取ORB词典,为回环检测做准备;
2)创建关键帧数据库KeyFrameDatabase,用于存放关键帧及其相关数据;
3)初始化Tracking线程,为下面main函数中运行Tracking线程做准备;
4)初始化并启动LocalMapping线程;
5)初始化并启动LoopClosing线程;
6)初始化并启动窗口显示线程mptViewer;
7)在各个线程之间分配资源,方便线程彼此之间的数据交互。

基本就是SLAM系统的核心了。

声明:System.h

    System(const string &strVocFile,            //指定ORB字典文件的路径
           const string &strSettingsFile,       //指定配置文件的路径
           const eSensor sensor,                //指定所使用的传感器类型
           const bool bUseViewer = true);       //指定是否使用可视化界面
strVocFile:ORB词典文件的路径;
strSettingsFile:配置文件路径
sensor:摄像头类型
bUseViewer = true:是否打开可视化界面Viewer

定义:System.cc中的System构造函数

System::System(const string &strVocFile, const string &strSettingsFile, const eSensor sensor, const bool bUseViewer):
		mSensor(sensor), 							// 初始化传感器类型
		mpViewer(static_cast<Viewer*>(NULL)), 		// 初始化可视化界面,置空
		mbReset(false),								// 复位标志
		mbActivateLocalizationMode(false), 			// 定位模式(不进行局部建图)
		mbDeactivateLocalizationMode(false)			// 非定位模式

System构造函数主要流程(关键!!!):
1)检测传感器类型,读取词袋(此处的词袋、词典状态采用的都是第三方库);

2)创建关键帧数据库:mpKeyFrameDatabase = new KeyFrameDatabase(*mpVocabulary);
创建地图:mpMap = new Map();
创建逐帧绘制器:mpFrameDrawer = new FrameDrawer(mpMap);
创建地图绘制器:mpMapDrawer = new MapDrawer(mpMap, strSettingsFile);

3)初始化Tracking线程:mpTracker = new Tracking();

4)…(目前学至Tracking线程,其他后续再填坑)

笔记简记:

C++ 类的构造函数后面加单:的作用:

① 对父类进行初始化;
② 对类成员进行初始化;
③ 对类的const成员变量进行初始化。
:对于②③的说明:
构造函数列表初始化执行顺序与成员变量在类中声明顺序相同,与初始化列表中语句书写先后无关;
相对于在构造函数中赋值,初始化列表执行效率更高。

3. 系统构建结束,开启跟踪线程

1)一帧帧地读取对应路径下的rgb图像:

注:如果实时跟踪的话,在一开始启动程序时就不会输入这个路径。

    // 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);	// 读图
        double tframe = vTimestamps[ni];														// 读取文件中的时间戳

        if(im.empty())
        {
            cerr << endl << "Failed to load image at: "
                 << string(argv[3]) << "/" << vstrImageFilenames[ni] << endl;
            return 1;
        }

2)将图像帧传入Tracking线程,开始一系列操作(关键):

SLAM.TrackMonocular(im,tframe);

TrackMonocular()函数的定义在System.cc中:

cv::Mat System::TrackMonocular(const cv::Mat &im, const double &timestamp)
{
	...
	//获取相机位姿的估计结果
    cv::Mat Tcw = mpTracker->GrabImageMonocular(im,timestamp);          //计算单目相机位姿,并存储与Tcw

    unique_lock<mutex> lock2(mMutexState);
    mTrackingState = mpTracker->mState;									// 更新追踪器状态
    mTrackedMapPoints = mpTracker->mCurrentFrame.mvpMapPoints;			// 更新当前跟踪的地图点
    mTrackedKeyPointsUn = mpTracker->mCurrentFrame.mvKeysUn;			// 更新校正后的特征点

    return Tcw;															// 返回相机位姿
}

GrabImageMonocular()函数的定义在Tracking.cc中。

得到相机位姿(从世界坐标系转换到相机坐标系的变换矩阵)Tcw后,更新追踪状态标志。

如此反复重复的进行,最后关闭所有线程:

    SLAM.Shutdown();

输出一些跟踪得到的数据、打印时间、保存轨迹等。

over!


二、代码导图

【ORB-SLAM2源码梳理1】以单目mono_tum.cc为例,构建SLAM系统(含mono_tum.cc、System.cc关键代码解析)_第1张图片
绘图参考:CSDN@文科升

你可能感兴趣的:(ORB-SLAM2,c++,slam,orb)