| 
									
										
										
										
											2010-10-14 12:54:38 +08:00
										 |  |  | /* ----------------------------------------------------------------------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  * 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 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  * -------------------------------------------------------------------------- */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-27 02:46:48 +08:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * SimpleRotation.cpp | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This is a super-simple example of optimizing a single rotation according to a single prior | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *  Created on: Jul 1, 2010 | 
					
						
							|  |  |  |  *  @Author: Frank Dellaert | 
					
						
							|  |  |  |  *  @Author: Alex Cunningham | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-03-21 23:05:40 +08:00
										 |  |  | #include <cmath>
 | 
					
						
							| 
									
										
										
										
											2010-08-27 03:55:40 +08:00
										 |  |  | #include <iostream>
 | 
					
						
							| 
									
										
										
										
											2010-08-27 02:46:48 +08:00
										 |  |  | #include <gtsam/slam/PriorFactor.h>
 | 
					
						
							|  |  |  | #include <gtsam/geometry/Rot2.h>
 | 
					
						
							|  |  |  | #include <gtsam/linear/NoiseModel.h>
 | 
					
						
							| 
									
										
										
										
											2010-10-09 06:04:47 +08:00
										 |  |  | #include <gtsam/nonlinear/Key.h>
 | 
					
						
							| 
									
										
										
										
											2010-10-09 11:09:55 +08:00
										 |  |  | #include <gtsam/nonlinear/LieValues-inl.h>
 | 
					
						
							| 
									
										
										
										
											2010-08-27 02:46:48 +08:00
										 |  |  | #include <gtsam/nonlinear/NonlinearFactorGraph-inl.h>
 | 
					
						
							| 
									
										
										
										
											2010-10-18 02:52:52 +08:00
										 |  |  | #include <gtsam/nonlinear/NonlinearOptimization-inl.h>
 | 
					
						
							| 
									
										
										
										
											2011-08-12 01:18:40 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-27 02:46:48 +08:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2010-10-09 11:09:58 +08:00
										 |  |  |  * TODO: make factors independent of Values | 
					
						
							| 
									
										
										
										
											2010-08-27 02:46:48 +08:00
										 |  |  |  * TODO: make toplevel documentation | 
					
						
							| 
									
										
										
										
											2011-08-12 01:18:40 +08:00
										 |  |  |  * TODO: Clean up nonlinear optimization API | 
					
						
							| 
									
										
										
										
											2010-08-27 02:46:48 +08:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | using namespace std; | 
					
						
							|  |  |  | using namespace gtsam; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-12 01:18:40 +08:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  *   Step 1: Setup basic types for optimization of a single variable type | 
					
						
							|  |  |  |  * This can be considered to be specifying the domain of the problem we wish | 
					
						
							|  |  |  |  * to solve.  In this case, we will create a very simple domain that operates | 
					
						
							|  |  |  |  * on variables of a specific type, in this case, Rot2. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * To create a domain: | 
					
						
							|  |  |  |  *  - variable types need to have a key defined to act as a label in graphs | 
					
						
							|  |  |  |  *  - a "Values" structure needs to be defined to store the system state | 
					
						
							|  |  |  |  *  - a graph container acting on a given Values | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * In a typical scenario, these typedefs could be placed in a header | 
					
						
							| 
									
										
										
										
											2011-08-13 03:24:59 +08:00
										 |  |  |  * file and reused between projects.  Also, LieValues can be combined to | 
					
						
							|  |  |  |  * form a "TupleValues" to enable multiple variable types, such as 2D points | 
					
						
							|  |  |  |  * and 2D poses. | 
					
						
							| 
									
										
										
										
											2011-08-12 01:18:40 +08:00
										 |  |  |  */ | 
					
						
							|  |  |  | typedef TypedSymbol<Rot2, 'x'> Key; 								/// Variable labels for a specific type
 | 
					
						
							|  |  |  | typedef LieValues<Key> Values;											/// Class to store values - acts as a state for the system
 | 
					
						
							|  |  |  | typedef NonlinearFactorGraph<Values> Graph;					/// Graph container for constraints - needs to know type of variables
 | 
					
						
							| 
									
										
										
										
											2010-08-27 02:46:48 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | const double degree = M_PI / 180; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int main() { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-12 01:18:40 +08:00
										 |  |  | 	/**
 | 
					
						
							|  |  |  | 	 * This example will perform a relatively trivial optimization on | 
					
						
							|  |  |  | 	 * a single variable with a single factor. | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2010-08-27 02:46:48 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-12 01:18:40 +08:00
										 |  |  | 	/**
 | 
					
						
							|  |  |  | 	 *    Step 2: create a factor on to express a unary constraint | 
					
						
							|  |  |  | 	 * The "prior" in this case is the measurement from a sensor, | 
					
						
							|  |  |  | 	 * with a model of the noise on the measurement. | 
					
						
							|  |  |  | 	 * | 
					
						
							|  |  |  | 	 * The "Key" created here is a label used to associate parts of the | 
					
						
							|  |  |  | 	 * state (stored in "Values") with particular factors.  They require | 
					
						
							|  |  |  | 	 * an index to allow for lookup, and should be unique. | 
					
						
							|  |  |  | 	 * | 
					
						
							|  |  |  | 	 * In general, creating a factor requires: | 
					
						
							|  |  |  | 	 *  - A key or set of keys labeling the variables that are acted upon | 
					
						
							|  |  |  | 	 *  - A measurement value | 
					
						
							|  |  |  | 	 *  - A measurement model with the correct dimensionality for the factor | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	Rot2 prior = Rot2::fromAngle(30 * degree); | 
					
						
							|  |  |  | 	prior.print("goal angle"); | 
					
						
							|  |  |  | 	SharedDiagonal model = noiseModel::Isotropic::Sigma(1, 1 * degree); | 
					
						
							|  |  |  | 	Key key(1); | 
					
						
							|  |  |  | 	PriorFactor<Values, Key> factor(key, prior, model); | 
					
						
							| 
									
										
										
										
											2010-08-27 02:46:48 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-12 01:18:40 +08:00
										 |  |  | 	/**
 | 
					
						
							|  |  |  | 	 *    Step 3: create a graph container and add the factor to it | 
					
						
							|  |  |  | 	 * Before optimizing, all factors need to be added to a Graph container, | 
					
						
							|  |  |  | 	 * which provides the necessary top-level functionality for defining a | 
					
						
							|  |  |  | 	 * system of constraints. | 
					
						
							|  |  |  | 	 * | 
					
						
							|  |  |  | 	 * In this case, there is only one factor, but in a practical scenario, | 
					
						
							|  |  |  | 	 * many more factors would be added. | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2010-08-27 02:46:48 +08:00
										 |  |  | 	Graph graph; | 
					
						
							| 
									
										
										
										
											2011-08-12 01:18:40 +08:00
										 |  |  | 	graph.add(factor); | 
					
						
							|  |  |  | 	graph.print("full graph"); | 
					
						
							| 
									
										
										
										
											2010-08-27 02:46:48 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-12 01:18:40 +08:00
										 |  |  | 	/**
 | 
					
						
							|  |  |  | 	 *    Step 4: create an initial estimate | 
					
						
							|  |  |  | 	 * An initial estimate of the solution for the system is necessary to | 
					
						
							|  |  |  | 	 * start optimization.  This system state is the "Values" structure, | 
					
						
							|  |  |  | 	 * which is similar in structure to a STL map, in that it maps | 
					
						
							|  |  |  | 	 * keys (the label created in step 1) to specific values. | 
					
						
							|  |  |  | 	 * | 
					
						
							|  |  |  | 	 * The initial estimate provided to optimization will be used as | 
					
						
							|  |  |  | 	 * a linearization point for optimization, so it is important that | 
					
						
							|  |  |  | 	 * all of the variables in the graph have a corresponding value in | 
					
						
							|  |  |  | 	 * this structure. | 
					
						
							| 
									
										
										
										
											2011-08-13 03:24:59 +08:00
										 |  |  | 	 * | 
					
						
							|  |  |  | 	 * The interface to all Values types is the same, it only depends | 
					
						
							|  |  |  | 	 * on the type of key used to find the appropriate value map if there | 
					
						
							|  |  |  | 	 * are multiple types of variables. | 
					
						
							| 
									
										
										
										
											2011-08-12 01:18:40 +08:00
										 |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2010-10-22 05:38:38 +08:00
										 |  |  | 	Values initial; | 
					
						
							| 
									
										
										
										
											2011-08-12 01:18:40 +08:00
										 |  |  | 	initial.insert(key, Rot2::fromAngle(20 * degree)); | 
					
						
							| 
									
										
										
										
											2010-10-22 05:38:38 +08:00
										 |  |  | 	initial.print("initial estimate"); | 
					
						
							| 
									
										
										
										
											2010-08-27 02:46:48 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-12 01:18:40 +08:00
										 |  |  | 	/**
 | 
					
						
							|  |  |  | 	 *    Step 5: optimize | 
					
						
							|  |  |  | 	 * After formulating the problem with a graph of constraints | 
					
						
							|  |  |  | 	 * and an initial estimate, executing optimization is as simple | 
					
						
							|  |  |  | 	 * as calling a general optimization function with the graph and | 
					
						
							|  |  |  | 	 * initial estimate.  This will yield a new Values structure | 
					
						
							|  |  |  | 	 * with the final state of the optimization. | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2010-10-22 05:38:38 +08:00
										 |  |  | 	Values result = optimize<Graph, Values>(graph, initial); | 
					
						
							|  |  |  | 	result.print("final result"); | 
					
						
							| 
									
										
										
										
											2010-08-27 02:46:48 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } |