gtsam
Loading...
Searching...
No Matches
triangulation.h
Go to the documentation of this file.
1/* ----------------------------------------------------------------------------
2
3 * GTSAM Copyright 2010, Georgia Tech Research Corporation,
4 * Atlanta, Georgia 30332-0415
5 * All Rights Reserved
6 * Authors: Frank Dellaert, et al. (see THANKS for the full author list)
7
8 * See LICENSE for the license information
9
10 * -------------------------------------------------------------------------- */
11
20
21#pragma once
22
35#include <gtsam/slam/TriangulationFactor.h>
36
37#include <map>
38#include <optional>
39#include <stdexcept>
40
41namespace gtsam {
42
44class GTSAM_EXPORT TriangulationUnderconstrainedException: public std::runtime_error {
45public:
46 TriangulationUnderconstrainedException() :
47 std::runtime_error("Triangulation Underconstrained Exception.") {
48 }
49};
50
52class GTSAM_EXPORT TriangulationCheiralityException: public std::runtime_error {
53public:
54 TriangulationCheiralityException() :
55 std::runtime_error(
56 "Triangulation Cheirality Exception: The resulting landmark is behind one or more cameras.") {
57 }
58};
59
67GTSAM_EXPORT Vector4 triangulateHomogeneousDLT(
68 const std::vector<Matrix34, Eigen::aligned_allocator<Matrix34>>& projection_matrices,
69 const Point2Vector& measurements, double rank_tol = 1e-9);
70
79GTSAM_EXPORT Vector4 triangulateHomogeneousDLT(
80 const std::vector<Matrix34, Eigen::aligned_allocator<Matrix34>>& projection_matrices,
81 const std::vector<Unit3>& measurements, double rank_tol = 1e-9);
82
90GTSAM_EXPORT Point3 triangulateDLT(
91 const std::vector<Matrix34, Eigen::aligned_allocator<Matrix34>>& projection_matrices,
92 const Point2Vector& measurements,
93 double rank_tol = 1e-9);
94
98GTSAM_EXPORT Point3 triangulateDLT(
99 const std::vector<Matrix34, Eigen::aligned_allocator<Matrix34>>& projection_matrices,
100 const std::vector<Unit3>& measurements,
101 double rank_tol = 1e-9);
102
113GTSAM_EXPORT Point3 triangulateLOST(const std::vector<Pose3>& poses,
114 const Point3Vector& calibratedMeasurements,
115 const SharedIsotropic& measurementNoise,
116 double rank_tol = 1e-9);
117
127template<class CALIBRATION>
128std::pair<NonlinearFactorGraph, Values> triangulationGraph(
129 const std::vector<Pose3>& poses, std::shared_ptr<CALIBRATION> sharedCal,
130 const Point2Vector& measurements, Key landmarkKey,
131 const Point3& initialEstimate,
132 const SharedNoiseModel& model = noiseModel::Unit::Create(2)) {
133 Values values;
134 values.insert(landmarkKey, initialEstimate); // Initial landmark value
136 for (size_t i = 0; i < measurements.size(); i++) {
137 const Pose3& pose_i = poses[i];
138 typedef PinholePose<CALIBRATION> Camera;
139 Camera camera_i(pose_i, sharedCal);
141 (camera_i, measurements[i], model, landmarkKey);
142 }
143 return {graph, values};
144}
145
155template<class CAMERA>
156std::pair<NonlinearFactorGraph, Values> triangulationGraph(
157 const CameraSet<CAMERA>& cameras,
158 const typename CAMERA::MeasurementVector& measurements, Key landmarkKey,
159 const Point3& initialEstimate,
160 const SharedNoiseModel& model = nullptr) {
161 Values values;
162 values.insert(landmarkKey, initialEstimate); // Initial landmark value
166 for (size_t i = 0; i < measurements.size(); i++) {
167 const CAMERA& camera_i = cameras[i];
169 (camera_i, measurements[i], model? model : unit, landmarkKey);
170 }
171 return {graph, values};
172}
173
181GTSAM_EXPORT Point3 optimize(const NonlinearFactorGraph& graph,
182 const Values& values, Key landmarkKey);
183
192template<class CALIBRATION>
193Point3 triangulateNonlinear(const std::vector<Pose3>& poses,
194 std::shared_ptr<CALIBRATION> sharedCal,
195 const Point2Vector& measurements, const Point3& initialEstimate,
196 const SharedNoiseModel& model = nullptr) {
197
198 // Create a factor graph and initial values
199 const auto [graph, values] = triangulationGraph<CALIBRATION> //
200 (poses, sharedCal, measurements, Symbol('p', 0), initialEstimate, model);
201
202 return optimize(graph, values, Symbol('p', 0));
203}
204
212template<class CAMERA>
214 const CameraSet<CAMERA>& cameras,
215 const typename CAMERA::MeasurementVector& measurements, const Point3& initialEstimate,
216 const SharedNoiseModel& model = nullptr) {
217
218 // Create a factor graph and initial values
219 const auto [graph, values] = triangulationGraph<CAMERA> //
220 (cameras, measurements, Symbol('p', 0), initialEstimate, model);
221
222 return optimize(graph, values, Symbol('p', 0));
223}
224
225template<class CAMERA>
226std::vector<Matrix34, Eigen::aligned_allocator<Matrix34>>
227projectionMatricesFromCameras(const CameraSet<CAMERA> &cameras) {
228 std::vector<Matrix34, Eigen::aligned_allocator<Matrix34>> projection_matrices;
229 for (const CAMERA &camera: cameras) {
230 projection_matrices.push_back(camera.cameraProjectionMatrix());
231 }
232 return projection_matrices;
233}
234
235// overload, assuming pinholePose
236template<class CALIBRATION>
237std::vector<Matrix34, Eigen::aligned_allocator<Matrix34>> projectionMatricesFromPoses(
238 const std::vector<Pose3> &poses, std::shared_ptr<CALIBRATION> sharedCal) {
239 std::vector<Matrix34, Eigen::aligned_allocator<Matrix34>> projection_matrices;
240 for (size_t i = 0; i < poses.size(); i++) {
241 PinholePose<CALIBRATION> camera(poses.at(i), sharedCal);
242 projection_matrices.push_back(camera.cameraProjectionMatrix());
243 }
244 return projection_matrices;
245}
246
254template <class CALIBRATION>
255Cal3_S2 createPinholeCalibration(const CALIBRATION& cal) {
256 const auto& K = cal.K();
257 return Cal3_S2(K(0, 0), K(1, 1), K(0, 1), K(0, 2), K(1, 2));
258}
259
262template <class CALIBRATION, class MEASUREMENT>
264 const CALIBRATION& cal, const MEASUREMENT& measurement,
265 std::optional<Cal3_S2> pinholeCal = {}) {
266 if (!pinholeCal) {
267 pinholeCal = createPinholeCalibration(cal);
268 }
269 return pinholeCal->uncalibrate(cal.calibrate(measurement));
270}
271
283template <class CALIBRATION>
284Point2Vector undistortMeasurements(const CALIBRATION& cal,
285 const Point2Vector& measurements) {
286 Cal3_S2 pinholeCalibration = createPinholeCalibration(cal);
287 Point2Vector undistortedMeasurements;
288 // Calibrate with cal and uncalibrate with pinhole version of cal so that
289 // measurements are undistorted.
290 std::transform(measurements.begin(), measurements.end(),
291 std::back_inserter(undistortedMeasurements),
292 [&cal, &pinholeCalibration](const Point2& measurement) {
293 return undistortMeasurementInternal<CALIBRATION>(
294 cal, measurement, pinholeCalibration);
295 });
296 return undistortedMeasurements;
297}
298
300template <>
301inline Point2Vector undistortMeasurements(const Cal3_S2& cal,
302 const Point2Vector& measurements) {
303 return measurements;
304}
305
317template <class CAMERA>
318typename CAMERA::MeasurementVector undistortMeasurements(
319 const CameraSet<CAMERA>& cameras,
320 const typename CAMERA::MeasurementVector& measurements) {
321 const size_t nrMeasurements = measurements.size();
322#ifndef NDEBUG
323 if (nrMeasurements != cameras.size()) {
324 throw;
325 }
326#endif
327 typename CAMERA::MeasurementVector undistortedMeasurements(nrMeasurements);
328 for (size_t ii = 0; ii < nrMeasurements; ++ii) {
329 // Calibrate with cal and uncalibrate with pinhole version of cal so that
330 // measurements are undistorted.
331 undistortedMeasurements[ii] =
333 cameras[ii].calibration(), measurements[ii]);
334 }
335 return undistortedMeasurements;
336}
337
339template <class CAMERA = PinholeCamera<Cal3_S2>>
340inline PinholeCamera<Cal3_S2>::MeasurementVector undistortMeasurements(
341 const CameraSet<PinholeCamera<Cal3_S2>>& cameras,
342 const PinholeCamera<Cal3_S2>::MeasurementVector& measurements) {
343 return measurements;
344}
345
347template <class CAMERA = SphericalCamera>
348inline SphericalCamera::MeasurementVector undistortMeasurements(
349 const CameraSet<SphericalCamera>& cameras,
350 const SphericalCamera::MeasurementVector& measurements) {
351 return measurements;
352}
353
362template <class CALIBRATION>
363inline Point3Vector calibrateMeasurementsShared(
364 const CALIBRATION& cal, const Point2Vector& measurements) {
365 Point3Vector calibratedMeasurements;
366 // Calibrate with cal and uncalibrate with pinhole version of cal so that
367 // measurements are undistorted.
368 std::transform(measurements.begin(), measurements.end(),
369 std::back_inserter(calibratedMeasurements),
370 [&cal](const Point2& measurement) {
371 Point3 p;
372 p << cal.calibrate(measurement), 1.0;
373 return p;
374 });
375 return calibratedMeasurements;
376}
377
386template <class CAMERA>
387inline Point3Vector calibrateMeasurements(
388 const CameraSet<CAMERA>& cameras,
389 const typename CAMERA::MeasurementVector& measurements) {
390 const size_t nrMeasurements = measurements.size();
391 assert(nrMeasurements == cameras.size());
392 Point3Vector calibratedMeasurements(nrMeasurements);
393 for (size_t ii = 0; ii < nrMeasurements; ++ii) {
394 calibratedMeasurements[ii]
395 << cameras[ii].calibration().calibrate(measurements[ii]),
396 1.0;
397 }
398 return calibratedMeasurements;
399}
400
402template <class CAMERA = SphericalCamera>
403inline Point3Vector calibrateMeasurements(
404 const CameraSet<SphericalCamera>& cameras,
405 const SphericalCamera::MeasurementVector& measurements) {
406 Point3Vector calibratedMeasurements(measurements.size());
407 for (size_t ii = 0; ii < measurements.size(); ++ii) {
408 calibratedMeasurements[ii] << measurements[ii].point3();
409 }
410 return calibratedMeasurements;
411}
412
426template <class CALIBRATION>
427Point3 triangulatePoint3(const std::vector<Pose3>& poses,
428 std::shared_ptr<CALIBRATION> sharedCal,
429 const Point2Vector& measurements,
430 double rank_tol = 1e-9, bool optimize = false,
431 const SharedNoiseModel& model = nullptr,
432 const bool useLOST = false) {
433 assert(poses.size() == measurements.size());
434 if (poses.size() < 2) throw(TriangulationUnderconstrainedException());
435
436 // Triangulate linearly
437 Point3 point;
438 if (useLOST) {
439 // Reduce input noise model to an isotropic noise model using the mean of
440 // the diagonal.
441 const double measurementSigma = model ? model->sigmas().mean() : 1e-4;
442 SharedIsotropic measurementNoise =
443 noiseModel::Isotropic::Sigma(2, measurementSigma);
444 // calibrate the measurements to obtain homogenous coordinates in image
445 // plane.
446 auto calibratedMeasurements =
447 calibrateMeasurementsShared<CALIBRATION>(*sharedCal, measurements);
448
449 point = triangulateLOST(poses, calibratedMeasurements, measurementNoise,
450 rank_tol);
451 } else {
452 // construct projection matrices from poses & calibration
453 auto projection_matrices = projectionMatricesFromPoses(poses, sharedCal);
454
455 // Undistort the measurements, leaving only the pinhole elements in effect.
456 auto undistortedMeasurements =
457 undistortMeasurements<CALIBRATION>(*sharedCal, measurements);
458
459 point =
460 triangulateDLT(projection_matrices, undistortedMeasurements, rank_tol);
461 }
462
463 // Then refine using non-linear optimization
464 if (optimize) {
465 const auto noiseModel = noiseModel::validOrDefault(Point2(0, 0), model);
467 (poses, sharedCal, measurements, point, noiseModel);
468 }
469
470#ifdef GTSAM_THROW_CHEIRALITY_EXCEPTION
471 // verify that the triangulated point lies in front of all cameras
472 for (const Pose3& pose : poses) {
473 const Point3& p_local = pose.transformTo(point);
474 if (p_local.z() <= 0) throw(TriangulationCheiralityException());
475 }
476#endif
477
478 return point;
479}
480
495template <class CAMERA>
497 const typename CAMERA::MeasurementVector& measurements,
498 double rank_tol = 1e-9, bool optimize = false,
499 const SharedNoiseModel& model = nullptr,
500 const bool useLOST = false) {
501 size_t m = cameras.size();
502 assert(measurements.size() == m);
503
504 if (m < 2) throw(TriangulationUnderconstrainedException());
505
506 // Triangulate linearly
507 Point3 point;
508 if (useLOST) {
509 // Reduce input noise model to an isotropic noise model using the mean of
510 // the diagonal.
511 const double measurementSigma = model ? model->sigmas().mean() : 1e-4;
512 SharedIsotropic measurementNoise =
513 noiseModel::Isotropic::Sigma(2, measurementSigma);
514
515 // construct poses from cameras.
516 std::vector<Pose3> poses;
517 poses.reserve(cameras.size());
518 for (const auto& camera : cameras) poses.push_back(camera.pose());
519
520 // calibrate the measurements to obtain homogenous coordinates in image
521 // plane.
522 auto calibratedMeasurements =
523 calibrateMeasurements<CAMERA>(cameras, measurements);
524
525 point = triangulateLOST(poses, calibratedMeasurements, measurementNoise,
526 rank_tol);
527 } else {
528 // construct projection matrices from poses & calibration
529 auto projection_matrices = projectionMatricesFromCameras(cameras);
530
531 // Undistort the measurements, leaving only the pinhole elements in effect.
532 auto undistortedMeasurements =
533 undistortMeasurements<CAMERA>(cameras, measurements);
534
535 point =
536 triangulateDLT(projection_matrices, undistortedMeasurements, rank_tol);
537 }
538
539 // Then refine using non-linear optimization
540 if (optimize) {
541 point = triangulateNonlinear<CAMERA>(cameras, measurements, point, model);
542 }
543
544#ifdef GTSAM_THROW_CHEIRALITY_EXCEPTION
545 // verify that the triangulated point lies in front of all cameras
546 for (const CAMERA& camera : cameras) {
547 const Point3& p_local = camera.pose().transformTo(point);
548 if (p_local.z() <= 0) throw(TriangulationCheiralityException());
549 }
550#endif
551
552 return point;
553}
554
556template <class CALIBRATION>
558 const Point2Vector& measurements,
559 double rank_tol = 1e-9, bool optimize = false,
560 const SharedNoiseModel& model = nullptr,
561 const bool useLOST = false) {
563 (cameras, measurements, rank_tol, optimize, model, useLOST);
564}
565
566struct GTSAM_EXPORT TriangulationParameters {
567
571
577
584
589
591
601 TriangulationParameters(const double _rankTolerance = 1.0,
602 const bool _enableEPI = false, double _landmarkDistanceThreshold = -1,
603 double _dynamicOutlierRejectionThreshold = -1,
604 const bool _useLOST = false,
605 const SharedNoiseModel& _noiseModel = nullptr) :
606 rankTolerance(_rankTolerance), enableEPI(_enableEPI), //
607 landmarkDistanceThreshold(_landmarkDistanceThreshold), //
608 dynamicOutlierRejectionThreshold(_dynamicOutlierRejectionThreshold),
609 useLOST(_useLOST),
610 noiseModel(_noiseModel){
611 }
612
613 // stream to output
614 friend std::ostream &operator<<(std::ostream &os,
615 const TriangulationParameters& p) {
616 os << "rankTolerance = " << p.rankTolerance << std::endl;
617 os << "enableEPI = " << p.enableEPI << std::endl;
618 os << "landmarkDistanceThreshold = " << p.landmarkDistanceThreshold
619 << std::endl;
620 os << "dynamicOutlierRejectionThreshold = "
621 << p.dynamicOutlierRejectionThreshold << std::endl;
622 os << "useLOST = " << p.useLOST << std::endl;
623 os << "noise model" << std::endl;
624 return os;
625 }
626
627private:
628
629#if GTSAM_ENABLE_BOOST_SERIALIZATION
631 friend class boost::serialization::access;
632 template<class ARCHIVE>
633 void serialize(ARCHIVE & ar, const unsigned int version) {
634 ar & BOOST_SERIALIZATION_NVP(rankTolerance);
635 ar & BOOST_SERIALIZATION_NVP(enableEPI);
636 ar & BOOST_SERIALIZATION_NVP(landmarkDistanceThreshold);
637 ar & BOOST_SERIALIZATION_NVP(dynamicOutlierRejectionThreshold);
638 }
639#endif
640};
641
646class TriangulationResult : public std::optional<Point3> {
647 public:
648 enum Status { VALID, DEGENERATE, BEHIND_CAMERA, OUTLIER, FAR_POINT };
649 Status status;
650
651 private:
652 TriangulationResult(Status s) : status(s) {}
653
654 public:
659
663 TriangulationResult(const Point3& p) : status(VALID) { emplace(p); }
664 static TriangulationResult Degenerate() {
665 return TriangulationResult(DEGENERATE);
666 }
667 static TriangulationResult Outlier() { return TriangulationResult(OUTLIER); }
668 static TriangulationResult FarPoint() {
669 return TriangulationResult(FAR_POINT);
670 }
671 static TriangulationResult BehindCamera() {
672 return TriangulationResult(BEHIND_CAMERA);
673 }
674 bool valid() const { return status == VALID; }
675 bool degenerate() const { return status == DEGENERATE; }
676 bool outlier() const { return status == OUTLIER; }
677 bool farPoint() const { return status == FAR_POINT; }
678 bool behindCamera() const { return status == BEHIND_CAMERA; }
679 const gtsam::Point3& get() const {
680 if (!has_value()) throw std::runtime_error("TriangulationResult has no value");
681 return value();
682 }
683 // stream to output
684 GTSAM_EXPORT friend std::ostream& operator<<(
685 std::ostream& os, const TriangulationResult& result) {
686 if (result)
687 os << "point = " << *result << std::endl;
688 else
689 os << "no point, status = " << result.status << std::endl;
690 return os;
691 }
692
693 private:
694#if GTSAM_ENABLE_BOOST_SERIALIZATION
696 friend class boost::serialization::access;
697 template <class ARCHIVE>
698 void serialize(ARCHIVE& ar, const unsigned int version) {
699 ar& BOOST_SERIALIZATION_NVP(status);
700 }
701#endif
702};
703
705template<class CAMERA>
707 const typename CAMERA::MeasurementVector& measured,
708 const TriangulationParameters& params) {
709
710 size_t m = cameras.size();
711
712 // if we have a single pose the corresponding factor is uninformative
713 if (m < 2)
714 return TriangulationResult::Degenerate();
715 else
716 // We triangulate the 3D position of the landmark
717 try {
718 Point3 point =
719 triangulatePoint3<CAMERA>(cameras, measured, params.rankTolerance,
720 params.enableEPI, params.noiseModel, params.useLOST);
721
722 // Check landmark distance and re-projection errors to avoid outliers
723 size_t i = 0;
724 double maxReprojError = 0.0;
725 for(const CAMERA& camera: cameras) {
726 const Pose3& pose = camera.pose();
727 if (params.landmarkDistanceThreshold > 0
728 && distance3(pose.translation(), point)
730 return TriangulationResult::FarPoint();
731#ifdef GTSAM_THROW_CHEIRALITY_EXCEPTION
732 // verify that the triangulated point lies in front of all cameras
733 // Only needed if this was not yet handled by exception
734 const Point3& p_local = pose.transformTo(point);
735 if (p_local.z() <= 0)
736 return TriangulationResult::BehindCamera();
737#endif
738 // Check reprojection error
739 if (params.dynamicOutlierRejectionThreshold > 0) {
740 const typename CAMERA::Measurement& zi = measured.at(i);
741 Point2 reprojectionError = camera.reprojectionError(point, zi);
742 maxReprojError = std::max(maxReprojError, reprojectionError.norm());
743 }
744 i += 1;
745 }
746 // Flag as degenerate if average reprojection error is too large
748 && maxReprojError > params.dynamicOutlierRejectionThreshold)
749 return TriangulationResult::Outlier();
750
751 // all good!
752 return TriangulationResult(point);
754 // This exception is thrown if
755 // 1) There is a single pose for triangulation - this should not happen because we checked the number of poses before
756 // 2) The rank of the matrix used for triangulation is < 3: rotation-only, parallel cameras (or motion towards the landmark)
757 return TriangulationResult::Degenerate();
759 // point is behind one of the cameras: can be the case of close-to-parallel cameras or may depend on outliers
760 return TriangulationResult::BehindCamera();
761 }
762}
763
767template <class CAMERA>
768std::vector<TriangulationResult> triangulateSafe(
769 const CameraSet<CAMERA>& cameras,
770 const std::vector<std::map<size_t, typename CAMERA::Measurement>>& tracks,
771 const TriangulationParameters& params) {
772 std::vector<TriangulationResult> results;
773 results.reserve(tracks.size());
774 for (const auto& track : tracks) {
775 CameraSet<CAMERA> trackCameras;
776 typename CAMERA::MeasurementVector measurements;
777 trackCameras.reserve(track.size());
778 measurements.reserve(track.size());
779 for (const auto& [cameraIndex, measurement] : track) {
780 if (cameraIndex >= cameras.size()) {
781 throw std::out_of_range(
782 "triangulateSafe(batch): cameraIndex out of range for CameraSet");
783 }
784 trackCameras.push_back(cameras.at(cameraIndex));
785 measurements.push_back(measurement);
786 }
787 results.push_back(triangulateSafe(trackCameras, measurements, params));
788 }
789 return results;
790}
791
792// Vector of Cameras - used by the Python/MATLAB wrapper
793using CameraSetPinholePoseCal3Bundler = CameraSet<PinholePose<Cal3Bundler>>;
794using CameraSetPinholePoseCal3_S2 = CameraSet<PinholePose<Cal3_S2>>;
795using CameraSetPinholePoseCal3DS2 = CameraSet<PinholePose<Cal3DS2>>;
796using CameraSetPinholePoseCal3Fisheye = CameraSet<PinholePose<Cal3Fisheye>>;
797using CameraSetPinholePoseCal3Unified = CameraSet<PinholePose<Cal3Unified>>;
798
799using CameraSetCal3Bundler = CameraSet<PinholeCamera<Cal3Bundler>>;
800using CameraSetCal3_S2 = CameraSet<PinholeCamera<Cal3_S2>>;
801using CameraSetCal3DS2 = CameraSet<PinholeCamera<Cal3DS2>>;
802using CameraSetCal3Fisheye = CameraSet<PinholeCamera<Cal3Fisheye>>;
803using CameraSetCal3Unified = CameraSet<PinholeCamera<Cal3Unified>>;
804
805using CameraSetSpherical = CameraSet<SphericalCamera>;
806} // \namespace gtsam
The most common 5DOF 3D->2D calibration.
Unified Calibration Model, see Mei07icra for details.
Base class to create smart factors on poses or cameras.
3D Point
Base class for all pinhole cameras.
Calibration used by Bundler.
Calibrated camera with spherical projection.
2D Pose
Calibration of a camera with radial distortion, calculations in base class Cal3DS2_Base.
Calibration of a fisheye camera.
Factor Graph consisting of non-linear factors.
Global functions in a separate testing namespace.
Definition chartTesting.h:28
Point3Vector calibrateMeasurementsShared(const CALIBRATION &cal, const Point2Vector &measurements)
Convert pixel measurements in image to homogeneous measurements in the image plane using shared camer...
Definition triangulation.h:363
std::pair< NonlinearFactorGraph, Values > triangulationGraph(const std::vector< Pose3 > &poses, std::shared_ptr< CALIBRATION > sharedCal, const Point2Vector &measurements, Key landmarkKey, const Point3 &initialEstimate, const SharedNoiseModel &model=noiseModel::Unit::Create(2))
Create a factor graph with projection factors from poses and one calibration.
Definition triangulation.h:128
Point3 triangulateLOST(const std::vector< Pose3 > &poses, const Point3Vector &calibratedMeasurements, const SharedIsotropic &measurementNoise, double rank_tol)
Triangulation using the LOST (Linear Optimal Sine Triangulation) algorithm proposed in https://arxiv....
Definition triangulation.cpp:87
Point2Vector undistortMeasurements(const CALIBRATION &cal, const Point2Vector &measurements)
Remove distortion for measurements so as if the measurements came from a pinhole camera.
Definition triangulation.h:284
Cal3_S2 createPinholeCalibration(const CALIBRATION &cal)
Create a pinhole calibration from a different Cal3 object, removing distortion.
Definition triangulation.h:255
Vector3 Point3
As of GTSAM 4, in order to make GTSAM more lean, it is now possible to just typedef Point3 to Vector3...
Definition Point3.h:38
Point3 optimize(const NonlinearFactorGraph &graph, const Values &values, Key landmarkKey)
Optimize for triangulation.
Definition triangulation.cpp:178
MEASUREMENT undistortMeasurementInternal(const CALIBRATION &cal, const MEASUREMENT &measurement, std::optional< Cal3_S2 > pinholeCal={})
Internal undistortMeasurement to be used by undistortMeasurement and undistortMeasurements.
Definition triangulation.h:263
Vector2 Point2
As of GTSAM 4, in order to make GTSAM more lean, it is now possible to just typedef Point2 to Vector2...
Definition Point2.h:32
TriangulationResult triangulateSafe(const CameraSet< CAMERA > &cameras, const typename CAMERA::MeasurementVector &measured, const TriangulationParameters &params)
triangulateSafe: extensive checking of the outcome
Definition triangulation.h:706
noiseModel::Base::shared_ptr SharedNoiseModel
Aliases.
Definition NoiseModel.h:846
Point3 triangulateNonlinear(const std::vector< Pose3 > &poses, std::shared_ptr< CALIBRATION > sharedCal, const Point2Vector &measurements, const Point3 &initialEstimate, const SharedNoiseModel &model=nullptr)
Given an initial estimate , refine a point using measurements in several cameras.
Definition triangulation.h:193
std::uint64_t Key
Integer nonlinear key type.
Definition types.h:43
double distance3(const Point3 &p1, const Point3 &q, OptionalJacobian< 1, 3 > H1, OptionalJacobian< 1, 3 > H2)
distance between two points
Definition Point3.cpp:29
Point3Vector calibrateMeasurements(const CameraSet< CAMERA > &cameras, const typename CAMERA::MeasurementVector &measurements)
Convert pixel measurements in image to homogeneous measurements in the image plane using camera intri...
Definition triangulation.h:387
Point3 triangulateDLT(const std::vector< Matrix34, Eigen::aligned_allocator< Matrix34 > > &projection_matrices, const Point2Vector &measurements, double rank_tol)
DLT triangulation: See Hartley and Zisserman, 2nd Ed., page 312.
Definition triangulation.cpp:150
Point3 triangulatePoint3(const std::vector< Pose3 > &poses, std::shared_ptr< CALIBRATION > sharedCal, const Point2Vector &measurements, double rank_tol=1e-9, bool optimize=false, const SharedNoiseModel &model=nullptr, const bool useLOST=false)
Function to triangulate 3D landmark point from an arbitrary number of poses (at least 2) using the DL...
Definition triangulation.h:427
Vector4 triangulateHomogeneousDLT(const std::vector< Matrix34, Eigen::aligned_allocator< Matrix34 > > &projection_matrices, const Point2Vector &measurements, double rank_tol)
DLT triangulation: See Hartley and Zisserman, 2nd Ed., page 312.
Definition triangulation.cpp:28
All noise models live in the noiseModel namespace.
Definition LossFunctions.cpp:33
Base::shared_ptr validOrDefault(const T &value, const Base::shared_ptr &model)
Create.
Definition NoiseModel.h:833
A manifold defines a space in which there is a notion of a linear tangent space that can be centered ...
Definition Group.h:37
The most common 5DOF 3D->2D calibration.
Definition Cal3_S2.h:35
A set of cameras, all with their own calibration.
Definition CameraSet.h:37
A pinhole camera class that has a Pose3 and a Calibration.
Definition PinholeCamera.h:34
A pinhole camera class that has a Pose3 and a fixed Calibration.
Definition PinholePose.h:236
A 3D pose (R,t) : (Rot3,Point3).
Definition Pose3.h:42
const Point3 & translation(OptionalJacobian< 3, 6 > Hself={}) const
get translation
Definition Pose3.cpp:158
Point3 transformTo(const Point3 &point, OptionalJacobian< 3, 6 > Hself={}, OptionalJacobian< 3, 3 > Hpoint={}) const
takes point in world coordinates and transforms it to Pose coordinates
Definition Pose3.cpp:204
Exception thrown by triangulateDLT when SVD returns rank < 3.
Definition triangulation.h:44
Exception thrown by triangulateDLT when landmark is behind one or more of the cameras.
Definition triangulation.h:52
Definition triangulation.h:566
double dynamicOutlierRejectionThreshold
If this is nonnegative the we will check if the average reprojection error is smaller than this thres...
Definition triangulation.h:583
double rankTolerance
threshold to decide whether triangulation is result.degenerate
Definition triangulation.h:568
double landmarkDistanceThreshold
if the landmark is triangulated at distance larger than this, result is flagged as degenerate.
Definition triangulation.h:576
bool enableEPI
if set to true, will refine triangulation using LM
Definition triangulation.h:570
SharedNoiseModel noiseModel
used in the nonlinear triangulation
Definition triangulation.h:590
TriangulationParameters(const double _rankTolerance=1.0, const bool _enableEPI=false, double _landmarkDistanceThreshold=-1, double _dynamicOutlierRejectionThreshold=-1, const bool _useLOST=false, const SharedNoiseModel &_noiseModel=nullptr)
Constructor.
Definition triangulation.h:601
bool useLOST
if true, will use the LOST algorithm instead of DLT
Definition triangulation.h:588
TriangulationResult is an optional point, along with the reasons why it is invalid.
Definition triangulation.h:646
TriangulationResult()
Default constructor, only for serialization.
Definition triangulation.h:658
TriangulationResult(const Point3 &p)
Constructor.
Definition triangulation.h:663
IsDerived< DERIVEDFACTOR > emplace_shared(Args &&... args)
Emplace a shared pointer to factor of given type.
Definition FactorGraph.h:153
Character and index key used to refer to variables.
Definition Symbol.h:37
static shared_ptr Sigma(size_t dim, double sigma, bool smart=true)
An isotropic noise model created by specifying a standard deviation sigma.
Definition NoiseModel.cpp:706
static shared_ptr Create(size_t dim)
Create a unit covariance noise model.
Definition NoiseModel.h:673
Definition NonlinearFactorGraph.h:57
A non-templated config holding any types of Manifold-group elements.
Definition Values.h:65
void insert(Key j, const Value &val)
Add a variable with the given j, throws KeyAlreadyExists<J> if j is already present.
Definition Values.cpp:170
Non-linear factor for a constraint derived from a 2D measurement.
Definition TriangulationFactor.h:33
In nonlinear factors, the error function returns the negative log-likelihood as a non-linear function...