72 const Eigen::Vector2d& point2D,
73 Eigen::Vector3d* proj_center,
76 const Eigen::Vector3d bearing =
77 inv_proj_matrix.leftCols<3>() * point2D.homogeneous();
78 const Eigen::Vector3d bearing_normalized = bearing.normalized();
79 *proj_center = inv_proj_matrix.rightCols<1>();
80 *pluecker << bearing_normalized, proj_center->cross(bearing_normalized);
83 Eigen::Matrix3d CayleyToRotationMatrix(
const Eigen::Vector3d& cayley) {
84 const double cayley0_sqr = cayley[0] * cayley[0];
85 const double cayley1_sqr = cayley[1] * cayley[1];
86 const double cayley2_sqr = cayley[2] * cayley[2];
87 const double cayley01 = cayley[0] * cayley[1];
88 const double cayley12 = cayley[1] * cayley[2];
89 const double cayley02 = cayley[0] * cayley[2];
91 const double scale = 1 + cayley0_sqr + cayley1_sqr + cayley2_sqr;
92 const double inv_scale = 1.0 / scale;
96 R(0, 0) = inv_scale * (1 + cayley0_sqr - cayley1_sqr - cayley2_sqr);
97 R(0, 1) = inv_scale * (2 * (cayley01 - cayley[2]));
98 R(0, 2) = inv_scale * (2 * (cayley02 + cayley[1]));
99 R(1, 0) = inv_scale * (2 * (cayley01 + cayley[2]));
100 R(1, 1) = inv_scale * (1 - cayley0_sqr + cayley1_sqr - cayley2_sqr);
101 R(1, 2) = inv_scale * (2 * (cayley12 - cayley[0]));
102 R(2, 0) = inv_scale * (2 * (cayley02 - cayley[1]));
103 R(2, 1) = inv_scale * (2 * (cayley12 + cayley[0]));
104 R(2, 2) = inv_scale * (1 - cayley0_sqr - cayley1_sqr + cayley2_sqr);
109 Eigen::Vector3d RotationMatrixToCaley(
const Eigen::Matrix3d& R) {
110 const Eigen::Matrix3d C1 = R - Eigen::Matrix3d::Identity();
111 const Eigen::Matrix3d C2 = R + Eigen::Matrix3d::Identity();
112 const Eigen::Matrix3d C = C1 * C2.inverse();
113 return Eigen::Vector3d(-C(1, 2), C(0, 2), -C(0, 1));
116 Eigen::Vector3d ComputeRotationBetweenPoints(
117 const std::vector<Eigen::Vector6d>& plueckers1,
118 const std::vector<Eigen::Vector6d>& plueckers2) {
119 CHECK_EQ(plueckers1.size(), plueckers2.size());
122 Eigen::Vector3d points_center1 = Eigen::Vector3d::Zero();
123 Eigen::Vector3d points_center2 = Eigen::Vector3d::Zero();
124 for (
size_t i = 0; i < plueckers1.size(); i++) {
125 points_center1 += plueckers1[i].head<3>();
126 points_center2 += plueckers2[i].head<3>();
128 points_center1 = points_center1 / plueckers1.size();
129 points_center2 = points_center2 / plueckers1.size();
131 Eigen::Matrix3d Hcross = Eigen::Matrix3d::Zero();
132 for (
size_t i = 0; i < plueckers1.size(); i++) {
133 const Eigen::Vector3d f1 = plueckers1[i].head<3>() - points_center1;
134 const Eigen::Vector3d f2 = plueckers2[i].head<3>() - points_center2;
135 Hcross += f2 * f1.transpose();
138 const Eigen::JacobiSVD<Eigen::Matrix3d> svd(
139 Hcross, Eigen::ComputeFullU | Eigen::ComputeFullV);
140 const Eigen::Matrix3d V = svd.matrixV();
141 const Eigen::Matrix3d U = svd.matrixU();
143 Eigen::Matrix3d R = V * U.transpose();
144 if (R.determinant() < 0) {
145 Eigen::Matrix3d V_prime;
146 V_prime.col(0) = V.col(0);
147 V_prime.col(1) = V.col(1);
148 V_prime.col(2) = -V.col(2);
149 R = V_prime * U.transpose();
152 return RotationMatrixToCaley(R);
155 Eigen::Matrix4d ComposeG(
const Eigen::Matrix3d& xxF,
const Eigen::Matrix3d& yyF,
156 const Eigen::Matrix3d& zzF,
const Eigen::Matrix3d& xyF,
157 const Eigen::Matrix3d& yzF,
const Eigen::Matrix3d& zxF,
158 const Eigen::Matrix<double, 3, 9>& x1P,
159 const Eigen::Matrix<double, 3, 9>& y1P,
160 const Eigen::Matrix<double, 3, 9>& z1P,
161 const Eigen::Matrix<double, 3, 9>& x2P,
162 const Eigen::Matrix<double, 3, 9>& y2P,
163 const Eigen::Matrix<double, 3, 9>& z2P,
164 const Eigen::Matrix<double, 9, 9>& m11P,
165 const Eigen::Matrix<double, 9, 9>& m12P,
166 const Eigen::Matrix<double, 9, 9>& m22P,
168 const Eigen::Matrix3d R = CayleyToRotationMatrix(
rotation);
170 Eigen::Matrix<double, 1, 9> R_rows;
171 R_rows << R.row(0), R.row(1), R.row(2);
173 Eigen::Matrix<double, 9, 1> R_cols;
174 R_cols << R.col(0), R.col(1), R.col(2);
176 const Eigen::Vector3d xxFr1t = xxF * R.row(1).transpose();
177 const Eigen::Vector3d yyFr0t = yyF * R.row(0).transpose();
178 const Eigen::Vector3d zzFr0t = zzF * R.row(0).transpose();
179 const Eigen::Vector3d yzFr0t = yzF * R.row(0).transpose();
180 const Eigen::Vector3d xyFr1t = xyF * R.row(1).transpose();
181 const Eigen::Vector3d xyFr2t = xyF * R.row(2).transpose();
182 const Eigen::Vector3d zxFr1t = zxF * R.row(1).transpose();
183 const Eigen::Vector3d zxFr2t = zxF * R.row(2).transpose();
185 const Eigen::Vector3d x1PC = x1P * R_cols;
186 const Eigen::Vector3d y1PC = y1P * R_cols;
187 const Eigen::Vector3d z1PC = z1P * R_cols;
189 const Eigen::Vector3d x2PR = x2P * R_rows.transpose();
190 const Eigen::Vector3d y2PR = y2P * R_rows.transpose();
191 const Eigen::Vector3d z2PR = z2P * R_rows.transpose();
195 G(0, 0) = R.row(2) * yyF * R.row(2).transpose();
196 G(0, 0) += -2.0 * R.row(2) * yzF * R.row(1).transpose();
197 G(0, 0) += R.row(1) * zzF * R.row(1).transpose();
199 G(0, 1) = R.row(2) * yzFr0t;
200 G(0, 1) += -1.0 * R.row(2) * xyFr2t;
201 G(0, 1) += -1.0 * R.row(1) * zzFr0t;
202 G(0, 1) += R.row(1) * zxFr2t;
204 G(0, 2) = R.row(2) * xyFr1t;
205 G(0, 2) += -1.0 * R.row(2) * yyFr0t;
206 G(0, 2) += -1.0 * R.row(1) * zxFr1t;
207 G(0, 2) += R.row(1) * yzFr0t;
209 G(1, 1) = R.row(0) * zzFr0t;
210 G(1, 1) += -2.0 * R.row(0) * zxFr2t;
211 G(1, 1) += R.row(2) * xxF * R.row(2).transpose();
213 G(1, 2) = R.row(0) * zxFr1t;
214 G(1, 2) += -1.0 * R.row(0) * yzFr0t;
215 G(1, 2) += -1.0 * R.row(2) * xxFr1t;
216 G(1, 2) += R.row(0) * xyFr2t;
218 G(2, 2) = R.row(1) * xxFr1t;
219 G(2, 2) += -2.0 * R.row(0) * xyFr1t;
220 G(2, 2) += R.row(0) * yyFr0t;
226 G(0, 3) = R.row(2) * y1PC;
227 G(0, 3) += R.row(2) * y2PR;
228 G(0, 3) += -1.0 * R.row(1) * z1PC;
229 G(0, 3) += -1.0 * R.row(1) * z2PR;
231 G(1, 3) = R.row(0) * z1PC;
232 G(1, 3) += R.row(0) * z2PR;
233 G(1, 3) += -1.0 * R.row(2) * x1PC;
234 G(1, 3) += -1.0 * R.row(2) * x2PR;
236 G(2, 3) = R.row(1) * x1PC;
237 G(2, 3) += R.row(1) * x2PR;
238 G(2, 3) += -1.0 * R.row(0) * y1PC;
239 G(2, 3) += -1.0 * R.row(0) * y2PR;
241 G(3, 3) = -1.0 * R_cols.transpose() * m11P * R_cols;
242 G(3, 3) += -1.0 * R_rows * m22P * R_rows.transpose();
243 G(3, 3) += -2.0 * R_rows * m12P * R_cols;
252 Eigen::Vector4d ComputeEigenValue(
253 const Eigen::Matrix3d& xxF,
const Eigen::Matrix3d& yyF,
254 const Eigen::Matrix3d& zzF,
const Eigen::Matrix3d& xyF,
255 const Eigen::Matrix3d& yzF,
const Eigen::Matrix3d& zxF,
256 const Eigen::Matrix<double, 3, 9>& x1P,
257 const Eigen::Matrix<double, 3, 9>& y1P,
258 const Eigen::Matrix<double, 3, 9>& z1P,
259 const Eigen::Matrix<double, 3, 9>& x2P,
260 const Eigen::Matrix<double, 3, 9>& y2P,
261 const Eigen::Matrix<double, 3, 9>& z2P,
262 const Eigen::Matrix<double, 9, 9>& m11P,
263 const Eigen::Matrix<double, 9, 9>& m12P,
264 const Eigen::Matrix<double, 9, 9>& m22P,
const Eigen::Vector3d&
rotation) {
265 const Eigen::Matrix4d G =
266 ComposeG(xxF, yyF, zzF, xyF, yzF, zxF, x1P, y1P, z1P, x2P, y2P, z2P, m11P,
271 const double G01_2 = G(0, 1) * G(0, 1);
272 const double G02_2 = G(0, 2) * G(0, 2);
273 const double G03_2 = G(0, 3) * G(0, 3);
275 const double G12_2 = G(1, 2) * G(1, 2);
276 const double G13_2 = G(1, 3) * G(1, 3);
278 const double G23_2 = G(2, 3) * G(2, 3);
281 const double B = -G(3, 3) - G(2, 2) - G(1, 1) - G(0, 0);
282 const double C = -G23_2 + G(2, 2) * G(3, 3) - G13_2 - G12_2 +
283 G(1, 1) * G(3, 3) + G(1, 1) * G(2, 2) - G03_2 - G02_2 -
284 G01_2 + G(0, 0) * G(3, 3) + G(0, 0) * G(2, 2) +
287 G13_2 * G(2, 2) - 2.0 * G(1, 2) * G(1, 3) * G(2, 3) + G12_2 * G(3, 3) +
288 G(1, 1) * G23_2 - G(1, 1) * G(2, 2) * G(3, 3) + G03_2 * G(2, 2) +
289 G03_2 * G(1, 1) - 2.0 * G(0, 2) * G(0, 3) * G(2, 3) + G02_2 * G(3, 3) +
290 G02_2 * G(1, 1) - 2.0 * G(0, 1) * G(0, 3) * G(1, 3) -
291 2.0 * G(0, 1) * G(0, 2) * G(1, 2) + G01_2 * G(3, 3) + G01_2 * G(2, 2) +
292 G(0, 0) * G23_2 - G(0, 0) * G(2, 2) * G(3, 3) + G(0, 0) * G13_2 +
293 G(0, 0) * G12_2 - G(0, 0) * G(1, 1) * G(3, 3) -
294 G(0, 0) * G(1, 1) * G(2, 2);
296 G03_2 * G12_2 - G03_2 * G(1, 1) * G(2, 2) -
297 2.0 * G(0, 2) * G(0, 3) * G(1, 2) * G(1, 3) +
298 2.0 * G(0, 2) * G(0, 3) * G(1, 1) * G(2, 3) + G02_2 * G13_2 -
299 G02_2 * G(1, 1) * G(3, 3) + 2.0 * G(0, 1) * G(0, 3) * G(1, 3) * G(2, 2) -
300 2.0 * G(0, 1) * G(0, 3) * G(1, 2) * G(2, 3) -
301 2.0 * G(0, 1) * G(0, 2) * G(1, 3) * G(2, 3) +
302 2.0 * G(0, 1) * G(0, 2) * G(1, 2) * G(3, 3) + G01_2 * G23_2 -
303 G01_2 * G(2, 2) * G(3, 3) - G(0, 0) * G13_2 * G(2, 2) +
304 2.0 * G(0, 0) * G(1, 2) * G(1, 3) * G(2, 3) - G(0, 0) * G12_2 * G(3, 3) -
305 G(0, 0) * G(1, 1) * G23_2 + G(0, 0) * G(1, 1) * G(2, 2) * G(3, 3);
307 const double B_pw2 = B * B;
308 const double B_pw3 = B_pw2 * B;
309 const double B_pw4 = B_pw3 * B;
310 const double alpha = -0.375 * B_pw2 + C;
311 const double beta = B_pw3 / 8.0 - B * C / 2.0 + D;
312 const double gamma = -0.01171875 * B_pw4 + B_pw2 * C / 16.0 - B * D / 4.0 + E;
313 const double alpha_pw2 = alpha * alpha;
314 const double alpha_pw3 = alpha_pw2 * alpha;
315 const double p = -alpha_pw2 / 12.0 - gamma;
316 const double q = -alpha_pw3 / 108.0 + alpha * gamma / 3.0 - beta * beta / 8.0;
317 const double helper1 = -p * p * p / 27.0;
318 const double theta2 = pow(helper1, (1.0 / 3.0));
319 const double theta1 =
321 std::cos((1.0 / 3.0) * std::acos((-q / 2.0) / std::sqrt(helper1)));
322 const double y = -(5.0 / 6.0) * alpha -
323 ((1.0 / 3.0) * p * theta1 - theta1 * theta2) / theta2;
324 const double w = std::sqrt(alpha + 2.0 *
y);
326 Eigen::Vector4d roots;
327 roots(0) = -B / 4.0 + 0.5 * w +
328 0.5 * std::sqrt(-3.0 * alpha - 2.0 *
y - 2.0 * beta / w);
329 roots(1) = -B / 4.0 + 0.5 * w -
330 0.5 * std::sqrt(-3.0 * alpha - 2.0 *
y - 2.0 * beta / w);
331 roots(2) = -B / 4.0 - 0.5 * w +
332 0.5 * std::sqrt(-3.0 * alpha - 2.0 *
y + 2.0 * beta / w);
333 roots(3) = -B / 4.0 - 0.5 * w -
334 0.5 * std::sqrt(-3.0 * alpha - 2.0 *
y + 2.0 * beta / w);
338 double ComputeCost(
const Eigen::Matrix3d& xxF,
const Eigen::Matrix3d& yyF,
339 const Eigen::Matrix3d& zzF,
const Eigen::Matrix3d& xyF,
340 const Eigen::Matrix3d& yzF,
const Eigen::Matrix3d& zxF,
341 const Eigen::Matrix<double, 3, 9>& x1P,
342 const Eigen::Matrix<double, 3, 9>& y1P,
343 const Eigen::Matrix<double, 3, 9>& z1P,
344 const Eigen::Matrix<double, 3, 9>& x2P,
345 const Eigen::Matrix<double, 3, 9>& y2P,
346 const Eigen::Matrix<double, 3, 9>& z2P,
347 const Eigen::Matrix<double, 9, 9>& m11P,
348 const Eigen::Matrix<double, 9, 9>& m12P,
349 const Eigen::Matrix<double, 9, 9>& m22P,
350 const Eigen::Vector3d&
rotation,
const int step) {
354 const Eigen::Vector4d roots =
355 ComputeEigenValue(xxF, yyF, zzF, xyF, yzF, zxF, x1P, y1P, z1P, x2P, y2P,
360 }
else if (step == 1) {
367 Eigen::Vector3d ComputeJacobian(
368 const Eigen::Matrix3d& xxF,
const Eigen::Matrix3d& yyF,
369 const Eigen::Matrix3d& zzF,
const Eigen::Matrix3d& xyF,
370 const Eigen::Matrix3d& yzF,
const Eigen::Matrix3d& zxF,
371 const Eigen::Matrix<double, 3, 9>& x1P,
372 const Eigen::Matrix<double, 3, 9>& y1P,
373 const Eigen::Matrix<double, 3, 9>& z1P,
374 const Eigen::Matrix<double, 3, 9>& x2P,
375 const Eigen::Matrix<double, 3, 9>& y2P,
376 const Eigen::Matrix<double, 3, 9>& z2P,
377 const Eigen::Matrix<double, 9, 9>& m11P,
378 const Eigen::Matrix<double, 9, 9>& m12P,
379 const Eigen::Matrix<double, 9, 9>& m22P,
const Eigen::Vector3d&
rotation,
380 const double current_cost,
const int step) {
381 Eigen::Vector3d jacobian;
382 const double kEpsilon = 0.00000001;
383 for (
int j = 0; j < 3; j++) {
384 Eigen::Vector3d cayley_j =
rotation;
385 cayley_j[j] += kEpsilon;
386 const double cost_j =
387 ComputeCost(xxF, yyF, zzF, xyF, yzF, zxF, x1P, y1P, z1P, x2P, y2P, z2P,
388 m11P, m12P, m22P, cayley_j, step);
389 jacobian(j) = cost_j - current_cost;
397 const std::vector<X_t>& points1,
const std::vector<Y_t>& points2) {
398 CHECK_GE(points1.size(), 6);
399 CHECK_EQ(points1.size(), points2.size());
401 std::vector<Eigen::Vector3d> proj_centers1(points1.size());
402 std::vector<Eigen::Vector3d> proj_centers2(points1.size());
403 std::vector<Eigen::Vector6d> plueckers1(points1.size());
404 std::vector<Eigen::Vector6d> plueckers2(points1.size());
405 for (
size_t i = 0; i < points1.size(); ++i) {
406 ComposePlueckerData(points1[i].rel_tform, points1[i].xy, &proj_centers1[i],
408 ComposePlueckerData(points2[i].rel_tform, points2[i].xy, &proj_centers2[i],
412 Eigen::Matrix3d xxF = Eigen::Matrix3d::Zero();
413 Eigen::Matrix3d yyF = Eigen::Matrix3d::Zero();
414 Eigen::Matrix3d zzF = Eigen::Matrix3d::Zero();
415 Eigen::Matrix3d xyF = Eigen::Matrix3d::Zero();
416 Eigen::Matrix3d yzF = Eigen::Matrix3d::Zero();
417 Eigen::Matrix3d zxF = Eigen::Matrix3d::Zero();
419 Eigen::Matrix<double, 3, 9> x1P = Eigen::Matrix<double, 3, 9>::Zero();
420 Eigen::Matrix<double, 3, 9> y1P = Eigen::Matrix<double, 3, 9>::Zero();
421 Eigen::Matrix<double, 3, 9> z1P = Eigen::Matrix<double, 3, 9>::Zero();
422 Eigen::Matrix<double, 3, 9> x2P = Eigen::Matrix<double, 3, 9>::Zero();
423 Eigen::Matrix<double, 3, 9> y2P = Eigen::Matrix<double, 3, 9>::Zero();
424 Eigen::Matrix<double, 3, 9> z2P = Eigen::Matrix<double, 3, 9>::Zero();
426 Eigen::Matrix<double, 9, 9> m11P = Eigen::Matrix<double, 9, 9>::Zero();
427 Eigen::Matrix<double, 9, 9> m12P = Eigen::Matrix<double, 9, 9>::Zero();
428 Eigen::Matrix<double, 9, 9> m22P = Eigen::Matrix<double, 9, 9>::Zero();
430 for (
size_t i = 0; i < points1.size(); ++i) {
431 const Eigen::Vector3d f1 = plueckers1[i].head<3>();
432 const Eigen::Vector3d f2 = plueckers2[i].head<3>();
433 const Eigen::Vector3d t1 = proj_centers1[i];
434 const Eigen::Vector3d t2 = proj_centers2[i];
436 const Eigen::Matrix3d F = f2 * f2.transpose();
437 xxF += f1[0] * f1[0] * F;
438 yyF += f1[1] * f1[1] * F;
439 zzF += f1[2] * f1[2] * F;
440 xyF += f1[0] * f1[1] * F;
441 yzF += f1[1] * f1[2] * F;
442 zxF += f1[2] * f1[0] * F;
444 Eigen::Matrix<double, 9, 1> ff1;
445 ff1(0) = f1[0] * (f2[1] * t2[2] - f2[2] * t2[1]);
446 ff1(1) = f1[1] * (f2[1] * t2[2] - f2[2] * t2[1]);
447 ff1(2) = f1[2] * (f2[1] * t2[2] - f2[2] * t2[1]);
448 ff1(3) = f1[0] * (f2[2] * t2[0] - f2[0] * t2[2]);
449 ff1(4) = f1[1] * (f2[2] * t2[0] - f2[0] * t2[2]);
450 ff1(5) = f1[2] * (f2[2] * t2[0] - f2[0] * t2[2]);
451 ff1(6) = f1[0] * (f2[0] * t2[1] - f2[1] * t2[0]);
452 ff1(7) = f1[1] * (f2[0] * t2[1] - f2[1] * t2[0]);
453 ff1(8) = f1[2] * (f2[0] * t2[1] - f2[1] * t2[0]);
455 x1P += f1[0] * f2 * ff1.transpose();
456 y1P += f1[1] * f2 * ff1.transpose();
457 z1P += f1[2] * f2 * ff1.transpose();
459 Eigen::Matrix<double, 9, 1> ff2;
460 ff2(0) = f2[0] * (f1[1] * t1[2] - f1[2] * t1[1]);
461 ff2(1) = f2[1] * (f1[1] * t1[2] - f1[2] * t1[1]);
462 ff2(2) = f2[2] * (f1[1] * t1[2] - f1[2] * t1[1]);
463 ff2(3) = f2[0] * (f1[2] * t1[0] - f1[0] * t1[2]);
464 ff2(4) = f2[1] * (f1[2] * t1[0] - f1[0] * t1[2]);
465 ff2(5) = f2[2] * (f1[2] * t1[0] - f1[0] * t1[2]);
466 ff2(6) = f2[0] * (f1[0] * t1[1] - f1[1] * t1[0]);
467 ff2(7) = f2[1] * (f1[0] * t1[1] - f1[1] * t1[0]);
468 ff2(8) = f2[2] * (f1[0] * t1[1] - f1[1] * t1[0]);
470 x2P += f1[0] * f2 * ff2.transpose();
471 y2P += f1[1] * f2 * ff2.transpose();
472 z2P += f1[2] * f2 * ff2.transpose();
474 m11P -= ff1 * ff1.transpose();
475 m22P -= ff2 * ff2.transpose();
476 m12P -= ff2 * ff1.transpose();
479 const Eigen::Vector3d initial_rotation =
480 ComputeRotationBetweenPoints(plueckers1, plueckers2);
482 const double kMinLambda = 0.00001;
483 const double kMaxLambda = 0.08;
484 const double kLambdaModifier = 2.0;
485 const int kMaxNumIterations = 50;
486 const bool kDisableIncrements =
true;
488 double perturbation_amplitude = 0.3;
489 int num_random_trials = 0;
492 while (num_random_trials < 5) {
493 if (num_random_trials > 2) {
494 perturbation_amplitude = 0.6;
497 if (num_random_trials == 0) {
500 const Eigen::Vector3d perturbation(
501 RandomReal<double>(-perturbation_amplitude, perturbation_amplitude),
502 RandomReal<double>(-perturbation_amplitude, perturbation_amplitude),
503 RandomReal<double>(-perturbation_amplitude, perturbation_amplitude));
504 rotation = initial_rotation + perturbation;
507 double lambda = 0.01;
508 int num_iterations = 0;
509 double smallest_eigen_value =
510 ComputeCost(xxF, yyF, zzF, xyF, yzF, zxF, x1P, y1P, z1P, x2P, y2P, z2P,
513 for (
int iter = 0; iter < kMaxNumIterations; ++iter) {
514 const Eigen::Vector3d jacobian = ComputeJacobian(
515 xxF, yyF, zzF, xyF, yzF, zxF, x1P, y1P, z1P, x2P, y2P, z2P, m11P,
516 m12P, m22P,
rotation, smallest_eigen_value, 1);
518 const Eigen::Vector3d normalized_jacobian = jacobian.normalized();
520 Eigen::Vector3d sampling_point =
rotation - lambda * normalized_jacobian;
521 double sampling_eigen_value =
522 ComputeCost(xxF, yyF, zzF, xyF, yzF, zxF, x1P, y1P, z1P, x2P, y2P,
523 z2P, m11P, m12P, m22P, sampling_point, 1);
525 if (num_iterations == 0 || !kDisableIncrements) {
526 while (sampling_eigen_value < smallest_eigen_value) {
527 smallest_eigen_value = sampling_eigen_value;
528 if (lambda * kLambdaModifier > kMaxLambda) {
531 lambda *= kLambdaModifier;
532 sampling_point =
rotation - lambda * normalized_jacobian;
533 sampling_eigen_value =
534 ComputeCost(xxF, yyF, zzF, xyF, yzF, zxF, x1P, y1P, z1P, x2P, y2P,
535 z2P, m11P, m12P, m22P, sampling_point, 1);
539 while (sampling_eigen_value > smallest_eigen_value) {
540 lambda /= kLambdaModifier;
541 sampling_point =
rotation - lambda * normalized_jacobian;
542 sampling_eigen_value =
543 ComputeCost(xxF, yyF, zzF, xyF, yzF, zxF, x1P, y1P, z1P, x2P, y2P,
544 z2P, m11P, m12P, m22P, sampling_point, 1);
548 smallest_eigen_value = sampling_eigen_value;
550 if (lambda < kMinLambda) {
556 const double eigen_value2 =
557 ComputeCost(xxF, yyF, zzF, xyF, yzF, zxF, x1P, y1P, z1P, x2P, y2P,
558 z2P, m11P, m12P, m22P,
rotation, 0);
559 if (eigen_value2 > 0.001) {
560 num_random_trials += 1;
569 const Eigen::Matrix3d R = CayleyToRotationMatrix(
rotation).transpose();
571 const Eigen::Matrix4d G =
572 ComposeG(xxF, yyF, zzF, xyF, yzF, zxF, x1P, y1P, z1P, x2P, y2P, z2P, m11P,
575 const Eigen::EigenSolver<Eigen::Matrix4d> eigen_solver_G(G,
true);
576 const Eigen::Matrix4cd V = eigen_solver_G.eigenvectors();
579 std::vector<M_t> models(4);
580 for (
int i = 0; i < 4; ++i) {
581 models[i].leftCols<3>() = R;
582 models[i].rightCols<1>() = -R * VV.col(i);
589 const std::vector<Y_t>& points2,
590 const M_t& proj_matrix,
591 std::vector<double>* residuals) {
592 CHECK_EQ(points1.size(), points2.size());
594 residuals->resize(points1.size(), 0);
596 Eigen::Matrix4d proj_matrix_homogeneous;
597 proj_matrix_homogeneous.topRows<3>() = proj_matrix;
598 proj_matrix_homogeneous.bottomRows<1>() = Eigen::Vector4d(0, 0, 0, 1);
600 for (
size_t i = 0; i < points1.size(); ++i) {
603 points2[i].rel_tform * proj_matrix_homogeneous;
604 const Eigen::Matrix3d R12 =
605 proj_matrix2.leftCols<3>() * proj_matrix1.leftCols<3>().transpose();
606 const Eigen::Vector3d
t12 =
607 proj_matrix2.rightCols<1>() - R12 * proj_matrix1.rightCols<1>();
609 const Eigen::Vector3d Ex1 = E * points1[i].xy.homogeneous();
610 const Eigen::Vector3d Etx2 = E.transpose() * points2[i].xy.homogeneous();
611 const double x2tEx1 = points2[i].xy.homogeneous().transpose() * Ex1;
612 (*residuals)[i] = x2tEx1 * x2tEx1 /
613 (Ex1(0) * Ex1(0) + Ex1(1) * Ex1(1) + Etx2(0) * Etx2(0) +
static void Residuals(const std::vector< X_t > &points1, const std::vector< Y_t > &points2, const M_t &proj_matrix, std::vector< double > *residuals)
static std::vector< M_t > Estimate(const std::vector< X_t > &points1, const std::vector< Y_t > &points2)
Matrix< double, 3, 4 > Matrix3x4d
Eigen::Matrix< double, 6, 1 > Vector6d
Eigen::Matrix3d EssentialMatrixFromPose(const Eigen::Matrix3d &R, const Eigen::Vector3d &t)
Eigen::Matrix3x4d InvertProjectionMatrix(const Eigen::Matrix3x4d &proj_matrix)