一、前言

笔者认真学习了一年半有余的SLAM,期间学习过V-SLAM、VI-SLAM、激光SLAM和激光+IMU的SLAM,在看论文和代码的闲暇之余,会时常逛知乎和CSDN等博客膜拜大佬们的文章,回顾整个过程,似乎自己没有在相关博客留下痕迹,也深刻体会到“好记性不如烂笔头”的警示作用,因此想把自己学过的东西进行总结,也抱着向大家学习的态度,文章不足之处欢迎大家批评指正。由于ORBSLAM3的SLAM功能比较完备,因而笔者的第一篇文章想对其进行解读。
        ORBSLAM3是2020年开源的视觉惯性SLAM框架,定位精度优于其他视觉惯性SLAM系统,并且包含了单目、双目、RGB-D、单目+IMU、双目+IMU和RGB-D+IMU六种模式,多地图系统也契合目前的SLAM鲁棒感知发展时期,笔者自己用相机实测的效果也不错。ORBSLAM框架系列设计了一套命名规则,整体代码可读性很友好,包含了许多算法原理细节,而不是直接调用OpenCV,比如ORB特征、对极几何和PnP等,很值得学习。本文将对ORBSLAM3的大体框架进行总结,后续也会写文章对系统的各个部分的算法原理进行解读。

二、系统枢纽

系统的程序入口在文件Examples和Examples_old 下,以System类充当整个系统的枢纽,在System类构造的同时,开启了跟踪、局部建图、回环检测和Pangolin可视化四个线程,各线程之间通过指针互相指向的方式进行内存共享,便于系统进行管理。如图1所示,系统的整个框架,跟踪部分(Tracking)主要负责完成位姿的初始估计,保证状态估计的实时性;局部建图(Local Mapping)线程主要负责对跟踪线程传入的关键帧位姿及对应的地图点进行优化,IMU模式下,还会以最大后验估计的方式对系统进行初始化;回环检测(Loop & Map merging)线程则用于矫正系统的累积误差,ORBSLAM3由于添加了多地图管理功能,因此回环检测线程还包括了地图合并功能;可视化线程主要通过调用基于OpenGL的Pangolin对系统的关键帧、地图点、图结构以及一些系统操作按钮进行可视化。后文将分线程对整个框架进行大体解读,由于系统的算法核心集中在跟踪、局部建图线程和回环检测线程,本文只对这三个线程内容进行解读。

图1 ORBSLAM3框架

为了让读者对系统有初步的了解,咱们按照头文件的顺序提前小小地剧透一下各头文件所要实现的功能。

CameraModels:包含GeometricCamera.h、KannalaBrandt8.h和Pinhole.h三个头文件,第一个是相机模型的基类, 后两者分别为鱼眼相机和针孔相机模型的实现。
Atlas.h:实现多地图管理功能,系统跟踪失败不至于轨迹重建失败,增强了系统的鲁棒性
Config.h:这个文件里面的功能貌似没见实现,可能是作者想用其实现系统配置文件功能,但还来不及具体实现
Converter.h:全部声明为静态成员函数,Converter类无需实例化即可被外部调用,主要实现OpenCV、Eigen和G2o格式矩阵之间的转换
Frame.h:图像帧类,实现图像信息的存储与操作
FrameDrawer.h:实现图像帧的可视化
G2oTypes.h:ORBSLAM3后端优化利用g2o实现的,此处定义了图优化用到的边和节点信息 GeometricTools.h 通用相机模型工具,用来计算基础矩阵和三角化。
ImuTypes.h:IMU相机参数模型及预积分类
Initializer.h:ORBSLAM2的初始化器,ORBSLAM3并没有使用
KeyFrame.h:关键帧类,后端与闭环模块都是基于关键帧来进行优化的,内部会包含共视图连接关系 KeyFrameDatabase.h 生成关键帧数据库,方便利用图像帧描述子生成的词袋向量和特征向量建立图像特征的匹配关系。
LocalMapping.h:局部建图线程。
LoopClosing.h:回环检测线程。
Map.h:地图类,包含在Atlas(多地图)当中,可看作多地图的子图,内部包括属于该子图的关键帧和地图点。
MapDrawer.h:地图可视化类。
MapPoint.h: 地图点类,地图点关联了多个图像中的特征点,系统的共视图、本质图和生成树都是以对地图点的观测共视关系来建立图结构的。
MLPnPsolver.h:最大似然PnP求解器,充分考虑了观测的不确定性,或者说观测噪声,并且可不依赖于相机模型。
OptimizableTypes.h:优化所使用的一些顶点和边。
Optimizer.h:各种优化模式具体的实现流程。
ORBextractor.h:特征点提取器,对图像以四叉树的方法提取特征点,并计算特征点描述子。ORBmatcher.h:ORB特征点匹配器。
ORBVocabulay.h:DBoW2的词袋模板类。
PnPsolver.h:EPnP求解器,ORBSLAM2重定位模块就是它的。
SerializationUtils.h:序列化相关的类。
Settings.h:ORBSLAMS新搞的一个类,用于读取配置文件。
Sim3Solver.h:sim3问题的求解器。
System.h:系统枢纽类,各个线程包含在这里面,也会系统算法的入口。
Tracking.h: 跟踪线程。
TwoViewReconstruction.h:对极几何和三角化类,主要应用于单目初始化。
Viewer.h:可视化线程。

