一文详解SLAM回环及优化

点击上方“3D视觉工坊”,选择“星标”

干货第一时间送达

5fb12bd0887f0c32a34ca4eccd7326bb.png

作者丨 lovely_yoshino

来源丨古月居

bc23a0fc512339b06fa93e0c410e0384.png

3083330f7997403e927d5eeef72a8540.png

0. 前言

随着路径的不断延伸,机器人的建图过程会存在不断地累计误差。而传统的以gmapping为代表的使用粒子滤波进行定位的slam建图方式。以及ORB-SLAM为代表包含的局部优化和全局优化来调整外。但是这些处理方式只能减缓误差累计的程度,无法消除,而现在最为常用消除累计误差的方法就是利用回环检测来优化位姿。

当新的关键帧加入到优化模型时,在关键帧附近进行一次局部优化。

f9e97abe371344bdc3f666b4c9924c7b.png

在全局优化中,所有的关键帧(除了第一帧)和三维点都参与优化。

a0d02597abb02ceadb9ad30c120c4158.png

eb05bc79d8b85661d3c6df03bf8fc183.png

212848581ea5e98db2f44488e3f50ca2.png

1. 回环检测

回环检测作为近年来slam行业必备的部分,是指机器人识别曾到达某场景,使得地图闭环的能力。

8d36f27cf47da7b77097449b7b7536bf.png

回环检测之所以能成为一个难点,是因为:如果回环检测成功,可以显著地减小累积误差,帮助机器人更精准、快速的进行避障导航工作。而错误的检测结果可能使地图变得很糟糕。因此,回环检测在大面积、大场景地图构建上是非常有必要的 

词袋模型(bag of words,BoW)早期是一种文本表征方法,后引入到计算机视觉领域,逐渐成为一种很有效的图像特征建模方法。它通过提取图像特征,再将特征进行分类构建视觉字典,然后采用视觉字典中的单词集合可以表征任一幅图像。

换句话说,通过BOW可以把一张图片表示成一个向量。这对判断图像间的关联很有帮助,所以目前比较流行的回环解决方案都是采用的BoW及其基础上衍生的算法IAB-MAP、FAB-MAP是在滤波框架下计算回环概率,RTAB-MAP采用关键帧比较相似性,DLoopDetector(在DBoW2基础上开发的回环检测库)采用连续帧的相似性检测判断是否存在回环。回环检测主要由BoW模块、算法模块、验证模块三部分组成。

词袋模型(BoW模块)

每一帧都可以用单词来描述,也就是这一帧中有哪些单词,这里只关心了有没有,而不必关心具体在哪里。只有两帧中单词种类相近才可能构成回环。

(a)图像预处理,假设训练集有M幅图像,将图像标准化为patch,统一格式和规格;
(b)特征提取,假设M幅图像,对每一幅图像提取特征,共提取出N个SIFT特征;
(c)特征聚类,采用K-means算法把N个对象分为K个簇 (视觉单词表),使簇内具有较高的相似度,而簇间相似度较低;

d45f394f424c8e78e66d01bd1a06525d.png

(d)统计得到图像的码本,每幅图像以单词表为规范对该幅图像的每一个SIFT特征点计算它与单词表中每个单词的距 离,最近的加1,便得到该幅图像的码本;还需要码本矢量归一化,因为每一幅图像的SIFT特征个数不定,所以需要归一化。

6367aa76e41ad10ea2533664fb56a1df.png

相似度计算(算法模块)

现在有了字典,但还有一点需要注意。我们利用单词表示图像,目的是发现回环,也就是两帧图像具有较高的相似性。那其实不同的单词对这一目的的贡献性是不同的。例如,我这篇文章中有很多“我们”这个词,但这个词并不能告诉我们太多信息。

而有些单词例如“回环”、“K-means”就比较具有代表性,能大概告诉我们这句话讲了什么。因此不同的单词应该具有不同的权重。

(a)贝叶斯估计方法。采用BoW描述机器人每一位置的场景图像,估计已获取图像与对应位置的先验概率,对当前时刻计算该新场景图像与已访问位置匹配的后验概率,概率大于阈值则标记为闭环。

(b)相似性方法。有了字典以后,给定任意特征点f_i,只要在字典树中逐层查找,最后都能找到与之对应的单词w_i。通常字典足够大,可以说它们来自同一类物体。但是这种方法对所有单词都是同样对待,常规的做法是采用TF-IDF(term frequency-inverse document frequency)

