orbslam2代码解读(4):loopclosing回环检测线程

news2024/12/23 22:51:32

书接上回,介绍完了局部建图线程,局部建图线程在进行局部BA之后,也会将新的关键帧mpLoopCloser放进回环线程的mlpLoopKeyFrameQueue容器中。所以这时候回环检测线程就根据这个新的关键帧来进行回环检测的操作。

回环检测的主要程序

// 线程主循环
    while(1)
    {
        // Loopclosing中的关键帧是LocalMapping发送过来的,LocalMapping是Tracking中发过来的
        // 在LocalMapping中通过 InsertKeyFrame 将关键帧插入闭环检测队列mlpLoopKeyFrameQueue
        // Step 1 查看闭环检测队列mlpLoopKeyFrameQueue中有没有关键帧进来
        if(CheckNewKeyFrames())
        {
            // Detect loop candidates and check covisibility consistency
            if(DetectLoop())
            {
               // Compute similarity transformation [sR|t]
               // In the stereo/RGBD case s=1
               if(ComputeSim3())
               {
                   // Perform loop fusion and pose graph optimization
                   CorrectLoop();
               }
            }
        }
        // 查看是否有外部线程请求复位当前线程
        ResetIfRequested();
        // 查看外部线程是否有终止当前线程的请求,如果有的话就跳出这个线程的主函数的主循环
        if(CheckFinish())
            break;
        //usleep(5000);
		std::this_thread::sleep_for(std::chrono::milliseconds(5));
	}
    // 运行到这里说明有外部线程请求终止当前线程,在这个函数中执行终止当前线程的一些操作
    SetFinish();

cvlife的注释版删掉一些冗余的解释后,主要就是这么一个流程,后续就逐个流程介绍。

step1,DetectLoop()

