| 
									
										
										
										
											2013-10-18 13:32:20 +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 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  * -------------------------------------------------------------------------- */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * @file    SFMExample.cpp | 
					
						
							|  |  |  |  * @brief   Solve a structure-from-motion problem from a "Bundle Adjustment in the Large" file | 
					
						
							|  |  |  |  * @author  Frank Dellaert | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // For an explanation of headers, see SFMExample.cpp
 | 
					
						
							|  |  |  | #include <gtsam/inference/Symbol.h>
 | 
					
						
							|  |  |  | #include <gtsam/nonlinear/NonlinearFactorGraph.h>
 | 
					
						
							|  |  |  | #include <gtsam/nonlinear/LevenbergMarquardtOptimizer.h>
 | 
					
						
							|  |  |  | #include <gtsam/slam/PriorFactor.h>
 | 
					
						
							|  |  |  | #include <gtsam/slam/GeneralSFMFactor.h>
 | 
					
						
							|  |  |  | #include <gtsam/slam/dataset.h> // for loading BAL datasets !
 | 
					
						
							|  |  |  | #include <vector>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | using namespace std; | 
					
						
							|  |  |  | using namespace gtsam; | 
					
						
							| 
									
										
										
										
											2013-10-18 14:04:48 +08:00
										 |  |  | using symbol_shorthand::C; | 
					
						
							|  |  |  | using symbol_shorthand::P; | 
					
						
							| 
									
										
										
										
											2013-10-18 13:32:20 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | // We will be using a projection factor that ties a SFM_Camera to a 3D point.
 | 
					
						
							|  |  |  | // An SFM_Camera is defined in datase.h as a camera with unknown Cal3Bundler calibration
 | 
					
						
							|  |  |  | // and has a total of 9 free parameters
 | 
					
						
							|  |  |  | typedef GeneralSFMFactor<SfM_Camera,Point3> MyFactor; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | int main (int argc, char* argv[]) { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-18 14:04:48 +08:00
										 |  |  |   // Find default file, but if an argument is given, try loading a file
 | 
					
						
							| 
									
										
										
										
											2013-10-18 13:32:20 +08:00
										 |  |  |   string filename = findExampleDataFile("dubrovnik-3-7-pre"); | 
					
						
							|  |  |  |   if (argc>1) filename = string(argv[1]); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-18 14:04:48 +08:00
										 |  |  |   // Load the SfM data from file
 | 
					
						
							| 
									
										
										
										
											2013-10-27 01:10:42 +08:00
										 |  |  |   SfM_data mydata; | 
					
						
							| 
									
										
										
										
											2014-07-01 23:21:23 +08:00
										 |  |  |   assert(readBAL(filename, mydata)); | 
					
						
							| 
									
										
										
										
											2013-10-18 14:04:48 +08:00
										 |  |  |   cout << boost::format("read %1% tracks on %2% cameras\n") % mydata.number_tracks() % mydata.number_cameras(); | 
					
						
							| 
									
										
										
										
											2013-10-18 13:32:20 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // Create a factor graph
 | 
					
						
							|  |  |  |   NonlinearFactorGraph graph; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-18 14:04:48 +08:00
										 |  |  |   // We share *one* noiseModel between all projection factors
 | 
					
						
							| 
									
										
										
										
											2013-10-18 13:32:20 +08:00
										 |  |  |   noiseModel::Isotropic::shared_ptr noise = | 
					
						
							|  |  |  |       noiseModel::Isotropic::Sigma(2, 1.0); // one pixel in u and v
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Add measurements to the factor graph
 | 
					
						
							|  |  |  |   size_t j = 0; | 
					
						
							|  |  |  |   BOOST_FOREACH(const SfM_Track& track, mydata.tracks) { | 
					
						
							| 
									
										
										
										
											2013-10-18 14:04:48 +08:00
										 |  |  |     BOOST_FOREACH(const SfM_Measurement& m, track.measurements) { | 
					
						
							|  |  |  |       size_t i = m.first; | 
					
						
							|  |  |  |       Point2 uv = m.second; | 
					
						
							|  |  |  |       graph.push_back(MyFactor(uv, noise, C(i), P(j))); // note use of shorthand symbols C and P
 | 
					
						
							| 
									
										
										
										
											2013-10-18 13:32:20 +08:00
										 |  |  |     } | 
					
						
							|  |  |  |     j += 1; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Add a prior on pose x1. This indirectly specifies where the origin is.
 | 
					
						
							| 
									
										
										
										
											2013-10-18 14:04:48 +08:00
										 |  |  |   // and a prior on the position of the first landmark to fix the scale
 | 
					
						
							|  |  |  |   graph.push_back(PriorFactor<SfM_Camera>(C(0), mydata.cameras[0],  noiseModel::Isotropic::Sigma(9, 0.1))); | 
					
						
							|  |  |  |   graph.push_back(PriorFactor<Point3>    (P(0), mydata.tracks[0].p, noiseModel::Isotropic::Sigma(3, 0.1))); | 
					
						
							| 
									
										
										
										
											2013-10-18 13:32:20 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-18 14:04:48 +08:00
										 |  |  |   // Create initial estimate
 | 
					
						
							| 
									
										
										
										
											2013-10-18 13:32:20 +08:00
										 |  |  |   Values initial; | 
					
						
							| 
									
										
										
										
											2013-10-18 14:04:48 +08:00
										 |  |  |   size_t i = 0; j = 0; | 
					
						
							|  |  |  |   BOOST_FOREACH(const SfM_Camera& camera, mydata.cameras) initial.insert(C(i++), camera); | 
					
						
							|  |  |  |   BOOST_FOREACH(const SfM_Track& track, mydata.tracks)    initial.insert(P(j++), track.p); | 
					
						
							| 
									
										
										
										
											2013-10-18 13:32:20 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* Optimize the graph and print results */ | 
					
						
							|  |  |  |   Values result; | 
					
						
							|  |  |  |   try { | 
					
						
							|  |  |  |     LevenbergMarquardtParams params; | 
					
						
							|  |  |  |     params.setVerbosity("ERROR"); | 
					
						
							|  |  |  |     LevenbergMarquardtOptimizer lm(graph, initial, params); | 
					
						
							|  |  |  |     result = lm.optimize(); | 
					
						
							|  |  |  |   } catch (exception& e) { | 
					
						
							|  |  |  |     cout << e.what(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   cout << "final error: " << graph.error(result) << endl; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | 
 |