IDF(Inverse Document Frequency):描述单词在字典中出现的频率(构建字典时),越低越具有代表性

9dc2e29a5f598229e8de09a5d8b0c1b0.png

n为所有描述子数, n_i为该单词出现次数。ln的作用大概是降低量级,毕竟n很大。

TF(Term Frequency):单词在单帧图像中出现的频率,越高越具有代表性

8eccc8cf73450956a95ebacb8ec05934.png

n为一帧图像中所有单词数, n_i为一帧图像中该单词出现次数。

因此将一帧图像转化为单词表示时,我们要计算其单词的权重:

2b469753d20a5f811d2c83bb2aac411a.png

因此一帧图像A由单词 w_i,次数n_i以及权重η_i组成。

验证模块(回环处理)

回环的判断也并没有这么简单,含有很多的筛选环节,毕竟错误的回环将带来巨大灾难,宁可不要。例如某一位姿附近连续多次(ORB-SLAM中为3次)与历史中某一位姿附近出现回环才判断为回环;回环候选帧仍然要匹配,匹配点足够才为回环。方式主要有两种:

(a)时间一致性。正确的回环往往存在时间上的连续性,所以如果之后一段时间内能用同样的方法找到回环,则认为当前回环是正确的,也叫做顺序一致性约束。
(b)结构一致性校验。对回环检测到的两帧进行特征匹配并估计相机运动,因为各个特征点在空间中的位置是唯一不变的,与之前的估计误差比较大小。

然后下面主要就会涉及如何对找到的回环进行优化了。

9706b6450f9e037ff2906b2de812ca38.png

71fd1a40130f40cd2520551a552f360a.png

2. SLAM优化

闭环纠正

在判断出现回环后,两帧计算Sim3变换(因为有尺度漂移),也就是从历史帧直接推算当前位姿。下面我们以ORB-SLAM2为代表减少形成闭环时的Sim3优化。

单目SLAM一般都会发生尺度(scale)漂移,因此Sim3上的优化是必要的。相对于SE3,Sim3的自由度要多一个,而且优化的目标是矫正尺度因子,因此优化并没有加入更多的变量。

//BRIEF 形成闭环时进行Sim3优化//Sim3用于回环检测时计算关键帧与回环帧之间的关系 R 、t、 s//相似变换群Sim3int Optimizer::OptimizeSim3(KeyFrame *pKF1, //关键帧1                            KeyFrame *pKF2, //关键帧2                            vector<MapPoint *> &vpMatches1,//两帧匹配关系                             g2o::Sim3 &g2oS12, //两个关键帧间的Sim3变换                            const float th2, //核函数阈值                            const bool bFixScale//是否进行尺度优化                            ){    //创建优化器    g2o::SparseOptimizer optimizer;    g2o::BlockSolverX::LinearSolverType * linearSolver;    linearSolver = new g2o::LinearSolverDense<g2o::BlockSolverX::PoseMatrixType>();    g2o::BlockSolverX * solver_ptr = new g2o::BlockSolverX(linearSolver);    //使用LM算法    g2o::OptimizationAlgorithmLevenberg* solver = new g2o::OptimizationAlgorithmLevenberg(solver_ptr);    optimizer.setAlgorithm(solver);    // Calibration    //得到两帧相机内参    const cv::Mat &K1 = pKF1->mK;    const cv::Mat &K2 = pKF2->mK;    // Camera poses    //得到两帧的旋转与平移位姿    const cv::Mat R1w = pKF1->GetRotation();    const cv::Mat t1w = pKF1->GetTranslation();    const cv::Mat R2w = pKF2->GetRotation();    const cv::Mat t2w = pKF2->GetTranslation();    // Set Sim3 vertex    g2o::VertexSim3Expmap * vSim3 = new g2o::VertexSim3Expmap();        vSim3->_fix_scale=bFixScale;    //两帧之间的位姿变化为待估计量    vSim3->setEstimate(g2oS12);    vSim3->setId(0);    //不进行固定参数    vSim3->setFixed(false);    //提取相机内参参数    vSim3->_principle_point1[0] = K1.at<float>(0,2);    vSim3->_principle_point1[1] = K1.at<float>(1,2);    vSim3->_focal_length1[0] = K1.at<float>(0,0);    vSim3->_focal_length1[1] = K1.at<float>(1,1);    vSim3->_principle_point2[0] = K2.at<float>(0,2);    vSim3->_principle_point2[1] = K2.at<float>(1,2);    vSim3->_focal_length2[0] = K2.at<float>(0,0);    vSim3->_focal_length2[1] = K2.at<float>(1,1);    //加入图优化顶点    optimizer.addVertex(vSim3);    // Set MapPoint vertices    //建立地图点 顶点    const int N = vpMatches1.size();    const vector<MapPoint*> vpMapPoints1 = pKF1->GetMapPointMatches();    //定义两帧的公共地图点    vector<g2o::EdgeSim3ProjectXYZ*> vpEdges12;    vector<g2o::EdgeInverseSim3ProjectXYZ*> vpEdges21;    //定义边的尺寸    vector<size_t> vnIndexEdge;    //分配空间    vnIndexEdge.reserve(2*N);    vpEdges12.reserve(2*N);    vpEdges21.reserve(2*N);    const float deltaHuber = sqrt(th2);    int nCorrespondences = 0;    //遍历所有匹配点    for(int i=0; i<N; i++)    {        if(!vpMatches1[i])            continue;        MapPoint* pMP1 = vpMapPoints1[i];        MapPoint* pMP2 = vpMatches1[i];        const int id1 = 2*i+1;        const int id2 = 2*(i+1);        const int i2 = pMP2->GetIndexInKeyFrame(pKF2);        //如果匹配的两帧看到的地图点都存在        if(pMP1 && pMP2)        {            //判断是不是好点            if(!pMP1->isBad() && !pMP2->isBad() && i2>=0)            {                //建立优化器 优化位姿1                g2o::VertexSBAPointXYZ* vPoint1 = new g2o::VertexSBAPointXYZ();                //提取世界坐标转化相机坐标                cv::Mat P3D1w = pMP1->GetWorldPos();                cv::Mat P3D1c = R1w*P3D1w + t1w;                //待优化为相机位姿                vPoint1->setEstimate(Converter::toVector3d(P3D1c));                vPoint1->setId(id1);                //固定原点坐标                vPoint1->setFixed(true);                optimizer.addVertex(vPoint1);                //优化位姿2                g2o::VertexSBAPointXYZ* vPoint2 = new g2o::VertexSBAPointXYZ();                cv::Mat P3D2w = pMP2->GetWorldPos();                cv::Mat P3D2c = R2w*P3D2w + t2w;                vPoint2->setEstimate(Converter::toVector3d(P3D2c));                vPoint2->setId(id2);                vPoint2->setFixed(true);                optimizer.addVertex(vPoint2);            }            else                continue;        }        else            continue;        //成功一个点加一个        nCorrespondences++;        // Set edge x1 = S12*X2        //建立边,就是计算重投影误差        //提取像素坐标        Eigen::Matrix<double,2,1> obs1;        const cv::KeyPoint &kpUn1 = pKF1->mvKeysUn[i];        obs1 << kpUn1.pt.x, kpUn1.pt.y;        //建立边,也就是误差        g2o::EdgeSim3ProjectXYZ* e12 = new g2o::EdgeSim3ProjectXYZ();        //连接的两个顶点        e12->setVertex(0, dynamic_cast<g2o::OptimizableGraph::Vertex*>(optimizer.vertex(id2)));        e12->setVertex(1, dynamic_cast<g2o::OptimizableGraph::Vertex*>(optimizer.vertex(0)));        //观测值        e12->setMeasurement(obs1);        //信息矩阵        const float &invSigmaSquare1 = pKF1->mvInvLevelSigma2[kpUn1.octave];        e12->setInformation(Eigen::Matrix2d::Identity()*invSigmaSquare1);        //鲁棒核        g2o::RobustKernelHuber* rk1 = new g2o::RobustKernelHuber;        e12->setRobustKernel(rk1);        rk1->setDelta(deltaHuber);        //添加边        optimizer.addEdge(e12);        // Set edge x2 = S21*X1        //反向投影在进行优化        Eigen::Matrix<double,2,1> obs2;        const cv::KeyPoint &kpUn2 = pKF2->mvKeysUn[i2];        obs2 << kpUn2.pt.x, kpUn2.pt.y;        g2o::EdgeInverseSim3ProjectXYZ* e21 = new g2o::EdgeInverseSim3ProjectXYZ();        e21->setVertex(0, dynamic_cast<g2o::OptimizableGraph::Vertex*>(optimizer.vertex(id1)));        e21->setVertex(1, dynamic_cast<g2o::OptimizableGraph::Vertex*>(optimizer.vertex(0)));        e21->setMeasurement(obs2);        float invSigmaSquare2 = pKF2->mvInvLevelSigma2[kpUn2.octave];        e21->setInformation(Eigen::Matrix2d::Identity()*invSigmaSquare2);        g2o::RobustKernelHuber* rk2 = new g2o::RobustKernelHuber;        e21->setRobustKernel(rk2);        rk2->setDelta(deltaHuber);        optimizer.addEdge(e21);        vpEdges12.push_back(e12);        vpEdges21.push_back(e21);        vnIndexEdge.push_back(i);    }    // Optimize!    //开始优化    optimizer.initializeOptimization();    optimizer.optimize(5);    // Check inliers    //清除外点和误差过大的点    int nBad=0;    for(size_t i=0; i<vpEdges12.size();i++)    {        g2o::EdgeSim3ProjectXYZ* e12 = vpEdges12[i];        g2o::EdgeInverseSim3ProjectXYZ* e21 = vpEdges21[i];        if(!e12 || !e21)            continue;        if(e12->chi2()>th2 || e21->chi2()>th2)        {            size_t idx = vnIndexEdge[i];            vpMatches1[idx]=static_cast<MapPoint*>(NULL);            optimizer.removeEdge(e12);            optimizer.removeEdge(e21);            vpEdges12[i]=static_cast<g2o::EdgeSim3ProjectXYZ*>(NULL);            vpEdges21[i]=static_cast<g2o::EdgeInverseSim3ProjectXYZ*>(NULL);            nBad++;        }    }    //确定迭代次数    int nMoreIterations;    if(nBad>0)        nMoreIterations=10;    else        nMoreIterations=5;    if(nCorrespondences-nBad<10)        return 0;    // Optimize again only with inliers    //再次优化,只优化内点    optimizer.initializeOptimization();    optimizer.optimize(nMoreIterations);    int nIn = 0;    for(size_t i=0; i<vpEdges12.size();i++)    {        g2o::EdgeSim3ProjectXYZ* e12 = vpEdges12[i];        g2o::EdgeInverseSim3ProjectXYZ* e21 = vpEdges21[i];        if(!e12 || !e21)            continue;        if(e12->chi2()>th2 || e21->chi2()>th2)        {            size_t idx = vnIndexEdge[i];            vpMatches1[idx]=static_cast<MapPoint*>(NULL);        }        else            nIn++;    }    // Recover optimized Sim3    //恢复出位姿变化关系    g2o::VertexSim3Expmap* vSim3_recov = static_cast<g2o::VertexSim3Expmap*>(optimizer.vertex(0));    g2oS12= vSim3_recov->estimate();    return nIn;}

