g2o
Public Member Functions | Protected Member Functions | Protected Attributes | List of all members
g2o::SparseOptimizerIncremental Class Reference

#include <graph_optimizer_sparse_incremental.h>

Inheritance diagram for g2o::SparseOptimizerIncremental:
Inheritance graph
[legend]
Collaboration diagram for g2o::SparseOptimizerIncremental:
Collaboration graph
[legend]

Public Member Functions

 SparseOptimizerIncremental ()
 
 ~SparseOptimizerIncremental ()
 
int optimize (int iterations, bool online=false)
 
virtual bool updateInitialization (HyperGraph::VertexSet &vset, HyperGraph::EdgeSet &eset)
 
virtual bool initSolver (int dimension, int batchEveryN)
 
- Public Member Functions inherited from g2o::SparseOptimizerOnline
 SparseOptimizerOnline (bool pcg=false)
 
virtual ~SparseOptimizerOnline ()
 
int optimize (int iterations, bool online=false)
 
void update (double *update)
 
virtual void gnuplotVisualization ()
 
- Public Member Functions inherited from g2o::SparseOptimizer
 SparseOptimizer ()
 
virtual ~SparseOptimizer ()
 
virtual bool initializeOptimization (HyperGraph::EdgeSet &eset)
 
virtual bool initializeOptimization (HyperGraph::VertexSet &vset, int level=0)
 
virtual bool initializeOptimization (int level=0)
 
virtual void computeInitialGuess ()
 
virtual void computeInitialGuess (EstimatePropagatorCost &propagator)
 
virtual void setToOrigin ()
 
bool computeMarginals (SparseBlockMatrix< MatrixXD > &spinv, const std::vector< std::pair< int, int > > &blockIndices)
 
bool computeMarginals (SparseBlockMatrix< MatrixXD > &spinv, const Vertex *vertex)
 
bool computeMarginals (SparseBlockMatrix< MatrixXD > &spinv, const VertexContainer &vertices)
 
virtual VertexfindGauge ()
 finds a gauge in the graph to remove the undefined dof. More...
 
bool gaugeFreedom ()
 
double activeChi2 () const
 
double activeRobustChi2 () const
 
bool verbose () const
 verbose information during optimization More...
 
void setVerbose (bool verbose)
 
void setForceStopFlag (bool *flag)
 
bool * forceStopFlag () const
 
bool terminate ()
 if external stop flag is given, return its state. False otherwise More...
 
const VertexContainerindexMapping () const
 the index mapping of the vertices More...
 
const VertexContaineractiveVertices () const
 the vertices active in the current optimization More...
 
const EdgeContaineractiveEdges () const
 the edges active in the current optimization More...
 
virtual bool removeVertex (HyperGraph::Vertex *v, bool detach=false)
 
VertexContainer::const_iterator findActiveVertex (const OptimizableGraph::Vertex *v) const
 
EdgeContainer::const_iterator findActiveEdge (const OptimizableGraph::Edge *e) const
 
const OptimizationAlgorithmalgorithm () const
 the solver used by the optimizer More...
 
OptimizationAlgorithmsolver ()
 
void setAlgorithm (OptimizationAlgorithm *algorithm)
 
void push (SparseOptimizer::VertexContainer &vlist)
 push the estimate of a subset of the variables onto a stack More...
 
void push (HyperGraph::VertexSet &vlist)
 push the estimate of a subset of the variables onto a stack More...
 
void push ()
 push all the active vertices onto a stack More...
 
void pop (SparseOptimizer::VertexContainer &vlist)
 pop (restore) the estimate a subset of the variables from the stack More...
 
void pop (HyperGraph::VertexSet &vlist)
 pop (restore) the estimate a subset of the variables from the stack More...
 
void pop ()
 pop (restore) the estimate of the active vertices from the stack More...
 
void discardTop (SparseOptimizer::VertexContainer &vlist)
 ignore the latest stored element on the stack, remove it from the stack but do not restore the estimate More...
 
void discardTop ()
 same as above, but for the active vertices More...
 
virtual void clear ()
 
void computeActiveErrors ()
 
const BatchStatisticsContainerbatchStatistics () const
 
BatchStatisticsContainerbatchStatistics ()
 
void setComputeBatchStatistics (bool computeBatchStatistics)
 
bool computeBatchStatistics () const
 
bool addComputeErrorAction (HyperGraphAction *action)
 add an action to be executed before the error vectors are computed More...
 
bool removeComputeErrorAction (HyperGraphAction *action)
 remove an action that should no longer be execured before computing the error vectors More...
 
- Public Member Functions inherited from g2o::OptimizableGraph
Vertexvertex (int id)
 returns the vertex number id appropriately casted More...
 
const Vertexvertex (int id) const
 returns the vertex number id appropriately casted More...
 
 OptimizableGraph ()
 empty constructor More...
 
virtual ~OptimizableGraph ()
 
void addGraph (OptimizableGraph *g)
 adds all edges and vertices of the graph g to this graph. More...
 
virtual bool addVertex (HyperGraph::Vertex *v, Data *userData)
 
virtual bool addVertex (HyperGraph::Vertex *v)
 
virtual bool addEdge (HyperGraph::Edge *e)
 
virtual bool setEdgeVertex (HyperGraph::Edge *e, int pos, HyperGraph::Vertex *v)
 
double chi2 () const
 returns the chi2 of the current configuration More...
 
int maxDimension () const
 return the maximum dimension of all vertices in the graph More...
 
