33 #include <gtsam/inference/Symbol.h> 35 #include <gtsam/slam/TriangulationFactor.h> 45 std::runtime_error(
"Triangulation Underconstrained Exception.") {
54 "Triangulation Cheirality Exception: The resulting landmark is behind one or more cameras.") {
66 const std::vector<Matrix34, Eigen::aligned_allocator<Matrix34>>& projection_matrices,
67 const Point2Vector& measurements,
double rank_tol = 1e-9);
78 const std::vector<Matrix34, Eigen::aligned_allocator<Matrix34>>& projection_matrices,
79 const std::vector<Unit3>& measurements,
double rank_tol = 1e-9);
89 const std::vector<Matrix34, Eigen::aligned_allocator<Matrix34>>& projection_matrices,
90 const Point2Vector& measurements,
91 double rank_tol = 1e-9);
97 const std::vector<Matrix34, Eigen::aligned_allocator<Matrix34>>& projection_matrices,
98 const std::vector<Unit3>& measurements,
99 double rank_tol = 1e-9);
112 const Point3Vector& calibratedMeasurements,
113 const SharedIsotropic& measurementNoise);
124 template<
class CALIBRATION>
126 const std::vector<Pose3>& poses, std::shared_ptr<CALIBRATION> sharedCal,
127 const Point2Vector& measurements,
Key landmarkKey,
128 const Point3& initialEstimate,
131 values.
insert(landmarkKey, initialEstimate);
133 for (
size_t i = 0; i < measurements.size(); i++) {
134 const Pose3& pose_i = poses[i];
136 Camera camera_i(pose_i, sharedCal);
138 (camera_i, measurements[i], model, landmarkKey);
140 return {graph, values};
152 template<
class CAMERA>
155 const typename CAMERA::MeasurementVector& measurements,
Key landmarkKey,
156 const Point3& initialEstimate,
159 values.
insert(landmarkKey, initialEstimate);
163 for (
size_t i = 0; i < measurements.size(); i++) {
164 const CAMERA& camera_i = cameras[i];
166 (camera_i, measurements[i], model? model : unit, landmarkKey);
168 return {graph, values};
189 template<
class CALIBRATION>
191 std::shared_ptr<CALIBRATION> sharedCal,
192 const Point2Vector& measurements,
const Point3& initialEstimate,
196 const auto [graph, values] = triangulationGraph<CALIBRATION>
197 (poses, sharedCal, measurements,
Symbol(
'p', 0), initialEstimate, model);
209 template<
class CAMERA>
212 const typename CAMERA::MeasurementVector& measurements,
const Point3& initialEstimate,
216 const auto [graph, values] = triangulationGraph<CAMERA>
217 (cameras, measurements,
Symbol(
'p', 0), initialEstimate, model);
222 template<
class CAMERA>
223 std::vector<Matrix34, Eigen::aligned_allocator<Matrix34>>
225 std::vector<Matrix34, Eigen::aligned_allocator<Matrix34>> projection_matrices;
226 for (
const CAMERA &camera: cameras) {
227 projection_matrices.push_back(camera.cameraProjectionMatrix());
229 return projection_matrices;
233 template<
class CALIBRATION>
234 std::vector<Matrix34, Eigen::aligned_allocator<Matrix34>> projectionMatricesFromPoses(
235 const std::vector<Pose3> &poses, std::shared_ptr<CALIBRATION> sharedCal) {
236 std::vector<Matrix34, Eigen::aligned_allocator<Matrix34>> projection_matrices;
237 for (
size_t i = 0; i < poses.size(); i++) {
239 projection_matrices.push_back(camera.cameraProjectionMatrix());
241 return projection_matrices;
251 template <
class CALIBRATION>
253 const auto& K = cal.K();
254 return Cal3_S2(K(0, 0), K(1, 1), K(0, 1), K(0, 2), K(1, 2));
259 template <
class CALIBRATION,
class MEASUREMENT>
261 const CALIBRATION& cal,
const MEASUREMENT& measurement,
262 std::optional<Cal3_S2> pinholeCal = {}) {
266 return pinholeCal->uncalibrate(cal.calibrate(measurement));
280 template <
class CALIBRATION>
282 const Point2Vector& measurements) {
284 Point2Vector undistortedMeasurements;
287 std::transform(measurements.begin(), measurements.end(),
288 std::back_inserter(undistortedMeasurements),
289 [&cal, &pinholeCalibration](
const Point2& measurement) {
290 return undistortMeasurementInternal<CALIBRATION>(
291 cal, measurement, pinholeCalibration);
293 return undistortedMeasurements;
299 const Point2Vector& measurements) {
314 template <
class CAMERA>
317 const typename CAMERA::MeasurementVector& measurements) {
318 const size_t nrMeasurements = measurements.size();
319 assert(nrMeasurements == cameras.size());
320 typename CAMERA::MeasurementVector undistortedMeasurements(nrMeasurements);
321 for (
size_t ii = 0; ii < nrMeasurements; ++ii) {
324 undistortedMeasurements[ii] =
325 undistortMeasurementInternal<typename CAMERA::CalibrationType>(
326 cameras[ii].calibration(), measurements[ii]);
328 return undistortedMeasurements;
332 template <
class CAMERA = PinholeCamera<Cal3_S2>>
335 const PinholeCamera<Cal3_S2>::MeasurementVector& measurements) {
340 template <
class CAMERA = SphericalCamera>
343 const SphericalCamera::MeasurementVector& measurements) {
355 template <
class CALIBRATION>
357 const CALIBRATION& cal,
const Point2Vector& measurements) {
358 Point3Vector calibratedMeasurements;
361 std::transform(measurements.begin(), measurements.end(),
362 std::back_inserter(calibratedMeasurements),
363 [&cal](
const Point2& measurement) {
365 p << cal.calibrate(measurement), 1.0;
368 return calibratedMeasurements;
379 template <
class CAMERA>
382 const typename CAMERA::MeasurementVector& measurements) {
383 const size_t nrMeasurements = measurements.size();
384 assert(nrMeasurements == cameras.size());
385 Point3Vector calibratedMeasurements(nrMeasurements);
386 for (
size_t ii = 0; ii < nrMeasurements; ++ii) {
387 calibratedMeasurements[ii]
388 << cameras[ii].calibration().calibrate(measurements[ii]),
391 return calibratedMeasurements;
395 template <
class CAMERA = SphericalCamera>
398 const SphericalCamera::MeasurementVector& measurements) {
399 Point3Vector calibratedMeasurements(measurements.size());
400 for (
size_t ii = 0; ii < measurements.size(); ++ii) {
401 calibratedMeasurements[ii] << measurements[ii].point3();
403 return calibratedMeasurements;
419 template <
class CALIBRATION>
421 std::shared_ptr<CALIBRATION> sharedCal,
422 const Point2Vector& measurements,
423 double rank_tol = 1e-9,
bool optimize =
false,
425 const bool useLOST =
false) {
426 assert(poses.size() == measurements.size());
434 const double measurementSigma = model ? model->sigmas().mean() : 1e-4;
435 SharedIsotropic measurementNoise =
439 auto calibratedMeasurements =
440 calibrateMeasurementsShared<CALIBRATION>(*sharedCal, measurements);
442 point =
triangulateLOST(poses, calibratedMeasurements, measurementNoise);
445 auto projection_matrices = projectionMatricesFromPoses(poses, sharedCal);
448 auto undistortedMeasurements =
449 undistortMeasurements<CALIBRATION>(*sharedCal, measurements);
452 triangulateDLT(projection_matrices, undistortedMeasurements, rank_tol);
457 point = triangulateNonlinear<CALIBRATION>
458 (poses, sharedCal, measurements, point, model);
460 #ifdef GTSAM_THROW_CHEIRALITY_EXCEPTION 462 for (
const Pose3& pose : poses) {
463 const Point3& p_local = pose.transformTo(point);
485 template <
class CAMERA>
487 const typename CAMERA::MeasurementVector& measurements,
488 double rank_tol = 1e-9,
bool optimize =
false,
490 const bool useLOST =
false) {
491 size_t m = cameras.size();
492 assert(measurements.size() == m);
501 const double measurementSigma = model ? model->sigmas().mean() : 1e-4;
502 SharedIsotropic measurementNoise =
506 std::vector<Pose3> poses;
507 poses.reserve(cameras.size());
508 for (
const auto& camera : cameras) poses.push_back(camera.pose());
512 auto calibratedMeasurements =
513 calibrateMeasurements<CAMERA>(cameras, measurements);
515 point =
triangulateLOST(poses, calibratedMeasurements, measurementNoise);
518 auto projection_matrices = projectionMatricesFromCameras(cameras);
521 auto undistortedMeasurements =
522 undistortMeasurements<CAMERA>(cameras, measurements);
525 triangulateDLT(projection_matrices, undistortedMeasurements, rank_tol);
530 point = triangulateNonlinear<CAMERA>(cameras, measurements, point, model);
533 #ifdef GTSAM_THROW_CHEIRALITY_EXCEPTION 535 for (
const CAMERA& camera : cameras) {
536 const Point3& p_local = camera.pose().transformTo(point);
545 template <
class CALIBRATION>
547 const Point2Vector& measurements,
548 double rank_tol = 1e-9,
bool optimize =
false,
550 const bool useLOST =
false) {
551 return triangulatePoint3<PinholeCamera<CALIBRATION>>
552 (cameras, measurements, rank_tol,
optimize, model, useLOST);
586 const bool _enableEPI =
false,
double _landmarkDistanceThreshold = -1,
587 double _dynamicOutlierRejectionThreshold = -1,
589 rankTolerance(_rankTolerance), enableEPI(_enableEPI),
590 landmarkDistanceThreshold(_landmarkDistanceThreshold),
591 dynamicOutlierRejectionThreshold(_dynamicOutlierRejectionThreshold),
592 noiseModel(_noiseModel){
596 friend std::ostream &operator<<(std::ostream &os,
599 os <<
"enableEPI = " << p.
enableEPI << std::endl;
602 os <<
"dynamicOutlierRejectionThreshold = " 604 os <<
"noise model" << std::endl;
610 #ifdef GTSAM_ENABLE_BOOST_SERIALIZATION 611 friend class boost::serialization::access; 613 template<
class ARCHIVE>
614 void serialize(ARCHIVE & ar,
const unsigned int version) {
615 ar & BOOST_SERIALIZATION_NVP(rankTolerance);
616 ar & BOOST_SERIALIZATION_NVP(enableEPI);
617 ar & BOOST_SERIALIZATION_NVP(landmarkDistanceThreshold);
618 ar & BOOST_SERIALIZATION_NVP(dynamicOutlierRejectionThreshold);
629 enum Status { VALID, DEGENERATE, BEHIND_CAMERA, OUTLIER, FAR_POINT };
655 bool valid()
const {
return status == VALID; }
656 bool degenerate()
const {
return status == DEGENERATE; }
657 bool outlier()
const {
return status == OUTLIER; }
658 bool farPoint()
const {
return status == FAR_POINT; }
659 bool behindCamera()
const {
return status == BEHIND_CAMERA; }
661 if (!has_value())
throw std::runtime_error(
"TriangulationResult has no value");
665 friend std::ostream& operator<<(std::ostream& os,
668 os <<
"point = " << *result << std::endl;
670 os <<
"no point, status = " << result.status << std::endl;
675 #ifdef GTSAM_ENABLE_BOOST_SERIALIZATION 676 friend class boost::serialization::access; 678 template <
class ARCHIVE>
679 void serialize(ARCHIVE& ar,
const unsigned int version) {
680 ar& BOOST_SERIALIZATION_NVP(status);
686 template<
class CAMERA>
688 const typename CAMERA::MeasurementVector& measured,
691 size_t m = cameras.size();
695 return TriangulationResult::Degenerate();
700 triangulatePoint3<CAMERA>(cameras, measured, params.
rankTolerance,
705 double maxReprojError = 0.0;
706 for(
const CAMERA& camera: cameras) {
707 const Pose3& pose = camera.pose();
711 return TriangulationResult::FarPoint();
712 #ifdef GTSAM_THROW_CHEIRALITY_EXCEPTION 716 if (p_local.z() <= 0)
717 return TriangulationResult::BehindCamera();
721 const typename CAMERA::Measurement& zi = measured.at(i);
722 Point2 reprojectionError = camera.reprojectionError(point, zi);
723 maxReprojError = std::max(maxReprojError, reprojectionError.norm());
730 return TriangulationResult::Outlier();
738 return TriangulationResult::Degenerate();
741 return TriangulationResult::BehindCamera();
TriangulationParameters(const double _rankTolerance=1.0, const bool _enableEPI=false, double _landmarkDistanceThreshold=-1, double _dynamicOutlierRejectionThreshold=-1, const SharedNoiseModel &_noiseModel=nullptr)
Definition: triangulation.h:585
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))
Definition: triangulation.h:125
TriangulationResult(const Point3 &p)
Definition: triangulation.h:644
GTSAM_EXPORT Vector4 triangulateHomogeneousDLT(const std::vector< Matrix34, Eigen::aligned_allocator< Matrix34 >> &projection_matrices, const Point2Vector &measurements, double rank_tol=1e-9)
IsDerived< DERIVEDFACTOR > emplace_shared(Args &&... args)
Emplace a shared pointer to factor of given type.
Definition: FactorGraph.h:196
SharedNoiseModel noiseModel
used in the nonlinear triangulation
Definition: triangulation.h:574
Factor Graph consisting of non-linear factors.
std::string serialize(const T &input)
serializes to a string
Definition: serialization.h:113
void insert(Key j, const Value &val)
Base class to create smart factors on poses or cameras.
Vector2 Point2
Definition: Point2.h:32
double dynamicOutlierRejectionThreshold
Definition: triangulation.h:572
Point3Vector calibrateMeasurements(const CameraSet< CAMERA > &cameras, const typename CAMERA::MeasurementVector &measurements)
Definition: triangulation.h:380
Calibrated camera with spherical projection.
Calibration of a camera with radial distortion, calculations in base class Cal3DS2_Base.
GTSAM_EXPORT Point3 triangulateLOST(const std::vector< Pose3 > &poses, const Point3Vector &calibratedMeasurements, const SharedIsotropic &measurementNoise)
Triangulation using the LOST (Linear Optimal Sine Triangulation) algorithm proposed in https://arxiv...
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
A set of cameras, all with their own calibration.
Definition: CameraSet.h:36
static shared_ptr Create(size_t dim)
Definition: NoiseModel.h:610
Definition: TriangulationFactor.h:31
Base class for all pinhole cameras.
GTSAM_EXPORT Point3 optimize(const NonlinearFactorGraph &graph, const Values &values, Key landmarkKey)
double landmarkDistanceThreshold
Definition: triangulation.h:565
Definition: triangulation.h:555
Cal3_S2 createPinholeCalibration(const CALIBRATION &cal)
Definition: triangulation.h:252
bool enableEPI
if set to true, will refine triangulation using LM
Definition: triangulation.h:559
double rankTolerance
(the rank is the number of singular values of the triangulation matrix which are larger than rankTole...
Definition: triangulation.h:557
TriangulationResult()
Definition: triangulation.h:639
Point2Vector undistortMeasurements(const CALIBRATION &cal, const Point2Vector &measurements)
Definition: triangulation.h:281
Exception thrown by triangulateDLT when SVD returns rank < 3.
Definition: triangulation.h:42
The most common 5DOF 3D->2D calibration.
Definition: Cal3_S2.h:34
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)
Definition: triangulation.h:420
TriangulationResult triangulateSafe(const CameraSet< CAMERA > &cameras, const typename CAMERA::MeasurementVector &measured, const TriangulationParameters ¶ms)
triangulateSafe: extensive checking of the outcome
Definition: triangulation.h:687
Definition: PinholePose.h:239
Definition: NonlinearFactorGraph.h:55
Exception thrown by triangulateDLT when landmark is behind one or more of the cameras.
Definition: triangulation.h:50
Definition: PinholeCamera.h:33
Definition: chartTesting.h:28
GTSAM_EXPORT Point3 triangulateDLT(const std::vector< Matrix34, Eigen::aligned_allocator< Matrix34 >> &projection_matrices, const Point2Vector &measurements, double rank_tol=1e-9)
const Point3 & translation(OptionalJacobian< 3, 6 > Hself={}) const
get translation
GTSAM_EXPORT double distance3(const Point3 &p1, const Point3 &q, OptionalJacobian< 1, 3 > H1={}, OptionalJacobian< 1, 3 > H2={})
distance between two points
MEASUREMENT undistortMeasurementInternal(const CALIBRATION &cal, const MEASUREMENT &measurement, std::optional< Cal3_S2 > pinholeCal={})
Definition: triangulation.h:260
Calibration of a fisheye camera.
Vector3 Point3
Definition: Point3.h:38
Point3 triangulateNonlinear(const std::vector< Pose3 > &poses, std::shared_ptr< CALIBRATION > sharedCal, const Point2Vector &measurements, const Point3 &initialEstimate, const SharedNoiseModel &model=nullptr)
Definition: triangulation.h:190
Unified Calibration Model, see Mei07icra for details.
Definition: triangulation.h:627
std::uint64_t Key
Integer nonlinear key type.
Definition: types.h:102
Calibration used by Bundler.
noiseModel::Base::shared_ptr SharedNoiseModel
Definition: NoiseModel.h:741
The most common 5DOF 3D->2D calibration.
Point3Vector calibrateMeasurementsShared(const CALIBRATION &cal, const Point2Vector &measurements)
Definition: triangulation.h:356
static shared_ptr Sigma(size_t dim, double sigma, bool smart=true)