1. okvis_app_synchronous.cpp

在此文件中 okvis 对象为 okvis_estimator,是类 okvis::ThreadedKFVio 的实例化对象。

数据输入接口是 ThreadedKFVio::addImuMeasurement 和 ThreadedKFVio::addImage。

整个数据输入的代码,在 for(...; i < numCameras; ...) 内,可支持多个相机的影像。

此文件是为 EuRoC 数据集写的入口,所以 IMU 只有 1 个,也没有为多个 IMU 提供便利。

输入 IMU 数据的代码如下,其中 deltaT 为 0,而 start 是第一张影像的时间。此 if 判断,将输入的 IMU 时间控制在,[start - 1, +inf],IMU 需要在影像 1s 前启动初始化。

if (t_imu - start + okvis::Duration(1.0) > deltaT) {
okvis_estimator.addImuMeasurement(t_imu, acc, gyr);
}

2. ThreadedKFVio::addImuMeasurement 和 ThreadedKFVio::addImage

IMU 数据与相机数据在这两个函数中进行封装(okvis::ImuMeasurement 和 okvis::CameraMeasurement),随后 push 到队列的尾部,等待其他线程进行处理。

这两个队列实例是 imuMeasurementReceived_ 和 cameraMeasurementReceived_。对应的类是 okvis::threadsafe::ThreadSafeQueue,嗯,这个类可以仔细看看,对小白来说很有价值。对数据的处理有两种方式,blocking 和 non blocking,控制对列繁忙的时候是不是要把数据丢弃。

3. ThreadedKFVio 中的线程

okvis 开了一些线程进行不同部分的计算,可以在 Threaded::startThreads 中看到这些进程的启动。这个函数中启动了一些现在没有用的线程,如 position, gps, manetometer, differential 数据处理的线程,这些数据当前都没有支持。

主要关注的线程函数有,frameConsumerLoop 和 imuConsumerLoop 数据预处理,matchingLoop 影像匹配,optimizationLoop 后端优化,publisherLoop publish 最终位姿计算结果。

3.1 ThreadedKFVio::imuConsumerLoop

从 imuMeasurementReceived_ 中 pop 出 imu 数据,push 到 imuMeasurements_ 这个 std::deque 中去。随后在 frameConsumerLoop 中调用函数 ThreadedKFVio::getImuMeasurements,将其取出进行处理。

最后 imuFrameSynchronizer_.gotImuData(data.timeStamp) 向其他等待的线程申明已经把该时刻之前的 imu 数据放入 imuMeasurements_ 中。

如果设置中设定了要 publish imu 积分结果,就进行一次 imu 积分,frontend_.propagation,积分的结果存放在 optimizationResults_ 中。在 ThreadedKFVio.cpp 中搜一下 optimizationResults_ 的出现场景,实际上对其中数据的输入、输出只另外出现在了 optimizationLoop 输入和 publisherLoop 输出。

3.2 ThreadedKFVio::frameConsumerLoop

这个函数有 numCameras_ 个,之间用函数参数 cameraIndex 区别。作用是提取每一张影像上的 brisk 特征点,并计算描述子。

先从 cameraMeasurementsReceived_ 中 pop 出 camera 数据 frame,使用 frameSynchronizer_.addNewFrame(frame) 中得到一个 okvis::MultiFrame,MultiFrame 是同一时刻所有相机拍摄到影像的集合(当然也不是完全绝对的同一时刻,总是有点偏差,具体细节看 Frame:Synchronizer::addNewFrame)。

现在,multiFrame 代表了这一张影像。因为特征点需要绝对的方向进行描述,所以现在需要使用 imu 数据积分算当前影像的姿态。若是第一帧,imu 没有启动,使用 okvis::Estimator::initPoseFromImu 进行启动。如果不是第一帧,则使用 okvis::ceres::ImuError::propagation 积分得到当前的姿态。而这个积分的起点是 lastOptimized_T_WS_,是 optimizationLoop 得到的上一帧影像优化结果(publish 出去的最终姿态)。

得到当前影像位姿(中间结果,未优化),进行特征点处理。

frontend.detectAndDescribe(frame->sensorId, multiFrame, T_WC, nullptr);

bool push = false;之后的部分,就是一些后续的结尾工作。

frameSynchronizer_.detectionEndedForMultiFrame(multiFrame->id());

为当前 multiFrame 的处理计数 +1,当该计数为 numCameras_ 时,说明这个 multiFrame 处理完成了,下面这个 if 语句为真。

if (frameSynchronizer_.detectionCompletedForAllCameras(multiFrame->id())) {
push = true;
}

push 为真,西面就可以把当前 multiFrame push 到 keypointMeasurements_ 中,matchingLoop 会从 keypointMeasurements_ 中取数据。

3.3 ThreadedKFVio::matchingLoop

fontend_.dataAssociationAndInitialization(estimator_, T_WS, parameters_, map_, frame, &asKeyframe);

与上一个关键帧进行匹配,当前帧不同影像之间进行 Stereo Matching。

if (estimator_.addStates(frame, imuData, asKeyframe)) {
...
}

estimator_ 是后端优化的实例,这里又将当前帧与上一帧(上一次 matchingLoop 处理的帧)之间的 imu 提取出存储在 imuData 中,加入到后端中。

3.4 ThreadedKFVio::optimizationLoop

