ORB-SLAM2学习笔记7之System主类和多线程

文章目录

  • 0 引言
  • 1 整体框架
    • 1.1 整体流程
  • 2 System主类
    • 2.1 成员函数
    • 2.2 成员变量
  • 3 多线程
    • 3.1 ORB-SLAM2中的多线程
    • 3.2 加锁

0 引言

ORB-SLAM2是一种基于特征的视觉SLAMSimultaneous Localization and Mapping)系统,它能够从单个、双目或RBGD相机的输入中实时地同时定位相机的位置,并构建环境的三维地图。ORB-SLAM2是在ORB-SLAM的基础上进行改进和扩展的版本。

本文主要对ORB-SLAM2的整体框架,System主类和多线程进行学习和总结,如有理解错误,欢迎指正交流。

1 整体框架

1.1 整体流程

ORB-SLAM2整体框架如下图,主要流程可以概括为以下几个步骤:

请添加图片描述

  1. 特征提取和匹配ORB-SLAM2首先对输入的图像进行特征提取,通常使用Oriented FAST and Rotated BRIEF (ORB)算法来检测和描述图像中的特征点。然后,它使用特征描述子进行特征匹配,以在连续帧之间建立对应关系。

  2. 初始化:初始化阶段是在初始帧上建立初始地图并估计相机的初始位姿。ORB-SLAM2使用基于单目、双目或RGB-D输入的不同方法来进行初始化。在单目或双目情况下,可以使用基于运动的方法或基于平面的方法来估计相机的初始位姿。在RGB-D情况下,可以通过三角测量来估计初始位姿。

  3. 跟踪:跟踪阶段是ORB-SLAM2的核心部分,它通过连续图像帧之间的特征匹配和运动估计来实时定位相机。通过追踪特征点的运动,ORB-SLAM2可以估计相机的位姿变化,并通过优化方法来减小累积误差。

  4. 局部地图更新ORB-SLAM2通过局部地图来表示环境的三维结构。在跟踪过程中,它会不断地更新和扩展局部地图,包括添加新的地图点和关键帧。同时,ORB-SLAM2还会执行一些优化步骤,如相机位姿优化、地图点优化等,以提高地图的一致性和准确性。

  5. 回环检测:回环检测是为了解决定位漂移和累积误差问题的关键步骤。ORB-SLAM2会在跟踪过程中检测可能的回环,并使用回环检测算法来识别和纠正回环。一旦回环被检测到,ORB-SLAM2会进行全局优化来提高整体的一致性。

  6. 闭环优化:闭环优化是在回环检测之后执行的步骤,通过全局优化来进一步提高地图的一致性和准确性。ORB-SLAM2会使用所有的关键帧和地图点进行非线性优化,以减小累积误差并提高整体的位姿和地图质量。

  7. 地图管理ORB-SLAM2会维护一个稠密的局部地图和一个稀疏的全局地图,用于表示环境的三维结构。地图管理模块负责管理和更新地图,包括删除冗余地图点、关键帧的选择和插入、地图点的筛选等。

以上是ORB-SLAM2的主要流程和步骤。通过不断的特征提取、跟踪、地图更新、回环检测和优化,ORB-SLAM2能够实现实时的定位和地图构建,并在大范围和长时间的场景中表现出较好的性能。

也有大佬绘制了更详细的流程图(以mono_tum.cc的运行流程为例,建议下载学习):
👉 https://www.jianguoyun.com/p/Dc1MEhMQ-9KLBxjM3uED

请添加图片描述
此外,还有大佬已经中文注释了ORB_SLAM2可以参考理解代码:
👉 https://github.com/electech6/ORB_SLAM2_detailed_comments/tree/master

但是在学习以上的核心的主要流程之前,需要先熟悉ORB-SLAM2中的System主类和多线程…

2 System主类

System类是ORB-SLAM2系统的主类,主要代码是头文件ORB_SLAM2/include/System.h和源文件ORB_SLAM2/src/System.cc,分析其主要的成员函数和成员变量。

2.1 成员函数

vscode打开System.cc文件,如下,可以看到成员函数的大纲:

请添加图片描述
具体成员函数的类型和定义如下:

成员函数类型定义
System(const string &strVocFile, string &strSettingsFile, const eSensor sensor, const bool bUseViewer=true)public构造System函数
cv::Mat TrackStereo(const cv::Mat &imLeft, const cv::Mat &imRight, const double &timestamp)public跟踪双目相机,返回相机位姿
cv::Mat TrackRGBD(const cv::Mat &im, const cv::Mat &depthmap, const double &timestamp)public跟踪RGBD相机,返回相机位姿
cv::Mat TrackMonocular(const cv::Mat &im, const double &timestamp)public跟踪单目相机,返回相机位姿
void ActivateLocalizationMode()public开启纯定位模式
void DeactivateLocalizationMode()public关闭纯定位模式
bool System::MapChanged()public检测地图是否有较大变化
void System::Reset()public系统复位
void System::Shutdown()public系统关闭
void System::SaveTrajectoryTUM(const string &filename)publicTUM格式保存相机运动轨迹
void System::SaveKeyFrameTrajectoryTUM(const string &filename)publicTUM格式保存关键帧位姿
void System::SaveTrajectoryKITTI(const string &filename)publicKITTI格式保存相机运动轨迹
int System::GetTrackingState()public获取追踪器状态
vector<MapPoint*> System::GetTrackedMapPoints()public获取追踪到的地图点
vector<cv::KeyPoint> System::GetTrackedKeyPointsUn()public获取追踪到的关键帧的点

