ORB-SLAM2 ---- Tracking::UpdateLastFrame函数

news2024/12/24 21:01:41

目录

1.函数作用

2.步骤 

3.code 

4.函数解释

4.1 利用参考关键帧更新上一帧在世界坐标系下的位姿

4.2 对于双目或rgbd相机,为上一帧生成新的临时地图点 


1.函数作用

        更新上一帧位姿,在上一帧中生成临时地图点。

        单目情况:只计算了上一帧的世界坐标系位姿
        双目和rgbd情况:选取有有深度值的并且没有被选为地图点的点生成新的临时地图点,提高跟踪鲁棒性

2.步骤 

Step 1:利用参考关键帧更新上一帧在世界坐标系下的位姿

Step 2:对于双目或rgbd相机,为上一帧生成新的临时地图点

Step 2.1:得到上一帧中具有有效深度值的特征点(不一定是地图点)

Step 2.2:从中找出不是地图点的部分  

Step 2.3:需要创建的点,包装为地图点。只是为了提高双目和RGBD的跟踪成功率,并没有添加复杂属性,因为后面会扔掉

Step 2.4:如果地图点质量不好,停止创建地图点

3.code 

void Tracking::UpdateLastFrame()
{
    // Update pose according to reference keyframe
    // Step 1:利用参考关键帧更新上一帧在世界坐标系下的位姿
    // 上一普通帧的参考关键帧,注意这里用的是参考关键帧(位姿准)而不是上上一帧的普通帧
    KeyFrame* pRef = mLastFrame.mpReferenceKF;  
    // ref_keyframe 到 lastframe的位姿变换
    cv::Mat Tlr = mlRelativeFramePoses.back();

    // 将上一帧的世界坐标系下的位姿计算出来
    // l:last, r:reference, w:world
    // Tlw = Tlr*Trw 
    mLastFrame.SetPose(Tlr*pRef->GetPose()); 

    // 如果上一帧为关键帧,或者单目的情况,则退出
    if(mnLastKeyFrameId==mLastFrame.mnId || mSensor==System::MONOCULAR)
        return;

    // Step 2:对于双目或rgbd相机,为上一帧生成新的临时地图点
    // 注意这些地图点只是用来跟踪,不加入到地图中,跟踪完后会删除

    // Create "visual odometry" MapPoints
    // We sort points according to their measured depth by the stereo/RGB-D sensor
    // Step 2.1:得到上一帧中具有有效深度值的特征点(不一定是地图点)
    vector<pair<float,int> > vDepthIdx;
    vDepthIdx.reserve(mLastFrame.N);

    for(int i=0; i<mLastFrame.N;i++)
    {
        float z = mLastFrame.mvDepth[i];
        if(z>0)
        {
            // vDepthIdx第一个元素是某个点的深度,第二个元素是对应的特征点id
            vDepthIdx.push_back(make_pair(z,i));
        }
    }

    // 如果上一帧中没有有效深度的点,那么就直接退出
    if(vDepthIdx.empty())
        return;

    // 按照深度从小到大排序
    sort(vDepthIdx.begin(),vDepthIdx.end());

    // We insert all close points (depth<mThDepth)
    // If less than 100 close points, we insert the 100 closest ones.
    // Step 2.2:从中找出不是地图点的部分  
    int nPoints = 0;
    for(size_t j=0; j<vDepthIdx.size();j++)
    {
        int i = vDepthIdx[j].second;

        bool bCreateNew = false;

        // 如果这个点对应在上一帧中的地图点没有,或者创建后就没有被观测到,那么就生成一个临时的地图点
        MapPoint* pMP = mLastFrame.mvpMapPoints[i];
        if(!pMP)
            bCreateNew = true;
        else if(pMP->Observations()<1)      
        {
            // 地图点被创建后就没有被观测,认为不靠谱,也需要重新创建
            bCreateNew = true;
        }

        if(bCreateNew)
        {
            // Step 2.3:需要创建的点,包装为地图点。只是为了提高双目和RGBD的跟踪成功率,并没有添加复杂属性,因为后面会扔掉
            // 反投影到世界坐标系中
            cv::Mat x3D = mLastFrame.UnprojectStereo(i);
            MapPoint* pNewMP = new MapPoint(
                x3D,            // 世界坐标系坐标
                mpMap,          // 跟踪的全局地图
                &mLastFrame,    // 存在这个特征点的帧(上一帧)
                i);             // 特征点id

            // 加入上一帧的地图点中
            mLastFrame.mvpMapPoints[i]=pNewMP; 

            // 标记为临时添加的MapPoint,之后在CreateNewKeyFrame之前会全部删除
            mlpTemporalPoints.push_back(pNewMP);
            nPoints++;
        }
        else
        {
            // 因为从近到远排序,记录其中不需要创建地图点的个数
            nPoints++;
        }

        // Step 2.4:如果地图点质量不好,停止创建地图点
        // 停止新增临时地图点必须同时满足以下条件:
        // 1、当前的点的深度已经超过了设定的深度阈值(35倍基线)
        // 2、nPoints已经超过100个点,说明距离比较远了,可能不准确,停掉退出
        if(vDepthIdx[j].first>mThDepth && nPoints>100)
            break;
    }
}

