179 lines
6.4 KiB
C++
179 lines
6.4 KiB
C++
/* ----------------------------------------------------------------------------
|
|
|
|
* GTSAM Copyright 2010, Georgia Tech Research Corporation,
|
|
* Atlanta, Georgia 30332-0415
|
|
* All Rights Reserved
|
|
* Authors: Frank Dellaert, et al. (see THANKS for the full author list)
|
|
|
|
* See LICENSE for the license information
|
|
|
|
* -------------------------------------------------------------------------- */
|
|
|
|
/**
|
|
* @file ISAM2Clique.h
|
|
* @brief Specialized iSAM2 Clique
|
|
* @author Michael Kaess, Richard Roberts
|
|
*/
|
|
|
|
// \callgraph
|
|
|
|
#pragma once
|
|
|
|
#include <gtsam/inference/BayesTreeCliqueBase.h>
|
|
#include <gtsam/inference/Key.h>
|
|
#include <gtsam/linear/GaussianBayesNet.h>
|
|
#include <gtsam/linear/GaussianConditional.h>
|
|
#include <gtsam/linear/GaussianFactorGraph.h>
|
|
#include <string>
|
|
|
|
namespace gtsam {
|
|
|
|
/**
|
|
* Specialized Clique structure for ISAM2, incorporating caching and gradient
|
|
* contribution
|
|
* TODO: more documentation
|
|
*/
|
|
class GTSAM_EXPORT ISAM2Clique
|
|
: public BayesTreeCliqueBase<ISAM2Clique, GaussianFactorGraph> {
|
|
public:
|
|
typedef ISAM2Clique This;
|
|
typedef BayesTreeCliqueBase<This, GaussianFactorGraph> Base;
|
|
typedef boost::shared_ptr<This> shared_ptr;
|
|
typedef boost::weak_ptr<This> weak_ptr;
|
|
typedef GaussianConditional ConditionalType;
|
|
typedef ConditionalType::shared_ptr sharedConditional;
|
|
|
|
Base::FactorType::shared_ptr cachedFactor_;
|
|
Vector gradientContribution_;
|
|
#ifdef USE_BROKEN_FAST_BACKSUBSTITUTE
|
|
mutable FastMap<Key, VectorValues::iterator> solnPointers_;
|
|
#endif
|
|
|
|
/// Default constructor
|
|
ISAM2Clique() : Base() {}
|
|
virtual ~ISAM2Clique() = default;
|
|
|
|
/// Copy constructor, does *not* copy solution pointers as these are invalid
|
|
/// in different trees.
|
|
ISAM2Clique(const ISAM2Clique& other)
|
|
: Base(other),
|
|
cachedFactor_(other.cachedFactor_),
|
|
gradientContribution_(other.gradientContribution_) {}
|
|
|
|
/// Assignment operator, does *not* copy solution pointers as these are
|
|
/// invalid in different trees.
|
|
ISAM2Clique& operator=(const ISAM2Clique& other) {
|
|
Base::operator=(other);
|
|
cachedFactor_ = other.cachedFactor_;
|
|
gradientContribution_ = other.gradientContribution_;
|
|
return *this;
|
|
}
|
|
|
|
/// Overridden to also store the remaining factor and gradient contribution
|
|
void setEliminationResult(
|
|
const FactorGraphType::EliminationResult& eliminationResult);
|
|
|
|
/** Access the cached factor */
|
|
Base::FactorType::shared_ptr& cachedFactor() { return cachedFactor_; }
|
|
|
|
/// Access the gradient contribution
|
|
const Vector& gradientContribution() const { return gradientContribution_; }
|
|
|
|
/// Recursively add gradient at zero to g
|
|
void addGradientAtZero(VectorValues* g) const;
|
|
|
|
bool equals(const This& other, double tol = 1e-9) const;
|
|
|
|
/** print this node */
|
|
void print(const std::string& s = "",
|
|
const KeyFormatter& formatter = DefaultKeyFormatter) const override;
|
|
|
|
void optimizeWildfire(const KeySet& replaced, double threshold,
|
|
KeySet* changed, VectorValues* delta,
|
|
size_t* count) const;
|
|
|
|
bool optimizeWildfireNode(const KeySet& replaced, double threshold,
|
|
KeySet* changed, VectorValues* delta,
|
|
size_t* count) const;
|
|
|
|
/**
|
|
* Starting from the root, add up entries of frontal and conditional matrices
|
|
* of each conditional
|
|
*/
|
|
void nnz_internal(size_t* result) const;
|
|
size_t calculate_nnz() const;
|
|
|
|
/**
|
|
* Recursively search this clique and its children for marked keys appearing
|
|
* in the separator, and add the *frontal* keys of any cliques whose
|
|
* separator contains any marked keys to the set \c keys. The purpose of
|
|
* this is to discover the cliques that need to be redone due to information
|
|
* propagating to them from cliques that directly contain factors being
|
|
* relinearized.
|
|
*
|
|
* The original comment says this finds all variables directly connected to
|
|
* the marked ones by measurements. Is this true, because it seems like this
|
|
* would also pull in variables indirectly connected through other frontal or
|
|
* separator variables?
|
|
*
|
|
* Alternatively could we trace up towards the root for each variable here?
|
|
*/
|
|
void findAll(const KeySet& markedMask, KeySet* keys) const;
|
|
|
|
private:
|
|
/**
|
|
* Check if clique was replaced, or if any parents were changed above the
|
|
* threshold or themselves replaced.
|
|
*/
|
|
bool isDirty(const KeySet& replaced, const KeySet& changed) const;
|
|
|
|
/**
|
|
* Back-substitute - special version stores solution pointers in cliques for
|
|
* fast access.
|
|
*/
|
|
void fastBackSubstitute(VectorValues* delta) const;
|
|
|
|
/*
|
|
* Check whether the values changed above a threshold, or always true if the
|
|
* clique was replaced.
|
|
*/
|
|
bool valuesChanged(const KeySet& replaced, const Vector& originalValues,
|
|
const VectorValues& delta, double threshold) const;
|
|
|
|
/// Set changed flag for each frontal variable
|
|
void markFrontalsAsChanged(KeySet* changed) const;
|
|
|
|
/// Restore delta to original values, guided by frontal keys.
|
|
void restoreFromOriginals(const Vector& originalValues,
|
|
VectorValues* delta) const;
|
|
|
|
/** Serialization function */
|
|
friend class boost::serialization::access;
|
|
template <class ARCHIVE>
|
|
void serialize(ARCHIVE& ar, const unsigned int /*version*/) {
|
|
ar& BOOST_SERIALIZATION_BASE_OBJECT_NVP(Base);
|
|
ar& BOOST_SERIALIZATION_NVP(cachedFactor_);
|
|
ar& BOOST_SERIALIZATION_NVP(gradientContribution_);
|
|
}
|
|
}; // \struct ISAM2Clique
|
|
|
|
/**
|
|
* Optimize the BayesTree, starting from the root.
|
|
* @param threshold The maximum change against the PREVIOUS delta for
|
|
* non-replaced variables that can be ignored, ie. the old delta entry is kept
|
|
* and recursive backsubstitution might eventually stop if none of the changed
|
|
* variables are contained in the subtree.
|
|
* @param replaced Needs to contain all variables that are contained in the top
|
|
* of the Bayes tree that has been redone.
|
|
* @return The number of variables that were solved for.
|
|
* @param delta The current solution, an offset from the linearization point.
|
|
*/
|
|
size_t optimizeWildfire(const ISAM2Clique::shared_ptr& root, double threshold,
|
|
const KeySet& replaced, VectorValues* delta);
|
|
|
|
size_t optimizeWildfireNonRecursive(const ISAM2Clique::shared_ptr& root,
|
|
double threshold, const KeySet& replaced,
|
|
VectorValues* delta);
|
|
|
|
} // namespace gtsam
|