真正的后端处理在这个函数中。分为三个部分:optimization, marginalization, afterOptimization 三个部分。

OKVIS 代码框架的更多相关文章

  1. x01.CodeBuilder: 生成代码框架

    根据 Assembly 生成代码框架. 这是学习 AvalonEdit 的一个副产品.学习时,照着源代码新建文件夹,新建文件,添加方法与属性,虽然只是个框架,也要花费大量时间.为什么不让它自动生成呢? ...

  2. twemproxy代码框架概述——剖析twemproxy代码前编

    本篇将去探索twemproxy源码的主干流程,想来对于想要开始啃这份优秀源码生肉的童鞋会有不小的帮助.这里我们首先要找到 twemproxy正确的打开方式--twemproxy的文件结构,接着介绍tw ...

  3. [C++]Linux之多进程运行代码框架

    声明:如需引用或者摘抄本博文源码或者其文章的,请在显著处注明,来源于本博文/作者,以示尊重劳动成果,助力开源精神.也欢迎大家一起探讨,交流,以共同进步- 0.0  多进程代码框架示例 /* @url: ...

  4. python爬取网页的通用代码框架

    python爬取网页的通用代码框架: def getHTMLText(url):#参数code缺省值为‘utf-8’(编码方式) try: r=requests.get(url,timeout=30) ...

  5. DSO 代码框架

    从数据流的角度讲一遍 DSO 代码框架. DSO 的入口是 FullSystem::addActiveFrame,输入的影像生成 FrameHessian 和 FrameShell 的 Object, ...

  6. 深入浅出etcd系列Part 1 – etcd架构和代码框架

    1.绪论 etcd作为华为云PaaS的核心部件,实现了PaaS大多数组件的数据持久化.集群选举.状态同步等功能.如此重要的一个部件,我们只有深入地理解其架构设计和内部工作机制,才能更好地学习华为云Ku ...

  7. 自适应大邻域搜索代码系列之(1) - 使用ALNS代码框架求解TSP问题

    前言 上次出了邻域搜索的各种概念科普,尤其是LNS和ALNS的具体过程更是描述得一清二楚.不知道你萌都懂了吗?小编相信大家早就get到啦.不过有个别不愿意透露姓名的热心网友表示上次没有代码,遂不过瘾啊 ...

  8. 使用EA生成多层次的代码框架

    最近工作期间发现了一个非常棒的UML软件[Enterprise Architect UML 建模工具]简称EA,在该软件上绘制框架层面的类之间关系后,可以自动生成相关语言的代码. EA上目前支持的语言 ...

  9. Onvif开发之代码框架生成篇

    看了前一篇的ONVIF的简单介绍应该对它的基本使用都有了一些基本的了解了吧!下面我讲一步分解向大家介绍下如何通过gsoap生成需要的代码,以及代码中需要注意的问题[基于Linux平台 C开发] 生成O ...

随机推荐

  1. BZOJ3597 SCOI2014方伯伯运椰子(分数规划+spfa)

    即在总流量不变的情况下调整每条边的流量.显然先二分答案变为求最小费用.容易想到直接流量清空跑费用流,但复杂度略有些高. 首先需要知道(不知道也行?)一种平时基本不用的求最小费用流的算法——消圈法.算法 ...

  2. LAMP和LNMP去除index.php访问

    使用TP或者Laravel开发的时候,后时候会遇到需要加index.php才能正常访问 LAMP解决方法 1.修改配置 打开配置文件(如:httpd.conf),找到你网站根目录的配置,将AllowO ...

  3. git push -f

    有的时候使用GIT工作时,会遇到一下这种问题, Pushing to git@github.com:519ebayproject/519ebayproject.git To git@github.co ...

  4. Android Studio中Git和GitHub使用详解

    一.Git和GitHub简述 1.Git 分布式版本控制系统,最先使用于Linux社区,是一个开源免费的版本控制系统,功能类似于SVN和CVS.Git与其他版本管理工具最大的区别点和优点就是分布式: ...

  5. 自学Linux Shell11.2-echo命令

    点击返回 自学Linux命令行与Shell脚本之路 11.2-echo命令 echo命令的功能是在显示器上显示一段文字,一般起到一个提示的作用. 语 法:echo [-n][字符串]或 echo [- ...

  6. 自学Python1.7-python变量以及类型

    自学Python之路 自学Python1.7-python 变量以及类型 1 变量是什么 变量是容器 2 变量的作用 存储数据到内存 3 为什么要用变量 存储数据方便后面引用 4 变量定义的规范 变量 ...

  7. JDK源码分析(1)ArrayList

    JDK版本 ArrayList简介 ArrayList 是一个数组队列,相当于 动态数组.与Java中的数组相比,它的容量能动态增长.它继承于AbstractList,实现了List, RandomA ...

  8. os模块(二十)

    os模块是与操作系统交互的一个接口 os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径 os.chdir("dirname") 改变当前脚本工作目录:相 ...

  9. typescript接口(学习笔记非干货)

    typescript的核心原则之一就是对所具有的shape类型检查结构性子类型化 One of the core principles of typescript is to check struct ...

  10. Windows7 64下搭建Caffe+python接口环境

    参考链接: http://www.cnblogs.com/yixuan-xu/p/5858595.html http://www.cnblogs.com/zf-blog/p/6139044.html ...