1.自己定义顶点类、边类或者用已经有的。
1.1定义顶点
例子
class CurveFittingVertex: public g2o::BaseVertex<3, Eigen::Vector3d>
{
public:
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
virtual void setToOriginImpl() // 重置
{
_estimate << 0,0,0;
}

virtual void oplusImpl( const double* update ) // 更新
{
_estimate += Eigen::Vector3d(update);
}
// 存盘和读盘:留空
virtual bool read( istream& in ) {}
virtual bool write( ostream& out ) const {}
};
自己能够操作的,修改类名为自己的类名。修改顶点的维度和类型,就是g2o:BaseVertex<>里的两个参数。
函数setToOriginImpl{}里设置_estimate的初值。你可以如例子中_estimate<<0,0,0,也可以_estimate=SE3Quat(),也可以留空。
oplusImpl是设定估计的更新值的函数,一般里面的变量都是更新值const double* update,至于这个update你可以设成update_什么的。然后函数里估计值会变成估计值和更新值的和或积,而更新值的类型必须修改成和顶点类型一致。也可以重写这个函数,在括号后输入override,而在{}定义一个新参数v,这个v可以和顶点类型不一致,v是由update得到或者由update和其他参数一起得到,然后是_estimate+=v,最后在设顶点估计值的时候,估计值要和v的类型一致。最重要的就是这个oplusImpl函数。
而存盘和读盘函数,可以选择留空,或者在{}里输入你想输入的数,比如return false;等
也可以设置参数。
1.2定义边
class CurveFittingEdge: public g2o::BaseUnaryEdge<1,double,CurveFittingVertex>
{
public:
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
CurveFittingEdge( double x ): BaseUnaryEdge(), _x(x) {}
// 计算曲线模型误差
void computeError()
{
const CurveFittingVertex* v = static_cast<const CurveFittingVertex*> (_vertices[0]);
const Eigen::Vector3d abc = v->estimate();
_error(0,0) = _measurement - std::exp( abc(0,0)*_x*_x + abc(1,0)*_x + abc(2,0) ) ;
}
virtual bool read( istream& in ) {}
virtual bool write( ostream& out ) const {}
public:
double _x; // x 值, y 值为 _measurement
};
可操作的:边类名,边的顶点数,边数据类型,和边顶点类型。也就是g2o::BaseUnaryEdge<>中的内容。
CurveFittingEdge( double x ): BaseUnaryEdge(), _x(x) {}这个是类赋值,可以有,也可以没有,如果有,那么要定义参数_x,因为这里是把x赋值给_x.
最重要的就是计算误差函数computeError(),具体操作在{},主要是要给出_error的具体形式。
一般赋值_vertices[i]给顶点,比如v或者v1,v2等。这里v的类型就是之前我们定义的顶点类的指针。一般是这样定义的
const 顶点类* v=static_cast<const 顶点类*>(_vertices[0])
要么把v->estimate估计值传给新的值,要么直接用来计算误差值。误差值的是由测量值_measuremen减去预测值得到的,预测值是根据v->estimate得到的,具体怎么得按实际情况来。
还有linearizeOplus函数,这个函数是求雅克比矩阵,也可以没有这个函数。雅克比矩阵也就是误差函数对顶点的求导值。不是范数啊。
过程:先把_vertices[0],_vertices[1]等赋值给顶点,跟computeError函数里一模一样,也是
const 顶点类* 顶点名=static_cast<const 顶点类*>(_vertices[0]);
是跟computeError函数里重名的。
也会用到顶点的估计值来计算出雅克比矩阵的每一项的值。一般都是
_jacobianOplusXi(i,j)=;
2.定义图模型
typedef g2o::BlockSolver< g2o::BlockSolverTraits<3,1> > Block; // 每个误差项优化变量维度为3,误差值维度为1
Block::LinearSolverType* linearSolver = new g2o::LinearSolverDense<Block::PoseMatrixType>(); // 线性方程求解器
Block* solver_ptr = new Block( linearSolver ); // 矩阵块求解器
// 梯度下降方法,从GN, LM, DogLeg 中选
g2o::OptimizationAlgorithmLevenberg* solver = new g2o::OptimizationAlgorithmLevenberg( solver_ptr );
// g2o::OptimizationAlgorithmGaussNewton* solver = new g2o::OptimizationAlgorithmGaussNewton( solver_ptr );
// g2o::OptimizationAlgorithmDogleg* solver = new g2o::OptimizationAlgorithmDogleg( solver_ptr );
g2o::SparseOptimizer optimizer; // 图模型
optimizer.setAlgorithm( solver ); // 设置求解器
optimizer.setVerbose( true ); // 打开调试输出
上面的基本就是套路了。
自己操作的是定义自己的误差项的优化变量的维度,还有误差值的维度,就是g2o::BlockSolverTraits<> 里的两个值。
线性方程求解器如果是提取特征点之类的用Dense,稠密的,如果是要进行消元什么的,用Cholmod.
优化算法一般用的都是列文伯格,也可以用高斯牛顿等。
过程就是由线性方程求解器linearSolver得到矩阵块求解器solver_ptr,由矩阵块求解器得到梯度下降方法solver,图模型再设置算法为solver.

2.1图模型添加顶点
CurveFittingVertex* v = new CurveFittingVertex();
v->setEstimate( Eigen::Vector3d(0,0,0) );
v->setId(0);
optimizer.addVertex( v );
一般的模式就是先设置顶点,如果是多于一个顶点的话,以顶点数量为最大值做一个for循环,在for循环里,设置顶点,顶点估计值,顶点id,是否可以边缘化,也就是之后要不要进行消元,图模型添加边。形式如下
顶点类* v=new 顶点类();要有一个括号,如果有输入值的话,可以放在括号里。
v->setId(i);
v->setEstimate();//估计值如果有初值,就添加上,如果没有,就设成和顶点类型相同的,并且设为0.如果顶点中update被重写,那么估计值类型和顶点类型不一致
v->setMarginlized(true);//默认false,需要设置的时候都是true
optimizer.addVertex(v)
注意顶点和边都是指针,所以用->访问。
2.2图模型添加边
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 );
}
根据边的数量做一个for循环,先设置边。然后边要设置id,顶点,测量值,信息矩阵,图模型添加边。
形式如下,设边名称为edge的话
边类* edge=new 边类();
edge->setId(j);
edge->setVertex(0,v);
edge->setMeasurement();测量值是必须得有的,视具体情况而定。
edge->setInformation();设置信息矩阵,信息矩阵是协方差矩阵的逆,所以也可以称之为设置协方差矩阵。
edge->setParameterId();//一般没有这一项
optimizer->addEdge(edge);

2.3图模型求解
optimizer.initializeOptimization();
optimizer.optimize(100);
直接就这两句就可以了。
optimize()括号内的数值可以修改。

