ORB-SLAM中优化使用g2o库,先复习一下g2o的用法,上类图

其中SparseOptimizer就是我们需要维护的优化求解器,他是一个优化图,也是一个超图(包含若干顶点和一元二元多元边),怎样定义图的顶点(优化变量_estimate)和边(误差项_error)是用户需要考虑的问题,可以从g2o/types查找是否已经有定义好的顶点或边,若没有,需要自己去实现。

自己实现的时候注意,基本都是去继承BaseVertex<D,T>; BaseUnaryEdge<D,E,VertexXi>...这几个模板类,根据需要实现(override)虚函数.

  • virtual void setToOriginImpl() 设定优化变量0点 _estimate = 0 ;
  • virtual void oplusImpl(const double* v)实现优化变量的增量计算,特别是优化变量不在欧式空间中,没有的"+"定义时。例如李代数中,需要使用左乘或者右乘定义而不是直接的加法;
  • void computeError() 计算估计值和测量值之间的误差项_error
  • virtual void linearizeOplus() 计算雅可比的解析形式_jacobianOplus[i],每一个雅可比的类型为MatrixX::MapType, 参考Eigen::Map类 https://eigen.tuxfamily.org/dox/classEigen_1_1Map.html,可以认为是将一块内存数据构造成一个矩阵,比较灵活地适应相对各个优化变量的雅可比形式。

这张类图的下半部分就是我们初始化优化求解器时需要指定的求解方法。

求解的梯度下降算法可以选择GN,LM(最常用),或者DogLeg;

算法求解器还包括两部分,

  • 计算目标函数雅可比和海塞(或者近似的海塞),以及执行Schur complement的BlockSolver,需要指定优化变量的维度,常见的有

    •   //variable size solver
      using BlockSolverX = BlockSolverPL<Eigen::Dynamic, Eigen::Dynamic>; // solver for BA/3D SLAM
      using BlockSolver_6_3 = BlockSolverPL<, >; // solver fo BA with scale
      using BlockSolver_7_3 = BlockSolverPL<, >; // 2Dof landmarks 3Dof poses
      using BlockSolver_3_2 = BlockSolverPL<, >;

      可以设置为动态的BlockSolverX

  • 求解线性方程组 Hx = b (linear problem constructed from _jacobianOplus and _error)的线性求解器,完全采用第三方的线性代数库,主要采用Cholesky分解和PCG迭代,具体可以选择的有
    • Cholmod,CSparse (以上两者为比较著名的线性代数库),
    • PCG (pre-conditioner is block Jacobi),
    • Dense(dense Cholesky decomposition),
    • 或者ORB-SLAM中使用的Eigen(sparse Cholesky decoposition from Eigen)。

因此,ORB-SLAM中优化求解器初始化过程如下:

g2o::SparseOptimizer optimizer;
g2o::BlockSolver_6_3::LinearSolverType * linearSolver;
// 线性方程求解器
linearSolver = new g2o::LinearSolverEigen<g2o::BlockSolver_6_3::PoseMatrixType>();
// 稀疏矩阵块求解器
g2o::BlockSolver_6_3 * solver_ptr = new g2o::BlockSolver_6_3(linearSolver);
// 梯度下降算法
g2o::OptimizationAlgorithmLevenberg* solver = new g2o::OptimizationAlgorithmLevenberg(solver_ptr);
optimizer.setAlgorithm(solver);

ORB中使用的这些优化函数是非常重要的,在视觉SLAM中有很强的通用性,自己实现的时候完全可以参考其实现方法。分为:

1. BundleAdjustment()

  • GlobalBundleAdjustment():用于单目初始化的CreateInitialMapMonocular函数以及闭环优化的RunGlobalBundleAdjustment函数(在闭环结束前新开一个线程,全局优化,在此之前会OptimizeEssentialGraph,论文中说其实这里全局优化提升的精度有限)。
  • LocalBundleAdjustment():用于LocalMapping线程中剔除关键帧之前的局部地图优化。

2. PoseOptimization()

  • 只优化当前帧pose,地图点固定。
  • 用于LocalTracking中运动模型跟踪,参考帧跟踪,地图跟踪TrackLocalMap,重定位。

3. OptimizeEssentialGraph()

  • EssentialGraph包括所有的关键帧顶点,但是优化边大大减少,包括spanning tree(生成树),共视权重θ>100的边,以及闭环连接边。
  • 用于闭环检测Sim3调整后优化。

4. OptimizeSim3()

  • 在用RANSAC求解过Sim3,以及通过Sim3匹配更多的地图点后,对当前关键帧,闭环关键帧,以及匹配的地图点进行优化,获得更准确的Sim3位姿,再去下一步的闭环调整。

使用到的g2o顶点包括:

1. VertexSE3Expmap():SE(3)位姿

2. VertexSim3Expmap():Sim(3)位姿

3. VertexSBAPointXYZ():地图点坐标

使用到的g2o边包括:

1. EdgeSE3ProjectXYZ():BA中的重投影误差(3D-2D(u,v)误差),将地图点投影到相机坐标系下的相机平面。

2. EdgeSE3ProjectXYZOnlyPose():PoseEstimation中的重投影误差,将地图点投影到相机坐标系下的相机平面。优化变量只有pose,地图点位置固定,是一边元,双目中使用的是EdgeStereoSE3ProjectXYZOnlyPoze()。

3. EdgeSim3():Sim3之间的相对误差。优化变量只有Sim3表示的pose,用于OptimizeEssentialGraph。

4. EdgeSim3ProjectXYZ():重投影误差。优化变量Sim3位姿与地图点,用于闭环检测中的OptimizeSim3。