如果mlpLoopKeyFrameQueue容器中有新的关键帧,就会执行DetectLoop()函数。
这个函数的过程如下:

  1. 从队列中取出新的关键帧,作为当前检测闭环关键帧,且设置当前关键帧不要在优化的过程中被删除(mpCurrentKF->SetNotErase()
  2. 如果距离上次闭环没多久(小于10帧),或者map中关键帧总共还没有10帧,则不进行闭环检测
  3. 遍历当前回环关键帧所有连接关键帧(一级相邻关键帧),计算当前关键帧与每个共视关键帧的bow相似度得分,并得到最低得分minScore。意义:本质就是设置一个阈值,意思就是如果回环候选帧的相似度得分都比一级相邻关键帧的得分低,那么这些回环候选帧就不可信
  4. 在所有关键帧中找出相似度得分大于minScore的闭环候选帧(注意候选帧应该选不和当前帧相连的关键帧)。
    在这里插入图片描述
  5. 在候选帧中检测具有连续性的候选帧。其实就是当一个候选关键帧符合相似度要求的时候,先不急着确立回环关系,仅仅当候选关键帧连续与三个(代码上写的是3个,也可以改)新的关键帧都能连接上的时候,才确立回环关系。
    在这里插入图片描述
  6. 将当前新的关键帧放到关键帧数据库mpKeyFrameDB中,如果成功检测到回环就返回true,否则返回false。

step2,ComputeSim3()

如果上一个函数检测到回环了,那么就需要求出回环两个关键帧之间的匹配关系。如果是单目情况就需要考虑尺度漂移的问题,所以计算Sim3变换;如果是双目或者rgbd,这个尺度直接就设置成1。
这个函数的过程如下:

  1. 遍历闭环候选帧集,初步筛选出与当前关键帧的匹配特征点数大于20的候选帧集合(经典使用词袋找到两帧的匹配点对SearchByBoW),并为每一个候选帧构造一个Sim3Solver。
  2. 对每一个候选帧用Sim3Solver迭代匹配,直到有一个候选帧匹配成功,或者全部失败。匹配成功的过程:①先是通过Sim3Solver进行迭代求解,如果能够得到一个粗略的Sim3变换,那么就需要进一步优化这个粗略的Sim3变换。②通过matcher.SearchBySim3找到两帧更多的匹配点对(只有互相投影都成功匹配的才认为是可靠的匹配)。③用新的匹配点对通过g2o来优化Sim3(只优化Sim3,不优化地图点)。
    在这里插入图片描述在这里插入图片描述
           SearchBySim3             g2o的Sim3优化
  3. 如果Sim3优化成功,取出闭环候选的关键帧及其共视关键帧,以及这些共视关键帧的地图点。
  4. 根据Sim3变换,将闭环候选关键帧及其连接关键帧的所有地图点投影到当前关键帧进行投影匹配(matcher.SearchByProjection),如果匹配点对超过40个,则说明这个闭环是稳定且成功的,否则说明这个闭环是失败的,删除相关信息。
    在这里插入图片描述
          闭环候选帧往当前帧的投影过程

step3,CorrectLoop()

这个函数就是根据上一个函数计算出来的Sim3变换,调整与当前帧相连的关键帧位姿以及这些关键帧观测到的地图点位置。(简单来说就是位姿和尺度的联合矫正)
这个函数的过程如下:

  1. 结束局部地图线程、全局BA,为闭环矫正做准备
  2. 根据共视关系更新当前关键帧与其它关键帧之间的连接关系(因为之前闭环检测、计算Sim3中增加了该关键帧的地图点,所以需要更新)
  3. 得到Sim3优化后,当前帧与世界坐标系之间的Sim变换在ComputeSim3函数中已经确定并优化,通过相对位姿关系,可以确定这些相连的关键帧与世界坐标系之间的Sim3变换,进行后续的矫正。
    在这里插入图片描述
  4. 得到矫正的当前关键帧的共视关键帧位姿后,修正这些共视关键帧的地图点。修正的具体流程:①将当前kf及其共视kf的地图点进行遍历,先将地图点从世界坐标系根据初始的相机位姿(g2oSiw,这个相机位姿因为累计误差会有尺度漂移,所以实际上这个位姿是有尺度的)变换到相机坐标系。②再通过矫正后的相机位姿(g2oCorrectedSwi,这个Sim的尺度其实就是为了抵消尺度漂移而产生的尺度)将相机坐标系的地图点矫正回到世界坐标系当中。③至此这些地图点的尺度一致了。
    在这里插入图片描述
  5. 根据(当前关键帧和其相连的关键帧)与世界坐标系之间的Sim3变换,将Sim3转换成SE3,并且更新关键帧的位姿。这时(当前关键帧和其相连的关键帧)与产生时间较早的闭环候选关键帧的位姿也尺度一致了。具体Sim3转换SE3的代码:
    // 调用toRotationMatrix 可以自动归一化旋转矩阵
    Eigen::Matrix3d eigR = g2oCorrectedSiw.rotation().toRotationMatrix(); 
    Eigen::Vector3d eigt = g2oCorrectedSiw.translation();                  
    double s = g2oCorrectedSiw.scale();
    // 平移向量中包含有尺度信息,还需要用尺度归一化
    eigt *=(1./s); 

最终当前关键帧和其相连的关键帧直接设置为校正后的SE3,且更新关键帧之间的连接关系。

  1. 检查当前帧的地图点与经过闭环匹配后该帧的地图点是否存在冲突,对冲突的进行替换或填补。本质上更相信回环过程中得到的地图点(时间靠前,累计误差小),而当前关键帧原来的地图点时间靠后可能有累计误差。

  2. 闭环候选帧的相连关键帧组投影到当前关键帧的相连关键帧组中进行匹配,新增或替换当前关键帧的相连关键帧组中的地图点。跟第6步本质上是一样的,更相信闭环候选帧的相连关键帧组中的地图点,误差更小。第6、7步都是做关键帧之间地图点的更新融合,因为前面经过了尺度对齐,所以地图点肯定会有冲突。具体两个相连组也可以看下图:
    在这里插入图片描述

  3. 更新当前关键帧组之间的两级共视相连关系,得到因闭环时地图点融合而新得到的连接关系。这个步骤最大的作用就是得到因为闭环地图点调整而新生成的连接关系,后续本质图优化的时候需要加的边。

  4. 进行本质图优化。仅仅优化本质图中所有关键帧的位姿(Sim3位姿优化),不优化地图点。共视图比较稠密,本质图比共视图更稀疏,这是因为本质图的作用是用在闭环矫正时,用相似变换来矫正尺度漂移,把闭环误差均摊在本质图中。本质图中节点也是所有关键帧,但是连接边更少,只保留了联系紧密的边来使得结果更精确。本质图中的边包含:①生成树连接关系。②形成闭环的连接关系,闭环后地图点变动后新增加的连接关系。③当前帧与闭环匹配帧之间的连接关系(这里面也包括了当前遍历到的这个关键帧之前曾经存在过的回环边)。④共视程度超过100的关键帧也作为边进行优化。
    在这里插入图片描述在这里插入图片描述
             本质图                 生成树

最后就是将优化后的位姿更新到关键帧中,并且地图点根据参考帧优化前后的相对关系调整自己的位置,然后更新地图点的平均观测方向和深度。

  1. 本质图将位姿优化完后,新建一个线程用于全局BA优化。因为在全局BA之前,数据已经做了很多处理,通过本质图对相机位姿进行了优化,并且地图点也根据参考帧优化前后的相对关系调整自己的位置,所以这个全局BA的代码还是比较容易懂的。需要注意的点是:①这个全局BA除了初始关键帧是固定的,其他关键帧和地图点都是需要优化的量。②相机位姿是SE3优化,因为在本质图优化的时候是Sim3优化,并且做了尺度归一化了,所以全局BA用的是SE3优化。

总结

完结撒花!!!这一系列的记录文章,主要是把orbslam2中一些主要的函数实现过程弄清楚,并且明白整个orbslam2的运行流程。所以不会对函数中具体的代码做详细的讲解(这部分完全可以去看代码注释),而我们要做的是明白orbslam2的流程和处理思路。在学习orbslam2的时候真的学习到了很多,之前看完视觉slam14讲,里面的内容确实很多很详细可以作为一个教科书,但是更多的还是得学优秀的开源项目,这样才能对slam整个框架有更深的理解。感谢orbslam2的讲解课程和注解代码。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

177.二叉树:从前序与中序遍历序列构造二叉树(力扣)

代码解决 /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}* Tre…

