文章目录
前言
因为对于视觉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数据集中的图片。
注:每个数据集库的图片/数据形式不同,故此函数的内容略有差异。
笔记简记:
- open()函数
笔记来源:CSDN@Ocean&&Star
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
/*
* 返回:若成功则为新文件描述符,若出错为-1
*/
int open( const char * pathname, int oflags);
int open(char *filename, int flags, mode_t mode);
功能:open 函数将 filename 转换为一个文件描述符,并且返回描述符数字。返回的描述符总是在进程中当前没有打开的最小描述符。
参数:
pathname 是待打开/创建文件的路径名
flags 指明了进程打算如何访问这个文件
mode 参数仅当创建新文件时才使用(而且必须用),用于指定文件的访问权限。
- c_str()函数
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()返回的指针,否则会得到一些垃圾内容。
- 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 ×tamp)
{
...
//获取相机位姿的估计结果
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!
二、代码导图
绘图参考:CSDN@文科升