ORB-SLAM(五)KeyFrame类-最小生成树
KeyFrame中维护了一个map,保存了与当前帧共视的KeyFrame*与权重(共视MapPonits数量)。对关键帧之间关系是用加权有向图来完成的,那么理解其spanning tree生成树的原理就很有必要了。
KeyFrame中比较难理解的是SetBagFlag()函数,真实删除当前关键帧之前,需要处理好父亲和儿子关键帧关系,不然会造成整个关键帧维护的图断裂,或者混乱,不能够为后端提供较好的初值。
理解起来就是父亲挂了,儿子需要找新的父亲,在候选父亲里找,当前帧的父亲(mpParent)肯定在候选父亲中的;
1. 首先将当前帧的父亲,放入候选父亲中
sParentCandidates.insert(mpParent);
2. 遍历当前帧的所有儿子,然后遍历儿子A的每个共视帧,如果其中有候选父亲,则将A的父亲更新为该候选父亲,并且将A放入候选父亲中(因为这时候A已经将整个图联系起来了);如果没有,break。如果遍历一圈下来,发现有的儿子还没有找到新父亲,例如儿子B的共视帧不是候选父亲里的任何一个。这种情况出现在,B和当前帧的父亲不存在共视关系(速度太快,旋转太急,匹配跟丢)。并且B与当前帧的儿子之间也没有共视关系:当前帧不是一个好的关键帧,本来就没有多少儿子;或者B本身是个例外,恩,反正B是个孤家寡人。。。那么直接将B的父亲设置为当前帧的父亲,交给爷爷去管。
while(!mspChildrens.empty())
{
bool bContinue = false; int max = -;
KeyFrame* pC;
KeyFrame* pP; for(set<KeyFrame*>::iterator sit=mspChildrens.begin(), send=mspChildrens.end(); sit!=send; sit++)
{
KeyFrame* pKF = *sit;
if(pKF->isBad())
continue; // Check if a parent candidate is connected to the keyframe
vector<KeyFrame*> vpConnected = pKF->GetVectorCovisibleKeyFrames();
for(size_t i=, iend=vpConnected.size(); i<iend; i++)
{
for(set<KeyFrame*>::iterator spcit=sParentCandidates.begin(), spcend=sParentCandidates.end(); spcit!=spcend; spcit++)
{
if(vpConnected[i]->mnId == (*spcit)->mnId)
{
int w = pKF->GetWeight(vpConnected[i]);
if(w>max)
{
pC = pKF;
pP = vpConnected[i];
max = w;
bContinue = true;
}
}
}
}
}
} if(bContinue)
{
pC->ChangeParent(pP);
sParentCandidates.insert(pC);
mspChildrens.erase(pC);
}
else
break;
} if(!mspChildrens.empty())
for(set<KeyFrame*>::iterator sit=mspChildrens.begin(); sit!=mspChildrens.end(); sit++)
{
(*sit)->ChangeParent(mpParent);
}
3. 具体删除一个关键帧的步骤是这样的:
1) 初始mbNotErase状态是true,那么调用SetBadFlag后,将mbToBeErased状态置为true,然后return,并没有执行SetBadFlag()中后面的代码。
2) 然后调用SetErase(),这时首先要检查mspLoopEdges是否是空的!因为如果当前帧维护了一个回环,删了该关键帧回环就没了。。。通常情况下是空的,那么把mbNotErase置为false,此时再在SetErase()中调用SetBagFlag时,就会真正去执行删除该帧的代码了。
总结一下就是,首先设置为坏帧,如果该帧不是回环帧,则可以真的删掉;如果该帧是回环帧,怎么都删不掉的。。。
ORB-SLAM(五)KeyFrame类-最小生成树的更多相关文章
- ORB-SLAM(五)KeyFrame类
KeyFrame类利用Frame类来构造.对于什么样的Frame可以认为是关键帧以及何时需要加入关键帧,是实现在tracking模块中的. 由于KeyFrame中一部分数据会被多个线程访问修改,因此需 ...
- (转)Qt Model/View 学习笔记 (五)——View 类
Qt Model/View 学习笔记 (五) View 类 概念 在model/view架构中,view从model中获得数据项然后显示给用户.数据显示的方式不必与model提供的表示方式相同,可以与 ...
- Typescript 学习笔记五:类
中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...
- c++ 吕凤翥 第五章 类对象一
一 类的声明和实现 1. class tdate //声明部分 { public: void setdate(int y,int m,int d); int isleapyear(); voi ...
- Java基础复习笔记系列 五 常用类
Java基础复习笔记系列之 常用类 1.String类介绍. 首先看类所属的包:java.lang.String类. 再看它的构造方法: 2. String s1 = “hello”: String ...
- Java编程思想学习(五) 复用类
1.继承与组合 复用类的方法有两种:继承与组合.继承就不多说了,组合就是直接在类中new一个对象. 数组也是对象,使用数组也是组合的一种. 2.初始化基类 当创建一个导出类的对象时,该对象包含一个基类 ...
- C#基础(五)——类中私有构造函数作用
如果类成员有private修饰符,就不允许在类范围以外访问这个类成员.对类构造函数应用private修饰符时,则禁止外部类创建该类的实例.尽管看上去有些不好理解(既然不能实例化,那么这个类还有什么用处 ...
- Java解惑五:类之谜
本文是依据JAVA解惑这本书,做的笔记.电子书见:http://download.csdn.net/detail/u010378705/7527721 谜题46 函数重载的问题. JAVA重载解析过程 ...
- PHP学习笔记二十五【类的继承】
<?php //定义父类 class Stu{ public $name; protected $age; protected $grade; private $address;//私有变量不会 ...
随机推荐
- dom4j.jar有什么作用?
om4j是一个Java的XML API,类似于jdom,用来读写XML文件的.dom4j是一个非常非常优秀的Java XML API,具有性能优异.功能强大和极端易用使用的特点,同时它也是一个开放源代 ...
- 【转】XZip and XUnzip - Add zip and/or unzip to your app with no extra .lib or .dll
原文:http://www.codeproject.com/Articles/4135/XZip-and-XUnzip-Add-zip-and-or-unzip-to-your-app-w Downl ...
- Spring IoC 中的(Singleton)单例对象创建过程探索
前言 之前将spring framework 源码导入了idea,后来折腾调试了一下,于是研究了一下最简单的singleton对象在spring中是如何创建的.这里所谓的简单,就是指无属性注入,无复杂 ...
- alibaba--java规范
18. [推荐]final 可以声明类.成员变量.方法.以及本地变量,下列情况使用 final 关键字: 1) 不允许被继承的类,如:String 类. 2) 不允许修改引用的域对象,如:POJO 类 ...
- CPP-基础:信号量
windows api 多线程---信号量 信号量(Semaphore)和互斥量一样,属于内核对象.它自动执行可用资源查询的测试,如果有可用资源,则可用资源的计数减少1,从而避免其它线程请求资源.当该 ...
- Cesium.js学习第三天(模型展示)
var viewer = new Cesium.Viewer('cs'); viewer.scene.primitives.add(Cesium.Model.fromGltf({ url : '/Ce ...
- python 使用gRPC
Python gRPC 简介 grpc 是google 开源的一款rpc服务框架,可以轻松的实现跨语言的微服务,将项目中的各个模块独立出来,单独部署,独立升级,也可以根据模块的情况进行不同语言的变成. ...
- Knowledge Point 20180305 十进制转换成二进制浮点数
如何将十进制的浮点数 转换二进制的浮点数,分为两部分: 1. 先将整数部分转换为二进制, 2. 将小数部分转换为二进制, 然后将整数部分与小数部分相加. 以 20.5 转换为例,20转换后变为1010 ...
- 『ACM C++』 Codeforces | 1003C - Intense Heat
今日兴趣新闻: NASA 研制最强推进器,加速度可达每秒 40 公里,飞火星全靠它 链接:https://mbd.baidu.com/newspage/data/landingsuper?contex ...
- 463. Island Perimeter (5月29日)
解答 class Solution { public: int islandPerimeter(vector<vector<int>>& grid) { int num ...