目录

1.写在前边的话

2.mono_kitti单目数据集运行效果

3.系统框架简要了解

4.最开始的代码

5.mono_kitti代码总结


1.写在前边的话

最近开始学习SLAM,除了学习SLAM相关理论知识外,自己还开始学习ORB-SLAM2开源系统代码,毕竟ORB-SLAM2是比较完整的SLAM系统,里边包括了前端VO,后端优化和闭环检测这三大主要模块。所以,结合SLAM的理论学习和ORB-SLAM2代码完整梳理一遍相信一定会对SLAM相关理论有更深入的认识。

ORB-SLAM2的github代码路径为https://github.com/raulmur/ORB_SLAM2 下载后按照github上的相关编译提示来进行编译就可以了。对了,需要预先安装的软件也都要照着要求一一安装好。

2.mono_kitti单目数据集运行效果

ORB-SLAM2支持单目、双目和RGBD数据,我自己选择mono_kitti的单目数据集来运行和调试。如下所示来运行系统:

运行命令格式为:./mono_kitti path_to_vocabulary path_to_settings path_to_sequence

该命令共有4个参数:

mono_kitti为ORB-SLAM2编译生成的针对MONO_KITTI数据集的可执行文件,一般路径为ORB-SLAM2工程目录下Examples/Monocular/mono_kitti;

path_to_vocabulary为所选词典的路径,路径为ORB-SLAM2/Vocabulary/ORBvoc.txt;

path_to_settings为配置文件,存放在ORB-SLAM2/Examples/Monocular下,我运行时选择了KITTI00-02.yaml,该配置文件中存放的相机的内参和外参,提取特征时候图像金字塔相关参数,可视化过程中用到的参数;

path_to_sequence为数据集路径,这个根据自己下载的kitti数据集路径来指定, http://www.cvlibs.net/datasets/kitti/eval_odometry.php为kitti数据集的下载路径。

xxx@xxx-TM1705:~/Desktop/SLAM/ORB_SLAM2$ ./Examples/Monocular/mono_kitti Vocabulary/ORBvoc.txt Examples/Monocular/KITTI00-02.yaml ../dataset/sequences/00/ORB-SLAM2 Copyright (C) 2014-2016 Raul Mur-Artal, University of Zaragoza.
This program comes with ABSOLUTELY NO WARRANTY;
This is free software, and you are welcome to redistribute it
under certain conditions. See LICENSE.txt.Input sensor was set to: MonocularLoading ORB Vocabulary. This could take a while...
Vocabulary loaded!//以下是从KITTI00-02.yaml中读取的相机参数,其中fx fy cx cy为相机内参,k1 k2 p1 p2为相机外参而且都为0,可以看出该数据集图片是没有畸变的
Camera Parameters:
- fx: 718.856
- fy: 718.856
- cx: 607.193
- cy: 185.216
- k1: 0
- k2: 0
- p1: 0
- p2: 0
- fps: 10
- color order: RGB (ignored if grayscale)
//ORB特征提取器的参数
ORB Extractor Parameters:
- Number of Features: 2000
- Scale Levels: 8
- Scale Factor: 1.2
- Initial Fast Threshold: 20
- Minimum Fast Threshold: 7-------
Start processing sequence ...
Images in the sequence: 4541New Map created with 115 points
Local Mapping STOP
Local Mapping RELEASE
System Reseting
Reseting Local Mapper... done
Reseting Loop Closing... done
Reseting Database... done
New Map created with 84 points
Wrong initialization, reseting...
System Reseting
Reseting Local Mapper... done
Reseting Loop Closing... done
Reseting Database... done
New Map created with 147 points
Local Mapping STOP
Local Mapping RELEASE
System Reseting
Reseting Local Mapper... done
Reseting Loop Closing... done
Reseting Database... done
New Map created with 153 points
virtual int g2o::SparseOptimizer::optimize(int, bool): 0 vertices to optimize, maybe forgot to call initializeOptimization()
virtual int g2o::SparseOptimizer::optimize(int, bool): 0 vertices to optimize, maybe forgot to call initializeOptimization()
virtual int g2o::SparseOptimizer::optimize(int, bool): 0 vertices to optimize, maybe forgot to call initializeOptimization()
Local Mapping STOP
Local Mapping RELEASE
System Reseting
Reseting Local Mapper... done
Reseting Loop Closing... done
Reseting Database... done
New Map created with 128 points
Track lost soon after initialisation, reseting...
System Reseting
Reseting Local Mapper... done
Reseting Loop Closing... done
Reseting Database... done
New Map created with 109 pointsLoop detected!
Local Mapping STOP
Local Mapping RELEASE
Starting Global Bundle Adjustment
Global Bundle Adjustment finished
Updating map ...
Local Mapping STOP
Local Mapping RELEASE
Map updated!
-------median tracking time: 0.0313816
mean tracking time: 0.0334428
//这行日志出现后,表示讲相机位子存储在了KeyFrameTrajectory.txt文件中了
Saving keyframe trajectory to KeyFrameTrajectory.txt ...trajectory saved!
QObject::~QObject: Timers cannot be stopped from another thread

