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. ceph 安装过程

    安装依赖: yum install -y yum-utils && yum-config-manager --add-repo https://dl.fedoraproject.org ...

  2. 数字对——RMQ+二分答案

    题目描述 小H是个善于思考的学生,现在她又在思考一个有关序列的问题. 她的面前浮现出一个长度为n的序列{ai},她想找出一段区间[L, R](1 <= L <= R <= n). 这 ...

  3. python成长之路七-函数的进阶

    1,python中,名称空间分三种: 全局命名空间 局部命名空间(临时命名空间) 内置名称空间 2,作用域(两种): 1,全局作用域  包含:全局名称空间   内置名称空间 2,局部作用域  包含:局 ...

  4. Redundant Paths POJ - 3177(边—双连通分量)

    题意: 在图中加边 看最少能通过加多少条边把 图变成边—双连通分量 解析: 先做一次dfs,不同的连通分量的low是不同的  注意重边 缩点 统计度为1的点  那么需要加的边为(ret+1)/2 #i ...

  5. 【POI每日题解 #9】SKA-Piggy Banks

    题目链接 题意: 有一棵环套树 求最少从多少个节点出发能沿边走过整棵树 环套树 并查集求联通块 有几块就砸几个 太简单不发代码了 不过某大佬的环套树找环dfs让我研究了好久… 贴一下以Orz #inc ...

  6. 集成Android免费语音合成功能(在线、离线、离在线融合)

    集成Android免费语音合成功能(在线.离线.离在线融合),有这一篇文章就够了(离线)集成Android免费语音合成功能(在线.离线.离在线融合),有这一篇文章就够了(离在线融合) 转眼间,大半年没 ...

  7. 洛谷 P1452 Beauty Contest 解题报告

    P1452 Beauty Contest 题意 求平面\(n(\le 50000)\)个点的最远点对 收获了一堆计算几何的卡点.. 凸包如果不保留共线的点,在加入上凸壳时搞一个相对栈顶,以免把\(n\ ...

  8. ubuntu 14.04下使用fcitx时将caps lock映射为ctrl

    在~/.xprofile中加入 setxkbmap -option caps:ctrl_modifier 要弄成全局的就在 /etc/X11/Xsession.d/ 里面找个文件塞进去. archli ...

  9. 树莓派上使用Pi-FM-RDS工具打造FM调频电台

    安装Pi-FM-RDS 安装依赖.sudo apt-get install libsndfile1-dev 克隆Pi-FM-RDS到本地.git clone https://github.com/Ch ...

  10. 省选前的th题

    沙茶博主终于整完了知识点并学完了早该在NOIP之前学的知识们 于是终于开始见题了,之前那个奇怪的题单的结果就是这个了 题目按沙茶博主的做题顺序排序 个人感觉(暂时)意义不大的已被自动忽略 洛谷 491 ...