16 #include <Eigen/Dense>
28 "KannalaBrandtK3: fx, fy, cx, cy, kb0, kb1, kb2, kb3";
30 template <
class TScalar>
32 template <
class TScalar>
34 template <
class TScalar>
35 using Params = Eigen::Matrix<TScalar, kNumParams, 1>;
36 template <
class TScalar>
39 template <
class TParamsTypeT,
class TPo
intTypeT>
41 Eigen::MatrixBase<TParamsTypeT>
const& params,
42 Eigen::MatrixBase<TPointTypeT>
const& proj_point_in_camera_z1_plane)
45 TParamsTypeT::ColsAtCompileTime == 1,
"params must be a column-vector");
48 "params must have exactly kNumParams rows");
50 TPointTypeT::ColsAtCompileTime == 1,
51 "point_camera must be a column-vector");
53 TPointTypeT::RowsAtCompileTime == 2,
54 "point_camera must have exactly 2 columns");
56 auto const k0 = params[4];
57 auto const k1 = params[5];
58 auto const k2 = params[6];
59 auto const k3 = params[7];
61 auto const radius_squared =
62 proj_point_in_camera_z1_plane[0] * proj_point_in_camera_z1_plane[0] +
63 proj_point_in_camera_z1_plane[1] * proj_point_in_camera_z1_plane[1];
67 if (radius_squared > sophus::kEpsilonF64) {
68 auto const radius = sqrt(radius_squared);
69 auto const radius_inverse = 1.0 / radius;
70 auto const theta = atan2(radius,
typename TPointTypeT::Scalar(1.0));
71 auto const theta2 = theta * theta;
72 auto const theta4 = theta2 * theta2;
73 auto const theta6 = theta4 * theta2;
74 auto const theta8 = theta4 * theta4;
75 auto const r_distorted =
76 theta * (1.0 + k0 * theta2 + k1 * theta4 + k2 * theta6 + k3 * theta8);
77 auto const scaling = r_distorted * radius_inverse;
79 return scaling * proj_point_in_camera_z1_plane.cwiseProduct(
80 params.template head<2>()) +
81 params.template segment<2>(2);
86 params.template head<4>(), proj_point_in_camera_z1_plane);
89 template <
class TScalar>
98 const TScalar fu = params[0];
99 const TScalar fv = params[1];
100 const TScalar u0 = params[2];
101 const TScalar v0 = params[3];
103 const TScalar k0 = params[4];
104 const TScalar k1 = params[5];
105 const TScalar k2 = params[6];
106 const TScalar k3 = params[7];
108 const TScalar un = (pixel_image(0) - u0) / fu;
109 const TScalar vn = (pixel_image(1) - v0) / fv;
110 const TScalar rth2 = un * un + vn * vn;
112 if (rth2 < sophus::kEpsilon<TScalar> * sophus::kEpsilon<TScalar>) {
113 return Eigen::Matrix<TScalar, 2, 1>(un, vn);
116 const TScalar rth = sqrt(rth2);
119 TScalar th = sqrt(rth);
120 for (
int i = 0; i < 500; ++i) {
121 const TScalar th2 = th * th;
122 const TScalar th4 = th2 * th2;
123 const TScalar th6 = th4 * th2;
124 const TScalar th8 = th4 * th4;
127 th * (TScalar(1.0) + k0 * th2 + k1 * th4 + k2 * th6 + k3 * th8);
129 const TScalar d_thd_wtr_th =
130 TScalar(1.0) + TScalar(3.0) * k0 * th2 + TScalar(5.0) * k1 * th4 +
131 TScalar(7.0) * k2 * th6 + TScalar(9.0) * k3 * th8;
133 const TScalar step = (thd - rth) / d_thd_wtr_th;
137 sophus::kEpsilon<TScalar>) {
142 TScalar radius_undistorted = tan(th);
144 if (radius_undistorted < TScalar(0.0)) {
145 return Eigen::Matrix<TScalar, 2, 1>(
146 -radius_undistorted * un / rth, -radius_undistorted * vn / rth);
148 return Eigen::Matrix<TScalar, 2, 1>(
149 radius_undistorted * un / rth, radius_undistorted * vn / rth);
152 template <
class TParamsTypeT,
class TPo
intTypeT>
154 Eigen::MatrixBase<TParamsTypeT>
const& params,
155 Eigen::MatrixBase<TPointTypeT>
const& proj_point_in_camera_z1_plane)
156 -> Eigen::Matrix<typename TPointTypeT::Scalar, 2, 2> {
158 TParamsTypeT::ColsAtCompileTime == 1,
"params must be a column-vector");
160 TParamsTypeT::RowsAtCompileTime ==
kNumParams,
161 "params must have exactly kNumParams rows");
163 TPointTypeT::ColsAtCompileTime == 1,
164 "point_camera must be a column-vector");
166 TPointTypeT::RowsAtCompileTime == 2,
167 "point_camera must have exactly 2 columns");
168 using Scalar =
typename TPointTypeT::Scalar;
170 Scalar a = proj_point_in_camera_z1_plane[0];
171 Scalar b = proj_point_in_camera_z1_plane[1];
172 Scalar
const fx = params[0];
173 Scalar
const fy = params[1];
174 Eigen::Matrix<Scalar, kNumDistortionParams, 1> k =
175 params.template tail<kNumDistortionParams>();
177 auto const radius_squared = a * a + b * b;
181 Eigen::Matrix<typename TPointTypeT::Scalar, 2, 2> dx;
183 if (radius_squared < sophus::kEpsilonSqrtF64) {
196 Scalar
const c0 = pow(a, 2);
197 Scalar
const c1 = pow(b, 2);
198 Scalar
const c2 = c0 + c1;
199 Scalar
const c3 = pow(c2, 5.0 / 2.0);
200 Scalar
const c4 = c2 + 1;
201 Scalar
const c5 = atan(sqrt(c2));
202 Scalar
const c6 = pow(c5, 2);
203 Scalar
const c7 = c6 * k[0];
204 Scalar
const c8 = pow(c5, 4);
205 Scalar
const c9 = c8 * k[1];
206 Scalar
const c10 = pow(c5, 6);
207 Scalar
const c11 = c10 * k[2];
208 Scalar
const c12 = pow(c5, 8) * k[3];
209 Scalar
const c13 = 1.0 * c4 * c5 * (c11 + c12 + c7 + c9 + 1.0);
210 Scalar
const c14 = c13 * c3;
211 Scalar
const c15 = pow(c2, 3.0 / 2.0);
212 Scalar
const c16 = c13 * c15;
214 1.0 * c11 + 1.0 * c12 +
215 2.0 * c6 * (4 * c10 * k[3] + 2 * c6 * k[1] + 3 * c8 * k[2] + k[0]) +
216 1.0 * c7 + 1.0 * c9 + 1.0;
217 Scalar
const c18 = c17 * pow(c2, 2);
218 Scalar
const c19 = 1.0 / c4;
219 Scalar
const c20 = c19 / pow(c2, 3);
220 Scalar
const c21 = a * b * c19 * (-c13 * c2 + c15 * c17) / c3;
222 dx(0, 0) = c20 * fx * (-c0 * c16 + c0 * c18 + c14);
226 dx(1, 1) = c20 * fy * (-c1 * c16 + c1 * c18 + c14);