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
virtual void printVerbose(std::ostream &os) const
virtual bool updateInitialization(HyperGraph::VertexSet &vset, HyperGraph::EdgeSet &eset)
virtual void computeInitialGuess()
virtual SolverResult solve(int iteration, bool online=false)=0
int id() const
returns the id
Definition: hyper_graph.h:103
statistics about the optimization
Definition: batch_stats.h:39
VertexContainer _ivMap
const Vertex * vertex(size_t i) const
Definition: hyper_graph.h:140
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
virtual bool getEstimateData(double *estimate) const
VertexContainer _activeVertices
sorted according to VertexIDCompare
virtual const double * errorData() const =0
returns the error vector cached after calling the computeError;
int dimension() const
returns the dimensions of the error function
std::vector< Vertex * > VertexContainer
Definition: hyper_graph.h:94
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: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 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:41
virtual void setToOrigin()
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:177
bool arrayHasNaN(const double *array, int size, int *nanIndex=0)
Definition: misc.h:177
void update(const std::string &key, const XmlRpc::XmlRpcValue &v)
std::set< Edge * > EdgeSet
Definition: hyper_graph.h:90
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
virtual bool removeVertex(HyperGraph::Vertex *v)
virtual bool removeVertex(Vertex *v)
removes a vertex from the graph. Returns true on success (vertex was present)
const VertexContainer & vertices() const
Definition: hyper_graph.h:132
virtual void robustify(double squaredError, Eigen::Vector3d &rho) const =0
const EdgeSet & edges() const
returns the set of hyper-edges that are leaving/entering in this vertex
Definition: hyper_graph.h:106
void setVerbose(bool verbose)
virtual int estimateDimension() const
bool computeMarginals(SparseBlockMatrix< MatrixXd > &spinv, const std::vector< std::pair< int, int > > &blockIndices)
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:182
virtual bool computeMarginals(SparseBlockMatrix< MatrixXd > &spinv, const std::vector< std::pair< int, int > > &blockIndices)=0
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:43
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
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
bool buildIndexMapping(SparseOptimizer::VertexContainer &vlist)
void pop()
pop (restore) the estimate of the active vertices from the stack
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:97
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) ...
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 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.
double activeChi2() const


orb_slam2_ros
Author(s):
autogenerated on Wed Apr 21 2021 02:53:05