22 #include "JacobianFactorQ.h"
23 #include "JacobianFactorSVD.h"
30 #include <gtsam/inference/Symbol.h>
33 #include <boost/optional.hpp>
34 #include <boost/make_shared.hpp>
39 template<
class POSE,
class CALIBRATION,
size_t D>
45 std::vector<SharedNoiseModel>
noise_;
52 typedef Eigen::Matrix<double, D, 2> MatrixD2;
53 typedef std::pair<Key, Matrix2D> KeyMatrix2D;
54 typedef Eigen::Matrix<double, D, D> MatrixDD;
55 typedef Eigen::Matrix<double, 2, 3> Matrix23;
56 typedef Eigen::Matrix<double, D, 1> VectorD;
57 typedef Eigen::Matrix<double, 2, 2> Matrix2;
72 typedef std::vector<Camera> Cameras;
95 this->
keys_.push_back(poseKey_i);
96 this->
noise_.push_back(noise_i);
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));
116 void add(std::vector<Point2>& measurements, std::vector<Key>& poseKeys,
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);
131 for (
size_t k = 0; k < trackToAdd.number_measurements(); k++) {
134 this->
noise_.push_back(noise);
144 const std::vector<SharedNoiseModel>&
noise()
const {
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 = ");
167 const This *e =
dynamic_cast<const This*
>(&p);
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;
175 return e &&
Base::equals(p, tol) && areMeasurementsEqual
185 Vector b =
zero(2 * cameras.size());
188 BOOST_FOREACH(
const Camera& camera, cameras) {
193 b[2 * i + 1] = e.y();
195 std::cout <<
"Cheirality exception " << std::endl;
213 const Point3& point)
const {
215 double overallError = 0;
218 BOOST_FOREACH(
const Camera& camera, cameras) {
225 std::cout <<
"Cheirality exception " << std::endl;
235 void computeEP(Matrix& E, Matrix& PointCov,
const Cameras& cameras,
236 const Point3& point)
const {
238 int numKeys = this->
keys_.size();
239 E =
zeros(2 * numKeys, 3);
240 Vector b =
zero(2 * numKeys);
243 for (
size_t i = 0; i < this->
measured_.size(); i++) {
245 cameras[i].project(point, boost::none, Ei);
247 std::cout <<
"Cheirality exception " << std::endl;
250 this->
noise_.at(i)->WhitenSystem(Ei, b);
251 E.block<2, 3>(2 * i, 0) = Ei;
255 PointCov.noalias() = (E.transpose() * E).
inverse();
262 Vector& b,
const Cameras& cameras,
const Point3& point)
const {
264 size_t numKeys = this->
keys_.size();
265 E =
zeros(2 * numKeys, 3);
266 b =
zero(2 * numKeys);
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++) {
275 -(cameras[i].project(point, Fi, Ei, Hcali) - this->
measured_.at(i)).vector();
277 std::cout <<
"Cheirality exception " << std::endl;
280 this->
noise_.at(i)->WhitenSystem(Fi, Ei, Hcali, bi);
282 f += bi.squaredNorm();
284 Fblocks.push_back(KeyMatrix2D(this->
keys_[i], Fi));
286 Hcam.block<2, 6>(0, 0) = Fi;
287 Hcam.block<2, D - 6>(0, 6) = Hcali;
288 Fblocks.push_back(KeyMatrix2D(this->
keys_[i], Hcam));
290 E.block<2, 3>(2 * i, 0) = Ei;
299 Matrix3& PointCov, Vector& b,
const Cameras& cameras,
const Point3& point,
300 double lambda = 0.0,
bool diagonalDamping =
false)
const {
305 Matrix3 EtE = E.transpose() * E;
307 if (diagonalDamping) {
308 EtE(0, 0) += lambda * EtE(0, 0);
309 EtE(1, 1) += lambda * EtE(1, 1);
310 EtE(2, 2) += lambda * EtE(2, 2);
317 PointCov.noalias() = (EtE).
inverse();
325 const Cameras& cameras,
const Point3& point,
326 const double lambda = 0.0)
const {
328 size_t numKeys = this->
keys_.size();
329 std::vector<KeyMatrix2D> Fblocks;
332 F =
zeros(2 * numKeys, D * numKeys);
334 for (
size_t i = 0; i < this->
keys_.size(); ++i) {
335 F.block<2, D>(2 * i, D * i) = Fblocks.at(i).second;
343 Vector& b,
const Cameras& cameras,
const Point3& point,
double lambda =
344 0.0,
bool diagonalDamping =
false)
const {
348 double f =
computeJacobians(Fblocks, E, PointCov, b, cameras, point, lambda,
352 Eigen::JacobiSVD<Matrix>
svd(E, Eigen::ComputeFullU);
353 Vector s = svd.singularValues();
355 size_t numKeys = this->
keys_.size();
356 Enull = svd.matrixU().block(0, 3, 2 * numKeys, 2 * numKeys - 3);
365 const Cameras& cameras,
const Point3& point)
const {
367 int numKeys = this->
keys_.size();
368 std::vector<KeyMatrix2D> Fblocks;
370 F.resize(2 * numKeys, D * numKeys);
373 for (
size_t i = 0; i < this->
keys_.size(); ++i)
374 F.block<2, D>(2 * i, D * i) = Fblocks.at(i).second;
382 const Cameras& cameras,
const Point3& point,
const double lambda = 0.0,
383 bool diagonalDamping =
false)
const {
385 int numKeys = this->
keys_.size();
387 std::vector<KeyMatrix2D> Fblocks;
391 double f =
computeJacobians(Fblocks, E, PointCov, b, cameras, point, lambda,
395 #ifdef HESSIAN_BLOCKS
397 std::vector < Matrix > Gs(numKeys * (numKeys + 1) / 2);
398 std::vector < Vector > gs(numKeys);
400 sparseSchurComplement(Fblocks, E, PointCov, b, Gs, gs);
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);
411 std::fill(dims.begin(), dims.end() - 1, D);
415 sparseSchurComplement(Fblocks, E, PointCov, b, augmentedHessian);
416 augmentedHessian(numKeys, numKeys)(0, 0) = f;
417 return boost::make_shared<RegularHessianFactor<D> >(this->
keys_,
425 const Matrix& PointCov,
const Vector& b,
426 std::vector<Matrix>& Gs, std::vector<Vector>& gs)
const {
432 int numKeys = this->
keys_.size();
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;
439 Matrix H(D * numKeys, D * numKeys);
442 H.noalias() = F.transpose() * (F - (E * (PointCov * (E.transpose() * F))));
443 gs_vector.noalias() = F.transpose()
444 * (b - (E * (PointCov * (E.transpose() * b))));
450 gs.at(i1) = gs_vector.segment<D>(i1D);
453 Gs.at(GsCount2) = H.block<D, D>(i1D, i2 * D);
461 void sparseSchurComplement(
const std::vector<KeyMatrix2D>& Fblocks,
462 const Matrix& E,
const Matrix& P ,
const Vector& b,
469 size_t numKeys = this->
keys_.size();
472 for (
size_t i1 = 0; i1 < numKeys; i1++) {
474 const Matrix2D& Fi1 = Fblocks.at(i1).second;
475 const Matrix23 Ei1_P = E.block<2, 3>(2 * i1, 0) * P;
479 augmentedHessian(i1, numKeys) = Fi1.transpose() * b.segment<2>(2 * i1)
480 - Fi1.transpose() * (Ei1_P * (E.transpose() * b));
483 augmentedHessian(i1, i1) = Fi1.transpose()
484 * (Fi1 - Ei1_P * E.block<2, 3>(2 * i1, 0).transpose() * Fi1);
487 for (
size_t i2 = i1 + 1; i2 < numKeys; i2++) {
488 const Matrix2D& Fi2 = Fblocks.at(i2).second;
491 augmentedHessian(i1, i2) = -Fi1.transpose()
492 * (Ei1_P * E.block<2, 3>(2 * i2, 0).transpose() * Fi2);
498 void sparseSchurComplement(
const std::vector<KeyMatrix2D>& Fblocks,
499 const Matrix& E,
const Matrix& P ,
const Vector& b,
500 std::vector<Matrix>& Gs, std::vector<Vector>& gs)
const {
506 size_t numKeys = this->
keys_.size();
510 for (
size_t i1 = 0; i1 < numKeys; i1++) {
517 const Matrix2D& Fi1 = Fblocks.at(i1).second;
519 const Matrix23 Ei1_P = E.block<2, 3>(2 * i1, 0) * P;
523 gs.at(i1) = Fi1.transpose() * b.segment<2>(2 * i1)
524 -Fi1.transpose() * (Ei1_P * (E.transpose() * b));
527 Gs.at(GsIndex) = Fi1.transpose()
528 * (Fi1 - Ei1_P * E.block<2, 3>(2 * i1, 0).transpose() * Fi1);
532 for (
size_t i2 = i1 + 1; i2 < numKeys; i2++) {
533 const Matrix2D& Fi2 = Fblocks.at(i2).second;
536 Gs.at(GsIndex) = -Fi1.transpose()
537 * (Ei1_P * E.block<2, 3>(2 * i2, 0).transpose() * Fi2);
544 void updateAugmentedHessian(
const Cameras& cameras,
const Point3& point,
545 const double lambda,
bool diagonalDamping,
546 SymmetricBlockMatrix& augmentedHessian,
547 const FastVector<Key> allKeys)
const {
551 std::vector<KeyMatrix2D> Fblocks;
555 double f =
computeJacobians(Fblocks, E, PointCov, b, cameras, point, lambda,
563 const Matrix& E,
const Matrix& P ,
const Vector& b,
570 MatrixDD matrixBlock;
574 for (
size_t slot=0; slot < allKeys.size(); slot++)
575 KeySlotMap.insert(std::make_pair(allKeys[slot],slot));
578 size_t numKeys = this->
keys_.size();
579 size_t aug_numKeys = (augmentedHessian.
rows() - 1) / D;
582 for (
size_t i1 = 0; i1 < numKeys; i1++) {
584 const Matrix2D& Fi1 = Fblocks.at(i1).second;
585 const Matrix23 Ei1_P = E.block<2, 3>(2 * i1, 0) * P;
596 augmentedHessian(aug_i1, aug_numKeys) = augmentedHessian(aug_i1, aug_numKeys).knownOffDiagonal()
597 + Fi1.transpose() * b.segment<2>(2 * i1)
598 - Fi1.transpose() * (Ei1_P * (E.transpose() * b));
602 matrixBlock = augmentedHessian(aug_i1, aug_i1);
604 augmentedHessian(aug_i1, aug_i1) = matrixBlock +
605 ( Fi1.transpose() * (Fi1 - Ei1_P * E.block<2, 3>(2 * i1, 0).transpose() * Fi1) );
608 for (
size_t i2 = i1 + 1; i2 < numKeys; i2++) {
609 const Matrix2D& Fi2 = Fblocks.at(i2).second;
612 DenseIndex aug_i2 = KeySlotMap[this->keys_[i2]];
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);
623 augmentedHessian(aug_numKeys, aug_numKeys)(0, 0) += f;
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(
633 cameras, point, lambda, diagonalDamping);
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;
648 return boost::make_shared<JacobianFactorQ<D> >(Fblocks, E, PointCov, b);
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;
657 Matrix Enull(2*numKeys, 2*numKeys-3);
659 return boost::make_shared< JacobianFactorSVD<6> >(Fblocks, Enull, b);
666 template<
class ARCHIVE>
667 void serialize(ARCHIVE & ar,
const unsigned int version) {
668 ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(
Base);
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
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
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
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