运行效果如下:

可以看到,此时桌面出现了两个窗口,上边的图像一帧一帧变化,下边的相机路径也同步变化。其实这个在代码中对应两个窗口类,FrameDrawer类为上边的显示图像帧的窗口,MapDrawer为下边的显示地图路径的窗口。上图中的绿色点为每一帧图像中识别出来的特征关键点,下图中所有的倒三角行连在一起构成了相机的运动轨迹,红色的点云为图像中的特征点。

3.系统框架简要了解

一般情况下,要了解一个系统的代码实现,总是要先从熟悉系统的框架开始,ORB-SLAM2的系统框架如下图所示:

在只对SLAM的正常框架有所了解的前提下,我们可以看到TRACKING线程中做了提取ORB特征、初始位姿估计等操作,那么这个线程应该属于SLAM中的“前端VO”;LOCAL MAPPING线程里有Local BA,我们可以知道这个线程属于后端,主要做后端优化和建图工作;LOOP CLOSING线程从字面意思就能判断出是做回环检测的,分为回环检测和回环矫正。

再需要知道的就是TRACKING线程接收了一帧一帧的图片后开始工作的,而LOCAL MAPPING线程接收的KeyFrame来自TRACKING线程“加工提炼”之后,LOOP CLOSING线程也是接收LOCAL MAPPING线程“进一步加工提炼”后的KeyFrame来进行工作。

可以看出,Frame为整个系统运行起来的“原料”。这样三个核心的线程就串起来了,至于PLACE RECOGNITION和MAP是什么鬼?留到以后需要了解的时候再去研究吧。

4.最开始的代码

看过了系统框架的真面目,此时开始分析代码。本篇笔记作为笔者开始记录ORB-SLAM2的第一篇笔记,本篇只会对ORB-SLAM2最开始的代码进行分析。

从mono_kitti开始运行的,那么自然应该先从寻找mono_kitti的main函数开始。mono_kitti.cc文件主要的函数如下。

