使用非静态变量定义雅可比循环时Ceres-Solver报错求助
Hey there, let's break down the Ceres Solver issue you're facing and walk through the likely causes and fixes:
First, let's start with the most obvious red flag in your code, then move into the trickier runtime problems.
1. Your Jacobian Calculation is Completely Incorrect
Looking at your residual formula:
residuals[0] = d0; for (int i = 0; i < num_weights; ++i) { residuals[0] += parameters[i+1][0]; }
This means the residual is a sum of all parameters (the first d0 plus every weight parameter). The partial derivative of this residual with respect to each parameter is 1, not 0.
Right now you're setting all Jacobian entries to 0:
jacobians[i][0] = 0;
Ceres Solver runs consistency checks by default (comparing your analytical Jacobian to numerical differentiation). When these two results don't match, it throws the "Residual and Jacobian evaluation failed." error.
Fix This First:
Update the Jacobian assignment to:
jacobians[i][0] = 1;
2. _weights.size() Might Be Changing Unexpectedly at Runtime
You mentioned hardcoding num_weights fixes the issue, which suggests that when you use _weights.size() in Evaluate, it's returning a value that doesn't match what was used to set up the parameter blocks in the constructor.
Possible reasons:
- Memory corruption: Some other part of your code is writing to invalid memory, overwriting the internal state of the
_weightsvector (e.g., its size counter). Tools like Valgrind can help track this down. - Lifetime mismatch: If your
Costobjects are being destroyed or deallocated before the solver runs, accessing_weightswould lead to undefined behavior. Double-check that all cost objects remain valid for the full duration of the solver's execution.
3. Parameter Block Count vs. Passed Parameters Don't Match
In your constructor, you set up 1 + _weights.size() parameter blocks. If you pass fewer or more parameters when calling AddResidualBlock, Ceres will pass a mismatched number of parameters to Evaluate.
For example:
- If you construct a
Costwith 5 weights (so 6 parameter blocks total), but only pass 5 parameters toAddResidualBlock, accessingparameters[i+1]in your loop will go out of bounds, triggering a runtime error. - Hardcoding
num_weightsmight accidentally align with the actual number of parameters passed, avoiding the out-of-bounds access.
Verify This:
Add a debug print after creating your cost object to confirm the parameter block count, then ensure you pass exactly that many parameters to AddResidualBlock:
auto cost_function = new Cost(weights); std::cout << "Expected parameter blocks: " << cost_function->parameter_block_sizes().size() << std::endl; // Make sure AddResidualBlock receives this exact number of parameters problem.AddResidualBlock(cost_function, nullptr, param0, param1, param2, ...);
内容的提问来源于stack exchange,提问作者Jan-Michael Tressler