std::set< int > dimensions () const
 
virtual void preIteration (int)
 called at the beginning of an iteration (argument is the number of the iteration) More...
 
virtual void postIteration (int)
 called at the end of an iteration (argument is the number of the iteration) More...
 
bool addPreIterationAction (HyperGraphAction *action)
 add an action to be executed before each iteration More...
 
bool addPostIterationAction (HyperGraphAction *action)
 add an action to be executed after each iteration More...
 
bool removePreIterationAction (HyperGraphAction *action)
 remove an action that should no longer be execured before each iteration More...
 
bool removePostIterationAction (HyperGraphAction *action)
 remove an action that should no longer be execured after each iteration More...
 
virtual bool load (std::istream &is, bool createEdges=true)
 load the graph from a stream. Uses the Factory singleton for creating the vertices and edges. More...
 
bool load (const char *filename, bool createEdges=true)
 
virtual bool save (std::ostream &os, int level=0) const
 save the graph to a stream. Again uses the Factory system. More...
 
bool save (const char *filename, int level=0) const
 function provided for convenience, see save() above More...
 
bool saveSubset (std::ostream &os, HyperGraph::VertexSet &vset, int level=0)
 save a subgraph to a stream. Again uses the Factory system. More...
 
bool saveSubset (std::ostream &os, HyperGraph::EdgeSet &eset)
 save a subgraph to a stream. Again uses the Factory system. More...
 
virtual void discardTop (HyperGraph::VertexSet &vset)
 ignore the latest stored element on the stack, remove it from the stack but do not restore the estimate More...
 
virtual void setFixed (HyperGraph::VertexSet &vset, bool fixed)
 fixes/releases a set of vertices More...
 
void setRenamedTypesFromString (const std::string &types)
 
bool isSolverSuitable (const OptimizationAlgorithmProperty &solverProperty, const std::set< int > &vertDims=std::set< int >()) const
 
virtual void clearParameters ()
 
bool addParameter (Parameter *p)
 
Parameterparameter (int id)
 
bool verifyInformationMatrices (bool verbose=false) const
 
bool saveVertex (std::ostream &os, Vertex *v) const
 
bool saveParameter (std::ostream &os, Parameter *v) const
 
bool saveEdge (std::ostream &os, Edge *e) const
 
bool saveUserData (std::ostream &os, HyperGraph::Data *v) const
 
JacobianWorkspacejacobianWorkspace ()
 the workspace for storing the Jacobians of the graph More...
 
const JacobianWorkspacejacobianWorkspace () const
 
ParameterContainerparameters ()
 
const ParameterContainerparameters () const
 
- Public Member Functions inherited from g2o::HyperGraph
 HyperGraph ()
 constructs an empty hyper graph More...
 
virtual ~HyperGraph ()
 destroys the hyper-graph and all the vertices of the graph More...
 
Vertexvertex (int id)
 returns a vertex id in the hyper-graph, or 0 if the vertex id is not present More...
 
const Vertexvertex (int id) const
 returns a vertex id in the hyper-graph, or 0 if the vertex id is not present More...
 
virtual bool removeEdge (Edge *e)
 removes a vertex from the graph. Returns true on success (edge was present) More...
 
const VertexIDMapvertices () const
 
VertexIDMapvertices ()
 
const EdgeSetedges () const
 
EdgeSetedges ()
 
virtual bool mergeVertices (Vertex *vBig, Vertex *vSmall, bool erase)
 
virtual bool detachVertex (Vertex *v)
 
virtual bool changeId (Vertex *v, int newId)
 

Protected Member Functions

bool computeCholeskyUpdate ()
 
void convertTripletUpdateToSparse ()
 
- Protected Member Functions inherited from g2o::SparseOptimizer
void sortVectorContainers ()
 
bool buildIndexMapping (SparseOptimizer::VertexContainer &vlist)
 
void clearIndexMapping ()
 

Protected Attributes

SparseBlockMatrix< Eigen::MatrixXd > _updateMat
 
cholmod_common _cholmodCommon
 
CholmodExt_cholmodSparse
 
cholmod_factor * _cholmodFactor
 
cholmod_triplet * _permutedUpdate
 
cholmod_factor * _L
 
LinearSolverCholmodOnlineInterface_solverInterface
 
HyperGraph::VertexSet _touchedVertices
 
Eigen::VectorXi _perm
 
Eigen::VectorXi _cmember
 
Eigen::VectorXi _tripletWorkspace
 
CholmodExt_permutedUpdateAsSparse
 
- Protected Attributes inherited from g2o::SparseOptimizerOnline
FILE * _gnuplot
 
bool _usePcg
 
Solver_underlyingSolver
 
- Protected Attributes inherited from g2o::SparseOptimizer
bool * _forceStopFlag
 
bool _verbose
 
VertexContainer _ivMap
 
VertexContainer _activeVertices
 sorted according to VertexIDCompare More...
 
EdgeContainer _activeEdges
 sorted according to EdgeIDCompare More...
 
OptimizationAlgorithm_algorithm
 
BatchStatisticsContainer _batchStatistics
 global statistics of the optimizer, e.g., timing, num-non-zeros More...
 
bool _computeBatchStatistics
 
- Protected Attributes inherited from g2o::OptimizableGraph
std::map< std::string, std::string > _renamedTypesLookup
 
long long _nextEdgeId
 
std::vector< HyperGraphActionSet_graphActions
 
bool _edge_has_id
 
ParameterContainer _parameters
 
