gicp_demo.cpp
Go to the documentation of this file.
00001 // g2o - General Graph Optimization
00002 // Copyright (C) 2011 Kurt Konolige
00003 // 
00004 // g2o is free software: you can redistribute it and/or modify
00005 // it under the terms of the GNU Lesser General Public License as published
00006 // by the Free Software Foundation, either version 3 of the License, or
00007 // (at your option) any later version.
00008 // 
00009 // g2o is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 // GNU Lesser General Public License for more details.
00013 // 
00014 // You should have received a copy of the GNU Lesser General Public License
00015 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
00016 
00017 #include <Eigen/StdVector>
00018 #include <tr1/random>
00019 #include <iostream>
00020 #include <stdint.h>
00021 
00022 #include "g2o/core/graph_optimizer_sparse.h"
00023 #include "g2o/core/block_solver.h"
00024 #include "g2o/core/solver.h"
00025 #include "g2o/solvers/cholmod/linear_solver_cholmod.h"
00026 #include "g2o/types/icp/types_icp.h"
00027 
00028 using namespace Eigen;
00029 using namespace std;
00030 using namespace g2o;
00031 
00032 // sampling distributions
00033   class Sample
00034   {
00035 
00036     static tr1::ranlux_base_01 gen_real;
00037     static tr1::mt19937 gen_int;
00038   public:
00039     static int uniform(int from, int to);
00040 
00041     static double uniform();
00042 
00043     static double gaussian(double sigma);
00044   };
00045 
00046 
00047  tr1::ranlux_base_01 Sample::gen_real;
00048   tr1::mt19937 Sample::gen_int;
00049 
00050   int Sample::uniform(int from, int to)
00051   {
00052     tr1::uniform_int<int> unif(from, to);
00053     int sam = unif(gen_int);
00054     return  sam;
00055   }
00056 
00057   double Sample::uniform()
00058   {
00059     std::tr1::uniform_real<double> unif(0.0, 1.0);
00060     double sam = unif(gen_real);
00061     return  sam;
00062   }
00063 
00064   double Sample::gaussian(double sigma)
00065   {
00066     std::tr1::normal_distribution<double> gauss(0.0, sigma);
00067     double sam = gauss(gen_real);
00068     return  sam;
00069   }
00070 
00071 
00072 //
00073 // set up simulated system with noise, optimize it
00074 //
00075 
00076 int main()
00077 {
00078   double euc_noise = 0.01;       // noise in position, m
00079   //  double outlier_ratio = 0.1;
00080 
00081 
00082   SparseOptimizer optimizer;
00083   optimizer.setMethod(SparseOptimizer::LevenbergMarquardt);
00084   optimizer.setVerbose(false);
00085 
00086   // variable-size block solver
00087   BlockSolverX::LinearSolverType * linearSolver
00088       = new LinearSolverCholmod<g2o
00089         ::BlockSolverX::PoseMatrixType>();
00090 
00091 
00092   BlockSolverX * solver_ptr
00093       = new BlockSolverX(&optimizer,linearSolver);
00094 
00095 
00096   optimizer.setSolver(solver_ptr);
00097 
00098 
00099   vector<Vector3d> true_points;
00100   for (size_t i=0;i<1000; ++i)
00101   {
00102     true_points.push_back(Vector3d((Sample::uniform()-0.5)*3,
00103                                    Sample::uniform()-0.5,
00104                                    Sample::uniform()+10));
00105   }
00106 
00107 
00108   // set up two poses
00109   int vertex_id = 0;
00110   for (size_t i=0; i<2; ++i)
00111   {
00112     // set up rotation and translation for this node
00113     Vector3d t(0,0,i);
00114     Quaterniond q;
00115     q.setIdentity();
00116 
00117     SE3Quat cam(q,t);           // camera pose
00118 
00119     // set up node
00120     VertexSE3 *vc = new VertexSE3();
00121     vc->estimate() = cam;
00122 
00123     vc->setId(vertex_id);      // vertex id
00124 
00125     cerr << t.transpose() << " | " << q.coeffs().transpose() << endl;
00126 
00127     // set first cam pose fixed
00128     if (i==0)
00129       vc->setFixed(true);
00130 
00131     // add to optimizer
00132     optimizer.addVertex(vc);
00133 
00134     vertex_id++;                
00135   }
00136 
00137   // set up point matches
00138   for (size_t i=0; i<true_points.size(); ++i)
00139   {
00140     // get two poses
00141     VertexSE3* vp0 = 
00142       dynamic_cast<VertexSE3*>(optimizer.vertices().find(0)->second);
00143     VertexSE3* vp1 = 
00144       dynamic_cast<VertexSE3*>(optimizer.vertices().find(1)->second);
00145 
00146     // calculate the relative 3D position of the point
00147     Vector3d pt0,pt1;
00148     pt0 = vp0->estimate().inverse().map(true_points[i]);
00149     pt1 = vp1->estimate().inverse().map(true_points[i]);
00150 
00151     // add in noise
00152     pt0 += Vector3d(Sample::gaussian(euc_noise ),
00153                     Sample::gaussian(euc_noise ),
00154                     Sample::gaussian(euc_noise ));
00155 
00156     pt1 += Vector3d(Sample::gaussian(euc_noise ),
00157                     Sample::gaussian(euc_noise ),
00158                     Sample::gaussian(euc_noise ));
00159 
00160     // form edge, with normals in varioius positions
00161     Vector3d nm0, nm1;
00162     nm0 << 0, i, 1;
00163     nm1 << 0, i, 1;
00164     nm0.normalize();
00165     nm1.normalize();
00166 
00167     Edge_V_V_GICP * e           // new edge with correct cohort for caching
00168         = new Edge_V_V_GICP(); 
00169 
00170     e->vertices()[0]            // first viewpoint
00171       = dynamic_cast<OptimizableGraph::Vertex*>(vp0);
00172 
00173     e->vertices()[1]            // second viewpoint
00174       = dynamic_cast<OptimizableGraph::Vertex*>(vp1);
00175 
00176     e->measurement().pos0 = pt0;
00177     e->measurement().pos1 = pt1;
00178     e->measurement().normal0 = nm0;
00179     e->measurement().normal1 = nm1;
00180     //        e->inverseMeasurement().pos() = -kp;
00181 
00182     // use this for point-plane
00183     e->information() = e->measurement().prec0(0.01);
00184 
00185     // use this for point-point 
00186     //    e->information().setIdentity();
00187 
00188     //    e->setRobustKernel(true);
00189     e->setHuberWidth(0.01);
00190 
00191     optimizer.addEdge(e);
00192   }
00193 
00194   // move second cam off of its true position
00195   VertexSE3* vc = 
00196     dynamic_cast<VertexSE3*>(optimizer.vertices().find(1)->second);
00197   SE3Quat &cam = vc->estimate();
00198   cam.translation() = Vector3d(0,0,0.2);
00199 
00200   optimizer.initializeOptimization();
00201   optimizer.computeActiveErrors();
00202   cout << "Initial chi2 = " << FIXED(optimizer.chi2()) << endl;
00203 
00204   optimizer.setVerbose(true);
00205 
00206   optimizer.optimize(5);
00207 
00208   cout << endl << "Second vertex should be near 0,0,1" << endl;
00209   cout <<  dynamic_cast<VertexSE3*>(optimizer.vertices().find(0)->second)
00210     ->estimate().translation().transpose() << endl;
00211   cout <<  dynamic_cast<VertexSE3*>(optimizer.vertices().find(1)->second)
00212     ->estimate().translation().transpose() << endl;
00213 }


re_vision
Author(s): Dorian Galvez-Lopez
autogenerated on Sun Jan 5 2014 11:31:16