Skip to content

Commit 7af7e0c

Browse files
davidv1992rnijveld
authored andcommitted
Modified kalman filter to avoid accidental nans on sqrt.
1 parent c4f63a0 commit 7af7e0c

File tree

1 file changed

+17
-9
lines changed

1 file changed

+17
-9
lines changed

statime/src/filters/kalman.rs

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ fn chi_1(chi: f64) -> f64 {
9393
const A4: f64 = -1.453152027;
9494
const A5: f64 = 1.061405429;
9595

96-
let x = (chi / 2.).sqrt();
96+
let x = (chi / 2.).max(0.0).sqrt();
9797
let t = 1. / (1. + P * x);
9898
(A1 * t + A2 * t * t + A3 * t * t * t + A4 * t * t * t * t + A5 * t * t * t * t * t)
9999
* (-(x * x)).exp()
@@ -175,7 +175,7 @@ impl MeasurementErrorEstimator {
175175
);
176176
log::info!(
177177
"New uncertainty estimate: {}ns",
178-
self.measurement_variance(config).sqrt() * 1e9,
178+
self.measurement_variance(config).max(0.0).sqrt() * 1e9,
179179
);
180180
} else {
181181
self.last_sync = Some((m.event_time, sync_offset));
@@ -194,7 +194,7 @@ impl MeasurementErrorEstimator {
194194
);
195195
log::info!(
196196
"New uncertainty estimate: {}ns",
197-
self.measurement_variance(config).sqrt() * 1e9,
197+
self.measurement_variance(config).max(0.0).sqrt() * 1e9,
198198
);
199199
} else {
200200
self.last_delay = Some((m.event_time, delay_offset));
@@ -409,7 +409,7 @@ impl BaseFilter {
409409
fn offset_uncertainty(&self, config: &KalmanConfiguration) -> f64 {
410410
self.0
411411
.as_ref()
412-
.map(|inner| inner.uncertainty.entry(0, 0).sqrt())
412+
.map(|inner| inner.uncertainty.entry(0, 0).max(0.0).sqrt())
413413
.unwrap_or(config.step_threshold.seconds())
414414
}
415415

@@ -423,7 +423,7 @@ impl BaseFilter {
423423
fn freq_offset_uncertainty(&self, config: &KalmanConfiguration) -> f64 {
424424
self.0
425425
.as_ref()
426-
.map(|inner| inner.uncertainty.entry(1, 1).sqrt())
426+
.map(|inner| inner.uncertainty.entry(1, 1).max(0.0).sqrt())
427427
.unwrap_or(config.initial_frequency_uncertainty)
428428
}
429429

@@ -437,7 +437,7 @@ impl BaseFilter {
437437
fn mean_delay_uncertainty(&self, config: &KalmanConfiguration) -> f64 {
438438
self.0
439439
.as_ref()
440-
.map(|inner| inner.uncertainty.entry(2, 2).sqrt())
440+
.map(|inner| inner.uncertainty.entry(2, 2).max(0.0).sqrt())
441441
.unwrap_or(config.step_threshold.seconds())
442442
}
443443

@@ -497,6 +497,7 @@ impl Filter for KalmanFilter {
497497
wander: config.initial_wander,
498498
wander_measurement_error: measurement_error_estimator
499499
.measurement_variance(&config)
500+
.max(0.0)
500501
.sqrt(),
501502
measurement_error_estimator,
502503
cur_frequency: None,
@@ -649,28 +650,34 @@ impl KalmanFilter {
649650
}
650651

651652
fn wander_score_update(&mut self, uncertainty: f64, prediction: f64, actual: f64) {
652-
log::info!("Wander uncertainty: {}ns", uncertainty.sqrt() * 1e9);
653+
log::info!(
654+
"Wander uncertainty: {}ns",
655+
uncertainty.max(0.0).sqrt() * 1e9
656+
);
653657
if self.wander_measurement_error
654658
> 10.0
655659
* self
656660
.measurement_error_estimator
657661
.measurement_variance(&self.config)
662+
.max(0.0)
658663
.sqrt()
659664
{
660665
self.wander_filter = self.running_filter.clone();
661666
self.wander_measurement_error = self
662667
.measurement_error_estimator
663668
.measurement_variance(&self.config)
669+
.max(0.0)
664670
.sqrt()
665-
} else if uncertainty.sqrt() > 10.0 * self.wander_measurement_error {
671+
} else if uncertainty.max(0.0).sqrt() > 10.0 * self.wander_measurement_error {
666672
log::info!(
667673
"Wander update predict: {}ns, actual: {}ns",
668674
prediction * 1e9,
669675
actual * 1e9
670676
);
671677
let p = 1.
672678
- chi_1(
673-
sqr(actual - prediction) / (uncertainty + sqr(self.wander_measurement_error)),
679+
sqr(actual - prediction)
680+
/ (uncertainty + sqr(self.wander_measurement_error)).max(f64::EPSILON),
674681
);
675682
log::info!("p: {}", p);
676683
if p < self.config.precision_low_probability {
@@ -685,6 +692,7 @@ impl KalmanFilter {
685692
self.wander_measurement_error = self
686693
.measurement_error_estimator
687694
.measurement_variance(&self.config)
695+
.max(0.0)
688696
.sqrt();
689697
}
690698
}

0 commit comments

Comments
 (0)