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.