| 
									
										
										
										
											2014-10-01 20:10:54 +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 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  * -------------------------------------------------------------------------- */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2014-10-03 02:19:49 +08:00
										 |  |  |  * @file    SFMExampleExpressions.cpp | 
					
						
							| 
									
										
										
										
											2014-10-01 20:10:54 +08:00
										 |  |  |  * @brief   A structure-from-motion example done with Expressions | 
					
						
							|  |  |  |  * @author  Frank Dellaert | 
					
						
							|  |  |  |  * @author  Duy-Nguyen Ta | 
					
						
							|  |  |  |  * @date    October 1, 2014 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * This is the Expression version of SFMExample | 
					
						
							|  |  |  |  * See detailed description of headers there, this focuses on explaining the AD part | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // The two new headers that allow using our Automatic Differentiation Expression framework
 | 
					
						
							|  |  |  | #include <gtsam_unstable/slam/expressions.h>
 | 
					
						
							| 
									
										
										
										
											2014-10-09 19:00:56 +08:00
										 |  |  | #include <gtsam_unstable/nonlinear/ExpressionFactor.h>
 | 
					
						
							| 
									
										
										
										
											2014-10-01 20:10:54 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | // Header order is close to far
 | 
					
						
							|  |  |  | #include <examples/SFMdata.h>
 | 
					
						
							|  |  |  | #include <gtsam/slam/PriorFactor.h>
 | 
					
						
							|  |  |  | #include <gtsam/slam/ProjectionFactor.h>
 | 
					
						
							|  |  |  | #include <gtsam/geometry/Point2.h>
 | 
					
						
							|  |  |  | #include <gtsam/nonlinear/NonlinearFactorGraph.h>
 | 
					
						
							|  |  |  | #include <gtsam/nonlinear/DoglegOptimizer.h>
 | 
					
						
							|  |  |  | #include <gtsam/nonlinear/Values.h>
 | 
					
						
							|  |  |  | #include <gtsam/inference/Symbol.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <vector>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | using namespace std; | 
					
						
							|  |  |  | using namespace gtsam; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | int main(int argc, char* argv[]) { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-02 17:21:24 +08:00
										 |  |  |   Cal3_S2 K(50.0, 50.0, 0.0, 50.0, 50.0); | 
					
						
							| 
									
										
										
										
											2014-10-01 20:10:54 +08:00
										 |  |  |   noiseModel::Isotropic::shared_ptr measurementNoise = noiseModel::Isotropic::Sigma(2, 1.0); // one pixel in u and v
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Create the set of ground-truth landmarks and poses
 | 
					
						
							|  |  |  |   vector<Point3> points = createPoints(); | 
					
						
							|  |  |  |   vector<Pose3> poses = createPoses(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Create a factor graph
 | 
					
						
							|  |  |  |   NonlinearFactorGraph graph; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Specify uncertainty on first pose prior
 | 
					
						
							|  |  |  |   noiseModel::Diagonal::shared_ptr poseNoise = noiseModel::Diagonal::Sigmas((Vector(6) << Vector3::Constant(0.3), Vector3::Constant(0.1))); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-09 19:00:56 +08:00
										 |  |  |   // Here we don't use a PriorFactor but directly the ExpressionFactor class
 | 
					
						
							| 
									
										
										
										
											2014-10-01 20:10:54 +08:00
										 |  |  |   // The object x0 is an Expression, and we create a factor wanting it to be equal to poses[0]
 | 
					
						
							|  |  |  |   Pose3_ x0('x',0); | 
					
						
							| 
									
										
										
										
											2014-10-09 19:00:56 +08:00
										 |  |  |   graph.push_back(ExpressionFactor<Pose3>(poseNoise, poses[0], x0)); | 
					
						
							| 
									
										
										
										
											2014-10-02 17:21:24 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // We create a constant Expression for the calibration here
 | 
					
						
							|  |  |  |   Cal3_S2_ cK(K); | 
					
						
							| 
									
										
										
										
											2014-10-01 20:10:54 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // Simulated measurements from each camera pose, adding them to the factor graph
 | 
					
						
							|  |  |  |   for (size_t i = 0; i < poses.size(); ++i) { | 
					
						
							| 
									
										
										
										
											2014-10-02 17:44:16 +08:00
										 |  |  |     Pose3_ x('x', i); | 
					
						
							|  |  |  |     SimpleCamera camera(poses[i], K); | 
					
						
							| 
									
										
										
										
											2014-10-01 20:10:54 +08:00
										 |  |  |     for (size_t j = 0; j < points.size(); ++j) { | 
					
						
							|  |  |  |       Point2 measurement = camera.project(points[j]); | 
					
						
							| 
									
										
										
										
											2014-10-02 17:21:24 +08:00
										 |  |  |       // Below an expression for the prediction of the measurement:
 | 
					
						
							|  |  |  |       Point3_ p('l', j); | 
					
						
							| 
									
										
										
										
											2014-10-03 02:19:49 +08:00
										 |  |  |       Point2_ prediction = uncalibrate(cK, project(transform_to(x, p))); | 
					
						
							| 
									
										
										
										
											2014-10-09 19:00:56 +08:00
										 |  |  |       // Again, here we use a ExpressionFactor
 | 
					
						
							|  |  |  |       graph.push_back(ExpressionFactor<Point2>(measurementNoise, measurement, prediction)); | 
					
						
							| 
									
										
										
										
											2014-10-01 20:10:54 +08:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-09 19:00:56 +08:00
										 |  |  |   // Add prior on first point to constrain scale, again with ExpressionFactor
 | 
					
						
							| 
									
										
										
										
											2014-10-01 20:10:54 +08:00
										 |  |  |   noiseModel::Isotropic::shared_ptr pointNoise = noiseModel::Isotropic::Sigma(3, 0.1); | 
					
						
							| 
									
										
										
										
											2014-10-09 19:00:56 +08:00
										 |  |  |   graph.push_back(ExpressionFactor<Point3>(pointNoise, points[0], Point3_('l', 0))); | 
					
						
							| 
									
										
										
										
											2014-10-01 20:10:54 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-02 17:21:24 +08:00
										 |  |  |   // Create perturbed initial
 | 
					
						
							| 
									
										
										
										
											2014-10-01 20:10:54 +08:00
										 |  |  |   Values initialEstimate; | 
					
						
							|  |  |  |   for (size_t i = 0; i < poses.size(); ++i) | 
					
						
							|  |  |  |     initialEstimate.insert(Symbol('x', i), poses[i].compose(Pose3(Rot3::rodriguez(-0.1, 0.2, 0.25), Point3(0.05, -0.10, 0.20)))); | 
					
						
							|  |  |  |   for (size_t j = 0; j < points.size(); ++j) | 
					
						
							|  |  |  |     initialEstimate.insert(Symbol('l', j), points[j].compose(Point3(-0.25, 0.20, 0.15))); | 
					
						
							| 
									
										
										
										
											2014-10-02 17:21:24 +08:00
										 |  |  |   cout << "initial error = " << graph.error(initialEstimate) << endl; | 
					
						
							| 
									
										
										
										
											2014-10-01 20:10:54 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* Optimize the graph and print results */ | 
					
						
							|  |  |  |   Values result = DoglegOptimizer(graph, initialEstimate).optimize(); | 
					
						
							| 
									
										
										
										
											2014-10-02 17:21:24 +08:00
										 |  |  |   cout << "final error = " << graph.error(result) << endl; | 
					
						
							| 
									
										
										
										
											2014-10-01 20:10:54 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | 
 |