Check corrected Hessian in Corrector.MultidimensionalGaussNewtonApproximation When rho[2] <= 0, Corrector clamps alpha to 0 and drops the rank-1 curvature correction term, so the implied Gauss-Newton Hessian is rho[1] * J'J rather than rho[1] * J'J + 2 * rho[2] * J'r r'J. Account for this in g_hess and assert that c_hess matches g_hess. Thanks to Matthias Kraft (@matthias-kraft) for reporting this. Fixes https://github.com/ceres-solver/ceres-solver/issues/363 Change-Id: I3ccc3753aab5a5d753a8f650ff71f2b8ea96a51d
diff --git a/internal/ceres/corrector_test.cc b/internal/ceres/corrector_test.cc index e042481..aa1e0a7 100644 --- a/internal/ceres/corrector_test.cc +++ b/internal/ceres/corrector_test.cc
@@ -186,8 +186,12 @@ sqrt(rho[1]) * (jac - kAlpha / sq_norm * res * res.transpose() * jac); g_grad = rho[1] * jac.transpose() * res; - g_hess = rho[1] * jac.transpose() * jac + - 2.0 * rho[2] * jac.transpose() * res * res.transpose() * jac; + if (rho[2] > 0.0) { + g_hess = rho[1] * jac.transpose() * jac + + 2.0 * rho[2] * jac.transpose() * res * res.transpose() * jac; + } else { + g_hess = rho[1] * jac.transpose() * jac; + } Corrector c(sq_norm, rho); c.CorrectJacobian(3, 2, residuals, jacobian); @@ -201,6 +205,7 @@ ASSERT_NEAR((g_jac - jac).norm(), 0.0, 1e-10); ASSERT_NEAR((g_grad - c_grad).norm(), 0.0, 1e-10); + ASSERT_NEAR((g_hess - c_hess).norm(), 0.0, 1e-10); } }