当我们用第m帧推算了回环帧n的位姿时,使得n的位姿漂移误差较小,但其实同时可以用第n帧来计算n-1帧的位姿,使n-1帧的位姿漂移误差也减小。因此,这里还要有一个位姿传播。

另外我们可以优化所有的位姿,也就是进行一个位姿图优化(由位姿变换构建位姿约束)。

最后,我们还可以进行一起全局所有变量的BA优化。

//  初始化g2o::LinearSolverEigen< g2o::BlockSolver_6_3::PoseMatrixType >* linearSolver     = new g2o::LinearSolverEigen< g2o::BlockSolver_6_3::PoseMatrixType >();g2o::BlockSolver_6_3* blockSolver = new g2o::BlockSolver_6_3(linearSolver);g2o::OptimizationAlgorithmLevenberg* solver= new g2o::OptimizationAlgorithmLevenberg( blockSolver );    optimizer.setAlgorithm( solver );optimizer.setVerbose( false );// 初始顶点    g2o::VertexSE3* v = new g2o::VertexSE3();   v->setId( cutIndex );   v->setEstimate( Eigen::Isometry3d::Identity() );    v->setFixed( true );    optimizer.addVertex( v )// 添加新的节点(顶点)g2o::VertexSE3* vNext = new g2o::VertexSE3();vNext->setId(currFrame.frameID);vNext->setEstimate( Eigen::Isometry3d::Identity());optimizer.addVertex(vNext);// 添加边的数据g2o::EdgeSE3* edgeNew = new g2o::EdgeSE3();edgeNew->setVertex(0, optimizer.vertex(pousFrame.frameID));edgeNew->setVertex(1, optimizer.vertex(currFrame.frameID));edgeNew->setRobustKernel( new g2o::RobustKernelHuber() );//edgeNew->setInformation( Eigen::Matrix2d::Identity());  //the size is worthy to research// 信息矩阵// 两个节点的转换矩阵Eigen::Isometry3d T = cvMat2Eigen( m_result.rotaMatrix, m_result.tranMatrix );    edgeNew->setMeasurement(T);optimizer.addEdge(edgeNew);// 开始优化optimizer.initializeOptimization();optimizer.optimize(10);