2.2 成员变量

主要的成员变量及其定义如下:

成员变量类型定义
eSensor mSensorprivate传感器类型单目相机MONOCULAR,双目相机STEREO,彩色深度相机RGBD
ORBVocabulary* mpVocabularyprivateORB字典,保存ORB描述子聚类结果
KeyFrameDatabase* mpKeyFrameDatabaseprivate关键帧数据库,保存ORB描述子倒排索引
Map* mpMapprivate地图
Tracking* mpTrackerprivate追踪器
LocalMapping* mpLocalMapperprivate局部建图器
std::thread* mptLocalMappingprivate局部建图线程
LoopClosing* mpLoopCloserprivate回环检测器
std::thread* mptLoopClosingprivate回环检测线程
Viewer* mpViewerprivate查看器
FrameDrawer* mpFrameDrawerprivate帧绘制器
MapDrawer* mpMapDrawerprivate地图绘制器
std::thread* mptViewerprivate查看器线程
int mTrackingStateprivate追踪状态
std::mutex mMutexStateprivate追踪状态加锁
bool mbActivateLocalizationModeprivate开启纯定位模式
bool mbDeactivateLocalizationModeprivate关闭纯定位模式
std::mutex mMutexModeprivate纯定位模式加锁
bool mbResetprivate系统复位
std::mutex mMutexResetprivate系统复位加锁

都说ORB-SLAM2有三大线程TrackingLocalMappingLoopClosing线程,可从成员变量中只定义了LocalMappingLoopClosing线程,其实Tracking线程就是Syetem类的主线程,构成三大线程,虽然Tracking线程在代码实现上是主线程,但三者的关系其实是并发的。

3 多线程

刚刚学习到ORB-SLAM2中主要有三大线程,其实SLAM项目中一般都会使用多线程,由于某个节点可能同时订阅多个消息,或多个线程函数共享数据,为了防止在多个消息被订阅时发生处理时间过长或阻塞,而导致其他回调函数无法正常使用,也为了防止共享数据时在存储或调用时发生错乱,一般都会使用std::mutex(互斥锁)std::thread(多线程管理)

3.1 ORB-SLAM2中的多线程

ORB-SLAM2中三大线程中的Tracking线程产生关键帧的频率和时机不是固定的,三个线程同时运行,方便LocalMappingLoopClosing线程查询Tracking线程是否产生关键帧。

// Tracking线程主函数
void Tracking::Track() {// 进行跟踪// ...// 若跟踪成功,根据条件判定是否产生关键帧if (NeedNewKeyFrame())// 产生关键帧并将关键帧传给LocalMapping线程KeyFrame *pKF = new KeyFrame(mCurrentFrame, mpMap, mpKeyFrameDB);mpLocalMapper->InsertKeyFrame(pKF);	
}// LocalMapping线程主函数
void LocalMapping::Run() {// 死循环while (1) {// 判断是否接收到关键帧if (CheckNewKeyFrames()) {// 处理关键帧// ...// 将关键帧传给LoopClosing线程mpLoopCloser->InsertKeyFrame(mpCurrentKeyFrame);}// 线程暂停3毫秒,3毫秒结束后再从while(1)循环首部运行std::this_thread::sleep_for(std::chrono::milliseconds(3));}
}// LoopClosing线程主函数
void LoopClosing::Run() {// 死循环while (1) {// 判断是否接收到关键帧if (CheckNewKeyFrames()) {// 处理关键帧// ...}// 查看是否有外部线程请求复位当前线程ResetIfRequested();// 线程暂停5毫秒,5毫秒结束后再从while(1)循环首部运行std::this_thread::sleep_for(std::chrono::milliseconds(5));}
}

3.2 加锁

多线程一般都是和锁一起使用,ORB-SLAM2中多线程和互斥锁一起使用,而互斥锁是有范围的,锁的有效性仅限于大括号{}之内,程序运行出大括号之后就释放锁。另外,一把锁一般在某个时刻只有一个线程能够拿到,比如程序执行到某个需要锁的范围,但是锁正在另一个线程,那当前线程就会先停下来,直到其他线程释放这个锁,当前线程才能继续向下运行。

void KeyFrame::EraseConnection(KeyFrame *pKF) {// 以下大括号中的代码部分加锁{unique_lock<mutex> lock(mMutexConnections);if (mConnectedKeyFrameWeights.count(pKF)) {mConnectedKeyFrameWeights.erase(pKF);bUpdate = true;}}// 程序运行到这里就释放锁,比如下行代码未在加锁范围UpdateBestCovisibles();
}

至此,学习了ORB-SLAM2中的System主类的实现细节和ORB-SLAM2中的多线程。后续在此基础上继续学习ORB-SLAM2中的输入预处理部分的核心—特征点的提取、描述子的生成及特征点匹配等等。


