Don't assume program state is user state
The SolverImpl::Solve() method incorrectly assumed that the
state pointers inside the parameter blocks always pointed to
the user state at the start of the method. That is not true.
Change-Id: I73f8eeda453422c99e09d71a3cd0bfa92dd45742
diff --git a/internal/ceres/program.cc b/internal/ceres/program.cc
index 444b102..529e4a3 100644
--- a/internal/ceres/program.cc
+++ b/internal/ceres/program.cc
@@ -86,11 +86,19 @@
void Program::CopyParameterBlockStateToUserState() {
for (int i = 0; i < parameter_blocks_.size(); ++i) {
- parameter_blocks_[i]->GetState(
- parameter_blocks_[i]->mutable_user_state());
+ parameter_blocks_[i]->GetState(parameter_blocks_[i]->mutable_user_state());
}
}
+bool Program::CopyUserStateToParameterBlocks() {
+ for (int i = 0; i < parameter_blocks_.size(); ++i) {
+ if (!parameter_blocks_[i]->SetState(parameter_blocks_[i]->user_state())) {
+ return false;
+ }
+ }
+ return true;
+}
+
bool Program::Plus(const double* state,
const double* delta,
double* state_plus_delta) const {
diff --git a/internal/ceres/program.h b/internal/ceres/program.h
index 113d352..27b58e1 100644
--- a/internal/ceres/program.h
+++ b/internal/ceres/program.h
@@ -71,8 +71,9 @@
bool StateVectorToParameterBlocks(const double *state);
void ParameterBlocksToStateVector(double *state) const;
- // Copy internal state out to the user's parameters.
+ // Copy internal state to and from the user's parameters.
void CopyParameterBlockStateToUserState();
+ bool CopyUserStateToParameterBlocks();
// Update a state vector for the program given a delta.
bool Plus(const double* state,
diff --git a/internal/ceres/solver_impl.cc b/internal/ceres/solver_impl.cc
index ca35adc..506ef2f 100644
--- a/internal/ceres/solver_impl.cc
+++ b/internal/ceres/solver_impl.cc
@@ -207,6 +207,16 @@
options.sparse_linear_algebra_library;
summary->trust_region_strategy_type = options.trust_region_strategy_type;
+ // Ensure the program state is set to the user parameters.
+ Program* program = CHECK_NOTNULL(problem_impl)->mutable_program();
+ if (!program->CopyUserStateToParameterBlocks()) {
+ // This can only happen if there was a numerical problem updating the local
+ // jacobians. Indicate as such and fail out.
+ summary->termination_type == NUMERICAL_FAILURE;
+ summary->error = "Local parameterization failure.";
+ return;
+ }
+
// Evaluate the initial cost and residual vector (if needed). The
// initial cost needs to be computed on the original unpreprocessed
// problem, as it is used to determine the value of the "fixed" part
@@ -315,7 +325,6 @@
time_t post_process_end_time = time(NULL);
summary->postprocessor_time_in_seconds =
post_process_end_time - post_process_start_time;
- return;
}
// Strips varying parameters and residuals, maintaining order, and updating