|
| 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 | + |
| 12 | +/** |
| 13 | + * @file EssentialMatrixWithCalibrationFactor.h |
| 14 | + * |
| 15 | + * @brief A factor evaluating algebraic epipolar error with essential matrix and calibration as variables. |
| 16 | + * |
| 17 | + * @author Ayush Baid |
| 18 | + * @author Akshay Krishnan |
| 19 | + * @date April 23, 2021 |
| 20 | + */ |
| 21 | + |
| 22 | +#pragma once |
| 23 | + |
| 24 | +#include <gtsam/nonlinear/NonlinearFactor.h> |
| 25 | +#include <gtsam/geometry/EssentialMatrix.h> |
| 26 | +#include <iostream> |
| 27 | + |
| 28 | +namespace gtsam { |
| 29 | + |
| 30 | +/** |
| 31 | + * Factor that evaluates algebraic epipolar error (K^-1 p)'E (K^-1 p) for given essential matrix and calibration shared |
| 32 | + * between two images. |
| 33 | + */ |
| 34 | +template<class CALIBRATION> |
| 35 | +class EssentialMatrixWithCalibrationFactor: public NoiseModelFactor2<EssentialMatrix, CALIBRATION > { |
| 36 | + |
| 37 | + Point2 pA_, pB_; ///< points in pixel coordinates |
| 38 | + |
| 39 | + typedef NoiseModelFactor2<EssentialMatrix, CALIBRATION> Base; |
| 40 | + typedef EssentialMatrixWithCalibrationFactor This; |
| 41 | + |
| 42 | +public: |
| 43 | + |
| 44 | + /** |
| 45 | + * Constructor |
| 46 | + * @param essentialMatrixKey Essential Matrix variable key |
| 47 | + * @param calibrationKey Calibration variable key |
| 48 | + * @param pA point in first camera, in pixel coordinates |
| 49 | + * @param pB point in second camera, in pixel coordinates |
| 50 | + * @param model noise model is about dot product in ideal, homogeneous coordinates |
| 51 | + */ |
| 52 | + EssentialMatrixWithCalibrationFactor(Key essentialMatrixKey, Key calibrationKey, const Point2& pA, const Point2& pB, |
| 53 | + const SharedNoiseModel& model) : |
| 54 | + Base(model, essentialMatrixKey, calibrationKey), pA_(pA), pB_(pB) {} |
| 55 | + |
| 56 | + |
| 57 | + /// @return a deep copy of this factor |
| 58 | + gtsam::NonlinearFactor::shared_ptr clone() const override { |
| 59 | + return boost::static_pointer_cast<gtsam::NonlinearFactor>( |
| 60 | + gtsam::NonlinearFactor::shared_ptr(new This(*this))); |
| 61 | + } |
| 62 | + |
| 63 | + /// print |
| 64 | + void print(const std::string& s = "", |
| 65 | + const KeyFormatter& keyFormatter = DefaultKeyFormatter) const override { |
| 66 | + Base::print(s); |
| 67 | + std::cout << " EssentialMatrixWithCalibrationFactor with measurements\n (" |
| 68 | + << pA_.transpose() << ")' and (" << pB_.transpose() << ")'" |
| 69 | + << std::endl; |
| 70 | + } |
| 71 | + |
| 72 | + /// vector of errors returns 1D vector |
| 73 | + /** |
| 74 | + * @brief Calculate the algebraic epipolar error p' (K^-1)' E K p. |
| 75 | + * |
| 76 | + * @param E essential matrix for key essentialMatrixKey |
| 77 | + * @param K calibration (common for both images) for key calibrationKey |
| 78 | + * @param H1 optional jacobian in E |
| 79 | + * @param H2 optional jacobian in K |
| 80 | + * @return * Vector |
| 81 | + */ |
| 82 | + Vector evaluateError(const EssentialMatrix& E, const CALIBRATION& K, |
| 83 | + boost::optional<Matrix&> H1 = boost::none, boost::optional<Matrix&> H2 = boost::none) const override { |
| 84 | + Vector error(1); |
| 85 | + // converting from pixel coordinates to normalized coordinates cA and cB |
| 86 | + Matrix cA_H_K; // dcA/dK |
| 87 | + Matrix cB_H_K; // dcB/dK |
| 88 | + Point2 cA = K.calibrate(pA_, cA_H_K); |
| 89 | + Point2 cB = K.calibrate(pB_, cB_H_K); |
| 90 | + |
| 91 | + // Homogeneous the coordinates |
| 92 | + Vector3 vA = EssentialMatrix::Homogeneous(cA); |
| 93 | + Vector3 vB = EssentialMatrix::Homogeneous(cB); |
| 94 | + |
| 95 | + if (H2){ |
| 96 | + // compute the jacobian of error w.r.t K |
| 97 | + |
| 98 | + // dvX / dcX [3x2] = [1, 0], [0, 1], [0, 0] |
| 99 | + Matrix v_H_c = (Matrix(3, 2) << 1.0, 0.0, 0.0, 1.0, 0.0, 0.0).finished(); // [3x2] |
| 100 | + |
| 101 | + // computing dvA/dK = dvA/dcA * dcA/dK and dVB/dK = dvB/dcB * dcB/dK |
| 102 | + Matrix vA_H_K = v_H_c * cA_H_K; |
| 103 | + Matrix vB_H_K = v_H_c * cB_H_K; |
| 104 | + |
| 105 | + // error function f = vB.T * E * vA |
| 106 | + // H2 = df/dK = vB.T * E.T * dvA/dK + vA.T * E * dvB/dK |
| 107 | + *H2 = vB.transpose() * E.matrix().transpose() * vA_H_K + vA.transpose() * E.matrix() * vB_H_K; |
| 108 | + } |
| 109 | + |
| 110 | + error << E.error(vA, vB, H1); |
| 111 | + |
| 112 | + return error; |
| 113 | + } |
| 114 | + |
| 115 | +public: |
| 116 | + GTSAM_MAKE_ALIGNED_OPERATOR_NEW |
| 117 | +}; |
| 118 | + |
| 119 | +}// gtsam |
0 commit comments