add better visualSLAM examples
							parent
							
								
									be7828b8cf
								
							
						
					
					
						commit
						4eee4b72f4
					
				|  | @ -0,0 +1,91 @@ | |||
| /* ----------------------------------------------------------------------------
 | ||||
| 
 | ||||
|  * 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    VisualSLAMSimulatedData.cpp | ||||
|  * @brief   Generate ground-truth simulated data for VisualSLAM examples (SFM and ISAM2) | ||||
|  * @author  Duy-Nguyen Ta | ||||
|  */ | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include <vector> | ||||
| #include <map> | ||||
| #include <gtsam/geometry/SimpleCamera.h> | ||||
| 
 | ||||
| /* ************************************************************************* */ | ||||
| /**
 | ||||
|  * Simulated data for the example: | ||||
|  * - 8 Landmarks:	(10,10,10) (-10,10,10) (-10,-10,10) (10,-10,10) | ||||
|  *      					(10,10,-10) (-10,10,-10) (-10,-10,-10) (10,-10,-10) | ||||
|  * - n 90-deg-FoV cameras with the same calibration parameters: | ||||
|  * 				 f = 50.0, Image: 100x100, center: 50.0, 50.0 | ||||
|  * 		and ground-truth poses on a circle around the landmarks looking at the world's origin: | ||||
|  * 					Rot3(-sin(theta),  0, -cos(theta), | ||||
|  * 							  cos(theta),  0, -sin(theta), | ||||
|  * 							 					 0, -1,					 0 ), | ||||
|  * 					Point3(r*cos(theta), r*sin(theta), 0.0) | ||||
|  * 		(theta += 2*pi/N) | ||||
|  * - Measurement noise: 1 pix sigma | ||||
|  */ | ||||
| struct VisualSLAMExampleData { | ||||
| 	gtsam::shared_ptrK sK;								// camera calibration parameters
 | ||||
| 	std::vector<gtsam::Pose3> poses;          // ground-truth camera poses
 | ||||
| 	gtsam::Pose3 odometry;								// ground-truth odometry between 2 consecutive poses (simulated data for iSAM)
 | ||||
| 	std::vector<gtsam::Point3> landmarks;     // ground-truth landmarks
 | ||||
| 	std::map<int, vector<gtsam::Point2> > z;	// 2D measurements of landmarks in each camera frame
 | ||||
| 	gtsam::SharedDiagonal noiseZ; 			// measurement noise (noiseModel::Isotropic::Sigma(2, 5.0f));
 | ||||
| 	gtsam::SharedDiagonal noiseX; 			// noise for camera poses
 | ||||
| 	gtsam::SharedDiagonal noiseL; 			// noise for landmarks
 | ||||
| 
 | ||||
| 	static const VisualSLAMExampleData generate() { | ||||
| 		VisualSLAMExampleData data; | ||||
| 		// Landmarks (ground truth)
 | ||||
| 		data.landmarks.push_back(gtsam::Point3(10.0,10.0,10.0)); | ||||
| 		data.landmarks.push_back(gtsam::Point3(-10.0,10.0,10.0)); | ||||
| 		data.landmarks.push_back(gtsam::Point3(-10.0,-10.0,10.0)); | ||||
| 		data.landmarks.push_back(gtsam::Point3(10.0,-10.0,10.0)); | ||||
| 		data.landmarks.push_back(gtsam::Point3(10.0,10.0,-10.0)); | ||||
| 		data.landmarks.push_back(gtsam::Point3(-10.0,10.0,-10.0)); | ||||
| 		data.landmarks.push_back(gtsam::Point3(-10.0,-10.0,-10.0)); | ||||
| 		data.landmarks.push_back(gtsam::Point3(10.0,-10.0,-10.0)); | ||||
| 
 | ||||
| 		// Camera calibration parameters
 | ||||
| 		data.sK = gtsam::shared_ptrK(new gtsam::Cal3_S2(50.0, 50.0, 0.0, 50.0, 50.0)); | ||||
| 
 | ||||
| 		// n camera poses
 | ||||
| 		int n = 8; | ||||
| 		double theta = 0.0; | ||||
| 		double r = 30.0; | ||||
| 		for (int i=0; i<n; ++i) { | ||||
| 			theta += 2*M_PI/n; | ||||
| 			data.poses.push_back(gtsam::Pose3( | ||||
| 					gtsam::Rot3(-sin(theta), 0.0, -cos(theta), | ||||
| 											cos(theta), 0.0, -sin(theta), | ||||
| 											0.0, -1.0, 0.0), | ||||
| 					gtsam::Point3(r*cos(theta), r*sin(theta), 0.0))); | ||||
| 		} | ||||
| 		data.odometry = data.poses[0].between(data.poses[1]); | ||||
| 
 | ||||
| 		// Simulated measurements with Gaussian noise
 | ||||
| 		data.noiseZ = gtsam::sharedSigma(2, 1.0); | ||||
| 		for (size_t i=0; i<data.poses.size(); ++i) { | ||||
| 			for (size_t j=0; j<data.landmarks.size(); ++j) { | ||||
| 				gtsam::SimpleCamera camera(data.poses[i], *data.sK); | ||||
| 				data.z[i].push_back(camera.project(data.landmarks[j]) + gtsam::Point2(data.noiseZ->sample())); | ||||
| 			} | ||||
| 		} | ||||
| 		data.noiseX = gtsam::sharedSigmas(gtsam::Vector_(6, 0.01, 0.01, 0.01, 0.1, 0.1, 0.1)); | ||||
| 		data.noiseL = gtsam::sharedSigma(3, 0.1); | ||||
| 
 | ||||
| 		return data; | ||||
| 	} | ||||
| }; | ||||
|  | @ -0,0 +1,64 @@ | |||
| /* ----------------------------------------------------------------------------
 | ||||
| 
 | ||||
|  * 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    VisualSLAMforSFMExample.cpp | ||||
|  * @brief   A visualSLAM example for the structure-from-motion problem on a simulated dataset | ||||
|  * @author  Duy-Nguyen Ta | ||||
|  */ | ||||
| 
 | ||||
