graph_optimizer_sparse_online.cpp
Go to the documentation of this file.
00001 // g2o - General Graph Optimization
00002 // Copyright (C) 2011 R. Kuemmerle, G. Grisetti, W. Burgard
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 "types_slam2d_online.h"
00018 #include "types_slam3d_online.h"
00019 
00020 #include "graph_optimizer_sparse_online.h"
00021 
00022 #include "g2o/stuff/macros.h"
00023 #include "g2o/core/block_solver.h"
00024 #include "g2o/core/solver_factory.h"
00025 
00026 #include "g2o/solvers/pcg/linear_solver_pcg.h"
00027 
00028 #include <iostream>
00029 #include <iomanip>
00030 #include <fstream>
00031 using namespace std;
00032 
00033 #define DIM_TO_SOLVER(p, l) BlockSolver< BlockSolverTraits<p, l> >
00034 
00035 #define ALLOC_PCG(s, p, l) \
00036   if (1) { \
00037     std::cerr << "# Using PCG online poseDim " << p << " landMarkDim " << l << " blockordering 1" << std::endl; \
00038     LinearSolverPCG< DIM_TO_SOLVER(p, l)::PoseMatrixType >* linearSolver = new LinearSolverPCG<DIM_TO_SOLVER(p, l)::PoseMatrixType>(); \
00039     linearSolver->setMaxIterations(6); \
00040     s = new DIM_TO_SOLVER(p, l)(opt, linearSolver); \
00041   } else (void)0
00042 
00043 namespace g2o {
00044 
00045 SparseOptimizerOnline::SparseOptimizerOnline(bool pcg) :
00046   SparseOptimizer(),
00047   slamDimension(3), newEdges(0), batchStep(true), vizWithGnuplot(false),
00048   _gnuplot(0), _usePcg(pcg)
00049 {
00050 }
00051 
00052 SparseOptimizerOnline::~SparseOptimizerOnline()
00053 {
00054   if (_gnuplot) {
00055     pclose(_gnuplot);
00056   }
00057 }
00058 
00059 int SparseOptimizerOnline::optimize(int iterations, bool online)
00060 {
00061   //return SparseOptimizer::optimize(iterations, online);
00062 
00063   (void) iterations; // we only do one iteration anyhow
00064   Solver* solver = _solver;
00065   solver->init(online);
00066 
00067   int cjIterations=0;
00068   bool ok=true;
00069 
00070   if (!online) {
00071     ok = solver->buildStructure();
00072     if (! ok) {
00073       cerr << __PRETTY_FUNCTION__ << ": Failure while building CCS structure" << endl;
00074       return 0;
00075     }
00076   }
00077 
00078   if (_usePcg)
00079     batchStep = true;
00080 
00081   if (! online || batchStep) {
00082     //cerr << "BATCH" << endl;
00083     // copy over the updated estimate as new linearization point
00084     if (slamDimension == 3) {
00085       for (size_t i = 0; i < indexMapping().size(); ++i) {
00086         OnlineVertexSE2* v = static_cast<OnlineVertexSE2*>(indexMapping()[i]);
00087         v->estimate() = v->updatedEstimate;
00088       }
00089     }
00090     else if (slamDimension == 6) {
00091       for (size_t i=0; i < indexMapping().size(); ++i) {
00092         OnlineVertexSE3* v = static_cast<OnlineVertexSE3*>(indexMapping()[i]);
00093         v->estimate() = v->updatedEstimate;
00094       }
00095     }
00096 
00097     SparseOptimizer::computeActiveErrors();
00098     SparseOptimizer::linearizeSystem();
00099     solver->buildSystem();
00100   }
00101   else {
00102     //cerr << "UPDATE" << endl;
00103     // compute the active errors for the required edges
00104     for (HyperGraph::EdgeSet::iterator it = newEdges->begin(); it != newEdges->end(); ++it) {
00105       OptimizableGraph::Edge * e = static_cast<OptimizableGraph::Edge*>(*it);
00106       e->computeError();
00107     }
00108     // linearize the constraints
00109     for (HyperGraph::EdgeSet::iterator it = newEdges->begin(); it != newEdges->end(); ++it) {
00110       OptimizableGraph::Edge* e = static_cast<OptimizableGraph::Edge*>(*it);
00111       e->linearizeOplus();
00112     }
00113     // add the updated constraints again to the Hessian
00114     for (HyperGraph::EdgeSet::iterator it = newEdges->begin(); it != newEdges->end(); ++it) {
00115       OptimizableGraph::Edge* e = static_cast<OptimizableGraph::Edge*>(*it);
00116       e->constructQuadraticForm();
00117     }
00118     // update the b vector
00119     for (int i = 0; i < static_cast<int>(indexMapping().size()); ++i) {
00120       OptimizableGraph::Vertex* v = indexMapping()[i];
00121       int iBase = v->colInHessian();
00122       v->copyB(solver->b() + iBase);
00123     }
00124   }
00125 
00126   ok = solver->solve();
00127   update(solver->x());
00128   ++cjIterations; 
00129 
00130   if (verbose()){
00131     computeActiveErrors();
00132     cerr
00133       << "nodes = " << vertices().size()
00134       << "\t edges= " << _activeEdges.size()
00135       << "\t chi2= " << FIXED(activeChi2())
00136       << endl << endl;
00137   }
00138 
00139   if (vizWithGnuplot)
00140     gnuplotVisualization();
00141 
00142   if (! ok)
00143     return 0;
00144   return 1;
00145 }
00146 
00147 void SparseOptimizerOnline::update(double* update)
00148 {
00149   if (slamDimension == 3) {
00150     for (size_t i=0; i < _ivMap.size(); ++i) {
00151       OnlineVertexSE2* v= static_cast<OnlineVertexSE2*>(_ivMap[i]);
00152       v->oplusUpdatedEstimate(update);
00153       update += 3;
00154     }
00155   }
00156   else if (slamDimension == 6) {
00157     for (size_t i=0; i < _ivMap.size(); ++i) {
00158       OnlineVertexSE3* v= static_cast<OnlineVertexSE3*>(_ivMap[i]);
00159       v->oplusUpdatedEstimate(update);
00160       update += 6;
00161     }
00162   }
00163 }
00164 
00165 bool SparseOptimizerOnline::updateInitialization(HyperGraph::VertexSet& vset, HyperGraph::EdgeSet& eset)
00166 {
00167   newEdges = &eset;
00168   bool result = SparseOptimizer::updateInitialization(vset, eset);
00169   for (HyperGraph::VertexSet::iterator it = vset.begin(); it != vset.end(); ++it) {
00170     OptimizableGraph::Vertex* v = static_cast<OptimizableGraph::Vertex*>(*it);
00171     v->clearQuadraticForm(); // be sure that b is zero for this vertex
00172   }
00173   return result;
00174 }
00175 
00176 static Solver* createSolver(SparseOptimizer* opt, const std::string& solverName)
00177 {
00178   g2o::Solver* s = 0;
00179   if (solverName == "pcg3_2_cholmod") {
00180     ALLOC_PCG(s, 3, 2);
00181   }
00182   else if (solverName == "pcg6_3_cholmod") {
00183     ALLOC_PCG(s, 6, 3);
00184   }
00185   return s;
00186 }
00187 
00188 bool SparseOptimizerOnline::initSolver(int dimension, int /*batchEveryN*/)
00189 {
00190   slamDimension = dimension;
00191   SolverFactory* solverFactory = SolverFactory::instance();
00192   SolverProperty solverProperty;
00193   if (_usePcg) {
00194     if (dimension == 3) {
00195       setSolver(createSolver(this, "pcg3_2_cholmod"));
00196     } else {
00197       setSolver(createSolver(this, "pcg6_3_cholmod"));
00198     }
00199   }
00200   else {
00201     if (dimension == 3) {
00202       setSolver(solverFactory->construct("fix3_2_cholmod", this, solverProperty));
00203     } else {
00204       setSolver(solverFactory->construct("fix6_3_cholmod", this, solverProperty));
00205     }
00206   }
00207   solver()->setSchur(false);
00208   if (! solver()) {
00209     cerr << "Error allocating solver. Allocating CHOLMOD solver failed!" << endl;
00210     return false;
00211   }
00212   return true;
00213 }
00214 
00215 void SparseOptimizerOnline::gnuplotVisualization()
00216 {
00217   if (slamDimension == 3) {
00218     if (! _gnuplot) {
00219       _gnuplot = popen("gnuplot -persistent", "w");
00220       fprintf(_gnuplot, "set terminal X11 noraise\n");
00221       fprintf(_gnuplot, "set size ratio -1\n");
00222     }
00223     fprintf(_gnuplot, "plot \"-\" w l\n");
00224     for (EdgeSet::iterator it = edges().begin(); it != edges().end(); ++it) {
00225       OnlineEdgeSE2* e = (OnlineEdgeSE2*) *it;
00226       OnlineVertexSE2* v1 = (OnlineVertexSE2*) e->vertices()[0];
00227       OnlineVertexSE2* v2 = (OnlineVertexSE2*) e->vertices()[1];
00228       fprintf(_gnuplot, "%f %f\n", v1->updatedEstimate.translation().x(), v1->updatedEstimate.translation().y());
00229       fprintf(_gnuplot, "%f %f\n\n", v2->updatedEstimate.translation().x(), v2->updatedEstimate.translation().y());
00230     }
00231     fprintf(_gnuplot, "e\n");
00232   }
00233   if (slamDimension == 6) {
00234     if (! _gnuplot) {
00235       _gnuplot = popen("gnuplot -persistent", "w");
00236       fprintf(_gnuplot, "set terminal X11 noraise\n");
00237     }
00238     fprintf(_gnuplot, "splot \"-\" w l\n");
00239     for (EdgeSet::iterator it = edges().begin(); it != edges().end(); ++it) {
00240       OnlineEdgeSE3* e = (OnlineEdgeSE3*) *it;
00241       OnlineVertexSE3* v1 = (OnlineVertexSE3*) e->vertices()[0];
00242       OnlineVertexSE3* v2 = (OnlineVertexSE3*) e->vertices()[1];
00243       fprintf(_gnuplot, "%f %f %f\n", v1->updatedEstimate.translation().x(), v1->updatedEstimate.translation().y(), v1->updatedEstimate.translation().z());
00244       fprintf(_gnuplot, "%f %f %f \n\n\n", v2->updatedEstimate.translation().x(), v2->updatedEstimate.translation().y(), v2->updatedEstimate.translation().z());
00245     }
00246     fprintf(_gnuplot, "e\n");
00247   }
00248 }
00249 
00250 } // end namespace


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