| 
									
										
										
										
											2022-07-11 07:49:30 +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 TriangulationLOSTExample.cpp | 
					
						
							|  |  |  |  * @author Akshay Krishnan | 
					
						
							|  |  |  |  * @brief This example runs triangulation several times using 3 different | 
					
						
							|  |  |  |  * approaches: LOST, DLT, and DLT with optimization. It reports the covariance | 
					
						
							|  |  |  |  * and the runtime for each approach. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * @date 2022-07-10 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | #include <gtsam/geometry/Cal3_S2.h>
 | 
					
						
							|  |  |  | #include <gtsam/geometry/PinholeCamera.h>
 | 
					
						
							|  |  |  | #include <gtsam/geometry/Point2.h>
 | 
					
						
							|  |  |  | #include <gtsam/geometry/Point3.h>
 | 
					
						
							|  |  |  | #include <gtsam/geometry/Pose3.h>
 | 
					
						
							|  |  |  | #include <gtsam/geometry/Rot3.h>
 | 
					
						
							|  |  |  | #include <gtsam/geometry/triangulation.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <chrono>
 | 
					
						
							|  |  |  | #include <iostream>
 | 
					
						
							|  |  |  | #include <random>
 | 
					
						
							| 
									
										
										
										
											2023-01-13 05:11:55 +08:00
										 |  |  | #include <optional>
 | 
					
						
							| 
									
										
										
										
											2022-07-11 07:49:30 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | using namespace std; | 
					
						
							|  |  |  | using namespace gtsam; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static std::mt19937 rng(42); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void PrintCovarianceStats(const Matrix& mat, const std::string& method) { | 
					
						
							|  |  |  |   Matrix centered = mat.rowwise() - mat.colwise().mean(); | 
					
						
							|  |  |  |   Matrix cov = (centered.adjoint() * centered) / double(mat.rows() - 1); | 
					
						
							|  |  |  |   std::cout << method << " covariance: " << std::endl; | 
					
						
							|  |  |  |   std::cout << cov << std::endl; | 
					
						
							|  |  |  |   std::cout << "Trace sqrt: " << sqrt(cov.trace()) << std::endl << std::endl; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void PrintDuration(const std::chrono::nanoseconds dur, double num_samples, | 
					
						
							|  |  |  |                    const std::string& method) { | 
					
						
							|  |  |  |   double nanoseconds = dur.count() / num_samples; | 
					
						
							|  |  |  |   std::cout << "Time taken by " << method << ": " << nanoseconds * 1e-3 | 
					
						
							|  |  |  |             << std::endl; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GetLargeCamerasDataset(CameraSet<PinholeCamera<Cal3_S2>>* cameras, | 
					
						
							|  |  |  |                             std::vector<Pose3>* poses, Point3* point, | 
					
						
							|  |  |  |                             Point2Vector* measurements) { | 
					
						
							| 
									
										
										
										
											2022-07-13 11:03:02 +08:00
										 |  |  |   const double minXY = -10, maxXY = 10; | 
					
						
							|  |  |  |   const double minZ = -20, maxZ = 0; | 
					
						
							|  |  |  |   const int nrCameras = 500; | 
					
						
							|  |  |  |   cameras->reserve(nrCameras); | 
					
						
							|  |  |  |   poses->reserve(nrCameras); | 
					
						
							|  |  |  |   measurements->reserve(nrCameras); | 
					
						
							| 
									
										
										
										
											2022-07-11 07:49:30 +08:00
										 |  |  |   *point = Point3(0.0, 0.0, 10.0); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-13 11:03:02 +08:00
										 |  |  |   std::uniform_real_distribution<double> rand_xy(minXY, maxXY); | 
					
						
							|  |  |  |   std::uniform_real_distribution<double> rand_z(minZ, maxZ); | 
					
						
							|  |  |  |   Cal3_S2 identityK; | 
					
						
							| 
									
										
										
										
											2022-07-11 07:49:30 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-13 11:03:02 +08:00
										 |  |  |   for (int i = 0; i < nrCameras; ++i) { | 
					
						
							| 
									
										
										
										
											2022-07-11 07:49:30 +08:00
										 |  |  |     Point3 wti(rand_xy(rng), rand_xy(rng), rand_z(rng)); | 
					
						
							|  |  |  |     Pose3 wTi(Rot3(), wti); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     poses->push_back(wTi); | 
					
						
							| 
									
										
										
										
											2022-07-13 11:03:02 +08:00
										 |  |  |     cameras->emplace_back(wTi, identityK); | 
					
						
							| 
									
										
										
										
											2022-07-11 07:49:30 +08:00
										 |  |  |     measurements->push_back(cameras->back().project(*point)); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GetSmallCamerasDataset(CameraSet<PinholeCamera<Cal3_S2>>* cameras, | 
					
						
							|  |  |  |                             std::vector<Pose3>* poses, Point3* point, | 
					
						
							|  |  |  |                             Point2Vector* measurements) { | 
					
						
							| 
									
										
										
										
											2022-07-13 11:03:02 +08:00
										 |  |  |   Pose3 pose1; | 
					
						
							|  |  |  |   Pose3 pose2(Rot3(), Point3(5., 0., -5.)); | 
					
						
							|  |  |  |   Cal3_S2 identityK; | 
					
						
							|  |  |  |   PinholeCamera<Cal3_S2> camera1(pose1, identityK); | 
					
						
							|  |  |  |   PinholeCamera<Cal3_S2> camera2(pose2, identityK); | 
					
						
							| 
									
										
										
										
											2022-07-11 07:49:30 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   *point = Point3(0, 0, 1); | 
					
						
							| 
									
										
										
										
											2022-07-13 11:03:02 +08:00
										 |  |  |   cameras->push_back(camera1); | 
					
						
							|  |  |  |   cameras->push_back(camera2); | 
					
						
							|  |  |  |   *poses = {pose1, pose2}; | 
					
						
							|  |  |  |   *measurements = {camera1.project(*point), camera2.project(*point)}; | 
					
						
							| 
									
										
										
										
											2022-07-11 07:49:30 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Point2Vector AddNoiseToMeasurements(const Point2Vector& measurements, | 
					
						
							| 
									
										
										
										
											2022-07-13 11:03:02 +08:00
										 |  |  |                                     const double measurementSigma) { | 
					
						
							|  |  |  |   std::normal_distribution<double> normal(0.0, measurementSigma); | 
					
						
							| 
									
										
										
										
											2022-07-11 07:49:30 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-13 11:03:02 +08:00
										 |  |  |   Point2Vector noisyMeasurements; | 
					
						
							|  |  |  |   noisyMeasurements.reserve(measurements.size()); | 
					
						
							| 
									
										
										
										
											2022-07-11 07:49:30 +08:00
										 |  |  |   for (const auto& p : measurements) { | 
					
						
							| 
									
										
										
										
											2022-07-13 11:03:02 +08:00
										 |  |  |     noisyMeasurements.emplace_back(p.x() + normal(rng), p.y() + normal(rng)); | 
					
						
							| 
									
										
										
										
											2022-07-11 07:49:30 +08:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2022-07-13 11:03:02 +08:00
										 |  |  |   return noisyMeasurements; | 
					
						
							| 
									
										
										
										
											2022-07-11 07:49:30 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | int main(int argc, char* argv[]) { | 
					
						
							|  |  |  |   CameraSet<PinholeCamera<Cal3_S2>> cameras; | 
					
						
							|  |  |  |   std::vector<Pose3> poses; | 
					
						
							| 
									
										
										
										
											2022-07-13 11:03:02 +08:00
										 |  |  |   Point3 landmark; | 
					
						
							| 
									
										
										
										
											2022-07-11 07:49:30 +08:00
										 |  |  |   Point2Vector measurements; | 
					
						
							| 
									
										
										
										
											2022-07-13 11:03:02 +08:00
										 |  |  |   GetLargeCamerasDataset(&cameras, &poses, &landmark, &measurements); | 
					
						
							|  |  |  |   // GetSmallCamerasDataset(&cameras, &poses, &landmark, &measurements);
 | 
					
						
							|  |  |  |   const double measurementSigma = 1e-2; | 
					
						
							|  |  |  |   SharedNoiseModel measurementNoise = | 
					
						
							|  |  |  |       noiseModel::Isotropic::Sigma(2, measurementSigma); | 
					
						
							| 
									
										
										
										
											2022-07-11 07:49:30 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-13 11:03:02 +08:00
										 |  |  |   const long int nrTrials = 1000; | 
					
						
							|  |  |  |   Matrix errorsDLT = Matrix::Zero(nrTrials, 3); | 
					
						
							|  |  |  |   Matrix errorsLOST = Matrix::Zero(nrTrials, 3); | 
					
						
							|  |  |  |   Matrix errorsDLTOpt = Matrix::Zero(nrTrials, 3); | 
					
						
							| 
									
										
										
										
											2022-07-11 07:49:30 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   double rank_tol = 1e-9; | 
					
						
							| 
									
										
										
										
											2023-01-18 06:05:12 +08:00
										 |  |  |   std::shared_ptr<Cal3_S2> calib = std::make_shared<Cal3_S2>(); | 
					
						
							| 
									
										
										
										
											2022-07-13 11:03:02 +08:00
										 |  |  |   std::chrono::nanoseconds durationDLT; | 
					
						
							|  |  |  |   std::chrono::nanoseconds durationDLTOpt; | 
					
						
							|  |  |  |   std::chrono::nanoseconds durationLOST; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (int i = 0; i < nrTrials; i++) { | 
					
						
							|  |  |  |     Point2Vector noisyMeasurements = | 
					
						
							|  |  |  |         AddNoiseToMeasurements(measurements, measurementSigma); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     auto lostStart = std::chrono::high_resolution_clock::now(); | 
					
						
							| 
									
										
										
										
											2023-01-12 05:49:07 +08:00
										 |  |  |     auto estimateLOST = triangulatePoint3<Cal3_S2>( | 
					
						
							| 
									
										
										
										
											2022-07-13 11:03:02 +08:00
										 |  |  |         cameras, noisyMeasurements, rank_tol, false, measurementNoise, true); | 
					
						
							|  |  |  |     durationLOST += std::chrono::high_resolution_clock::now() - lostStart; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     auto dltStart = std::chrono::high_resolution_clock::now(); | 
					
						
							| 
									
										
										
										
											2023-01-12 05:49:07 +08:00
										 |  |  |     auto estimateDLT = triangulatePoint3<Cal3_S2>( | 
					
						
							| 
									
										
										
										
											2022-07-13 11:03:02 +08:00
										 |  |  |         cameras, noisyMeasurements, rank_tol, false, measurementNoise, false); | 
					
						
							|  |  |  |     durationDLT += std::chrono::high_resolution_clock::now() - dltStart; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     auto dltOptStart = std::chrono::high_resolution_clock::now(); | 
					
						
							| 
									
										
										
										
											2023-01-12 05:49:07 +08:00
										 |  |  |     auto estimateDLTOpt = triangulatePoint3<Cal3_S2>( | 
					
						
							| 
									
										
										
										
											2022-07-13 11:03:02 +08:00
										 |  |  |         cameras, noisyMeasurements, rank_tol, true, measurementNoise, false); | 
					
						
							|  |  |  |     durationDLTOpt += std::chrono::high_resolution_clock::now() - dltOptStart; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-13 05:11:55 +08:00
										 |  |  |     errorsLOST.row(i) = estimateLOST - landmark; | 
					
						
							|  |  |  |     errorsDLT.row(i) = estimateDLT - landmark; | 
					
						
							|  |  |  |     errorsDLTOpt.row(i) = estimateDLTOpt - landmark; | 
					
						
							| 
									
										
										
										
											2022-07-11 07:49:30 +08:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2022-07-13 11:03:02 +08:00
										 |  |  |   PrintCovarianceStats(errorsLOST, "LOST"); | 
					
						
							|  |  |  |   PrintCovarianceStats(errorsDLT, "DLT"); | 
					
						
							|  |  |  |   PrintCovarianceStats(errorsDLTOpt, "DLT_OPT"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   PrintDuration(durationLOST, nrTrials, "LOST"); | 
					
						
							|  |  |  |   PrintDuration(durationDLT, nrTrials, "DLT"); | 
					
						
							|  |  |  |   PrintDuration(durationDLTOpt, nrTrials, "DLT_OPT"); | 
					
						
							|  |  |  | } |