JacobianWorkspace _jacobianWorkspace
 
- Protected Attributes inherited from g2o::HyperGraph
VertexIDMap _vertices
 
EdgeSet _edges
 

Additional Inherited Members

- Public Types inherited from g2o::SparseOptimizer
enum  { AT_COMPUTEACTIVERROR = OptimizableGraph::AT_NUM_ELEMENTS, AT_NUM_ELEMENTS }
 
- Public Types inherited from g2o::OptimizableGraph
enum  ActionType { AT_PREITERATION, AT_POSTITERATION, AT_NUM_ELEMENTS }
 
typedef std::set< HyperGraphAction * > HyperGraphActionSet
 
typedef std::vector< OptimizableGraph::Vertex * > VertexContainer
 vector container for vertices More...
 
typedef std::vector< OptimizableGraph::Edge * > EdgeContainer
 vector container for edges More...
 
- Public Types inherited from g2o::HyperGraph
typedef std::bitset< HyperGraph::HGET_NUM_ELEMS > GraphElemBitset
 
typedef std::set< Edge * > EdgeSet
 
typedef std::set< Vertex * > VertexSet
 
typedef std::unordered_map< int, Vertex * > VertexIDMap
 
typedef std::vector< Vertex * > VertexContainer
 
- Static Public Member Functions inherited from g2o::OptimizableGraph
static bool initMultiThreading ()
 
- Public Attributes inherited from g2o::SparseOptimizerOnline
int slamDimension
 
HyperGraph::EdgeSetnewEdges
 
bool batchStep
 
bool vizWithGnuplot
 
- Public Attributes inherited from g2o::OptimizableGraph
class G2O_CORE_API Vertex
 
class G2O_CORE_API Edge
 
- Public Attributes inherited from g2o::HyperGraph
class G2O_CORE_API Data
 
class G2O_CORE_API DataContainer
 
class G2O_CORE_API Vertex
 
class G2O_CORE_API Edge
 
- Static Public Attributes inherited from g2o::HyperGraph
static const int UnassignedId = -1
 
static const int InvalidId = -2
 

Detailed Description

Definition at line 30 of file graph_optimizer_sparse_incremental.h.

Constructor & Destructor Documentation

g2o::SparseOptimizerIncremental::SparseOptimizerIncremental ( )

Definition at line 57 of file graph_optimizer_sparse_incremental.cpp.

58  {
59  _cholmodSparse = new CholmodExt();
60  _cholmodFactor = 0;
61  cholmod_start(&_cholmodCommon);
62 
63  // setup ordering strategy to not permute the matrix
64  _cholmodCommon.nmethods = 1 ;
65  _cholmodCommon.method[0].ordering = CHOLMOD_NATURAL;
66  _cholmodCommon.postorder = 0;
67  _cholmodCommon.supernodal = CHOLMOD_SIMPLICIAL;
68 
69  _permutedUpdate = cholmod_allocate_triplet(1000, 1000, 1024, 0, CHOLMOD_REAL, &_cholmodCommon);
70  _L = 0;
71  _cholmodFactor = 0;
72  _solverInterface = 0;
73 
74  _permutedUpdateAsSparse = new CholmodExt;
75  }
LinearSolverCholmodOnlineInterface * _solverInterface
g2o::SparseOptimizerIncremental::~SparseOptimizerIncremental ( )

Definition at line 77 of file graph_optimizer_sparse_incremental.cpp.

78  {
80  _updateMat.clear(true);
81  delete _cholmodSparse;
82  if (_cholmodFactor) {
83  cholmod_free_factor(&_cholmodFactor, &_cholmodCommon);
84  _cholmodFactor = 0;
85  }
86  cholmod_free_triplet(&_permutedUpdate, &_cholmodCommon);
87  cholmod_finish(&_cholmodCommon);
88  }
void clear(bool dealloc=false)
this zeroes all the blocks. If dealloc=true the blocks are removed from memory
SparseBlockMatrix< Eigen::MatrixXd > _updateMat

Member Function Documentation

bool g2o::SparseOptimizerIncremental::computeCholeskyUpdate ( )
protected

Definition at line 402 of file graph_optimizer_sparse_incremental.cpp.

References g2o::SparseBlockMatrix< MatrixType >::cols(), g2o::SparseBlockMatrix< MatrixType >::fillCCS(), g2o::SparseBlockMatrix< MatrixType >::nonZeros(), and g2o::SparseBlockMatrix< MatrixType >::rows().

