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 "../stuff/timeutil.h"
42 #include "../stuff/macros.h"
43 #include "../stuff/misc.h"
44 #include "../../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  Eigen::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  bool workspaceAllocated = _jacobianWorkspace.allocate(); (void) workspaceAllocated;
212  assert(workspaceAllocated && "Error while allocating memory for the Jacobians");
214  _activeVertices.clear();
215  _activeVertices.reserve(vset.size());
216  _activeEdges.clear();
217  set<Edge*> auxEdgeSet; // temporary structure to avoid duplicates
218  for (HyperGraph::VertexSet::iterator it=vset.begin(); it!=vset.end(); ++it){
220  const OptimizableGraph::EdgeSet& vEdges=v->edges();
221  // count if there are edges in that level. If not remove from the pool
222  int levelEdges=0;
223  for (OptimizableGraph::EdgeSet::const_iterator it=vEdges.begin(); it!=vEdges.end(); ++it){
224  OptimizableGraph::Edge* e=reinterpret_cast<OptimizableGraph::Edge*>(*it);
225  if (level < 0 || e->level() == level) {
226 
227  bool allVerticesOK = true;
228  for (vector<HyperGraph::Vertex*>::const_iterator vit = e->vertices().begin(); vit != e->vertices().end(); ++vit) {
229  if (vset.find(*vit) == vset.end()) {
230  allVerticesOK = false;
231  break;
232  }
233  }
234  if (allVerticesOK && !e->allVerticesFixed()) {
235  auxEdgeSet.insert(e);
236  levelEdges++;
237  }
238 
239  }
240  }
241  if (levelEdges){
242  _activeVertices.push_back(v);
243 
244  // test for NANs in the current estimate if we are debugging
245 # ifndef NDEBUG
246  int estimateDim = v->estimateDimension();
247  if (estimateDim > 0) {
248  Eigen::VectorXd estimateData(estimateDim);
249  if (v->getEstimateData(estimateData.data()) == true) {
250  int k;
251  bool hasNan = arrayHasNaN(estimateData.data(), estimateDim, &k);
252  if (hasNan)
253  cerr << __PRETTY_FUNCTION__ << ": Vertex " << v->id() << " contains a nan entry at index " << k << endl;
254  }
255  }
256 # endif
257 
258  }
259  }
260 
261  _activeEdges.reserve(auxEdgeSet.size());
262  for (set<Edge*>::iterator it = auxEdgeSet.begin(); it != auxEdgeSet.end(); ++it)
263  _activeEdges.push_back(*it);
264 
267  }
268 
270  bool workspaceAllocated = _jacobianWorkspace.allocate(); (void) workspaceAllocated;
271  assert(workspaceAllocated && "Error while allocating memory for the Jacobians");
273  _activeVertices.clear();
274  _activeEdges.clear();
275  _activeEdges.reserve(eset.size());
276  set<Vertex*> auxVertexSet; // temporary structure to avoid duplicates
277  for (HyperGraph::EdgeSet::iterator it=eset.begin(); it!=eset.end(); ++it){
279  for (vector<HyperGraph::Vertex*>::const_iterator vit = e->vertices().begin(); vit != e->vertices().end(); ++vit) {
280  auxVertexSet.insert(static_cast<OptimizableGraph::Vertex*>(*vit));
281  }
282  _activeEdges.push_back(reinterpret_cast<OptimizableGraph::Edge*>(*it));
283  }
284 
285  _activeVertices.reserve(auxVertexSet.size());
286  for (set<Vertex*>::iterator it = auxVertexSet.begin(); it != auxVertexSet.end(); ++it)
287  _activeVertices.push_back(*it);
288 
291  }
292 
294  for (VertexIDMap::iterator it=vertices().begin(); it!=vertices().end(); ++it) {
295  OptimizableGraph::Vertex* v = static_cast<OptimizableGraph::Vertex*>(it->second);
296  v->setToOrigin();
297  }
298  }
299 
301  {
302  EstimatePropagator::PropagateCost costFunction(this);
303  computeInitialGuess(costFunction);
304  }
305 
307  {
309  std::set<Vertex*> backupVertices;
310  HyperGraph::VertexSet fixedVertices; // these are the root nodes where to start the initialization
311  for (EdgeContainer::iterator it = _activeEdges.begin(); it != _activeEdges.end(); ++it) {
312  OptimizableGraph::Edge* e = *it;
313  for (size_t i = 0; i < e->vertices().size(); ++i) {
314  OptimizableGraph::Vertex* v = static_cast<OptimizableGraph::Vertex*>(e->vertex(i));
315  if (v->fixed())
316  fixedVertices.insert(v);
317  else { // check for having a prior which is able to fully initialize a vertex
318  for (EdgeSet::const_iterator vedgeIt = v->edges().begin(); vedgeIt != v->edges().end(); ++vedgeIt) {
319  OptimizableGraph::Edge* vedge = static_cast<OptimizableGraph::Edge*>(*vedgeIt);
320  if (vedge->vertices().size() == 1 && vedge->initialEstimatePossible(emptySet, v) > 0.) {
321  //cerr << "Initialize with prior for " << v->id() << endl;
322  vedge->initialEstimate(emptySet, v);
323  fixedVertices.insert(v);
324  }
325  }
326  }
327  if (v->hessianIndex() == -1) {
328  std::set<Vertex*>::const_iterator foundIt = backupVertices.find(v);
329  if (foundIt == backupVertices.end()) {
330  v->push();
331  backupVertices.insert(v);
332  }
333  }
334  }
335  }
336 
337  EstimatePropagator estimatePropagator(this);
338  estimatePropagator.propagate(fixedVertices, costFunction);
339 
340  // restoring the vertices that should not be initialized
341  for (std::set<Vertex*>::iterator it = backupVertices.begin(); it != backupVertices.end(); ++it) {
342  Vertex* v = *it;
343  v->pop();
344  }
345  if (verbose()) {
347  cerr << "iteration= -1\t chi2= " << activeChi2()
348  << "\t time= 0.0"
349  << "\t cumTime= 0.0"
350  << "\t (using initial guess from " << costFunction.name() << ")" << endl;
351  }
352  }
353 
354  int SparseOptimizer::optimize(int iterations, bool online)
355  {
356  if (_ivMap.size() == 0) {
357  cerr << __PRETTY_FUNCTION__ << ": 0 vertices to optimize, maybe forgot to call initializeOptimization()" << endl;
358  return -1;
359  }
360 
361  int cjIterations=0;
362  double cumTime=0;
363  bool ok=true;
364 
365  ok = _algorithm->init(online);
366  if (! ok) {
367  cerr << __PRETTY_FUNCTION__ << " Error while initializing" << endl;
368  return -1;
369  }
370 
371  _batchStatistics.clear();
373  _batchStatistics.resize(iterations);
374 
376  for (int i=0; i<iterations && ! terminate() && ok; i++){
377  preIteration(i);
378 
382  cstat.iteration = i;
383  cstat.numEdges = _activeEdges.size();
384  cstat.numVertices = _activeVertices.size();
385  }
386 
387  double ts = get_monotonic_time();
388  result = _algorithm->solve(i, online);
389  ok = ( result == OptimizationAlgorithm::OK );
390 
391  bool errorComputed = false;
394  errorComputed = true;
396  _batchStatistics[i].timeIteration = get_monotonic_time()-ts;
397  }
398 
399  if (verbose()){
400  double dts = get_monotonic_time()-ts;
401  cumTime += dts;
402  if (! errorComputed)
404  cerr << "iteration= " << i
405  << "\t chi2= " << FIXED(activeRobustChi2())
406  << "\t time= " << dts
407  << "\t cumTime= " << cumTime
408  << "\t edges= " << _activeEdges.size();
409  _algorithm->printVerbose(cerr);
410  cerr << endl;
411  }
412  ++cjIterations;
413  postIteration(i);
414  }
415  if (result == OptimizationAlgorithm::Fail) {
416  return 0;
417  }
418  return cjIterations;
419  }
420 
421 
422  void SparseOptimizer::update(const double* update)
423  {
424  // update the graph by calling oplus on the vertices
425  for (size_t i=0; i < _ivMap.size(); ++i) {
427 #ifndef NDEBUG
428  bool hasNan = arrayHasNaN(update, v->dimension());
429  if (hasNan)
430  cerr << __PRETTY_FUNCTION__ << ": Update contains a nan for vertex " << v->id() << endl;
431 #endif
432  v->oplus(update);
433  update += v->dimension();
434  }
435  }
436 
438  {
439  if ((_computeBatchStatistics == true) && (computeBatchStatistics == false)) {
441  _batchStatistics.clear();
442  }
444  }
445 
447  {
448  std::vector<HyperGraph::Vertex*> newVertices;
449  newVertices.reserve(vset.size());
450  _activeVertices.reserve(_activeVertices.size() + vset.size());
451  _activeEdges.reserve(_activeEdges.size() + eset.size());
452  for (HyperGraph::EdgeSet::iterator it = eset.begin(); it != eset.end(); ++it) {
453  OptimizableGraph::Edge* e = static_cast<OptimizableGraph::Edge*>(*it);
454  if (!e->allVerticesFixed()) _activeEdges.push_back(e);
455  }
456 
457  // update the index mapping
458  size_t next = _ivMap.size();
459  for (HyperGraph::VertexSet::iterator it = vset.begin(); it != vset.end(); ++it) {
461  if (! v->fixed()){
462  if (! v->marginalized()){
463  v->setHessianIndex(next);
464  _ivMap.push_back(v);
465  newVertices.push_back(v);
466  _activeVertices.push_back(v);
467  next++;
468  }
469  else // not supported right now
470  abort();
471  }
472  else {
473  v->setHessianIndex(-1);
474  }
475  }
476 
477  //if (newVertices.size() != vset.size())
478  //cerr << __PRETTY_FUNCTION__ << ": something went wrong " << PVAR(vset.size()) << " " << PVAR(newVertices.size()) << endl;
479  return _algorithm->updateStructure(newVertices, eset);
480  }
481 
483  {
484  // sort vector structures to get deterministic ordering based on IDs
485  sort(_activeVertices.begin(), _activeVertices.end(), VertexIDCompare());
486  sort(_activeEdges.begin(), _activeEdges.end(), EdgeIDCompare());
487  }
488 
490  _ivMap.clear();
491  _activeVertices.clear();
492  _activeEdges.clear();
494  }
495 
496  SparseOptimizer::VertexContainer::const_iterator SparseOptimizer::findActiveVertex(const OptimizableGraph::Vertex* v) const
497  {
498  VertexContainer::const_iterator lower = lower_bound(_activeVertices.begin(), _activeVertices.end(), v, VertexIDCompare());
499  if (lower == _activeVertices.end())
500  return _activeVertices.end();
501  if ((*lower) == v)
502  return lower;
503  return _activeVertices.end();
504  }
505 
506  SparseOptimizer::EdgeContainer::const_iterator SparseOptimizer::findActiveEdge(const OptimizableGraph::Edge* e) const
507  {
508  EdgeContainer::const_iterator lower = lower_bound(_activeEdges.begin(), _activeEdges.end(), e, EdgeIDCompare());
509  if (lower == _activeEdges.end())
510  return _activeEdges.end();
511  if ((*lower) == e)
512  return lower;
513  return _activeEdges.end();
514  }
515 
517  {
518  for (VertexContainer::iterator it = vlist.begin(); it != vlist.end(); ++it)
519  (*it)->push();
520  }
521 
523  {
524  for (VertexContainer::iterator it = vlist.begin(); it != vlist.end(); ++it)
525  (*it)->pop();
526  }
527 
529  {
530  for (HyperGraph::VertexSet::iterator it = vlist.begin(); it != vlist.end(); ++it) {
531  OptimizableGraph::Vertex* v = dynamic_cast<OptimizableGraph::Vertex*>(*it);
532  if (v)
533  v->push();
534  else
535  cerr << __FUNCTION__ << ": FATAL PUSH SET" << endl;
536  }
537  }
538 
540  {
541  for (HyperGraph::VertexSet::iterator it = vlist.begin(); it != vlist.end(); ++it){
542  OptimizableGraph::Vertex* v = dynamic_cast<OptimizableGraph::Vertex*> (*it);
543  if (v)
544  v->pop();
545  else
546  cerr << __FUNCTION__ << ": FATAL POP SET" << endl;
547  }
548  }
549 
551  {
552  for (VertexContainer::iterator it = vlist.begin(); it != vlist.end(); ++it)
553  (*it)->discardTop();
554  }
555 
557  {
558  _verbose = verbose;
559  }
560 
562  {
563  if (_algorithm) // reset the optimizer for the formerly used solver
566  if (_algorithm)
567  _algorithm->setOptimizer(this);
568  }
569 
570  bool SparseOptimizer::computeMarginals(SparseBlockMatrix<MatrixXd>& spinv, const std::vector<std::pair<int, int> >& blockIndices){
571  return _algorithm->computeMarginals(spinv, blockIndices);
572  }
573 
575  {
576  _forceStopFlag=flag;
577  }
578 
580  {
581  OptimizableGraph::Vertex* vv = static_cast<OptimizableGraph::Vertex*>(v);
582  if (vv->hessianIndex() >= 0) {
584  _ivMap.clear();
585  }
586  return HyperGraph::removeVertex(v);
587  }
588 
590  {
591  std::pair<HyperGraphActionSet::iterator, bool> insertResult = _graphActions[AT_COMPUTEACTIVERROR].insert(action);
592  return insertResult.second;
593  }
594 
596  {
597  return _graphActions[AT_COMPUTEACTIVERROR].erase(action) > 0;
598  }
599 
601  {
603  }
604 
606  {
608  }
609 
611  {
613  }
614 
615 } // end namespace
double activeChi2() const
double activeRobustChi2() const
virtual bool updateInitialization(HyperGraph::VertexSet &vset, HyperGraph::EdgeSet &eset)
virtual void computeInitialGuess()
virtual SolverResult solve(int iteration, bool online=false)=0
virtual const char * name() const
statistics about the optimization
Definition: batch_stats.h:39
VertexContainer _ivMap
bool terminate()
if external stop flag is given, return its state. False otherwise
#define __PRETTY_FUNCTION__
Definition: macros.h:95
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:42
const OptimizationAlgorithm * algorithm() const
the solver used by the optimizer
VertexContainer _activeVertices
sorted according to VertexIDCompare
int dimension() const
returns the dimensions of the error function
const Vertex * vertex(size_t i) const
Definition: hyper_graph.h:140
virtual const double * errorData() const =0
returns the error vector cached after calling the computeError;
const EdgeSet & edges() const
Definition: hyper_graph.h:182
bool fixed() const
true => this node is fixed during the optimization
const VertexIDMap & vertices() const
Definition: hyper_graph.h:177
std::vector< Vertex * > VertexContainer
Definition: hyper_graph.h:94
void setComputeBatchStatistics(bool computeBatchStatistics)
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:91
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 hessianIndex() const
temporary index of this node in the parameter vector obtained from linearization
int optimize(int iterations, bool online=false)
virtual bool init(bool online=false)=0
virtual double initialEstimatePossible(const OptimizableGraph::VertexSet &from, OptimizableGraph::Vertex *to)
bool verbose() const
verbose information during optimization
bool computeBatchStatistics() const
int iteration
which iteration
Definition: batch_stats.h:41
virtual void setToOrigin()
RobustKernel * robustKernel() const
if NOT NULL, error of this edge will be robustifed with the kernel
virtual void postIteration(int)
called at the end of an iteration (argument is the number of the iteration)
bool arrayHasNaN(const double *array, int size, int *nanIndex=0)
Definition: misc.h:177
int dimension() const
dimension of the estimated state belonging to this node
void update(const std::string &key, const XmlRpc::XmlRpcValue &v)
const VertexContainer & vertices() const
Definition: hyper_graph.h:132
std::set< Edge * > EdgeSet
Definition: hyper_graph.h:90
virtual Vertex * findGauge()
finds a gauge in the graph to remove the undefined dof.
virtual bool removeVertex(HyperGraph::Vertex *v)
virtual bool removeVertex(Vertex *v)
removes a vertex from the graph. Returns true on success (vertex was present)
virtual void robustify(double squaredError, Eigen::Vector3d &rho) const =0
void setVerbose(bool verbose)
bool computeMarginals(SparseBlockMatrix< MatrixXd > &spinv, const std::vector< std::pair< int, int > > &blockIndices)
virtual void initialEstimate(const OptimizableGraph::VertexSet &from, OptimizableGraph::Vertex *to)=0
virtual bool computeMarginals(SparseBlockMatrix< MatrixXd > &spinv, const std::vector< std::pair< int, int > > &blockIndices)=0
virtual bool getEstimateData(double *estimate) const
void setForceStopFlag(bool *flag)
virtual void computeError()=0
void setAlgorithm(OptimizationAlgorithm *algorithm)
int numEdges
how many edges
Definition: batch_stats.h:43
BatchStatisticsContainer _batchStatistics
global statistics of the optimizer, e.g., timing, num-non-zeros
void push()
push all the active vertices onto a stack
ROSCPP_DECL bool ok()
void setOptimizer(SparseOptimizer *optimizer)
virtual void push()=0
backup the position of the vertex to a stack
EdgeContainer _activeEdges
sorted according to EdgeIDCompare
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
double get_monotonic_time()
Definition: timeutil.cpp:113
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
virtual bool updateStructure(const std::vector< HyperGraph::Vertex *> &vset, const HyperGraph::EdgeSet &edges)=0
bool marginalized() const
true => this node is marginalized out during the optimization
bool buildIndexMapping(SparseOptimizer::VertexContainer &vlist)
void pop()
pop (restore) the estimate of the active vertices from the stack
const EdgeSet & edges() const
returns the set of hyper-edges that are leaving/entering in this vertex
Definition: hyper_graph.h:106
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:97
void setToOrigin()
sets the node to the origin (used in the multilevel stuff)
JacobianWorkspace _jacobianWorkspace
virtual void printVerbose(std::ostream &os) const
virtual void preIteration(int)
called at the beginning of an iteration (argument is the number of the iteration) ...
void discardTop()
same as above, but for the active vertices
std::set< HyperGraphAction * > HyperGraphActionSet
int id() const
returns the id
Definition: hyper_graph.h:103
virtual bool initializeOptimization(HyperGraph::EdgeSet &eset)
Generic interface for a non-linear solver operating on a graph.
EdgeContainer::const_iterator findActiveEdge(const OptimizableGraph::Edge *e) const
std::vector< HyperGraphActionSet > _graphActions
VertexContainer::const_iterator findActiveVertex(const OptimizableGraph::Vertex *v) const
virtual int estimateDimension() const
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.


orb_slam2_ros
Author(s):
autogenerated on Mon Feb 28 2022 23:03:52