| #include <gtsam/slam/visualSLAM.h> | ||||
| #include <gtsam/nonlinear/Symbol.h> | ||||
| #include <gtsam/nonlinear/LevenbergMarquardtOptimizer.h> | ||||
| #include <gtsam/nonlinear/GaussNewtonOptimizer.h> | ||||
| #include "VisualSLAMExampleData.h" | ||||
| 
 | ||||
| using namespace std; | ||||
| using namespace gtsam; | ||||
| 
 | ||||
| // Convenience for named keys
 | ||||
| using symbol_shorthand::X; | ||||
| using symbol_shorthand::L; | ||||
| 
 | ||||
| /* ************************************************************************* */ | ||||
| int main(int argc, char* argv[]) { | ||||
| 
 | ||||
| 	VisualSLAMExampleData data = VisualSLAMExampleData::generate(); | ||||
| 
 | ||||
|   /* 1. Create graph *///using the 2D measurements (features) and the calibration data
 | ||||
|   visualSLAM::Graph graph; | ||||
| 
 | ||||
|   /* 2. Add factors to the graph */ | ||||
|   // 2a. Measurement factors
 | ||||
|   for (size_t i=0; i<data.poses.size(); ++i) { | ||||
|   	for (size_t j=0; j<data.landmarks.size(); ++j) | ||||
|   		graph.addMeasurement(data.z[i][j], data.noiseZ, X(i), L(j), data.sK); | ||||
|   } | ||||
|   // 2b. Prior factor for the first pose to resolve ambiguity (not needed for LevenbergMarquardtOptimizer)
 | ||||
|   graph.addPosePrior(X(0), data.poses[0], data.noiseX); | ||||
| 
 | ||||
|   /* 3. Initial estimates for variable nodes, simulated by Gaussian noises */ | ||||
|   Values initial; | ||||
|   for (size_t i=0; i<data.poses.size(); ++i) | ||||
|   	initial.insert(X(i), data.poses[i]*Pose3::Expmap(data.noiseX->sample())); | ||||
|   for (size_t j=0; j<data.landmarks.size(); ++j) | ||||
|   	initial.insert(L(j), data.landmarks[j] + Point3(data.noiseL->sample())); | ||||
|   initial.print("Intial Estimates: "); | ||||
| 
 | ||||
|   /* 4. Optimize the graph and print results */ | ||||
|   visualSLAM::Values result = GaussNewtonOptimizer(graph, initial).optimize(); | ||||
| //  visualSLAM::Values result = LevenbergMarquardtOptimizer(graph, initial).optimize();
 | ||||
|   result.print("Final results: "); | ||||
| 
 | ||||
|   return 0; | ||||
| } | ||||
| /* ************************************************************************* */ | ||||
| 
 | ||||
|  | @ -0,0 +1,113 @@ | |||
| /* ----------------------------------------------------------------------------
 | ||||
| 
 | ||||
|  * 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    VisualSLAMwISAM2Example.cpp | ||||
|  * @brief   An ISAM example for synthesis sequence, single camera | ||||
|  * @author  Duy-Nguyen Ta | ||||
|  */ | ||||
| 
 | ||||
| #include <gtsam/nonlinear/Symbol.h> | ||||
| #include <gtsam/nonlinear/NonlinearISAM.h> | ||||
| #include <gtsam/slam/visualSLAM.h> | ||||
| #include <gtsam/slam/BetweenFactor.h> | ||||
| #include "VisualSLAMExampleData.h" | ||||
| 
 | ||||
| using namespace std; | ||||
| using namespace gtsam; | ||||
| 
 | ||||
| // Convenience for named keys
 | ||||
| using symbol_shorthand::X; | ||||
| using symbol_shorthand::L; | ||||
| 
 | ||||
