Skip to content

Commit e5b4100

Browse files
committed
nyx: attempt at creating a propagation method
Signed-off-by: Guillaume W. Bres <guillaume.bressaix@gmail.com>
1 parent f5ed59c commit e5b4100

File tree

3 files changed

+110
-2
lines changed

3 files changed

+110
-2
lines changed

Cargo.toml

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ all-features = true
2323
rustdoc-args = ["--cfg", "docrs", "--generate-link-to-definition"]
2424

2525
[features]
26-
default = ["flate2"] # gzip files by default
26+
default = ["flate2", "nyx-space"] # gzip files by default
2727

2828
# File Merging and other high level methods
2929
qc = [
@@ -36,13 +36,20 @@ processing = [
3636
"gnss-qc-traits/processing",
3737
]
3838

39+
# Unlock nyx-spae propagators for SP3 prediction
40+
nyx-space = [
41+
"dep:anise",
42+
"dep:nyx-space",
43+
]
44+
3945
[dependencies]
4046
thiserror = "2"
4147
itertools = "0.14"
42-
anise = { version = "0.6", optional = true }
48+
anise = { version = "0.6", optional = true, features = ["embed_ephem"] }
4349
gnss-rs = { version = "2.4.0", features = ["serde"] }
4450
gnss-qc-traits = { version = "0.3.1", optional = true }
4551
hifitime = { version = "4.1", features = ["serde", "std"] }
52+
nyx-space = { git = "https://github.com/nyx-space/nyx", rev = "a0a4638a8b53302f832791c0d7a26bc64e3166ea", optional = true }
4653

4754
flate2 = { version = "1", optional = true, default-features = false, features = ["zlib"] }
4855
serde = { version = "1.0", optional = true, default-features = false, features = ["derive"] }

src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ mod qc;
3434
#[cfg_attr(docsrs, doc(cfg(feature = "processing")))]
3535
mod processing;
3636

37+
#[cfg(feature = "nyx-space")]
38+
#[cfg_attr(docsrs, doc(cfg(feature = "nyx-space")))]
39+
mod nyx;
40+
3741
#[cfg(feature = "anise")]
3842
use anise::{
3943
astro::AzElRange,

src/nyx.rs

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
use crate::prelude::{Duration, Epoch, SP3, SV};
2+
3+
use anise::{
4+
constants::{
5+
celestial_objects::{MOON, SUN},
6+
frames::{EARTH_J2000, MOON_J2000},
7+
},
8+
prelude::Almanac,
9+
};
10+
11+
use std::{collections::BTreeMap, sync::Arc};
12+
13+
use nyx_space::{
14+
dynamics::{OrbitalDynamics, SolarPressure, SpacecraftDynamics},
15+
od::{kalman::KalmanVariant, SpacecraftKalmanOD},
16+
propagators::{IntegratorOptions, Propagator},
17+
};
18+
19+
impl SP3 {
20+
/// Propagate this [SP3] into the future, returning a new extended [SP3].
21+
/// Refer to [Self::propagate_mut] for more information.
22+
pub fn propagate(&self, almanac: Arc<Almanac>, prediction_duration: Duration) -> Self {
23+
let mut s = self.clone();
24+
s.propagate_mut(almanac, prediction_duration);
25+
s
26+
}
27+
28+
/// Propagate this (entire) [SP3] in the future, using [Propagator::dp78]
29+
/// and mutable access.
30+
///
31+
/// ## Input
32+
/// - almanac: [Almanac]
33+
/// - prediction_duration: [Duration] of the prediction
34+
pub fn propagate_mut(&mut self, almanac: Arc<Almanac>, prediction_duration: Duration) {
35+
let opts = IntegratorOptions::with_fixed_step(self.header.sampling_period);
36+
37+
let orbital_model = OrbitalDynamics::point_masses(vec![MOON, SUN]);
38+
39+
let srp_model = SolarPressure::new(vec![EARTH_J2000, MOON_J2000], almanac.clone())
40+
.unwrap_or_else(|e| {
41+
// TODO replace with proper error
42+
panic!("failed to build solar pressure model: {}", e);
43+
});
44+
45+
let dynamics = SpacecraftDynamics::from_model(orbital_model, srp_model);
46+
47+
// Propagates each satellite, arming the propagator using last described precise position.
48+
// There should be better approach by taking all the data set into account, reducing the propagtion error.
49+
let last_epoch = self.last_epoch().expect("empty data set"); // TODO replace with proper error
50+
51+
let final_states = self
52+
.data
53+
.iter()
54+
.filter(|(k, v)| k.epoch == last_epoch)
55+
.collect::<Vec<_>>();
56+
57+
// Create a propagator that uses the same model
58+
let setup = Propagator::dp78(dynamics, opts);
59+
60+
for (k, v) in final_states.iter() {
61+
// Deploy a process
62+
let mut odp = SpacecraftKalmanOD::new(
63+
setup.clone(),
64+
KalmanVariant::DeviationTracking,
65+
None,
66+
BTreeMap::new(),
67+
almanac.clone(),
68+
);
69+
}
70+
}
71+
}
72+
73+
#[cfg(test)]
74+
mod test {
75+
use crate::prelude::{Duration, Epoch, Split, SP3};
76+
use anise::prelude::Almanac;
77+
use std::str::FromStr;
78+
use std::sync::Arc;
79+
80+
#[test]
81+
fn test_nyx_propagator() {
82+
let almanac = Arc::new(Almanac::until_2035().unwrap());
83+
84+
// entire setup
85+
let parsed =
86+
SP3::from_gzip_file("data/SP3/C/GRG0MGXFIN_20201770000_01D_15M_ORB.SP3.gz").unwrap();
87+
88+
// grab first 12 hours, propagate last 12 hours,
89+
let noon = Epoch::from_str("2020-06-25T12:00:00 GPST").unwrap();
90+
let (sp3_morning, _) = parsed.split(noon);
91+
92+
let predicted = sp3_morning.propagate(almanac, Duration::from_hours(12.0));
93+
94+
// compare
95+
let residuals = predicted.substract(&parsed);
96+
}
97+
}

0 commit comments

Comments
 (0)