/** * @file ISAM2-inl.h * @brief Incremental update functionality (ISAM2) for BayesTree, with fluid relinearization. * @author Michael Kaess */ #include #include // for operator += using namespace boost::assign; #include #include "NonlinearFactorGraph.h" #include "GaussianFactor.h" #include "VectorConfig.h" #include "Conditional.h" #include "BayesTree-inl.h" #include "ISAM2.h" namespace gtsam { using namespace std; /** Create an empty Bayes Tree */ template ISAM2::ISAM2() : BayesTree() {} /** Create a Bayes Tree from a nonlinear factor graph */ template ISAM2::ISAM2(const NonlinearFactorGraph& nlfg, const Ordering& ordering, const Config& config) : BayesTree(nlfg.linearize(config).eliminate(ordering)), nonlinearFactors_(nlfg), config_(config) {} /* ************************************************************************* */ template void ISAM2::update_internal(const NonlinearFactorGraph& newFactors, const Config& config, Cliques& orphans) { // copy variables into config_, but don't overwrite existing entries (current linearization point!) for (typename Config::const_iterator it = config.begin(); it!=config.end(); it++) { if (!config_.contains(it->first)) { config_.insert(it->first, it->second); } } nonlinearFactors_.push_back(newFactors); FactorGraph newFactorsLinearized = newFactors.linearize(config_); // Remove the contaminated part of the Bayes tree FactorGraph affectedFactors; boost::tie(affectedFactors, orphans) = this->removeTop(newFactorsLinearized); #if 1 // find the corresponding original nonlinear factors, and relinearize them NonlinearFactorGraph nonlinearAffectedFactors; set idxs; // avoid duplicates by putting index into set BOOST_FOREACH(FactorGraph::sharedFactor fac, affectedFactors) { // retrieve correspondent factor from nonlinearFactors_ Ordering keys = fac->keys(); BOOST_FOREACH(string key, keys) { list indices = nonlinearFactors_.factors(key); BOOST_FOREACH(int idx, indices) { // todo - only insert index if factor is subset of keys... not needed once we do relinearization - but then how to deal with overlap with orphans? bool subset = true; BOOST_FOREACH(string k, nonlinearFactors_[idx]->keys()) { if (find(keys.begin(), keys.end(), k)==keys.end()) subset = false; } if (subset) { idxs.insert(idx); } } } } BOOST_FOREACH(int idx, idxs) { nonlinearAffectedFactors.push_back(nonlinearFactors_[idx]); } FactorGraph factors = nonlinearAffectedFactors.linearize(config_); // add the new factors themselves factors.push_back(newFactorsLinearized); #endif affectedFactors.push_back(newFactorsLinearized); // create an ordering for the new and contaminated factors Ordering ordering; if (true) { ordering = /*affectedF*/factors.getOrdering(); } else { list keys = /*affectedF*/factors.keys(); keys.sort(); // todo: correct sorting order? ordering = keys; } // eliminate into a Bayes net BayesNet bayesNet = eliminate(affectedFactors,ordering); #if 1 BayesNet bayesNetTest = eliminate(factors,ordering); // todo - debug only if (!bayesNet.equals(bayesNetTest)) { printf("differ\n"); bayesNet.print(); bayesNetTest.print(); exit(42); } #endif // insert conditionals back in, straight into the topless bayesTree typename BayesNet::const_reverse_iterator rit; for ( rit=bayesNet.rbegin(); rit != bayesNet.rend(); ++rit ) this->insert(*rit); int count = 0; // add orphans to the bottom of the new tree BOOST_FOREACH(sharedClique orphan, orphans) { string key = orphan->separator_.front(); sharedClique parent = (*this)[key]; parent->children_ += orphan; orphan->parent_ = parent; // set new parent! } } template void ISAM2::update(const NonlinearFactorGraph& newFactors, const Config& config) { Cliques orphans; this->update_internal(newFactors, config, orphans); } /* ************************************************************************* */ } /// namespace gtsam