gtsam
Loading...
Searching...
No Matches
EssentialMatrixFactor.h
1/* ----------------------------------------------------------------------------
2
3 * GTSAM Copyright 2010-2014, 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
12/*
13 * @file EssentialMatrixFactor.h
14 * @brief EssentialMatrixFactor class
15 * @author Frank Dellaert
16 * @author Ayush Baid
17 * @author Akshay Krishnan
18 * @date December 17, 2013
19 */
20
21#pragma once
22
23#include <gtsam/geometry/EssentialMatrix.h>
26
27#include <iostream>
28
29namespace gtsam {
30
35class EssentialMatrixFactor : public NoiseModelFactorN<EssentialMatrix> {
36 Vector3 vA_, vB_;
37
39 typedef EssentialMatrixFactor This;
40
41 public:
42 // Provide access to the Matrix& version of evaluateError:
44
53 EssentialMatrixFactor(Key key, const Point2& pA, const Point2& pB,
54 const SharedNoiseModel& model)
55 : Base(model, key) {
58 }
59
69 template <class CALIBRATION>
70 EssentialMatrixFactor(Key key, const Point2& pA, const Point2& pB,
71 const SharedNoiseModel& model,
72 std::shared_ptr<CALIBRATION> K)
73 : Base(model, key) {
74#ifndef NDEBUG
75 if (!K) throw;
76#endif
77 vA_ = EssentialMatrix::Homogeneous(K->calibrate(pA));
78 vB_ = EssentialMatrix::Homogeneous(K->calibrate(pB));
79 }
80
82 gtsam::NonlinearFactor::shared_ptr clone() const override {
83 return std::static_pointer_cast<gtsam::NonlinearFactor>(
84 gtsam::NonlinearFactor::shared_ptr(new This(*this)));
85 }
86
88 void print(
89 const std::string& s = "",
90 const KeyFormatter& keyFormatter = DefaultKeyFormatter) const override {
91 Base::print(s);
92 std::cout << " EssentialMatrixFactor with measurements\n ("
93 << vA_.transpose() << ")' and (" << vB_.transpose() << ")'"
94 << std::endl;
95 }
96
99 OptionalMatrixType H) const override {
100 Vector error(1);
101 error(0) = E.error(vA_, vB_, H);
102 return error;
103 }
104};
105
112 : public NoiseModelFactorT<Vector2, EssentialMatrix, double> {
113 Point3 dP1_;
114 Point2 pn_;
115 double f_;
116
118 typedef EssentialMatrixFactor2 This;
119
120 public:
121 // Provide access to the Matrix& version of evaluateError:
123
132 EssentialMatrixFactor2(Key key1, Key key2, const Point2& pA, const Point2& pB,
133 const SharedNoiseModel& model)
134 : Base(model, key1, key2),
135 dP1_(EssentialMatrix::Homogeneous(pA)),
136 pn_(pB) {
137 f_ = 1.0;
138 }
139
149 template <class CALIBRATION>
150 EssentialMatrixFactor2(Key key1, Key key2, const Point2& pA, const Point2& pB,
151 const SharedNoiseModel& model,
152 std::shared_ptr<CALIBRATION> K)
153 : Base(model, key1, key2),
154 dP1_(EssentialMatrix::Homogeneous(K->calibrate(pA))),
155 pn_(K->calibrate(pB)) {
156 f_ = 0.5 * (K->fx() + K->fy());
157 }
158
160 gtsam::NonlinearFactor::shared_ptr clone() const override {
161 return std::static_pointer_cast<gtsam::NonlinearFactor>(
162 gtsam::NonlinearFactor::shared_ptr(new This(*this)));
163 }
164
166 void print(
167 const std::string& s = "",
168 const KeyFormatter& keyFormatter = DefaultKeyFormatter) const override {
169 Base::print(s);
170 std::cout << " EssentialMatrixFactor2 with measurements\n ("
171 << dP1_.transpose() << ")' and (" << pn_.transpose() << ")'"
172 << std::endl;
173 }
174
175 /*
176 * Vector of errors returns 2D vector
177 * @param E essential matrix
178 * @param d inverse depth d
179 */
180 Vector2 evaluateError(const EssentialMatrix& E, const double& d,
182 OptionalMatrixType Dd) const override {
183 // We have point x,y in image 1
184 // Given a depth Z, the corresponding 3D point P1 = Z*(x,y,1) = (x,y,1)/d
185 // We then convert to second camera by P2 = 1R2'*(P1-1T2)
186 // The homogeneous coordinates of can be written as
187 // 2R1*(P1-1T2) == 2R1*d*(P1-1T2) == 2R1*((x,y,1)-d*1T2)
188 // where we multiplied with d which yields equivalent homogeneous
189 // coordinates. Note that this is just the homography 2R1 for d==0 The point
190 // d*P1 = (x,y,1) is computed in constructor as dP1_
191
192 // Project to normalized image coordinates, then uncalibrate
193 Point2 pn(0, 0);
194 if (!DE && !Dd) {
195 Point3 _1T2 = E.direction().point3();
196 Point3 d1T2 = d * _1T2;
197 Point3 dP2 = E.rotation().unrotate(dP1_ - d1T2); // 2R1*((x,y,1)-d*1T2)
198 pn = PinholeBase::Project(dP2);
199
200 } else {
201 // Calculate derivatives. TODO if slow: optimize with Mathematica
202 // 3*2 3*3 3*3
203 Matrix D_1T2_dir, DdP2_rot, DP2_point;
204
205 Point3 _1T2 = E.direction().point3(D_1T2_dir);
206 Point3 d1T2 = d * _1T2;
207 Point3 dP2 = E.rotation().unrotate(dP1_ - d1T2, DdP2_rot, DP2_point);
208
209 Matrix23 Dpn_dP2;
210 pn = PinholeBase::Project(dP2, Dpn_dP2);
211
212 if (DE) {
213 Matrix DdP2_E(3, 5);
214 DdP2_E << DdP2_rot, -DP2_point * d * D_1T2_dir; // (3*3), (3*3) * (3*2)
215 *DE = f_ * Dpn_dP2 * DdP2_E; // (2*3) * (3*5)
216 }
217
218 if (Dd) // efficient backwards computation:
219 // (2*3) * (3*3) * (3*1)
220 *Dd = -f_ * (Dpn_dP2 * (DP2_point * _1T2));
221 }
222 Point2 reprojectionError = pn - pn_;
223 return f_ * reprojectionError;
224 }
225};
226// EssentialMatrixFactor2
227
235 typedef EssentialMatrixFactor2 Base;
236 typedef EssentialMatrixFactor3 This;
237
238 Rot3 cRb_;
239
240 public:
241 // Provide access to the Matrix& version of evaluateError:
242 using Base::evaluateError;
243
253 EssentialMatrixFactor3(Key key1, Key key2, const Point2& pA, const Point2& pB,
254 const Rot3& cRb, const SharedNoiseModel& model)
255 : EssentialMatrixFactor2(key1, key2, pA, pB, model), cRb_(cRb) {}
256
266 template <class CALIBRATION>
267 EssentialMatrixFactor3(Key key1, Key key2, const Point2& pA, const Point2& pB,
268 const Rot3& cRb, const SharedNoiseModel& model,
269 std::shared_ptr<CALIBRATION> K)
270 : EssentialMatrixFactor2(key1, key2, pA, pB, model, K), cRb_(cRb) {}
271
273 gtsam::NonlinearFactor::shared_ptr clone() const override {
274 return std::static_pointer_cast<gtsam::NonlinearFactor>(
275 gtsam::NonlinearFactor::shared_ptr(new This(*this)));
276 }
277
279 void print(
280 const std::string& s = "",
281 const KeyFormatter& keyFormatter = DefaultKeyFormatter) const override {
282 Base::print(s);
283 std::cout << " EssentialMatrixFactor3 with rotation " << cRb_ << std::endl;
284 }
285
286 /*
287 * Vector of errors returns 2D vector
288 * @param E essential matrix
289 * @param d inverse depth d
290 */
291 Vector2 evaluateError(const EssentialMatrix& E, const double& d,
293 OptionalMatrixType Dd) const override {
294 if (!DE) {
295 // Convert E from body to camera frame
296 EssentialMatrix cameraE = cRb_ * E;
297 // Evaluate error
298 return Base::evaluateError(cameraE, d, OptionalNone, Dd);
299 } else {
300 // Version with derivatives
301 Matrix D_e_cameraE, D_cameraE_E; // 2*5, 5*5
302 EssentialMatrix cameraE = E.rotate(cRb_, D_cameraE_E);
303 // Using the pointer version of evaluateError since the Base class
304 // (EssentialMatrixFactor2) does not have the matrix reference version of
305 // evaluateError
306 Vector e = Base::evaluateError(cameraE, d, &D_e_cameraE, Dd);
307 *DE = D_e_cameraE * D_cameraE_E; // (2*5) * (5*5)
308 return e;
309 }
310 }
311};
312// EssentialMatrixFactor3
313
328template <class CALIBRATION>
330 : public NoiseModelFactorT<Vector1, EssentialMatrix, CALIBRATION> {
331 private:
332 Point2 pA_, pB_;
333
335 typedef EssentialMatrixFactor4 This;
336
337 static constexpr int DimK = FixedDimension<CALIBRATION>::value;
338 typedef Eigen::Matrix<double, 2, DimK> JacobianCalibration;
339
340 public:
341 // Provide access to the Matrix& version of evaluateError:
343
353 EssentialMatrixFactor4(Key keyE, Key keyK, const Point2& pA, const Point2& pB,
354 const SharedNoiseModel& model = nullptr)
355 : Base(noiseModel::validOrDefault(0.0, model), keyE, keyK),
356 pA_(pA), pB_(pB) {}
357
359 gtsam::NonlinearFactor::shared_ptr clone() const override {
360 return std::static_pointer_cast<gtsam::NonlinearFactor>(
361 gtsam::NonlinearFactor::shared_ptr(new This(*this)));
362 }
363
365 void print(
366 const std::string& s = "",
367 const KeyFormatter& keyFormatter = DefaultKeyFormatter) const override {
368 Base::print(s);
369 std::cout << " EssentialMatrixFactor4 with measurements\n ("
370 << pA_.transpose() << ")' and (" << pB_.transpose() << ")'"
371 << std::endl;
372 }
373
383 Vector1 evaluateError(const EssentialMatrix& E, const CALIBRATION& K,
385 OptionalMatrixType HK) const override {
386 // converting from pixel coordinates to normalized coordinates cA and cB
387 JacobianCalibration cA_H_K; // dcA/dK
388 JacobianCalibration cB_H_K; // dcB/dK
389 Point2 cA = K.calibrate(pA_, HK ? &cA_H_K : 0, OptionalNone);
390 Point2 cB = K.calibrate(pB_, HK ? &cB_H_K : 0, OptionalNone);
391
392 // convert to homogeneous coordinates
393 Vector3 vA = EssentialMatrix::Homogeneous(cA);
394 Vector3 vB = EssentialMatrix::Homogeneous(cB);
395
396 if (HK) {
397 // compute the jacobian of error w.r.t K
398
399 // error function f = vA.T * E * vB
400 // H2 = df/dK = vB.T * E.T * dvA/dK + vA.T * E * dvB/dK
401 // where dvA/dK = dvA/dcA * dcA/dK, dVB/dK = dvB/dcB * dcB/dK
402 // and dvA/dcA = dvB/dcB = [[1, 0], [0, 1], [0, 0]]
403 Matrix DynamicH_K = vB.transpose() * E.matrix().transpose().leftCols<2>() * cA_H_K +
404 vA.transpose() * E.matrix().leftCols<2>() * cB_H_K; // (1*2) * (2*DimK)
405 *HK = DynamicH_K;
406 }
407
408 return Vector1(E.error(vA, vB, HE));
409 }
410};
411// EssentialMatrixFactor4
412
425template <class CALIBRATION>
427 : public NoiseModelFactorT<Vector1, EssentialMatrix, CALIBRATION,
428 CALIBRATION> {
429 private:
430 Point2 pA_, pB_;
431
433 Base;
434 typedef EssentialMatrixFactor5 This;
435
436 static constexpr int DimK = FixedDimension<CALIBRATION>::value;
437 typedef Eigen::Matrix<double, 2, DimK> JacobianCalibration;
438
439 public:
440 // Provide access to the Matrix& version of evaluateError:
442
453 EssentialMatrixFactor5(Key keyE, Key keyKa, Key keyKb, const Point2& pA,
454 const Point2& pB,
455 const SharedNoiseModel& model = nullptr)
456 : Base(noiseModel::validOrDefault(0.0, model), keyE, keyKa, keyKb),
457 pA_(pA), pB_(pB) {}
458
460 gtsam::NonlinearFactor::shared_ptr clone() const override {
461 return std::static_pointer_cast<gtsam::NonlinearFactor>(
462 gtsam::NonlinearFactor::shared_ptr(new This(*this)));
463 }
464
466 void print(
467 const std::string& s = "",
468 const KeyFormatter& keyFormatter = DefaultKeyFormatter) const override {
469 Base::print(s);
470 std::cout << " EssentialMatrixFactor5 with measurements\n ("
471 << pA_.transpose() << ")' and (" << pB_.transpose() << ")'"
472 << std::endl;
473 }
474
486 Vector1 evaluateError(const EssentialMatrix& E, const CALIBRATION& Ka,
487 const CALIBRATION& Kb, OptionalMatrixType HE,
489 OptionalMatrixType HKb) const override {
490 // converting from pixel coordinates to normalized coordinates cA and cB
491 JacobianCalibration cA_H_Ka; // dcA/dKa
492 JacobianCalibration cB_H_Kb; // dcB/dKb
493 Point2 cA = Ka.calibrate(pA_, HKa ? &cA_H_Ka : 0, OptionalNone);
494 Point2 cB = Kb.calibrate(pB_, HKb ? &cB_H_Kb : 0, OptionalNone);
495
496 // Convert to homogeneous coordinates.
497 Vector3 vA = EssentialMatrix::Homogeneous(cA);
498 Vector3 vB = EssentialMatrix::Homogeneous(cB);
499
500 if (HKa) {
501 // Compute the jacobian of error w.r.t Ka.
502 Matrix DynamicHka = vB.transpose() * E.matrix().transpose().leftCols<2>() * cA_H_Ka;
503 *HKa = DynamicHka;
504 }
505
506 if (HKb) {
507 // Compute the jacobian of error w.r.t Kb.
508 Matrix DynamicHkb = vA.transpose() * E.matrix().leftCols<2>() * cB_H_Kb;
509 *HKb = DynamicHkb;
510 }
511
512 return Vector1(E.error(vA, vB, HE));
513 }
514};
515// EssentialMatrixFactor5
516
517} // namespace gtsam
Base class for all pinhole cameras.
Non-linear factor base classes.
#define OptionalNone
These typedefs and aliases will help with making the evaluateError interface independent of boost TOD...
Definition NonlinearFactor.h:51
Global functions in a separate testing namespace.
Definition chartTesting.h:28
KeyFormatter DefaultKeyFormatter
Assign default key formatter.
Definition Key.cpp:30
Matrix * OptionalMatrixType
This typedef will be used everywhere boost::optional<Matrix&> reference was used previously.
Definition NonlinearFactor.h:57
NoiseModelFactorT< Vector, ValueTypes... > NoiseModelFactorN
Noise model factor with N value types and dynamic-sized error vector.
Definition NoiseModelFactorN.h:561
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
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
std::function< std::string(Key)> KeyFormatter
Typedef for a function to format a key, i.e. to convert it to a string.
Definition Key.h:35
noiseModel::Base::shared_ptr SharedNoiseModel
Aliases.
Definition NoiseModel.h:846
std::uint64_t Key
Integer nonlinear key type.
Definition types.h:43
All noise models live in the noiseModel namespace.
Definition LossFunctions.cpp:33
static Point2 Project(const Point3 &pc, OptionalJacobian< 2, 3 > Dpoint={})
Project from 3D point in camera coordinates into image Does not throw a CheiralityException,...
Definition CalibratedCamera.cpp:89
An essential matrix is like a Pose3, except with translation up to scale It is named after the 3*3 ma...
Definition EssentialMatrix.h:26
static Vector3 Homogeneous(const Point2 &p)
Static function to convert Point2 to homogeneous coordinates.
Definition EssentialMatrix.h:34
Rot3 is a 3D rotation represented as a rotation matrix if the preprocessor symbol GTSAM_USE_QUATERNIO...
Definition Rot3.h:65
virtual void print(const std::string &s="Factor", const KeyFormatter &formatter=DefaultKeyFormatter) const
print
Definition Factor.cpp:29
NoiseModelFactorT()
Definition NoiseModelFactorN.h:257
virtual Vector evaluateError(const ValueTypes &... x, OptionalMatrixTypeT< ValueTypes >... H) const=0
Key key() const
Definition NoiseModelFactorN.h:307
double error(const Values &c) const override
Calculate the error of the factor.
Definition NonlinearFactor.cpp:146
EssentialMatrixFactor(Key key, const Point2 &pA, const Point2 &pB, const SharedNoiseModel &model, std::shared_ptr< CALIBRATION > K)
Constructor.
Definition EssentialMatrixFactor.h:70
gtsam::NonlinearFactor::shared_ptr clone() const override
Definition EssentialMatrixFactor.h:82
EssentialMatrixFactor(Key key, const Point2 &pA, const Point2 &pB, const SharedNoiseModel &model)
Constructor.
Definition EssentialMatrixFactor.h:53
Vector evaluateError(const EssentialMatrix &E, OptionalMatrixType H) const override
vector of errors returns 1D vector
Definition EssentialMatrixFactor.h:98
void print(const std::string &s="", const KeyFormatter &keyFormatter=DefaultKeyFormatter) const override
print
Definition EssentialMatrixFactor.h:88
gtsam::NonlinearFactor::shared_ptr clone() const override
Definition EssentialMatrixFactor.h:160
EssentialMatrixFactor2(Key key1, Key key2, const Point2 &pA, const Point2 &pB, const SharedNoiseModel &model, std::shared_ptr< CALIBRATION > K)
Constructor.
Definition EssentialMatrixFactor.h:150
EssentialMatrixFactor2(Key key1, Key key2, const Point2 &pA, const Point2 &pB, const SharedNoiseModel &model)
Constructor.
Definition EssentialMatrixFactor.h:132
void print(const std::string &s="", const KeyFormatter &keyFormatter=DefaultKeyFormatter) const override
print
Definition EssentialMatrixFactor.h:166
void print(const std::string &s="", const KeyFormatter &keyFormatter=DefaultKeyFormatter) const override
print
Definition EssentialMatrixFactor.h:279
EssentialMatrixFactor3(Key key1, Key key2, const Point2 &pA, const Point2 &pB, const Rot3 &cRb, const SharedNoiseModel &model)
Constructor.
Definition EssentialMatrixFactor.h:253
gtsam::NonlinearFactor::shared_ptr clone() const override
Definition EssentialMatrixFactor.h:273
EssentialMatrixFactor3(Key key1, Key key2, const Point2 &pA, const Point2 &pB, const Rot3 &cRb, const SharedNoiseModel &model, std::shared_ptr< CALIBRATION > K)
Constructor.
Definition EssentialMatrixFactor.h:267
EssentialMatrixFactor4(Key keyE, Key keyK, const Point2 &pA, const Point2 &pB, const SharedNoiseModel &model=nullptr)
Constructor.
Definition EssentialMatrixFactor.h:353
Vector1 evaluateError(const EssentialMatrix &E, const CALIBRATION &K, OptionalMatrixType HE, OptionalMatrixType HK) const override
Calculate the algebraic epipolar error pA' (K^-1)' E K pB.
Definition EssentialMatrixFactor.h:383
void print(const std::string &s="", const KeyFormatter &keyFormatter=DefaultKeyFormatter) const override
print
Definition EssentialMatrixFactor.h:365
gtsam::NonlinearFactor::shared_ptr clone() const override
Definition EssentialMatrixFactor.h:359
Vector1 evaluateError(const EssentialMatrix &E, const CALIBRATION &Ka, const CALIBRATION &Kb, OptionalMatrixType HE, OptionalMatrixType HKa, OptionalMatrixType HKb) const override
Calculate the algebraic epipolar error pA' (Ka^-1)' E Kb pB.
Definition EssentialMatrixFactor.h:486
EssentialMatrixFactor5(Key keyE, Key keyKa, Key keyKb, const Point2 &pA, const Point2 &pB, const SharedNoiseModel &model=nullptr)
Constructor.
Definition EssentialMatrixFactor.h:453
gtsam::NonlinearFactor::shared_ptr clone() const override
Definition EssentialMatrixFactor.h:460
void print(const std::string &s="", const KeyFormatter &keyFormatter=DefaultKeyFormatter) const override
print
Definition EssentialMatrixFactor.h:466