4.函数解释

4.1 利用参考关键帧更新上一帧在世界坐标系下的位姿

         如上图,我们获得上一普通帧mLastFrame的参考关键帧pRef,获得ref_keyframe 到 lastframe的位姿变换Tlr,用Tlw = Tlr*Trw获得lastframe的位姿。

        如果上一帧为关键帧,或者单目的情况,则退出。

4.2 对于双目或rgbd相机,为上一帧生成新的临时地图点 

        注意这些地图点只是用来跟踪,不加入到地图中,跟踪完后会删除。

        遍历上一帧LastFrame中具有有效深度值的特征点(不一定是地图点),记录特征点的深度和序号到vDepthIdx容器中。接着按照深度从小到大排序。

        遍历具有有效深度值的特征点vDepthIdx,用变量i记录是该特征点LastFrame中的哪个索引,如果这个点:

        ①对应在上一帧LastFrame中的地图点没有(!pMP)

        ②或者创建后就没有被观测到(pMP->Observations()<1)

        那么就生成一个临时的地图点

        将这个特征点反投影到世界坐标系中得到3D点x3D,并包装成地图点pNewMP,加入上一帧LastFrame的地图点mvpMapPoints中,标记为临时添加的MapPointmlpTemporalPoints.,之后在CreateNewKeyFrame之前会全部删除。将标记nPoints++。

        如果地图上有地图点我们也需要将nPoints++。

        直到满足下列条件我们停止新增LastFrame的地图点:

        ①当前的点的深度已经超过了设定的深度阈值(35倍基线)(我们之前把地图点的深度从小到大排序)

        ②nPoints已经超过100个点,说明距离比较远了,可能不准确,停掉退出

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

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

相关文章

【富文本编辑器】简记功能:neditor上传操作时提交额外数据

目录 编辑器下载&#xff08;本文使用版本v2.1.19&#xff09; 功能需求 解决思路 相关代码 调用实例的html neditor.config.js&#xff08;搜索修改内容&#xff1a;/* 设置额外请求参数 */&#xff09; 完成&#xff0c;如有其它方法&#xff0c;欢迎一起讨论 编辑器下…

使用 Fluent Bit 实现云边统一可观测性

本文基于 KubeSphere 可观测性与边缘计算负责人霍秉杰在北美 KubeCon 的 Co-located event Open Observability Day 闪电演讲的内容进行整理。 整理人&#xff1a;米开朗基杨、大飞哥 Fluent Operator 简介 2019 年 1 月 21 日&#xff0c;KubeSphere 社区为了满足以云原生的方…

NX上配置TLD的环境---对opencv的版本没有要求

一、TLD工程编译及运行 1.1 源码下载 网上的TLD有两个版本&#xff0c;一个是Zdenek Kalal自己使用matlabvs混合编程实现的&#xff0c;另外一个是 arthurv利用c和opencv实现的。 我利用的是arthurv版本的Tracking-Learning-Detection 连接&#xff1a;https://github.com/al…

基于Android平台的手机安全卫士的设计与实现

目 录 第1章 引言 1 1.1 研究背景及意义 1 1.2 安全软件的现状 1 1.3 本文主要工作 2 1.4 本文的组织结构 2 第2章 Android的相关技术介绍及分析 3 2.1 搭建Android开发环境 3 2.1.1 搭建Ubuntu系统下Java开发环境 3 2.1.2 搭建Ubuntu系统下Android开发环境 3 2.2 Android项目目…

「企企通」完成Pre-D轮融资,加速采购供应链工业软件和 SaaS 网络生态构建

企企通作为领先的采购供应链工业软件和SaaS生态平台&#xff0c;在一年内再次宣布获得Pre-D轮融资&#xff0c;全年合计融资额达数亿元人民币&#xff0c;目前还有意向投资机构在进行&#xff0c;并开始启动IPO的筹备工作。本轮投资由华映资本独家投资。华映资本是企企通C2轮融…

flutter系列之:flutter中的变形金刚Transform

文章目录简介Transform简介Transform的使用总结简介 虽然我们在开发APP的过程中是以功能为主&#xff0c;但是有时候为了美观或者其他的特殊的需求&#xff0c;需要对组件进行一些变换。在Flutter中这种变换就叫做Transform。 flutter的强大之处在于&#xff0c;可以对所有的…

IBM MQ 通道

一&#xff0c;定义 通道是分布式队列管理器在IBM MQ MQI 客户端和IBM MQ服务器之间或两个IBM MQ服务器之间使用的逻辑通信链接。 通道是提供从一个队列管理器到另一个队列管理器的通信路径的对象。通道在分布式队列中用于将消息从一个队列管理器移动到另一个队列管理器&#x…

计算机网络-应用层详解(持续更新中)

应用层概述 应用层是解决通过应用进程的交互来实现特定网络应用的问题。 应用层是计算机网络体系结构的最顶层&#xff0c;是设计和建立计算机网络的最终目的&#xff0c;也是计算机网络中发展最快的部分。 早期基于文本的应用&#xff08;电子邮件、远程登录、文件传输、新…

