in IsometricPatternMatcher/CameraModels.h [396:458]
static Eigen::Matrix<typename D::Scalar, 3, 1> unproject(
const Eigen::MatrixBase<D>& uvPixel,
const Eigen::MatrixBase<DP>& params) {
EIGEN_STATIC_ASSERT(D::RowsAtCompileTime == 2 && D::ColsAtCompileTime == 1,
THIS_METHOD_IS_ONLY_FOR_MATRICES_OF_A_SPECIFIC_SIZE);
EIGEN_STATIC_ASSERT(
DP::ColsAtCompileTime == 1 && (DP::RowsAtCompileTime == kNumParams ||
DP::RowsAtCompileTime == Eigen::Dynamic),
THIS_METHOD_IS_ONLY_FOR_MATRICES_OF_A_SPECIFIC_SIZE);
using T = typename D::Scalar;
// Unprojection
const T fu = params[0];
const T fv = params[1];
const T u0 = params[2];
const T v0 = params[3];
const T k0 = params[4];
const T k1 = params[5];
const T k2 = params[6];
const T k3 = params[7];
const T un = (uvPixel(0) - u0) / fu;
const T vn = (uvPixel(1) - v0) / fv;
const T rth2 = un * un + vn * vn;
if (rth2 <
Sophus::Constants<T>::epsilon() * Sophus::Constants<T>::epsilon()) {
return Eigen::Matrix<T, 3, 1>(un, vn, T(1.0));
}
const T rth = sqrt(rth2);
// Use Newtons method to solve for theta, 50 iterations max
T th = initTheta(rth);
for (int i = 0; i < 50; ++i) {
const T th2 = th * th;
const T th4 = th2 * th2;
const T th6 = th4 * th2;
const T th8 = th4 * th4;
const T thd = th * (T(1.0) + k0 * th2 + k1 * th4 + k2 * th6 + k3 * th8);
const T d_thd_wtr_th = T(1.0) + T(3.0) * k0 * th2 + T(5.0) * k1 * th4 +
T(7.0) * k2 * th6 + T(9.0) * k3 * th8;
const T step = (thd - rth) / d_thd_wtr_th;
th -= step;
if (hasConverged(step)) {
break;
}
}
using std::tan;
T radiusUndistorted = tan(th);
if (radiusUndistorted < T(0.0)) {
return Eigen::Matrix<T, 3, 1>(-radiusUndistorted * un / rth,
-radiusUndistorted * vn / rth, T(-1.0));
}
return Eigen::Matrix<T, 3, 1>(radiusUndistorted * un / rth,
radiusUndistorted * vn / rth, T(1.0));
}