【视觉SLAM】 G2O库编写步骤介绍

介绍G2O,并阐述基本使用方法。

G2O以稀疏优化器(SparseOptimizer)为核心,分为图的构建与求解器构建两部分,分别对应该图的上下两部分。

G2O编程步骤共分七步,如图所示:

构建求解器

1、创建一个线性求解器(LinearSolver)。

在此设定H Δx = -b的求解方法,一般采用LinearSolverDense:使用 dense cholesky 分解法。

2、创建块求解器(BlockSolver),并用上面定义的线性求解器初始化。

using BlockSolverPL=BlockSolver< BlockSolverTraits<p,l>>;

在此设定误差项优化变量维度与误差值纬度。可选可变尺寸的求解器。

3、创建总求解器(Solver),,并从 GN、LM、DogLeg 中选择一个,再用上述块求解器初始化。

4、创建稀疏优化器(Sparse0ptimizer),并用已定义求解器作为来解方法。

构建图结构

5、定义顶点以及顶点添加至优化器(Sparse0ptimizer)

Vertex : public Basevertex< D,T>

顶点模板中的参数 D 和 T。

D是int 类型的,表示Vertex的最小维度,比如在 3D 空间中旋转是三维的那么这里 D =3。

T是待估计 Vertex的数据类型,比如用四元数表达三维旋转,那么 T就是Quaternion 类型的。

存在一些常用顶点:

2D位姿顶点(x,y, theta)

VertexSE2 : public Basevertex<3,SE2>

六维向量(x,y,z,qx,qy,qz),省略了四元数中的qw

VertexSE3 : public BaseVertex<6,Isometry3>

二维点和三维点

VertexPointXY : public BaseVertex<2,Vector2>

VertexPointXYZ: public BaseVertex<3,Vector3>

VertexSBAPointXYZ: public BaseVertex<3,Vector3>

SE(3)顶点,内部用变换矩阵参数化,外部用指数映射参数化

VertexsE3Expmap : public BaseVertex<6,SE3Quat>

sBACam 顶点

VertexCam :public BaseVertex<6,SBACam>

sim(3)顶点

Vertexsim3Expmap : public BaseVertex<7,Sim3>


当所需定顶点不在其中时,需要重新定义顶点。重新定义顶点需要重写一下函数:

1、读/写函数,一般情况下不需要进行读/写操作的话,仅仅声明一下就可以。

virtual bool read(std::istreams is);

virtual bool write(std::ostreams os) const;

2、顶点更新函数。这是一个非常重要的雨数,主要用于优化过程中增量Δx的计算。计算出增量后,就是通过这个函数对估计值进行调整的。

virtual void oplusImpl(const number t* update);

3、设定被优化顶点的初始值。

virtual void setToOriginImpl();


构建完成顶点后,需要向优化器(Sparse0ptimizer)中添加顶点。如下所示:

在曲线拟合中向图中添加顶点示例

新建顶点

CurveFittingVertex* v=new CurveFittingVertex();

设定估计值

v->setEstimate(Eigen::Vector3d(0,0,0));

//设置顶点编号ID

v->setId(0);

将顶点添加到优化器中

optimizer.addVertex(v);

6、定义边以及边添加至优化器(Sparse0ptimizer)

BaseBinaryEdge<D,E, VertexXi, VertexXi >

D是int 类型的,表示测量值的维度(Dimension)。

E 表示测量值的数据类型。

VertexXi、VertexXi分别表示不同顶点的类型。

定义边时我们通常也需要复写一些要的成员函数。

读/写函数,一般情况下不需要进行读/写操作,仅声明一下就可以。

virtual bool read(std::istream& is);

virtual bool write(std::ostream& os) const;

使用当前顶点的值计算的测量值与真实的测量值之间的误差

virtual void computeError();

误差对优化变量的偏导数,也就是我们说的 Jacobianvirtual

void linearizeOplus();


定义完成边后,需要向优化器(Sparse0ptimizer)中添加边。如下所示:

CurveFittingEdge* edge=new CurveFittingEdge(x data[i]);

//设置边的ID

edge->setId(i);

//设置连接的顶点v,其编号为0

edge->setVertex(0,v);

//设置观测的数值

edge->setMeasurement(ydata[i]);

// 信息矩阵

edge->setInformation( Eigen::Matrix<double,1,1>::Identity()*1/ (wsigma*w sigma));

//将边添加到优化器

optimizer.addEdge( edge);

7、设置优化参数

//开始执行优化。

optimizer.initializeOptimization();

//设置迭代次数

optimizer.optimize(100);

相关推荐
_feivirus_17 分钟前
神经网络_使用TensorFlow预测气温
人工智能·神经网络·算法·tensorflow·预测气温
大柏怎么被偷了27 分钟前
【C++算法】位运算
开发语言·c++·算法
程序猿方梓燚28 分钟前
C/C++实现植物大战僵尸(PVZ)(打地鼠版)
c语言·开发语言·c++·算法·游戏
CPP_ZhouXuyang29 分钟前
C语言——模拟实现strcpy
c语言·开发语言·数据结构·算法·程序员创富
闻缺陷则喜何志丹29 分钟前
【C++前后缀分解 动态规划】2100. 适合野炊的日子|1702
c++·算法·动态规划·力扣·前后缀分解·日子·适合
逝去的秋风43 分钟前
【代码随想录训练营第42期 Day57打卡 - 图论Part7 - Prim算法与Kruskal算法
算法·图论·prim算法
QXH2000001 小时前
数据结构—双向链表
c语言·数据结构·算法·链表
旺小仔.1 小时前
【数据结构篇】~排序(1)之插入排序
c语言·数据结构·算法·链表·性能优化·排序算法
绎岚科技2 小时前
深度学习自编码器 - 随机编码器和解码器篇
人工智能·深度学习·算法·机器学习
jingling5552 小时前
后端开发刷题 | 数字字符串转化成IP地址
java·开发语言·javascript·算法