Skip to content

Commit d9ea0c9

Browse files
jbrodovskyclaude
andcommitted
Fix UKF negative variance by adding diagonal regularization
The standard UKF covariance update P = P - K*S*K' is numerically unstable and can produce negative eigenvalues due to floating-point rounding errors, causing the health monitor to fail with "Negative variance on diagonal" errors. This fix adds gentle diagonal regularization (eps = 1e-9) after the covariance update to prevent negative eigenvalues without drastically affecting filter behavior. The approach uses symmetrize() followed by small diagonal additions, which is more stable than aggressive eigenvalue flooring that can cause filter divergence. Fixes #133 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent c27fa87 commit d9ea0c9

1 file changed

Lines changed: 7 additions & 1 deletion

File tree

core/src/kalman.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,13 @@ impl NavigationFilter for UnscentedKalmanFilter {
300300
self.mean_state[7] = wrap_to_2pi(self.mean_state[7]);
301301
self.mean_state[8] = wrap_to_2pi(self.mean_state[8]);
302302
self.covariance -= &k * &s * &k.transpose();
303-
self.covariance = 0.5 * (&self.covariance + self.covariance.transpose());
303+
// Ensure covariance remains positive semi-definite with gentle regularization
304+
self.covariance = symmetrize(&self.covariance);
305+
// Add small diagonal regularization to prevent negative eigenvalues
306+
let eps = 1e-9;
307+
for i in 0..self.state_size {
308+
self.covariance[(i, i)] += eps;
309+
}
304310
}
305311
fn get_estimate(&self) -> DVector<f64> {
306312
self.mean_state.clone()

0 commit comments

Comments
 (0)