09fc4e18263989aaf566ab2515989dcd.png

54bfde39c4d19a0a63a9d10f10b48d5c.png

08b715492b8a96873358f246b614aafc.png

3. 参考链接

https://baijiahao.baidu.com/s?id=1627227355343777871&wfr=spider&for=pc
https://zhuanlan.zhihu.com/p/45573552
https://blog.csdn.net/stihy/article/details/62219842

本文仅做学术分享,如有侵权,请联系删文。

3D视觉精品课程推荐:

1.面向自动驾驶领域的多传感器数据融合技术

2.面向自动驾驶领域的3D点云目标检测全栈学习路线!(单模态+多模态/数据+代码)
3.彻底搞透视觉三维重建:原理剖析、代码讲解、及优化改进
4.国内首个面向工业级实战的点云处理课程
5.激光-视觉-IMU-GPS融合SLAM算法梳理和代码讲解
6.彻底搞懂视觉-惯性SLAM:基于VINS-Fusion正式开课啦
7.彻底搞懂基于LOAM框架的3D激光SLAM: 源码剖析到算法优化
8.彻底剖析室内、室外激光SLAM关键算法原理、代码和实战(cartographer+LOAM +LIO-SAM)

9.从零搭建一套结构光3D重建系统[理论+源码+实践]

10.单目深度估计方法:算法梳理与代码实现

重磅!3DCVer-学术论文写作投稿 交流群已成立

扫码添加小助手微信,可申请加入3D视觉工坊-学术论文写作与投稿 微信交流群,旨在交流顶会、顶刊、SCI、EI等写作与投稿事宜。

同时也可申请加入我们的细分方向交流群,目前主要有3D视觉CV&深度学习SLAM三维重建点云后处理自动驾驶、多传感器融合、CV入门、三维测量、VR/AR、3D人脸识别、医疗影像、缺陷检测、行人重识别、目标跟踪、视觉产品落地、视觉竞赛、车牌识别、硬件选型、学术交流、求职交流、ORB-SLAM系列源码交流、深度估计等微信群。

一定要备注:研究方向+学校/公司+昵称,例如:”3D视觉 + 上海交大 + 静静“。请按照格式备注,可快速被通过且邀请进群。原创投稿也请联系。

9339d6e9c780053c49a43341904c6c2d.png

▲长按加微信群或投稿

82d1b8ae344858cd7f1d6bf8d7e6163e.png

▲长按关注公众号

3D视觉从入门到精通知识星球:针对3D视觉领域的视频课程( 三维重建系列、 三维点云系列、 结构光系列、 手眼标定、 相机标定、激光/视觉SLAM自动驾驶等)、知识点汇总、入门进阶学习路线、最新paper分享、疑问解答五个方面进行深耕,更有各类大厂的算法工程人员进行技术指导。与此同时,星球将联合知名企业发布3D视觉相关算法开发岗位以及项目对接信息,打造成集技术与就业为一体的铁杆粉丝聚集区,近4000星球成员为创造更好的AI世界共同进步,知识星球入口:

学习3D视觉核心技术,扫描查看介绍,3天内无条件退款

5ac99839d08aeac1a057c3d12ecc3da3.png

 圈里有高质量教程资料、答疑解惑、助你高效解决问题

觉得有用,麻烦给个赞和在看~  

3D视觉工坊
关注 关注
  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