百度联合行业头部企业新发5个行业大模型,大模型产业落地路径愈发清晰

本文已在【飞桨PaddlePaddle】公众号平台发布&#xff0c;详情请戳链接&#xff1a;百度联合行业头部企业新发5个行业大模型&#xff0c;大模型产业落地路径愈发清晰 11月30日&#xff0c;由深度学习技术与应用国家工程研究中心主办、飞桨承办的WAVE SUMMIT2022深度学习开发者…

WLAN AP安全策略中WPA认证与WPA2认证的差异

一、安全策略WPA认证&#xff08;PSK认证TKIP加密&#xff09;的案例 组网需求&#xff1a; 设备作为FAT AP&#xff0c;为用户提供WLAN服务&#xff0c;用户可以搜索到名为huawei的无线网络&#xff0c;采用的安全策略为WPA-PSK认证TKIP加密的方式。 组网图如下&#xff1a;…

3 内存访问

内存访问 1 字的存储 寄存器中&#xff1a;16位寄存器存一个字。高8位放高位字节&#xff0c;低8位当低位字节。 内存中&#xff1a;内存单元是字节单元&#xff0c;一个字要用2个连续的内存单元保存。低位字节保存在低地址内存单元&#xff0c;高位字节保存在高地址内存单元…

vmware上的centos8没有网络

目录一、先了解虚拟机的三种网络模式二、目前的网络模式和网络状况三、 解决网络不可用问题一、先了解虚拟机的三种网络模式 虚拟机的三种网络模式 二、目前的网络模式和网络状况 我的虚拟机网络配置 我们要将虚拟机和本机在同一个局域网络里才能入网 进入cmd输入ipconfig…

Java多线程之常用的相关方法总结(线程停止、线程休眠、线程礼让、线程优先级、守护线程等等)

Java多线程之相关常用方法一、线程方法二、线程停止1、思路2、样例三、线程休眠&#xff08;sleep&#xff09;1、思路2、样例四、线程礼让&#xff08;yield&#xff09;1、思路2、样例五、线程强制执行&#xff08;join&#xff09;1、思路2、样例六、观测线程状态1、相关概念…

Mac配置python wind量化接口

首先Mac与Windows的wind配置完全不同&#xff1a; Windows&#xff1a;wind相对容易配置&#xff0c;直接用软件就可以点击并添加配置环境即可Mac配置如下 文章目录Mac上Wind的基本情况Mac配置python Wind量化接口1. 在App Store中下载并打开 “Wind App” 这个应用2. 配置pyt…

带有SPI接口的独立CAN控制器DP2515

DP2515是一款独立控制器局域网络&#xff08;Controller Area Network&#xff0c; CAN&#xff09;协议控制器&#xff0c;完全支持 CAN V2.0B 技术规范。该器件能发送和接收标准和扩展数据帧以及远程帧。 DP2515自带的两个验收屏蔽寄存器和六个验收滤波寄存器可以过滤掉不想要…

MySql使用MyCat分库分表(五)MyCat 管理及监控

视频学习地址&#xff1a;17-尚硅谷-垂直分库_哔哩哔哩_bilibili 笔记参考地址&#xff1a;MySQL 分库分表 | xustudyxus Blog (frxcat.fun) MyCat 管理 Mycat默认开通2个端口&#xff0c;可以在server.xml中进行修改。 8066 数据访问端口&#xff0c;即进行 DML 和 DDL 操…

Java搭建宝塔部署实战毕设项目SSM学生学籍管理系统源码

大家好啊&#xff0c;我是测评君&#xff0c;欢迎来到web测评。 本期给大家带来一套Java开发的毕设项目SSM学生学籍管理系统的源码&#xff0c;适合拿来做毕业设计的同学。可以下载来学习一下&#xff0c;本期把这套系统分享给大家。 技术架构 技术框架&#xff1a;ssm layui…

Kafka 数据重复怎么办?(案例)

一、前言 数据重复这个问题其实也是挺正常&#xff0c;全链路都有可能会导致数据重复。 通常&#xff0c;消息消费时候都会设置一定重试次数来避免网络波动造成的影响&#xff0c;同时带来副作用是可能出现消息重复。 整理下消息重复的几个场景&#xff1a; 生产端&#xff1…

Scanner、Random、stirng

API的使用 API : Application Programming Interface [应用程序编程接口] -> 帮助文档,词典 [对JDK的翻译文档][外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aWo9KVNQ-1670235353300)(https://cdn.staticaly.com/gh/quinhua/picsmain/markdown/…

RabbitMQ发布确认高级

在生产环境中由于一些不明原因&#xff0c;导致 RabbitMQ 重启&#xff0c;在 RabbitMQ 重启期间生产者消息投递失败&#xff0c;导致消息丢失&#xff0c;需要手动处理和恢复。 在这样比较极端的情况&#xff0c;RabbitMQ 集群不可用的时候&#xff0c;无法投递的消息该如何处…