当前位置: 首页 > news >正文

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



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



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

相关文章:

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

文章目录 0 引言1 整体框架1.1 整体流程 2 System主类2.1 成员函数2.2 成员变量 3 多线程3.1 ORB-SLAM2中的多线程3.2 加锁 0 引言 ORB-SLAM2是一种基于特征的视觉SLAM&#xff08;Simultaneous Localization and Mapping&#xff09;系统&#xff0c;它能够从单个、双目或RBG…...

gin的占位符:和通配符*

1、用法 在 Gin 路由中&#xff0c;可以使用一个通配符&#xff08;*&#xff09;或一个占位符&#xff08;:&#xff09;来捕获 URL 的一部分。 r.GET("/royal/:id", func(c *gin.Context) {id : c.Param("id")//fmt.Println("into :id")c.Str…...

【量化课程】08_2.深度学习量化策略基础实战

文章目录 1. 深度学习简介2. 常用深度学习模型架构2.1 LSTM 介绍2.2 LSTM在股票预测中的应用 3. 模块分类3.1 卷积层3.2 池化层3.3 全连接层3.4 Dropout层 4. 深度学习模型构建5. 策略实现 1. 深度学习简介 深度学习是模拟人脑进行分析学习的神经网络。 2. 常用深度学习模型架…...

12-数据结构-数组、矩阵、广义表

数组、矩阵、广义表 目录 数组、矩阵、广义表 一、数组 二.矩阵 三、广义表 一、数组 这一章节理解基本概念即可。数组要看清其实下标是多少&#xff0c;并且二维数组&#xff0c;存取数据&#xff0c;要先看清楚是按照行存还是按列存&#xff0c;按行则是正常一行一行的去读…...

Idea 反编译jar包

实际项目中&#xff0c;有时候会需要更改jar包源码来达到业务需求&#xff0c;本文章将介绍一下如何通过Idea来进行jar反编译 1、Idea安装decompiler插件 2、找到decompiler插件文件夹 decompiler插件文件夹路径为&#xff1a;idea安装路径/plugins/java-decompiler/lib 3、…...

【Git】安装以及基本操作

目录 一、初识Git二、 在Linux底下安装Git一&#xff09;centOS二&#xff09;Ubuntu 三、 Git基本操作一&#xff09; 创建本地仓库二&#xff09;配置本地仓库三&#xff09;认识工作区、暂存区、版本库四&#xff09;添加文件五&#xff09;查看.git文件六&#xff09;修改文…...

Spring创建Bean的过程(2)

上一节介绍了Spring创建过程中的两个重要的接口&#xff0c;那么它们在创建Bean的过程中起到了什么作用呢&#xff1f;接下来请看&#xff1a; Spring有三种方式寻找 xml 配置文件&#xff0c;根据 xml 文件内容来构建 ApplicationContext&#xff0c;分别为ClassPathXmlAppli…...

Linux 终端操作命令(2)内部命令

Linux 终端操作命令 也称Shell命令&#xff0c;是用户与操作系统内核进行交互的命令解释器&#xff0c;它接收用户输入的命令并将其传递给操作系统进行执行&#xff0c;可分为内部命令和外部命令。内部命令是Shell程序的一部分&#xff0c;而外部命令是独立于Shell的可执行程序…...