三、跟踪线程

跟踪线程实则是系统的主线程,每来一帧数据调用一次System的跟踪成员函数,具体为以下(形参进行了省略),注意:为了与后端g2o流形优化位姿形式统一,ORBSLAM3使用Sophus定义的位姿结构来存储载体位姿。

Sophus::SE3f TrackMonocular(...){}

Sophus::SE3f TrackStereo(...){}

Sophus::SE3f TrackRGBD(...){}

之后构造图像帧类(Frame),对图像数据提取ORB特征,其中RGB-D和双目相机还会获取特征点的深度信息,RGB-D相机由于有深度图的加持,特征点深度则很容易获取,对于双目相机,若是立体的针孔相机,则通过基于SAD的双目立体匹配恢复深度,若是双目鱼眼相机,则使用暴力的近邻描述子匹配建立左右目的特征匹配,再结合标定的外参对特征点进行三角化获取深度信息。最后,转到跟踪(Tracking)类下的Track()函数对前端位姿进行初步的估计。根据系统阶段的不同、跟踪状态以及质量,可将跟踪阶段化分为:初始化模式、参考关键帧模式、运动模型模式和重定位模式。此外,跟踪阶段会通过NeedNewKeyFrame函数决定系统是否需要关键帧,若需要的话,会通过CreateNewKeyFrame建立新的关键帧,并插入局部建图线程进行优化。

四、局部建图线程

PTAM首次将系统化分为跟踪和建图线程,随后慢慢流行开来,如后来的SVO和ORBSLAM等都借鉴了这一思想。ORBSLAM3中跟踪线程用来保证位姿估计的实时性,建图线程对负责构建地图点并以共视图的方式对位姿和地图点中优化(当然IMU模式优化变量还包括速度与零偏),由于两个线程之间共享内存,优化后的地图点,又可以与跟踪线程的图像帧进行投影匹配,利用迭代PnP方法对跟踪线程的位姿进行优化,下面对局部建图流程进行大体介绍。

开启局部建图模式,首先需要设置不能接受关键帧,告知跟踪线程不要插入关键帧;若关键帧队列有关键帧数据并自IMU数据正常,则通过ProcessNewKeyFrame()函数处理新的关键帧,处理关键帧操作包括计算BOW向量、添加地图点信息(增加关于当前关键帧的观测、平均观测方向、观测深度范围和地图点最具代表性描述子)、更新共视图连接关系、将关键帧插入当前活动地图;对新增的地图点进行筛选,删除质量不好的地图点;遍历相邻的关键帧,生成新的地图点;若关键帧队列的关键帧已处理完毕,则进行地图点重复性检查,融合重复的地图点;之后,则分阶段进行IMU初始化,并进行全局VI-BA;若处于IMU模式并且IMU已经初始化完毕,则进行局部VI-BA,否则做纯视觉局部BA;此外,考虑到关键帧冗余会增加系统的计算量,移除点冗余关键帧。

五、回环检测线程

相较于ORBSLAM2,ORBSLAM3的回环模块功能添加了不少,主要是因为系统添加了多地图功能,若回环候选帧与当前帧不属于同一个地图,则需要进行地图合并,若属于同一个地图则进行回环矫正。由于传感器的噪声,系统不可避免存在累积误差,需要执行回环检测对系统的状态变量进行调整,直观地解释就是当前发生回环的帧与回环候选帧之间存在一定的误差,系统若是零漂移的,两者的误差应该是一样的,回环的意义就是通过建立优化目标函数,对系统的关键帧进行调整,使得存在的误差达到最小。

六、总结

本文对ORBSLAM3的大体框架先简单总结到这里,由于涉及到大量算法原理,一篇文章很难进行细致分析,因此后续会针对系统各个部分进行分开解读,陆续会包括:相机模型的推导、系统所涉及的重要数据结构、流形预积分的原理及推导、跟踪线程的四种跟踪模式、系统初始化问题、局部建图线程和回环检测线程详细解读。