ORB-SLAM(十二)优化的更多相关文章

  1. SLAM中的优化理论(二)- 非线性最小二乘

    本篇博客为系列博客第二篇,主要介绍非线性最小二乘相关内容,线性最小二乘介绍请参见SLAM中的优化理论(一)-- 线性最小二乘.本篇博客期望通过下降法和信任区域法引出高斯牛顿和LM两种常用的非线性优化方 ...

  2. [十二省联考2019]字符串问题——后缀自动机+parent树优化建图+拓扑序DP+倍增

    题目链接: [十二省联考2019]字符串问题 首先考虑最暴力的做法就是对于每个$B$串存一下它是哪些$A$串的前缀,然后按每组支配关系连边,做一遍拓扑序DP即可. 但即使忽略判断前缀的时间,光是连边的 ...

  3. Mysql优化(出自官方文档) - 第十二篇(优化锁操作篇)

    Mysql优化(出自官方文档) - 第十二篇(优化锁操作篇) 目录 Mysql优化(出自官方文档) - 第十二篇(优化锁操作篇) 1 Internal Locking Methods Row-Leve ...

  4. 高博-《视觉SLAM十四讲》

    0 讲座 (1)SLAM定义 对比雷达传感器和视觉传感器的优缺点(主要介绍视觉SLAM) 单目:不知道尺度信息 双目:知道尺度信息,但测量范围根据预定的基线相关 RGBD:知道深度信息,但是深度信息对 ...

  5. 《SLAM十四讲》个人学习知识点梳理

    0.引言 从六月末到八月初大概一个月时间一直在啃SLAM十四讲[1]这本书,这本书把SLAM中涉及的基本知识点都涵盖了,所以在这里做一个复习,对这本书自己学到的东西做一个梳理. 书本地址:http:/ ...

  6. 视觉slam十四讲第七章课后习题6

    版权声明:本文为博主原创文章,转载请注明出处: http://www.cnblogs.com/newneul/p/8545450.html 6.在PnP优化中,将第一个相机的观测也考虑进来,程序应如何 ...

  7. 视觉slam十四讲第七章课后习题7

    版权声明:本文为博主原创文章,转载请注明出处:http://www.cnblogs.com/newneul/p/8544369.html  7.题目要求:在ICP程序中,将空间点也作为优化变量考虑进来 ...

  8. 《视觉SLAM十四讲》第2讲

    目录 一 视觉SLAM中的传感器 二 经典视觉SLAM框架 三 SLAM问题的数学表述 注:原创不易,转载请务必注明原作者和出处,感谢支持! 本讲主要内容: (1) 视觉SLAM中的传感器 (2) 经 ...

  9. 我的MYSQL学习心得(十二) 触发器

    我的MYSQL学习心得(十二) 触发器 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数 ...

  10. 【腾讯Bugly干货分享】腾讯验证码的十二年

    本文来自于腾讯bugly开发者社区,未经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/581301b146dfb1456904df8d Dev Club 是一个交流移动 ...

随机推荐

  1. github基本概念

    github: 托管项目代码. 仓库(repository):用来存放项目的代码,每个项目对应一个仓库,多个项目则有多个仓库. 收藏(star):收藏项目的人数.收藏别人的项目方便下次查看. 复制克隆 ...

  2. 【C++】随机重命名MP3文件

    新置MP3一件,竟然没有随机播放的功能.坑啊!身为程序媛一枚,自己动手吧~ 获取当前路径: char buf[1000]; GetCurrentDirectory(1000,buf); string ...

  3. ssm小小整合

    ssm整合: 首先是创建数据库: CREATE TABLE `user` ( `id` ) NOT NULL, `username` varchar() NOT NULL, `password` va ...

  4. 浅谈DB2的四个隔离级别

    隔离级别定义用于控制并发事务的行为,它决定在访问数据时数据是如何锁定的.如何与其他进程隔离的. 包括四个级别,级别从高到低: RR(可重复读取) RS(读取稳定性) CS(游标稳定性) UR(未提交的 ...

  5. 上传组件uploadify在spring中返回406 / Not Acceptable 问题解决

    这个问题在chrome中正常.在火狐和ie中就会报这个错误. 原因就是chrome的accept是*/* 火狐和ie的accept是text/* 但是spring的accept清单中是没有text/* ...

  6. 关于ucos操作系统中如何从邮箱中提取出消息

    问题提出? 定义两个任务,task1,task2,想task1用OSMboxPost,task2用OSMboxPend定义了一个邮箱Mbox1=OSMboxCreate(括号里面应该怎么写?)还有具体 ...

  7. 【Javascript-ECMA6-Fetch详解】

    Fetch 由于Fetch API是基于Promise设计,因此旧的浏览器并不支持该API,需要引用时引用es6-promise. 基本知识 fetch请求返回response格式 body Fetc ...

  8. 史上最简单的SpringCloud教程 | 第十二篇: 断路器监控(Hystrix Dashboard)(Finchley版本)

    转载请标明出处: 原文首发于:https://www.fangzhipeng.com/springcloud/2018/08/30/sc-f12-dash/ 本文出自方志朋的博客 在我的第四篇文章断路 ...

  9. Vue--- 一点车项目 6个小时实际看了10天(完结)

    一个项目 环境安装   使用了 cli 脚手架  Koa2  workpackage  其他小的不计 前端Vue组件搭建 数据的简单测试交互 数据库的设计 创建.连接接数据库 前台[表单/分类]   ...

  10. 基于MySql和Sails.js的RESTful风格的api实现

    Sails.js是类似于express的node后台框架,她面向数据库的特性使得面向数据库的服务器的搭建变得特别简单快捷. 现在网上关于Sails的教程大多是基于V0.12版本的,但是现在Sails的 ...