| /* ************************************************************************* */ | ||||
| int main(int argc, char* argv[]) { | ||||
| 
 | ||||
| 	VisualSLAMExampleData data = VisualSLAMExampleData::generate(); | ||||
| 
 | ||||
|   /* 1. Create a NonlinearISAM which will be relinearized and reordered after every "relinearizeInterval" updates */ | ||||
|   int relinearizeInterval = 3; | ||||
|   NonlinearISAM<> isam(relinearizeInterval); | ||||
| 
 | ||||
|   /* 2. At each frame (poseId) with new camera pose and set of associated measurements,
 | ||||
|    * create a graph of new factors and update ISAM */ | ||||
| 
 | ||||
|   // Store the current best estimate from ISAM
 | ||||
| 	Values currentEstimate; | ||||
| 
 | ||||
|   // First two frames:
 | ||||
| 	// Add factors and initial values for the first two poses and landmarks then update ISAM.
 | ||||
| 	// Note: measurements from the first pose only are not enough to update ISAM:
 | ||||
| 	//       the system is underconstrained.
 | ||||
|   { | ||||
|   	visualSLAM::Graph newFactors; | ||||
| 
 | ||||
|   	// First pose with prior factor
 | ||||
|   	newFactors.addPosePrior(X(0), data.poses[0], data.noiseX); | ||||
| 
 | ||||
|   	// Second pose with odometry measurement, simulated by adding Gaussian noise to the ground-truth.
 | ||||
|   	Pose3 odoMeasurement =  data.odometry*Pose3::Expmap(data.noiseX->sample()); | ||||
|   	newFactors.push_back( boost::shared_ptr<BetweenFactor<Pose3> >( | ||||
|   	  			new BetweenFactor<Pose3>(X(0), X(1), odoMeasurement, data.noiseX))); | ||||
| 
 | ||||
|   	// Visual measurements at both poses
 | ||||
|   	for (size_t i=0; i<2; ++i) { | ||||
| 			for (size_t j=0; j<data.z[i].size(); ++j) { | ||||
| 				newFactors.addMeasurement(data.z[i][j], data.noiseZ, X(i), L(j), data.sK); | ||||
| 			} | ||||
|   	} | ||||
| 
 | ||||
|   	// Initial values for the first two poses, simulated with Gaussian noise
 | ||||
|   	Values initials; | ||||
|   	Pose3 pose0Init = data.poses[0]*Pose3::Expmap(data.noiseX->sample()); | ||||
|   	initials.insert(X(0), pose0Init); | ||||
|   	initials.insert(X(1), pose0Init*odoMeasurement); | ||||
| 
 | ||||
|   	// Initial values for the landmarks, simulated with Gaussian noise
 | ||||
|   	for (size_t j=0; j<data.landmarks.size(); ++j) | ||||
|   		initials.insert(L(j), data.landmarks[j] + Point3(data.noiseL->sample())); | ||||
| 
 | ||||
|   	// Update ISAM the first time and obtain the current estimate
 | ||||
|   	isam.update(newFactors, initials); | ||||
|   	currentEstimate = isam.estimate(); | ||||
|   	cout << "Pose 0 and 1: " << endl; | ||||
|   	currentEstimate.print("Current estimate: "); | ||||
|   } | ||||
| 
 | ||||
|   // Subsequent frames: Add new odometry and measurement factors and initial values,
 | ||||
|   // then update ISAM at each frame
 | ||||
|   for (size_t i=2; i<data.poses.size(); ++i) { | ||||
|   	visualSLAM::Graph newFactors; | ||||
|   	// Factor for odometry measurements, simulated by adding Gaussian noise to the ground-truth.
 | ||||
|   	Pose3 odoMeasurement =  data.odometry*Pose3::Expmap(data.noiseX->sample()); | ||||
|   	newFactors.push_back( boost::shared_ptr<BetweenFactor<Pose3> >( | ||||
|   			new BetweenFactor<Pose3>(X(i-1), X(i), odoMeasurement, data.noiseX))); | ||||
|   	// Factors for visual measurements
 | ||||
|   	for (size_t j=0; j<data.z[i].size(); ++j) { | ||||
|   		newFactors.addMeasurement(data.z[i][j], data.noiseZ, X(i), L(j), data.sK); | ||||
|   	} | ||||
| 
 | ||||
|     // Initial estimates for the new node Xi, simulated by Gaussian noises
 | ||||
|   	Values initials; | ||||
|   	initials.insert(X(i), currentEstimate.at<Pose3>(X(i-1))*odoMeasurement); | ||||
| 
 | ||||
|   	// update ISAM
 | ||||
|   	isam.update(newFactors, initials); | ||||
|   	currentEstimate = isam.estimate(); | ||||
|   	cout << "****************************************************" << endl; | ||||
|   	cout << "Pose " << i << ": " << endl; | ||||
|   	currentEstimate.print("Current estimate: "); | ||||
|   } | ||||
| 
 | ||||
|   return 0; | ||||
| } | ||||
| /* ************************************************************************* */ | ||||
| 
 | ||||
		Loading…
	
		Reference in New Issue