403  {
404  if (_cholmodFactor) {
405  cholmod_free_factor(&_cholmodFactor, &_cholmodCommon);
406  _cholmodFactor = 0;
407  }
408 
409  const SparseBlockMatrix<MatrixXd>& A = _updateMat;
410  size_t m = A.rows();
411  size_t n = A.cols();
412 
413  if (_cholmodSparse->columnsAllocated < n) {
414  //std::cerr << __PRETTY_FUNCTION__ << ": reallocating columns" << std::endl;
415  _cholmodSparse->columnsAllocated = _cholmodSparse->columnsAllocated == 0 ? n : 2 * n; // pre-allocate more space if re-allocating
416  delete[] (int*)_cholmodSparse->p;
418  }
419  size_t nzmax = A.nonZeros();
420  if (_cholmodSparse->nzmax < nzmax) {
421  //std::cerr << __PRETTY_FUNCTION__ << ": reallocating row + values" << std::endl;
422  _cholmodSparse->nzmax = _cholmodSparse->nzmax == 0 ? nzmax : 2 * nzmax; // pre-allocate more space if re-allocating
423  delete[] (double*)_cholmodSparse->x;
424  delete[] (int*)_cholmodSparse->i;
425  _cholmodSparse->i = new int[_cholmodSparse->nzmax];
426  _cholmodSparse->x = new double[_cholmodSparse->nzmax];
427  }
428  _cholmodSparse->ncol = n;
429  _cholmodSparse->nrow = m;
430 
431  A.fillCCS((int*)_cholmodSparse->p, (int*)_cholmodSparse->i, (double*)_cholmodSparse->x, true);
432  //writeCCSMatrix("updatesparse.txt", _cholmodSparse->nrow, _cholmodSparse->ncol, (int*)_cholmodSparse->p, (int*)_cholmodSparse->i, (double*)_cholmodSparse->x, true);
433 
434  _cholmodFactor = cholmod_analyze(_cholmodSparse, &_cholmodCommon);
435  cholmod_factorize(_cholmodSparse, _cholmodFactor, &_cholmodCommon);
436 
437 #if 0
438  int* p = (int*)_cholmodFactor->Perm;
439  for (int i = 0; i < (int)n; ++i)
440  if (i != p[i])
441  cerr << "wrong permutation" << i << " -> " << p[i] << endl;
442 #endif
443 
444  if (_cholmodCommon.status == CHOLMOD_NOT_POSDEF) {
445  //std::cerr << "Cholesky failure, writing debug.txt (Hessian loadable by Octave)" << std::endl;
446  //writeCCSMatrix("debug.txt", _cholmodSparse->nrow, _cholmodSparse->ncol, (int*)_cholmodSparse->p, (int*)_cholmodSparse->i, (double*)_cholmodSparse->x, true);
447  return false;
448  }
449 
450  // change to the specific format we need to have a pretty normal L
451  int change_status = cholmod_change_factor(CHOLMOD_REAL, 1, 0, 1, 1, _cholmodFactor, &_cholmodCommon);
452  if (! change_status) {
453  return false;
454  }
455 
456  return true;
457  }
int rows() const
rows of the matrix
SparseBlockMatrix< Eigen::MatrixXd > _updateMat
void g2o::SparseOptimizerIncremental::convertTripletUpdateToSparse ( )
protected

Definition at line 510 of file graph_optimizer_sparse_incremental.cpp.

References g2o::BlockSolver< Traits >::resize().

511  {
512  // re-allocate the memory
513  if (_tripletWorkspace.size() < (int)_permutedUpdate->ncol) {
514  _tripletWorkspace.resize(_permutedUpdate->ncol * 2);
515  }
516 
517  // reallocate num-zeros
518  if (_permutedUpdateAsSparse->nzmax < _permutedUpdate->nzmax) {
520  delete[] (int*)_permutedUpdateAsSparse->i;
521  delete[] (double*)_permutedUpdateAsSparse->x;
522  _permutedUpdateAsSparse->x = new double[_permutedUpdateAsSparse->nzmax];
524  }
525 
528  delete[] (int*) _permutedUpdateAsSparse->p;
530  }
531 
534 
535  int* w = _tripletWorkspace.data();
536  memset(w, 0, sizeof(int) * _permutedUpdate->ncol);
537 
538  int* Ti = (int*) _permutedUpdate->i;
539  int* Tj = (int*) _permutedUpdate->j;
540  double* Tx = (double*) _permutedUpdate->x;
541 
542  int* Cp = (int*) _permutedUpdateAsSparse->p;
543  int* Ci = (int*) _permutedUpdateAsSparse->i;
544  double* Cx = (double*) _permutedUpdateAsSparse->x;
545 
546  for (size_t k = 0; k < _permutedUpdate->nnz; ++k) /* column counts */
547  w[Tj [k]]++;
548 
549  /* column pointers */
550  int n = _permutedUpdate->ncol;
551  int nz = 0;
552  for (int i = 0 ; i < n ; i++) {
553  Cp[i] = nz;
554  nz += w[i];
555  w[i] = Cp[i];
556  }
557  Cp[n] = nz;
558  assert((size_t)nz == _permutedUpdate->nnz);
559 
560  int p;
561  for (size_t k = 0 ; k < _permutedUpdate->nnz ; ++k) {
562  p = w[Tj[k]]++;
563  Ci[p] = Ti[k] ; /* A(i,j) is the pth entry in C */
564  Cx[p] = Tx[k] ;
565  }
566 
567  }
bool g2o::SparseOptimizerIncremental::initSolver ( int  dimension,
int  batchEveryN 
)
virtual

Reimplemented from g2o::SparseOptimizerOnline.

Definition at line 474 of file graph_optimizer_sparse_incremental.cpp.

References g2o::createSolver(), g2o::BlockSolver< Traits >::linearSolver(), g2o::Solver::setAdditionalVectorSpace(), g2o::BlockSolver< Traits >::setSchur(), and g2o::OptimizationAlgorithmWithHessian::solver().

