Skip to content

Commit 24bfc7f

Browse files
authored
Upgrade to qc_traits 0.3 (#365)
Signed-off-by: Guillaume W. Bres <[email protected]>
1 parent dcdabcd commit 24bfc7f

File tree

7 files changed

+388
-53
lines changed

7 files changed

+388
-53
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ anise = { version = "0.6", optional = true }
134134
hifitime = { version = "4.1", features = ["serde", "std"] }
135135
wkt = { version = "0.10.0", default-features = false, optional = true }
136136
gnss-rs = { version = "2.4.0", features = ["serde", "domes", "cospar"] }
137-
gnss-qc-traits = { version = "0.2.0", features = ["html"], optional = true }
137+
gnss-qc-traits = { version = "0.3.1", features = ["html"], optional = true }
138138
serde = { version = "1.0", optional = true, default-features = false, features = ["derive"] }
139139

140140
# Log is optional and our "debug" feature: use this if you're a dev.

src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -190,8 +190,8 @@ pub mod prelude {
190190
#[cfg_attr(docsrs, doc(cfg(feature = "processing")))]
191191
pub mod processing {
192192
pub use qc_traits::{
193-
Decimate, DecimationFilter, Filter, GnssAbsoluteTime, MaskFilter, Masking,
194-
Preprocessing, Split, Timeshift,
193+
Decimate, DecimationFilter, Filter, MaskFilter, Masking, Preprocessing, Split,
194+
TimeCorrection, TimeCorrectionError, TimeCorrectionsDB, Timeshift,
195195
};
196196
}
197197

src/navigation/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@ mod header;
66
mod ionosphere;
77
mod message;
88
mod parsing;
9-
mod rinex;
109
mod time;
1110

11+
pub mod rinex;
12+
1213
pub(crate) mod formatting;
1314

1415
pub(crate) use formatting::format;

src/navigation/rinex/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
#[cfg(feature = "nav")]
22
#[cfg_attr(docsrs, doc(cfg(feature = "nav")))]
3-
mod feature; // feature dependent, high level methods
3+
pub mod feature; // feature dependent, high level methods
44

55
#[cfg(all(feature = "nav", feature = "processing"))]
66
#[cfg_attr(docsrs, doc(cfg(all(feature = "nav", feature = "processing"))))]
7-
mod time; // feature dependent high level methods
7+
pub mod time; // feature dependent high level methods
88

99
#[cfg(feature = "ut1")]
1010
#[cfg_attr(docsrs, doc(cfg(feature = "ut1")))]
11-
mod ut1; // feature dependent high level methods
11+
pub mod ut1; // feature dependent high level methods
1212

1313
use crate::{
1414
navigation::{

src/navigation/rinex/time.rs

Lines changed: 274 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,294 @@
1-
use qc_traits::GnssAbsoluteTime;
1+
use qc_traits::{TimeCorrection, TimeCorrectionsDB};
22

3-
use crate::prelude::Rinex;
3+
use crate::prelude::{Duration, Epoch, Rinex};
44

55
impl Rinex {
6-
/// Collect [GnssAbsoluteTime] solver from this Navigation [Rinex].
6+
/// Collect a [TimeCorrectionsDB] from this Navigation [Rinex],
7+
/// which you can then use for internal or external precise correction.
78
/// Does not apply to any other format.
8-
pub fn gnss_absolute_time_solver(&self) -> Option<GnssAbsoluteTime> {
9+
/// ```
10+
/// use std::str::FromStr;
11+
/// use rinex::prelude::{Rinex, Epoch, TimeScale};
12+
///
13+
/// // This file describes GAGP, GAUT, GPUT (only)
14+
/// // For example: BDT is not available.
15+
/// let rinex = Rinex::from_gzip_file("data/NAV/V3/ESBC00DNK_R_20201770000_01D_MN.rnx.gz")
16+
/// .unwrap();
17+
18+
/// let db = rinex.time_corrections_database()
19+
/// .unwrap_or_else(|| {
20+
/// panic!("Time corrections should exist for V3/BRDC00GOP_R_20210010000_01D_MN.rnx.gz");
21+
/// });
22+
///
23+
/// // In its default form, the database applies without any restriction.
24+
25+
/// for (t_before, t_in, t_after, ts) in [
26+
/// (
27+
/// "2020-06-24T12:00:00 GPST",
28+
/// "2020-06-25T12:00:00 GPST",
29+
/// "2020-06-26T01:00:00 GPST",
30+
/// TimeScale::UTC,
31+
/// ),
32+
/// (
33+
/// "2020-06-24T12:00:00 GPST",
34+
/// "2020-06-25T12:00:00 GPST",
35+
/// "2020-06-26T01:00:00 GPST",
36+
/// TimeScale::GST,
37+
/// ),
38+
/// (
39+
/// "2020-06-24T12:00:00 GST",
40+
/// "2020-06-25T12:00:00 GST",
41+
/// "2020-06-26T01:00:00 GST",
42+
/// TimeScale::GPST,
43+
/// ),
44+
/// (
45+
/// "2020-06-24T12:00:00 UTC",
46+
/// "2020-06-25T12:00:00 UTC",
47+
/// "2020-06-26T01:00:00 UTC",
48+
/// TimeScale::GST,
49+
/// ),
50+
/// ] {
51+
/// let t = Epoch::from_str(t_before).unwrap();
52+
///
53+
/// assert!(db.precise_epoch_correction(t, ts)
54+
/// .is_some(),
55+
/// "precise correction to {} should be feasible @ {}",
56+
/// ts,
57+
/// t_before);
58+
///
59+
/// let t = Epoch::from_str(t_in).unwrap();
60+
///
61+
/// assert!(db.precise_epoch_correction(t, ts)
62+
/// .is_some(),
63+
/// "precise correction to {} should be feasible @ {}",
64+
/// ts,
65+
/// t_in);
66+
///
67+
/// let t = Epoch::from_str(t_after).unwrap();
68+
///
69+
/// assert!(db.precise_epoch_correction(t, ts)
70+
/// .is_some(),
71+
/// "precise correction to {} should be feasible @ {}",
72+
/// ts,
73+
/// t_after);
74+
/// }
75+
///
76+
/// // verify that BDT is indeed not available
77+
/// let t_before = "2020-06-24T12:00:00 BDT";
78+
/// let t = Epoch::from_str(t_before).unwrap();
79+
80+
/// assert!(db.precise_epoch_correction(t, TimeScale::GPST)
81+
/// .is_none(),
82+
/// "GPST/BDT is not available!",
83+
/// );
84+
///
85+
/// let t_in = "2020-06-25T12:00:00 BDT";
86+
/// let t = Epoch::from_str(t_in).unwrap();
87+
88+
/// assert!(db.precise_epoch_correction(t, TimeScale::GPST)
89+
/// .is_none(),
90+
/// "GPST/BDT is not available!",
91+
/// );
92+
93+
/// let t_after = "2020-06-26T01:00:00 BDT";
94+
/// let t = Epoch::from_str(t_after).unwrap();
95+
96+
/// assert!(db.precise_epoch_correction(t, TimeScale::GPST)
97+
/// .is_none(),
98+
/// "GPST/BDT is not available!",
99+
/// );
100+
/// ```
101+
#[cfg(all(feature = "nav", feature = "processing"))]
102+
#[cfg_attr(docsrs, doc(cfg(all(feature = "nav", feature = "processing"))))]
103+
pub fn time_corrections_database(&self) -> Option<TimeCorrectionsDB> {
9104
if !self.is_navigation_rinex() {
10105
return None;
11106
}
12107

13-
let mut polynomials = Vec::new();
108+
let mut db = TimeCorrectionsDB::default();
14109

15110
// collect from possible V3 header
16111
let header = self.header.nav.as_ref()?;
17112

113+
let one_day = Duration::from_days(1.0);
114+
18115
for value in header.time_offsets.iter() {
19-
polynomials.push(value.to_time_polynomial());
116+
let ref_epoch = Epoch::from_time_of_week(value.t_ref.0, value.t_ref.1, value.lhs);
117+
118+
let correction = TimeCorrection {
119+
lhs_timescale: value.lhs,
120+
rhs_timescale: value.rhs,
121+
ref_epoch,
122+
validity_period: one_day,
123+
polynomial: value.to_hifitime_polynomial(),
124+
};
125+
126+
db.add(correction);
20127
}
21128

22129
// collect from possible V4 frames
23130
// TODO: don't know how to interprate the ref time
24-
let record = self.record.as_nav()?;
131+
// let record = self.record.as_nav()?;
132+
133+
Some(db)
134+
}
135+
}
136+
137+
#[cfg(test)]
138+
mod test {
139+
use crate::prelude::{Epoch, Rinex, TimeScale};
140+
use std::str::FromStr;
141+
142+
#[test]
143+
fn test_v3_time_corrections_database() {
144+
// This file describes GAGP, GAUT, GPUT (only)
145+
// For example: BDT is not available.
146+
let rinex =
147+
Rinex::from_gzip_file("data/NAV/V3/ESBC00DNK_R_20201770000_01D_MN.rnx.gz").unwrap();
148+
149+
let db = rinex.time_corrections_database().unwrap_or_else(|| {
150+
panic!("Time corrections should exist for V3/BRDC00GOP_R_20210010000_01D_MN.rnx.gz");
151+
});
152+
153+
// In its default form, the database applies without any restriction.
154+
155+
for (t_before, t_in, t_after, ts) in [
156+
(
157+
"2020-06-24T12:00:00 GPST",
158+
"2020-06-25T12:00:00 GPST",
159+
"2020-06-26T01:00:00 GPST",
160+
TimeScale::UTC,
161+
),
162+
(
163+
"2020-06-24T12:00:00 GPST",
164+
"2020-06-25T12:00:00 GPST",
165+
"2020-06-26T01:00:00 GPST",
166+
TimeScale::GST,
167+
),
168+
(
169+
"2020-06-24T12:00:00 GST",
170+
"2020-06-25T12:00:00 GST",
171+
"2020-06-26T01:00:00 GST",
172+
TimeScale::GPST,
173+
),
174+
(
175+
"2020-06-24T12:00:00 UTC",
176+
"2020-06-25T12:00:00 UTC",
177+
"2020-06-26T01:00:00 UTC",
178+
TimeScale::GST,
179+
),
180+
] {
181+
let t = Epoch::from_str(t_before).unwrap();
182+
183+
assert!(
184+
db.precise_epoch_correction(t, ts).is_some(),
185+
"precise correction to {} should be feasible @ {}",
186+
ts,
187+
t_before
188+
);
189+
190+
let t = Epoch::from_str(t_in).unwrap();
191+
192+
assert!(
193+
db.precise_epoch_correction(t, ts).is_some(),
194+
"precise correction to {} should be feasible @ {}",
195+
ts,
196+
t_in
197+
);
198+
199+
let t = Epoch::from_str(t_after).unwrap();
200+
201+
assert!(
202+
db.precise_epoch_correction(t, ts).is_some(),
203+
"precise correction to {} should be feasible @ {}",
204+
ts,
205+
t_after
206+
);
207+
}
208+
209+
// verify that BDT is indeed not available
210+
let t_before = "2020-06-24T12:00:00 BDT";
211+
let t = Epoch::from_str(t_before).unwrap();
212+
213+
assert!(
214+
db.precise_epoch_correction(t, TimeScale::GPST).is_none(),
215+
"GPST/BDT is not available!",
216+
);
217+
218+
let t_in = "2020-06-25T12:00:00 BDT";
219+
let t = Epoch::from_str(t_in).unwrap();
220+
221+
assert!(
222+
db.precise_epoch_correction(t, TimeScale::GPST).is_none(),
223+
"GPST/BDT is not available!",
224+
);
225+
226+
let t_after = "2020-06-26T01:00:00 BDT";
227+
let t = Epoch::from_str(t_after).unwrap();
228+
229+
assert!(
230+
db.precise_epoch_correction(t, TimeScale::GPST).is_none(),
231+
"GPST/BDT is not available!",
232+
);
233+
234+
// Convert to strict database that only propose corrections
235+
// within their respective validity period.
236+
// In NAV V3, V2 (prior V4) the corrections were given in the file header,
237+
// and apply for a 24h time frame.
238+
let _db = db.strict_validity();
25239

26-
Some(GnssAbsoluteTime::new(&polynomials))
240+
// TODO
241+
// // verify that some corrections still apply, but only during
242+
// // that time frame
243+
// for (t_before, t_in, t_after, ts) in [
244+
// (
245+
// "2020-06-24T12:00:00 GPST",
246+
// "2020-06-25T12:00:00 GPST",
247+
// "2020-06-26T01:00:00 GPST",
248+
// TimeScale::UTC,
249+
// ),
250+
// (
251+
// "2020-06-24T12:00:00 GPST",
252+
// "2020-06-25T12:00:00 GPST",
253+
// "2020-06-26T01:00:00 GPST",
254+
// TimeScale::GST,
255+
// ),
256+
// (
257+
// "2020-06-24T12:00:00 GST",
258+
// "2020-06-25T12:00:00 GST",
259+
// "2020-06-26T01:00:00 GST",
260+
// TimeScale::GPST,
261+
// ),
262+
// (
263+
// "2020-06-24T12:00:00 UTC",
264+
// "2020-06-25T12:00:00 UTC",
265+
// "2020-06-26T01:00:00 UTC",
266+
// TimeScale::GST,
267+
// ),
268+
// ] {
269+
// let t = Epoch::from_str(t_before).unwrap();
270+
//
271+
// assert!(db.precise_epoch_correction(t, ts)
272+
// .is_none(),
273+
// "{} correction is not available yet @ {}",
274+
// ts,
275+
// t_before);
276+
//
277+
// let t = Epoch::from_str(t_in).unwrap();
278+
//
279+
// assert!(db.precise_epoch_correction(t, ts)
280+
// .is_some(),
281+
// "precise correction to {} should be feasible @ {}",
282+
// ts,
283+
// t_in);
284+
//
285+
// let t = Epoch::from_str(t_after).unwrap();
286+
//
287+
// assert!(db.precise_epoch_correction(t, ts)
288+
// .is_none(),
289+
// "{} correction is not available past @ {}",
290+
// ts,
291+
// t_after);
292+
// }
27293
}
28294
}

0 commit comments

Comments
 (0)