| 
									
										
										
										
											2018-09-29 12:05:39 +08:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * @file ISAM2Example_SmartFactor.cpp | 
					
						
							|  |  |  |  * @brief test of iSAM with smart factors, led to bitbucket issue #367 | 
					
						
							|  |  |  |  * @author Alexander (pumaking on BitBucket) | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2018-09-29 12:04:13 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-22 08:42:55 +08:00
										 |  |  | #include <gtsam/geometry/PinholeCamera.h>
 | 
					
						
							| 
									
										
										
										
											2020-03-22 03:29:07 +08:00
										 |  |  | #include <gtsam/geometry/Cal3_S2.h>
 | 
					
						
							| 
									
										
										
										
											2018-09-30 05:31:46 +08:00
										 |  |  | #include <gtsam/nonlinear/ISAM2.h>
 | 
					
						
							| 
									
										
										
										
											2018-09-29 12:04:13 +08:00
										 |  |  | #include <gtsam/slam/BetweenFactor.h>
 | 
					
						
							|  |  |  | #include <gtsam/slam/SmartProjectionPoseFactor.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-29 12:05:39 +08:00
										 |  |  | #include <iostream>
 | 
					
						
							|  |  |  | #include <vector>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | using namespace std; | 
					
						
							| 
									
										
										
										
											2018-09-29 12:04:13 +08:00
										 |  |  | using namespace gtsam; | 
					
						
							| 
									
										
										
										
											2018-09-29 12:05:39 +08:00
										 |  |  | using symbol_shorthand::P; | 
					
						
							|  |  |  | using symbol_shorthand::X; | 
					
						
							| 
									
										
										
										
											2018-09-29 12:04:13 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | // Make the typename short so it looks much cleaner
 | 
					
						
							|  |  |  | typedef SmartProjectionPoseFactor<Cal3_S2> SmartFactor; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int main(int argc, char* argv[]) { | 
					
						
							|  |  |  |   Cal3_S2::shared_ptr K(new Cal3_S2(50.0, 50.0, 0.0, 50.0, 50.0)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-29 12:05:39 +08:00
										 |  |  |   auto measurementNoise = | 
					
						
							|  |  |  |       noiseModel::Isotropic::Sigma(2, 1.0);  // one pixel in u and v
 | 
					
						
							| 
									
										
										
										
											2018-09-29 12:04:13 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-29 12:05:39 +08:00
										 |  |  |   Vector6 sigmas; | 
					
						
							| 
									
										
										
										
											2020-01-05 08:57:22 +08:00
										 |  |  |   sigmas << Vector3::Constant(0.1), Vector3::Constant(0.3); | 
					
						
							| 
									
										
										
										
											2018-09-29 12:05:39 +08:00
										 |  |  |   auto noise = noiseModel::Diagonal::Sigmas(sigmas); | 
					
						
							| 
									
										
										
										
											2018-09-29 12:04:13 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   ISAM2Params parameters; | 
					
						
							|  |  |  |   parameters.relinearizeThreshold = 0.01; | 
					
						
							|  |  |  |   parameters.relinearizeSkip = 1; | 
					
						
							|  |  |  |   parameters.cacheLinearizedFactors = false; | 
					
						
							|  |  |  |   parameters.enableDetailedResults = true; | 
					
						
							|  |  |  |   parameters.print(); | 
					
						
							|  |  |  |   ISAM2 isam(parameters); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Create a factor graph
 | 
					
						
							|  |  |  |   NonlinearFactorGraph graph; | 
					
						
							| 
									
										
										
										
											2018-09-29 12:05:39 +08:00
										 |  |  |   Values initialEstimate; | 
					
						
							| 
									
										
										
										
											2018-09-29 12:04:13 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   Point3 point(0.0, 0.0, 1.0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Intentionally initialize the variables off from the ground truth
 | 
					
						
							|  |  |  |   Pose3 delta(Rot3::Rodrigues(0.0, 0.0, 0.0), Point3(0.05, -0.10, 0.20)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Pose3 pose1(Rot3(), Point3(0.0, 0.0, 0.0)); | 
					
						
							|  |  |  |   Pose3 pose2(Rot3(), Point3(0.0, 0.2, 0.0)); | 
					
						
							|  |  |  |   Pose3 pose3(Rot3(), Point3(0.0, 0.4, 0.0)); | 
					
						
							|  |  |  |   Pose3 pose4(Rot3(), Point3(0.0, 0.5, 0.0)); | 
					
						
							|  |  |  |   Pose3 pose5(Rot3(), Point3(0.0, 0.6, 0.0)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-29 12:05:39 +08:00
										 |  |  |   vector<Pose3> poses = {pose1, pose2, pose3, pose4, pose5}; | 
					
						
							| 
									
										
										
										
											2018-09-29 12:04:13 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-30 05:31:46 +08:00
										 |  |  |   // Add first pose
 | 
					
						
							| 
									
										
										
										
											2020-04-13 01:10:09 +08:00
										 |  |  |   graph.addPrior(X(0), poses[0], noise); | 
					
						
							| 
									
										
										
										
											2018-09-29 12:05:39 +08:00
										 |  |  |   initialEstimate.insert(X(0), poses[0].compose(delta)); | 
					
						
							| 
									
										
										
										
											2018-09-30 05:31:46 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // Create smart factor with measurement from first pose only
 | 
					
						
							|  |  |  |   SmartFactor::shared_ptr smartFactor(new SmartFactor(measurementNoise, K)); | 
					
						
							| 
									
										
										
										
											2018-09-29 12:05:39 +08:00
										 |  |  |   smartFactor->add(PinholePose<Cal3_S2>(poses[0], K).project(point), X(0)); | 
					
						
							| 
									
										
										
										
											2018-09-30 05:31:46 +08:00
										 |  |  |   graph.push_back(smartFactor); | 
					
						
							| 
									
										
										
										
											2018-09-29 12:04:13 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-30 05:31:46 +08:00
										 |  |  |   // loop over remaining poses
 | 
					
						
							| 
									
										
										
										
											2018-09-29 12:05:39 +08:00
										 |  |  |   for (size_t i = 1; i < 5; i++) { | 
					
						
							|  |  |  |     cout << "****************************************************" << endl; | 
					
						
							|  |  |  |     cout << "i = " << i << endl; | 
					
						
							| 
									
										
										
										
											2018-09-29 12:04:13 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-30 05:31:46 +08:00
										 |  |  |     // Add prior on new pose
 | 
					
						
							| 
									
										
										
										
											2020-04-13 01:10:09 +08:00
										 |  |  |     graph.addPrior(X(i), poses[i], noise); | 
					
						
							| 
									
										
										
										
											2018-09-30 05:31:46 +08:00
										 |  |  |     initialEstimate.insert(X(i), poses[i].compose(delta)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // "Simulate" measurement from this pose
 | 
					
						
							| 
									
										
										
										
											2018-09-29 12:05:39 +08:00
										 |  |  |     PinholePose<Cal3_S2> camera(poses[i], K); | 
					
						
							|  |  |  |     Point2 measurement = camera.project(point); | 
					
						
							|  |  |  |     cout << "Measurement " << i << "" << measurement << endl; | 
					
						
							| 
									
										
										
										
											2018-09-29 12:04:13 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-30 05:31:46 +08:00
										 |  |  |     // Add measurement to smart factor
 | 
					
						
							|  |  |  |     smartFactor->add(measurement, X(i)); | 
					
						
							| 
									
										
										
										
											2018-09-29 12:04:13 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-29 12:05:39 +08:00
										 |  |  |     // Update iSAM2
 | 
					
						
							|  |  |  |     ISAM2Result result = isam.update(graph, initialEstimate); | 
					
						
							| 
									
										
										
										
											2018-09-29 12:04:13 +08:00
										 |  |  |     result.print(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-29 12:05:39 +08:00
										 |  |  |     cout << "Detailed results:" << endl; | 
					
						
							|  |  |  |     for (auto keyedStatus : result.detail->variableStatus) { | 
					
						
							|  |  |  |       const auto& status = keyedStatus.second; | 
					
						
							| 
									
										
										
										
											2018-09-30 05:31:46 +08:00
										 |  |  |       PrintKey(keyedStatus.first); | 
					
						
							|  |  |  |       cout << " {" << endl; | 
					
						
							| 
									
										
										
										
											2018-09-29 12:05:39 +08:00
										 |  |  |       cout << "reeliminated: " << status.isReeliminated << endl; | 
					
						
							|  |  |  |       cout << "relinearized above thresh: " << status.isAboveRelinThreshold | 
					
						
							|  |  |  |            << endl; | 
					
						
							|  |  |  |       cout << "relinearized involved: " << status.isRelinearizeInvolved << endl; | 
					
						
							|  |  |  |       cout << "relinearized: " << status.isRelinearized << endl; | 
					
						
							|  |  |  |       cout << "observed: " << status.isObserved << endl; | 
					
						
							|  |  |  |       cout << "new: " << status.isNew << endl; | 
					
						
							|  |  |  |       cout << "in the root clique: " << status.inRootClique << endl; | 
					
						
							|  |  |  |       cout << "}" << endl; | 
					
						
							| 
									
										
										
										
											2018-09-29 12:04:13 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-29 12:05:39 +08:00
										 |  |  |     Values currentEstimate = isam.calculateEstimate(); | 
					
						
							|  |  |  |     currentEstimate.print("Current estimate: "); | 
					
						
							| 
									
										
										
										
											2018-09-29 12:04:13 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-12 05:49:07 +08:00
										 |  |  |     auto pointEstimate = smartFactor->point(currentEstimate); | 
					
						
							| 
									
										
										
										
											2018-09-29 12:05:39 +08:00
										 |  |  |     if (pointEstimate) { | 
					
						
							|  |  |  |       cout << *pointEstimate << endl; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       cout << "Point degenerate." << endl; | 
					
						
							| 
									
										
										
										
											2018-09-29 12:04:13 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-09-29 12:05:39 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // Reset graph and initial estimate for next iteration
 | 
					
						
							|  |  |  |     graph.resize(0); | 
					
						
							|  |  |  |     initialEstimate.clear(); | 
					
						
							| 
									
										
										
										
											2018-09-29 12:04:13 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return 0; | 
					
						
							|  |  |  | } |