475  {
476  //cerr << __PRETTY_FUNCTION__ << endl;
477  slamDimension = dimension;
478  if (dimension == 3) {
479  setAlgorithm(createSolver("fix3_2_cholmod"));
480  OptimizationAlgorithmGaussNewton* gaussNewton = dynamic_cast<OptimizationAlgorithmGaussNewton*>(solver());
481  assert(gaussNewton);
482  BlockSolver<BlockSolverTraits<3, 2> >* bs = dynamic_cast<BlockSolver<BlockSolverTraits<3, 2> >*>(gaussNewton->solver());
483  assert(bs && "Unable to get internal block solver");
484  LinearSolverCholmodOnline<Matrix3d>* s = dynamic_cast<LinearSolverCholmodOnline<Matrix3d>*>(bs->linearSolver());
485  bs->setAdditionalVectorSpace(300);
486  bs->setSchur(false);
487  _solverInterface = s;
488  _underlyingSolver = bs;
489  } else {
490  setAlgorithm(createSolver("fix6_3_cholmod"));
491  OptimizationAlgorithmGaussNewton* gaussNewton = dynamic_cast<OptimizationAlgorithmGaussNewton*>(solver());
492  assert(gaussNewton);
493  BlockSolver<BlockSolverTraits<6, 3> >* bs = dynamic_cast<BlockSolver<BlockSolverTraits<6, 3> >*>(gaussNewton->solver());
494  assert(bs && "Unable to get internal block solver");
495  LinearSolverCholmodOnline<Matrix<double, 6, 6> >* s = dynamic_cast<LinearSolverCholmodOnline<Matrix<double, 6, 6> >*>(bs->linearSolver());
496  bs->setAdditionalVectorSpace(600);
497  bs->setSchur(false);
498  _solverInterface = s;
499  _underlyingSolver = bs;
500  }
502  _solverInterface->batchEveryN = batchEveryN;
503  if (! solver()) {
504  cerr << "Error allocating solver. Allocating CHOLMOD solver failed!" << endl;
505  return false;
506  }
507  return true;
508  }
static OptimizationAlgorithm * createSolver(const std::string &solverName)
OptimizationAlgorithm * solver()
void setAlgorithm(OptimizationAlgorithm *algorithm)
LinearSolverCholmodOnlineInterface * _solverInterface
int g2o::SparseOptimizerIncremental::optimize ( int  iterations,
bool  online = false 
)
virtual

starts one optimization run given the current configuration of the graph, and the current settings stored in the class instance. It can be called only after initializeOptimization

Reimplemented from g2o::SparseOptimizer.

Definition at line 90 of file graph_optimizer_sparse_incremental.cpp.

References __PRETTY_FUNCTION__, g2o::OptimizableGraph::Vertex::colInHessian(), g2o::OptimizableGraph::Vertex::copyB(), g2o::OptimizableGraph::Vertex::hessianIndex(), g2o::OptimizationAlgorithm::init(), g2o::BaseVertex< D, T >::setEstimate(), g2o::OnlineVertexSE3::updatedEstimate, g2o::OnlineVertexSE2::updatedEstimate, vertices, and g2o::HyperGraph::Edge::vertices().

91  {
92  (void) iterations; // we only do one iteration anyhow
94  solver->init(online);
95 
96  int cjIterations=0;
97  bool ok=true;
98 
99  if (! online || batchStep) {
100  //cerr << "performing batch step" << endl;
101  if (! online) {
103  if (! ok) {
104  cerr << __PRETTY_FUNCTION__ << ": Failure while building CCS structure" << endl;
105  return 0;
106  }
107  }
108 
109  // copy over the updated estimate as new linearization point
110  if (slamDimension == 3) {
111  for (size_t i = 0; i < indexMapping().size(); ++i) {
112  OnlineVertexSE2* v = static_cast<OnlineVertexSE2*>(indexMapping()[i]);
113  v->setEstimate(v->updatedEstimate);
114  }
115  }
116  else if (slamDimension == 6) {
117  for (size_t i = 0; i < indexMapping().size(); ++i) {
118  OnlineVertexSE3* v= static_cast<OnlineVertexSE3*>(indexMapping()[i]);
119  v->setEstimate(v->updatedEstimate);
120  }
121  }
122 
124  //SparseOptimizer::linearizeSystem();
126 
127  // mark vertices to be sorted as last
128  int numBlocksRequired = _ivMap.size();
129  if (_cmember.size() < numBlocksRequired) {
130  _cmember.resize(2 * numBlocksRequired);
131  }
132  memset(_cmember.data(), 0, numBlocksRequired * sizeof(int));
133  if (_ivMap.size() > 100) {
134  for (size_t i = _ivMap.size() - 20; i < _ivMap.size(); ++i) {
135  const HyperGraph::EdgeSet& eset = _ivMap[i]->edges();
136  for (HyperGraph::EdgeSet::const_iterator it = eset.begin(); it != eset.end(); ++it) {
137  OptimizableGraph::Edge* e = static_cast<OptimizableGraph::Edge*>(*it);
138  OptimizableGraph::Vertex* v1 = static_cast<OptimizableGraph::Vertex*>(e->vertices()[0]);
139  OptimizableGraph::Vertex* v2 = static_cast<OptimizableGraph::Vertex*>(e->vertices()[1]);
140  if (v1->hessianIndex() >= 0)
141  _cmember(v1->hessianIndex()) = 1;
142  if (v2->hessianIndex() >= 0)
143  _cmember(v2->hessianIndex()) = 1;
144  }
145  }
146  //OptimizableGraph::Vertex* lastPose = _ivMap.back();
147  //_cmember(lastPose->hessianIndex()) = 2;
148  }
149 
150  ok = _underlyingSolver->solve();
151 
152  // get the current cholesky factor along with the permutation
153  _L = _solverInterface->L();
154  if (_perm.size() < (int)_L->n)
155  _perm.resize(2*_L->n);
156  int* p = (int*)_L->Perm;
157  for (size_t i = 0; i < _L->n; ++i)
158  _perm[p[i]] = i;
159 
160  }
161  else {
162  // update the b vector
163  for (HyperGraph::VertexSet::iterator it = _touchedVertices.begin(); it != _touchedVertices.end(); ++it) {
164  OptimizableGraph::Vertex* v = static_cast<OptimizableGraph::Vertex*>(*it);
165  int iBase = v->colInHessian();
166  v->copyB(_underlyingSolver->b() + iBase);
167  }
169  }
170 
171  // print statistics for the non-zeros
172  //static ofstream debugNonZeros("non-zeros.txt");
173  //debugNonZeros << _solverInterface->nonZerosInL() << endl;
174 
176  ++cjIterations;
177 
178  if (verbose()){
180  cerr
181  << "nodes = " << vertices().size()
182  << "\t edges= " << _activeEdges.size()
183  << "\t chi2= " << FIXED(activeChi2())
184  << endl;
185  }
186 
187  if (vizWithGnuplot)
189 
190  if (! ok)
191  return 0;
192  return 1;
193  }
VertexContainer _ivMap
#define __PRETTY_FUNCTION__
Definition: macros.h:89
virtual bool init(bool online=false)=0
OptimizationAlgorithm * solver()
class G2O_CORE_API OptimizationAlgorithm
virtual bool solve(double *x, double *b)=0
const VertexIDMap & vertices() const
Definition: hyper_graph.h:225
std::set< Edge * > EdgeSet
Definition: hyper_graph.h:135
class G2O_CORE_API Vertex
virtual cholmod_factor * L() const =0
class G2O_CORE_API Edge
const VertexContainer & indexMapping() const
the index mapping of the vertices
EdgeContainer _activeEdges
sorted according to EdgeIDCompare
virtual bool solve()=0
double * x()
return x, the solution vector
Definition: solver.h:96
double * b()
return b, the right hand side of the system
Definition: solver.h:99
virtual bool buildSystem()=0
LinearSolverCholmodOnlineInterface * _solverInterface
bool verbose() const
verbose information during optimization
OptimizationAlgorithm * _algorithm
virtual bool buildStructure(bool zeroBlocks=false)=0
double activeChi2() const
bool g2o::SparseOptimizerIncremental::updateInitialization ( HyperGraph::VertexSet vset,
HyperGraph::EdgeSet eset 
)
virtual

