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: T
The 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: bool
Whether 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 // For all of the resulting trajectories, we'll want to compute the percentage of penumbra and umbra.
152 let eclipse_loc = EclipseLocator::cislunar(almanac.clone());
153 let umbra_event = eclipse_loc.to_umbra_event();
154 let penumbra_event = eclipse_loc.to_penumbra_event();
155
156 rslts.to_parquet(
157 "02_jwst_monte_carlo.parquet",
158 Some(vec![&umbra_event, &penumbra_event]),
159 ExportCfg::default(),
160 almanac,
161 )?;
162
163 Ok(())
164}
Sourcepub fn sigma_for(&self, param: StateParameter) -> Result<f64, AstroError>
pub fn sigma_for(&self, param: StateParameter) -> 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<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.