OKVIS框架之前端
1. 数据流入
在okvis_app_sychronous.cpp内,把IMU和图像数据加入到各自的队列里。由ThreadedKFVio负责队列的各种操作。作者对队列加了特殊功能,保证队列是线程安全的。比如:在push时,当超过最大设定值,可以选择是阻塞还是丢掉最老的数据。在pop时也有互斥锁。
/// \brief Push to the queue if the size is less than max_queue_size, else block.
/// \param[in] value New entry in queue.
/// \param[in] max_queue_size Maximum queue size.
/// \return False if shutdown is requested.
bool PushBlockingIfFull(const QueueType& value, size_t max_queue_size) {
while (!shutdown_) {
pthread_mutex_lock(&mutex_);
size_t size = queue_.size();
if (size >= max_queue_size) {
pthread_cond_wait(&condition_full_, &mutex_);
}
if (size >= max_queue_size) {
pthread_mutex_unlock(&mutex_);
continue;
}
queue_.push(value);
pthread_cond_signal(&condition_empty_); // Signal that data is available.
pthread_mutex_unlock(&mutex_);
return true;
}
return false;
}
/// \brief Push to the queue. If full, drop the oldest entry.
/// \param[in] value New entry in queue.
/// \param[in] max_queue_size Maximum queue size.
/// \return True if oldest was dropped because queue was full.
bool PushNonBlockingDroppingIfFull(const QueueType& value,
size_t max_queue_size) {
pthread_mutex_lock(&mutex_);
bool result = false;
if (queue_.size() >= max_queue_size) {
queue_.pop();
result = true;
}
queue_.push(value);
pthread_cond_signal(&condition_empty_); // Signal that data is available.
pthread_mutex_unlock(&mutex_);
return result;
}
/**
* @brief Get the oldest entry still in the queue. Blocking if queue is empty.
* @param[out] value Oldest entry in queue.
* @return False if shutdown is requested.
*/
bool Pop(QueueType* value) {
return PopBlocking(value);
}
2. IMU数据处理线程---imuConsumerLoop()
此线程主要是进行IMU积分,获得最新的没有优化过的位姿,以及速度,偏置等信息。每当位姿优化过后,会使repropagationNeeded置为真,则在优化后的参数上进行积分处理。
if (parameters_.publishing.publishImuPropagatedState) {
if (!repropagationNeeded_ && imuMeasurements_.size() > 0) {
start = imuMeasurements_.back().timeStamp;
} else if (repropagationNeeded_) {
std::lock_guard<std::mutex> lastStateLock(lastState_mutex_);
start = lastOptimizedStateTimestamp_;
T_WS_propagated_ = lastOptimized_T_WS_;
speedAndBiases_propagated_ = lastOptimizedSpeedAndBiases_;
repropagationNeeded_ = false;
} else
start = okvis::Time(0, 0);
end = &data.timeStamp;
}
imuMeasurements_.push_back(data);
} // unlock _imuMeasurements_mutex
std::cout<<"IMU loop"<<data.timeStamp<<std::endl;
// notify other threads that imu data with timeStamp is here.
imuFrameSynchronizer_.gotImuData(data.timeStamp);
if (parameters_.publishing.publishImuPropagatedState) {
Eigen::Matrix<double, 15, 15> covariance;
Eigen::Matrix<double, 15, 15> jacobian;
frontend_.propagation(imuMeasurements_, imu_params_, T_WS_propagated_,
speedAndBiases_propagated_, start, *end, &covariance,
&jacobian);
OptimizationResults result;
result.stamp = *end;
result.T_WS = T_WS_propagated_;
result.speedAndBiases = speedAndBiases_propagated_;
result.omega_S = imuMeasurements_.back().measurement.gyroscopes
- speedAndBiases_propagated_.segment<3>(3);
for (size_t i = 0; i < parameters_.nCameraSystem.numCameras(); ++i) {
result.vector_of_T_SCi.push_back(
okvis::kinematics::Transformation(
*parameters_.nCameraSystem.T_SC(i)));
}
result.onlyPublishLandmarks = false;
optimizationResults_.PushNonBlockingDroppingIfFull(result,1);
}
3. 图像数据处理线程---frameConsumerLoop(size_t cameraIndex)
3.1 生成multiFrame类
每一个相机都会有一个线程处理图像,所以这里需要把两个相机的图像融合到一个数据结构里,也就是multiFrame。
multiFrame = frameSynchronizer_.addNewFrame(frame);
此函数内部,不做检测,仅仅是融合左右两个图像到一个multiFrame里。
3.2 IMU预积分
如果是第一帧图像对,则不进行预积分。这里预积分是为了获得TWS,然后的出相机位姿,因为对特征点进行描述时,需要方向信息。但是目前左右帧都会进行预积分,然后在后端优化时候,estimator类里也会进行预积分。不明白对于同一对图像为什么不能只进行一次预积分。
3.3 特征点检测以及描述子计算
frontend_.detectAndDescribe(frame->sensorId, multiFrame, T_WC, nullptr);
这里没有用什么特殊的方法,都是opencv内的特征提取方法。
for (size_t i = 0; i < numCameras_; ++i) {
featureDetectors_.push_back(
std::shared_ptr<cv::FeatureDetector>(
#ifdef __ARM_NEON__
new cv::GridAdaptedFeatureDetector(
new cv::FastFeatureDetector(briskDetectionThreshold_),
briskDetectionMaximumKeypoints_, 7, 4 ))); // from config file, except the 7x4...
#else
new brisk::ScaleSpaceFeatureDetector<brisk::HarrisScoreCalculator>(
briskDetectionThreshold_, briskDetectionOctaves_,
briskDetectionAbsoluteThreshold_,
briskDetectionMaximumKeypoints_)));
#endif
descriptorExtractors_.push_back(
std::shared_ptr<cv::DescriptorExtractor>(
new brisk::BriskDescriptorExtractor(
briskDescriptionRotationInvariance_,
briskDescriptionScaleInvariance_)));
}
4. 匹配线程---matchingLoop()
在判断左右两幅图像都检测完后,则把数据传给匹配线程。匹配过程略复杂,而且代码使用了很多模板,比较难看懂。在进行图像匹配前,作者先把状态参数,传递给后端,添加各种误差项。这里不太明白为什么要在匹配前进行。
if (estimator_.addStates(frame, imuData, asKeyframe))
{
lastAddedStateTimestamp_ = frame->timestamp();
addStateTimer.stop();
} else {
LOG(ERROR) << "Failed to add state! will drop multiframe.";
addStateTimer.stop();
continue;
}
// -- matching keypoints, initialising landmarks etc.
okvis::kinematics::Transformation T_WS;
estimator_.get_T_WS(frame->id(), T_WS);
matchingTimer.start();
frontend_.dataAssociationAndInitialization(estimator_, T_WS, parameters_, map_, frame, &asKeyframe);
matchingTimer.stop();
然后先让current frame 和以前所有的关键帧进行匹配。然后再和lastFrame进行匹配,最后进行左右立体匹配。每种匹配后都会在setBestMatch函数内增加每个点的投影误差。matchingLoop有点像前端和后端的桥梁,在这里准备后端优化所需要的数据。
OKVIS框架之前端的更多相关文章
- 刚写完的商城erp + 这个商城前台,新鲜出炉。自己1个人写, 包括php框架和前端html页面.
刚写完的商城erp + 这个商城前台,新鲜出炉.自己1个人写, 包括php框架和前端html页面. 刚写完的商城erp + 这个商城前台,新鲜出炉.自己1个人写, 包括php框架和前端html页面.
- MUI框架-11-MUI前端 +php后台接入百度文字识别API
MUI框架-11-MUI前端 +php后台接入百度文字识别API 这里后台不止一种,Python,Java,PHP,Node,C++,C# 都可以 这里使用的是 php 来介绍,已经解决所有问题,因为 ...
- 循序渐进VUE+Element 前端应用开发(12)--- 整合ABP框架的前端登录处理
VUE+Element 前端是一个纯粹的前端处理,前面介绍了很多都是Vue+Element开发的基础,从本章随笔开始,就需要进入深水区了,需要结合ABP框架使用(如果不知道,请自行补习一下我的随笔:A ...
- abp.zero 9.0框架的前端Angular使用说明
abp.zero 9.0框架的前端Angular使用说明 目录 abp.zero 9.0框架的前端Angular使用说明 摘要 1 部署及启动 1.1 依赖包安装 1.2 使用yarn安装依赖包 1. ...
- 在基于ABP框架的前端项目Vue&Element项目中采用电子签名的处理
在前面随笔介绍了<在基于ABP框架的前端项目Vue&Element项目中采用电子签章处理文件和打印处理>的处理,有的时候,我们在流程中或者一些文件签署的时候,需要签上自己的大名,一 ...
- 二十三、【开源】EFW框架Web前端开发之常用组件(FusionCharts图表、ReportAll报表等)
回<[开源]EFW框架系列文章索引> EFW框架源代码下载V1.2:http://pan.baidu.com/s/1hcnuA EFW框架实例源代码下载:http://pan ...
- 二十一、【.Net开源框架】EFW框架Web前端开发之目录结构和使用FireBug调试方法
回<[开源]EFW框架系列文章索引> EFW框架源代码下载V1.2:http://pan.baidu.com/s/1hcnuA EFW框架实例源代码下载:http://pan.baidu. ...
- 找到MVC框架中前端URL与后端同步的解决方案
基本思路: 先用URL标签生成完整的URL字符,前端动态参数的部分以适配符先填充,最后动态参数利用正则匹配进行替换. 这种方式,可以在各种MVC框架中适用,妙. 不废话,上码. var url = & ...
- 2017年 JavaScript 框架回顾 -- 前端框架
概述: 对于 JavaScript 社区来说,npm 的主要功能之一就是帮助开发者发掘所需的 npm Registry 中的库和框架.npm 强大的搜索功能能够帮助找到一组相关的软件包,同时其内置的的 ...
随机推荐
- opencv视频流的读取和处理
Opencv提供一个简单易用的框架以提取视频文件和USB摄像头中的图像帧,如果只是想读取某个视频,你只需要创建一个VideoCapture实例,然后在循环中提取每一帧.下面是一个简单的代码 #incl ...
- python 从csv文件插入mysql数据库
一个工作遇到的问题,将excel文件的内容插入到mysql数据库中. 总体思路是 excel文件-->转换成csv文件-->csv文件读取-->读取数据插入mysql数据库 用到py ...
- 【记录】eclipse jar包看不了源码
第一步:下载JAD . jad官方地址的官方下载地址是: http://www.softpedia.com/get/Programming/Debuggers-Decompilers-Dissasem ...
- 2018-8-10-win10-uwp-线程池
title author date CreateTime categories win10 uwp 线程池 lindexi 2018-08-10 19:16:50 +0800 2018-05-15 1 ...
- Sass-减法
Sass 的减法运算和加法运算类似,我们通过一个简单的示例来做阐述: 同样的,运算时碰到不同类型的单位时,编译也会报错,如:
- springcloud整合分布式事务LCN
一.创建eureka注册中心 a.pom文件 <properties> <java.version>1.8</java.version> <spring-cl ...
- 洛咕P4180 严格次小生成树
鸽了很久的一道题(?)貌似是去年NOIP前听的emm... 首先我们分析一下最小生成树的性质 我们kruskal建树的时候呢是从小到大贪心加的边,这个的证明用到拟阵.(我太菜了不会) 首先我们不存在连 ...
- ThreadPoolExecutor扩展
import java.util.concurrent.*; /** * ThreadPoolExecutor扩展 */ public class ExtThreadPool { public sta ...
- Python 分段利润提成
题目:企业发放的奖金根据利润提成.利润(I)低于或等于10万元时,奖金可提10%:利润高于10万元,低于20万元时,低于10万元的部分按10%提成,高于10万元的部分,可提成7.5%:20万到40万之 ...
- yield关键字详解与三种用法
本篇文章比较硬核, 适合有一定Python基础的读者阅读, 如果您对Python还不甚了解可以先关注我哦, 我会持续更新Python技术文章 yield详解 yield与return相同每次调用都会返 ...