HACK updating the internal structures for online processing

Reimplemented from g2o::SparseOptimizerOnline.

Definition at line 195 of file graph_optimizer_sparse_incremental.cpp.

References g2o::OptimizableGraph::Vertex::clearQuadraticForm(), g2o::OptimizableGraph::Edge::computeError(), g2o::OptimizableGraph::Edge::constructQuadraticForm(), g2o::OptimizableGraph::Vertex::dimension(), g2o::OptimizableGraph::Vertex::fixed(), g2o::OptimizableGraph::Vertex::hessianData(), g2o::OptimizableGraph::Vertex::hessianIndex(), g2o::OptimizableGraph::Edge::linearizeOplus(), g2o::OptimizableGraph::Vertex::mapHessianMemory(), g2o::OptimizableGraph::Edge::mapHessianMemory(), g2o::OptimizableGraph::Vertex::marginalized(), g2o::OptimizableGraph::Vertex::setHessianIndex(), and g2o::HyperGraph::Edge::vertices().

196  {
197  if (batchStep) {
199  }
200 
201  for (HyperGraph::VertexSet::iterator it = vset.begin(); it != vset.end(); ++it) {
202  OptimizableGraph::Vertex* v = static_cast<OptimizableGraph::Vertex*>(*it);
203  v->clearQuadraticForm(); // be sure that b is zero for this vertex
204  }
205 
206  // get the touched vertices
207  _touchedVertices.clear();
208  for (HyperGraph::EdgeSet::iterator it = eset.begin(); it != eset.end(); ++it) {
209  OptimizableGraph::Edge* e = static_cast<OptimizableGraph::Edge*>(*it);
210  OptimizableGraph::Vertex* v1 = static_cast<OptimizableGraph::Vertex*>(e->vertices()[0]);
211  OptimizableGraph::Vertex* v2 = static_cast<OptimizableGraph::Vertex*>(e->vertices()[1]);
212  if (! v1->fixed())
213  _touchedVertices.insert(v1);
214  if (! v2->fixed())
215  _touchedVertices.insert(v2);
216  }
217  //cerr << PVAR(_touchedVertices.size()) << endl;
218 
219  // updating the internal structures
220  std::vector<HyperGraph::Vertex*> newVertices;
221  newVertices.reserve(vset.size());
222  _activeVertices.reserve(_activeVertices.size() + vset.size());
223  _activeEdges.reserve(_activeEdges.size() + eset.size());
224  for (HyperGraph::EdgeSet::iterator it = eset.begin(); it != eset.end(); ++it)
225  _activeEdges.push_back(static_cast<OptimizableGraph::Edge*>(*it));
226  //cerr << "updating internal done." << endl;
227 
228  // update the index mapping
229  size_t next = _ivMap.size();
230  for (HyperGraph::VertexSet::iterator it = vset.begin(); it != vset.end(); ++it) {
232  if (! v->fixed()){
233  if (! v->marginalized()){
234  v->setHessianIndex(next);
235  _ivMap.push_back(v);
236  newVertices.push_back(v);
237  _activeVertices.push_back(v);
238  next++;
239  }
240  else // not supported right now
241  abort();
242  }
243  else {
244  v->setHessianIndex(-1);
245  }
246  }
247  //cerr << "updating index mapping done." << endl;
248 
249  // backup the tempindex and prepare sorting structure
250 #ifdef _MSC_VER
251  VertexBackup* backupIdx = new VertexBackup[_touchedVertices.size()];
252 #else
253  VertexBackup backupIdx[_touchedVertices.size()];
254 #endif
255  memset(backupIdx, 0, sizeof(VertexBackup) * _touchedVertices.size());
256  int idx = 0;
257  for (HyperGraph::VertexSet::iterator it = _touchedVertices.begin(); it != _touchedVertices.end(); ++it) {
258  OptimizableGraph::Vertex* v = static_cast<OptimizableGraph::Vertex*>(*it);
259  backupIdx[idx].hessianIndex = v->hessianIndex();
260  backupIdx[idx].vertex = v;
261  backupIdx[idx].hessianData = v->hessianData();
262  ++idx;
263  }
264  sort(backupIdx, backupIdx + _touchedVertices.size()); // sort according to the hessianIndex which is the same order as used later by the optimizer
265  for (int i = 0; i < idx; ++i) {
266  backupIdx[i].vertex->setHessianIndex(i);
267  }
268  //cerr << "backup tempindex done." << endl;
269 
270  // building the structure of the update
271  _updateMat.clear(true); // get rid of the old matrix structure
272  _updateMat.rowBlockIndices().clear();
273  _updateMat.colBlockIndices().clear();
274  _updateMat.blockCols().clear();
275 
276  // placing the current stuff in _updateMat
277  MatrixXd* lastBlock = 0;
278  int sizePoses = 0;
279  for (int i = 0; i < idx; ++i) {
280  OptimizableGraph::Vertex* v = backupIdx[i].vertex;
281  int dim = v->dimension();
282  sizePoses+=dim;
283  _updateMat.rowBlockIndices().push_back(sizePoses);
284  _updateMat.colBlockIndices().push_back(sizePoses);
286  int ind = v->hessianIndex();
287  //cerr << PVAR(ind) << endl;
288  if (ind >= 0) {
289  MatrixXd* m = _updateMat.block(ind, ind, true);
290  v->mapHessianMemory(m->data());
291  lastBlock = m;
292  }
293  }
294  lastBlock->diagonal().array() += 1e-6; // HACK to get Eigen value > 0
295 
296 
297  for (HyperGraph::EdgeSet::const_iterator it = eset.begin(); it != eset.end(); ++it) {
298  OptimizableGraph::Edge* e = static_cast<OptimizableGraph::Edge*>(*it);
299  OptimizableGraph::Vertex* v1 = (OptimizableGraph::Vertex*) e->vertices()[0];
300  OptimizableGraph::Vertex* v2 = (OptimizableGraph::Vertex*) e->vertices()[1];
301 
302  int ind1 = v1->hessianIndex();
303  if (ind1 == -1)
304  continue;
305  int ind2 = v2->hessianIndex();
306  if (ind2 == -1)
307  continue;
308  bool transposedBlock = ind1 > ind2;
309  if (transposedBlock) // make sure, we allocate the upper triangular block
310  swap(ind1, ind2);
311 
312  MatrixXd* m = _updateMat.block(ind1, ind2, true);
313  e->mapHessianMemory(m->data(), 0, 1, transposedBlock);
314  }
315 
316  // build the system into _updateMat
317  for (HyperGraph::EdgeSet::iterator it = eset.begin(); it != eset.end(); ++it) {
318  OptimizableGraph::Edge * e = static_cast<OptimizableGraph::Edge*>(*it);
319  e->computeError();
320  }
321  for (HyperGraph::EdgeSet::iterator it = eset.begin(); it != eset.end(); ++it) {
322  OptimizableGraph::Edge* e = static_cast<OptimizableGraph::Edge*>(*it);
323  e->linearizeOplus(jacobianWorkspace());
324  e->constructQuadraticForm();
325  }
326 
327  // restore the original data for the vertex
328  for (int i = 0; i < idx; ++i) {
329  backupIdx[i].vertex->setHessianIndex(backupIdx[i].hessianIndex);
330  if (backupIdx[i].hessianData)
331  backupIdx[i].vertex->mapHessianMemory(backupIdx[i].hessianData);
332  }
333 
334  // update the structure of the real block matrix
335  bool solverStatus = _algorithm->updateStructure(newVertices, eset);
336 
337  bool updateStatus = computeCholeskyUpdate();
338  if (! updateStatus) {
339  cerr << "Error while computing update" << endl;
340  }
341 
342  cholmod_sparse* updateAsSparseFactor = cholmod_factor_to_sparse(_cholmodFactor, &_cholmodCommon);
343 
344  // convert CCS update by permuting back to the permutation of L
345  if (updateAsSparseFactor->nzmax > _permutedUpdate->nzmax) {
346  //cerr << "realloc _permutedUpdate" << endl;
347  cholmod_reallocate_triplet(updateAsSparseFactor->nzmax, _permutedUpdate, &_cholmodCommon);
348  }
349  _permutedUpdate->nnz = 0;
350  _permutedUpdate->nrow = _permutedUpdate->ncol = _L->n;
351  {
352  int* Ap = (int*)updateAsSparseFactor->p;
353  int* Ai = (int*)updateAsSparseFactor->i;
354  double* Ax = (double*)updateAsSparseFactor->x;
355  int* Bj = (int*)_permutedUpdate->j;
356  int* Bi = (int*)_permutedUpdate->i;
357  double* Bx = (double*)_permutedUpdate->x;
358  for (size_t c = 0; c < updateAsSparseFactor->ncol; ++c) {
359  const int& rbeg = Ap[c];
360  const int& rend = Ap[c+1];
361  int cc = c / slamDimension;
362  int coff = c % slamDimension;
363  const int& cbase = backupIdx[cc].vertex->colInHessian();
364  const int& ccol = _perm(cbase + coff);
365  for (int j = rbeg; j < rend; j++) {
366  const int& r = Ai[j];
367  const double& val = Ax[j];
368 
369  int rr = r / slamDimension;
370  int roff = r % slamDimension;
371  const int& rbase = backupIdx[rr].vertex->colInHessian();
372 
373  int row = _perm(rbase + roff);
374  int col = ccol;
375  if (col > row) // lower triangular entry
376  swap(col, row);
377  Bi[_permutedUpdate->nnz] = row;
378  Bj[_permutedUpdate->nnz] = col;
379  Bx[_permutedUpdate->nnz] = val;
380  ++_permutedUpdate->nnz;
381  }
382  }
383  }
384  cholmod_free_sparse(&updateAsSparseFactor, &_cholmodCommon);
385 #ifdef _MSC_VER
386  delete[] backupIdx;
387 #endif
388 
389 #if 0
390  cholmod_sparse* updatePermuted = cholmod_triplet_to_sparse(_permutedUpdate, _permutedUpdate->nnz, &_cholmodCommon);
391  //writeCCSMatrix("update-permuted.txt", updatePermuted->nrow, updatePermuted->ncol, (int*)updatePermuted->p, (int*)updatePermuted->i, (double*)updatePermuted->x, false);
392  _solverInterface->choleskyUpdate(updatePermuted);
393  cholmod_free_sparse(&updatePermuted, &_cholmodCommon);
394 #else
397 #endif
398 
399  return solverStatus;
400  }
const std::vector< int > & rowBlockIndices() const
indices of the row blocks
VertexContainer _ivMap
VertexContainer _activeVertices
sorted according to VertexIDCompare
virtual int choleskyUpdate(cholmod_sparse *update)=0
virtual bool updateStructure(const std::vector< HyperGraph::Vertex * > &vset, const HyperGraph::EdgeSet &edges)=0
SparseMatrixBlock * block(int r, int c, bool alloc=false)
returns the block at location r,c. if alloc=true he block is created if it does not exist ...
void clear(bool dealloc=false)
this zeroes all the blocks. If dealloc=true the blocks are removed from memory
JacobianWorkspace & jacobianWorkspace()
the workspace for storing the Jacobians of the graph
const std::vector< int > & colBlockIndices() const
indices of the column blocks
class G2O_CORE_API Vertex
class G2O_CORE_API Edge
SparseBlockMatrix< Eigen::MatrixXd > _updateMat
EdgeContainer _activeEdges
sorted according to EdgeIDCompare
std::map< int, SparseMatrixBlock * > IntBlockMap
const std::vector< IntBlockMap > & blockCols() const
the block matrices per block-column
LinearSolverCholmodOnlineInterface * _solverInterface
virtual bool updateInitialization(HyperGraph::VertexSet &vset, HyperGraph::EdgeSet &eset)
OptimizationAlgorithm * _algorithm

