g2o
sparse_optimizer.cpp
Go to the documentation of this file.
1 // g2o - General Graph Optimization
2 // Copyright (C) 2011 R. Kuemmerle, G. Grisetti, W. Burgard
3 // All rights reserved.
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 // * Redistributions of source code must retain the above copyright notice,
10 // this list of conditions and the following disclaimer.
11 // * Redistributions in binary form must reproduce the above copyright
12 // notice, this list of conditions and the following disclaimer in the
13 // documentation and/or other materials provided with the distribution.
14 //
15 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
16 // IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17 // TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
18 // PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19 // HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
21 // TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 
27 #include "sparse_optimizer.h"
28 
29 #include <iostream>
30 #include <iomanip>
31 #include <algorithm>
32 #include <iterator>
33 #include <cassert>
34 #include <algorithm>
35 
36 #include "estimate_propagator.h"
37 #include "optimization_algorithm.h"
38 #include "batch_stats.h"
39 #include "hyper_graph_action.h"
40 #include "robust_kernel.h"
41 #include "g2o/stuff/timeutil.h"
42 #include "g2o/stuff/macros.h"
43 #include "g2o/stuff/misc.h"
44 #include "g2o/config.h"
45 
46 namespace g2o{
47  using namespace std;
48 
49 
51  _forceStopFlag(0), _verbose(false), _algorithm(0), _computeBatchStatistics(false)
52  {
54  }
55 
57  delete _algorithm;
59  }
60 
62  {
63  // call the callbacks in case there is something registered
65  if (actions.size() > 0) {
66  for (HyperGraphActionSet::iterator it = actions.begin(); it != actions.end(); ++it)
67  (*(*it))(this);
68  }
69 
70 # ifdef G2O_OPENMP
71 # pragma omp parallel for default (shared) if (_activeEdges.size() > 50)
72 # endif
73  for (int k = 0; k < static_cast<int>(_activeEdges.size()); ++k) {
75  e->computeError();
76  }
77 
78 # ifndef NDEBUG
79  for (int k = 0; k < static_cast<int>(_activeEdges.size()); ++k) {
81  bool hasNan = arrayHasNaN(e->errorData(), e->dimension());
82  if (hasNan) {
83  cerr << "computeActiveErrors(): found NaN in error for edge " << e << endl;
84  }
85  }
86 # endif
87 
88  }
89 
91  {
92  double chi = 0.0;
93  for (EdgeContainer::const_iterator it = _activeEdges.begin(); it != _activeEdges.end(); ++it) {
94  const OptimizableGraph::Edge* e = *it;
95  chi += e->chi2();
96  }
97  return chi;
98  }
99 
101  {
102  Vector3D rho;
103  double chi = 0.0;
104  for (EdgeContainer::const_iterator it = _activeEdges.begin(); it != _activeEdges.end(); ++it) {
105  const OptimizableGraph::Edge* e = *it;
106  if (e->robustKernel()) {
107  e->robustKernel()->robustify(e->chi2(), rho);
108  chi += rho[0];
109  }
110  else
111  chi += e->chi2();
112  }
113  return chi;
114  }
115 
117  if (vertices().empty())
118  return 0;
119 
120  int maxDim=0;
121  for (HyperGraph::VertexIDMap::iterator it=vertices().begin(); it!=vertices().end(); ++it){
122  OptimizableGraph::Vertex* v=static_cast<OptimizableGraph::Vertex*>(it->second);
123  maxDim=std::max(maxDim,v->dimension());
124  }
125 
127  for (HyperGraph::VertexIDMap::iterator it=vertices().begin(); it!=vertices().end(); ++it){
128  OptimizableGraph::Vertex* v=static_cast<OptimizableGraph::Vertex*>(it->second);
129  if (v->dimension()==maxDim){
130  rut=v;
131  break;
132  }
133  }
134  return rut;
135  }
136 
138  {
139  if (vertices().empty())
140  return false;
141 
142  int maxDim=0;
143  for (HyperGraph::VertexIDMap::iterator it=vertices().begin(); it!=vertices().end(); ++it){
144  OptimizableGraph::Vertex* v=static_cast<OptimizableGraph::Vertex*>(it->second);
145  maxDim = std::max(maxDim,v->dimension());
146  }
147 
148  for (HyperGraph::VertexIDMap::iterator it=vertices().begin(); it!=vertices().end(); ++it){
149  OptimizableGraph::Vertex* v=static_cast<OptimizableGraph::Vertex*>(it->second);
150  if (v->dimension() == maxDim) {
151  // test for fixed vertex
152  if (v->fixed()) {
153  return false;
154  }
155  // test for full dimension prior
156  for (HyperGraph::EdgeSet::const_iterator eit = v->edges().begin(); eit != v->edges().end(); ++eit) {
157  OptimizableGraph::Edge* e = static_cast<OptimizableGraph::Edge*>(*eit);
158  if (e->vertices().size() == 1 && e->dimension() == maxDim)
159  return false;
160  }
161  }
162  }
163  return true;
164  }
165 
167  if (! vlist.size()){
168  _ivMap.clear();
169  return false;
170  }
171 
172  _ivMap.resize(vlist.size());
173  size_t i = 0;
174  for (int k=0; k<2; k++)
175  for (VertexContainer::iterator it=vlist.begin(); it!=vlist.end(); ++it){
176  OptimizableGraph::Vertex* v = *it;
177  if (! v->fixed()){
178  if (static_cast<int>(v->marginalized()) == k){
179  v->setHessianIndex(i);
180  _ivMap[i]=v;
181  i++;
182  }
183  }
184  else {
185  v->setHessianIndex(-1);
186  }
187  }
188  _ivMap.resize(i);
189  return true;
190  }
191 
193  for (size_t i=0; i<_ivMap.size(); ++i){
194  _ivMap[i]->setHessianIndex(-1);
195  _ivMap[i]=0;
196  }
197  }
198 
201  for (VertexIDMap::iterator it=vertices().begin(); it!=vertices().end(); ++it)
202  vset.insert(it->second);
203  return initializeOptimization(vset,level);
204  }
205 
207  if (edges().size() == 0) {
208  cerr << __PRETTY_FUNCTION__ << ": Attempt to initialize an empty graph" << endl;
209  return false;
210  }
211  preIteration(-1);
212  bool workspaceAllocated = _jacobianWorkspace.allocate(); (void) workspaceAllocated;
213  assert(workspaceAllocated && "Error while allocating memory for the Jacobians");
215  _activeVertices.clear();
216  _activeVertices.reserve(vset.size());
217  _activeEdges.clear();
218  set<Edge*> auxEdgeSet; // temporary structure to avoid duplicates
219  for (HyperGraph::VertexSet::iterator it=vset.begin(); it!=vset.end(); ++it){
221  const OptimizableGraph::EdgeSet& vEdges=v->edges();
222  // count if there are edges in that level. If not remove from the pool
223  int levelEdges=0;
224  for (OptimizableGraph::EdgeSet::const_iterator it=vEdges.begin(); it!=vEdges.end(); ++it){
225  OptimizableGraph::Edge* e=reinterpret_cast<OptimizableGraph::Edge*>(*it);
226  if (level < 0 || e->level() == level) {
227 
228  bool allVerticesOK = true;
229  for (vector<HyperGraph::Vertex*>::const_iterator vit = e->vertices().begin(); vit != e->vertices().end(); ++vit) {
230  if (vset.find(*vit) == vset.end()) {
231  allVerticesOK = false;
232  break;
233  }
234  }
235  if (allVerticesOK && !e->allVerticesFixed()) {
236  auxEdgeSet.insert(e);
237  levelEdges++;
238  }
239 
240  }
241  }
242  if (levelEdges){
243  _activeVertices.push_back(v);
244 
245  // test for NANs in the current estimate if we are debugging
246 # ifndef NDEBUG
247  int estimateDim = v->estimateDimension();
248  if (estimateDim > 0) {
249  VectorXD estimateData(estimateDim);
250  if (v->getEstimateData(estimateData.data()) == true) {
251  int k;
252  bool hasNan = arrayHasNaN(estimateData.data(), estimateDim, &k);
253  if (hasNan)
254  cerr << __PRETTY_FUNCTION__ << ": Vertex " << v->id() << " contains a nan entry at index " << k << endl;
255  }
256  }
257 # endif
258 
259  }
260  }
261 
262  _activeEdges.reserve(auxEdgeSet.size());
263  for (set<Edge*>::iterator it = auxEdgeSet.begin(); it != auxEdgeSet.end(); ++it)
264  _activeEdges.push_back(*it);
265 
267  bool indexMappingStatus = buildIndexMapping(_activeVertices);
268  postIteration(-1);
269  return indexMappingStatus;
270  }
271 
273  preIteration(-1);
274  bool workspaceAllocated = _jacobianWorkspace.allocate(); (void) workspaceAllocated;
275  assert(workspaceAllocated && "Error while allocating memory for the Jacobians");
277  _activeVertices.clear();
278  _activeEdges.clear();
279  _activeEdges.reserve(eset.size());
280  set<Vertex*> auxVertexSet; // temporary structure to avoid duplicates
281  for (HyperGraph::EdgeSet::iterator it=eset.begin(); it!=eset.end(); ++it){
283  if (e->numUndefinedVertices())
284  continue;
285  for (vector<HyperGraph::Vertex*>::const_iterator vit = e->vertices().begin(); vit != e->vertices().end(); ++vit) {
286  auxVertexSet.insert(static_cast<OptimizableGraph::Vertex*>(*vit));
287  }
288  _activeEdges.push_back(reinterpret_cast<OptimizableGraph::Edge*>(*it));
289  }
290 
291  _activeVertices.reserve(auxVertexSet.size());
292  for (set<Vertex*>::iterator it = auxVertexSet.begin(); it != auxVertexSet.end(); ++it)
293  _activeVertices.push_back(*it);
294 
296  bool indexMappingStatus = buildIndexMapping(_activeVertices);
297  postIteration(-1);
298  return indexMappingStatus;
299  }
300 
302  for (VertexIDMap::iterator it=vertices().begin(); it!=vertices().end(); ++it) {
303  OptimizableGraph::Vertex* v = static_cast<OptimizableGraph::Vertex*>(it->second);
304  v->setToOrigin();
305  }
306  }
307 
309  {
310  EstimatePropagator::PropagateCost costFunction(this);
311  computeInitialGuess(costFunction);
312  }
313 
315  {
317  std::set<Vertex*> backupVertices;
318  HyperGraph::VertexSet fixedVertices; // these are the root nodes where to start the initialization
319  for (EdgeContainer::iterator it = _activeEdges.begin(); it != _activeEdges.end(); ++it) {
320  OptimizableGraph::Edge* e = *it;
321  for (size_t i = 0; i < e->vertices().size(); ++i) {
322  OptimizableGraph::Vertex* v = static_cast<OptimizableGraph::Vertex*>(e->vertex(i));
323  if (!v)
324  continue;
325  if (v->fixed())
326  fixedVertices.insert(v);
327  else { // check for having a prior which is able to fully initialize a vertex
328  for (EdgeSet::const_iterator vedgeIt = v->edges().begin(); vedgeIt != v->edges().end(); ++vedgeIt) {
329  OptimizableGraph::Edge* vedge = static_cast<OptimizableGraph::Edge*>(*vedgeIt);
330  if (vedge->vertices().size() == 1 && vedge->initialEstimatePossible(emptySet, v) > 0.) {
331  //cerr << "Initialize with prior for " << v->id() << endl;
332  vedge->initialEstimate(emptySet, v);
333  fixedVertices.insert(v);
334  }
335  }
336  }
337  if (v->hessianIndex() == -1) {
338  std::set<Vertex*>::const_iterator foundIt = backupVertices.find(v);
339  if (foundIt == backupVertices.end()) {
340  v->push();
341  backupVertices.insert(v);
342  }
343  }
344  }
345  }
346 
347  EstimatePropagator estimatePropagator(this);
348  estimatePropagator.propagate(fixedVertices, costFunction);
349 
350  // restoring the vertices that should not be initialized
351  for (std::set<Vertex*>::iterator it = backupVertices.begin(); it != backupVertices.end(); ++it) {
352  Vertex* v = *it;
353  v->pop();
354  }
355  if (verbose()) {
357  cerr << "iteration= -1\t chi2= " << activeChi2()
358  << "\t time= 0.0"
359  << "\t cumTime= 0.0"
360  << "\t (using initial guess from " << costFunction.name() << ")" << endl;
361  }
362  }
363 
364  int SparseOptimizer::optimize(int iterations, bool online)
365  {
366  if (_ivMap.size() == 0) {
367  cerr << __PRETTY_FUNCTION__ << ": 0 vertices to optimize, maybe forgot to call initializeOptimization()" << endl;
368  return -1;
369  }
370 
371  int cjIterations=0;
372  double cumTime=0;
373  bool ok=true;
374 
375  ok = _algorithm->init(online);
376  if (! ok) {
377  cerr << __PRETTY_FUNCTION__ << " Error while initializing" << endl;
378  return -1;
379  }
380 
381  _batchStatistics.clear();
383  _batchStatistics.resize(iterations);
384 
385  OptimizationAlgorithm::SolverResult result = OptimizationAlgorithm::OK;
386  for (int i=0; i<iterations && ! terminate() && ok; i++){
387  preIteration(i);
388 
392  cstat.iteration = i;
393  cstat.numEdges = _activeEdges.size();
394  cstat.numVertices = _activeVertices.size();
395  }
396 
397  double ts = get_monotonic_time();
398  result = _algorithm->solve(i, online);
399  ok = ( result == OptimizationAlgorithm::OK );
400 
401  bool errorComputed = false;
404  errorComputed = true;
406  _batchStatistics[i].timeIteration = get_monotonic_time()-ts;
407  }
408 
409  if (verbose()){
410  double dts = get_monotonic_time()-ts;
411  cumTime += dts;
412  if (! errorComputed)
414  cerr << "iteration= " << i
415  << "\t chi2= " << FIXED(activeRobustChi2())
416  << "\t time= " << dts
417  << "\t cumTime= " << cumTime
418  << "\t edges= " << _activeEdges.size();
419  _algorithm->printVerbose(cerr);
420  cerr << endl;
421  }
422  ++cjIterations;
423  postIteration(i);
424  }
425  if (result == OptimizationAlgorithm::Fail) {
426  return 0;
427  }
428  return cjIterations;
429  }
430 
431  void SparseOptimizer::update(const double* update)
432  {
433  // update the graph by calling oplus on the vertices
434  for (size_t i=0; i < _ivMap.size(); ++i) {
436 #ifndef NDEBUG
437  bool hasNan = arrayHasNaN(update, v->dimension());
438  if (hasNan)
439  cerr << __PRETTY_FUNCTION__ << ": Update contains a nan for vertex " << v->id() << endl;
440 #endif
441  v->oplus(update);
442  update += v->dimension();
443  }
444  }
445 
447  {
448  if ((_computeBatchStatistics == true) && (computeBatchStatistics == false)) {
450  _batchStatistics.clear();
451  }
453  }
454 
456  {
457  std::vector<HyperGraph::Vertex*> newVertices;
458  newVertices.reserve(vset.size());
459  _activeVertices.reserve(_activeVertices.size() + vset.size());
460  _activeEdges.reserve(_activeEdges.size() + eset.size());
461  for (HyperGraph::EdgeSet::iterator it = eset.begin(); it != eset.end(); ++it) {
462  OptimizableGraph::Edge* e = static_cast<OptimizableGraph::Edge*>(*it);
463  if (!e->allVerticesFixed()) _activeEdges.push_back(e);
464  }
465 
466  // update the index mapping
467  size_t next = _ivMap.size();
468  for (HyperGraph::VertexSet::iterator it = vset.begin(); it != vset.end(); ++it) {
470  if (! v->fixed()){
471  if (! v->marginalized()){
472  v->setHessianIndex(next);
473  _ivMap.push_back(v);
474  newVertices.push_back(v);
475  _activeVertices.push_back(v);
476  next++;
477  }
478  else // not supported right now
479  abort();
480  }
481  else {
482  v->setHessianIndex(-1);
483  }
484  }
485 
486  //if (newVertices.size() != vset.size())
487  //cerr << __PRETTY_FUNCTION__ << ": something went wrong " << PVAR(vset.size()) << " " << PVAR(newVertices.size()) << endl;
488  return _algorithm->updateStructure(newVertices, eset);
489  }
490 
492  {
493  // sort vector structures to get deterministic ordering based on IDs
494  sort(_activeVertices.begin(), _activeVertices.end(), VertexIDCompare());
495  sort(_activeEdges.begin(), _activeEdges.end(), EdgeIDCompare());
496  }
497 
499  _ivMap.clear();
500  _activeVertices.clear();
501  _activeEdges.clear();
503  }
504 
505  SparseOptimizer::VertexContainer::const_iterator SparseOptimizer::findActiveVertex(const OptimizableGraph::Vertex* v) const
506  {
507  VertexContainer::const_iterator lower = lower_bound(_activeVertices.begin(), _activeVertices.end(), v, VertexIDCompare());
508  if (lower == _activeVertices.end())
509  return _activeVertices.end();
510  if ((*lower) == v)
511  return lower;
512  return _activeVertices.end();
513  }
514 
515  SparseOptimizer::EdgeContainer::const_iterator SparseOptimizer::findActiveEdge(const OptimizableGraph::Edge* e) const
516  {
517  EdgeContainer::const_iterator lower = lower_bound(_activeEdges.begin(), _activeEdges.end(), e, EdgeIDCompare());
518  if (lower == _activeEdges.end())
519  return _activeEdges.end();
520  if ((*lower) == e)
521  return lower;
522  return _activeEdges.end();
523  }
524 
526  {
527  for (VertexContainer::iterator it = vlist.begin(); it != vlist.end(); ++it)
528  (*it)->push();
529  }
530 
532  {
533  for (VertexContainer::iterator it = vlist.begin(); it != vlist.end(); ++it)
534  (*it)->pop();
535  }
536 
538  {
539  for (HyperGraph::VertexSet::iterator it = vlist.begin(); it != vlist.end(); ++it) {
540  OptimizableGraph::Vertex* v = dynamic_cast<OptimizableGraph::Vertex*>(*it);
541  if (v)
542  v->push();
543  else
544  cerr << __FUNCTION__ << ": FATAL PUSH SET" << endl;
545  }
546  }
547 
549  {
550  for (HyperGraph::VertexSet::iterator it = vlist.begin(); it != vlist.end(); ++it){
551  OptimizableGraph::Vertex* v = dynamic_cast<OptimizableGraph::Vertex*> (*it);
552  if (v)
553  v->pop();
554  else
555  cerr << __FUNCTION__ << ": FATAL POP SET" << endl;
556  }
557  }
558 
560  {
561  for (VertexContainer::iterator it = vlist.begin(); it != vlist.end(); ++it)
562  (*it)->discardTop();
563  }
564 
566  {
567  _verbose = verbose;
568  }
569 
571  {
572  if (_algorithm) // reset the optimizer for the formerly used solver
575  if (_algorithm)
576  _algorithm->setOptimizer(this);
577  }
578 
579  bool SparseOptimizer::computeMarginals(SparseBlockMatrix<MatrixXD>& spinv, const std::vector<std::pair<int, int> >& blockIndices){
580  return _algorithm->computeMarginals(spinv, blockIndices);
581  }
582 
584  {
585  _forceStopFlag=flag;
586  }
587 
589  {
590  OptimizableGraph::Vertex* vv = static_cast<OptimizableGraph::Vertex*>(v);
591  if (vv->hessianIndex() >= 0) {
593  _ivMap.clear();
594  }
595  return HyperGraph::removeVertex(v, detach);
596  }
597 
599  {
600  std::pair<HyperGraphActionSet::iterator, bool> insertResult = _graphActions[AT_COMPUTEACTIVERROR].insert(action);
601  return insertResult.second;
602  }
603 
605  {
606  return _graphActions[AT_COMPUTEACTIVERROR].erase(action) > 0;
607  }
608 
610  {
612  }
613 
615  {
617  }
618 
620  {
622  }
623 
624 } // end namespace
virtual void printVerbose(std::ostream &os) const
virtual bool updateInitialization(HyperGraph::VertexSet &vset, HyperGraph::EdgeSet &eset)
virtual void computeInitialGuess()
double get_monotonic_time()
Definition: timeutil.cpp:113
virtual SolverResult solve(int iteration, bool online=false)=0
int id() const
returns the id
Definition: hyper_graph.h:148
statistics about the optimization
Definition: batch_stats.h:40
VertexContainer _ivMap
const Vertex * vertex(size_t i) const
Definition: hyper_graph.h:186
bool terminate()
if external stop flag is given, return its state. False otherwise
#define __PRETTY_FUNCTION__
Definition: macros.h:89
void setHessianIndex(int ti)
set the temporary index of the vertex in the parameter blocks
int numVertices
how many vertices are involved
Definition: batch_stats.h:43
virtual bool getEstimateData(double *estimate) const
some general case utility functions
VertexContainer _activeVertices
sorted according to VertexIDCompare
virtual bool removeVertex(Vertex *v, bool detach=false)
removes a vertex from the graph. Returns true on success (vertex was present)
virtual const double * errorData() const =0
returns the error vector cached after calling the computeError;
Eigen::Matrix< double, 3, 1, Eigen::ColMajor > Vector3D
Definition: eigen_types.h:46
int dimension() const
returns the dimensions of the error function
std::vector< Vertex * > VertexContainer
Definition: hyper_graph.h:139
void setComputeBatchStatistics(bool computeBatchStatistics)
virtual bool updateStructure(const std::vector< HyperGraph::Vertex * > &vset, const HyperGraph::EdgeSet &edges)=0
bool removeComputeErrorAction(HyperGraphAction *action)
remove an action that should no longer be execured before computing the error vectors ...
virtual bool allVerticesFixed() const =0
std::set< Vertex * > VertexSet
Definition: hyper_graph.h:136
virtual double chi2() const =0
computes the chi2 based on the cached error value, only valid after computeError has been called...
propagation of an initial guess
int optimize(int iterations, bool online=false)
virtual bool init(bool online=false)=0
virtual double initialEstimatePossible(const OptimizableGraph::VertexSet &from, OptimizableGraph::Vertex *to)
int hessianIndex() const
temporary index of this node in the parameter vector obtained from linearization
int iteration
which iteration
Definition: batch_stats.h:42
virtual void setToOrigin()
virtual void robustify(double squaredError, Vector3D &rho) const =0
virtual void postIteration(int)
called at the end of an iteration (argument is the number of the iteration)
const VertexIDMap & vertices() const
Definition: hyper_graph.h:225
bool arrayHasNaN(const double *array, int size, int *nanIndex=0)
Definition: misc.h:177
utility functions for handling time related stuff
std::set< Edge * > EdgeSet
Definition: hyper_graph.h:135
virtual Vertex * findGauge()
finds a gauge in the graph to remove the undefined dof.
int dimension() const
dimension of the estimated state belonging to this node
int numUndefinedVertices() const
Definition: hyper_graph.cpp:59
const VertexContainer & vertices() const
Definition: hyper_graph.h:178
const EdgeSet & edges() const
returns the set of hyper-edges that are leaving/entering in this vertex
Definition: hyper_graph.h:151
void setVerbose(bool verbose)
virtual int estimateDimension() const
RobustKernel * robustKernel() const
if NOT NULL, error of this edge will be robustifed with the kernel
virtual void initialEstimate(const OptimizableGraph::VertexSet &from, OptimizableGraph::Vertex *to)=0
const EdgeSet & edges() const
Definition: hyper_graph.h:230
VertexContainer::const_iterator findActiveVertex(const OptimizableGraph::Vertex *v) const
void setForceStopFlag(bool *flag)
virtual void computeError()=0
void setAlgorithm(OptimizationAlgorithm *algorithm)
int numEdges
how many edges
Definition: batch_stats.h:44
BatchStatisticsContainer _batchStatistics
global statistics of the optimizer, e.g., timing, num-non-zeros
void push()
push all the active vertices onto a stack
void setOptimizer(SparseOptimizer *optimizer)
virtual void push()=0
backup the position of the vertex to a stack
EdgeContainer _activeEdges
sorted according to EdgeIDCompare
virtual const char * name() const
void propagate(OptimizableGraph::Vertex *v, const EstimatePropagator::PropagateCost &cost, const EstimatePropagator::PropagateAction &action=PropagateAction(), double maxDistance=std::numeric_limits< double >::max(), double maxEdgeCost=std::numeric_limits< double >::max())
cost for traversing along active edges in the optimizer
virtual void clear()
clears the graph and empties all structures.
virtual void pop()=0
restore the position of the vertex by retrieving the position from the stack
order vertices based on their ID
bool buildIndexMapping(SparseOptimizer::VertexContainer &vlist)
void pop()
pop (restore) the estimate of the active vertices from the stack
Protocol The SLAM executable accepts actions
Definition: protocol.txt:3
bool marginalized() const
true => this node is marginalized out during the optimization
order edges based on the internal ID, which is assigned to the edge in addEdge()
A general case Vertex for optimization.
bool addComputeErrorAction(HyperGraphAction *action)
add an action to be executed before the error vectors are computed
abstract Vertex, your types must derive from that one
Definition: hyper_graph.h:142
Eigen::Matrix< double, Eigen::Dynamic, 1, Eigen::ColMajor > VectorXD
Definition: eigen_types.h:48
void setToOrigin()
sets the node to the origin (used in the multilevel stuff)
bool computeBatchStatistics() const
EdgeContainer::const_iterator findActiveEdge(const OptimizableGraph::Edge *e) const
JacobianWorkspace _jacobianWorkspace
double activeRobustChi2() const
virtual void preIteration(int)
called at the beginning of an iteration (argument is the number of the iteration) ...
virtual bool removeVertex(HyperGraph::Vertex *v, bool detach=false)
bool fixed() const
true => this node is fixed during the optimization
void discardTop()
same as above, but for the active vertices
std::set< HyperGraphAction * > HyperGraphActionSet
virtual bool initializeOptimization(HyperGraph::EdgeSet &eset)
Generic interface for a non-linear solver operating on a graph.
std::vector< HyperGraphActionSet > _graphActions
bool computeMarginals(SparseBlockMatrix< MatrixXD > &spinv, const std::vector< std::pair< int, int > > &blockIndices)
bool verbose() const
verbose information during optimization
const OptimizationAlgorithm * algorithm() const
the solver used by the optimizer
Sparse matrix which uses blocks.
static void setGlobalStats(G2OBatchStatistics *b)
Definition: batch_stats.cpp:85
OptimizationAlgorithm * _algorithm
Abstract action that operates on an entire graph.
virtual bool computeMarginals(SparseBlockMatrix< MatrixXD > &spinv, const std::vector< std::pair< int, int > > &blockIndices)=0
double activeChi2() const