176.二叉树:从中序与后序遍历序列构造二叉树(力扣)

代码解决 /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}* Tre…

OpenGauss常操作

OpenGauss官网已经有很详细的说明了,但是对于新手而言还有一些需要注意的地方; 安装 yum一键安装; yum -y install libaio-devel yum -y install readline-devel yum -y install libnsl 单独创建用户和组; groupadd dbgroup useradd -g dbgroup omm passwd omm 取消打开文…

DriveWorld:一个预训练模型大幅提升检测+地图+跟踪+运动预测+Occ多个任务性能

1. 写在前面 以视觉为中心的自动驾驶技术近期因其较低的成本而引起了广泛关注,而预训练对于提取通用表示至关重要。然而,当前的以视觉为中心的预训练通常依赖于2D或3D预训练任务,忽视了自动驾驶作为4D场景理解任务的时序特征。这里通过引入一…

中国最受欢迎起名大师,国内顶级的姓名学大师是谁

唐王古镇龙泉边, 端午邀约凤凰山, 举国共享康宁日, 泉星福瑞天下安… 颜廷利敬献---福祐安康 中国最受欢迎起名大师,国内顶级的姓名学大师是谁?在齐鲁的心脏,济南的历史悠长的唐王古镇边,龙泉大…

香港优才是不是智商税?搞懂香港身份不后悔

很多中产家庭和明星通过不同方式获得香港身份,以享受其诸多优势,如子女教育和事业发展。明星如孙俪/邓超夫妇、汤唯、朗朗、章子怡和黄晓明等都获得了香港身份。 一、香港身份「优才计划」是什么?是否值得追求? 香港身份&#xf…

知识管理与集体创新——从企业到新型研发机构的实践与思考︱PMO大会

全国PMO专业人士年度盛会 鹏城实验室人力资源处人才发展主管,原华为供应链管理部知识管理负责人王万翎女士受邀为PMO评论主办的2024第十三届中国PMO大会演讲嘉宾,演讲议题为“知识管理与集体创新——从企业到新型研发机构的实践与思考”。大会将于6月29-…

springboot在线雅思学习平台 -计算机毕业设计源码44566

目 录 摘要 1 绪论 1.1系统背景 1.2课题背景及目的 2 1.3系统开发技术的特色 3 1.4 springboot框架介绍 3 1.5论文结构与章节安排 4 2 在线雅思学习平台系统分析 5 2.1 可行性分析 5 2.2 系统流程分析 5 2.2.1数据增加流程 5 2.2.2数据修改流程 6 2.2.3数据删除流程 6 2.3 …