Member Data Documentation

cholmod_common g2o::SparseOptimizerIncremental::_cholmodCommon
protected

Definition at line 44 of file graph_optimizer_sparse_incremental.h.

cholmod_factor* g2o::SparseOptimizerIncremental::_cholmodFactor
protected

Definition at line 46 of file graph_optimizer_sparse_incremental.h.

CholmodExt* g2o::SparseOptimizerIncremental::_cholmodSparse
protected

Definition at line 45 of file graph_optimizer_sparse_incremental.h.

Eigen::VectorXi g2o::SparseOptimizerIncremental::_cmember
protected

Definition at line 53 of file graph_optimizer_sparse_incremental.h.

cholmod_factor* g2o::SparseOptimizerIncremental::_L
protected

Definition at line 48 of file graph_optimizer_sparse_incremental.h.

Eigen::VectorXi g2o::SparseOptimizerIncremental::_perm
protected

Definition at line 52 of file graph_optimizer_sparse_incremental.h.

cholmod_triplet* g2o::SparseOptimizerIncremental::_permutedUpdate
protected

Definition at line 47 of file graph_optimizer_sparse_incremental.h.

CholmodExt* g2o::SparseOptimizerIncremental::_permutedUpdateAsSparse
protected

Definition at line 56 of file graph_optimizer_sparse_incremental.h.

LinearSolverCholmodOnlineInterface* g2o::SparseOptimizerIncremental::_solverInterface
protected

Definition at line 49 of file graph_optimizer_sparse_incremental.h.

HyperGraph::VertexSet g2o::SparseOptimizerIncremental::_touchedVertices
protected

Definition at line 51 of file graph_optimizer_sparse_incremental.h.

Eigen::VectorXi g2o::SparseOptimizerIncremental::_tripletWorkspace
protected

Definition at line 55 of file graph_optimizer_sparse_incremental.h.

SparseBlockMatrix<Eigen::MatrixXd> g2o::SparseOptimizerIncremental::_updateMat
protected

Definition at line 43 of file graph_optimizer_sparse_incremental.h.


The documentation for this class was generated from the following files: