pub struct KfEstimate<T: State>where
DefaultAllocator: Allocator<<T as State>::Size> + Allocator<<T as State>::Size, <T as State>::Size> + Allocator<<T as State>::VecLength>,
<DefaultAllocator as Allocator<<T as State>::Size>>::Buffer<f64>: Copy,
<DefaultAllocator as Allocator<<T as State>::Size, <T as State>::Size>>::Buffer<f64>: Copy,{
pub nominal_state: T,
pub state_deviation: OVector<f64, <T as State>::Size>,
pub covar: OMatrix<f64, <T as State>::Size, <T as State>::Size>,
pub covar_bar: OMatrix<f64, <T as State>::Size, <T as State>::Size>,
pub predicted: bool,
pub stm: OMatrix<f64, <T as State>::Size, <T as State>::Size>,
}Expand description
Kalman filter Estimate
Fields§
§nominal_state: TThe estimated state
state_deviation: OVector<f64, <T as State>::Size>The state deviation
covar: OMatrix<f64, <T as State>::Size, <T as State>::Size>The Covariance of this estimate
covar_bar: OMatrix<f64, <T as State>::Size, <T as State>::Size>The predicted covariance of this estimate
predicted: boolWhether or not this is a predicted estimate from a time update, or an estimate from a measurement
stm: OMatrix<f64, <T as State>::Size, <T as State>::Size>The STM used to compute this Estimate
Implementations§
Source§impl<T: State> KfEstimate<T>where
DefaultAllocator: Allocator<<T as State>::Size> + Allocator<<T as State>::Size, <T as State>::Size> + Allocator<<T as State>::VecLength>,
<DefaultAllocator as Allocator<<T as State>::Size>>::Buffer<f64>: Copy,
<DefaultAllocator as Allocator<<T as State>::Size, <T as State>::Size>>::Buffer<f64>: Copy,
impl<T: State> KfEstimate<T>where
DefaultAllocator: Allocator<<T as State>::Size> + Allocator<<T as State>::Size, <T as State>::Size> + Allocator<<T as State>::VecLength>,
<DefaultAllocator as Allocator<<T as State>::Size>>::Buffer<f64>: Copy,
<DefaultAllocator as Allocator<<T as State>::Size, <T as State>::Size>>::Buffer<f64>: Copy,
Source§impl KfEstimate<Spacecraft>
impl KfEstimate<Spacecraft>
Sourcepub fn disperse_from_diag(
nominal_state: Spacecraft,
dispersions: Vec<StateDispersion>,
seed: Option<u128>,
) -> Result<Self, Box<dyn Error>>
pub fn disperse_from_diag( nominal_state: Spacecraft, dispersions: Vec<StateDispersion>, seed: Option<u128>, ) -> Result<Self, Box<dyn Error>>
Generates an initial Kalman filter state estimate dispersed from the nominal state using the provided standard deviation parameters.
The resulting estimate will have a diagonal covariance matrix constructed from the variances of each parameter. Limitation: This method may not work correctly for all Keplerian orbital elements, refer to https://github.com/nyx-space/nyx/issues/339 for details.
Sourcepub fn to_random_variable(&self) -> Result<MvnSpacecraft, Box<dyn Error>>
pub fn to_random_variable(&self) -> Result<MvnSpacecraft, Box<dyn Error>>
Builds a multivariate random variable from this estimate’s nominal state and covariance, zero mean.
Examples found in repository?
26fn main() -> Result<(), Box<dyn Error>> {
27 pel::init();
28 // Dynamics models require planetary constants and ephemerides to be defined.
29 // Let's start by grabbing those by using ANISE's latest MetaAlmanac.
30 // For details, refer to https://github.com/nyx-space/anise/blob/master/data/latest.dhall.
31
32 // Download the regularly update of the James Webb Space Telescope reconstucted (or definitive) ephemeris.
33 // Refer to https://naif.jpl.nasa.gov/pub/naif/JWST/kernels/spk/aareadme.txt for details.
34 let mut latest_jwst_ephem = MetaFile {
35 uri: "https://naif.jpl.nasa.gov/pub/naif/JWST/kernels/spk/jwst_rec.bsp".to_string(),
36 crc32: None,
37 };
38 latest_jwst_ephem.process(true)?;
39
40 // Load this ephem in the general Almanac we're using for this analysis.
41 let almanac = Arc::new(
42 MetaAlmanac::latest()
43 .map_err(Box::new)?
44 .load_from_metafile(latest_jwst_ephem, true)?,
45 );
46
47 // By loading this ephemeris file in the ANISE GUI or ANISE CLI, we can find the NAIF ID of the JWST
48 // in the BSP. We need this ID in order to query the ephemeris.
49 const JWST_NAIF_ID: i32 = -170;
50 // Let's build a frame in the J2000 orientation centered on the JWST.
51 const JWST_J2000: Frame = Frame::from_ephem_j2000(JWST_NAIF_ID);
52
53 // Since the ephemeris file is updated regularly, we'll just grab the latest state in the ephem.
54 let (earliest_epoch, latest_epoch) = almanac.spk_domain(JWST_NAIF_ID)?;
55 println!("JWST defined from {earliest_epoch} to {latest_epoch}");
56 // Fetch the state, printing it in the Earth J2000 frame.
57 let jwst_orbit = almanac.transform(JWST_J2000, EARTH_J2000, latest_epoch, None)?;
58 println!("{jwst_orbit:x}");
59
60 // Build the spacecraft
61 // SRP area assumed to be the full sunshield and mass if 6200.0 kg, c.f. https://webb.nasa.gov/content/about/faqs/facts.html
62 // SRP Coefficient of reflectivity assumed to be that of Kapton, i.e. 2 - 0.44 = 1.56, table 1 from https://amostech.com/TechnicalPapers/2018/Poster/Bengtson.pdf
63 let jwst = Spacecraft::builder()
64 .orbit(jwst_orbit)
65 .srp(SRPData {
66 area_m2: 21.197 * 14.162,
67 coeff_reflectivity: 1.56,
68 })
69 .mass(Mass::from_dry_mass(6200.0))
70 .build();
71
72 // Build up the spacecraft uncertainty builder.
73 // We can use the spacecraft uncertainty structure to build this up.
74 // We start by specifying the nominal state (as defined above), then the uncertainty in position and velocity
75 // in the RIC frame. We could also specify the Cr, Cd, and mass uncertainties, but these aren't accounted for until
76 // Nyx can also estimate the deviation of the spacecraft parameters.
77 let jwst_uncertainty = SpacecraftUncertainty::builder()
78 .nominal(jwst)
79 .frame(LocalFrame::RIC)
80 .x_km(0.5)
81 .y_km(0.3)
82 .z_km(1.5)
83 .vx_km_s(1e-4)
84 .vy_km_s(0.6e-3)
85 .vz_km_s(3e-3)
86 .build();
87
88 println!("{jwst_uncertainty}");
89
90 // Build the Kalman filter estimate.
91 // Note that we could have used the KfEstimate structure directly (as seen throughout the OD integration tests)
92 // but this approach requires quite a bit more boilerplate code.
93 let jwst_estimate = jwst_uncertainty.to_estimate()?;
94
95 // Set up the spacecraft dynamics.
96 // We'll use the point masses of the Earth, Sun, Jupiter (barycenter, because it's in the DE440), and the Moon.
97 // We'll also enable solar radiation pressure since the James Webb has a huge and highly reflective sun shield.
98
99 let orbital_dyn = OrbitalDynamics::point_masses(vec![MOON, SUN, JUPITER_BARYCENTER]);
100 let srp_dyn = SolarPressure::new(vec![EARTH_J2000, MOON_J2000], almanac.clone())?;
101
102 // Finalize setting up the dynamics.
103 let dynamics = SpacecraftDynamics::from_model(orbital_dyn, srp_dyn);
104
105 // Build the propagator set up to use for the whole analysis.
106 let setup = Propagator::default(dynamics);
107
108 // All of the analysis will use this duration.
109 let prediction_duration = 6.5 * Unit::Day;
110
111 // === Covariance mapping ===
112 // For the covariance mapping / prediction, we'll use the common orbit determination approach.
113 // This is done by setting up a spacecraft Kalman filter OD process, and predicting for the analysis duration.
114
115 // Build the propagation instance for the OD process.
116 let odp = SpacecraftKalmanOD::new(
117 setup.clone(),
118 KalmanVariant::DeviationTracking,
119 None,
120 BTreeMap::new(),
121 almanac.clone(),
122 );
123
124 // The prediction step is 1 minute by default, configured in the OD process, i.e. how often we want to know the covariance.
125 assert_eq!(odp.max_step, 1_i64.minutes());
126 // Finally, predict, and export the trajectory with covariance to a parquet file.
127 let od_sol = odp.predict_for(jwst_estimate, prediction_duration)?;
128 od_sol.to_parquet("./02_jwst_covar_map.parquet", ExportCfg::default())?;
129
130 // === Monte Carlo framework ===
131 // Nyx comes with a complete multi-threaded Monte Carlo frame. It's blazing fast.
132
133 let my_mc = MonteCarlo::new(
134 jwst, // Nominal state
135 jwst_estimate.to_random_variable()?,
136 "02_jwst".to_string(), // Scenario name
137 None, // No specific seed specified, so one will be drawn from the computer's entropy.
138 );
139
140 let num_runs = 5_000;
141 let rslts = my_mc.run_until_epoch(
142 setup,
143 almanac.clone(),
144 jwst.epoch() + prediction_duration,
145 num_runs,
146 );
147
148 assert_eq!(rslts.runs.len(), num_runs);
149 // Finally, export these results, computing the eclipse percentage for all of these results.
150
151 rslts.to_parquet("02_jwst_monte_carlo.parquet", ExportCfg::default())?;
152
153 Ok(())
154}Sourcepub fn sigma_for(&self, param: OrbitalElement) -> Result<f64, AstroError>
pub fn sigma_for(&self, param: OrbitalElement) -> Result<f64, AstroError>
Returns the 1-sigma uncertainty for a given parameter, in that parameter’s unit
This method uses the [OrbitDual] structure to compute the estimate in the hyperdual space and rotate the nominal covariance into that space.
Sourcepub fn keplerian_covar(&self) -> SMatrix<f64, 6, 6>
pub fn keplerian_covar(&self) -> SMatrix<f64, 6, 6>
Returns the 6x6 covariance (i.e. square of the sigma/uncertainty) of the SMA, ECC, INC, RAAN, AOP, and True Anomaly.
Trait Implementations§
Source§impl<T: Clone + State> Clone for KfEstimate<T>where
DefaultAllocator: Allocator<<T as State>::Size> + Allocator<<T as State>::Size, <T as State>::Size> + Allocator<<T as State>::VecLength>,
<DefaultAllocator as Allocator<<T as State>::Size>>::Buffer<f64>: Copy,
<DefaultAllocator as Allocator<<T as State>::Size, <T as State>::Size>>::Buffer<f64>: Copy,
impl<T: Clone + State> Clone for KfEstimate<T>where
DefaultAllocator: Allocator<<T as State>::Size> + Allocator<<T as State>::Size, <T as State>::Size> + Allocator<<T as State>::VecLength>,
<DefaultAllocator as Allocator<<T as State>::Size>>::Buffer<f64>: Copy,
<DefaultAllocator as Allocator<<T as State>::Size, <T as State>::Size>>::Buffer<f64>: Copy,
Source§fn clone(&self) -> KfEstimate<T>
fn clone(&self) -> KfEstimate<T>
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl<T: Debug + State> Debug for KfEstimate<T>where
DefaultAllocator: Allocator<<T as State>::Size> + Allocator<<T as State>::Size, <T as State>::Size> + Allocator<<T as State>::VecLength>,
<DefaultAllocator as Allocator<<T as State>::Size>>::Buffer<f64>: Copy,
<DefaultAllocator as Allocator<<T as State>::Size, <T as State>::Size>>::Buffer<f64>: Copy,
impl<T: Debug + State> Debug for KfEstimate<T>where
DefaultAllocator: Allocator<<T as State>::Size> + Allocator<<T as State>::Size, <T as State>::Size> + Allocator<<T as State>::VecLength>,
<DefaultAllocator as Allocator<<T as State>::Size>>::Buffer<f64>: Copy,
<DefaultAllocator as Allocator<<T as State>::Size, <T as State>::Size>>::Buffer<f64>: Copy,
Source§impl<T: State> Display for KfEstimate<T>where
DefaultAllocator: Allocator<<T as State>::Size> + Allocator<<T as State>::Size, <T as State>::Size> + Allocator<<T as State>::VecLength>,
<DefaultAllocator as Allocator<<T as State>::Size>>::Buffer<f64>: Copy,
<DefaultAllocator as Allocator<<T as State>::Size, <T as State>::Size>>::Buffer<f64>: Copy,
impl<T: State> Display for KfEstimate<T>where
DefaultAllocator: Allocator<<T as State>::Size> + Allocator<<T as State>::Size, <T as State>::Size> + Allocator<<T as State>::VecLength>,
<DefaultAllocator as Allocator<<T as State>::Size>>::Buffer<f64>: Copy,
<DefaultAllocator as Allocator<<T as State>::Size, <T as State>::Size>>::Buffer<f64>: Copy,
Source§impl<T: State> Estimate<T> for KfEstimate<T>where
DefaultAllocator: Allocator<<T as State>::Size> + Allocator<<T as State>::Size, <T as State>::Size> + Allocator<<T as State>::VecLength>,
<DefaultAllocator as Allocator<<T as State>::Size>>::Buffer<f64>: Copy,
<DefaultAllocator as Allocator<<T as State>::Size, <T as State>::Size>>::Buffer<f64>: Copy,
impl<T: State> Estimate<T> for KfEstimate<T>where
DefaultAllocator: Allocator<<T as State>::Size> + Allocator<<T as State>::Size, <T as State>::Size> + Allocator<<T as State>::VecLength>,
<DefaultAllocator as Allocator<<T as State>::Size>>::Buffer<f64>: Copy,
<DefaultAllocator as Allocator<<T as State>::Size, <T as State>::Size>>::Buffer<f64>: Copy,
Source§fn zeros(nominal_state: T) -> Self
fn zeros(nominal_state: T) -> Self
Source§fn nominal_state(&self) -> T
fn nominal_state(&self) -> T
Source§fn state_deviation(&self) -> OVector<f64, <T as State>::Size>
fn state_deviation(&self) -> OVector<f64, <T as State>::Size>
Source§fn covar(&self) -> OMatrix<f64, <T as State>::Size, <T as State>::Size>
fn covar(&self) -> OMatrix<f64, <T as State>::Size, <T as State>::Size>
Source§fn predicted_covar(
&self,
) -> OMatrix<f64, <T as State>::Size, <T as State>::Size>
fn predicted_covar( &self, ) -> OMatrix<f64, <T as State>::Size, <T as State>::Size>
Source§fn predicted(&self) -> bool
fn predicted(&self) -> bool
Source§fn stm(&self) -> &OMatrix<f64, <T as State>::Size, <T as State>::Size>
fn stm(&self) -> &OMatrix<f64, <T as State>::Size, <T as State>::Size>
Source§fn set_state_deviation(&mut self, new_state: OVector<f64, <T as State>::Size>)
fn set_state_deviation(&mut self, new_state: OVector<f64, <T as State>::Size>)
Source§fn set_covar(
&mut self,
new_covar: OMatrix<f64, <T as State>::Size, <T as State>::Size>,
)
fn set_covar( &mut self, new_covar: OMatrix<f64, <T as State>::Size, <T as State>::Size>, )
fn set_epoch(&mut self, dt: Epoch)
Source§fn within_sigma(&self, sigma: f64) -> bool
fn within_sigma(&self, sigma: f64) -> bool
Source§fn within_3sigma(&self) -> bool
fn within_3sigma(&self) -> bool
Source§impl<StateType: State> From<BLSSolution<StateType>> for KfEstimate<StateType>where
DefaultAllocator: Allocator<<StateType as State>::Size> + Allocator<<StateType as State>::Size, <StateType as State>::Size> + Allocator<<StateType as State>::VecLength>,
<DefaultAllocator as Allocator<<StateType as State>::Size>>::Buffer<f64>: Copy,
<DefaultAllocator as Allocator<<StateType as State>::Size, <StateType as State>::Size>>::Buffer<f64>: Copy,
impl<StateType: State> From<BLSSolution<StateType>> for KfEstimate<StateType>where
DefaultAllocator: Allocator<<StateType as State>::Size> + Allocator<<StateType as State>::Size, <StateType as State>::Size> + Allocator<<StateType as State>::VecLength>,
<DefaultAllocator as Allocator<<StateType as State>::Size>>::Buffer<f64>: Copy,
<DefaultAllocator as Allocator<<StateType as State>::Size, <StateType as State>::Size>>::Buffer<f64>: Copy,
Source§fn from(bls: BLSSolution<StateType>) -> Self
fn from(bls: BLSSolution<StateType>) -> Self
Source§impl<T: State> LowerExp for KfEstimate<T>where
DefaultAllocator: Allocator<<T as State>::Size> + Allocator<<T as State>::Size, <T as State>::Size> + Allocator<<T as State>::VecLength>,
<DefaultAllocator as Allocator<<T as State>::Size>>::Buffer<f64>: Copy,
<DefaultAllocator as Allocator<<T as State>::Size, <T as State>::Size>>::Buffer<f64>: Copy,
impl<T: State> LowerExp for KfEstimate<T>where
DefaultAllocator: Allocator<<T as State>::Size> + Allocator<<T as State>::Size, <T as State>::Size> + Allocator<<T as State>::VecLength>,
<DefaultAllocator as Allocator<<T as State>::Size>>::Buffer<f64>: Copy,
<DefaultAllocator as Allocator<<T as State>::Size, <T as State>::Size>>::Buffer<f64>: Copy,
Source§impl LowerHex for KfEstimate<Spacecraft>
impl LowerHex for KfEstimate<Spacecraft>
Source§impl<T: State> Mul<f64> for KfEstimate<T>where
DefaultAllocator: Allocator<<T as State>::Size> + Allocator<<T as State>::Size, <T as State>::Size> + Allocator<<T as State>::VecLength>,
<DefaultAllocator as Allocator<<T as State>::Size>>::Buffer<f64>: Copy,
<DefaultAllocator as Allocator<<T as State>::Size, <T as State>::Size>>::Buffer<f64>: Copy,
impl<T: State> Mul<f64> for KfEstimate<T>where
DefaultAllocator: Allocator<<T as State>::Size> + Allocator<<T as State>::Size, <T as State>::Size> + Allocator<<T as State>::VecLength>,
<DefaultAllocator as Allocator<<T as State>::Size>>::Buffer<f64>: Copy,
<DefaultAllocator as Allocator<<T as State>::Size, <T as State>::Size>>::Buffer<f64>: Copy,
fn orbital_state(&self) -> Orbit
Source§fn expected_state(&self) -> Orbit
fn expected_state(&self) -> Orbit
Source§impl<T: PartialEq + State> PartialEq for KfEstimate<T>where
DefaultAllocator: Allocator<<T as State>::Size> + Allocator<<T as State>::Size, <T as State>::Size> + Allocator<<T as State>::VecLength>,
<DefaultAllocator as Allocator<<T as State>::Size>>::Buffer<f64>: Copy,
<DefaultAllocator as Allocator<<T as State>::Size, <T as State>::Size>>::Buffer<f64>: Copy,
impl<T: PartialEq + State> PartialEq for KfEstimate<T>where
DefaultAllocator: Allocator<<T as State>::Size> + Allocator<<T as State>::Size, <T as State>::Size> + Allocator<<T as State>::VecLength>,
<DefaultAllocator as Allocator<<T as State>::Size>>::Buffer<f64>: Copy,
<DefaultAllocator as Allocator<<T as State>::Size, <T as State>::Size>>::Buffer<f64>: Copy,
impl<T: Copy + State> Copy for KfEstimate<T>where
DefaultAllocator: Allocator<<T as State>::Size> + Allocator<<T as State>::Size, <T as State>::Size> + Allocator<<T as State>::VecLength>,
<DefaultAllocator as Allocator<<T as State>::Size>>::Buffer<f64>: Copy,
<DefaultAllocator as Allocator<<T as State>::Size, <T as State>::Size>>::Buffer<f64>: Copy,
impl<T: State> StructuralPartialEq for KfEstimate<T>where
DefaultAllocator: Allocator<<T as State>::Size> + Allocator<<T as State>::Size, <T as State>::Size> + Allocator<<T as State>::VecLength>,
<DefaultAllocator as Allocator<<T as State>::Size>>::Buffer<f64>: Copy,
<DefaultAllocator as Allocator<<T as State>::Size, <T as State>::Size>>::Buffer<f64>: Copy,
Auto Trait Implementations§
impl<T> !Freeze for KfEstimate<T>
impl<T> !RefUnwindSafe for KfEstimate<T>
impl<T> !Send for KfEstimate<T>
impl<T> !Sync for KfEstimate<T>
impl<T> !Unpin for KfEstimate<T>
impl<T> !UnwindSafe for KfEstimate<T>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more§impl<T> Pointable for T
impl<T> Pointable for T
§impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
§fn to_subset(&self) -> Option<SS>
fn to_subset(&self) -> Option<SS>
self from the equivalent element of its
superset. Read more§fn is_in_subset(&self) -> bool
fn is_in_subset(&self) -> bool
self is actually part of its subset T (and can be converted to it).§fn to_subset_unchecked(&self) -> SS
fn to_subset_unchecked(&self) -> SS
self.to_subset but without any property checks. Always succeeds.§fn from_subset(element: &SS) -> SP
fn from_subset(element: &SS) -> SP
self to the equivalent element of its superset.