ORB_SLAM2程序入口(System.cc)
程序入口
ORB_SLAM2的程序入口为src/System.cc。在CMakeList.txt中可知,ORB_SLAM2的可执行程序为:
Examples/Stereo/stereo_kitti.cc等。
add_executable(stereo_kitti
Examples/Stereo/stereo_kitti.cc)
target_link_libraries(stereo_kitti ${PROJECT_NAME})add_executable(stereo_euroc
Examples/Stereo/stereo_euroc.cc)
target_link_libraries(stereo_euroc ${PROJECT_NAME})set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/Examples/Monocular)add_executable(mono_tum
Examples/Monocular/mono_tum.cc)
target_link_libraries(mono_tum ${PROJECT_NAME})add_executable(mono_kitti
Examples/Monocular/mono_kitti.cc)
target_link_libraries(mono_kitti ${PROJECT_NAME})add_executable(mono_euroc
Examples/Monocular/mono_euroc.cc)
target_link_libraries(mono_euroc ${PROJECT_NAME})
在Examples/Stereo/stereo_kitti.cc程序中可见:argc===4,即在命令行中输入的四部分:1)可执行程序。2)词典。3)配置文件。4)数据集。
./Examples/Stereo/stereo_kitti Vocabulary/ORBvoc.txt ./Examples/Stereo/KITTI00-02.yaml /home/dk/桌面/kitti/00
接下来,笔者以./Examples/Monocular/EuRoC_TImeStamps/mono_kitti.cc为例。因为其包含单目初始化,比较经典。
读取图片的路径+名称、时间戳
首先使用LoadImages函数获得左右目图像以及时间戳。
初始化整个系统
而后调用ORB_SLAM2::System的构造函数初始化整个系统。
主循环
调用SLAM.TrackMonocular处理每一帧输入的图片。如果处理一帧所用时间小于两帧之间实际拍摄所间隔时间,则用usleep函数停顿相应时间再进行下一轮循环。
double 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);
终止
结束所有线程,计算出平均每帧的运行时间,并保存关键帧的位姿信息。
// 结束所有线程SLAM.Shutdown();// 统计时间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;// 保存关键帧位姿信息SLAM.SaveKeyFrameTrajectoryTUM("KeyFrameTrajectory.txt");
System.cc
主程序的实现文件。在其中声明了界面信息,导入了关键帧数据库,开启了三个线程(追踪线程、局部建图线程、回环检测线程)。
构造函数
//系统的构造函数,将会启动其他的线程
System::System(const string &strVocFile, //词典文件路径const string &strSettingsFile, //配置文件路径const eSensor sensor, //传感器类型const bool bUseViewer): //是否使用可视化界面mSensor(sensor), //初始化传感器类型mpViewer(static_cast<Viewer*>(NULL)), //空。。。对象指针? TODO mbReset(false), //无复位标志mbActivateLocalizationMode(false), //没有这个模式转换标志mbDeactivateLocalizationMode(false) //没有这个模式转换标志
(1)strVocFile为词典路径:Vocabulary路径下的ORBvoc.txt。
(2)strSettingsFile:配置文件路径,即Examples目录下的yaml文件。其中包含一些配置信息,如相机的内参,特征点的提取数量,图像金字塔的信息等。
(3)sensor:传感器的类型,在system.h中有设置。
// 单目、双目、RGB-Denum eSensor{MONOCULAR=0,STEREO=1,RGBD=2};
(4)bUseViewer:是否使用可视化界面,即运行ORB_SLAM2中的运行界面。
界面的声明信息
// Output welcome messagecout << endl <<"ORB-SLAM2 Copyright (C) 2014-2016 Raul Mur-Artal, 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;//Check settings filecv::FileStorage fsSettings(strSettingsFile.c_str(), //将配置文件名转换成为字符串cv::FileStorage::READ); //只读//如果打开失败,就输出调试信息if(!fsSettings.isOpened()){cerr << "Failed to open settings file at: " << strSettingsFile << endl;//然后退出exit(-1);}//Load ORB Vocabularycout << endl << "Loading ORB Vocabulary. This could take a while..." << endl;//建立一个新的ORB字典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;
构建关键帧数据库
ORB_SLAM2是基于关键帧优化的SLAM系统,因此需要一个关键帧数据库。
关键帧数据库类在KeyFrameDatabase.h中定义,主要包含训练好的词典,以及单词的出现情况与关键帧索引间的联系。
该库在重定位和回环检测时被使用,用于检测与当前帧最相似的关键帧。
mpKeyFrameDatabase = new KeyFrameDatabase(*mpVocabulary);
初始化地图与绘制器
初始化一个地图类,主要包含该地图中的关键帧和路标点。
构造绘图变量,用于绘制可视化界面(包括关键帧与路标点)。
mpMap = new Map();
mpFrameDrawer = new FrameDrawer(mpMap);
mpMapDrawer = new MapDrawer(mpMap, strSettingsFile);
开启三个线程
开启三个线程:Tracking、LocalMapping、LoopClosing。(三者之间应该有个沟通,否则数据会紊乱)
其中Tracking为主线程(初始化追踪线程),LocalMapping、LoopClosing为子线程。子线程的运行函数分别为:&ORB_SLAM2::LocalMapping::Run、&ORB_SLAM2::LoopClosing::Run。使用thread加入到子线程中。根据输入的参数bUseViewer决定是否启动可视化线程。
mpTracker = new Tracking(this, //现在还不是很明白为什么这里还需要一个this指针 TODO mpVocabulary, //字典mpFrameDrawer, //帧绘制器mpMapDrawer, //地图绘制器mpMap, //地图mpKeyFrameDatabase, //关键帧地图strSettingsFile, //设置文件路径mSensor); //传感器类型iomanip//初始化局部建图线程并运行//Initialize the Local Mapping thread and launchmpLocalMapper = new LocalMapping(mpMap, //指定使iomanipmSensor==MONOCULAR); // TODO 为什么这个要设置成为MONOCULAR???//运行这个局部建图线程mptLocalMapping = new thread(&ORB_SLAM2::LocalMapping::Run, //这个线程会调用的函数mpLocalMapper); //这个调用函数的参数//Initialize the Loop Closing thread and launchiomanipmpLoopCloser = new LoopClosing(mpMap, //地图mpKeyFrameDatabase, //关键帧数据库mpVocabulary, //ORB字典mSensor!=MONOCULAR); //当前的传感器是否是单目//创建回环检测线程mptLoopClosing = new thread(&ORB_SLAM2::LoopClosing::Run, //线程的主函数mpLoopCloser); //该函数的参数if(bUseViewer){//如果指定了,程序的运行过程中需要运行可视化部分//新建viewermpViewer = new Viewer(this, //又是这个mpFrameDrawer, //帧绘制器mpMapDrawer, //地图绘制器mpTracker, //追踪器strSettingsFile); //配置文件的访问路径//新建viewer线程mptViewer = new thread(&Viewer::Run, mpViewer);//给运动追踪器设置其查看器mpTracker->SetViewer(mpViewer);}
建立各个线程间的联系
//设置进程间的指针mpTracker->SetLocalMapper(mpLocalMapper);mpTracker->SetLoopClosing(mpLoopCloser);mpLocalMapper->SetTracker(mpTracker);mpLocalMapper->SetLoopCloser(mpLoopCloser);mpLoopCloser->SetTracker(mpTracker);mpLoopCloser->SetLocalMapper(mpLocalMapper);
处理单目相机传入的每一帧图片
判断系统的模式是否发生了改变
cv::Mat System::TrackMonocular(const cv::Mat &im, const double ×tamp)
主循环中的函数System::TrackMonocular。
(1)判断系统的模式是否发生了变化。即激活定位模式和关闭定位模式。
(2)如果开启定位模式,则关闭局部建图线程,且标志位 置为true。
(3)如果关闭定位模式,则开启局部建图线程,且标志位 置为false。
if(mbActivateLocalizationMode){mpLocalMapper->RequestStop();// Wait until Local Mapping has effectively stoppedwhile(!mpLocalMapper->isStopped()){usleep(1000);}// 局部地图关闭以后,只进行追踪的线程,只计算相机的位姿,没有对局部地图进行更新// 设置mbOnlyTracking为真mpTracker->InformOnlyTracking(true);// 关闭线程可以使得别的线程得到更多的资源mbActivateLocalizationMode = false;}// 如果mbDeactivateLocalizationMode是true,局部地图线程就被释放, 关键帧从局部地图中删除.if(mbDeactivateLocalizationMode){mpTracker->InformOnlyTracking(false);mpLocalMapper->Release();mbDeactivateLocalizationMode = false;}
判断是否需要重置
当重定位失败之后,系统无法定位,此时需要重置。
unique_lock<mutex> lock(mMutexReset);if(mbReset){mpTracker->Reset();mbReset = false;}
计算位姿
计算相机位姿(相对于世界坐标的位姿变换),
cv::Mat Tcw = mpTracker->GrabImageMonocular(im,timestamp);
更新系统变量
包括更新系统的跟踪状态(mTrackingState),当前帧的路标点(mTrackedMapPoints),当前帧的特征点(mTrackedKeyPointsUn)。
保存相机轨迹
以数据集的格式保存相机轨迹。使用当前帧相对于参考关键帧的转换+参考关键帧相对于第一个关键帧的转换计算出当前帧相对于第一个关键帧(世界坐标)的转换。
void System::SaveTrajectoryTUM(const string &filename)
相关文章:

HDU 6229 Wandering Robots 找规律+离散化
题目链接:Wandering Robots 题解:先讲一下规律,对于每一个格子它可以从多少个地方来有一个值(可以从自己到自己),然后答案就是统计合法格子上的数与所有格子的数的比值 比如说样例的3 0格子上的值就是 3 4 …

app、H5、safari、appstore应用主页评分页之间拉起调用、打开手机某些系统功能、app打开文档
定义打开URL的方法 - (void)openURL:(NSString *)urlStr {NSURL *url [NSURL URLWithString:urlStr];UIApplication *app [UIApplication sharedApplication];if ([app canOpenURL:url]) { #ifdef __IPHONE_10_0[app openURL:url options:[NSDictionary dictionary] complet…
XML学习总结
1、XML结构 2、XmlNodeType值为一个枚举类型: 假设我们对一个XML文件进行遍历,不推断节点是否为Element类型。就会将文本节点遍历出来,出现#test。 3、XmlElement和XmlNode的差别:(摘自CSDN论坛) ÿ…

Linux01-基本操作与Shell
目录 一、环境 二、Linux目录结构及基本操作 2.1 Linux目录结构 2.2 基本操作 三、shell 3.1 shell的意义 3.2 su - 一、环境 2019年搞下RHCE的证书,但是一直没有整理Linux学习的笔记,为了不让到手的知识被遗忘,从今天起整理Linux学习…

ORB_SLAM2中Tracking线程的三种追踪方式
1、参考关键帧追踪模式 bool Tracking::TrackReferenceKeyFrame()对参考关键帧中的路标点进行跟踪。在Tracking线程中,每传入一帧,都会进行位姿优化。 以上一帧的位姿为当前位姿进行优化。 (1)计算当前帧的词袋 mCurrentFra…

nodejs 中间件 反向代理 接口转发
背景 随着后端业务系统的增加,纵向需求不断扩展,一个业务系统已经无法满足需求了,衍生出多个业务系统,对外暴露的ip、端口就可能有多个,此时不方便外部接口调用,有些特殊行业客户出于安全性考虑不发提供多…

oneinstack
https://oneinstack.com/转载于:https://www.cnblogs.com/diyunpeng/p/9740895.html

最近在做托盘时,发现 CnTrayIcon1的OnClick 事件,不能被其它按钮来执行,蛋疼。...
比如: procedure TForm1.Button1Click(Sender: TObject);begin CnTrayIcon1.OnClick ; // 这句就是不能通过!!end; 有过路的高手,指点学生一下。谢谢转载于:https://www.cnblogs.com/hahy8008/p/6783614.html

Linux02-帮助手册
目录 一、man手册 1.1 man的基本使用 1.2 mandb更新文档 二、/usr/share/doc 三、access.redhat.com 门户 一、man手册 1.1 man的基本使用 man就是mannual的缩写,手册的意思。Linux的命令很多,参数选项更多,人脑一般是记不住的&…

ORB_SLAM2中Tracking线程
Tracking线程是ORB_SLAM2的主线程。在System.cc中,使用构造函数进行了初始化,开启了三个线程。 可执行程序—>System构造函数(初始化三个线程)—>处理输入的帧(TrackMonocular)—>调用Tracking线程…

selenium的基础知识点
from selenium import webdriver from scrapy.selector import Selector#模拟登陆 browser webdriver.Chrome(executable_pathChromedriver.exe) #路径是Chromedriver.exe的存放位置,windows下只要配置好这个环境就不需要了browser.get(http://w) #需要登陆的那个网…

iOS 直播专题2-音视频采集
从设备(手机)的摄像头、MIC中采集音频、视频的原始数据ios的音视频采集可以从AVFoundation框架里采集 视频采集 这里我们选取GPUImage来采集视频,因为这个框架集成了很多视频滤镜,例如美颜 采集流程: 摄像头采集视频代码 GPUImageVideoCamera.m // 从前摄像头或后摄像头…

bzoj 4871: [Shoi2017]摧毁“树状图”
4871: [Shoi2017]摧毁“树状图” Time Limit: 25 Sec Memory Limit: 512 MBSubmit: 53 Solved: 9[Submit][Status][Discuss]Description 自从上次神刀手帮助蚯蚓国增添了上千万人口(蚯口?),蚯蚓国发展得越来越繁荣了!…

Linux03-本地账户和组
目录 一、本地账户/etc/passwd 二、本地组/etc/group 三、切换账户su - 四、增删改本地账户useradd、userdel、usermod 五、账户默认配置文件/etc/login.defs 六、设置密码passwd(5)命令 七、增删改组groupadd、groupdel和groupmod 八、通过sudo以root身份运行命令 九…

ORB_SLAM2单目初始化策略
基本流程 单目初始化程序存储在Initializer.cc中 需要注意,对于双目/RGB-D相机,初始化时,由于可以直接获得相机的深度信息,因此无需求H/F,直接作为关键帧插入就行。 使用RANSACDLT求解H,RANSAC八点…

Powerdesigner逆向工程64位Oracle数据库
Powerdesigner老版本不支持64位Client,新版本弄不到破解码 解决方法,用Powerdesigner32位Oracle Clent访问64位Oracle Server 遇到的坑分享下 安装完64位的Oracle Server ,32位的 Oracle Clent默认的listener.ora文件有PROGRAM和ENVS这两个节点 Plsql(3…

运行jsp时,报错404
The origin server did not find a current reprsentation for the target resource or is not willing to disclose that one exists. 解决: 1. web.xml文件位置是否放错,应该放在WebContent/WEB-INF文件夹中 2. web.xml文件中是否有拼写错误࿰…

iOS 直播专题3-前置处理
前置处理 对视频添加美颜、水印、滤镜等对音频进行混音、消除环境音、声音特效等上一篇iOS 直播专题2-音视频采集提到视频采集采用的是GPUImage框架,这个框架集成了很多滤镜效果 这里主要介绍美颜、水印处理 处理流程: 美颜 这里的美颜效果用的是GPUImageBeautyFilter 功…

ORA-10873解决办法
今天,发现SAP系统的oracle数据库宕掉了。报错ORA-10873,经过查证解决该问题。记录一下,备忘。 一、问题 Oracle版本为12.1.0.2.0,在启动服务器后启动数据库startup,报错ORA-10873。 二、查证 到SAP Support Portal上…

ORB_SLAM2局部建图线程
局部建图线程入口:可执行程序在初始化三个线程的时候,在System.cc的构造函数中进入局部建图线程 mpLocalMapper new LocalMapping(mpMap, //指定使iomanipmSensorMONOCULAR); // TODO 为什么这个要设置成为MONOCULAR??&#…

十一连测day1
这次测试,是福建第三中学的某同学出的,感觉难度还行吧,今天我就浅谈一下这场比赛的时间分配与心得 打开题目,看到了T1,这题是一道计数题吧,感觉心态一下子就崩了,100%的数据点应该是组合数学容斥…

iOS 直播专题5-推流
常用的推流协议有: 协议内容RTP实时流传输协议,但不保证服务质量RTCPRTP数据流协议的一个姐妹协议,为RTP提供服务质量反馈SRTP & SRTCPRTP和RTCP的安全版本,提供数据加密、消息认证功能RTSP控制声音或影像的多媒体数据串流协议RTMPADOBE公司播放器与服务器之间多媒体数…

centos6.5-vsftp搭建
我的机子是默认是没有的vsftp。 yum install -y vsftp 创建账户专为ftp而生。useradd ftp01 更改账户不可登录系统。usermod -s /sbin/nologin ftp01 vsftp默认是可以匿名登录的,也是默认的端口,这些不安全选项都要修改! anonymous_enableYES…

Linux04-文件系统权限与ACL权限
目录 一、文件系统权限 1.1、认识文件系统权限 1.2、管理文件系统权限 1.3、特殊权限 1.4、默认权限 二、ACL权限 2.1、ACL本质是文件系统的一个挂载选项 2.2、更改文件的ACL权限 2.3、设置文件和目录的默认ACL权限 Linux中的权限管理分为两种类型 用户自主访问控制&…

ORB_SLAM2帧Frame
在追踪线程的一开始就会创建一个帧 cv::Mat Tracking::GrabImageMonocular(const cv::Mat &im,const double ×tamp)构造函数 在构造函数中,会对特征点进行提取。 ExtractORB(0,imGray);特征点分配至网格 将图像划分为48*64的网格,然后将…

Servlet的基本架构
Servlet的基本架构: package test;import java.io.IOException;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class Serv…

ORACLE 用户权限管理
Oracle创建用户的语法: CREATE USER username IDENTIFIED BY password OR IDENTIFIED EXETERNALLY OR IDENTIFIED GLOBALLY AS CNuser [DEFAULT TABLESPACE tablespace] [TEMPORARY TABLESPACE temptablespace] [QUOTA [integer K[M] ] [UNLIMITED] ] ON tables…

iOS 直播专题6-流媒体服务器
常用的流媒体服务器有: nginx、SRS、BMS 这里主要介绍nginx、SRS 这里都用docker来运行流媒体服务器 docker 安装 下载Mac版docker stable 直接安装 注册一个docer账号直接登录SRS 安装 SRS guthub地址:https://github.com/ossrs/srs/ 启动上面安装的docker软件后,打开终端…

Linux05-进程管理
目录 一、进程 1.1、进程ID 1.2、列出进程 1.3、进程前后台 二、使用信号控制进程 三、以管理员身份注销用户(踢掉在线用户) 四、监控进程活动 4.1、负载平均值 4.2、实时进程监控 进程是已启动的可执行程序的运行中的实力。它由以下部分组成&a…

Mat常用赋值方式
参考https://blog.csdn.net/wanggao_1990/article/details/53264753 #include <iostream> #include <opencv2/opencv.hpp> #include <unordered_map> using namespace std; using namespace cv; int main(int argc,char** argv) {// 1Mat mat (Mat_<flo…