视觉SLAM笔记(57) 回环检测
氢键H-H
11-17 1万+
回环检测的意义、实现方法、准确率和召回率、词袋模型
视觉SLAM十四讲——第十讲:后端1
weixin_37709708的博客
10-03 891
@ 《视觉SLAM十四讲》知识点与习题 《视觉SLAM十四讲》第十讲知识点整理+习题 正在学习SLAM相关知识,将一些关键点及时记录下来。 知识点整理 本讲主要是针对长时间内最优轨迹和地图的优化,减小累积误差对长时间运动带来的影响 批量的处理方式:考虑在很长一段时间内的状态估计问题,而且不仅使用过去的信息更新自己的状态,也会用未来的信息来更新自己 渐进的处理方式:当前状态只由过去的时刻决定,甚至...
激光SLAM后端优化方法
12-22
一种非常经典的SLAM后端优化方法,相比其他方法,该方法适合新手熟悉后端算法的流程。
详解 | SLAM回环检测问题
小白学视觉
02-18 1638
点击上方“小白学视觉”,选择加"星标"或“置顶”重磅干货,第一时间送达本文经知乎作者fishmarch授权转载,二次转载请联系作者原文:https://zhuanlan.zhihu.com...
5.2ORB-SLAM3之回环矫正
超爱吃小蛋糕的66的博客
07-06 597
在上一章已经介绍了检测共视区域的部分,接下来就是对共视区域进行回环矫正或者地图融合。回环矫正和之前的ORBSLAM系列一致,就是消除因为长时间运动产生的位姿累计误差和尺度漂移。在ORBSLAM3中新增了多地图系统,因此出现共视区域的地方有可能出现在不同的子地图中,需要对两个子地图进行融合。本篇主要对回环矫正部分进行介绍。
《视觉 SLAM 十四讲》V2 第 11 讲 回环检测【消除累积误差】
weixin_46034116的博客
09-28 567
P283。
SLAM回环检测
ljtx200888的博客
04-10 468
(一)两帧相似度计算 词袋模型BoW(Bag-of-Words) 一、BoW实现原理:用“图像上有哪几种特征”来描述一个图像。例如,如果某个照片,我们说里面有一个人、一辆车;而另一张则有两个人、一只狗。根据这样的描述,可以度量这两个图像的相似性。具体实现步骤: 确定“人、车、狗”等概念——对应于 BoW 中的“单词”(Word),许多单词放在一起,组成了“字典”(Dictionary)。 确定一张图像中,出现了哪些在字典中定义的概念——我们用单词出现的情况(或直方图)描述整张图像。这就把一个图像转换
​综述 | SLAM回环检测方法
计算机视觉life
08-27 2362
本文作者任旭倩,公众号:计算机视觉life成员,由于格式原因,公式显示可能出问题,建议阅读原文链接:综述 | SLAM回环检测方法在视觉SLAM问题中,位姿的估计往往是一个递推的过程,即由上一帧位姿解算当前帧位姿,因此其中的误差便这样一帧一帧的传递下去,也就是我们所说的累积误差。一个消除误差有效的办法是进行回环检测回环检测判断机器人是否回到了先前经过的位置,如果检测回环,它会把信息传递给后端进...
SLam算法详解基础理论
01-12
### SLAM算法详解基础理论 #### 一、SLAM技术概览 SLAM(Simultaneous Localization and Mapping)即同时定位与建图技术,是指在机器人自身位置不确定的情况下,在完全未知环境中创建地图,并同时更新自身位置的...
SLAM优化算法(图优化)(代码 C)
05-10
SLAM优化算法 SLAM优化算法 SLAM优化算法 SLAM优化算法 SLAM优化算法 SLAM优化算法 SLAM优化算法 SLAM优化算法 SLAM优化算法 SLAM优化算法 SLAM优化算法 SLAM优化算法SLAM优化算法 SLAM优化算法 SLAM优化算法 SLAM...
基于图优化SLAM后端优化算法研究
01-12
针对移动机器人的同时定位与地图构建(Simultaneous Localization and Mapping,SLAM)问题,传统后端优化算法比较依赖于前端传感器构造位姿图,而且对于假阳性环形闭合约束鲁棒性较低。基于此,提出了一种鲁棒后端...
SLAM回环检测技术解读
qq_38403231的博客
05-22 4582
随着路径的不断延伸,机器人在建图过程中会存在一些累计误差,除了利用局部优化、全局优化等来调整之外,还可以利用回环检测优化位姿。 回环检测是什么? 回环检测,又称闭环检测,是指机器人识别曾到达某场景,使得地图闭环的能力。说的简单点,就是机器人在左转一下,右转一下建图的时候能意识到某个地方是“我”曾经来过的,然后把此刻生成的地图与刚刚生成的地图做匹配。 回环检测成功 回环检测之所...
SLAM第三讲实践:运行显示运动轨迹plotTrajectory.cpp
zhangyuanbonj的博客
09-25 387
因为观察外边的目录结构,就发现这个txt文件是存在examples下面的,但是呢你执行的时候,是在examples/build下执行的。切换到plotTrajectory所在目录。
ORB_SLAM3 闭环检测
火柴的初心的博客
06-11 975
【代码】ORB_SLAM3 闭环检测
视觉SLAM如何基于深度学习闭环检测
小白学视觉
06-22 1695
点击上方“小白学视觉”,选择加"星标"或“置顶”重磅干货,第一时间送达 本文转自:计算机视觉life请问有做视觉SLAM基于深度学习闭环检测的吗?TurtleZhong:...
激光SLAM闭环方案总结
啥也不懂的研究生也淦SLAM的博客
01-30 1342
激光SLAM闭环方案总结
位姿图优化小记2021.10.18
qq_42731705的博客
10-18 1292
1.场景描述 现在有一个小车在运动,并搭载相机或激光雷达进行建图工作,由于SLAM的作用,在建图的同时小车也可以进行自身的定位,因此建立的地图的参考都是相对于自身坐标系的,也就是每一个时刻看到的地图点都是相对于小车当前的位姿的。注意建图的真实性反应在它要是全局一致(不知道这里用这个词对不对)的地图,或者简单来说建立的这个地图要对比GPS上的地图是一样的。但实际上由于建立的地图是相对于自身坐标系的,所以如果某个时刻的小车位姿不准确,此时虽然建立的相对于小车坐标系的位姿是准确的,但是看整个地图来说,其相比GPS
算法的学习笔记—删除链表中重复的结点(牛客JZ76)
最新发布
业精于勤,荒于嬉
08-14 1222
本文介绍了一种删除排序链表中重复节点的高效算法。通过递归的方式,算法能够有效地删除所有重复节点,并保留链表中仅出现一次的节点。此方法的实现简单且易于理解,同时在时间和空间复杂度方面表现优异,适用于处理大规模数据链表中的重复节点问题。😁热门专栏推荐想学习vue的可以看看这个java基础合集数据库合集redis合集nginx合集linux合集手写机制微服务组件spring_尘觉springMVCmybits🤔欢迎大家加入我的社区尘觉社区。
PTAM算法回环检测
07-28
回答: 是的,PTAM算法回环检测。PTAM是一种基于特征点的视觉SLAM算法,它可以通过回环检测来判断机器人是否回到了先前经过的位置,并将这一信息传递给后端进行优化处理。回环检测可以有效地消除累积误差,并形成一个拓扑一致的轨迹地图,从而提高位姿估计的准确性。在回环检测中,PTAM使用词袋模型(Bag Of Words, BOW)原理来进行特征点的匹配,以判断是否存在回环。\[1\]\[3\] #### 引用[.reference_title] - *1* *3* [​综述 | SLAM回环检测方法](https://blog.csdn.net/Yong_Qi2015/article/details/122694518)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [SLAM | 视觉SLAM中特征点法开源算法:PTAM、ORB-SLAM](https://blog.csdn.net/sinat_17456165/article/details/106760610)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
写文章

