Skip to content

Commit bb69de2

Browse files
authored
Absolute time (#17)
* Improve GnssAbsoluteTime and publication management --------- Signed-off-by: Guillaume W. Bres <[email protected]>
1 parent 0fabfde commit bb69de2

File tree

2 files changed

+215
-93
lines changed

2 files changed

+215
-93
lines changed

src/processing/time/absolute.rs

Lines changed: 199 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,25 @@
1-
use super::TimePolynomial;
1+
use crate::{
2+
merge::{Error as MergeError, Merge},
3+
processing::TimePolynomial,
4+
};
25

3-
use hifitime::{Duration, Epoch, TimeScale};
6+
use hifitime::{Epoch, TimeScale};
47

58
#[cfg(doc)]
69
use super::Timeshift;
710

811
/// [GnssAbsoluteTime] is used by applications that need to precisely describe
912
/// the actual state of one or several [TimeScale]s. It is used in our [Timeshift] trait
1013
/// to allow precise [TimeScale] transposition.
11-
#[derive(Default)]
14+
/// [GnssAbsoluteTime] does not guard about "bad" operations:
15+
/// - You are responsible for the [TimePolynomial] you store with respect of the
16+
/// current time.
17+
/// - We have no means to consider [TimePolynomial]s are now outdated.
18+
/// You should always maintain [GnssAbsoluteTime] with up to date polynomials.
19+
/// To avoid memory growth in very long surveying, we propose:
20+
/// - [GnssAbsoluteTime::outdate_past] to declare past [TimePolynomial]s as outdated
21+
/// - and [GnssAbsoluteTime::outdate_weekly] to discard [TimePolynomial]s published before that week
22+
#[derive(Default, Clone)]
1223
pub struct GnssAbsoluteTime {
1324
/// Internal [TimePolynomial]s
1425
polynomials: Vec<TimePolynomial>,
@@ -22,16 +33,25 @@ impl GnssAbsoluteTime {
2233
}
2334
}
2435

25-
/// Add a new [TimePolynomial] to this management pool.
26-
/// Usually right after its publication.
27-
pub fn add_polynomial(&mut self, polynomial: TimePolynomial) {
28-
self.polynomials.retain(|poly| {
29-
let same_ref = poly.ref_epoch.time_scale == polynomial.ref_epoch.time_scale;
36+
/// Discard [TimePolynomial]s that were published prior "now".
37+
/// You must have latched newer [TimePolynomial]s with [Self::add_polynomial] for the structure to remain valid.
38+
pub fn outdate_past(&mut self, now: Epoch) {
39+
self.polynomials.retain(|poly| poly.ref_epoch > now);
40+
}
3041

31-
let same_lhs = poly.ref_epoch.time_scale == polynomial.ref_epoch.time_scale;
32-
!(same_ref && same_lhs)
42+
/// Discard [TimePolynomial]s that were published during past week from "now".
43+
/// You must have latched newer [TimePolynomial]s with [Self::add_polynomial] for the structure to remain valid.
44+
pub fn outdate_weekly(&mut self, now: Epoch) {
45+
let new_week = now.to_time_of_week().0;
46+
self.polynomials.retain(|poly| {
47+
let tow = poly.ref_epoch.to_time_of_week().0;
48+
tow >= new_week
3349
});
50+
}
3451

52+
/// Add a new [TimePolynomial] to this management pool.
53+
/// Usually right after its publication.
54+
pub fn add_polynomial(&mut self, polynomial: TimePolynomial) {
3555
self.polynomials.push(polynomial);
3656
}
3757

@@ -45,7 +65,17 @@ impl GnssAbsoluteTime {
4565
if let Some(poly) = self
4666
.polynomials
4767
.iter()
48-
.find(|poly| poly.lhs_timescale == t.time_scale && poly.rhs_timescale == target)
68+
.filter_map(|poly| {
69+
if poly.lhs_timescale == t.time_scale && poly.rhs_timescale == target {
70+
Some(poly)
71+
} else {
72+
None
73+
}
74+
})
75+
.min_by_key(|poly| {
76+
let transposed = t.to_time_scale(poly.lhs_timescale);
77+
transposed - poly.ref_epoch
78+
})
4979
{
5080
Some(
5181
t.precise_timescale_conversion(true, poly.ref_epoch, poly.polynomial, target)
@@ -54,95 +84,171 @@ impl GnssAbsoluteTime {
5484
} else if let Some(poly) = self
5585
.polynomials
5686
.iter()
57-
.find(|poly| poly.rhs_timescale == t.time_scale && poly.lhs_timescale == target)
87+
.filter_map(|poly| {
88+
if poly.lhs_timescale == target && poly.rhs_timescale == t.time_scale {
89+
Some(poly)
90+
} else {
91+
None
92+
}
93+
})
94+
.min_by_key(|poly| {
95+
let transposed = t.to_time_scale(poly.lhs_timescale);
96+
transposed - poly.ref_epoch
97+
})
5898
{
5999
Some(
60100
t.precise_timescale_conversion(false, poly.ref_epoch, poly.polynomial, target)
61101
.unwrap(),
62102
)
63103
} else {
64-
for lhs_poly in self.polynomials.iter() {
65-
for rhs_poly in self.polynomials.iter() {
66-
if lhs_poly.lhs_timescale == t.time_scale && rhs_poly.rhs_timescale == target {
67-
// indirect forward transforms
68-
69-
// |BDT-GST|=a0_bdt & |GST-GPST|=a1 dt_gst
70-
// GST=BDT-a0_bdt
71-
// BDT-a0 dt_bdt - GPST = a1 dt_gpst
72-
// BDT-GPST (foward indirect) = a1 dt_gpst + a0 dt_bdt
73-
74-
let dt_lhs_s = (t.to_time_scale(lhs_poly.lhs_timescale)
75-
- lhs_poly.ref_epoch)
76-
.to_seconds();
77-
let dt_rhs_s = (t.to_time_scale(rhs_poly.lhs_timescale)
78-
- rhs_poly.ref_epoch)
79-
.to_seconds();
80-
81-
let mut correction = lhs_poly.polynomial.constant.to_seconds()
82-
+ lhs_poly.polynomial.rate.to_seconds() * dt_lhs_s
83-
+ lhs_poly.polynomial.accel.to_seconds() * dt_lhs_s.powi(2);
84-
85-
// println!("correction = {}", correction);
86-
87-
correction += rhs_poly.polynomial.constant.to_seconds()
88-
+ rhs_poly.polynomial.rate.to_seconds() * dt_rhs_s
89-
+ rhs_poly.polynomial.accel.to_seconds() * dt_rhs_s.powi(2);
90-
91-
// println!("total correction = {}", correction);
92-
93-
return Some(
94-
t.to_time_scale(rhs_poly.rhs_timescale)
95-
- Duration::from_seconds(correction),
96-
);
97-
} else if lhs_poly.rhs_timescale == t.time_scale
98-
&& rhs_poly.rhs_timescale == target
99-
{
100-
// indirect backward + forward transforms
101-
} else if lhs_poly.lhs_timescale == t.time_scale
102-
&& rhs_poly.lhs_timescale == target
103-
{
104-
// indirect forward + backward transforms
105-
} else if lhs_poly.rhs_timescale == t.time_scale
106-
&& rhs_poly.lhs_timescale == target
107-
{
108-
// indirect backward transforms
109-
110-
// |BDT-GST|=a0_bdt & |GST-GPST|=a1 dt_gst
111-
// BDT = a0_bdt + GST
112-
// GPST = GST -a1 dt_gpst
113-
// GPST-BDT (backward indirect) = -a1 -a0
114-
115-
let dt_lhs_s = (t.to_time_scale(lhs_poly.lhs_timescale)
116-
- lhs_poly.ref_epoch)
117-
.to_seconds();
118-
let dt_rhs_s = (t.to_time_scale(rhs_poly.lhs_timescale)
119-
- rhs_poly.ref_epoch)
120-
.to_seconds();
121-
122-
let correction_a = lhs_poly.polynomial.constant.to_seconds()
123-
+ lhs_poly.polynomial.rate.to_seconds() * dt_lhs_s
124-
+ lhs_poly.polynomial.accel.to_seconds() * dt_lhs_s.powi(2);
125-
126-
// println!("correction = {}", correction_a);
127-
128-
let correction_b = rhs_poly.polynomial.constant.to_seconds()
129-
+ rhs_poly.polynomial.rate.to_seconds() * dt_rhs_s
130-
+ rhs_poly.polynomial.accel.to_seconds() * dt_rhs_s.powi(2);
131-
132-
// println!("correction = {}", correction_b);
133-
134-
return Some(
135-
t.to_time_scale(rhs_poly.lhs_timescale)
136-
+ Duration::from_seconds(correction_a)
137-
+ Duration::from_seconds(correction_b),
138-
);
139-
}
140-
}
141-
}
142-
104+
// mixed combinations not supported yet
143105
None
144106
}
145107
}
108+
109+
// else if let Some(poly) = self
110+
// .polynomials
111+
// .iter()
112+
// .filter(|poly| {
113+
// if poly.lhs_timescale == t.time_scale {
114+
// Some(poly)
115+
// } else {
116+
// None
117+
// }
118+
// })
119+
// .min_by_key(|poly| {
120+
// let transposed = t.to_time_scale(poly.lhs_timescale);
121+
// transposed - poly.ref_epoch
122+
// })
123+
// {
124+
// // got a forward (1) proposal
125+
// if let Some(poly) = self
126+
// .polynomials
127+
// .iter()
128+
// .filter(|poly| {
129+
// if poly.rhs_timescale == target {
130+
// Some(poly)
131+
// } else {
132+
// None
133+
// }
134+
// })
135+
// .min_by_key(|poly| {
136+
// let transposed = t.to_time_scale(poly.lhs_timescale);
137+
// transposed - poly.ref_epoch
138+
// })
139+
// {
140+
// // got a forward (2) proposal
141+
// } else {
142+
// // got a backward (2) proposal
143+
// None
144+
// }
145+
// } else {
146+
// None
147+
// }
148+
// Some(
149+
// t.precise_timescale_conversion(true, poly.ref_epoch, poly.polynomial, target)
150+
// .unwrap(),
151+
// )
152+
153+
// for lhs_poly in self.polynomials.iter() {
154+
// for rhs_poly in self.polynomials.iter() {
155+
// if lhs_poly.lhs_timescale == t.time_scale && rhs_poly.rhs_timescale == target {
156+
// // indirect forward transforms
157+
158+
// // |BDT-GST|=a0_bdt & |GST-GPST|=a1 dt_gst
159+
// // GST=BDT-a0_bdt
160+
// // BDT-a0 dt_bdt - GPST = a1 dt_gpst
161+
// // BDT-GPST (foward indirect) = a1 dt_gpst + a0 dt_bdt
162+
163+
// let dt_lhs_s = (t.to_time_scale(lhs_poly.lhs_timescale)
164+
// - lhs_poly.ref_epoch)
165+
// .to_seconds();
166+
167+
// let dt_rhs_s = (t.to_time_scale(rhs_poly.lhs_timescale)
168+
// - rhs_poly.ref_epoch)
169+
// .to_seconds();
170+
171+
// let mut correction = lhs_poly.polynomial.constant.to_seconds()
172+
// + lhs_poly.polynomial.rate.to_seconds() * dt_lhs_s
173+
// + lhs_poly.polynomial.accel.to_seconds() * dt_lhs_s.powi(2);
174+
175+
// // println!("correction = {}", correction);
176+
177+
// correction += rhs_poly.polynomial.constant.to_seconds()
178+
// + rhs_poly.polynomial.rate.to_seconds() * dt_rhs_s
179+
// + rhs_poly.polynomial.accel.to_seconds() * dt_rhs_s.powi(2);
180+
181+
// // println!("total correction = {}", correction);
182+
183+
// return Some(t.to_time_scale(target) - Duration::from_seconds(correction));
184+
// } else if lhs_poly.rhs_timescale == t.time_scale
185+
// && rhs_poly.rhs_timescale == target
186+
// {
187+
// // indirect backward + forward transforms
188+
// } else if lhs_poly.lhs_timescale == t.time_scale
189+
// && rhs_poly.lhs_timescale == target
190+
// {
191+
// // indirect forward + backward transforms
192+
// } else if lhs_poly.rhs_timescale == t.time_scale
193+
// && rhs_poly.lhs_timescale == target
194+
// {
195+
// // indirect backward transforms
196+
197+
// // |BDT-GST|=a0_bdt & |GST-GPST|=a1 dt_gst
198+
// // BDT = a0_bdt + GST
199+
// // GPST = GST -a1 dt_gpst
200+
// // GPST-BDT (backward indirect) = -a1 -a0
201+
202+
// let dt_lhs_s = (t.to_time_scale(lhs_poly.lhs_timescale)
203+
// - lhs_poly.ref_epoch)
204+
// .to_seconds();
205+
206+
// let dt_rhs_s = (t.to_time_scale(rhs_poly.lhs_timescale)
207+
// - rhs_poly.ref_epoch)
208+
// .to_seconds();
209+
210+
// let correction_a = lhs_poly.polynomial.constant.to_seconds()
211+
// + lhs_poly.polynomial.rate.to_seconds() * dt_lhs_s
212+
// + lhs_poly.polynomial.accel.to_seconds() * dt_lhs_s.powi(2);
213+
214+
// // println!("correction = {}", correction_a);
215+
216+
// let correction_b = rhs_poly.polynomial.constant.to_seconds()
217+
// + rhs_poly.polynomial.rate.to_seconds() * dt_rhs_s
218+
// + rhs_poly.polynomial.accel.to_seconds() * dt_rhs_s.powi(2);
219+
220+
// // println!("correction = {}", correction_b);
221+
222+
// return Some(
223+
// t.to_time_scale(target)
224+
// + Duration::from_seconds(correction_a)
225+
// + Duration::from_seconds(correction_b),
226+
// );
227+
// }
228+
// }
229+
// }
230+
231+
// None
232+
}
233+
234+
impl Merge for GnssAbsoluteTime {
235+
fn merge(&self, rhs: &Self) -> Result<Self, MergeError>
236+
where
237+
Self: Sized,
238+
{
239+
let mut s = self.clone();
240+
s.merge_mut(rhs)?;
241+
242+
Ok(s)
243+
}
244+
245+
fn merge_mut(&mut self, rhs: &Self) -> Result<(), MergeError> {
246+
// latch new polynomials
247+
for polynomial in rhs.polynomials.iter() {
248+
self.add_polynomial(*polynomial);
249+
}
250+
Ok(())
251+
}
146252
}
147253

148254
#[cfg(test)]
@@ -203,6 +309,7 @@ mod test {
203309
}
204310

205311
#[test]
312+
#[ignore]
206313
fn test_indirect_forward_transform_not_utc() {
207314
let t_ref_bdt = Epoch::from_str("2020-01-01T00:00:00 BDT").unwrap();
208315
let t_ref_gst = Epoch::from_str("2020-01-01T00:00:00 GST").unwrap();
@@ -313,6 +420,7 @@ mod test {
313420
}
314421

315422
#[test]
423+
#[ignore]
316424
fn test_indirect_forward_transform_utc() {
317425
let t_ref_bdt = Epoch::from_str("2020-01-01T00:00:00 BDT").unwrap();
318426
//let t_ref_gst = Epoch::from_str("2020-01-01T00:00:00 GST").unwrap();

src/processing/time/polynomial.rs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ use hifitime::{Epoch, Polynomial, TimeScale};
44
/// For example, |[TimeScale::GPST]-[TimeScale::UTC]| when referencing [TimeScale::GPST] to [TimeScale::UTC].
55
#[derive(Copy, Clone, PartialEq)]
66
pub struct TimePolynomial {
7-
/// LHS [TimeScale] to which the [Polynomial] applies
7+
/// LHS [TimeScale] to which [Polynomial] applies
88
pub lhs_timescale: TimeScale,
9-
/// RHS [TimeScale] to which the [Polynomial] applies
9+
/// RHS [TimeScale] to which [Polynomial] applies
1010
pub rhs_timescale: TimeScale,
1111
/// Reference [Epoch] usually expressed in LHS [TimeScale], but we support any [TimeScale] here.
1212
pub ref_epoch: Epoch,
@@ -33,6 +33,20 @@ impl TimePolynomial {
3333
)
3434
}
3535

36+
/// Define new [TimePolynomial] from reference [Epoch] that must be expressed in the correct [TimeScale]
37+
pub fn from_reference_epoch(
38+
ref_epoch: Epoch,
39+
rhs_timescale: TimeScale,
40+
polynomial: Polynomial,
41+
) -> Self {
42+
Self {
43+
ref_epoch,
44+
lhs_timescale: ref_epoch.time_scale,
45+
rhs_timescale,
46+
polynomial,
47+
}
48+
}
49+
3650
/// Define a new [TimePolynomials] from Reference [Epoch] expressed as week counter and
3751
/// elapsed nanoseconds within week.
3852
pub fn from_reference_time_of_week_nanos(

0 commit comments

Comments
 (0)