gtsam  3.2.1
gtsam
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SmartFactorBase.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 #pragma once
21 
22 #include "JacobianFactorQ.h"
23 #include "JacobianFactorSVD.h"
24 #include "ImplicitSchurFactor.h"
25 #include "RegularHessianFactor.h"
26 
29 #include <gtsam/geometry/Pose3.h>
30 #include <gtsam/inference/Symbol.h>
31 #include <gtsam/slam/dataset.h>
32 
33 #include <boost/optional.hpp>
34 #include <boost/make_shared.hpp>
35 #include <vector>
36 
37 namespace gtsam {
39 template<class POSE, class CALIBRATION, size_t D>
41 protected:
42 
43  // Keep a copy of measurement and calibration for I/O
44  std::vector<Point2> measured_;
45  std::vector<SharedNoiseModel> noise_;
46 
48  boost::optional<POSE> body_P_sensor_;
49 
51  typedef Eigen::Matrix<double, 2, D> Matrix2D; // F
52  typedef Eigen::Matrix<double, D, 2> MatrixD2; // F'
53  typedef std::pair<Key, Matrix2D> KeyMatrix2D; // Fblocks
54  typedef Eigen::Matrix<double, D, D> MatrixDD; // camera hessian block
55  typedef Eigen::Matrix<double, 2, 3> Matrix23;
56  typedef Eigen::Matrix<double, D, 1> VectorD;
57  typedef Eigen::Matrix<double, 2, 2> Matrix2;
58 
61 
64 
65 public:
66 
68  typedef boost::shared_ptr<This> shared_ptr;
69 
72  typedef std::vector<Camera> Cameras;
73 
78  SmartFactorBase(boost::optional<POSE> body_P_sensor = boost::none) :
79  body_P_sensor_(body_P_sensor) {
80  }
81 
83  virtual ~SmartFactorBase() {
84  }
85 
92  void add(const Point2& measured_i, const Key& poseKey_i,
93  const SharedNoiseModel& noise_i) {
94  this->measured_.push_back(measured_i);
95  this->keys_.push_back(poseKey_i);
96  this->noise_.push_back(noise_i);
97  }
98 
102  // ****************************************************************************************************
103  void add(std::vector<Point2>& measurements, std::vector<Key>& poseKeys,
104  std::vector<SharedNoiseModel>& noises) {
105  for (size_t i = 0; i < measurements.size(); i++) {
106  this->measured_.push_back(measurements.at(i));
107  this->keys_.push_back(poseKeys.at(i));
108  this->noise_.push_back(noises.at(i));
109  }
110  }
111 
115  // ****************************************************************************************************
116  void add(std::vector<Point2>& measurements, std::vector<Key>& poseKeys,
117  const SharedNoiseModel& noise) {
118  for (size_t i = 0; i < measurements.size(); i++) {
119  this->measured_.push_back(measurements.at(i));
120  this->keys_.push_back(poseKeys.at(i));
121  this->noise_.push_back(noise);
122  }
123  }
124 
129  // ****************************************************************************************************
130  void add(const SfM_Track& trackToAdd, const SharedNoiseModel& noise) {
131  for (size_t k = 0; k < trackToAdd.number_measurements(); k++) {
132  this->measured_.push_back(trackToAdd.measurements[k].second);
133  this->keys_.push_back(trackToAdd.measurements[k].first);
134  this->noise_.push_back(noise);
135  }
136  }
137 
139  const std::vector<Point2>& measured() const {
140  return measured_;
141  }
142 
144  const std::vector<SharedNoiseModel>& noise() const {
145  return noise_;
146  }
147 
153  void print(const std::string& s = "", const KeyFormatter& keyFormatter =
154  DefaultKeyFormatter) const {
155  std::cout << s << "SmartFactorBase, z = \n";
156  for (size_t k = 0; k < measured_.size(); ++k) {
157  std::cout << "measurement, p = " << measured_[k] << "\t";
158  noise_[k]->print("noise model = ");
159  }
160  if (this->body_P_sensor_)
161  this->body_P_sensor_->print(" sensor pose in body frame: ");
162  Base::print("", keyFormatter);
163  }
164 
166  virtual bool equals(const NonlinearFactor& p, double tol = 1e-9) const {
167  const This *e = dynamic_cast<const This*>(&p);
168 
169  bool areMeasurementsEqual = true;
170  for (size_t i = 0; i < measured_.size(); i++) {
171  if (this->measured_.at(i).equals(e->measured_.at(i), tol) == false)
172  areMeasurementsEqual = false;
173  break;
174  }
175  return e && Base::equals(p, tol) && areMeasurementsEqual
176  && ((!body_P_sensor_ && !e->body_P_sensor_)
177  || (body_P_sensor_ && e->body_P_sensor_
178  && body_P_sensor_->equals(*e->body_P_sensor_)));
179  }
180 
181  // ****************************************************************************************************
183  Vector reprojectionError(const Cameras& cameras, const Point3& point) const {
184 
185  Vector b = zero(2 * cameras.size());
186 
187  size_t i = 0;
188  BOOST_FOREACH(const Camera& camera, cameras) {
189  const Point2& zi = this->measured_.at(i);
190  try {
191  Point2 e(camera.project(point) - zi);
192  b[2 * i] = e.x();
193  b[2 * i + 1] = e.y();
194  } catch (CheiralityException& e) {
195  std::cout << "Cheirality exception " << std::endl;
196  exit(EXIT_FAILURE);
197  }
198  i += 1;
199  }
200 
201  return b;
202  }
203 
204  // ****************************************************************************************************
212  double totalReprojectionError(const Cameras& cameras,
213  const Point3& point) const {
214 
215  double overallError = 0;
216 
217  size_t i = 0;
218  BOOST_FOREACH(const Camera& camera, cameras) {
219  const Point2& zi = this->measured_.at(i);
220  try {
221  Point2 reprojectionError(camera.project(point) - zi);
222  overallError += 0.5
223  * this->noise_.at(i)->distance(reprojectionError.vector());
224  } catch (CheiralityException&) {
225  std::cout << "Cheirality exception " << std::endl;
226  exit(EXIT_FAILURE);
227  }
228  i += 1;
229  }
230  return overallError;
231  }
232 
233  // ****************************************************************************************************
235  void computeEP(Matrix& E, Matrix& PointCov, const Cameras& cameras,
236  const Point3& point) const {
237 
238  int numKeys = this->keys_.size();
239  E = zeros(2 * numKeys, 3);
240  Vector b = zero(2 * numKeys);
241 
242  Matrix Ei(2, 3);
243  for (size_t i = 0; i < this->measured_.size(); i++) {
244  try {
245  cameras[i].project(point, boost::none, Ei);
246  } catch (CheiralityException& e) {
247  std::cout << "Cheirality exception " << std::endl;
248  exit(EXIT_FAILURE);
249  }
250  this->noise_.at(i)->WhitenSystem(Ei, b);
251  E.block<2, 3>(2 * i, 0) = Ei;
252  }
253 
254  // Matrix PointCov;
255  PointCov.noalias() = (E.transpose() * E).inverse();
256  }
257 
258  // ****************************************************************************************************
261  double computeJacobians(std::vector<KeyMatrix2D>& Fblocks, Matrix& E,
262  Vector& b, const Cameras& cameras, const Point3& point) const {
263 
264  size_t numKeys = this->keys_.size();
265  E = zeros(2 * numKeys, 3);
266  b = zero(2 * numKeys);
267  double f = 0;
268 
269  Matrix Fi(2, 6), Ei(2, 3), Hcali(2, D - 6), Hcam(2, D);
270  for (size_t i = 0; i < this->measured_.size(); i++) {
271 
272  Vector bi;
273  try {
274  bi =
275  -(cameras[i].project(point, Fi, Ei, Hcali) - this->measured_.at(i)).vector();
276  } catch (CheiralityException&) {
277  std::cout << "Cheirality exception " << std::endl;
278  exit(EXIT_FAILURE);
279  }
280  this->noise_.at(i)->WhitenSystem(Fi, Ei, Hcali, bi);
281 
282  f += bi.squaredNorm();
283  if (D == 6) { // optimize only camera pose
284  Fblocks.push_back(KeyMatrix2D(this->keys_[i], Fi));
285  } else {
286  Hcam.block<2, 6>(0, 0) = Fi; // 2 x 6 block for the cameras
287  Hcam.block<2, D - 6>(0, 6) = Hcali; // 2 x nrCal block for the cameras
288  Fblocks.push_back(KeyMatrix2D(this->keys_[i], Hcam));
289  }
290  E.block<2, 3>(2 * i, 0) = Ei;
291  subInsert(b, bi, 2 * i);
292  }
293  return f;
294  }
295 
296  // ****************************************************************************************************
298  double computeJacobians(std::vector<KeyMatrix2D>& Fblocks, Matrix& E,
299  Matrix3& PointCov, Vector& b, const Cameras& cameras, const Point3& point,
300  double lambda = 0.0, bool diagonalDamping = false) const {
301 
302  double f = computeJacobians(Fblocks, E, b, cameras, point);
303 
304  // Point covariance inv(E'*E)
305  Matrix3 EtE = E.transpose() * E;
306 
307  if (diagonalDamping) { // diagonal of the hessian
308  EtE(0, 0) += lambda * EtE(0, 0);
309  EtE(1, 1) += lambda * EtE(1, 1);
310  EtE(2, 2) += lambda * EtE(2, 2);
311  }else{
312  EtE(0, 0) += lambda;
313  EtE(1, 1) += lambda;
314  EtE(2, 2) += lambda;
315  }
316 
317  PointCov.noalias() = (EtE).inverse();
318 
319  return f;
320  }
321 
322  // ****************************************************************************************************
323  // TODO, there should not be a Matrix version, really
324  double computeJacobians(Matrix& F, Matrix& E, Matrix3& PointCov, Vector& b,
325  const Cameras& cameras, const Point3& point,
326  const double lambda = 0.0) const {
327 
328  size_t numKeys = this->keys_.size();
329  std::vector<KeyMatrix2D> Fblocks;
330  double f = computeJacobians(Fblocks, E, PointCov, b, cameras, point,
331  lambda);
332  F = zeros(2 * numKeys, D * numKeys);
333 
334  for (size_t i = 0; i < this->keys_.size(); ++i) {
335  F.block<2, D>(2 * i, D * i) = Fblocks.at(i).second; // 2 x 6 block for the cameras
336  }
337  return f;
338  }
339 
340  // ****************************************************************************************************
342  double computeJacobiansSVD(std::vector<KeyMatrix2D>& Fblocks, Matrix& Enull,
343  Vector& b, const Cameras& cameras, const Point3& point, double lambda =
344  0.0, bool diagonalDamping = false) const {
345 
346  Matrix E;
347  Matrix3 PointCov; // useless
348  double f = computeJacobians(Fblocks, E, PointCov, b, cameras, point, lambda,
349  diagonalDamping); // diagonalDamping should have no effect (only on PointCov)
350 
351  // Do SVD on A
352  Eigen::JacobiSVD<Matrix> svd(E, Eigen::ComputeFullU);
353  Vector s = svd.singularValues();
354  // Enull = zeros(2 * numKeys, 2 * numKeys - 3);
355  size_t numKeys = this->keys_.size();
356  Enull = svd.matrixU().block(0, 3, 2 * numKeys, 2 * numKeys - 3); // last 2m-3 columns
357 
358  return f;
359  }
360 
361  // ****************************************************************************************************
363  // TODO, there should not be a Matrix version, really
364  double computeJacobiansSVD(Matrix& F, Matrix& Enull, Vector& b,
365  const Cameras& cameras, const Point3& point) const {
366 
367  int numKeys = this->keys_.size();
368  std::vector<KeyMatrix2D> Fblocks;
369  double f = computeJacobiansSVD(Fblocks, Enull, b, cameras, point);
370  F.resize(2 * numKeys, D * numKeys);
371  F.setZero();
372 
373  for (size_t i = 0; i < this->keys_.size(); ++i)
374  F.block<2, D>(2 * i, D * i) = Fblocks.at(i).second; // 2 x 6 block for the cameras
375 
376  return f;
377  }
378 
379  // ****************************************************************************************************
381  boost::shared_ptr<RegularHessianFactor<D> > createHessianFactor(
382  const Cameras& cameras, const Point3& point, const double lambda = 0.0,
383  bool diagonalDamping = false) const {
384 
385  int numKeys = this->keys_.size();
386 
387  std::vector<KeyMatrix2D> Fblocks;
388  Matrix E;
389  Matrix3 PointCov;
390  Vector b;
391  double f = computeJacobians(Fblocks, E, PointCov, b, cameras, point, lambda,
392  diagonalDamping);
393 
394 //#define HESSIAN_BLOCKS // slower, as internally the Hessian factor will transform the blocks into SymmetricBlockMatrix
395 #ifdef HESSIAN_BLOCKS
396  // Create structures for Hessian Factors
397  std::vector < Matrix > Gs(numKeys * (numKeys + 1) / 2);
398  std::vector < Vector > gs(numKeys);
399 
400  sparseSchurComplement(Fblocks, E, PointCov, b, Gs, gs);
401  // schurComplement(Fblocks, E, PointCov, b, Gs, gs);
402 
403  //std::vector < Matrix > Gs2(Gs.begin(), Gs.end());
404  //std::vector < Vector > gs2(gs.begin(), gs.end());
405 
406  return boost::make_shared < RegularHessianFactor<D>
407  > (this->keys_, Gs, gs, f);
408 #else // we create directly a SymmetricBlockMatrix
409  size_t n1 = D * numKeys + 1;
410  std::vector<DenseIndex> dims(numKeys + 1); // this also includes the b term
411  std::fill(dims.begin(), dims.end() - 1, D);
412  dims.back() = 1;
413 
414  SymmetricBlockMatrix augmentedHessian(dims, Matrix::Zero(n1, n1)); // for 10 cameras, size should be (10*D+1 x 10*D+1)
415  sparseSchurComplement(Fblocks, E, PointCov, b, augmentedHessian); // augmentedHessian.matrix().block<D,D> (i1,i2) = ...
416  augmentedHessian(numKeys, numKeys)(0, 0) = f;
417  return boost::make_shared<RegularHessianFactor<D> >(this->keys_,
418  augmentedHessian);
419 #endif
420  }
421 
422  // ****************************************************************************************************
423  // slow version - works on full (sparse) matrices
424  void schurComplement(const std::vector<KeyMatrix2D>& Fblocks, const Matrix& E,
425  const Matrix& PointCov, const Vector& b,
426  /*output ->*/std::vector<Matrix>& Gs, std::vector<Vector>& gs) const {
427  // Schur complement trick
428  // Gs = F' * F - F' * E * inv(E'*E) * E' * F
429  // gs = F' * (b - E * inv(E'*E) * E' * b)
430  // This version uses full matrices
431 
432  int numKeys = this->keys_.size();
433 
435  Matrix F = zeros(2 * numKeys, D * numKeys);
436  for (size_t i = 0; i < this->keys_.size(); ++i)
437  F.block<2, D>(2 * i, D * i) = Fblocks.at(i).second; // 2 x 6 block for the cameras
438 
439  Matrix H(D * numKeys, D * numKeys);
440  Vector gs_vector;
441 
442  H.noalias() = F.transpose() * (F - (E * (PointCov * (E.transpose() * F))));
443  gs_vector.noalias() = F.transpose()
444  * (b - (E * (PointCov * (E.transpose() * b))));
445 
446  // Populate Gs and gs
447  int GsCount2 = 0;
448  for (DenseIndex i1 = 0; i1 < numKeys; i1++) { // for each camera
449  DenseIndex i1D = i1 * D;
450  gs.at(i1) = gs_vector.segment<D>(i1D);
451  for (DenseIndex i2 = 0; i2 < numKeys; i2++) {
452  if (i2 >= i1) {
453  Gs.at(GsCount2) = H.block<D, D>(i1D, i2 * D);
454  GsCount2++;
455  }
456  }
457  }
458  }
459 
460  // ****************************************************************************************************
461  void sparseSchurComplement(const std::vector<KeyMatrix2D>& Fblocks,
462  const Matrix& E, const Matrix& P /*Point Covariance*/, const Vector& b,
463  /*output ->*/SymmetricBlockMatrix& augmentedHessian) const {
464  // Schur complement trick
465  // Gs = F' * F - F' * E * P * E' * F
466  // gs = F' * (b - E * P * E' * b)
467 
468  // a single point is observed in numKeys cameras
469  size_t numKeys = this->keys_.size();
470 
471  // Blockwise Schur complement
472  for (size_t i1 = 0; i1 < numKeys; i1++) { // for each camera
473 
474  const Matrix2D& Fi1 = Fblocks.at(i1).second;
475  const Matrix23 Ei1_P = E.block<2, 3>(2 * i1, 0) * P;
476 
477  // D = (Dx2) * (2)
478  // (augmentedHessian.matrix()).block<D,1> (i1,numKeys+1) = Fi1.transpose() * b.segment < 2 > (2 * i1); // F' * b
479  augmentedHessian(i1, numKeys) = Fi1.transpose() * b.segment<2>(2 * i1) // F' * b
480  - Fi1.transpose() * (Ei1_P * (E.transpose() * b)); // D = (Dx2) * (2x3) * (3*2m) * (2m x 1)
481 
482  // (DxD) = (Dx2) * ( (2xD) - (2x3) * (3x2) * (2xD) )
483  augmentedHessian(i1, i1) = Fi1.transpose()
484  * (Fi1 - Ei1_P * E.block<2, 3>(2 * i1, 0).transpose() * Fi1);
485 
486  // upper triangular part of the hessian
487  for (size_t i2 = i1 + 1; i2 < numKeys; i2++) { // for each camera
488  const Matrix2D& Fi2 = Fblocks.at(i2).second;
489 
490  // (DxD) = (Dx2) * ( (2x2) * (2xD) )
491  augmentedHessian(i1, i2) = -Fi1.transpose()
492  * (Ei1_P * E.block<2, 3>(2 * i2, 0).transpose() * Fi2);
493  }
494  } // end of for over cameras
495  }
496 
497  // ****************************************************************************************************
498  void sparseSchurComplement(const std::vector<KeyMatrix2D>& Fblocks,
499  const Matrix& E, const Matrix& P /*Point Covariance*/, const Vector& b,
500  /*output ->*/std::vector<Matrix>& Gs, std::vector<Vector>& gs) const {
501  // Schur complement trick
502  // Gs = F' * F - F' * E * P * E' * F
503  // gs = F' * (b - E * P * E' * b)
504 
505  // a single point is observed in numKeys cameras
506  size_t numKeys = this->keys_.size();
507 
508  int GsIndex = 0;
509  // Blockwise Schur complement
510  for (size_t i1 = 0; i1 < numKeys; i1++) { // for each camera
511  // GsIndex points to the upper triangular blocks
512  // 0 1 2 3 4
513  // X 5 6 7 8
514  // X X 9 10 11
515  // X X X 12 13
516  // X X X X 14
517  const Matrix2D& Fi1 = Fblocks.at(i1).second;
518 
519  const Matrix23 Ei1_P = E.block<2, 3>(2 * i1, 0) * P;
520 
521  { // for i1 = i2
522  // D = (Dx2) * (2)
523  gs.at(i1) = Fi1.transpose() * b.segment<2>(2 * i1) // F' * b
524  -Fi1.transpose() * (Ei1_P * (E.transpose() * b)); // D = (Dx2) * (2x3) * (3*2m) * (2m x 1)
525 
526  // (DxD) = (Dx2) * ( (2xD) - (2x3) * (3x2) * (2xD) )
527  Gs.at(GsIndex) = Fi1.transpose()
528  * (Fi1 - Ei1_P * E.block<2, 3>(2 * i1, 0).transpose() * Fi1);
529  GsIndex++;
530  }
531  // upper triangular part of the hessian
532  for (size_t i2 = i1 + 1; i2 < numKeys; i2++) { // for each camera
533  const Matrix2D& Fi2 = Fblocks.at(i2).second;
534 
535  // (DxD) = (Dx2) * ( (2x2) * (2xD) )
536  Gs.at(GsIndex) = -Fi1.transpose()
537  * (Ei1_P * E.block<2, 3>(2 * i2, 0).transpose() * Fi2);
538  GsIndex++;
539  }
540  } // end of for over cameras
541  }
542 
543  // ****************************************************************************************************
544  void updateAugmentedHessian(const Cameras& cameras, const Point3& point,
545  const double lambda, bool diagonalDamping,
546  SymmetricBlockMatrix& augmentedHessian,
547  const FastVector<Key> allKeys) const {
548 
549  // int numKeys = this->keys_.size();
550 
551  std::vector<KeyMatrix2D> Fblocks;
552  Matrix E;
553  Matrix3 PointCov;
554  Vector b;
555  double f = computeJacobians(Fblocks, E, PointCov, b, cameras, point, lambda,
556  diagonalDamping);
557 
558  updateSparseSchurComplement(Fblocks, E, PointCov, b, f, allKeys, augmentedHessian); // augmentedHessian.matrix().block<D,D> (i1,i2) = ...
559  }
560 
561  // ****************************************************************************************************
562  void updateSparseSchurComplement(const std::vector<KeyMatrix2D>& Fblocks,
563  const Matrix& E, const Matrix& P /*Point Covariance*/, const Vector& b,
564  const double f, const FastVector<Key> allKeys,
565  /*output ->*/SymmetricBlockMatrix& augmentedHessian) const {
566  // Schur complement trick
567  // Gs = F' * F - F' * E * P * E' * F
568  // gs = F' * (b - E * P * E' * b)
569 
570  MatrixDD matrixBlock;
571  typedef SymmetricBlockMatrix::Block Block;
572 
573  FastMap<Key,size_t> KeySlotMap;
574  for (size_t slot=0; slot < allKeys.size(); slot++)
575  KeySlotMap.insert(std::make_pair(allKeys[slot],slot));
576 
577  // a single point is observed in numKeys cameras
578  size_t numKeys = this->keys_.size(); // cameras observing current point
579  size_t aug_numKeys = (augmentedHessian.rows() - 1) / D; // all cameras in the group
580 
581  // Blockwise Schur complement
582  for (size_t i1 = 0; i1 < numKeys; i1++) { // for each camera in the current factor
583 
584  const Matrix2D& Fi1 = Fblocks.at(i1).second;
585  const Matrix23 Ei1_P = E.block<2, 3>(2 * i1, 0) * P;
586 
587  // D = (Dx2) * (2)
588  // allKeys are the list of all camera keys in the group, e.g, (1,3,4,5,7)
589  // we should map those to a slot in the local (grouped) hessian (0,1,2,3,4)
590  // Key cameraKey_i1 = this->keys_[i1];
591  DenseIndex aug_i1 = KeySlotMap[this->keys_[i1]];
592 
593  // information vector - store previous vector
594  // vectorBlock = augmentedHessian(aug_i1, aug_numKeys).knownOffDiagonal();
595  // add contribution of current factor
596  augmentedHessian(aug_i1, aug_numKeys) = augmentedHessian(aug_i1, aug_numKeys).knownOffDiagonal()
597  + Fi1.transpose() * b.segment<2>(2 * i1) // F' * b
598  - Fi1.transpose() * (Ei1_P * (E.transpose() * b)); // D = (Dx2) * (2x3) * (3*2m) * (2m x 1)
599 
600  // (DxD) = (Dx2) * ( (2xD) - (2x3) * (3x2) * (2xD) )
601  // main block diagonal - store previous block
602  matrixBlock = augmentedHessian(aug_i1, aug_i1);
603  // add contribution of current factor
604  augmentedHessian(aug_i1, aug_i1) = matrixBlock +
605  ( Fi1.transpose() * (Fi1 - Ei1_P * E.block<2, 3>(2 * i1, 0).transpose() * Fi1) );
606 
607  // upper triangular part of the hessian
608  for (size_t i2 = i1 + 1; i2 < numKeys; i2++) { // for each camera
609  const Matrix2D& Fi2 = Fblocks.at(i2).second;
610 
611  //Key cameraKey_i2 = this->keys_[i2];
612  DenseIndex aug_i2 = KeySlotMap[this->keys_[i2]];
613 
614  // (DxD) = (Dx2) * ( (2x2) * (2xD) )
615  // off diagonal block - store previous block
616  // matrixBlock = augmentedHessian(aug_i1, aug_i2).knownOffDiagonal();
617  // add contribution of current factor
618  augmentedHessian(aug_i1, aug_i2) = augmentedHessian(aug_i1, aug_i2).knownOffDiagonal()
619  - Fi1.transpose() * (Ei1_P * E.block<2, 3>(2 * i2, 0).transpose() * Fi2);
620  }
621  } // end of for over cameras
622 
623  augmentedHessian(aug_numKeys, aug_numKeys)(0, 0) += f;
624  }
625 
626  // ****************************************************************************************************
627  boost::shared_ptr<ImplicitSchurFactor<D> > createImplicitSchurFactor(
628  const Cameras& cameras, const Point3& point, double lambda = 0.0,
629  bool diagonalDamping = false) const {
630  typename boost::shared_ptr<ImplicitSchurFactor<D> > f(
631  new ImplicitSchurFactor<D>());
632  computeJacobians(f->Fblocks(), f->E(), f->PointCovariance(), f->b(),
633  cameras, point, lambda, diagonalDamping);
634  f->initKeys();
635  return f;
636  }
637 
638  // ****************************************************************************************************
639  boost::shared_ptr<JacobianFactorQ<D> > createJacobianQFactor(
640  const Cameras& cameras, const Point3& point, double lambda = 0.0,
641  bool diagonalDamping = false) const {
642  std::vector<KeyMatrix2D> Fblocks;
643  Matrix E;
644  Matrix3 PointCov;
645  Vector b;
646  computeJacobians(Fblocks, E, PointCov, b, cameras, point, lambda,
647  diagonalDamping);
648  return boost::make_shared<JacobianFactorQ<D> >(Fblocks, E, PointCov, b);
649  }
650 
651  // ****************************************************************************************************
652  boost::shared_ptr<JacobianFactor> createJacobianSVDFactor(
653  const Cameras& cameras, const Point3& point, double lambda = 0.0) const {
654  size_t numKeys = this->keys_.size();
655  std::vector < KeyMatrix2D > Fblocks;
656  Vector b;
657  Matrix Enull(2*numKeys, 2*numKeys-3);
658  computeJacobiansSVD(Fblocks, Enull, b, cameras, point, lambda);
659  return boost::make_shared< JacobianFactorSVD<6> >(Fblocks, Enull, b);
660  }
661 
662 private:
663 
666  template<class ARCHIVE>
667  void serialize(ARCHIVE & ar, const unsigned int version) {
668  ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Base);
669  ar & BOOST_SERIALIZATION_NVP(measured_);
670  ar & BOOST_SERIALIZATION_NVP(body_P_sensor_);
671  }
672 };
673 
674 } // \ namespace gtsam
Non-linear factor base classes.
double computeJacobiansSVD(Matrix &F, Matrix &Enull, Vector &b, const Cameras &cameras, const Point3 &point) const
Matrix version of SVD.
Definition: SmartFactorBase.h:364
void computeEP(Matrix &E, Matrix &PointCov, const Cameras &cameras, const Point3 &point) const
Assumes non-degenerate !
Definition: SmartFactorBase.h:235
virtual bool equals(const NonlinearFactor &p, double tol=1e-9) const
equals
Definition: SmartFactorBase.h:166
virtual void print(const std::string &s="", const KeyFormatter &keyFormatter=DefaultKeyFormatter) const
print
Definition: NonlinearFactor.h:84
const std::vector< SharedNoiseModel > & noise() const
return the noise model
Definition: SmartFactorBase.h:144
const std::vector< Point2 > & measured() const
return the measurements
Definition: SmartFactorBase.h:139
Matrix inverse(const Matrix &A)
invert A
Definition: Matrix.cpp:289
void add(std::vector< Point2 > &measurements, std::vector< Key > &poseKeys, const SharedNoiseModel &noise)
variant of the previous add: adds a bunch of measurements and uses the same noise model for all of th...
Definition: SmartFactorBase.h:116
double computeJacobiansSVD(std::vector< KeyMatrix2D > &Fblocks, Matrix &Enull, Vector &b, const Cameras &cameras, const Point3 &point, double lambda=0.0, bool diagonalDamping=false) const
SVD version.
Definition: SmartFactorBase.h:342
ImplicitSchurFactor.
Definition: ImplicitSchurFactor.h:23
Definition: Point2.h:35
FastVector< Key > keys_
The keys involved in this factor.
Definition: Factor.h:69
Eigen::Matrix< double, 2, D > Matrix2D
Definitions for blocks of F.
Definition: SmartFactorBase.h:51
Point2 project(const Point3 &pw, boost::optional< Matrix & > Dpose=boost::none, boost::optional< Matrix & > Dpoint=boost::none, boost::optional< Matrix & > Dcal=boost::none) const
project a point from world coordinate to the image
Definition: PinholeCamera.h:299
std::vector< SfM_Measurement > measurements
The 2D image projections (id,(u,v))
Definition: dataset.h:144
void schurComplement(const std::vector< KeyMatrix2D > &Fblocks, const Matrix &E, const Matrix &PointCov, const Vector &b, std::vector< Matrix > &Gs, std::vector< Vector > &gs) const
Definition: SmartFactorBase.h:424
This is the base class for all factor types.
Definition: Factor.h:51
std::vector< Point2 > measured_
2D measurement for each of the m views
Definition: SmartFactorBase.h:44
DenseIndex rows() const
Row size.
Definition: SymmetricBlockMatrix.h:108
Base class for all pinhole cameras.
bool zero(const Vector &v)
check if all zero
Definition: Vector.cpp:39
utility functions for loading datasets
void add(std::vector< Point2 > &measurements, std::vector< Key > &poseKeys, std::vector< SharedNoiseModel > &noises)
variant of the previous add: adds a bunch of measurements, together with the camera keys and noises ...
Definition: SmartFactorBase.h:103
void subInsert(Vector &fullVector, const Vector &subVector, size_t i)
Inserts a subvector into a vector IN PLACE.
Definition: Vector.cpp:180
Definition: PinholeCamera.h:40
Base class with no internal point, completely functional.
Definition: SmartFactorBase.h:40
A matrix expression that references a single block of a SymmetricBlockMatrix.
Definition: SymmetricBlockMatrixBlockExpr.h:22
boost::optional< POSE > body_P_sensor_
The pose of the sensor in the body frame (one for all cameras)
Definition: SmartFactorBase.h:48
HessianFactor class with constant sized blcoks.
boost::shared_ptr< RegularHessianFactor< D > > createHessianFactor(const Cameras &cameras, const Point3 &point, const double lambda=0.0, bool diagonalDamping=false) const
linearize returns a Hessianfactor that is an approximation of error(p)
Definition: SmartFactorBase.h:381
Definition: CalibratedCamera.h:27
NonlinearFactor Base
shorthand for base class type
Definition: SmartFactorBase.h:60
virtual bool equals(const NonlinearFactor &f, double tol=1e-9) const
Check if two factors are equal.
Definition: NonlinearFactor.h:93
SmartFactorBase< POSE, CALIBRATION, D > This
shorthand for this class
Definition: SmartFactorBase.h:63
std::vector< SharedNoiseModel > noise_
noise model used
Definition: SmartFactorBase.h:45
size_t Key
Integer nonlinear key type.
Definition: types.h:59
Define the structure for the 3D points.
Definition: dataset.h:141
ptrdiff_t DenseIndex
The index type for Eigen objects.
Definition: types.h:74
void svd(const Matrix &A, Matrix &U, Vector &S, Matrix &V)
SVD computes economy SVD A=U*S*V'.
Definition: Matrix.cpp:630
boost::shared_ptr< This > shared_ptr
shorthand for a smart pointer to a factor
Definition: SmartFactorBase.h:68
PinholeCamera< CALIBRATION > Camera
shorthand for a pinhole camera
Definition: SmartFactorBase.h:71
void updateSparseSchurComplement(const std::vector< KeyMatrix2D > &Fblocks, const Matrix &E, const Matrix &P, const Vector &b, const double f, const FastVector< Key > allKeys, SymmetricBlockMatrix &augmentedHessian) const
Definition: SmartFactorBase.h:562
3D Pose
friend class boost::serialization::access
Serialization function.
Definition: SmartFactorBase.h:665
double x() const
get x
Definition: Point2.h:210
void print(const std::string &s="", const KeyFormatter &keyFormatter=DefaultKeyFormatter) const
print
Definition: SmartFactorBase.h:153
double computeJacobians(std::vector< KeyMatrix2D > &Fblocks, Matrix &E, Matrix3 &PointCov, Vector &b, const Cameras &cameras, const Point3 &point, double lambda=0.0, bool diagonalDamping=false) const
Version that computes PointCov, with optional lambda parameter.
Definition: SmartFactorBase.h:298
Definition: SymmetricBlockMatrix.h:40
void add(const SfM_Track &trackToAdd, const SharedNoiseModel &noise)
Adds an entire SfM_track (collection of cameras observing a single point).
Definition: SmartFactorBase.h:130
virtual ~SmartFactorBase()
Virtual destructor.
Definition: SmartFactorBase.h:83
A new type of linear factor (GaussianFactor), which is subclass of GaussianFactor.
void add(const Point2 &measured_i, const Key &poseKey_i, const SharedNoiseModel &noise_i)
add a new measurement and pose key
Definition: SmartFactorBase.h:92
double totalReprojectionError(const Cameras &cameras, const Point3 &point) const
Calculate the error of the factor.
Definition: SmartFactorBase.h:212
Vector reprojectionError(const Cameras &cameras, const Point3 &point) const
Calculate vector of re-projection errors, before applying noise model.
Definition: SmartFactorBase.h:183
noiseModel::Base::shared_ptr SharedNoiseModel
Note, deliberately not in noiseModel namespace.
Definition: NoiseModel.h:884
Nonlinear factor base class.
Definition: NonlinearFactor.h:54
double computeJacobians(std::vector< KeyMatrix2D > &Fblocks, Matrix &E, Vector &b, const Cameras &cameras, const Point3 &point) const
Compute F, E only (called below in both vanilla and SVD versions) Given a Point3, assumes dimensional...
Definition: SmartFactorBase.h:261
Definition: Point3.h:39
SmartFactorBase(boost::optional< POSE > body_P_sensor=boost::none)
Constructor.
Definition: SmartFactorBase.h:78
Matrix zeros(size_t m, size_t n)
Creates an zeros matrix, with matlab-like syntax.
Definition: Matrix.cpp:40
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