Autoware 定位之EKF 滤波定位(四)

Tip: 如果你在进行深度学习、自动驾驶、模型推理、微调或AI绘画出图等任务,并且需要GPU资源,可以考虑使用UCloud云计算旗下的Compshare的GPU算力云平台。他们提供高性价比的4090 GPU,按时收费每卡2.6元,月卡只需要1.7元每小时&…

网络抓取的最佳用户代理 2024 | 避免在抓取时被禁止使用 UA

你是经常进行网页抓取的人吗?你对你的隐私非常小心吗?那么你一定多次听说过“用户代理”。你知道什么是用户代理吗?它如何影响我们的在线生活呢? 请开始阅读,你会对这篇博客中的一切感兴趣! 什么是用户代…

经典文献阅读之--FlashOcc(快速且内存高效的占用预测模块)

Tip: 如果你在进行深度学习、自动驾驶、模型推理、微调或AI绘画出图等任务,并且需要GPU资源,可以考虑使用UCloud云计算旗下的Compshare的GPU算力云平台。他们提供高性价比的4090 GPU,按时收费每卡2.6元,月卡只需要1.7元每小时&…

调用华为API实现语音合成

目录 1.作者介绍2.华为云语音合成2.1 语音合成介绍2.2 华为语音合成服务2.3 应用场景 3. 实验过程以及结果3.1 获取API密钥3.2 调用语音合成算法API3.3 实验代码3.4 运行结果 1.作者介绍 袁斌,男,西安工程大学电子信息学院,2023级研究生 研究…

哥斯拉v4.01webshell实验

1、工具使用 生成有效载荷 选择载荷和加密器 放到对应web目录下,然后就可以添加管理 2 、JAVA_AES_RAW-JSPX/JSP 流量 第一组:请求34880,响应0 第二组:请求48,响应32 第三组:请求64,响应2576…

Navicat访问宝塔中的MySQL

开放数据库权限: 开放3306端口: 连接数据库: 对应好用户名与名称,要不会报错1024:

【每日一题】错误的集合

错误的集合 ✨审题:在一个1-n的数组中,会有一个元素重复,一个元素丢失;👉目标;找到重复的元素和丢失的元素并放入一个数组中返还回去 ✨有没有想到单身狗问题的进阶版那个思路,找2个单身狗,一个…

升级和维护老旧LabVIEW程序

在升级老旧LabVIEW程序至64位环境时,需要解决兼容性、性能和稳定性等问题。本文从软件升级、硬件兼容性、程序优化、故障修复等多个角度详细分析。具体包括64位迁移注意事项、修复页面跳转崩溃、解决关闭程序后残留进程的问题,确保程序在新环境中的平稳运…

C++学习日记 | Lecture 7 函数进阶

资料来源:南科大 余仕琪 C/C Program Design LINK: CPP/week07 at main ShiqiYu/CPP GitHub7.1-default-arguments_哔哩哔哩_bilibili7.2-function-overloading_哔哩哔哩_bilibili7.3-function-templates_哔哩哔哩_bilibili7.4-function-pointers-an…

【课程总结】Day7:深度学习概述

前言 本篇文章,我们将通过示例来逐步学习理解导数、求函数最小值、深度学习的本质、以及使用numpy和pytorch实操深度学习训练过程。 线性回归 线性回归内容回顾 在《【课程总结】Day5(下):PCA降维、SVD分解、聚类算法和集成学习》中,我们…

Diffusers代码学习-ControlNet(Inpaint)

对于Inpaint,需要一个初始图像、一个蒙版图像和一个描述用什么替换蒙版的提示词。ControlNet模型允许添加另一个控制图片来调节模型。让我们用Inpaint蒙版来调整模型。这样,ControlNet可以使用修复掩模作为控件来引导模型在蒙版区域内生成图像。 # 以下代…

【Unity | Editor强化工具】资产快速访问工具

经常在Project窗口中翻找资产相对麻烦,Unity自带的Favorite功能又和Project窗口强绑定,且只能在双列视图下使用,故制作了一个可以在独立窗口中列举常用资产的小工具: Unity Asset Quick Access 。 CSDN弄了个Github加速计划&…