g2o的一般过程的更多相关文章

  1. 一起做RGB-D SLAM(8) (关于调试与补充内容)

    “一起做”系列完结后,我收到不少同学给我的反馈.他们提了一些在程序编译/运行过程中的问题.我把它们汇总起来,组成了这个“补充篇”.你也可以看成是一个Q&A. Q: OpenCV的版本?A: 我 ...

  2. 改进地图的vo类

    现在的地图只是各帧特征点的集合.创建地图:局部,全局.局部:只相机位置附近的特征点,用来和当前帧匹配求解相机位置的.全局:不定位,回环检测和地图表达.重点或麻烦:维护局部地图的规模.为了实时,保证地图 ...

  3. vo优化总结

    问题1:位姿估计用的ransac,只用了几个点,如果3d_2d点存在噪声,不行.优化:把这值当做初值,用非线性优化问题2:深度图有误差,深度过近或过远不行,有误差.而特征点往往在物体边缘处,深度测量值 ...

  4. c++ primer plus 第6版 部分二 5- 8章

    ---恢复内容开始--- c++ primer plus 第6版 部分二    5-  章 第五章 计算机除了存储外 还可以对数据进行分析.合并.重组.抽取.修改.推断.合成.以及其他操作 1.for ...

  5. 从零开始一起学习SLAM | 掌握g2o顶点编程套路

    点"计算机视觉life"关注,置顶更快接收消息! ## 小白:师兄,上一次将的g2o框架<从零开始一起学习SLAM | 理解图优化,一步步带你看懂g2o代码>真的很清晰 ...

  6. Ubuntu配置ORB-SLAM2过程中的问题

    https://www.imooc.com/article/details/id/29136 1. 提示“CMAKE_CXX_COMPILER-NOTFOUND ” 具体形式: Check for w ...

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

    首发于公众号:计算机视觉life 旗下知识星球「从零开始学习SLAM」 这可能是最清晰讲解g2o代码框架的文章 理解图优化,一步步带你看懂g2o框架 小白:师兄师兄,最近我在看SLAM的优化算法,有种 ...

  8. g2o的使用

    相关文献 1.论文 Grisetti, Giorgio, et al. “A tutorial on graph-based SLAM.” IEEE Intelligent Transportatio ...

  9. 视觉SLAM漫淡(二):图优化理论与g2o的使用

    视觉SLAM漫谈(二):图优化理论与g2o的使用 1    前言以及回顾 各位朋友,自从上一篇<视觉SLAM漫谈>写成以来已经有一段时间了.我收到几位热心读者的邮件.有的希望我介绍一下当前 ...

随机推荐

  1. 性能测试报告模板 V1.0

    1. 测试项目概述与测试目的 1.1 项目概述 本部分主要是针对即将进行压力测试的对象(接口.模块.进程或系统)进行概要的说明,让人明白该测试对象的主要功能与作用及相关背景. 1.2 测试目标 简要列 ...

  2. iOS开发个人独立博客收集

    如今国内技术博客站点有非常多,如CSDN,CNBlog,ITEye等.论坛的话主要是要cocachina. 这里是我收集的iOS开发个人独立博客,文章用搜索引擎比較难搜到,都是牛人: OneV's D ...

  3. Java排序算法(三):直接插入排序

    [基本思想] 关键:在前面已经排好序的序列中找到合适的插入位置 步骤: 1. 从第一个元素開始,该元素能够觉得已经排好序. 2. 取出下一个元素.在已经排好序的元素序列中从后往前扫描进行比較. 3. ...

  4. http协议(转http://www.cnblogs.com/guguli/p/4758937.html)

    一. HTTP协议的应用简单概况 HTTP协议的主要特点可概括如下: 1.支持客户/服务器模式.2.简单快速:客户向服务器请求服务时,只需传送请求方法和路径.请求方法常用的有GET.HEAD.POST ...

  5. 使用jquey的css()方法改变样式,

    $("#tip").css("display","none"); $("#tip").css("display ...

  6. hdu2141Can you find it?

     给你四个集合.要你从这四个集合中 各取出一个数出来,推断,取出的前三个数的和 是否等于第四个数. 数据比較大.我的做法是将 前两个集合全部数全部和的情况取出来, 然后二分查找第四个集合和第三集合 ...

  7. H5和CSS3新增内容总结

    CSS3选择器有哪些?答:属性选择器.伪类选择器.伪元素选择器.CSS3新特性有哪些?答:1.颜色:新增RGBA,HSLA模式 文字阴影(text-shadow.) 边框: 圆角(border-rad ...

  8. Anaconda2

    Anaconda 是一个打包的python,一次把好多需要的包都安装好了.对于Python2.7把PyQt5都弄好了,不需要自己来编译! 看看这个 http://conda.pydata.org/do ...

  9. go with go

    1, vim 安装vim-go 打造GOLANG 专用IDE golang和vim-go安装配置 2, 阅读图书 <Go语言实战> William Kennedy等, 李兆海 译 3,在线 ...

  10. ios和mac开发 学习资料

    1.WWDC14 Session 409 学习笔记: http://url.cn/Ju2Yt5 2..WWDC14 Session 4092学习笔记: http://url.cn/Rx0mAN 3.i ...