gicp_sba_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(int argc, char **argv)
00077 {
00078   int num_points = 0;
00079 
00080   // check for arg, # of points to use in projection SBA
00081   if (argc > 1)
00082     num_points = atoi(argv[1]);
00083 
00084   double euc_noise = 0.1;      // noise in position, m
00085   double pix_noise = 1.0;       // pixel noise
00086   //  double outlier_ratio = 0.1;
00087 
00088 
00089   SparseOptimizer optimizer;
00090   optimizer.setMethod(SparseOptimizer::LevenbergMarquardt);
00091   optimizer.setVerbose(false);
00092 
00093   // variable-size block solver
00094   BlockSolverX::LinearSolverType * linearSolver
00095       = new LinearSolverCholmod<g2o
00096         ::BlockSolverX::PoseMatrixType>();
00097 
00098 
00099   BlockSolverX * solver_ptr
00100       = new BlockSolverX(&optimizer,linearSolver);
00101 
00102 
00103   optimizer.setSolver(solver_ptr);
00104 
00105 
00106   vector<Vector3d> true_points;
00107   for (size_t i=0;i<1000; ++i)
00108   {
00109     true_points.push_back(Vector3d((Sample::uniform()-0.5)*3,
00110                                    Sample::uniform()-0.5,
00111                                    Sample::uniform()+10));
00112   }
00113 
00114 
00115   // set up camera params
00116   Vector2d focal_length(500,500); // pixels
00117   Vector2d principal_point(320,240); // 640x480 image
00118   double baseline = 0.075;      // 7.5 cm baseline
00119 
00120   // set up camera params and projection matrices on vertices
00121   g2o::VertexSCam::setKcam(focal_length[0],focal_length[1],
00122                            principal_point[0],principal_point[1],
00123                            baseline);
00124 
00125 
00126   // set up two poses
00127   int vertex_id = 0;
00128   for (size_t i=0; i<2; ++i)
00129   {
00130     // set up rotation and translation for this node
00131     Vector3d t(0,0,i);
00132     Quaterniond q;
00133     q.setIdentity();
00134 
00135     SE3Quat cam(q,t);           // camera pose
00136 
00137     // set up node
00138     VertexSCam *vc = new VertexSCam();
00139     vc->estimate() = cam;
00140     vc->setId(vertex_id);      // vertex id
00141 
00142     cerr << t.transpose() << " | " << q.coeffs().transpose() << endl;
00143 
00144     // set first cam pose fixed
00145     if (i==0)
00146       vc->setFixed(true);
00147 
00148     // make sure projection matrices are set
00149     vc->setAll();
00150 
00151     // add to optimizer
00152     optimizer.addVertex(vc);
00153 
00154     vertex_id++;                
00155   }
00156 
00157   // set up point matches for GICP
00158   for (size_t i=0; i<true_points.size(); ++i)
00159   {
00160     // get two poses
00161     VertexSE3* vp0 = 
00162       dynamic_cast<VertexSE3*>(optimizer.vertices().find(0)->second);
00163     VertexSE3* vp1 = 
00164       dynamic_cast<VertexSE3*>(optimizer.vertices().find(1)->second);
00165 
00166     // calculate the relative 3D position of the point
00167     Vector3d pt0,pt1;
00168     pt0 = vp0->estimate().inverse().map(true_points[i]);
00169     pt1 = vp1->estimate().inverse().map(true_points[i]);
00170 
00171     // add in noise
00172     pt0 += Vector3d(Sample::gaussian(euc_noise ),
00173                     Sample::gaussian(euc_noise ),
00174                     Sample::gaussian(euc_noise ));
00175 
00176     pt1 += Vector3d(Sample::gaussian(euc_noise ),
00177                     Sample::gaussian(euc_noise ),
00178                     Sample::gaussian(euc_noise ));
00179 
00180     // form edge, with normals in varioius positions
00181     Vector3d nm0, nm1;
00182     nm0 << 0, i, 1;
00183     nm1 << 0, i, 1;
00184     nm0.normalize();
00185     nm1.normalize();
00186 
00187     Edge_V_V_GICP * e           // new edge with correct cohort for caching
00188         = new Edge_V_V_GICP(); 
00189 
00190     e->vertices()[0]            // first viewpoint
00191       = dynamic_cast<OptimizableGraph::Vertex*>(vp0);
00192 
00193     e->vertices()[1]            // second viewpoint
00194       = dynamic_cast<OptimizableGraph::Vertex*>(vp1);
00195 
00196     e->measurement().pos0 = pt0;
00197     e->measurement().pos1 = pt1;
00198     e->measurement().normal0 = nm0;
00199     e->measurement().normal1 = nm1;
00200     //        e->inverseMeasurement().pos() = -kp;
00201 
00202     // use this for point-plane
00203     e->information() = e->measurement().prec0(0.01);
00204 
00205     // use this for point-point 
00206     //    e->information().setIdentity();
00207 
00208     //    e->setRobustKernel(true);
00209     e->setHuberWidth(0.01);
00210 
00211     optimizer.addEdge(e);
00212   }
00213 
00214   // set up SBA projections with some number of points
00215 
00216   true_points.clear();
00217   for (int i=0;i<num_points; ++i)
00218   {
00219     true_points.push_back(Vector3d((Sample::uniform()-0.5)*3,
00220                                    Sample::uniform()-0.5,
00221                                    Sample::uniform()+10));
00222   }
00223 
00224 
00225   // add point projections to this vertex
00226   for (size_t i=0; i<true_points.size(); ++i)
00227   {
00228     g2o::VertexPointXYZ * v_p
00229         = new g2o::VertexPointXYZ();
00230 
00231 
00232     v_p->setId(vertex_id++);
00233     v_p->setMarginalized(true);
00234     v_p->estimate() = true_points.at(i)
00235         + Vector3d(Sample::gaussian(1),
00236                    Sample::gaussian(1),
00237                    Sample::gaussian(1));
00238 
00239     optimizer.addVertex(v_p);
00240 
00241     for (size_t j=0; j<2; ++j)
00242       {
00243         Vector3d z;
00244         dynamic_cast<g2o::VertexSCam*>
00245           (optimizer.vertices().find(j)->second)
00246           ->mapPoint(z,true_points.at(i));
00247 
00248         if (z[0]>=0 && z[1]>=0 && z[0]<640 && z[1]<480)
00249         {
00250           z += Vector3d(Sample::gaussian(pix_noise),
00251                         Sample::gaussian(pix_noise),
00252                         Sample::gaussian(pix_noise/16.0));
00253 
00254           g2o::Edge_XYZ_VSC * e
00255               = new g2o::Edge_XYZ_VSC();
00256 
00257           e->vertices()[0]
00258               = dynamic_cast<g2o::OptimizableGraph::Vertex*>(v_p);
00259 
00260           e->vertices()[1]
00261               = dynamic_cast<g2o::OptimizableGraph::Vertex*>
00262               (optimizer.vertices().find(j)->second);
00263 
00264           e->measurement() = z;
00265           e->inverseMeasurement() = -z;
00266           e->information() = Matrix3d::Identity();
00267 
00268           e->setRobustKernel(false);
00269           e->setHuberWidth(1);
00270 
00271           optimizer.addEdge(e);
00272         }
00273 
00274       }
00275   } // done with adding projection points
00276 
00277 
00278 
00279   // move second cam off of its true position
00280   VertexSE3* vc = 
00281     dynamic_cast<VertexSE3*>(optimizer.vertices().find(1)->second);
00282   SE3Quat &cam = vc->estimate();
00283   cam.translation() = Vector3d(-0.1,0.1,0.2);
00284 
00285   optimizer.initializeOptimization();
00286   optimizer.computeActiveErrors();
00287   cout << "Initial chi2 = " << FIXED(optimizer.chi2()) << endl;
00288 
00289   optimizer.setVerbose(true);
00290 
00291   optimizer.optimize(20);
00292 
00293   cout << endl << "Second vertex should be near 0,0,1" << endl;
00294   cout <<  dynamic_cast<VertexSE3*>(optimizer.vertices().find(0)->second)
00295     ->estimate().translation().transpose() << endl;
00296   cout <<  dynamic_cast<VertexSE3*>(optimizer.vertices().find(1)->second)
00297     ->estimate().translation().transpose() << endl;
00298 }


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