int main(int argc, char **argv)
{if(argc != 4){cerr << endl << "Usage: ./mono_kitti path_to_vocabulary path_to_settings path_to_sequence" << endl;return 1;}// Retrieve paths to imagesvector<string> vstrImageFilenames;vector<double> vTimestamps;//讲单目数据集图片(也就是Frames)load进来,argv[3]是Frame的路径LoadImages(string(argv[3]), vstrImageFilenames, vTimestamps);int nImages = vstrImageFilenames.size();// Create SLAM system. It initializes all system threads and gets ready to process frames.//argv[1]为vocfile 里边存储的是词汇//argv[2]为settingfile 里边存储摄像机校准和畸变参数和ORB相关参数//这里创建了System类型的SLAM对象,SLAM构造函数中初始化了系统所有线程和相关参数,代码留待后边详细分析ORB_SLAM2::System SLAM(argv[1],argv[2],ORB_SLAM2::System::MONOCULAR,true);// Vector for tracking time statisticsvector<float> vTimesTrack;vTimesTrack.resize(nImages);cout << endl << "-------" << endl;cout << "Start processing sequence ..." << endl;cout << "Images in the sequence: " << nImages << endl << endl;cv::Mat im;// Main loop 主循环代码,循环读取一帧一帧的图片for(int ni=0; ni<nImages; ni++){// Read image from file 读取图片im = cv::imread(vstrImageFilenames[ni],CV_LOAD_IMAGE_UNCHANGED);//读取时间戳double tframe = vTimestamps[ni];if(im.empty()){cerr << endl << "Failed to load image at: " << vstrImageFilenames[ni] << endl;return 1;}#ifdef COMPILEDWITHC11std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
#elsestd::chrono::monotonic_clock::time_point t1 = std::chrono::monotonic_clock::now();
#endif// Pass the image to the SLAM system //将图片传给SLAM系统。TrackMonocular讲图片传给Tracking,其实Tracking就是系统的主线程。这里传入的im引起了系统的一系列操作SLAM.TrackMonocular(im,tframe);#ifdef COMPILEDWITHC11std::chrono::steady_clock::time_point t2 = std::chrono::steady_clock::now();
#elsestd::chrono::monotonic_clock::time_point t2 = std::chrono::monotonic_clock::now();
#endifdouble ttrack= std::chrono::duration_cast<std::chrono::duration<double> >(t2 - t1).count();vTimesTrack[ni]=ttrack;// Wait to load the next framedouble 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系统,也就关闭了系统中的几个线程SLAM.Shutdown();// Tracking time statisticssort(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系统运行完后,计算出来的是相机的运行轨迹,系统退出时保存相机轨迹SLAM.SaveKeyFrameTrajectoryTUM("KeyFrameTrajectory.txt");    return 0;
}
/*** 读入一帧帧的图像数据和时间戳数据* strPathToSequence 为入参,表示image文件存储的路径* vstrImageFilenames 为出参,存储获取image文件列表的具体路径* vTimestamps 为出参, 存储和每一个image文件对应的时间戳*
*/
void LoadImages(const string &strPathToSequence, vector<string> &vstrImageFilenames, vector<double> &vTimestamps)
{ifstream fTimes;string strPathTimeFile = strPathToSequence + "/times.txt";fTimes.open(strPathTimeFile.c_str());while(!fTimes.eof()){string s;getline(fTimes,s);if(!s.empty()){stringstream ss;ss << s;double t;ss >> t;//vTimestamps中存入了所有的时间戳vTimestamps.push_back(t);}}//组装mono_kitti数据集中image_0目录的路径string strPrefixLeft = strPathToSequence + "/image_0/";const int nTimes = vTimestamps.size();vstrImageFilenames.resize(nTimes);for(int i=0; i<nTimes; i++){stringstream ss;//std::setw :需要填充多少个字符,默认填充的字符为' '空格//std::setfill:设置std::setw将填充什么样的字符,如:std::setfill('*')//ss总共为6位,i之外的前边几位用0来填充,得到的结果为000001 000099之类ss << setfill('0') << setw(6) << i;vstrImageFilenames[i] = strPrefixLeft + ss.str() + ".png";}
}

5.mono_kitti代码总结

mono_kitti的main函数主要步骤如下,可以看清楚看到和SLAM系统关联的函数为TrackMonocular,这个函数接收了Frame(或者说将Frame传给了TRACKING线程)。  

main函数中调用的System相关函数见ORB-SLAM2代码阅读笔记(二):System.cc相关函数

ORB-SLAM2代码阅读笔记(一):从mono_kitti单目运行开始相关推荐

  1. ORB-SLAM2代码阅读笔记(五):Tracking线程3——Track函数中单目相机初始化

    Table of Contents 1.特征点匹配相关理论简介 2.ORB-SLAM2中特征匹配代码分析 (1)Tracking线程中的状态机 (2)单目相机初始化函数MonocularInitial ...

  2. [置顶] Linux协议栈代码阅读笔记(一)

    Linux协议栈代码阅读笔记(一) (基于linux-2.6.21.7) (一)用户态通过诸如下面的C库函数访问协议栈服务 int socket(int domain, int type, int p ...

  3. linux 协议栈 位置,[置顶] Linux协议栈代码阅读笔记(一)

    Linux协议栈代码阅读笔记(一) (基于linux-2.6.21.7) (一)用户态通过诸如下面的C库函数访问协议栈服务 int socket(int domain, int type, int p ...

  4. BNN Pytorch代码阅读笔记

    BNN Pytorch代码阅读笔记 这篇博客来写一下我对BNN(二值化神经网络)pytorch代码的理解,我是第一次阅读项目代码,所以想仔细的自己写一遍,把细节理解透彻,希望也能帮到大家! 论文链接: ...

  5. 菜鸟笔记-DuReader阅读理解基线模型代码阅读笔记(八)—— 模型训练-训练

    系列目录: 菜鸟笔记-DuReader阅读理解基线模型代码阅读笔记(一)--数据 菜鸟笔记-DuReader阅读理解基线模型代码阅读笔记(二)-- 介绍及分词 菜鸟笔记-DuReader阅读理解基线模 ...

  6. leveldb代码阅读笔记(一)

    leveldb代码阅读笔记 above all leveldb是一个单机的键值存储的内存数据库,其内部使用了 LSM tree 作为底层存储结构,支持多版本数据控制,代码设计巧妙且简洁高效,十分值得作 ...

  7. C++ Primer Plus 6th代码阅读笔记

    C++ Primer Plus 6th代码阅读笔记 第一章没什么代码 第二章代码 carrots.cpp : cout 可以拼接输出,cin.get()接受输入 convert.cpp 函数原型放在主 ...

  8. [原创]fetchmail代码阅读笔记---ESMTP的认证方式

    fetchmail代码阅读笔记---ESMTP的认证方式 作者: 默难 ( monnand@gmail.com ) 0    引言 fetchmail是Eric S. Raymond组织编写的一款全功 ...

  9. CNN去马赛克代码阅读笔记

    有的博客链接是之前几周写好的草稿,最近整理的时候才发布的 CNN去马赛克论文及代码下载地址 有torch,minimal torch和caffe三种版本 关于minimal torch版所做的努力,以 ...

  10. P2PNet(代码阅读笔记)

    P2PNet 代码阅读笔记 一.主干网络 主干网络采用的是VGG16 class BackboneBase_VGG(nn.Module):def __init__(self, backbone: nn ...

最新文章

  1. C++ Primer 5th笔记(chap 10)泛型算法 :特定容器算法list
  2. 处理时间_4_计算时间列所在的周的序号
  3. loadRunner12试用
  4. crs 管理的几个演示(培训作业)
  5. WinCE 自由拼音输入法的测试
  6. 组态王怎么做超级曲线_鸭肉怎么做?大叔教你红烧鸭块,香气扑鼻,简单易做,超级好吃...
  7. C#如何去掉字符串中所有空格
  8. git 回退上一个版本
  9. 有时我们经常碰到某目录下文件名乱码的情况,convmv可以批量转换文件名编码。...
  10. 第9章 逻辑回归 学习笔记 下
  11. 汇编语言 王爽 第四版 第二章 检测点2.3
  12. 你知道数字图像处理的经典Lenna图背后的故事吗
  13. 小程序 video 控制器外观调整_Kessil 360X Tuna Sun无线控制器使用分享
  14. 6个好用免费的LiDAR数据处理软件【2021最新】
  15. 程序设计基础大作业:学生信息管理系统plus(彩色界面,登录功能,文件操作,多文件)
  16. C语言求最小公倍数和最大公约数三种算法(经典)----ACM
  17. 谷歌开始卷自己,AI架构Pathways加持,推出200亿生成模型
  18. 感动,我终于学会了用Java对数组求和
  19. 学会聆听别人,聆听也是一门艺术。
  20. 邮件发送失败服务器繁忙,★邮件发送失败的原因和解决方法

热门文章

  1. outlook html 图片,Outlook邮件内容中的图片无法显示 图片
  2. POJ 3987 Computer Virus on Planet Pandora (AC自动机优化)
  3. NHibernate]集合类(Collections)映射
  4. JM8.5中的高精度象素运动估计
  5. 中国程序员鼓励师都干啥? 美媒:按摩谈心样样通
  6. 美金融犯罪执法局文件遭泄露:汇丰、摩根大通、渣打等国际大行涉嫌非法转移资金...
  7. Hive指定位置增加字段及解决columns have types incompatible with the existing columns in their respective positio
  8. PythonOcc实战——step文件导入、零件识别、几何属性、爆炸图初步展示
  9. vscode 编辑特效 文字爆炸效果插件
  10. 提高scrapy的爬取速度