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 44 namespace g2o { 45 46 class HyperGraphAction; 47 struct OptimizationAlgorithmProperty; 48 class CacheContainer; 49 class RobustKernel; 50 51 /** 52 @addtogroup g2o 53 */ 54 /** 55 This is an abstract class that represents one optimization 56 problem. It specializes the general graph to contain special 57 vertices and edges. The vertices represent parameters that can 58 be optimized, while the edges represent constraints. This class 59 also provides basic functionalities to handle the backup/restore 60 of portions of the vertices. 61 */ 62 struct G2O_CORE_API OptimizableGraph : public HyperGraph { 63 64 enum ActionType { 65 AT_PREITERATION, AT_POSTITERATION, 66 AT_NUM_ELEMENTS, // keep as last element 67 }; 68 69 typedef std::set<HyperGraphAction*> HyperGraphActionSet; 70 71 // forward declarations 72 class G2O_CORE_API Vertex; 73 class G2O_CORE_API Edge; 74 75 76 /** 77 * \brief order vertices based on their ID 78 */ 79 struct G2O_CORE_API VertexIDCompare { operatorOptimizableGraph::VertexIDCompare80 bool operator() (const Vertex* v1, const Vertex* v2) const 81 { 82 return v1->id() < v2->id(); 83 } 84 }; 85 86 /** 87 * \brief order edges based on the internal ID, which is assigned to the edge in addEdge() 88 */ 89 struct G2O_CORE_API EdgeIDCompare { operatorOptimizableGraph::EdgeIDCompare90 bool operator() (const Edge* e1, const Edge* e2) const 91 { 92 return e1->internalId() < e2->internalId(); 93 } operatorOptimizableGraph::EdgeIDCompare94 bool operator() (const HyperGraph::Edge* e1, const HyperGraph::Edge* e2) const 95 { 96 return operator()(static_cast<const Edge*>(e1), static_cast<const Edge*>(e2)); 97 } 98 }; 99 100 //! vector container for vertices 101 typedef std::vector<OptimizableGraph::Vertex*> VertexContainer; 102 //! vector container for edges 103 typedef std::vector<OptimizableGraph::Edge*> EdgeContainer; 104 105 /** 106 * \brief A general case Vertex for optimization 107 */ 108 class G2O_CORE_API Vertex : public HyperGraph::Vertex, public HyperGraph::DataContainer { 109 private: 110 friend struct OptimizableGraph; 111 public: 112 Vertex(); 113 virtual ~Vertex(); 114 115 //! sets the node to the origin (used in the multilevel stuff) setToOriginOptimizableGraph116 void setToOrigin() { setToOriginImpl(); updateCache();} 117 118 //! get the element from the hessian matrix 119 virtual const number_t& hessian(int i, int j) const = 0; 120 virtual number_t& hessian(int i, int j) = 0; 121 virtual number_t hessianDeterminant() const = 0; 122 virtual number_t* hessianData() = 0; 123 124 /** maps the internal matrix to some external memory location */ 125 virtual void mapHessianMemory(number_t* d) = 0; 126 127 /** 128 * copies the b vector in the array b_ 129 * @return the number of elements copied 130 */ 131 virtual int copyB(number_t* b_) const = 0; 132 133 //! get the b vector element 134 virtual const number_t& b(int i) const = 0; 135 virtual number_t& b(int i) = 0; 136 //! return a pointer to the b vector associated with this vertex 137 virtual number_t* bData() = 0; 138 139 /** 140 * set the b vector part of this vertex to zero 141 */ 142 virtual void clearQuadraticForm() = 0; 143 144 /** 145 * updates the current vertex with the direct solution x += H_ii\b_ii 146 * @return the determinant of the inverted hessian 147 */ 148 virtual number_t solveDirect(number_t lambda=0) = 0; 149 150 /** 151 * sets the initial estimate from an array of number_t 152 * Implement setEstimateDataImpl() 153 * @return true on success 154 */ 155 bool setEstimateData(const number_t* estimate); 156 157 /** 158 * sets the initial estimate from an array of number_t 159 * Implement setEstimateDataImpl() 160 * @return true on success 161 */ setEstimateDataOptimizableGraph162 bool setEstimateData(const std::vector<number_t>& estimate) { 163 #ifndef NDEBUG 164 int dim = estimateDimension(); 165 assert((dim == -1) || (estimate.size() == std::size_t(dim))); 166 #endif 167 return setEstimateData(&estimate[0]); 168 }; 169 170 /** 171 * writes the estimater to an array of number_t 172 * @returns true on success 173 */ 174 virtual bool getEstimateData(number_t* estimate) const; 175 176 /** 177 * writes the estimater to an array of number_t 178 * @returns true on success 179 */ getEstimateDataOptimizableGraph180 virtual bool getEstimateData(std::vector<number_t>& estimate) const { 181 int dim = estimateDimension(); 182 if (dim < 0) 183 return false; 184 estimate.resize(dim); 185 return getEstimateData(&estimate[0]); 186 }; 187 188 /** 189 * returns the dimension of the extended representation used by get/setEstimate(number_t*) 190 * -1 if it is not supported 191 */ 192 virtual int estimateDimension() const; 193 194 /** 195 * sets the initial estimate from an array of number_t. 196 * Implement setMinimalEstimateDataImpl() 197 * @return true on success 198 */ 199 bool setMinimalEstimateData(const number_t* estimate); 200 201 /** 202 * sets the initial estimate from an array of number_t. 203 * Implement setMinimalEstimateDataImpl() 204 * @return true on success 205 */ setMinimalEstimateDataOptimizableGraph206 bool setMinimalEstimateData(const std::vector<number_t>& estimate) { 207 #ifndef NDEBUG 208 int dim = minimalEstimateDimension(); 209 assert((dim == -1) || (estimate.size() == std::size_t(dim))); 210 #endif 211 return setMinimalEstimateData(&estimate[0]); 212 }; 213 214 /** 215 * writes the estimate to an array of number_t 216 * @returns true on success 217 */ 218 virtual bool getMinimalEstimateData(number_t* estimate) const ; 219 220 /** 221 * writes the estimate to an array of number_t 222 * @returns true on success 223 */ getMinimalEstimateDataOptimizableGraph224 virtual bool getMinimalEstimateData(std::vector<number_t>& estimate) const { 225 int dim = minimalEstimateDimension(); 226 if (dim < 0) 227 return false; 228 estimate.resize(dim); 229 return getMinimalEstimateData(&estimate[0]); 230 }; 231 232 /** 233 * returns the dimension of the extended representation used by get/setEstimate(number_t*) 234 * -1 if it is not supported 235 */ 236 virtual int minimalEstimateDimension() const; 237 238 //! backup the position of the vertex to a stack 239 virtual void push() = 0; 240 241 //! restore the position of the vertex by retrieving the position from the stack 242 virtual void pop() = 0; 243 244 //! pop the last element from the stack, without restoring the current estimate 245 virtual void discardTop() = 0; 246 247 //! return the stack size 248 virtual int stackSize() const = 0; 249 250 /** 251 * Update the position of the node from the parameters in v. 252 * Depends on the implementation of oplusImpl in derived classes to actually carry 253 * out the update. 254 * Will also call updateCache() to update the caches of depending on the vertex. 255 */ oplusOptimizableGraph256 void oplus(const number_t* v) 257 { 258 oplusImpl(v); 259 updateCache(); 260 } 261 262 //! temporary index of this node in the parameter vector obtained from linearization hessianIndexOptimizableGraph263 int hessianIndex() const { return _hessianIndex;} G2O_ATTRIBUTE_DEPRECATEDOptimizableGraph264 int G2O_ATTRIBUTE_DEPRECATED(tempIndex() const) { return hessianIndex();} 265 //! set the temporary index of the vertex in the parameter blocks setHessianIndexOptimizableGraph266 void setHessianIndex(int ti) { _hessianIndex = ti;} G2O_ATTRIBUTE_DEPRECATEDOptimizableGraph267 void G2O_ATTRIBUTE_DEPRECATED(setTempIndex(int ti)) { setHessianIndex(ti);} 268 269 //! true => this node is fixed during the optimization fixedOptimizableGraph270 bool fixed() const {return _fixed;} 271 //! true => this node should be considered fixed during the optimization setFixedOptimizableGraph272 void setFixed(bool fixed) { _fixed = fixed;} 273 274 //! true => this node is marginalized out during the optimization marginalizedOptimizableGraph275 bool marginalized() const {return _marginalized;} 276 //! true => this node should be marginalized out during the optimization setMarginalizedOptimizableGraph277 void setMarginalized(bool marginalized) { _marginalized = marginalized;} 278 279 //! dimension of the estimated state belonging to this node dimensionOptimizableGraph280 int dimension() const { return _dimension;} 281 282 //! sets the id of the node in the graph be sure that the graph keeps consistent after changing the id setIdOptimizableGraph283 virtual void setId(int id) {_id = id;} 284 285 //! set the row of this vertex in the Hessian setColInHessianOptimizableGraph286 void setColInHessian(int c) { _colInHessian = c;} 287 //! get the row of this vertex in the Hessian colInHessianOptimizableGraph288 int colInHessian() const {return _colInHessian;} 289 graphOptimizableGraph290 const OptimizableGraph* graph() const {return _graph;} graphOptimizableGraph291 OptimizableGraph* graph() {return _graph;} 292 293 /** 294 * lock for the block of the hessian and the b vector associated with this vertex, to avoid 295 * race-conditions if multi-threaded. 296 */ lockQuadraticFormOptimizableGraph297 void lockQuadraticForm() { _quadraticFormMutex.lock();} 298 /** 299 * unlock the block of the hessian and the b vector associated with this vertex 300 */ unlockQuadraticFormOptimizableGraph301 void unlockQuadraticForm() { _quadraticFormMutex.unlock();} 302 303 //! read the vertex from a stream, i.e., the internal state of the vertex 304 virtual bool read(std::istream& is) = 0; 305 //! write the vertex to a stream 306 virtual bool write(std::ostream& os) const = 0; 307 308 virtual void updateCache(); 309 310 CacheContainer* cacheContainer(); 311 protected: 312 OptimizableGraph* _graph; 313 Data* _userData; 314 int _hessianIndex; 315 bool _fixed; 316 bool _marginalized; 317 int _dimension; 318 int _colInHessian; 319 OpenMPMutex _quadraticFormMutex; 320 321 CacheContainer* _cacheContainer; 322 323 /** 324 * update the position of the node from the parameters in v. 325 * Implement in your class! 326 */ 327 virtual void oplusImpl(const number_t* v) = 0; 328 329 //! sets the node to the origin (used in the multilevel stuff) 330 virtual void setToOriginImpl() = 0; 331 332 /** 333 * writes the estimater to an array of number_t 334 * @returns true on success 335 */ setEstimateDataImplOptimizableGraph336 virtual bool setEstimateDataImpl(const number_t* ) { return false;} 337 338 /** 339 * sets the initial estimate from an array of number_t 340 * @return true on success 341 */ setMinimalEstimateDataImplOptimizableGraph342 virtual bool setMinimalEstimateDataImpl(const number_t* ) { return false;} 343 344 }; 345 346 class G2O_CORE_API Edge: public HyperGraph::Edge, public HyperGraph::DataContainer { 347 private: 348 friend struct OptimizableGraph; 349 350 public: 351 Edge(); 352 virtual ~Edge(); 353 354 // indicates if all vertices are fixed 355 virtual bool allVerticesFixed() const = 0; 356 357 // computes the error of the edge and stores it in an internal structure 358 virtual void computeError() = 0; 359 360 //! sets the measurement from an array of number_t 361 //! @returns true on success 362 virtual bool setMeasurementData(const number_t* m); 363 364 //! writes the measurement to an array of number_t 365 //! @returns true on success 366 virtual bool getMeasurementData(number_t* m) const; 367 368 //! returns the dimension of the measurement in the extended representation which is used 369 //! by get/setMeasurement; 370 virtual int measurementDimension() const; 371 372 /** 373 * sets the estimate to have a zero error, based on the current value of the state variables 374 * returns false if not supported. 375 */ 376 virtual bool setMeasurementFromState(); 377 378 //! if NOT NULL, error of this edge will be robustifed with the kernel robustKernelOptimizableGraph379 RobustKernel* robustKernel() const { return _robustKernel;} 380 /** 381 * specify the robust kernel to be used in this edge 382 */ 383 void setRobustKernel(RobustKernel* ptr); 384 385 //! returns the error vector cached after calling the computeError; 386 virtual const number_t* errorData() const = 0; 387 virtual number_t* errorData() = 0; 388 389 //! returns the memory of the information matrix, usable for example with a Eigen::Map<MatrixX> 390 virtual const number_t* informationData() const = 0; 391 virtual number_t* informationData() = 0; 392 393 //! computes the chi2 based on the cached error value, only valid after computeError has been called. 394 virtual number_t chi2() const = 0; 395 396 /** 397 * Linearizes the constraint in the edge. 398 * Makes side effect on the vertices of the graph by changing 399 * the parameter vector b and the hessian blocks ii and jj. 400 * The off diagoinal block is accesed via _hessian. 401 */ 402 virtual void constructQuadraticForm() = 0; 403 404 /** 405 * maps the internal matrix to some external memory location, 406 * you need to provide the memory before calling constructQuadraticForm 407 * @param d the memory location to which we map 408 * @param i index of the vertex i 409 * @param j index of the vertex j (j > i, upper triangular fashion) 410 * @param rowMajor if true, will write in rowMajor order to the block. Since EIGEN is columnMajor by default, this results in writing the transposed 411 */ 412 virtual void mapHessianMemory(number_t* d, int i, int j, bool rowMajor) = 0; 413 414 /** 415 * Linearizes the constraint in the edge in the manifold space, and store 416 * the result in the given workspace 417 */ 418 virtual void linearizeOplus(JacobianWorkspace& jacobianWorkspace) = 0; 419 420 /** set the estimate of the to vertex, based on the estimate of the from vertices in the edge. */ 421 virtual void initialEstimate(const OptimizableGraph::VertexSet& from, OptimizableGraph::Vertex* to) = 0; 422 423 /** 424 * override in your class if it's possible to initialize the vertices in certain combinations. 425 * The return value may correspond to the cost for initiliaizng the vertex but should be positive if 426 * the initialization is possible and negative if not possible. 427 */ initialEstimatePossibleOptimizableGraph428 virtual number_t initialEstimatePossible(const OptimizableGraph::VertexSet& from, OptimizableGraph::Vertex* to) { (void) from; (void) to; return -1.;} 429 430 //! returns the level of the edge levelOptimizableGraph431 int level() const { return _level;} 432 //! sets the level of the edge setLevelOptimizableGraph433 void setLevel(int l) { _level=l;} 434 435 //! returns the dimensions of the error function dimensionOptimizableGraph436 int dimension() const { return _dimension;} 437 G2O_ATTRIBUTE_DEPRECATEDOptimizableGraph438 G2O_ATTRIBUTE_DEPRECATED(virtual Vertex* createFrom()) { return nullptr; } G2O_ATTRIBUTE_DEPRECATEDOptimizableGraph439 G2O_ATTRIBUTE_DEPRECATED(virtual Vertex* createTo()) { return nullptr; } createVertexOptimizableGraph440 virtual Vertex* createVertex(int) { return nullptr; } 441 442 //! read the vertex from a stream, i.e., the internal state of the vertex 443 virtual bool read(std::istream& is) = 0; 444 //! write the vertex to a stream 445 virtual bool write(std::ostream& os) const = 0; 446 447 //! the internal ID of the edge internalIdOptimizableGraph448 long long internalId() const { return _internalId;} 449 450 OptimizableGraph* graph(); 451 const OptimizableGraph* graph() const; 452 453 bool setParameterId(int argNum, int paramId); parameterOptimizableGraph454 inline const Parameter* parameter(int argNo) const {return *_parameters.at(argNo);} numParametersOptimizableGraph455 inline size_t numParameters() const {return _parameters.size();} resizeParametersOptimizableGraph456 inline void resizeParameters(size_t newSize) { 457 _parameters.resize(newSize, 0); 458 _parameterIds.resize(newSize, -1); 459 _parameterTypes.resize(newSize, typeid(void*).name()); 460 } 461 protected: 462 int _dimension; 463 int _level; 464 RobustKernel* _robustKernel; 465 long long _internalId; 466 std::vector<int> _cacheIds; 467 468 template <typename ParameterType> 469 bool installParameter(ParameterType*& p, size_t argNo, int paramId = -1) { 470 if (argNo >= _parameters.size()) return false; 471 _parameterIds[argNo] = paramId; 472 _parameters[argNo] = (Parameter**)&p; 473 _parameterTypes[argNo] = typeid(ParameterType).name(); 474 return true; 475 } 476 477 template <typename CacheType> 478 void resolveCache(CacheType*& cache, OptimizableGraph::Vertex*, const std::string& _type, 479 const ParameterVector& parameters); 480 481 bool resolveParameters(); 482 virtual bool resolveCaches(); 483 484 std::vector<std::string> _parameterTypes; 485 std::vector<Parameter**> _parameters; 486 std::vector<int> _parameterIds; 487 }; 488 489 //! returns the vertex number <i>id</i> appropriately casted vertexOptimizableGraph490 inline Vertex* vertex(int id) { return reinterpret_cast<Vertex*>(HyperGraph::vertex(id));} 491 492 //! returns the vertex number <i>id</i> appropriately casted vertexOptimizableGraph493 inline const Vertex* vertex (int id) const{ return reinterpret_cast<const Vertex*>(HyperGraph::vertex(id));} 494 495 //! empty constructor 496 OptimizableGraph(); 497 virtual ~OptimizableGraph(); 498 499 /** 500 * adds a new vertex. The new vertex is then "taken". 501 * @return false if a vertex with the same id as v is already in the graph, true otherwise. 502 */ 503 virtual bool addVertex(HyperGraph::Vertex* v, Data* userData); addVertexOptimizableGraph504 virtual bool addVertex(HyperGraph::Vertex* v) { return addVertex(v, 0);} 505 bool addVertex(OptimizableGraph::Vertex* v, Data* userData); addVertexOptimizableGraph506 bool addVertex(OptimizableGraph::Vertex* v) { return addVertex(v, 0); } 507 508 /** 509 * adds a new edge. 510 * The edge should point to the vertices that it is connecting (setFrom/setTo). 511 * @return false if the insertion does not work (incompatible types of the vertices/missing vertex). true otherwise. 512 */ 513 virtual bool addEdge(HyperGraph::Edge* e); 514 bool addEdge(OptimizableGraph::Edge* e); 515 516 /** 517 * overridden from HyperGraph, to mantain the bookkeeping of the caches/parameters and jacobian workspaces consistent upon a change in the veretx. 518 * @return false if something goes wriong. 519 */ 520 virtual bool setEdgeVertex(HyperGraph::Edge* e, int pos, HyperGraph::Vertex* v); 521 522 //! returns the chi2 of the current configuration 523 number_t chi2() const; 524 525 //! return the maximum dimension of all vertices in the graph 526 int maxDimension() const; 527 528 //! Recompute the size of the Jacobian workspace from all the 529 //! edges in the graph. recomputeJacobianWorkspaceSizeOptimizableGraph530 void recomputeJacobianWorkspaceSize() 531 { 532 _jacobianWorkspace.updateSize(*this, true); 533 } 534 535 /** 536 * iterates over all vertices and returns a set of all the vertex dimensions in the graph 537 */ 538 std::set<int> dimensions() const; 539 540 /** 541 * carry out n iterations 542 * @return the number of performed iterations 543 */ 544 virtual int optimize(int iterations, bool online=false); 545 546 //! called at the beginning of an iteration (argument is the number of the iteration) 547 virtual void preIteration(int); 548 //! called at the end of an iteration (argument is the number of the iteration) 549 virtual void postIteration(int); 550 551 //! add an action to be executed before each iteration 552 bool addPreIterationAction(HyperGraphAction* action); 553 //! add an action to be executed after each iteration 554 bool addPostIterationAction(HyperGraphAction* action); 555 556 //! remove an action that should no longer be execured before each iteration 557 bool removePreIterationAction(HyperGraphAction* action); 558 //! remove an action that should no longer be execured after each iteration 559 bool removePostIterationAction(HyperGraphAction* action); 560 561 //! push the estimate of all variables onto a stack 562 virtual void push(); 563 //! pop (restore) the estimate of all variables from the stack 564 virtual void pop(); 565 //! discard the last backup of the estimate for all variables by removing it from the stack 566 virtual void discardTop(); 567 568 569 570 //! load the graph from a stream. Uses the Factory singleton for creating the vertices and edges. 571 virtual bool load(std::istream& is); 572 bool load(const char* filename); 573 //! save the graph to a stream. Again uses the Factory system. 574 virtual bool save(std::ostream& os, int level = 0) const; 575 //! function provided for convenience, see save() above 576 bool save(const char* filename, int level = 0) const; 577 578 579 //! save a subgraph to a stream. Again uses the Factory system. 580 bool saveSubset(std::ostream& os, HyperGraph::VertexSet& vset, int level = 0); 581 582 //! save a subgraph to a stream. Again uses the Factory system. 583 bool saveSubset(std::ostream& os, HyperGraph::EdgeSet& eset); 584 585 //! push the estimate of a subset of the variables onto a stack 586 virtual void push(HyperGraph::VertexSet& vset); 587 //! pop (restore) the estimate a subset of the variables from the stack 588 virtual void pop(HyperGraph::VertexSet& vset); 589 //! ignore the latest stored element on the stack, remove it from the stack but do not restore the estimate 590 virtual void discardTop(HyperGraph::VertexSet& vset); 591 592 //! fixes/releases a set of vertices 593 virtual void setFixed(HyperGraph::VertexSet& vset, bool fixed); 594 595 /** 596 * set the renamed types lookup from a string, format is for example: 597 * VERTEX_CAM=VERTEX_SE3:EXPMAP,EDGE_PROJECT_P2MC=EDGE_PROJECT_XYZ:EXPMAP 598 * This will change the occurance of VERTEX_CAM in the file to VERTEX_SE3:EXPMAP 599 */ 600 void setRenamedTypesFromString(const std::string& types); 601 602 /** 603 * test whether a solver is suitable for optimizing this graph. 604 * @param solverProperty the solver property to evaluate. 605 * @param vertDims should equal to the set returned by dimensions() to avoid re-evaluating. 606 */ 607 bool isSolverSuitable(const OptimizationAlgorithmProperty& solverProperty, const std::set<int>& vertDims = std::set<int>()) const; 608 609 /** 610 * remove the parameters of the graph 611 */ 612 virtual void clearParameters(); 613 addParameterOptimizableGraph614 bool addParameter(Parameter* p) { 615 return _parameters.addParameter(p); 616 } 617 parameterOptimizableGraph618 Parameter* parameter(int id) { 619 return _parameters.getParameter(id); 620 } 621 622 /** 623 * verify that all the information of the edges are semi positive definite, i.e., 624 * all Eigenvalues are >= 0. 625 * @param verbose output edges with not PSD information matrix on cerr 626 * @return true if all edges have PSD information matrix 627 */ 628 bool verifyInformationMatrices(bool verbose = false) const; 629 630 // helper functions to save an individual vertex 631 bool saveVertex(std::ostream& os, Vertex* v) const; 632 633 // helper function to save an individual parameter 634 bool saveParameter(std::ostream& os, Parameter* v) const; 635 636 // helper functions to save an individual edge 637 bool saveEdge(std::ostream& os, Edge* e) const; 638 639 // helper functions to save the data packets 640 bool saveUserData(std::ostream& os, HyperGraph::Data* v) const; 641 642 //! the workspace for storing the Jacobians of the graph jacobianWorkspaceOptimizableGraph643 JacobianWorkspace& jacobianWorkspace() { return _jacobianWorkspace;} jacobianWorkspaceOptimizableGraph644 const JacobianWorkspace& jacobianWorkspace() const { return _jacobianWorkspace;} 645 646 /** 647 * Eigen starting from version 3.1 requires that we call an initialize 648 * function, if we perform calls to Eigen from several threads. 649 * Currently, this function calls Eigen::initParallel if g2o is compiled 650 * with OpenMP support and Eigen's version is at least 3.1 651 */ 652 static bool initMultiThreading(); 653 parametersOptimizableGraph654 inline ParameterContainer& parameters() {return _parameters;} parametersOptimizableGraph655 inline const ParameterContainer& parameters() const {return _parameters;} 656 657 //! apply a unary function to all vertices 658 void forEachVertex(std::function<void(OptimizableGraph::Vertex*)> fn); 659 //! apply a unary function to the vertices in vset 660 void forEachVertex(HyperGraph::VertexSet& vset, std::function<void(OptimizableGraph::Vertex*)> fn); 661 662 protected: 663 std::map<std::string, std::string> _renamedTypesLookup; 664 long long _nextEdgeId; 665 std::vector<HyperGraphActionSet> _graphActions; 666 667 ParameterContainer _parameters; 668 JacobianWorkspace _jacobianWorkspace; 669 670 void performActions(int iter, HyperGraphActionSet& actions); 671 }; 672 673 /** 674 @} 675 */ 676 677 } // end namespace 678 679 #endif 680