g2o(一):整体介绍

旧时模样 提交于 2020-03-05 13:34:52

0 参考链接

[从零开始一起学习SLAM | 理解图优化,一步步带你看懂g2o代码]

[深入理解图优化与g2o:g2o篇]

本文参考上面两个链接,想要了解详细内容,参考上面两个

1 基本流程梳理

g2o框架

在这里插入图片描述

图的核心

SparseOptimizer是整个图的核心, is-a 是实心箭头,表示这个SparseOptimizer它是一个Optimizable Graph,从而也是一个超图(HyperGraph)

定点和边

has-many 表示这个超图(HyperGraph)包含了许多顶点(HyperGraph::Vertex)和边(HyperGraph::Edge)。而这些顶点继承自 Base Vertex,也就是OptimizableGraph::Vertex,而边可以继承自 BaseUnaryEdge(单边), BaseBinaryEdge(双边)或BaseMultiEdge(多边),它们都叫做OptimizableGraph::Edge

is-a:相当于一个等号

has-a:表示包含一个,这个包含的的属于必备的组件

has-many:和has-a差不多,至少要有一个

配置SparseOptimizer的优化算法和求解器

核心SparseOptimizer 包含一个优化算法(OptimizationAlgorithm)的对象。OptimizationAlgorithm是通过OptimizationWithHessian 来实现的。其中迭代策略可以从Gauss-Newton(高斯牛顿法,简称GN), Levernberg-Marquardt(简称LM法), Powell’s dogleg 三者中间选择一个(我们常用的是GN和LM)

求解流程

OptimizationWithHessian 内部包含一个求解器(Solver),这个Solver实际是由一个BlockSolver组成的。这个BlockSolver有两个部分,一个是SparseBlockMatrix ,用于计算稀疏的雅可比和Hessian矩阵;一个是线性方程的求解器(LinearSolver),它用于计算迭代过程中最关键的一步HΔx=−b,LinearSolver有几种方法可以选择:PCG, CSparse, Choldmod

2 代码文件

$ tree -L 3 -d
.
├── bin
├── build
│   ├── CMakeFiles
│   │   ├── 3.9.1
│   │   └── CMakeTmp
│   ├── EXTERNAL
│   │   ├── CMakeFiles
│   │   ├── csparse
│   │   └── freeglut
│   └── g2o
│       ├── apps
│       ├── CMakeFiles
│       ├── core
│       ├── examples
│       ├── solvers
│       ├── stuff
│       └── types
├── cmake_modules
├── doc
│   ├── doxygen
│   └── pics
├── EXTERNAL
│   ├── ceres
│   ├── csparse
│   └── freeglut
├── g2o
│   ├── apps
│   │   ├── g2o_cli
│   │   ├── g2o_hierarchical
│   │   ├── g2o_simulator
│   │   ├── g2o_viewer
│   │   └── linked_binaries
│   ├── core
│   ├── examples
│   │   ├── ba
│   │   ├── ba_anchored_inverse_depth
│   │   ├── bal
│   │   ├── calibration_odom_laser
│   │   ├── data_convert
│   │   ├── data_fitting
│   │   ├── g2o_unfold
│   │   ├── icp
│   │   ├── interactive_slam
│   │   ├── line_slam
│   │   ├── plane_slam
│   │   ├── sba
│   │   ├── simple_optimize
│   │   ├── slam2d
│   │   ├── sphere
│   │   ├── target
│   │   └── tutorial_slam2d
│   ├── solvers
│   │   ├── cholmod
│   │   ├── csparse
│   │   ├── dense
│   │   ├── eigen
│   │   ├── pcg
│   │   ├── slam2d_linear
│   │   └── structure_only
│   ├── stuff
│   └── types
│       ├── data
│       ├── deprecated
│       ├── icp
│       ├── sba
│       ├── sclam2d
│       ├── sim3
│       ├── slam2d
│       ├── slam2d_addons
│       ├── slam3d
│       └── slam3d_addons
├── lib
└── script

g2o项目中含有若干文件夹。刨开那些gitignore之类的零碎文件,主要有以下几个:

  • EXTERNAL  三方库,有ceres, csparse, freeglut,可以选择性地编译;
  • cmake_modules  给cmake用来寻找库的文件。我们用g2o时也会用它里头的东西,例如FindG2O.cmake
  • doc     文档。包括g2o自带的说明书(难度挺大的一个说明文档)。
  • g2o      最重要的源代码都在这里!
  • script    在android等其他系统编译用的脚本

3 代码使用举例

typedef g2o::BlockSolver< g2o::BlockSolverTraits<3,1> > Block;  // 每个误差项优化变量维度为3,误差值维度为1

// 第1步:创建一个线性求解器LinearSolver
Block::LinearSolverType* linearSolver = new g2o::LinearSolverDense<Block::PoseMatrixType>(); 

// 第2步:创建BlockSolver。并用上面定义的线性求解器初始化
Block* solver_ptr = new Block( linearSolver );      

// 第3步:创建总求解器solver。并从GN, LM, DogLeg 中选一个,再用上述块求解器BlockSolver初始化
g2o::OptimizationAlgorithmLevenberg* solver = new g2o::OptimizationAlgorithmLevenberg( solver_ptr );

// 第4步:创建终极大boss 稀疏优化器(SparseOptimizer)
g2o::SparseOptimizer optimizer;     // 图模型
optimizer.setAlgorithm( solver );   // 设置求解器
optimizer.setVerbose( true );       // 打开调试输出

// 第5步:定义图的顶点和边。并添加到SparseOptimizer中
CurveFittingVertex* v = new CurveFittingVertex(); //往图中增加顶点
v->setEstimate( Eigen::Vector3d(0,0,0) );
v->setId(0);
optimizer.addVertex( v );
for ( int i=0; i<N; i++ )    // 往图中增加边
{
  CurveFittingEdge* edge = new CurveFittingEdge( x_data[i] );
  edge->setId(i);
  edge->setVertex( 0, v );                // 设置连接的顶点
  edge->setMeasurement( y_data[i] );      // 观测数值
  edge->setInformation( Eigen::Matrix<double,1,1>::Identity()*1/(w_sigma*w_sigma) ); // 信息矩阵:协方差矩阵之逆
  optimizer.addEdge( edge );
}

// 第6步:设置优化参数,开始执行优化
optimizer.initializeOptimization();
optimizer.optimize(100);
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!