Reference:

  • https://github.com/raulmur/ORB_SLAM2



须知少时凌云志,曾许人间第一流。



⭐️👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍🌔

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/66355.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

K8S系列二:实战入门

I. 配置kubectl 1.1 什么是kubectl&#xff1f; 官方文档中介绍kubectl是&#xff1a; Kubectl 是一个命令行接口&#xff0c;用于对 Kubernetes 集群运行命令。Kubectl的配置文件在$HOME/.kube目录。我们可以通过设置KUBECONFIG环境变量或设置命令参数–kubeconfig来指定其他…

优雅地处理RabbitMQ中的消息丢失

目录 一、异常处理 二、消息重试机制 三、错误日志记录 四、死信队列 五、监控与告警 优雅地处理RabbitMQ中的消息丢失对于构建可靠的消息系统至关重要。下面将介绍一些优雅处理消息丢失的方案&#xff0c;包括异常处理、重试机制、错误日志记录、死信队列和监控告警等。…

分布式系统的 38 个知识点

天天说分布式分布式&#xff0c;那么我们是否知道什么是分布式&#xff0c;分布式会遇到什么问题&#xff0c;有哪些理论支撑&#xff0c;有哪些经典的应对方案&#xff0c;业界是如何设计并保证分布式系统的高可用呢&#xff1f; 1. 架构设计 这一节将从一些经典的开源系统架…

wsl没有响应,wsl启动失败,docker启动失败

wsl的相关问题记录和解决 问题一&#xff1a;cmd命令窗口输入wsl后没有响应&#xff0c;会卡住&#xff0c;类似如图 排查&#xff1a; 输入 wsl -l -v看是否有东西输出&#xff1b;我的电脑没有东西输出&#xff0c;依旧是卡住;有内容请重启试试从开始菜单打开&#xff0c;点…

[保研/考研机试] KY80 进制转换 北京大学复试上机题 C++实现

题目链接&#xff1a; KY80 进制转换https://www.nowcoder.com/share/jump/437195121691735660774 描述 写出一个程序&#xff0c;接受一个十六进制的数值字符串&#xff0c;输出该数值的十进制字符串(注意可能存在的一个测试用例里的多组数据)。 输入描述&#xff1a; 输…

Maven 基础学习及使用

Maven1 Maven简介1.1 Maven模型1.2 仓库 2 Maven安装配置3 Maven基本使用3.1 Maven 常用命令3.2 Maven 生命周期 4 IDEA使用Maven4.1 IDEA配置Maven环境4.2 Maven 坐标详解4.3 IDEA 创建 Maven项目4.4 IDEA 导入 Maven项目 5 依赖管理5.1 使用坐标引入jar包5.2 依赖范围 Maven …

pytest的fixture梳理

fixture特性 可以重复使用&#xff0c;多个用例可以使用同一个fixture一个测试用例可以使用多个装置 import pytest # Arrange pytest.fixture def first_entry():return "a"# Arrange pytest.fixture def second_entry():return 2# Arrange pytest.fixture def or…

vscode搭建c语言环境问题

c语言环境搭建参考文章:【C语言初级阶段学习1】使用vscode运行C语言&#xff0c;vscode配置环境超详细过程&#xff08;包括安装vscode和MinGW-W64安装及后续配置使用的详细过程&#xff0c;vscode用户代码片段的使用&#xff09;[考研专用]_QAQshift的博客-CSDN博客 问题如下:…

FPGA外部触发信号毛刺产生及滤波

1、背景 最近在某个项目中&#xff0c;遇到输入给FPGA管脚的外部触发信号因为有毛刺产生&#xff0c;导致FPGA接收到的外部触发信号数量多于实际值。比如&#xff1a;用某个信号源产生1000个外部触发信号&#xff08;上升沿触发方式&#xff09;给到FPGA输入IO&#xff0c;实际…

工作:MODBUS通讯协议知识

工作&#xff1a;MODBUS通讯协议知识 一、Modbus三种通讯分类 Modbus TCP/IP 使用网口通讯&#xff0c;更多是用于快速网络设备&#xff0c;如机器人&#xff0c;上位机视觉。 Modbus RTU 使用RS232或者RS485/RS422接口&#xff0c;通讯方式是串口通讯&#xff0c;是直接传输…

《论文阅读13》Efficient Urban-scale Point Clouds Segmentationwith BEV Projection

一、论文 研究领域&#xff1a; 城市级3D语义分割论文&#xff1a;Efficient Urban-scale Point Clouds Segmentationwith BEV Projection清华大学&#xff0c;新疆大学2021.9.19论文github论文链接 二、论文概要 2.1主要思路 提出了城市级3D语义分割新的方法&#xff0c;将…

云服务监控解决方案

云监控是追踪、警报和报告性能指标的过程&#xff0c;目的是全面了解云服务和资源。应用程序管理器具有分析混合云和多云基础架构以及托管在其上的应用程序的性能所需的所有必要功能&#xff0c;它使管理员能够主动发现云服务的性能瓶颈&#xff0c;并在它们影响最终用户之前快…