diff --git a/gtsam/hybrid/HybridFactorGraph.h b/gtsam/hybrid/HybridFactorGraph.h index f415386ea..f19eb0faf 100644 --- a/gtsam/hybrid/HybridFactorGraph.h +++ b/gtsam/hybrid/HybridFactorGraph.h @@ -20,15 +20,19 @@ #include #include +#include +#include #include #include +#include +#include namespace gtsam { /** * Hybrid Factor Graph * ----------------------- - * This is the non-linear version of a hybrid factor graph. + * This is the base hybrid factor graph. * Everything inside needs to be hybrid factor or hybrid conditional. */ class HybridFactorGraph : public FactorGraph { @@ -40,9 +44,22 @@ class HybridFactorGraph : public FactorGraph { using Values = gtsam::Values; ///< backwards compatibility using Indices = KeyVector; ///> map from keys to values + protected: + /// Check if FACTOR type is derived from DiscreteFactor. + template + using IsDiscrete = typename std::enable_if< + std::is_base_of::value>::type; + + /// Check if FACTOR type is derived from HybridFactor. + template + using IsHybrid = typename std::enable_if< + std::is_base_of::value>::type; + + public: /// @name Constructors /// @{ + /// Default constructor HybridFactorGraph() = default; /** @@ -61,46 +78,68 @@ class HybridFactorGraph : public FactorGraph { using Base::size; using FactorGraph::add; using Base::operator[]; - - /// Add a Jacobian factor to the factor graph. - void add(JacobianFactor&& factor); - - /// Add a Jacobian factor as a shared ptr. - void add(boost::shared_ptr factor); - - /// Add a DecisionTreeFactor to the factor graph. - void add(DecisionTreeFactor&& factor); - - /// Add a DecisionTreeFactor as a shared ptr. - void add(boost::shared_ptr factor); + using Base::resize; /** - * @brief Linearize all the continuous factors in the - * NonlinearHybridFactorGraph. - * - * @param continuousValues: Dictionary of continuous values. - * @return GaussianHybridFactorGraph::shared_ptr + * Add a discrete factor *pointer* to the internal discrete graph + * @param discreteFactor - boost::shared_ptr to the factor to add */ - GaussianHybridFactorGraph::shared_ptr linearize( - const Values& continuousValues) const { - // create an empty linear FG - GaussianHybridFactorGraph::shared_ptr linearFG = - boost::make_shared(); + template + IsDiscrete push_discrete( + const boost::shared_ptr& discreteFactor) { + Base::push_back(boost::make_shared(discreteFactor)); + } - linearFG->reserve(size()); + /** + * Add a discrete-continuous (Hybrid) factor *pointer* to the graph + * @param hybridFactor - boost::shared_ptr to the factor to add + */ + template + IsHybrid push_hybrid(const boost::shared_ptr& hybridFactor) { + Base::push_back(boost::make_shared(factor)); + } - // linearize all factors - for (const sharedFactor& factor : factors_) { - if (factor) { - if (auto nf = boost::dynamic_pointer_cast) { - (*linearFG) += factor->linearize(linearizationPoint); - } else if (auto hf = boost::dynamic_pointer_cast) { - if (hf->isContinuous()) { - } - } + /// delete emplace_shared. + template + void emplace_shared(Args&&... args) = delete; - } else - (*linearFG) += GaussianFactor::shared_ptr(); + /// Construct a factor and add (shared pointer to it) to factor graph. + template + IsDiscrete emplace_discrete(Args&&... args) { + auto factor = boost::allocate_shared( + Eigen::aligned_allocator(), std::forward(args)...); + push_discrete(factor); + } + + /// Construct a factor and add (shared pointer to it) to factor graph. + template + IsHybrid emplace_hybrid(Args&&... args) { + auto factor = boost::allocate_shared( + Eigen::aligned_allocator(), std::forward(args)...); + push_hybrid(factor); + } + + /** + * @brief Add a single factor shared pointer to the hybrid factor graph. + * Dynamically handles the factor type and assigns it to the correct + * underlying container. + * + * @param sharedFactor The factor to add to this factor graph. + */ + void push_back(const SharedFactor& sharedFactor) { + if (auto p = boost::dynamic_pointer_cast(sharedFactor)) { + push_discrete(p); + } + if (auto p = boost::dynamic_pointer_cast(sharedFactor)) { + push_hybrid(p); + } + } + + /** Constructor from iterator over factors (shared_ptr or plain objects) */ + template + void push_back(ITERATOR firstFactor, ITERATOR lastFactor) { + for (auto&& it = firstFactor; it != lastFactor; it++) { + push_back(*it); } } };