ORBSLAM3整体框架相关推荐

  1. 【推荐系统】推荐系统整体框架概览

    感谢博文作者 Kevin_Duan 原文链接:https://blog.csdn.net/chunyun0716/article/details/83152037 推荐系统整体架构 先说点题外话,最近 ...

  2. 通俗易懂SpringMVC整体框架理解

    最近又重新温习了一下前台SpringMVC框架,能够从整体上对SpringMVC有一个全局的认识.在这里也总结一下,为那些即将学习SpringMVC的亲们,做一个很好的开端吧! 1. SpringMV ...

  3. V4L2 driver(一). 整体框架

    1.1 从字符设备说起 熟悉v4l2用户空间编程的都知道, v4l2编程主要是调用一系列的ioctl函数去对v4l2设备进行打开, 关闭, 查询, 设置等操作. v4l2设备是一个字符设备, 而且其驱 ...

  4. 推荐系统整体框架概览

    推荐系统整体框架概览 推荐系统整体架构 推荐系统的核心组成部分 离线 核心节点 服务 UI 总结 推荐系统整体架构 先说点题外话,最近在看的书中讲到了怎么进行自学的方法,分了十个层级.第一个便是要了解 ...

  5. 浅谈opencl之整体框架

    结合四大模型,以CPU和GPU平台为例子,opencl整体框架如下: CPU为host端, GPU为device端, host和device端的交互是以context为主.context贯穿到整个op ...

  6. jQuery源码分析 整体框架部分及部分常用方法

    最近尝试看看jQuery的源码. 版本 version = "1.11.1" 相对于看一本jQuery如何使用的书,看jQuery源码对它可以有更深层次的理解.jQuery中大量使 ...

  7. 第一次总结:整体框架

    第一次总结:整体框架 tcp部份: 1.初始化WiFi连接路由器 wifi.begin();bool b = wifi.Initialize(STA, SSID, PASSWORD);连接局域网if( ...

  8. zeptojs库解读1之整体框架

    首先看的是整体框架, // zepto骨骼,这个函数的作用使得Zepto(slector, context)使用很多$.fn里面的方法 var Zepto = (function(){// zepto ...

  9. 项目背景一般写什么_项目申报整体框架规划思路,提高你的书写逻辑!

    看到网友留言,希望我能分享下项目申报整体框架规划的思路,我们今天就这个内容深度讨论. 当我们拿到企业的所有材料的时候,第一件事情就是要看材料是否满足必须的申报条件,缺一不可,满足了这些条件,如果缺少一 ...

  10. 从0到1详解推荐系统的基础知识与整体框架

    猜你喜欢 0.淘宝首页猜你喜欢推荐建模实践 1.[免费下载]2022年6月份热门报告 2.[实践]小红书推荐中台实践 3.微信视频号实时推荐技术架构分享 4.对比学习在宽狩推荐系统中的应用实践 5.微 ...

最新文章

  1. 实战证明LINUX系统下密钥对验证的安全性
  2. 安全访问服务边缘(SASE)是什么?
  3. Hbase的读写流程
  4. [蓝桥杯][算法提高VIP]密码锁(BFS)
  5. [蓝桥杯]回形取数-方向向量+模拟
  6. mac下用xattr命令来删除文件的扩展属性
  7. 移动应用开发——实验二
  8. 基于51单片机的蜂鸣计算器设计
  9. 【AD】如何将喜欢的图案导出成为丝印层和PCB形状
  10. Vmware vSphere 5.0存储的连接
  11. C语言 整人程序“我是猪”
  12. h5禁止页面长按操作_解决HTML5对手机页面长按会粘贴复制禁用的方法-H5教程
  13. k8s core-dns 解析域名异常
  14. visual studio 2019 无法启动程序 系统找不到指定文件
  15. 一个简单的HTML网页
  16. 次梯度(subgradient)方法
  17. iphonex蓝牙打不开转圈_苹果6 plus蓝牙打不开总转圈怎么处理?
  18. c语言写rpg游戏,第1章 序(来,我们一起写个角色扮演游戏)
  19. 网络原理与交换机路由器应用
  20. 给大家介绍一下,这是twitter的创始人@

热门文章

  1. java ip子网计算器_ip子网计算器IPV4子网计算工具v1.1
  2. ASP.NET Web程序设计 第九章 初识 Web Pages
  3. 家庭收支软件用java写,eclipse编写的Java家庭收支记账软件
  4. docker修改服务器ip地址,如何修改docker的ip地址
  5. STM32WB55开发板(一)单板设计-硬件介绍
  6. 测试用例-1-微信发红包功能
  7. Mirth Linux(Centos)无界面安装及配置,可作为服务总线用,功能超强,就不细说了
  8. c# 服务器打印word文档,C#中5步完成word文档打印的方法
  9. QThread之重写run() 实现线程与业务解耦
  10. retainall java_瞬间教你学会使用java中list的retainAll方法