Add residuals and jacobian getters to TinySolver. - Add methods to aceess the cached residuals and jacobian computed in the optimization process in TinySolver. Usage of such methods will retrieve the corresponding values associated with the converged parameter. - Reorder the Update() call to ensure that the jacobian/residuals associated with the converged parameter are computed and cached. Change-Id: If82e19d67d28b057833357f2c9a75b2d0fd139af
diff --git a/include/ceres/tiny_solver.h b/include/ceres/tiny_solver.h index 9242cd0..f5cdfd8 100644 --- a/include/ceres/tiny_solver.h +++ b/include/ceres/tiny_solver.h
@@ -286,14 +286,13 @@ // model fits well. x = x_new_; + // TODO(sameeragarwal): Deal with failure. + Update(function, x); if (std::abs(cost_change) < options.function_tolerance) { - cost_ = f_x_new_.squaredNorm() / 2; summary.status = COST_CHANGE_TOO_SMALL; break; } - // TODO(sameeragarwal): Deal with failure. - Update(function, x); if (summary.gradient_max_norm < options.gradient_tolerance) { summary.status = GRADIENT_TOO_SMALL; break; @@ -329,6 +328,16 @@ return summary; } + Eigen::Matrix<Scalar, NUM_RESIDUALS, 1> Residuals() const { + // Residual updates are stored with the opposite sign. + return -residuals_; + } + + Eigen::Matrix<Scalar, NUM_RESIDUALS, NUM_PARAMETERS> Jacobian() const { + // Undo the scaling applied to the jacobian matrix during Update(). + return jacobian_ * jacobi_scaling_.cwiseInverse().asDiagonal(); + } + Options options; Summary summary;
diff --git a/internal/ceres/tiny_solver_test.cc b/internal/ceres/tiny_solver_test.cc index 645ddc5..f8b9264 100644 --- a/internal/ceres/tiny_solver_test.cc +++ b/internal/ceres/tiny_solver_test.cc
@@ -121,6 +121,14 @@ TinySolver<Function> solver; solver.Solve(f, &x); EXPECT_NEAR(0.0, solver.summary.final_cost, 1e-10); + + // Getter methods for residuals and jacobian should match the corresponding + // values evaluated at the converged parameter value. + Vec2 expected_residuals; + Eigen::Matrix<double, 2, 3> expected_jacobian; + f(x.data(), expected_residuals.data(), expected_jacobian.data()); + EXPECT_TRUE(expected_residuals.isApprox(solver.Residuals())); + EXPECT_TRUE(expected_jacobian.isApprox(solver.Jacobian())); } // A test case for when the cost function is statically sized.