| 
									
										
										
										
											2009-09-09 12:43:04 +08:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * NonlinearOptimizer.h | 
					
						
							|  |  |  |  * @brief: Encapsulates nonlinear optimization state | 
					
						
							|  |  |  |  * @Author: Frank Dellaert | 
					
						
							|  |  |  |  * Created on: Sep 7, 2009 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifndef NONLINEAROPTIMIZER_H_
 | 
					
						
							|  |  |  | #define NONLINEAROPTIMIZER_H_
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <boost/shared_ptr.hpp>
 | 
					
						
							| 
									
										
										
										
											2009-10-15 04:39:59 +08:00
										 |  |  | #include "VectorConfig.h"
 | 
					
						
							| 
									
										
										
										
											2010-03-05 23:09:09 +08:00
										 |  |  | #include "NonlinearFactorGraph.h"
 | 
					
						
							|  |  |  | #include "Factorization.h"
 | 
					
						
							| 
									
										
										
										
											2009-09-09 12:43:04 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | namespace gtsam { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-22 16:13:54 +08:00
										 |  |  | 	class NullOptimizerWriter { | 
					
						
							|  |  |  | 	public: | 
					
						
							|  |  |  | 		NullOptimizerWriter(double error) {} | 
					
						
							|  |  |  | 		virtual void write(double error) {} | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-09 12:43:04 +08:00
										 |  |  | 	/**
 | 
					
						
							|  |  |  | 	 * The class NonlinearOptimizer encapsulates an optimization state. | 
					
						
							|  |  |  | 	 * Typically it is instantiated with a NonlinearFactorGraph and an initial config | 
					
						
							|  |  |  | 	 * and then one of the optimization routines is called. These recursively iterate | 
					
						
							|  |  |  | 	 * until convergence. All methods are functional and return a new state. | 
					
						
							|  |  |  | 	 * | 
					
						
							| 
									
										
										
										
											2010-01-19 18:46:12 +08:00
										 |  |  | 	 * The class is parameterized by the Graph type $G$, Config class type $T$, | 
					
						
							|  |  |  | 	 * linear system class $L$ and the non linear solver type $S$. | 
					
						
							| 
									
										
										
										
											2010-02-22 07:50:28 +08:00
										 |  |  | 	 * the config type is in order to be able to optimize over non-vector configurations. | 
					
						
							| 
									
										
										
										
											2009-10-20 03:12:48 +08:00
										 |  |  | 	 * To use in code, include <gtsam/NonlinearOptimizer-inl.h> in your cpp file | 
					
						
							| 
									
										
										
										
											2010-01-20 14:34:25 +08:00
										 |  |  | 	 * | 
					
						
							|  |  |  | 	 * For example, in a 2D case, $G$ can be Pose2Graph, $T$ can be Pose2Config, | 
					
						
							|  |  |  | 	 * $L$ can be GaussianFactorGraph and $S$ can be Factorization<Pose2Graph, Pose2Config>. | 
					
						
							| 
									
										
										
										
											2010-02-22 07:50:28 +08:00
										 |  |  | 	 * The solver class has two main functions: linearize and optimize. The first one | 
					
						
							|  |  |  | 	 * linearizes the nonlinear cost function around the current estimate, and the second | 
					
						
							|  |  |  | 	 * one optimizes the linearized system using various methods. | 
					
						
							| 
									
										
										
										
											2009-09-09 12:43:04 +08:00
										 |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2010-01-22 16:13:54 +08:00
										 |  |  | 	template<class G, class T, class L = GaussianFactorGraph, class S = Factorization<G, T>, class Writer = NullOptimizerWriter> | 
					
						
							| 
									
										
										
										
											2009-09-09 12:43:04 +08:00
										 |  |  | 	class NonlinearOptimizer { | 
					
						
							|  |  |  | 	public: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// For performance reasons in recursion, we store configs in a shared_ptr
 | 
					
						
							| 
									
										
										
										
											2010-01-19 18:46:12 +08:00
										 |  |  | 		typedef boost::shared_ptr<const T> shared_config; | 
					
						
							|  |  |  | 		typedef boost::shared_ptr<const G> shared_graph; | 
					
						
							|  |  |  | 		typedef boost::shared_ptr<const S> shared_solver; | 
					
						
							| 
									
										
										
										
											2010-01-20 10:28:23 +08:00
										 |  |  | 		typedef const S solver; | 
					
						
							| 
									
										
										
										
											2009-09-09 12:43:04 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		enum verbosityLevel { | 
					
						
							|  |  |  | 			SILENT, | 
					
						
							|  |  |  | 			ERROR, | 
					
						
							|  |  |  | 			LAMBDA, | 
					
						
							| 
									
										
										
										
											2010-03-16 02:38:08 +08:00
										 |  |  | 			TRYLAMBDA, | 
					
						
							| 
									
										
										
										
											2009-09-09 12:43:04 +08:00
										 |  |  | 			CONFIG, | 
					
						
							|  |  |  | 			DELTA, | 
					
						
							|  |  |  | 			TRYCONFIG, | 
					
						
							|  |  |  | 			TRYDELTA, | 
					
						
							| 
									
										
										
										
											2009-12-01 01:36:34 +08:00
										 |  |  | 			LINEAR, | 
					
						
							| 
									
										
										
										
											2009-09-09 12:43:04 +08:00
										 |  |  | 			DAMPED | 
					
						
							|  |  |  | 		}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-11 00:27:38 +08:00
										 |  |  | 		enum LambdaMode { | 
					
						
							|  |  |  | 			FAST, | 
					
						
							|  |  |  | 			BOUNDED, | 
					
						
							|  |  |  | 			CAUTIOUS | 
					
						
							|  |  |  | 		}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-09 12:43:04 +08:00
										 |  |  | 	private: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-20 10:28:23 +08:00
										 |  |  | 		// keep a reference to const version of the graph
 | 
					
						
							| 
									
										
										
										
											2009-09-09 12:43:04 +08:00
										 |  |  | 		// These normally do not change
 | 
					
						
							| 
									
										
										
										
											2010-01-12 04:17:28 +08:00
										 |  |  | 		const shared_graph graph_; | 
					
						
							| 
									
										
										
										
											2009-09-09 12:43:04 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// keep a configuration and its error
 | 
					
						
							|  |  |  | 		// These typically change once per iteration (in a functional way)
 | 
					
						
							| 
									
										
										
										
											2010-01-12 04:17:28 +08:00
										 |  |  | 		const shared_config config_; | 
					
						
							| 
									
										
										
										
											2010-03-05 23:09:09 +08:00
										 |  |  | 		double error_; // TODO FD: no more const because in constructor I need to set it after checking :-(
 | 
					
						
							| 
									
										
										
										
											2009-09-09 12:43:04 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// keep current lambda for use within LM only
 | 
					
						
							|  |  |  | 		// TODO: red flag, should we have an LM class ?
 | 
					
						
							| 
									
										
										
										
											2010-01-12 04:17:28 +08:00
										 |  |  | 		const double lambda_; | 
					
						
							| 
									
										
										
										
											2009-09-09 12:43:04 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-18 13:51:19 +08:00
										 |  |  | 		// the linear system solver
 | 
					
						
							|  |  |  | 		const shared_solver solver_; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-09 12:43:04 +08:00
										 |  |  | 		// Recursively try to do tempered Gauss-Newton steps until we succeed
 | 
					
						
							| 
									
										
										
										
											2010-01-19 18:46:12 +08:00
										 |  |  | 		NonlinearOptimizer try_lambda(const L& linear, | 
					
						
							| 
									
										
										
										
											2010-03-11 00:27:38 +08:00
										 |  |  | 				verbosityLevel verbosity, double factor, LambdaMode lambdaMode) const; | 
					
						
							| 
									
										
										
										
											2009-09-09 12:43:04 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	public: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/**
 | 
					
						
							|  |  |  | 		 * Constructor | 
					
						
							|  |  |  | 		 */ | 
					
						
							| 
									
										
										
										
											2010-01-20 10:28:23 +08:00
										 |  |  | 		NonlinearOptimizer(shared_graph graph, shared_config config, shared_solver solver, | 
					
						
							| 
									
										
										
										
											2010-01-18 13:51:19 +08:00
										 |  |  | 				double lambda = 1e-5); | 
					
						
							| 
									
										
										
										
											2009-09-09 12:43:04 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-12 04:17:28 +08:00
										 |  |  | 		/**
 | 
					
						
							|  |  |  | 		 * Copy constructor | 
					
						
							|  |  |  | 		 */ | 
					
						
							| 
									
										
										
										
											2010-01-19 18:46:12 +08:00
										 |  |  | 		NonlinearOptimizer(const NonlinearOptimizer<G, T, L, S> &optimizer) : | 
					
						
							| 
									
										
										
										
											2010-01-20 10:28:23 +08:00
										 |  |  | 		  graph_(optimizer.graph_), config_(optimizer.config_), | 
					
						
							| 
									
										
										
										
											2010-01-18 13:51:19 +08:00
										 |  |  | 		  error_(optimizer.error_), lambda_(optimizer.lambda_), solver_(optimizer.solver_) {} | 
					
						
							| 
									
										
										
										
											2010-01-12 04:17:28 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-09 12:43:04 +08:00
										 |  |  | 		/**
 | 
					
						
							|  |  |  | 		 * Return current error | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 		double error() const { | 
					
						
							|  |  |  | 			return error_; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/**
 | 
					
						
							|  |  |  | 		 * Return current lambda | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 		double lambda() const { | 
					
						
							|  |  |  | 			return lambda_; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-11 06:08:47 +08:00
										 |  |  | 		/**
 | 
					
						
							|  |  |  | 		 * Return the config | 
					
						
							|  |  |  | 		 */ | 
					
						
							| 
									
										
										
										
											2009-09-12 02:33:05 +08:00
										 |  |  | 		shared_config config() const{ | 
					
						
							| 
									
										
										
										
											2009-09-11 06:08:47 +08:00
										 |  |  | 			return config_; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-09 12:43:04 +08:00
										 |  |  | 		/**
 | 
					
						
							|  |  |  | 		 *  linearize and optimize | 
					
						
							| 
									
										
										
										
											2010-01-19 18:46:12 +08:00
										 |  |  | 		 *  This returns an VectorConfig, i.e., vectors in tangent space of T | 
					
						
							| 
									
										
										
										
											2009-09-09 12:43:04 +08:00
										 |  |  | 		 */ | 
					
						
							| 
									
										
										
										
											2009-10-20 03:12:48 +08:00
										 |  |  | 		VectorConfig linearizeAndOptimizeForDelta() const; | 
					
						
							| 
									
										
										
										
											2009-09-09 12:43:04 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		/**
 | 
					
						
							|  |  |  | 		 * Do one Gauss-Newton iteration and return next state | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 		NonlinearOptimizer iterate(verbosityLevel verbosity = SILENT) const; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/**
 | 
					
						
							|  |  |  | 		 * Optimize a solution for a non linear factor graph | 
					
						
							|  |  |  | 		 * @param relativeTreshold | 
					
						
							|  |  |  | 		 * @param absoluteTreshold | 
					
						
							|  |  |  | 		 * @param verbosity Integer specifying how much output to provide | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 		NonlinearOptimizer | 
					
						
							|  |  |  | 		gaussNewton(double relativeThreshold, double absoluteThreshold, | 
					
						
							|  |  |  | 				verbosityLevel verbosity = SILENT, int maxIterations = 100) const; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/**
 | 
					
						
							|  |  |  | 		 * One iteration of Levenberg Marquardt | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 		NonlinearOptimizer iterateLM(verbosityLevel verbosity = SILENT, | 
					
						
							| 
									
										
										
										
											2010-03-11 00:27:38 +08:00
										 |  |  | 				double lambdaFactor = 10, LambdaMode lambdaMode = BOUNDED) const; | 
					
						
							| 
									
										
										
										
											2009-09-09 12:43:04 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		/**
 | 
					
						
							|  |  |  | 		 * Optimize using Levenberg-Marquardt. Really Levenberg's | 
					
						
							|  |  |  | 		 * algorithm at this moment, as we just add I*\lambda to Hessian | 
					
						
							|  |  |  | 		 * H'H. The probabilistic explanation is very simple: every | 
					
						
							|  |  |  | 		 * variable gets an extra Gaussian prior that biases staying at | 
					
						
							|  |  |  | 		 * current value, with variance 1/lambda. This is done very easily | 
					
						
							|  |  |  | 		 * (but perhaps wastefully) by adding a prior factor for each of | 
					
						
							|  |  |  | 		 * the variables, after linearization. | 
					
						
							|  |  |  | 		 * | 
					
						
							|  |  |  | 		 * @param relativeThreshold | 
					
						
							|  |  |  | 		 * @param absoluteThreshold | 
					
						
							|  |  |  | 		 * @param verbosity    Integer specifying how much output to provide | 
					
						
							|  |  |  | 		 * @param lambdaFactor Factor by which to decrease/increase lambda | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 		NonlinearOptimizer | 
					
						
							|  |  |  | 		levenbergMarquardt(double relativeThreshold, double absoluteThreshold, | 
					
						
							|  |  |  | 				verbosityLevel verbosity = SILENT, int maxIterations = 100, | 
					
						
							| 
									
										
										
										
											2010-03-11 00:27:38 +08:00
										 |  |  | 				double lambdaFactor = 10, LambdaMode lambdaMode = BOUNDED) const; | 
					
						
							| 
									
										
										
										
											2009-09-09 12:43:04 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-07 02:25:04 +08:00
										 |  |  | 	/**
 | 
					
						
							|  |  |  | 	 * Check convergence | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	bool check_convergence (double relativeErrorTreshold, | 
					
						
							|  |  |  | 			double absoluteErrorTreshold, | 
					
						
							|  |  |  | 			double currentError, double newError, | 
					
						
							|  |  |  | 			int verbosity); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } // gtsam
 | 
					
						
							| 
									
										
										
										
											2009-09-09 12:43:04 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | #endif /* NONLINEAROPTIMIZER_H_ */
 |