Skip to content

Commit 56ff064

Browse files
committed
Fixed incorrect bounding of frequency steering.
1 parent 529de5a commit 56ff064

File tree

1 file changed

+139
-5
lines changed

1 file changed

+139
-5
lines changed

statime/src/filters/kalman.rs

Lines changed: 139 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -629,19 +629,19 @@ impl KalmanFilter {
629629
if let Some(cur_frequency) = self.cur_frequency {
630630
let error_ppm = clamp_adjustment(
631631
cur_frequency,
632-
self.running_filter.freq_offset() * 1e6 - target,
632+
target - self.running_filter.freq_offset() * 1e6,
633633
self.config.max_freq_offset,
634634
);
635-
if let Ok(time) = clock.set_frequency(cur_frequency - error_ppm) {
636-
self.cur_frequency = Some(cur_frequency - error_ppm);
635+
if let Ok(time) = clock.set_frequency(cur_frequency + error_ppm) {
636+
self.cur_frequency = Some(cur_frequency + error_ppm);
637637
self.running_filter.absorb_frequency_steer(
638-
-error_ppm,
638+
error_ppm,
639639
time,
640640
self.wander,
641641
&self.config,
642642
);
643643
self.wander_filter.absorb_frequency_steer(
644-
-error_ppm,
644+
error_ppm,
645645
time,
646646
self.wander,
647647
&self.config,
@@ -779,3 +779,137 @@ impl KalmanFilter {
779779
}
780780
}
781781
}
782+
783+
#[cfg(test)]
784+
mod tests {
785+
use super::*;
786+
use crate::Clock;
787+
788+
#[derive(Default)]
789+
struct TestClock {
790+
last_freq: Option<f64>,
791+
}
792+
793+
impl Clock for TestClock {
794+
type Error = core::convert::Infallible;
795+
796+
fn now(&self) -> Time {
797+
Time::from_nanos(0)
798+
}
799+
800+
fn step_clock(&mut self, _offset: Duration) -> Result<Time, Self::Error> {
801+
panic!("Test should not step clock");
802+
}
803+
804+
fn set_frequency(&mut self, ppm: f64) -> Result<Time, Self::Error> {
805+
self.last_freq = Some(ppm);
806+
Ok(Time::from_nanos(0))
807+
}
808+
809+
fn set_properties(
810+
&mut self,
811+
_time_properties_ds: &crate::config::TimePropertiesDS,
812+
) -> Result<(), Self::Error> {
813+
panic!("Test should not set properties");
814+
}
815+
}
816+
817+
#[test]
818+
fn check_frequency_steering_bounding() {
819+
let timebase = Time::from_nanos(0);
820+
let mut filter = KalmanFilter {
821+
config: KalmanConfiguration {
822+
max_freq_offset: 10.0,
823+
..Default::default()
824+
},
825+
running_filter: BaseFilter(Some(InnerFilter {
826+
state: Vector::new_vector([0.0, 0.0, 0.0]),
827+
uncertainty: Matrix::new([[1e-17, 0.0, 0.0], [0.0, 1e-16, 0.0], [0.0, 0.0, 1e-18]]),
828+
filter_time: timebase,
829+
})),
830+
wander_filter: BaseFilter(None),
831+
wander_score: 0,
832+
wander: KalmanConfiguration::default().initial_wander,
833+
wander_measurement_error: 1.0,
834+
measurement_error_estimator: MeasurementErrorEstimator::default(),
835+
cur_frequency: Some(0.0),
836+
};
837+
let mut clock = TestClock::default();
838+
filter.change_frequency(50.0, &mut clock);
839+
assert_eq!(clock.last_freq, Some(10.0));
840+
filter.change_frequency(50.0, &mut clock);
841+
assert_eq!(clock.last_freq, Some(10.0));
842+
filter.change_frequency(-50.0, &mut clock);
843+
assert_eq!(clock.last_freq, Some(-10.0));
844+
845+
let timebase = Time::from_nanos(0);
846+
let mut filter = KalmanFilter {
847+
config: KalmanConfiguration {
848+
max_freq_offset: 10.0,
849+
..Default::default()
850+
},
851+
running_filter: BaseFilter(Some(InnerFilter {
852+
state: Vector::new_vector([0.0, 0.0, 0.0]),
853+
uncertainty: Matrix::new([[1e-17, 0.0, 0.0], [0.0, 1e-16, 0.0], [0.0, 0.0, 1e-18]]),
854+
filter_time: timebase,
855+
})),
856+
wander_filter: BaseFilter(None),
857+
wander_score: 0,
858+
wander: KalmanConfiguration::default().initial_wander,
859+
wander_measurement_error: 1.0,
860+
measurement_error_estimator: MeasurementErrorEstimator::default(),
861+
cur_frequency: Some(0.0),
862+
};
863+
let mut clock = TestClock::default();
864+
filter.change_frequency(-50.0, &mut clock);
865+
assert_eq!(clock.last_freq, Some(-10.0));
866+
filter.change_frequency(-50.0, &mut clock);
867+
assert_eq!(clock.last_freq, Some(-10.0));
868+
filter.change_frequency(50.0, &mut clock);
869+
assert_eq!(clock.last_freq, Some(10.0));
870+
871+
let timebase = Time::from_nanos(0);
872+
let mut filter = KalmanFilter {
873+
config: KalmanConfiguration {
874+
max_freq_offset: 10.0,
875+
..Default::default()
876+
},
877+
running_filter: BaseFilter(Some(InnerFilter {
878+
state: Vector::new_vector([0.0, 0.0, 0.0]),
879+
uncertainty: Matrix::new([[1e-17, 0.0, 0.0], [0.0, 1e-16, 0.0], [0.0, 0.0, 1e-18]]),
880+
filter_time: timebase,
881+
})),
882+
wander_filter: BaseFilter(None),
883+
wander_score: 0,
884+
wander: KalmanConfiguration::default().initial_wander,
885+
wander_measurement_error: 1.0,
886+
measurement_error_estimator: MeasurementErrorEstimator::default(),
887+
cur_frequency: Some(20.0),
888+
};
889+
let mut clock = TestClock::default();
890+
filter.change_frequency(50.0, &mut clock);
891+
assert_eq!(clock.last_freq, Some(10.0));
892+
893+
let timebase = Time::from_nanos(0);
894+
let mut filter = KalmanFilter {
895+
config: KalmanConfiguration {
896+
max_freq_offset: 10.0,
897+
..Default::default()
898+
},
899+
running_filter: BaseFilter(Some(InnerFilter {
900+
state: Vector::new_vector([0.0, 0.0, 0.0]),
901+
uncertainty: Matrix::new([[1e-17, 0.0, 0.0], [0.0, 1e-16, 0.0], [0.0, 0.0, 1e-18]]),
902+
filter_time: timebase,
903+
})),
904+
wander_filter: BaseFilter(None),
905+
wander_score: 0,
906+
wander: KalmanConfiguration::default().initial_wander,
907+
wander_measurement_error: 1.0,
908+
measurement_error_estimator: MeasurementErrorEstimator::default(),
909+
cur_frequency: Some(-20.0),
910+
};
911+
let mut clock = TestClock::default();
912+
filter.change_frequency(50.0, &mut clock);
913+
assert_eq!(clock.last_freq, Some(10.0));
914+
}
915+
}

0 commit comments

Comments
 (0)