| 
									
										
										
										
											2009-12-29 13:57:05 +08:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * @file    ISAM2-inl.h | 
					
						
							| 
									
										
										
										
											2009-12-30 12:27:14 +08:00
										 |  |  |  * @brief   Incremental update functionality (ISAM2) for BayesTree, with fluid relinearization. | 
					
						
							| 
									
										
										
										
											2009-12-29 13:57:05 +08:00
										 |  |  |  * @author  Michael Kaess | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <boost/foreach.hpp>
 | 
					
						
							|  |  |  | #include <boost/assign/std/list.hpp> // for operator +=
 | 
					
						
							|  |  |  | using namespace boost::assign; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-03 12:57:35 +08:00
										 |  |  | #include <set>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-16 09:16:59 +08:00
										 |  |  | #include "NonlinearFactorGraph-inl.h"
 | 
					
						
							| 
									
										
										
										
											2009-12-29 13:57:05 +08:00
										 |  |  | #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<class Conditional, class Config> | 
					
						
							|  |  |  | 	ISAM2<Conditional, Config>::ISAM2() : BayesTree<Conditional>() {} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-30 12:27:14 +08:00
										 |  |  | 	/** Create a Bayes Tree from a nonlinear factor graph */ | 
					
						
							| 
									
										
										
										
											2009-12-29 13:57:05 +08:00
										 |  |  | 	template<class Conditional, class Config> | 
					
						
							| 
									
										
										
										
											2009-12-31 13:35:08 +08:00
										 |  |  | 	ISAM2<Conditional, Config>::ISAM2(const NonlinearFactorGraph<Config>& nlfg, const Ordering& ordering, const Config& config) | 
					
						
							| 
									
										
										
										
											2010-01-03 12:57:35 +08:00
										 |  |  | 	: BayesTree<Conditional>(nlfg.linearize(config).eliminate(ordering)), nonlinearFactors_(nlfg), config_(config) {} | 
					
						
							| 
									
										
										
										
											2009-12-29 13:57:05 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* ************************************************************************* */ | 
					
						
							|  |  |  | 	template<class Conditional, class Config> | 
					
						
							| 
									
										
										
										
											2009-12-30 12:27:14 +08:00
										 |  |  | 	void ISAM2<Conditional, Config>::update_internal(const NonlinearFactorGraph<Config>& 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); | 
					
						
							| 
									
										
										
										
											2009-12-29 13:57:05 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-30 12:27:14 +08:00
										 |  |  | 		FactorGraph<GaussianFactor> newFactorsLinearized = newFactors.linearize(config_); | 
					
						
							| 
									
										
										
										
											2009-12-29 13:57:05 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// Remove the contaminated part of the Bayes tree
 | 
					
						
							| 
									
										
										
										
											2009-12-30 12:27:14 +08:00
										 |  |  | 		FactorGraph<GaussianFactor> affectedFactors; | 
					
						
							|  |  |  | 		boost::tie(affectedFactors, orphans) = this->removeTop(newFactorsLinearized); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-03 12:57:35 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | #if 1
 | 
					
						
							| 
									
										
										
										
											2009-12-30 12:27:14 +08:00
										 |  |  | 		// find the corresponding original nonlinear factors, and relinearize them
 | 
					
						
							|  |  |  | 		NonlinearFactorGraph<Config> nonlinearAffectedFactors; | 
					
						
							| 
									
										
										
										
											2010-01-03 12:57:35 +08:00
										 |  |  | 		set<int> idxs; // avoid duplicates by putting index into set
 | 
					
						
							| 
									
										
										
										
											2009-12-31 13:35:08 +08:00
										 |  |  | 		BOOST_FOREACH(FactorGraph<GaussianFactor>::sharedFactor fac, affectedFactors) { | 
					
						
							|  |  |  | 			// retrieve correspondent factor from nonlinearFactors_
 | 
					
						
							|  |  |  | 			Ordering keys = fac->keys(); | 
					
						
							| 
									
										
										
										
											2010-01-03 12:57:35 +08:00
										 |  |  | 			BOOST_FOREACH(string key, keys) { | 
					
						
							|  |  |  | 				list<int> 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); | 
					
						
							|  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2009-12-31 13:35:08 +08:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2009-12-30 12:27:14 +08:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2010-01-03 12:57:35 +08:00
										 |  |  | 		BOOST_FOREACH(int idx, idxs) { | 
					
						
							|  |  |  | 			nonlinearAffectedFactors.push_back(nonlinearFactors_[idx]); | 
					
						
							| 
									
										
										
										
											2009-12-31 13:35:08 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2010-01-03 12:57:35 +08:00
										 |  |  | 		FactorGraph<GaussianFactor> factors = nonlinearAffectedFactors.linearize(config_); | 
					
						
							| 
									
										
										
										
											2009-12-31 13:35:08 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-30 12:27:14 +08:00
										 |  |  | 		// add the new factors themselves
 | 
					
						
							|  |  |  | 		factors.push_back(newFactorsLinearized); | 
					
						
							| 
									
										
										
										
											2010-01-03 12:57:35 +08:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		affectedFactors.push_back(newFactorsLinearized); | 
					
						
							| 
									
										
										
										
											2009-12-29 13:57:05 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// create an ordering for the new and contaminated factors
 | 
					
						
							|  |  |  | 		Ordering ordering; | 
					
						
							|  |  |  | 		if (true) { | 
					
						
							| 
									
										
										
										
											2010-01-03 12:57:35 +08:00
										 |  |  | 			ordering = /*affectedF*/factors.getOrdering(); | 
					
						
							| 
									
										
										
										
											2009-12-29 13:57:05 +08:00
										 |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2010-01-03 12:57:35 +08:00
										 |  |  | 			list<string> keys = /*affectedF*/factors.keys(); | 
					
						
							| 
									
										
										
										
											2009-12-29 13:57:05 +08:00
										 |  |  | 			keys.sort(); // todo: correct sorting order?
 | 
					
						
							|  |  |  | 			ordering = keys; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// eliminate into a Bayes net
 | 
					
						
							| 
									
										
										
										
											2010-01-03 12:57:35 +08:00
										 |  |  | 		BayesNet<Conditional> bayesNet = eliminate<GaussianFactor, Conditional>(affectedFactors,ordering); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if 1
 | 
					
						
							|  |  |  | 		BayesNet<Conditional> bayesNetTest = eliminate<GaussianFactor, Conditional>(factors,ordering); // todo - debug only
 | 
					
						
							|  |  |  | 		if (!bayesNet.equals(bayesNetTest)) { | 
					
						
							|  |  |  | 			printf("differ\n"); | 
					
						
							|  |  |  | 			bayesNet.print(); | 
					
						
							|  |  |  | 			bayesNetTest.print(); | 
					
						
							|  |  |  | 			exit(42); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2009-12-29 13:57:05 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// insert conditionals back in, straight into the topless bayesTree
 | 
					
						
							|  |  |  | 		typename BayesNet<Conditional>::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<class Conditional, class Config> | 
					
						
							| 
									
										
										
										
											2009-12-29 22:54:45 +08:00
										 |  |  | 	void ISAM2<Conditional, Config>::update(const NonlinearFactorGraph<Config>& newFactors, const Config& config) { | 
					
						
							| 
									
										
										
										
											2009-12-29 13:57:05 +08:00
										 |  |  | 		Cliques orphans; | 
					
						
							| 
									
										
										
										
											2009-12-29 22:54:45 +08:00
										 |  |  | 		this->update_internal(newFactors, config, orphans); | 
					
						
							| 
									
										
										
										
											2009-12-29 13:57:05 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | /// namespace gtsam
 |