热门文章

  • YOLOV5 的小目标检测网络结构优化方法汇总(附代码) 46289
  • 一分钟详解「手眼标定」基本原理 37269
  • 手眼标定之基本原理 27051
  • 机器人操作系统ROS—深度相机+激光雷达实现vSLAM建图与导航 25098
  • undistortPoints()函数用法总结 24218

分类专栏

  • 3D视觉从入门到精通 付费 598篇
  • 3D视觉杂记 149篇
  • C++编程实战 3篇

最新评论

  • 超详细!手把手教你使用YOLOX进行物体检测(附数据集)

    我先睡了晚安x: 想请教一下,我yolox_voc_s.py中的self.num_classes和yolox_base.py中的self.num_classes都改成2了,但还是会警告WARNING | yolox.utils.checkpoint:26- Shape of head.cls_preds.0.weight in checkpoint is torch.Size([80,128, 1,1), while shape of head.cls_preds.0.weight in model is torch.Size([2,128,1,1]). 2022-03-01 16:43:04 I WARNINGI yolox.utils.checkpoint:26 - Shape of head.cls_preds.0.bias in checkpoint is torch.Size([80]), while shape of head.cls_preds.0.bias in model is torch.Size([2]).是哪里有问题呢?

  • RAL 2022|基于3D语义共视图的语义SLAM精确回环检测

    要坚持哦: 这个项目开源了嘛?如果有请私聊我一下

  • 机器人抓取领域相关数据集

    yuqingsong!: 私信给你 了

  • YOLOv7-Pose尝鲜 | 基于YOLOv7的关键点模型测评

    m0_46346901: 这个检测头尺寸是不是错了?

  • 时间同步,自动驾驶里的花好月圆

    qq_27349905: 你好有一点疑问,为什么要PPS+GPRMC进行授时?是因为GPRMC有除秒以外的时间还是其他原因?或者理解PPS信号意义是对晶振进行校准,从而保证GNSS信号丢失时可以保证秒内的精准授时?

最新文章

  • 聊一聊沉淀了6年的3D技术圈
  • 创业一年,人间三年。。。
  • ICRA'24 | UAV不再失控!FCMW 指标助力四旋翼 LOC 检测!
2024
08月 59篇
07月 97篇
06月 108篇
05月 118篇
04月 111篇
03月 118篇
02月 49篇
01月 84篇
2023年992篇
2022年764篇
2021年1113篇
2020年880篇
2019年71篇
2018年69篇
2017年3篇
2016年9篇

目录

目录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值

PHP网站源码宝安模板制作荷坳网站制作设计坪地百搜标王盐田网站优化按天收费沙井品牌网站设计坪山seo网站推广大鹏百搜词包荷坳网站优化光明设计网站坪山网页制作坂田百度网站优化永湖优秀网站设计南山优秀网站设计盐田外贸网站建设荷坳模板制作大运营销型网站建设吉祥网站搜索优化松岗外贸网站设计爱联如何制作网站沙井网站推广工具南澳关键词按天计费吉祥网站优化按天计费坪山网站推广工具双龙设计网站盐田网站制作沙井关键词排名包年推广福田网站优化软件平湖企业网站改版布吉网站搭建平湖网站推广系统歼20紧急升空逼退外机英媒称团队夜以继日筹划王妃复出草木蔓发 春山在望成都发生巨响 当地回应60岁老人炒菠菜未焯水致肾病恶化男子涉嫌走私被判11年却一天牢没坐劳斯莱斯右转逼停直行车网传落水者说“没让你救”系谣言广东通报13岁男孩性侵女童不予立案贵州小伙回应在美国卖三蹦子火了淀粉肠小王子日销售额涨超10倍有个姐真把千机伞做出来了近3万元金手镯仅含足金十克呼北高速交通事故已致14人死亡杨洋拄拐现身医院国产伟哥去年销售近13亿男子给前妻转账 现任妻子起诉要回新基金只募集到26元还是员工自购男孩疑遭霸凌 家长讨说法被踢出群充个话费竟沦为间接洗钱工具新的一天从800个哈欠开始单亲妈妈陷入热恋 14岁儿子报警#春分立蛋大挑战#中国投资客涌入日本东京买房两大学生合买彩票中奖一人不认账新加坡主帅:唯一目标击败中国队月嫂回应掌掴婴儿是在赶虫子19岁小伙救下5人后溺亡 多方发声清明节放假3天调休1天张家界的山上“长”满了韩国人?开封王婆为何火了主播靠辱骂母亲走红被批捕封号代拍被何赛飞拿着魔杖追着打阿根廷将发行1万与2万面值的纸币库克现身上海为江西彩礼“减负”的“试婚人”因自嘲式简历走红的教授更新简介殡仪馆花卉高于市场价3倍还重复用网友称在豆瓣酱里吃出老鼠头315晚会后胖东来又人满为患了网友建议重庆地铁不准乘客携带菜筐特朗普谈“凯特王妃P图照”罗斯否认插足凯特王妃婚姻青海通报栏杆断裂小学生跌落住进ICU恒大被罚41.75亿到底怎么缴湖南一县政协主席疑涉刑案被控制茶百道就改标签日期致歉王树国3次鞠躬告别西交大师生张立群任西安交通大学校长杨倩无缘巴黎奥运

PHP网站源码 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化