图优化与g2o通用图优化库入门讲解

图优化与g2o通用图优化库入门

图优化是指把一个常规的优化问题,以图(Graph)的形式来表述,图是由顶点(Vertex)和边(Edge)组成的结构,边也可以连接一个顶点(Unary Edge,一元边)、两个顶点(Binary Edge,二元边)或多个顶点(Hyper Edge,多元边)。当一个图中存在连接两个以上顶点的边时,称这个图为超图(Hyper Graph)。而SLAM问题就可以表示成一个超图,

图优化求解,其实是求解线性方程𝐻Δ𝑥=−𝑏,主要是求解一阶导雅可比矩阵J和二阶导海塞矩阵H,其流程如下:

    1.选择你想要的图里的节点与边的类型,确定它们的参数化形式;

    2.往图里加入实际的节点和边;

    3.选择初值,开始迭代;

    4.每一步迭代中,计算对应于当前估计值的雅可比矩阵和海塞矩阵;

    5.求解稀疏线性方程𝐻Δ𝑥=−𝑏,得到梯度方向;

    6.继续用GN或LM进行迭代。如果迭代结束,返回优化值。

 

实际上,g2o能帮你做好第3-6步,你要做的只是前两步而已。下节我们就来尝试这件事

 

g2O 叫通用图优化库,它带有各种各样的求解器,顶点和边的类型也多种多样,只要一个优化问题可以用图表示都可以用g2o 去求解它,常见的比如bundle adjustment(捆集调整),ICP,数据拟合等

 

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 ,用于计算稀疏的雅可比和海塞; 一个是用于计算迭代过程中最关键的一步

𝐻Δ𝑥=−𝑏

这就需要一个线性方程的求解器。而这个求解器,可以从 PCG, CSparse, Choldmod 三者选一。

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

选择一个线性方程求解器,从 PCG, CSparse, Choldmod中选,实际则来自 g2o/solvers 文件夹中定义的东东。

选择一个 BlockSolver 。

选择一个迭代策略,从GN, LM, Doglog中选

使用例子如下bundle adjustment:

// 构造g2o中的图     

// 先构造求解器    

g2o::SparseOptimizer    optimizer; 

 // 使用Cholmod中的线性方程求解器    

g2o::BlockSolver_6_3::LinearSolverType* linearSolver = new   g2o::LinearSolverCholmod<g2o::BlockSolver_6_3::PoseMatrixType> (); 

// 6*3 的参数 

 g2o::BlockSolver_6_3* block_solver = new g2o::BlockSolver_6_3( linearSolver ); 

// L-M 下降  

g2o::OptimizationAlgorithmLevenberg* algorithm = new  g2o::OptimizationAlgorithmLevenberg( block_solver );    optimizer.setAlgorithm( algorithm ); 

optimizer.setVerbose( false );

// 添加节点,两个位姿节点(代码只抽取一小部分,做说明)

g2o::VertexSE3Expmap* v = new g2o::VertexSE3Expmap();

optimizer.addVertex( v );

// 添加特征点的节点

g2o::VertexSBAPointXYZ* v = new g2o::VertexSBAPointXYZ();

optimizer.addVertex( v );

//添加多条边

vector<g2o::EdgeProjectXYZ2UV*> edges;

g2o::EdgeProjectXYZ2UV*  edge = new g2o::EdgeProjectXYZ2UV();

edge->setVertex( 0, dynamic_cast<g2o::VertexSBAPointXYZ*>   (optimizer.vertex(i+2)) );

edge->setVertex( 1, dynamic_cast<g2o::VertexSE3Expmap*>     (optimizer.vertex(0)) );

edge->setMeasurement( Eigen::Vector2d(pts1[i].x, pts1[i].y ) );

edge->setInformation( Eigen::Matrix2d::Identity() );

edge->setParameterId(0, 0);

edge->setRobustKernel( new g2o::RobustKernelHuber() );

optimizer.addEdge( edge );

edges.push_back(edge);


cout<<"开始优化"<<endl;

optimizer.setVerbose(true);

optimizer.initializeOptimization();

optimizer.optimize(10);

cout<<"优化完毕"<<endl;

 

 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值