[g2o]一个备忘
g2o使用的一个备忘
位姿已知,闭环的帧已知,进行图优化。
#include "stdafx.h"
#include <vector>
#include "PointXYZ.h"
#include "Annicp.h"
#include <Eigen/Dense>
#include "OptimizeHelper.h" #include "g2o/types/icp/types_icp.h"
#include "g2o/core/sparse_optimizer.h"
#include "g2o/core/block_solver.h"
#include "g2o/core/solver.h"
#include "g2o/core/robust_kernel.h"
#include <g2o/core/robust_kernel_factory.h>
#include <g2o/types/slam3d/types_slam3d.h>
#include <g2o/core/factory.h>
#include <g2o/core/optimization_algorithm_factory.h>
#include <g2o/core/optimization_algorithm_gauss_newton.h>
#include "g2o/core/optimization_algorithm_levenberg.h"
#include "g2o/solvers/dense/linear_solver_dense.h"
#include <g2o/solvers/csparse/linear_solver_csparse.h> using namespace Eigen;
using namespace Eigen::internal;
using namespace Eigen::Architecture;
using namespace std;
using namespace g2o;
typedef g2o::BlockSolver_6_3 SlamBlockSolver;
typedef g2o::LinearSolverCSparse< SlamBlockSolver::PoseMatrixType > SlamLinearSolver; int _tmain(int argc, _TCHAR* argv[])
{
#pragma region ICPParams
int startIndex=;//起始帧
int endIndex=;//终止帧
double scope=;//扫描上限距离cm
double rejectDistance=;//m
string path="Fubdata";
int maxiter=;
#pragma endregion ICPParams //人工增加闭环
vector<LoopClose> *loopCloses=new vector<LoopClose>(); LoopClose loop(,);
loopCloses->push_back(loop);
LoopClose loop2(,);
loopCloses->push_back(loop2); OptimizeHelper optimize0;
// 初始化求解器
SlamLinearSolver* linearSolver = new SlamLinearSolver();
linearSolver->setBlockOrdering( false );
SlamBlockSolver* blockSolver = new SlamBlockSolver( linearSolver );
g2o::OptimizationAlgorithmLevenberg* solver = new g2o::OptimizationAlgorithmLevenberg( blockSolver ); g2o::SparseOptimizer globalOptimizer; // 最后用的就是这个东东
globalOptimizer.setAlgorithm( solver );
globalOptimizer.setVerbose( false );// 不要输出调试信息 //读取已经计算出来的位姿数据
string posefilename=path+"\\finalpose.txt";
const char * posefile=posefilename.c_str();
FILE* inpose=fopen(posefile,"r");
if(inpose==NULL)
{
printf("missing file");
return ;
}
int inum=-;
vector<PoseX> poselist;
int stIdx=-,enIdx=-;
float M00,M01,M02,M03;
float M10,M11,M12,M13;
float M20,M21,M22,M23;
float M30,M31,M32,M33;
fscanf(inpose,"%d %d %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f",&stIdx,&enIdx,
&M00,&M01,&M02,&M03,
&M10,&M11,&M12,&M13,
&M20,&M21,&M22,&M23,
&M30,&M31,&M32,&M33);
while(feof(inpose)==) /*判断是否文件尾,不是则循环*/
{
inum++;
PoseX pose(M00,M01,M02,M03,
M10,M11,M12,M13,
M20,M21,M22,M23,
M30,M31,M32,M33);
printf("%d %d %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f\n",stIdx,enIdx,
M00,M01,M02,M03,
M10,M11,M12,M13,
M20,M21,M22,M23,
M30,M31,M32,M33);
poselist.push_back(pose);
fscanf(inpose,"%d %d %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f",&stIdx,&enIdx,
&M00,&M01,&M02,&M03,
&M10,&M11,&M12,&M13,
&M20,&M21,&M22,&M23,
&M30,&M31,&M32,&M33);
}
fclose(inpose);
startIndex=;
endIndex=poselist.size();
int currIndex=startIndex;//当前索引
// 向globalOptimizer增加第一个顶点
g2o::VertexSE3* v = new g2o::VertexSE3();
v->setId( currIndex ); Eigen::Isometry3d prev = Eigen::Isometry3d::Identity();
prev(,) = poselist[currIndex].M00;
prev(,) = poselist[currIndex].M01;
prev(,) = poselist[currIndex].M02;
prev(,) = poselist[currIndex].M03;
prev(,) = poselist[currIndex].M10;
prev(,) = poselist[currIndex].M11;
prev(,) = poselist[currIndex].M12;
prev(,) = poselist[currIndex].M13;
prev(,) = poselist[currIndex].M20;
prev(,) = poselist[currIndex].M21;
prev(,) = poselist[currIndex].M22;
prev(,) = poselist[currIndex].M23;
prev(,) = poselist[currIndex].M30;
prev(,) = poselist[currIndex].M31;
prev(,) = poselist[currIndex].M32;
prev(,) = poselist[currIndex].M33;
v->setEstimate( prev); //估计为单位矩阵
v->setFixed( true ); //第一个顶点固定,不用优化
globalOptimizer.addVertex( v ); for ( currIndex=startIndex+; currIndex< endIndex; currIndex++ )
{
g2o::VertexSE3 *v = new g2o::VertexSE3();
v->setId( currIndex ); Eigen::Isometry3d p = Eigen::Isometry3d::Identity();
p(,) = poselist[currIndex].M00;
p(,) = poselist[currIndex].M01;
p(,) = poselist[currIndex].M02;
p(,) = poselist[currIndex].M03;
p(,) = poselist[currIndex].M10;
p(,) = poselist[currIndex].M11;
p(,) = poselist[currIndex].M12;
p(,) = poselist[currIndex].M13;
p(,) = poselist[currIndex].M20;
p(,) = poselist[currIndex].M21;
p(,) = poselist[currIndex].M22;
p(,) = poselist[currIndex].M23;
p(,) = poselist[currIndex].M30;
p(,) = poselist[currIndex].M31;
p(,) = poselist[currIndex].M32;
p(,) = poselist[currIndex].M33; v->setEstimate(p);
globalOptimizer.addVertex(v); g2o::RobustKernel* robustKernel = g2o::RobustKernelFactory::instance()->construct( "Cauchy" );
// 连接此边的两个顶点id
g2o::EdgeSE3* edge = new g2o::EdgeSE3();
edge->vertices() [] = globalOptimizer.vertex( currIndex-);
edge->vertices() [] = globalOptimizer.vertex( currIndex );
edge->setRobustKernel( robustKernel );
// 信息矩阵
Eigen::Matrix<double, , > information = Eigen::Matrix< double, , >::Identity();
// 信息矩阵是协方差矩阵的逆,表示我们对边的精度的预先估计
// 因为pose为6D的,信息矩阵是6*6的阵,假设位置和角度的估计精度均为0.1且互相独立
// 那么协方差则为对角为0.01的矩阵,信息阵则为100的矩阵
information(,) = information(,) = information(,) = ;
information(,) = information(,) = information(,) = ;
// 也可以将角度设大一些,表示对角度的估计更加准确
edge->setInformation( information );
// 边的估计
Eigen::Isometry3d T = Eigen::Isometry3d::Identity();
T= prev.inverse() * p;
edge->setMeasurement(T);
// 将此边加入图中
globalOptimizer.addEdge(edge);//注意g2o目前用的代码都是Debug版本的
prev=p;
} for (vector<LoopClose>::iterator iter = loopCloses->begin();iter< loopCloses->end();iter++)
{
LoopClose tmp=(LoopClose)*iter;
//读取闭环的帧进行ICP匹配
char a[],b[];
sprintf(a, "%03d", tmp.StartIndex);
sprintf(b, "%03d", tmp.CloseIndex);
string filename=path + "\\scan" + a + ".txt";
string filename1=path + "\\scan" + b + ".txt";
Scan * model=new Scan();
model->ReadScanData(filename);
Scan * data=new Scan();
data->ReadScanData(filename1);
double* transformation=new double[];
transformation= optimize0.DoICP(model,data); printf("-----------闭环信息---------- \n");
printf("%f %f %f %f \n",transformation[],transformation[],transformation[],transformation[]);
printf("%f %f %f %f \n",transformation[],transformation[],transformation[],transformation[]);
printf("%f %f %f %f \n",transformation[],transformation[],transformation[],transformation[]);
printf("%f %f %f %f \n",transformation[],transformation[],transformation[],transformation[]); g2o::RobustKernel* robustKernel = g2o::RobustKernelFactory::instance()->construct( "Cauchy" );
// 连接此边的两个顶点id
g2o::EdgeSE3* edge = new g2o::EdgeSE3();
edge->vertices() [] = globalOptimizer.vertex(tmp.StartIndex);
edge->vertices() [] = globalOptimizer.vertex(tmp.CloseIndex );
edge->setRobustKernel( robustKernel );
// 信息矩阵
Eigen::Matrix<double, , > information = Eigen::Matrix< double, , >::Identity();
// 信息矩阵是协方差矩阵的逆,表示我们对边的精度的预先估计
// 因为pose为6D的,信息矩阵是6*6的阵,假设位置和角度的估计精度均为0.1且互相独立
// 那么协方差则为对角为0.01的矩阵,信息阵则为100的矩阵
information(,) = information(,) = information(,) = ;
information(,) = information(,) = information(,) = ;
// 也可以将角度设大一些,表示对角度的估计更加准确
edge->setInformation( information );
// 边的估计
Eigen::Isometry3d T = Eigen::Isometry3d::Identity();
T(,) = transformation[];
T(,) = transformation[];
T(,) = transformation[];
T(,) = transformation[];
T(,) = transformation[];
T(,) = transformation[];
T(,) = transformation[];
T(,) = transformation[];
T(,) = transformation[];
T(,) = transformation[];
T(,) = transformation[];
T(,) = transformation[];
T(,) = transformation[];
T(,) = transformation[];
T(,) = transformation[];
T(,) = transformation[];
edge->setMeasurement( T);
// 将此边加入图中
globalOptimizer.addEdge(edge);
} globalOptimizer.save("result_before.g2o");
globalOptimizer.initializeOptimization();
globalOptimizer.optimize( ); //可以指定优化步数
globalOptimizer.save( "result_after.g2o" ); for (int i=startIndex; i< endIndex; i++ )
{
// 从g2o里取出一帧
g2o::VertexSE3* vertex = dynamic_cast<g2o::VertexSE3*>(globalOptimizer.vertex(i ));
Eigen::Isometry3d pose = vertex->estimate(); //该帧优化后的位姿
char a[];
sprintf(a, "%03d", i+);//位姿索引从0开始,而文件帧时从1 开始
string filename=path + "\\scan" + a + ".txt"; Scan * model=new Scan();
model->ReadScanData(filename); Scan * newmodel=new Scan();
model->Transform(newmodel,pose);
string filename1=path + "\\scan" + a + "_optimal.txt";
model->Save(filename1);
// 把点云变换后加入全局地图中
delete model;
delete newmodel;
} printf("优化完毕!\n"); system("pause");
return ;
}
void Scan::Transform(Scan *newScan,const Eigen::Isometry3d& pose)
{
int count=ml_pts->size();
m_model=MatrixXd::Zero(,count);
int nidx=;
for (vector<PointXYZ>::iterator iter = ml_pts->begin();iter< ml_pts->end();iter++) //iter != modelslist->end(); ++iter)
{
PointXYZ tmp=(PointXYZ)*iter;
m_model(,nidx)=tmp.X;
m_model(,nidx)=tmp.Y;
m_model(,nidx)=tmp.Z;
m_model(,nidx)=;
nidx++;
}
m_model=pose.matrix()*m_model; }
[g2o]一个备忘的更多相关文章
- 11. 星际争霸之php设计模式--备忘模式
题记==============================================================================本php设计模式专辑来源于博客(jymo ...
- PostgreSQL 速查、备忘手册 | PostgreSQL Quick Find and Tutorial
PostgreSQL 速查.备忘手册 作者:汪嘉霖 这是一个你可能需要的一个备忘手册,此手册方便你快速查询到你需要的常见功能.有时也有一些曾经被使用过的高级功能.如无特殊说明,此手册仅适用于 Linu ...
- python序列,字典备忘
初识python备忘: 序列:列表,字符串,元组len(d),d[id],del d[id],data in d函数:cmp(x,y),len(seq),list(seq)根据字符串创建列表,max( ...
- Vi命令备忘
备忘 Ctrl+u:向文件首翻半屏: Ctrl+d:向文件尾翻半屏: Ctrl+f:向文件尾翻一屏: Ctrl+b:向文件首翻一屏: Esc:从编辑模式切换到命令模式: ZZ:命令模式下保存当前文件所 ...
- [备忘] Automatically reset Windows Update components
这两天遇到Windows 10的更新问题,官方有一个小工具,可以用来修复Windows Update的问题,备忘如下 https://support.microsoft.com/en-us/kb/97 ...
- ECMAScript 5(ES5)中bind方法简介备忘
一直以来对和this有关的东西模糊不清,譬如call.apply等等.这次看到一个和bind有关的笔试题,故记此文以备忘. bind和call以及apply一样,都是可以改变上下文的this指向的.不 ...
- MFC通过txt查找文件并进行复制-备忘
MFC基于对话框的Demo txt中每行一个23位的卡号. 文件夹中包含以卡号命名的图像文件.(fpt或者bmp文件) 要求遍历文件夹,找到txt中卡号所对应的图像文件,并复制出来. VC6.0写的. ...
- Javascript备忘模式
使用备忘模式,利用了函数的自定义属性,先看一个例子 var test = function (){} test.myAttr = "attr"; 这样,就给test加上了一个自定义 ...
- Cheat (tldr, bropages) - Unix命令用法备忘单
cheat 是一个Unix命令行小工具,用来查询一些常用命令的惯用法(我们都知道,man page阅读起来太累了,常常是跳到最后去看 examples,但并不是所有man pages里面都有examp ...
随机推荐
- HashTable的典型用法以及参考实例
Get-ADComputer -Identity "cnhzpd-f7sc83x" | select -property @{name="computername&quo ...
- Bootstrap兼容
转:http://blog.csdn.net/chenhongwu666/article/details/41513901 如有雷同,不胜荣幸,若转载,请注明让IE6 IE7 IE8 IE9 IE10 ...
- Android基础知识
一.四大组件 Activity(活动).Service(服务).BroadcastReceiver(广播器).Content Provider(内容提供器) 二.五大布局 LinearLayout(线 ...
- eclipse怎么显示代码行数
熟悉java开发的朋友们肯定有这样的经验,那就是在用eclipse进行java开发的时候,没有显示代码的行数,这并不利于我们进行程序的调试.今天,小编就来教大家eclipse怎么显示代码行数 ...
- Json工具类,实现了反射将整个Object转换为Json对象的功能,支持Hibernate的延迟加
package com.aherp.framework.util; import java.lang.reflect.Array;import java.lang.reflect.Method;imp ...
- Nginx 笔记与总结(15)nginx 实现反向代理 ( nginx + apache 动静分离)
在 nginx 中,proxy 用来实现反向代理,upstream 用来实现负载均衡. 例如有两台服务器,nginx 服务器作为代理服务器,执行 .html 文件,apache 服务器上执行 .php ...
- mysql字段额外属性,除去字段类型外的其他属性
如果你不想字段为 NULL 可以设置字段的属性为 NOT NULL, 在操作数据库时如果输入该字段的数据为NULL ,就会报错. AUTO_INCREMENT定义列为自增的属性,一般用于主键,数值会自 ...
- 一看就懂的Android APP开发入门教程
一看就懂的Android APP开发入门教程 作者: 字体:[增加 减小] 类型:转载 这篇文章主要介绍了Android APP开发入门教程,从SDK下载.开发环境搭建.代码编写.APP打包等步骤 ...
- CentOS上安装Node.js
CentOS上安装Node.js [日期:2014-07-21] 来源:Linux社区 作者:maskdfe [字体:大 中 小] CentOS上安装Node.js(想在Linux上学习No ...
- C# easyui datagrid 复选框填充。
具体效果如下: 首页