g2o
Loading...
Searching...
No Matches
optimizable_graph.h
Go to the documentation of this file.
1// g2o - General Graph Optimization
2// Copyright (C) 2011 R. Kuemmerle, G. Grisetti, H. Strasdat, 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#ifndef G2O_AIS_OPTIMIZABLE_GRAPH_HH_
28#define G2O_AIS_OPTIMIZABLE_GRAPH_HH_
29
30#include <functional>
31#include <iostream>
32#include <set>
33#include <typeinfo>
34
35#include "g2o/stuff/macros.h"
36#include "g2o_core_api.h"
37#include "hyper_graph.h"
38#include "io_helper.h"
39#include "jacobian_workspace.h"
40#include "openmp_mutex.h"
41#include "parameter.h"
42#include "parameter_container.h"
43
44namespace g2o {
45
46class HyperGraphAction;
47struct OptimizationAlgorithmProperty;
48class CacheContainer;
49class RobustKernel;
50
68
69 typedef std::set<HyperGraphAction*> HyperGraphActionSet;
70
71 // forward declarations
74
79 bool operator()(const Vertex* v1, const Vertex* v2) const {
80 return v1->id() < v2->id();
81 }
82 };
83
89 bool operator()(const Edge* e1, const Edge* e2) const {
90 return e1->internalId() < e2->internalId();
91 }
93 const HyperGraph::Edge* e2) const {
94 return operator()(static_cast<const Edge*>(e1),
95 static_cast<const Edge*>(e2));
96 }
97 };
98
100 typedef std::vector<OptimizableGraph::Vertex*> VertexContainer;
102 typedef std::vector<OptimizableGraph::Edge*> EdgeContainer;
103
109 private:
110 friend struct OptimizableGraph;
111
112 public:
113 Vertex();
114 virtual ~Vertex();
115
117 void setToOrigin() {
118 setToOriginImpl();
119 updateCache();
120 }
121
123 virtual const double& hessian(int i, int j) const = 0;
124 virtual double& hessian(int i, int j) = 0;
125 virtual double hessianDeterminant() const = 0;
126 virtual double* hessianData() = 0;
127
129 virtual void mapHessianMemory(double* d) = 0;
130
135 virtual int copyB(double* b_) const = 0;
136
138 virtual const double& b(int i) const = 0;
139 virtual double& b(int i) = 0;
141 virtual double* bData() = 0;
142
146 virtual void clearQuadraticForm() = 0;
147
152 virtual double solveDirect(double lambda = 0) = 0;
153
159 bool setEstimateData(const double* estimate);
160
166 bool setEstimateData(const std::vector<double>& estimate) {
167 int dim = estimateDimension();
168 if ((dim == -1) || (estimate.size() != std::size_t(dim))) return false;
169 return setEstimateData(&estimate[0]);
170 };
171
177 template <typename Derived>
178 bool setEstimateData(const Eigen::MatrixBase<Derived>& estimate) {
179 int dim = estimateDimension();
180 if ((dim == -1) || (estimate.size() != dim)) return false;
181 return setEstimateData(estimate.derived().data());
182 };
183
188 virtual bool getEstimateData(double* estimate) const;
189
194 virtual bool getEstimateData(std::vector<double>& estimate) const {
195 int dim = estimateDimension();
196 if (dim < 0) return false;
197 estimate.resize(dim);
198 return getEstimateData(&estimate[0]);
199 };
200
205 template <typename Derived>
206 bool getEstimateData(Eigen::MatrixBase<Derived>& estimate) const {
207 int dim = estimateDimension();
208 // If dim is -ve, getEstimateData is not implemented and fails
209 if (dim < 0) return false;
210
211 // If the vector isn't the right size to store the estimate, try to resize
212 // it. This only works if the vector is dynamic. If it is static, fail.
213 if (estimate.size() != dim) {
214 if ((estimate.RowsAtCompileTime == Eigen::Dynamic) ||
215 (estimate.ColsAtCompileTime == Eigen::Dynamic))
216 estimate.derived().resize(dim);
217 else
218 return false;
219 }
220 return getEstimateData(estimate.derived().data());
221 };
222
227 virtual int estimateDimension() const;
228
234 bool setMinimalEstimateData(const double* estimate);
235
241 bool setMinimalEstimateData(const std::vector<double>& estimate) {
242 int dim = minimalEstimateDimension();
243 if ((dim == -1) || (estimate.size() != std::size_t(dim))) return false;
244 return setMinimalEstimateData(&estimate[0]);
245 };
246
252 template <typename Derived>
253 bool setMinimalEstimateData(const Eigen::MatrixBase<Derived>& estimate) {
254 int dim = minimalEstimateDimension();
255 if ((dim == -1) || (estimate.size() != dim)) return false;
256 return setMinimalEstimateData(estimate.derived().data());
257 };
258
263 virtual bool getMinimalEstimateData(double* estimate) const;
264
269 virtual bool getMinimalEstimateData(std::vector<double>& estimate) const {
270 int dim = minimalEstimateDimension();
271 if (dim < 0) return false;
272 estimate.resize(dim);
273 return getMinimalEstimateData(&estimate[0]);
274 };
275
280 template <typename Derived>
281 bool getMinimalEstimateData(Eigen::MatrixBase<Derived>& estimate) const {
282 int dim = minimalEstimateDimension();
283 // If dim is -ve, getMinimalEstimateData is not implemented and fails
284 if (dim < 0) return false;
285
286 // If the vector isn't the right size to store the estimate, try to resize
287 // it. This only works if the vector is dynamic. If it is static, fail.
288 if (estimate.size() != dim) {
289 if ((estimate.RowsAtCompileTime == Eigen::Dynamic) ||
290 (estimate.ColsAtCompileTime == Eigen::Dynamic))
291 estimate.derived().resize(dim);
292 else
293 return false;
294 }
295 return getMinimalEstimateData(estimate.derived().data());
296 };
297
302 virtual int minimalEstimateDimension() const;
303
305 virtual void push() = 0;
306
309 virtual void pop() = 0;
310
313 virtual void discardTop() = 0;
314
316 virtual int stackSize() const = 0;
317
324 void oplus(const double* v) {
325 oplusImpl(v);
326 updateCache();
327 }
328
331 int hessianIndex() const { return _hessianIndex; }
332 int G2O_ATTRIBUTE_DEPRECATED(tempIndex() const) { return hessianIndex(); }
334 void setHessianIndex(int ti) { _hessianIndex = ti; }
335 void G2O_ATTRIBUTE_DEPRECATED(setTempIndex(int ti)) { setHessianIndex(ti); }
336
338 bool fixed() const { return _fixed; }
340 void setFixed(bool fixed) { _fixed = fixed; }
341
343 bool marginalized() const { return _marginalized; }
345 void setMarginalized(bool marginalized) { _marginalized = marginalized; }
346
348 int dimension() const { return _dimension; }
349
352 virtual void setId(int id) { _id = id; }
353
355 void setColInHessian(int c) { _colInHessian = c; }
357 int colInHessian() const { return _colInHessian; }
358
359 const OptimizableGraph* graph() const { return _graph; }
360 OptimizableGraph* graph() { return _graph; }
361
366 void lockQuadraticForm() { _quadraticFormMutex.lock(); }
371 void unlockQuadraticForm() { _quadraticFormMutex.unlock(); }
372
374 virtual bool read(std::istream& is) = 0;
376 virtual bool write(std::ostream& os) const = 0;
377
378 virtual void updateCache();
379
380 CacheContainer* cacheContainer();
381
382 protected:
386 bool _fixed;
391
393
398 virtual void oplusImpl(const double* v) = 0;
399
401 virtual void setToOriginImpl() = 0;
402
407 virtual bool setEstimateDataImpl(const double*) { return false; }
408
413 virtual bool setMinimalEstimateDataImpl(const double*) { return false; }
414 };
415
418 private:
419 friend struct OptimizableGraph;
420
421 public:
422 Edge();
423 virtual ~Edge();
424
425 // indicates if all vertices are fixed
426 virtual bool allVerticesFixed() const = 0;
427
428 // computes the error of the edge and stores it in an internal structure
429 virtual void computeError() = 0;
430
433 virtual bool setMeasurementData(const double* m);
434
437 virtual bool getMeasurementData(double* m) const;
438
441 virtual int measurementDimension() const;
442
447 virtual bool setMeasurementFromState();
448
450 RobustKernel* robustKernel() const { return _robustKernel; }
454 void setRobustKernel(RobustKernel* ptr);
455
457 virtual const double* errorData() const = 0;
458 virtual double* errorData() = 0;
459
462 virtual const double* informationData() const = 0;
463 virtual double* informationData() = 0;
464
467 virtual double chi2() const = 0;
468
475 virtual void constructQuadraticForm() = 0;
476
486 virtual void mapHessianMemory(double* d, int i, int j, bool rowMajor) = 0;
487
492 virtual void linearizeOplus(JacobianWorkspace& jacobianWorkspace) = 0;
493
498
507 (void)from;
508 (void)to;
509 return -1.;
510 }
511
513 int level() const { return _level; }
515 void setLevel(int l) { _level = l; }
516
518 int dimension() const { return _dimension; }
519
520 G2O_ATTRIBUTE_DEPRECATED(virtual Vertex* createFrom()) { return nullptr; }
521 G2O_ATTRIBUTE_DEPRECATED(virtual Vertex* createTo()) { return nullptr; }
522 virtual Vertex* createVertex(int) { return nullptr; }
523
525 virtual bool read(std::istream& is) = 0;
527 virtual bool write(std::ostream& os) const = 0;
528
530 long long internalId() const { return _internalId; }
531
532 OptimizableGraph* graph();
533 const OptimizableGraph* graph() const;
534
535 bool setParameterId(int argNum, int paramId);
536 inline const Parameter* parameter(int argNo) const {
537 return *_parameters.at(argNo);
538 }
539 inline size_t numParameters() const { return _parameters.size(); }
540 inline void resizeParameters(size_t newSize) {
541 _parameters.resize(newSize, 0);
542 _parameterIds.resize(newSize, -1);
543 _parameterTypes.resize(newSize, typeid(void*).name());
544 }
545
546 protected:
550 long long _internalId;
551 std::vector<int> _cacheIds;
552
553 template <typename ParameterType>
554 bool installParameter(ParameterType*& p, size_t argNo, int paramId = -1) {
555 if (argNo >= _parameters.size()) return false;
556 _parameterIds[argNo] = paramId;
557 _parameters[argNo] = (Parameter**)&p;
558 _parameterTypes[argNo] = typeid(ParameterType).name();
559 return true;
560 }
561
562 template <typename CacheType>
563 void resolveCache(CacheType*& cache, OptimizableGraph::Vertex*,
564 const std::string& _type,
565 const ParameterVector& parameters);
566
567 bool resolveParameters();
568 virtual bool resolveCaches();
569
570 std::vector<std::string> _parameterTypes;
571 std::vector<Parameter**> _parameters;
572 std::vector<int> _parameterIds;
573 };
574
576 inline Vertex* vertex(int id) {
577 return reinterpret_cast<Vertex*>(HyperGraph::vertex(id));
578 }
579
581 inline const Vertex* vertex(int id) const {
582 return reinterpret_cast<const Vertex*>(HyperGraph::vertex(id));
583 }
584
587 virtual ~OptimizableGraph();
588
594 virtual bool addVertex(HyperGraph::Vertex* v, Data* userData);
595 virtual bool addVertex(HyperGraph::Vertex* v) { return addVertex(v, 0); }
596 bool addVertex(OptimizableGraph::Vertex* v, Data* userData);
598
606 virtual bool addEdge(HyperGraph::Edge* e);
607 bool addEdge(OptimizableGraph::Edge* e);
608
615 virtual bool setEdgeVertex(HyperGraph::Edge* e, int pos,
617
619 double chi2() const;
620
622 int maxDimension() const;
623
627 _jacobianWorkspace.updateSize(*this, true);
628 }
629
634 std::set<int> dimensions() const;
635
640 virtual int optimize(int iterations, bool online = false);
641
644 virtual void preIteration(int);
647 virtual void postIteration(int);
648
650 bool addPreIterationAction(HyperGraphAction* action);
652 bool addPostIterationAction(HyperGraphAction* action);
653
655 bool removePreIterationAction(HyperGraphAction* action);
657 bool removePostIterationAction(HyperGraphAction* action);
658
660 virtual void push();
662 virtual void pop();
665 virtual void discardTop();
666
669 virtual bool load(std::istream& is);
670 bool load(const char* filename);
672 virtual bool save(std::ostream& os, int level = 0) const;
674 bool save(const char* filename, int level = 0) const;
675
677 bool saveSubset(std::ostream& os, HyperGraph::VertexSet& vset, int level = 0);
678
680 bool saveSubset(std::ostream& os, HyperGraph::EdgeSet& eset);
681
683 virtual void push(HyperGraph::VertexSet& vset);
685 virtual void pop(HyperGraph::VertexSet& vset);
688 virtual void discardTop(HyperGraph::VertexSet& vset);
689
691 virtual void setFixed(HyperGraph::VertexSet& vset, bool fixed);
692
699 void setRenamedTypesFromString(const std::string& types);
700
707 bool isSolverSuitable(const OptimizationAlgorithmProperty& solverProperty,
708 const std::set<int>& vertDims = std::set<int>()) const;
709
713 virtual void clearParameters();
714
715 bool addParameter(Parameter* p) { return _parameters.addParameter(p); }
716
717 Parameter* parameter(int id) { return _parameters.getParameter(id); }
718
725 bool verifyInformationMatrices(bool verbose = false) const;
726
727 // helper functions to save an individual vertex
728 bool saveVertex(std::ostream& os, Vertex* v) const;
729
730 // helper function to save an individual parameter
731 bool saveParameter(std::ostream& os, Parameter* v) const;
732
733 // helper functions to save an individual edge
734 bool saveEdge(std::ostream& os, Edge* e) const;
735
736 // helper functions to save the data packets
737 bool saveUserData(std::ostream& os, HyperGraph::Data* v) const;
738
740 JacobianWorkspace& jacobianWorkspace() { return _jacobianWorkspace; }
742 return _jacobianWorkspace;
743 }
744
751 static bool initMultiThreading();
752
753 inline ParameterContainer& parameters() { return _parameters; }
754 inline const ParameterContainer& parameters() const { return _parameters; }
755
757 void forEachVertex(std::function<void(OptimizableGraph::Vertex*)> fn);
759 void forEachVertex(HyperGraph::VertexSet& vset,
760 std::function<void(OptimizableGraph::Vertex*)> fn);
761
762 protected:
763 std::map<std::string, std::string> _renamedTypesLookup;
764 long long _nextEdgeId;
765 std::vector<HyperGraphActionSet> _graphActions;
766
769
770 void performActions(int iter, HyperGraphActionSet& actions);
771};
772
777} // namespace g2o
778
779#endif
Abstract action that operates on an entire graph.
Container class that implements an interface for adding/removing Data elements in a linked list.
data packet for a vertex. Extend this class to store in the vertices the potential additional informa...
Definition hyper_graph.h:93
abstract Vertex, your types must derive from that one
int id() const
returns the id
std::set< Edge * > EdgeSet
std::set< Vertex * > VertexSet
provide memory workspace for computing the Jacobians
std::vector< std::string > _parameterTypes
int dimension() const
returns the dimensions of the error function
virtual void linearizeOplus(JacobianWorkspace &jacobianWorkspace)=0
const Parameter * parameter(int argNo) const
virtual double chi2() const =0
virtual double initialEstimatePossible(const OptimizableGraph::VertexSet &from, OptimizableGraph::Vertex *to)
virtual void computeError()=0
bool installParameter(ParameterType *&p, size_t argNo, int paramId=-1)
int level() const
returns the level of the edge
G2O_ATTRIBUTE_DEPRECATED(virtual Vertex *createFrom())
virtual bool read(std::istream &is)=0
read the vertex from a stream, i.e., the internal state of the vertex
virtual void mapHessianMemory(double *d, int i, int j, bool rowMajor)=0
long long internalId() const
the internal ID of the edge
G2O_ATTRIBUTE_DEPRECATED(virtual Vertex *createTo())
virtual bool allVerticesFixed() const =0
std::vector< Parameter ** > _parameters
RobustKernel * robustKernel() const
if NOT NULL, error of this edge will be robustifed with the kernel
virtual double * informationData()=0
virtual void constructQuadraticForm()=0
virtual bool write(std::ostream &os) const =0
write the vertex to a stream
virtual const double * errorData() const =0
returns the error vector cached after calling the computeError;
virtual void initialEstimate(const OptimizableGraph::VertexSet &from, OptimizableGraph::Vertex *to)=0
void setLevel(int l)
sets the level of the edge
virtual double * errorData()=0
void resizeParameters(size_t newSize)
virtual const double * informationData() const =0
virtual Vertex * createVertex(int)
A general case Vertex for optimization.
virtual bool setMinimalEstimateDataImpl(const double *)
virtual const double & hessian(int i, int j) const =0
get the element from the hessian matrix
virtual int stackSize() const =0
return the stack size
virtual void mapHessianMemory(double *d)=0
bool setEstimateData(const std::vector< double > &estimate)
virtual double & hessian(int i, int j)=0
bool marginalized() const
true => this node is marginalized out during the optimization
virtual bool read(std::istream &is)=0
read the vertex from a stream, i.e., the internal state of the vertex
virtual bool setEstimateDataImpl(const double *)
void setHessianIndex(int ti)
set the temporary index of the vertex in the parameter blocks
virtual void oplusImpl(const double *v)=0
virtual bool write(std::ostream &os) const =0
write the vertex to a stream
int colInHessian() const
get the row of this vertex in the Hessian
virtual double solveDirect(double lambda=0)=0
virtual double & b(int i)=0
bool getEstimateData(Eigen::MatrixBase< Derived > &estimate) const
virtual void clearQuadraticForm()=0
virtual const double & b(int i) const =0
get the b vector element
int dimension() const
dimension of the estimated state belonging to this node
bool setMinimalEstimateData(const Eigen::MatrixBase< Derived > &estimate)
int G2O_ATTRIBUTE_DEPRECATED(tempIndex() const)
bool fixed() const
true => this node is fixed during the optimization
virtual void push()=0
backup the position of the vertex to a stack
void setColInHessian(int c)
set the row of this vertex in the Hessian
void setToOrigin()
sets the node to the origin (used in the multilevel stuff)
virtual void setToOriginImpl()=0
sets the node to the origin (used in the multilevel stuff)
void G2O_ATTRIBUTE_DEPRECATED(setTempIndex(int ti))
bool setMinimalEstimateData(const std::vector< double > &estimate)
virtual bool getEstimateData(std::vector< double > &estimate) const
virtual double hessianDeterminant() const =0
const OptimizableGraph * graph() const
bool getMinimalEstimateData(Eigen::MatrixBase< Derived > &estimate) const
virtual double * hessianData()=0
virtual double * bData()=0
return a pointer to the b vector associated with this vertex
virtual int copyB(double *b_) const =0
bool setEstimateData(const Eigen::MatrixBase< Derived > &estimate)
virtual bool getMinimalEstimateData(std::vector< double > &estimate) const
void setFixed(bool fixed)
true => this node should be considered fixed during the optimization
void setMarginalized(bool marginalized)
true => this node should be marginalized out during the optimization
base for all robust cost functions
#define G2O_CORE_API
std::vector< Parameter * > ParameterVector
Definition parameter.h:54
order edges based on the internal ID, which is assigned to the edge in addEdge()
bool operator()(const HyperGraph::Edge *e1, const HyperGraph::Edge *e2) const
bool operator()(const Edge *e1, const Edge *e2) const
order vertices based on their ID
bool operator()(const Vertex *v1, const Vertex *v2) const
JacobianWorkspace & jacobianWorkspace()
the workspace for storing the Jacobians of the graph
JacobianWorkspace _jacobianWorkspace
ParameterContainer & parameters()
bool saveSubset(std::ostream &os, HyperGraph::EdgeSet &eset)
save a subgraph to a stream. Again uses the Factory system.
std::vector< OptimizableGraph::Edge * > EdgeContainer
vector container for edges
ParameterContainer _parameters
const JacobianWorkspace & jacobianWorkspace() const
std::vector< OptimizableGraph::Vertex * > VertexContainer
vector container for vertices
bool addVertex(OptimizableGraph::Vertex *v)
std::vector< HyperGraphActionSet > _graphActions
std::map< std::string, std::string > _renamedTypesLookup
Parameter * parameter(int id)
std::set< HyperGraphAction * > HyperGraphActionSet
const Vertex * vertex(int id) const
returns the vertex number id appropriately casted
virtual bool save(std::ostream &os, int level=0) const
save the graph to a stream. Again uses the Factory system.
virtual bool addVertex(HyperGraph::Vertex *v)
const ParameterContainer & parameters() const
bool addParameter(Parameter *p)
bool saveSubset(std::ostream &os, HyperGraph::VertexSet &vset, int level=0)
save a subgraph to a stream. Again uses the Factory system.
virtual bool load(std::istream &is)
Vertex * vertex(int id)
returns the vertex number id appropriately casted