00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
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
00062
00063 (void) iterations;
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
00083
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
00103
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
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
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
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();
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 )
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 }