g2o的类结构,以及最关键的类结构图(十四讲笔记)

首先,感谢高翔博士的十四讲。

—————————————————————————————————————————————————————————————————————————————

g2o的结构

  g2o全称是什么?来跟我大声说一遍:General Graph Optimization!你可以叫它g土o,g二o,g方o,总之我也不知道该怎么叫它……

  所谓的通用图优化。

  为何叫通用呢?g2o的核里带有各种各样的求解器,而它的顶点、边的类型则多种多样。通过自定义顶点和边,事实上,只要一个优化问题能够表达成图,那么就可以用g2o去求解它。常见的,比如bundle adjustment,ICP,数据拟合,都可以用g2o来做。甚至我还在想神经网络能不能写成图优化的形式呢……

  从代码层面来说,g2o是一个c++编写的项目,用cmake构建。它的github地址在:https://github.com/RainerKuemmerle/g2o 

  它是一个重度模板类的c++项目,其中矩阵数据结构多来自Eigen。首先我们来扫一眼它的目录下面都有什么吧:

g2o的类结构,以及最关键的类结构图(十四讲笔记)

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

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

   综上所述,最重要的就是g2o的源代码文件啦!所以我们要进一步展开看一看!

g2o的类结构,以及最关键的类结构图(十四讲笔记)

   我们同样地介绍一下各文件夹的内容:

  • apps    一些应用程序。好用的g2o_viewer就在这里。其他还有一些不常用的命令行工具等。
  • core    核心组件,很重要!基本的顶点、边、图结构的定义,算法的定义,求解器接口的定义在这里。
  • examples  一些例程,可以参照着这里的东西来写。不过注释不太多。
  • solvers    求解器的实现。主要来自choldmod, csparse。在使用g2o时要先选择其中一种。
  • stuff    对用户来讲可有可无的一些工具函数。
  • types    各种顶点和边,很重要!我们用户在构建图优化问题时,先要想好自己的顶点和边是否已经提供了定义。如果没有,要自己实现。如果有,就用g2o提供的即可。

  就经验而言,solvers给人的感觉是大同小异,而 types 的选取,则是 g2o 用户主要关心的内容。然后 core 下面的内容,我们要争取弄的比较熟悉,才能确保使用中出现错误可以正确地应对。

  那么,g2o最基本的类结构是怎么样的呢?我们如何来表达一个Graph,选择求解器呢?我们祭出一张图:

g2o的类结构,以及最关键的类结构图(十四讲笔记)

  这个图第一次看,可能觉得有些混乱。但是随着g2o越用越多,你会发现越来越喜欢这个图……现在请读者跟着我的顺序来看这个图。

  先看上半部分。SparseOptimizer 是我们最终要维护的东东。它是一个Optimizable Graph,从而也是一个Hyper Graph。一个 SparseOptimizer 含有很多个顶点 (都继承自 Base Vertex)和很多个边(继承自 BaseUnaryEdge, BaseBinaryEdge或BaseMultiEdge)。这些 Base Vertex 和 Base Edge 都是抽象的基类,而实际用的顶点和边,都是它们的派生类。我们用 SparseOptimizer.addVertex 和 SparseOptimizer.addEdge 向一个图中添加顶点和边,最后调用 SparseOptimizer.optimize 完成优化。

  在优化之前,需要指定我们用的求解器和迭代算法。从图中下半部分可以看到,一个 SparseOptimizer 拥有一个 Optimization Algorithm,继承自Gauss-Newton, Levernberg-Marquardt, Powell's dogleg 三者之一(我们常用的是GN或LM)。同时,这个 Optimization Algorithm 拥有一个Solver,它含有两个部分。一个是 SparseBlockMatrix ,用于计算稀疏的雅可比和海塞; 一个是用于计算迭代过程中最关键的一步

HΔx=bHΔx=−b
这就需要一个线性方程的求解器。而这个求解器,可以从 PCG, CSparse, Choldmod 三者选一。

  综上所述,在g2o中选择优化方法一共需要三个步骤:

  1. 选择一个线性方程求解器,从 PCG, CSparse, Choldmod中选,实际则来自 g2o/solvers 文件夹中定义的东东。
  2. 选择一个 BlockSolver 。
  3. 选择一个迭代策略,从GN, LM, Doglog中选。

  这样一来,读者是否对g2o就更清楚的认识了呢?

  小萝卜:师兄你慢点,我已经晕了……