gtsam  3.2.1
gtsam
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
EssentialMatrixFactor.h
1 /*
2  * @file EssentialMatrixFactor.cpp
3  * @brief EssentialMatrixFactor class
4  * @author Frank Dellaert
5  * @date December 17, 2013
6  */
7 
8 #pragma once
9 
11 #include <gtsam/geometry/EssentialMatrix.h>
13 #include <gtsam/base/LieScalar.h>
14 #include <iostream>
15 
16 namespace gtsam {
17 
21 class EssentialMatrixFactor: public NoiseModelFactor1<EssentialMatrix> {
22 
23  Vector vA_, vB_;
24 
27 
28 public:
29 
37  EssentialMatrixFactor(Key key, const Point2& pA, const Point2& pB,
38  const SharedNoiseModel& model) :
39  Base(model, key) {
42  }
43 
52  template<class CALIBRATION>
53  EssentialMatrixFactor(Key key, const Point2& pA, const Point2& pB,
54  const SharedNoiseModel& model, boost::shared_ptr<CALIBRATION> K) :
55  Base(model, key) {
56  assert(K);
57  vA_ = EssentialMatrix::Homogeneous(K->calibrate(pA));
58  vB_ = EssentialMatrix::Homogeneous(K->calibrate(pB));
59  }
60 
62  virtual gtsam::NonlinearFactor::shared_ptr clone() const {
63  return boost::static_pointer_cast<gtsam::NonlinearFactor>(
64  gtsam::NonlinearFactor::shared_ptr(new This(*this)));
65  }
66 
68  virtual void print(const std::string& s = "",
69  const KeyFormatter& keyFormatter = DefaultKeyFormatter) const {
70  Base::print(s);
71  std::cout << " EssentialMatrixFactor with measurements\n ("
72  << vA_.transpose() << ")' and (" << vB_.transpose() << ")'"
73  << std::endl;
74  }
75 
77  Vector evaluateError(const EssentialMatrix& E, boost::optional<Matrix&> H =
78  boost::none) const {
79  Vector error(1);
80  error << E.error(vA_, vB_, H);
81  return error;
82  }
83 
84 };
85 
90 class EssentialMatrixFactor2: public NoiseModelFactor2<EssentialMatrix,
91  LieScalar> {
92 
93  Point3 dP1_;
94  Point2 pn_;
95  double f_;
96 
99 
100 public:
101 
110  EssentialMatrixFactor2(Key key1, Key key2, const Point2& pA, const Point2& pB,
111  const SharedNoiseModel& model) :
112  Base(model, key1, key2) {
113  dP1_ = Point3(pA.x(), pA.y(), 1);
114  pn_ = pB;
115  f_ = 1.0;
116  }
117 
127  template<class CALIBRATION>
128  EssentialMatrixFactor2(Key key1, Key key2, const Point2& pA, const Point2& pB,
129  const SharedNoiseModel& model, boost::shared_ptr<CALIBRATION> K) :
130  Base(model, key1, key2) {
131  assert(K);
132  Point2 p1 = K->calibrate(pA);
133  dP1_ = Point3(p1.x(), p1.y(), 1); // d*P1 = (x,y,1)
134  pn_ = K->calibrate(pB);
135  f_ = 0.5 * (K->fx() + K->fy());
136  }
137 
139  virtual gtsam::NonlinearFactor::shared_ptr clone() const {
140  return boost::static_pointer_cast<gtsam::NonlinearFactor>(
141  gtsam::NonlinearFactor::shared_ptr(new This(*this)));
142  }
143 
145  virtual void print(const std::string& s = "",
146  const KeyFormatter& keyFormatter = DefaultKeyFormatter) const {
147  Base::print(s);
148  std::cout << " EssentialMatrixFactor2 with measurements\n ("
149  << dP1_.vector().transpose() << ")' and (" << pn_.vector().transpose()
150  << ")'" << std::endl;
151  }
152 
153  /*
154  * Vector of errors returns 2D vector
155  * @param E essential matrix
156  * @param d inverse depth d
157  */
158  Vector evaluateError(const EssentialMatrix& E, const LieScalar& d,
159  boost::optional<Matrix&> DE = boost::none, boost::optional<Matrix&> Dd =
160  boost::none) const {
161 
162  // We have point x,y in image 1
163  // Given a depth Z, the corresponding 3D point P1 = Z*(x,y,1) = (x,y,1)/d
164  // We then convert to second camera by P2 = 1R2'*(P1-1T2)
165  // The homogeneous coordinates of can be written as
166  // 2R1*(P1-1T2) == 2R1*d*(P1-1T2) == 2R1*((x,y,1)-d*1T2)
167  // where we multiplied with d which yields equivalent homogeneous coordinates.
168  // Note that this is just the homography 2R1 for d==0
169  // The point d*P1 = (x,y,1) is computed in constructor as dP1_
170 
171  // Project to normalized image coordinates, then uncalibrate
172  Point2 pn;
173  if (!DE && !Dd) {
174 
175  Point3 _1T2 = E.direction().point3();
176  Point3 d1T2 = d * _1T2;
177  Point3 dP2 = E.rotation().unrotate(dP1_ - d1T2); // 2R1*((x,y,1)-d*1T2)
179 
180  } else {
181 
182  // Calculate derivatives. TODO if slow: optimize with Mathematica
183  // 3*2 3*3 3*3 2*3
184  Matrix D_1T2_dir, DdP2_rot, DP2_point, Dpn_dP2;
185 
186  Point3 _1T2 = E.direction().point3(D_1T2_dir);
187  Point3 d1T2 = d * _1T2;
188  Point3 dP2 = E.rotation().unrotate(dP1_ - d1T2, DdP2_rot, DP2_point);
189  pn = SimpleCamera::project_to_camera(dP2, Dpn_dP2);
190 
191  if (DE) {
192  Matrix DdP2_E(3, 5);
193  DdP2_E << DdP2_rot, -DP2_point * d * D_1T2_dir; // (3*3), (3*3) * (3*2)
194  *DE = f_ * Dpn_dP2 * DdP2_E; // (2*3) * (3*5)
195  }
196 
197  if (Dd) // efficient backwards computation:
198  // (2*3) * (3*3) * (3*1)
199  *Dd = -f_ * (Dpn_dP2 * (DP2_point * _1T2.vector()));
200 
201  }
202  Point2 reprojectionError = pn - pn_;
203  return f_ * reprojectionError.vector();
204  }
205 
206 };
207 // EssentialMatrixFactor2
208 
215 
218 
219  Rot3 cRb_;
220 
221 public:
222 
232  EssentialMatrixFactor3(Key key1, Key key2, const Point2& pA, const Point2& pB,
233  const Rot3& cRb, const SharedNoiseModel& model) :
234  EssentialMatrixFactor2(key1, key2, pA, pB, model), cRb_(cRb) {
235  }
236 
246  template<class CALIBRATION>
247  EssentialMatrixFactor3(Key key1, Key key2, const Point2& pA, const Point2& pB,
248  const Rot3& cRb, const SharedNoiseModel& model, boost::shared_ptr<CALIBRATION> K) :
249  EssentialMatrixFactor2(key1, key2, pA, pB, model, K), cRb_(cRb) {
250  }
251 
253  virtual gtsam::NonlinearFactor::shared_ptr clone() const {
254  return boost::static_pointer_cast<gtsam::NonlinearFactor>(
255  gtsam::NonlinearFactor::shared_ptr(new This(*this)));
256  }
257 
259  virtual void print(const std::string& s = "",
260  const KeyFormatter& keyFormatter = DefaultKeyFormatter) const {
261  Base::print(s);
262  std::cout << " EssentialMatrixFactor3 with rotation " << cRb_ << std::endl;
263  }
264 
265  /*
266  * Vector of errors returns 2D vector
267  * @param E essential matrix
268  * @param d inverse depth d
269  */
270  Vector evaluateError(const EssentialMatrix& E, const LieScalar& d,
271  boost::optional<Matrix&> DE = boost::none, boost::optional<Matrix&> Dd =
272  boost::none) const {
273  if (!DE) {
274  // Convert E from body to camera frame
275  EssentialMatrix cameraE = cRb_ * E;
276  // Evaluate error
277  return Base::evaluateError(cameraE, d, boost::none, Dd);
278  } else {
279  // Version with derivatives
280  Matrix D_e_cameraE, D_cameraE_E; // 2*5, 5*5
281  EssentialMatrix cameraE = E.rotate(cRb_, D_cameraE_E);
282  Vector e = Base::evaluateError(cameraE, d, D_e_cameraE, Dd);
283  *DE = D_e_cameraE * D_cameraE_E; // (2*5) * (5*5)
284  return e;
285  }
286  }
287 
288 };
289 // EssentialMatrixFactor3
290 
291 }// gtsam
292 
EssentialMatrixFactor(Key key, const Point2 &pA, const Point2 &pB, const SharedNoiseModel &model, boost::shared_ptr< CALIBRATION > K)
Constructor.
Definition: EssentialMatrixFactor.h:53
Non-linear factor base classes.
Vector evaluateError(const EssentialMatrix &E, boost::optional< Matrix & > H=boost::none) const
vector of errors returns 1D vector
Definition: EssentialMatrixFactor.h:77
virtual void print(const std::string &s="", const KeyFormatter &keyFormatter=DefaultKeyFormatter) const
print
Definition: EssentialMatrixFactor.h:259
A wrapper around scalar providing Lie compatibility.
const Point3 & point3(boost::optional< Matrix & > H=boost::none) const
Return unit-norm Point3.
Definition: Unit3.h:96
EssentialMatrixFactor3(Key key1, Key key2, const Point2 &pA, const Point2 &pB, const Rot3 &cRb, const SharedNoiseModel &model)
Constructor.
Definition: EssentialMatrixFactor.h:232
virtual void print(const std::string &s="", const KeyFormatter &keyFormatter=DefaultKeyFormatter) const
print
Definition: EssentialMatrixFactor.h:68
LieScalar is a wrapper around double to allow it to be a Lie type.
Definition: LieScalar.h:29
EssentialMatrix rotate(const Rot3 &cRb, boost::optional< Matrix & > HE=boost::none, boost::optional< Matrix & > HR=boost::none) const
Given essential matrix E in camera frame B, convert to body frame C.
Definition: EssentialMatrix.cpp:80
EssentialMatrixFactor3(Key key1, Key key2, const Point2 &pA, const Point2 &pB, const Rot3 &cRb, const SharedNoiseModel &model, boost::shared_ptr< CALIBRATION > K)
Constructor.
Definition: EssentialMatrixFactor.h:247
Point3 unrotate(const Point3 &p, boost::optional< Matrix & > H1=boost::none, boost::optional< Matrix & > H2=boost::none) const
rotate point from world to rotated frame
Definition: Rot3.cpp:102
EssentialMatrixFactor(Key key, const Point2 &pA, const Point2 &pB, const SharedNoiseModel &model)
Constructor.
Definition: EssentialMatrixFactor.h:37
Vector evaluateError(const EssentialMatrix &E, const LieScalar &d, boost::optional< Matrix & > DE=boost::none, boost::optional< Matrix & > Dd=boost::none) const
Override this method to finish implementing a binary factor.
Definition: EssentialMatrixFactor.h:270
virtual gtsam::NonlinearFactor::shared_ptr clone() const
Definition: EssentialMatrixFactor.h:139
Definition: Point2.h:35
Binary factor that optimizes for E and inverse depth d: assumes measurement in image 2 is perfect...
Definition: EssentialMatrixFactor.h:90
virtual gtsam::NonlinearFactor::shared_ptr clone() const
Definition: EssentialMatrixFactor.h:253
Vector evaluateError(const EssentialMatrix &E, const LieScalar &d, boost::optional< Matrix & > DE=boost::none, boost::optional< Matrix & > Dd=boost::none) const
Override this method to finish implementing a binary factor.
Definition: EssentialMatrixFactor.h:158
Vector3 vector() const
return vectorized form (column-wise)
Definition: Point3.h:196
A convenient base class for creating your own NoiseModelFactor with 2 variables.
Definition: NonlinearFactor.h:423
This is the base class for all factor types.
Definition: Factor.h:51
static Vector Homogeneous(const Point2 &p)
Static function to convert Point2 to homogeneous coordinates.
Definition: EssentialMatrix.h:34
Vector2 vector() const
return vectorized form (column-wise). TODO: why does this function exist?
Definition: Point2.h:216
EssentialMatrixFactor2(Key key1, Key key2, const Point2 &pA, const Point2 &pB, const SharedNoiseModel &model, boost::shared_ptr< CALIBRATION > K)
Constructor.
Definition: EssentialMatrixFactor.h:128
static Point2 project_to_camera(const Point3 &P, boost::optional< Matrix & > Dpoint=boost::none)
projects a 3-dimensional point in camera coordinates into the camera and returns a 2-dimensional poin...
Definition: PinholeCamera.h:272
virtual gtsam::NonlinearFactor::shared_ptr clone() const
Definition: EssentialMatrixFactor.h:62
EssentialMatrixFactor2(Key key1, Key key2, const Point2 &pA, const Point2 &pB, const SharedNoiseModel &model)
Constructor.
Definition: EssentialMatrixFactor.h:110
Factor that evaluates epipolar error p'Ep for given essential matrix.
Definition: EssentialMatrixFactor.h:21
An essential matrix is like a Pose3, except with translation up to scale It is named after the 3*3 ma...
Definition: EssentialMatrix.h:23
Key key1() const
methods to retrieve both keys
Definition: NonlinearFactor.h:455
Definition: Rot3.h:61
size_t Key
Integer nonlinear key type.
Definition: types.h:59
double y() const
get y
Definition: Point2.h:213
A convenient base class for creating your own NoiseModelFactor with 1 variable.
Definition: NonlinearFactor.h:354
const Unit3 & direction() const
Direction.
Definition: EssentialMatrix.h:106
double x() const
get x
Definition: Point2.h:210
virtual double error(const Values &c) const
Calculate the error of the factor.
Definition: NonlinearFactor.h:281
double error(const Vector &vA, const Vector &vB, boost::optional< Matrix & > H=boost::none) const
epipolar error, algebraic
Definition: EssentialMatrix.cpp:113
A simple camera class with a Cal3_S2 calibration.
virtual void print(const std::string &s="", const KeyFormatter &keyFormatter=DefaultKeyFormatter) const
Print.
Definition: NonlinearFactor.h:231
noiseModel::Base::shared_ptr SharedNoiseModel
Note, deliberately not in noiseModel namespace.
Definition: NoiseModel.h:884
const Rot3 & rotation() const
Rotation.
Definition: EssentialMatrix.h:101
Nonlinear factor base class.
Definition: NonlinearFactor.h:54
Definition: Point3.h:39
virtual void print(const std::string &s="", const KeyFormatter &keyFormatter=DefaultKeyFormatter) const
print
Definition: EssentialMatrixFactor.h:145
Binary factor that optimizes for E and inverse depth d: assumes measurement in image 2 is perfect...
Definition: EssentialMatrixFactor.h:214
boost::function< std::string(Key)> KeyFormatter
Typedef for a function to format a key, i.e. to convert it to a string.
Definition: types.h:62