nyx-space / hifitime Goto Github PK
View Code? Open in Web Editor NEWA high fidelity time management library in Rust
License: Apache License 2.0
A high fidelity time management library in Rust
License: Apache License 2.0
Also specify in docs that the random walk is the more accurate method, but it is very slow.
ClockNoise takes the span as the mean, but that's wrong. The mean of a clock is always zero. The span over which it is defined changes the ppm value.
It's easy to convert, but it'll help to have it as a method of Epoch.
Duration
is not used anywhere in this package anymore and Epoch - Epoch -> f64
. Hence noise_up
should take an f64
representing seconds.
Simulation feature should be default as it will allow it to be documented on docs.rs. I'm also the only one using the crate as a published dependency, so it shouldn't be much a problem to add that: https://crates.io/crates/hifitime/reverse_dependencies .
Following the PyO3 user guide, I shall make a Python package out of hifitime. This will significantly help using this from Python and other libraries.
It should be possible to initialize an Epoch
with a TimeSystem struct. This will allow the implementation of custom systems, cf. https://tycho.usno.navy.mil/systime.html .
The following time systems should be provided:
(cf. https://en.wikipedia.org/wiki/Terrestrial_Time#Approximation )
If a type parameter is a TimeSystem, then one ought to be able to pass it a Datetime or a ModifierJulian or an Instant (sicne the Instant represents an atomic unit of time). This would prevent the following errors:
error[E0277]: the trait bound `od::hifitime::datetime::Instant: od::hifitime::TimeSystem` is not satisfied
--> src/od/ranging.rs:50:23
|
50 | let tx_ecef = State::<ECEF>::from_geodesic(self.latitude, self.longitude, self.height, dt);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `od::hifitime::TimeSystem` is not implemented for `od::hifitime::datetime::Instant`
|
note: required by `<celestia::state::State<celestia::frames::ECEF>>::from_geodesic`
--> src/celestia/state.rs:600:5
|
600| pub fn from_geodesic<T: TimeSystem>(latitude: f64, longitude: f64, height: f64, dt: T) -> State<ECEF> {
Currently ClockNoise only does a timing random walk. However, it should also provide a way to sample a frequency (e.g. what could 2.3 GHz be with this clock).
The PPM should represent a value of seven sigma (effectively a perfect measurement).
Also separate the random walk method, from the frequency sample and the timing sample.
Note that a standard spacecraft clock is about 2 PPM. A high precision ground clock is in PPBs.
The simulation module should include clock drift handling (likely via the new offset system).
It may be easier than I initially thought, examples:
This would help in nyx
. Would have to check if this can be used for easy conversion, e.g. (epoch_1 - epoch2).into<days>() -> f64
;
TCB requires TDB, and the latter is a bit complicated to implement: https://en.wikipedia.org/wiki/Barycentric_Coordinate_Time . I also don't need it right now, so it'll come at a later date.
This should support doing:
1.0 * TimeUnit::Hour
.TimeUnit::Hour / 3
Also add documentation on TimeSeries. It took me a minute to figure it just weeks after 2.0 was released.
This comes from the following encountered use case:
Hence, either the constructor is added solely to MJ, or is it added to Instant. I'm in favor of the latter as I imagine similar use cases will occur with other time systems than MJ.
The clippy
tool notes the following:
warning: this function has too many arguments (8/7)
--> src/datetime.rs:303:5
|
303 | / pub fn with_offset(
304 | | year: i32,
305 | | month: u8,
306 | | day: u8,
... |
342 | | })
343 | | }
| |_____^
|
= note: #[warn(too_many_arguments)] on by default
= help: for further information visit https://rust-lang-nursery.github.io/rust-clippy/v0.0.179/index.html#too_many_arguments
I am looking for idea (or even PRs) which simplify the signature of this function. I initially wanted to code something up similar to chrono
's Datetime<Utc>::new
but that didn't seem like a correct pattern.
Devs may want to format dates differently. As such, it would be useful to support custom formats. My initial guess is that using the same formatting as Python would be useful. It could also be of interest to allow for custom formatters.
While Epoch::maybe_from_gregorian
validates that the nanos
parameter is valid (via is_gregorian_valid
), it does not actually include it in the quantity of seconds used to create the resulting Epoch
.
I suppose the simple fix would be:
diff --git a/src/epoch.rs b/src/epoch.rs
index 1623ce8..ae9870c 100644
--- a/src/epoch.rs
+++ b/src/epoch.rs
@@ -265,7 +265,8 @@ impl Epoch {
seconds_wrt_1900 += TimeUnit::Day * (day - 1)
+ TimeUnit::Hour * hour
+ TimeUnit::Minute * minute
- + TimeUnit::Second * second;
+ + TimeUnit::Second * second
+ + TimeUnit::Nanosecond * nanos;
if second == 60 {
// Herein lies the whole ambiguity of leap seconds. Two different UTC dates exist at the
// same number of second afters J1900.0.
Apologies if there's a reason for limiting this to second resolution that I didn't pick up on.
This will help us use it more easily on an embedded board without worry.
Quote from Matrix.org:
jplatte
xionbox: A good way to start is simply adding #![no_std] to your lib.rs and trying to convert all usages of std to the same things from core. You'll quickly notice whether there's stuff only in std that you depend on directly
Then you have to check all your dependencies to see whether they're all no_std or can be configured as such (often this is simply default-features = false)
There's little more to know beyond that AFAIK
https://github.com/core-error/core-error might be interesting if your library has its own error type(s)
Another potentially useful resource: https://github.com/johnthagen/min-sized-rust
Link to NAIF computation of TDB: https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/FORTRAN/req/time.html#Ephemeris%20Time%20(ET) .
Source data: https://naif.jpl.nasa.gov/pub/naif/pds/data/lro-l-spice-6-v1.0/lrosp_1000/data/lsk/naif0012.tls .
Determine API updates to match SPICE ET (maybe as_et_spice()
).
Re-exports should be a module level to make them easily available (unless specific to the module).
This should support a format similar to SPICE:
let dt = Epoch::from_gregorian_tai_at_midnight(2020, 1, 31);
println!("{}", dt.as_gregorian_utc_tai())
Prints
2020-01-30T23:59:23 TAI
Same with as_gregorian_utc_str
Currently as_et_seconds
uses the ESA computation instead of the 0.000935 second offset. The JDE function should also be using that too.
Use nyx as a validation of the test.
Currently, one can only do Datetime - Duration, and that returns a Datetime. It ought to be possible to do Datetime - Datetime to get a duration. This will be used for propagation times in nyx where we have a start and stop time.
hifitime::MyTimeSystem::Offset() -> hifitime::Offset
and the Offset struct defined as described above?hifitime::ModifiedJulian::from<f64>(245...) -> hifitime::Instant
+
and its assignment counterpart for hifitime::Instant and hifitime::Offset such that an instant plus an offset returns another instant.-
and its assignment counterpart for two hifitime::Offset
s to return another Offset.-
and its assignment counterpart for two hifitime::Instant
s to return an Offset.The durations crate is a simpler implementation of the constructors as needed, cf. https://github.com/newpavlov/durations-rs .
Currently, TimeZone
s aren't trivial to handle, as evident in tests/tz.rs
. Even making an impl
macro, as demonstrated here is not easy from that implementation.
It should be easy to convert a Utc to any other time zone object.
I guess that there needs to be some "generic date time container struct" which would house to computed date time with the computed offset, allowing for easy back and forth computations. Moreover, I don't think it's a great idea to require each TimeZone
implementation to also implement fmt::Display
: they will all be very similar so there needs to be a simple way to do this...
pub fn as_gregorian_utc_tai(&self) -> String
should be pub fn as_gregorian_tai_str(&self) -> String
This should return another Utc
. This will be needed to support loops over time, such as:
let mut current = Utc::new(/*...*/);
let end = Utc::new(/*...*/);
while current < end {
/* do stuff */
current += std::time::Duration(1, 0) // Or current += 1*SECOND
}
Eventually also include in this PR some short cuts such as:
hifitime::constants::{DAY, HOUR, MINUTE, SECOND, MICROSECOND, NANOSECOND};
Note that these short cut will need to support multiplications with floats and unsigned integers to make it useful. This may require some custom implementation such as hifitime::StdDuration::from_hours()
or hifitime::StdDuration::from_seconds(10)
. I am pretty sure I cannot just use hifitime::Duration
since it's re-exported.
This could be represented as a tuple of u64 or even u128 ?!
I cannot match SPICE ephemeris data otherwise, cf. https://gitlab.com/chrisrabotin/nyx/issues/70 .
This is helpful to support human-time which isn't UTC.
As I'm porting Nyx to hifitime 2, there are additional changes which will greatly simplify the clarity of the code.
The function should be as_gregorian_utc
. I do not think there should be a as_gregorian_tai
because that's confusing: no one needs a TAI date if it's in Gregorian...
Currently, to add seconds to an existing Epoch, one must do the following:
let mut end_time = start_time;
end_time.mut_add_secs(prop_time);
That's just annoying. I have use for, where prop_time would be an f64
.
let end_time = start_time + prop_time
It should be possible to parse a date time from a string
This could be useful as a shortcut to handle dates only instead of always handling date times. My initial guess is that this can be written as a separate TimeSystem, but I'm not sure yet.
Utc::at_noon(year, month, day)
Utc::at_midnight(year, month, day)
There is currently a conversion error between TAI and UTC. In the current implementation TAI is behind UTC by 37 seconds, when in fact it should be ahead of it: http://leapsecond.com/java/gpsclock.htm .
let now_tai = Epoch::from_gregorian_tai(2019, 8, 1, 20, 0, 0, 0);
let now_utc = Epoch::from_gregorian_tai(2019, 8, 1, 20, 0, 0, 0);
println!("{}", now_tai.as_tai_seconds() - now_utc.as_tai_seconds());
Returns: -37
Returns: 0
because (same function call)
Based on the KiloTZ test, it should be possible to provide a simple fixed offset time zone. Global time zones are only set by quarter hour at most, so maybe use a naming convention similar to chrono?
let ex1 = FixedOffset::east::from_hours(5).and_mins(15);
let ex2 = FixedOffset::east::from_mins(5);
let ex3 = FixedOffset::west::from_secs(5);
I need to think about this because I'm not a huge fan of chrono's naming convention in the first place.
There is UT1, UTC, TAI, GPS Time julian days. It should be clear that the current version is the UTC. TAI and GPS should also be supported (these are the same as UTC with less or no leap seconds and some extra offset for TAI).
This is important as some simulation systems might not include all of the leap seconds. This is needed for validation of astrodynamics computations.
This should return a f64 which corresponds to the number of seconds between both Instants. That number can be positive or negative.
As I'm about to use this for nyx
in the State
definition, I realized that I need to support Copy, Clone and Display to truly take advantage of TimeSystem
.
Might be complicated to make it work on all platforms though. I'm also not 100% it adds enough value just yet.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.