【Git】大大大问题之syntax error near unexpected token `(‘ 的错误解决办法

话不多说&#xff0c;先上图&#xff1a; 如图&#xff0c;因为在linux环境里&#xff0c;文件路径中含有括号&#xff08;&#xff09;&#xff0c;因此报错&#xff01; 解决办法 等同于 &#xff1a;linux下解决bash: syntax error near unexpected token (’ 的错误&am…...

Flink源码之TaskManager启动流程

从启动命令flink-daemon.sh可以看出TaskManger入口类为org.apache.flink.runtime.taskexecutor.TaskManagerRunner TaskManagerRunner::main TaskManagerRunner::runTaskManagerProcessSecurely TaskManagerRunner::runTaskManager //构造TaskManagerRunner并调用start()方法 …...

加入微软MCPP有什么优势?

目录 专业认可 技术支持 销售和市场推广支持 培训和认证 业务机会和合作伙伴网络...

leetcode做题笔记78子集

给你一个整数数组 nums &#xff0c;数组中的元素 互不相同 。返回该数组所有可能的子集&#xff08;幂集&#xff09;。 解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。 思路一&#xff1a;回溯 void backtracking(int* nums, int numsSize, int** res, int* ret…...

Skywalking-9.6.0系列之本地源码编译并启动

Skywalking相信有很多人使用过&#xff0c;通过容器或者下载安装包进行安装的&#xff0c;今天从源代码角度&#xff0c;拉取、构建、启动。 官方文档步骤简洁明了&#xff0c;我这边会结合自己遇到的一些问题做出总结。 当前构建资源版本&#xff1a; MAC 10.15.7IDEA 2021.…...

proteus结合keil-arm编译器构建STM32单片机项目进行仿真

proteus是可以直接创建设计图和源码的&#xff0c;但是源码编译它需要借助keil-arm编译器&#xff0c;也就是我们安装keil-mdk之后自带的编译器。 下面给出一个完整的示例&#xff0c;主要是做一个LED灯闪烁的效果。 新建工程指定路径&#xff0c;Schematic,PCB layout都选择默…...

第五十三天

●剪辑——Pr 剪辑(Film editing)&#xff0c;即将影片制作中所拍摄的大量素材&#xff0c;经过选择、取舍、分解与组接&#xff0c;最终完成一个连贯流畅、含义明确、主题鲜明并有艺术感染力的作品。 •线性编辑 将素材按时间顺序连接成新的连续画面的技术 •非线性编辑 …...

gorm基本操作

一、gorm安装 1.下载gorm go get -u gorm.io/gorm //gorm框架 go get -u gorm.io/driver/mysql //驱动2.mysql准备工作 mysql> create database godb; mysql> grant all on *.* to admin% identified by golang123!; mysql> flush privileges;3.导入gorm框架 impo…...

华为OD机试 - 排队游戏(Java JS Python)

题目描述 新来的老师给班里的同学排一个队。 每个学生有一个影力值。 一些学生是刺头,不会听老师的话,自己选位置,非刺头同学在剩下的位置按照能力值从小到大排。 对于非刺头同学,如果发现他前面有能力值比自己高的同学,他不满程度就增加,增加的数量等于前面能力值比…...

滚动条样式更改

::-webkit-scrollbar 滚动条整体部分&#xff0c;可以设置宽度啥的 ::-webkit-scrollbar-button 滚动条两端的按钮 ::-webkit-scrollbar-track 外层轨道 ::-webkit-scrollbar-track-piece 内层滚动槽 ::-webkit-scrollbar-thumb 滚动的滑块 ::-webkit-scrollbar…...

掌握Python的X篇_33_MATLAB的替代组合NumPy+SciPy+Matplotlib

numPy 通常与 SciPy( Scientific Python )和 Matplotlib (绘图库)一起使用&#xff0c;这种组合广泛用于替代 MatLab&#xff0c;是一个强大的科学计算环境&#xff0c;有助于我们通过 Python 学习数据科学或者机器学习。 文章目录 1. numpy1.1 numpy简介1.2 矩阵类型的nparra…...

Python解决-力扣002-两数相加

两数相加&#xff1a;链表表示的逆序整数求和 在这篇技术博客中&#xff0c;我们将讨论一个力扣&#xff08;LeetCode&#xff09;上的编程题目&#xff1a;两数相加。这个问题要求我们处理两个非空链表&#xff0c;它们表示两个非负整数。每个链表中的数字都是逆序存储的&…...

SkyWalking 10.2.0 SWCK 配置过程

SkyWalking 10.2.0 & SWCK 配置过程 skywalking oap-server & ui 使用Docker安装在K8S集群以外&#xff0c;K8S集群中的微服务使用initContainer按命名空间将skywalking-java-agent注入到业务容器中。 SWCK有整套的解决方案&#xff0c;全安装在K8S群集中。 具体可参…...

css实现圆环展示百分比,根据值动态展示所占比例

代码如下 <view class""><view class"circle-chart"><view v-if"!!num" class"pie-item" :style"{background: conic-gradient(var(--one-color) 0%,#E9E6F1 ${num}%),}"></view><view v-else …...

智能在线客服平台:数字化时代企业连接用户的 AI 中枢

随着互联网技术的飞速发展&#xff0c;消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁&#xff0c;不仅优化了客户体验&#xff0c;还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用&#xff0c;并…...

相机从app启动流程

一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...

Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)

引言&#xff1a;为什么 Eureka 依然是存量系统的核心&#xff1f; 尽管 Nacos 等新注册中心崛起&#xff0c;但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制&#xff0c;是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...

优选算法第十二讲:队列 + 宽搜 优先级队列

优选算法第十二讲&#xff1a;队列 宽搜 && 优先级队列 1.N叉树的层序遍历2.二叉树的锯齿型层序遍历3.二叉树最大宽度4.在每个树行中找最大值5.优先级队列 -- 最后一块石头的重量6.数据流中的第K大元素7.前K个高频单词8.数据流的中位数 1.N叉树的层序遍历 2.二叉树的锯…...

论文笔记——相干体技术在裂缝预测中的应用研究

目录 相关地震知识补充地震数据的认识地震几何属性 相干体算法定义基本原理第一代相干体技术&#xff1a;基于互相关的相干体技术&#xff08;Correlation&#xff09;第二代相干体技术&#xff1a;基于相似的相干体技术&#xff08;Semblance&#xff09;基于多道相似的相干体…...

MySQL JOIN 表过多的优化思路

当 MySQL 查询涉及大量表 JOIN 时&#xff0c;性能会显著下降。以下是优化思路和简易实现方法&#xff1a; 一、核心优化思路 减少 JOIN 数量 数据冗余&#xff1a;添加必要的冗余字段&#xff08;如订单表直接存储用户名&#xff09;合并表&#xff1a;将频繁关联的小表合并成…...

GO协程(Goroutine)问题总结

在使用Go语言来编写代码时&#xff0c;遇到的一些问题总结一下 [参考文档]&#xff1a;https://www.topgoer.com/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/goroutine.html 1. main()函数默认的Goroutine 场景再现&#xff1a; 今天在看到这个教程的时候&#xff0c;在自己的电…...

掌握 HTTP 请求:理解 cURL GET 语法

cURL 是一个强大的命令行工具&#xff0c;用于发送 HTTP 请求和与 Web 服务器交互。在 Web 开发和测试中&#xff0c;cURL 经常用于发送 GET 请求来获取服务器资源。本文将详细介绍 cURL GET 请求的语法和使用方法。 一、cURL 基本概念 cURL 是 "Client URL" 的缩写…...