VINS 检测回环辅助激光建图
最近接到一个任务,在激光检测回环失败时,比如黑色物体多,场景大等,可否利用视觉进行回环检测。如果只是检测回环,现有的许多框架都可以使用。ORB-SLAM本身就有单目模式,且效果不错。但是发现ORB在检测回环时,必须要进行pose计算,产生地图点,然后根据地图点和回环之间的关系进行回环检测。这样就比较耗费资源,可否只检测回环,并不计算位姿与地图点。然后想到VINS也是有单目检测回环功能,就着手从VINS开始。
1. feature_tracker模块
这部分模块无需较大改动,只需要在节点里增加激光数据触发信号,让激光关键帧与图象帧保持数据同步
2. estimator模块
此部分会融合IMU做pose计算,所以这个节点在回环检测中不需要使用。需要在launch文件中,删去此节点,不运行。
3. pose_graph模块
3.1 此部分为回环检测核心模块
首先修改订阅的topic,只需要订阅图像与feature_tracker发布的特征点信息。
ros::Subscriber sub_image = n.subscribe(IMAGE_TOPIC, 2000, image_callback);
ros::Subscriber sub_point = n.subscribe("/feature_tracker/feature", 2000, point_callback);
3.2 修改KeyFrame构造函数
以前的需要特征点对应的3D点,此时为了减少计算量,只需要特征点图像坐标与归一化坐标,以及特征点光流平均速度
KeyFrame::KeyFrame(double _time_stamp, int _index, cv::Mat &_image,vector<cv::Point2f> &_point_2d_uv, vector<cv::Point2f> &_point_2d_normal, double _aver_velocity, int _sequence)
{
time_stamp = _time_stamp;
index = _index;
image = _image.clone();
cv::resize(image, thumbnail, cv::Size(80, 60));
std::cout<<"this is resize"<<std::endl;
point_2d_uv = _point_2d_uv;
point_2d_norm = _point_2d_normal;
has_loop = false;
loop_index = -1;
has_fast_point = false;
loop_info << 0, 0, 0, 0, 0, 0, 0, 0;
sequence = _sequence;
computeWindowBRIEFPoint();
computeBRIEFPoint();
aver_velocity = _aver_velocity;
//这里可以把图像清除了,但是为了显示图像,可以暂且留着
}
3.3 改动的还有addkeyFrame
为了减少计算量,当机器人静止时,可以不需要进行回环检测,这里判断条件就是特征点的平均光溜速度,对于这个阈值可以根据最小视差来决定。
void PoseGraph::addKeyFrame(KeyFrame* cur_kf, bool flag_detect_loop)
{
//先判断是否关键帧
std::cout<<"this is function of addKeyFrame"<<std::endl;
if(cur_kf->aver_velocity<=0.2&&keyframelist.size()>0)
{
std::cout<<"loop index unchanged"<<last_loop_index<<std::endl;
}else{
if (sequence_cnt != cur_kf->sequence)
{
sequence_cnt++;
sequence_loop.push_back(0);
}
cur_kf->index = global_index;
last_index= global_index;
int loop_index = -1;
if (flag_detect_loop)
{
TicToc tmp_t;
loop_index = detectLoop(cur_kf, cur_kf->index);
last_loop_index = loop_index;
std::cout<<"loop index is "<<loop_index<<std::endl;
KeyFrame * old_kf = getKeyFrame(loop_index);
if(loop_index !=-1)
{
if(cur_kf->findConnection(old_kf))
{
std::cout<<"this is true loop with index of : "<< loop_index<<std::endl;
}
}
}
global_index++;
keyframelist.push_back(cur_kf);
}
}
detectLoop函数没有做改动,对与findConnection函数做了如下改动。一开始以为可以不需要findConnection函数,直接用detectLoop得出的结果就能使用了,但是发现误匹配很多,VINS之前是使用
PnPRANSAC(matched_2d_old_norm, matched_3d, status, PnP_T_old, PnP_R_old);
函数进行两帧之间的真实相似度检测。但是此函数需要3D点,且计算了相对位姿,并不适合我的任务,正好VINS的老版本仅仅使用了两帧图像的2d点进行验证,虽然精度略微降低,但是无需3D点,减少了计算量。
bool KeyFrame::findConnection(KeyFrame* old_kf)
{
std::cout<<"this is function of findConnection"<<std::endl;
TicToc tmp_t;
//printf("find Connection\n");
vector<cv::Point2f> matched_2d_cur, matched_2d_old;
vector<cv::Point2f> matched_2d_cur_norm, matched_2d_old_norm;
vector<uchar> status;
matched_2d_cur = point_2d_uv;
matched_2d_cur_norm = point_2d_norm;
TicToc t_match;
std::cout<<"old_kf keypoint : "<<old_kf->keypoints.size()<<std::endl;
searchByBRIEFDes(matched_2d_old, matched_2d_old_norm, status, old_kf->brief_descriptors, old_kf->keypoints, old_kf->keypoints_norm);
reduceVector(matched_2d_cur, status);
reduceVector(matched_2d_old, status);
reduceVector(matched_2d_cur_norm, status);
reduceVector(matched_2d_old_norm, status);
//printf("search by des finish\n");
status.clear();
if ((int)matched_2d_cur.size() > MIN_LOOP_NUM)
{
status.clear();
FundmantalMatrixRANSAC(matched_2d_cur_norm,matched_2d_old_norm,status);
reduceVector(matched_2d_cur, status);
reduceVector(matched_2d_old, status);
reduceVector(matched_2d_cur_norm, status);
reduceVector(matched_2d_old_norm, status);
int gap = 10;
cv::Mat gap_image(ROW, gap, CV_8UC1, cv::Scalar(255, 255, 255));
cv::Mat gray_img, loop_match_img;
cv::Mat old_img = old_kf->image;
cv::hconcat(image, gap_image, gap_image);
cv::hconcat(gap_image, old_img, gray_img);
cvtColor(gray_img, loop_match_img, CV_GRAY2RGB);
for(int i = 0; i< (int)matched_2d_cur.size(); i++)
{
cv::Point2f cur_pt = matched_2d_cur[i];
cv::circle(loop_match_img, cur_pt, 5, cv::Scalar(0, 255, 0));
}
for(int i = 0; i< (int)matched_2d_old.size(); i++)
{
cv::Point2f old_pt = matched_2d_old[i];
old_pt.x += (COL + gap);
cv::circle(loop_match_img, old_pt, 5, cv::Scalar(0, 255, 0));
}
for (int i = 0; i< (int)matched_2d_cur.size(); i++)
{
cv::Point2f old_pt = matched_2d_old[i];
old_pt.x += (COL + gap) ;
cv::line(loop_match_img, matched_2d_cur[i], old_pt, cv::Scalar(0, 255, 0), 2, 8, 0);
}
cv::Mat notation(50, COL + gap + COL, CV_8UC3, cv::Scalar(255, 255, 255));
putText(notation, "current frame: " + to_string(index) + " sequence: " + to_string(sequence), cv::Point2f(20, 30), CV_FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(255), 3);
putText(notation, "previous frame: " + to_string(old_kf->index) + " sequence: " + to_string(old_kf->sequence), cv::Point2f(20 + COL + gap, 30), CV_FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(255), 3);
cv::vconcat(notation, loop_match_img, loop_match_img);
if ((int)matched_2d_cur.size() > MIN_LOOP_NUM)
{
cv::imshow("loop connection",loop_match_img);
cv::waitKey(100);
return true;
}
}
//printf("loop final use num %d %lf--------------- \n", (int)matched_2d_cur.size(), t_match.toc());
return false;
}
效果如图所示。
VINS 检测回环辅助激光建图的更多相关文章
- 综述 | SLAM回环检测方法
本文作者任旭倩,公众号:计算机视觉life成员,由于格式原因,公式显示可能出问题,建议阅读原文链接:综述 | SLAM回环检测方法 在视觉SLAM问题中,位姿的估计往往是一个递推的过程,即由上一帧位姿 ...
- cartographer环境建立以及建图测试(详细级)
- 第五篇 openvslam建图与优化模块梳理
建图模块 mapping_module在初始化系统的时候进行实例化,在构建实例的时候会实例化local_map_cleaner和local_bundle_adjuster.系统启动的时候会在另外一个线 ...
- java下蛇形回环矩阵的实现
前文废话:这个问题据说是腾讯之前的一道笔试题,由于当时没认真看,现在记不清这种矩阵是不是叫"蛇形回环矩阵"......请大家直接看图1,就是那个样子的矩阵. 问题描述:输入一个N, ...
- VINS 回环检测与全局优化
回环检测 VINS回环检测与全局优化都在pose_graph.cpp内处理.首先在pose_graph_node加载vocabulary文件给BriefDatabase用,如果要加载地图,会loadP ...
- segMatch:基于3D点云分割的回环检测
该论文的地址是:https://arxiv.org/pdf/1609.07720.pdf segmatch是一个提供车辆的回环检测的技术,使用提取和匹配分割的三维激光点云技术.分割的例子可以在下面的图 ...
- ORB-SLAM(六)回环检测
上一篇提到,无论在单目.双目还是RGBD中,追踪得到的位姿都是有误差的.随着路径的不断延伸,前面帧的误差会一直传递到后面去,导致最后一帧的位姿在世界坐标系里的误差有可能非常大.除了利用优化方法在局部和 ...
- Code Reading: ORB-SLAM回环检测源码阅读+注释
之前研究过一些回环检测的内容,首先要看的自然是用词袋回环的鼻祖和正当继承人(没有冒犯VINS和LDSO的意思)ORB-SLAM.下面是我的代码注释.因为代码都是自己手打的,不是在源码上注释的,所以一些 ...
- 一个基于深度学习回环检测模块的简单双目 SLAM 系统
转载请注明出处,谢谢 原创作者:Mingrui 原创链接:https://www.cnblogs.com/MingruiYu/p/12634631.html 写在前面 最近在搞本科毕设,关于基于深度学 ...
随机推荐
- 2017ICPC沈阳赛现场赛 L-Tree (dfs)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6228 题目大意:给一棵树,需要用k种颜色给树上的节点染色,问你在最优的染色方案下,相同颜色的节点连接的 ...
- 前端学习(三十四)对象&模块化(笔记)
人,工人 //类的定义 function Person(name,age){ //构造函数 //工厂模式 //1.原料 //var obj = new ...
- 《Redis深度历险:核心原理和应用实践》学习笔记一
1.redis五种数据结构 1.1 String字符串类型,对应java字符串类型 用户信息序列化后,可以用string类型存入redis中批量读写string类型,见效网络消耗数字类型的string ...
- condition简单示例
在concurrent包中提供了condition接口,通过该接口可唤醒指定的某个线程,而不是采用随机唤醒的形式. import java.util.concurrent.locks.Conditio ...
- 利用jmeter发起java请求调用shell脚本
1.创建maven项目 在pom文件中加入依赖: 2.在路径src/main/java下创建类,如类名shellclass 3. 创建jmet ...
- QT中视图(setViewport)和窗口(setWindow) 小总结
参考博客: https://blog.csdn.net/weixin_39583140/article/details/92798127 https://blog.csdn.net/u01244271 ...
- archetypeCatalog=internal
Properties中添加 archetypeCatalog=internal,不加这个参数,在maven生成骨架的时候将会非常慢.
- 趣头条基于 Flink 的实时平台建设实践
本文由趣头条实时平台负责人席建刚分享趣头条实时平台的建设,整理者叶里君.文章将从平台的架构.Flink 现状,Flink 应用以及未来计划四部分分享. 一.平台架构 1.Flink 应用时间线 首先是 ...
- IDEA使用中的快捷键
项目与项目之间的跳转: Ctrl+Alt+] 下一个窗口. Ctrl+Alt+[ 跳转回上一个窗口. 文件之间的跳转: Ctrl+E. ...
- 单词计数-MapReduceJob
pom文件 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3. ...