Skip to main content

KfEstimate

Struct KfEstimate 

Source
pub struct KfEstimate<T: State>{
    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>

Source

pub fn from_covar( nominal_state: T, covar: OMatrix<f64, <T as State>::Size, <T as State>::Size>, ) -> Self

Initializes a new filter estimate from the nominal state (not dispersed) and the full covariance

Source

pub fn from_diag( nominal_state: T, diag: OVector<f64, <T as State>::Size>, ) -> Self

Initializes a new filter estimate from the nominal state (not dispersed) and the diagonal of the covariance

Source§

impl KfEstimate<Spacecraft>

Source

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.

Source

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?
examples/02_jwst_covar_monte_carlo/main.rs (line 135)
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}
Source

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.

Source

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>

Source§

fn clone(&self) -> KfEstimate<T>

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<T: Debug + State> Debug for KfEstimate<T>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<T: State> Display for KfEstimate<T>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<T: State> Estimate<T> for KfEstimate<T>

Source§

fn zeros(nominal_state: T) -> Self

An empty estimate. This is useful if wanting to store an estimate outside the scope of a filtering loop.
Source§

fn nominal_state(&self) -> T

The nominal state as reported by the filter dynamics
Source§

fn state_deviation(&self) -> OVector<f64, <T as State>::Size>

The state deviation as computed by the filter.
Source§

fn covar(&self) -> OMatrix<f64, <T as State>::Size, <T as State>::Size>

The Covariance of this estimate. Will return the predicted covariance if this is a time update/prediction.
Source§

fn predicted_covar( &self, ) -> OMatrix<f64, <T as State>::Size, <T as State>::Size>

The predicted covariance of this estimate from the time update
Source§

fn predicted(&self) -> bool

Whether or not this is a predicted estimate from a time update, or an estimate from a measurement
Source§

fn stm(&self) -> &OMatrix<f64, <T as State>::Size, <T as State>::Size>

The STM used to compute this Estimate
Source§

fn set_state_deviation(&mut self, new_state: OVector<f64, <T as State>::Size>)

Sets the state deviation.
Source§

fn set_covar( &mut self, new_covar: OMatrix<f64, <T as State>::Size, <T as State>::Size>, )

Sets the Covariance of this estimate
Source§

fn epoch(&self) -> Epoch

Epoch of this Estimate
Source§

fn set_epoch(&mut self, dt: Epoch)

Source§

fn state(&self) -> T

The estimated state
Source§

fn within_sigma(&self, sigma: f64) -> bool

Returns whether this estimate is within some bound The 68-95-99.7 rule is a good way to assess whether the filter is operating normally
Source§

fn within_3sigma(&self) -> bool

Returns whether this estimate is within 3 sigma, which represent 99.7% for a Normal distribution
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,

Source§

fn from(bls: BLSSolution<StateType>) -> Self

Converts to this type from the input type.
Source§

impl<T: State> LowerExp for KfEstimate<T>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl LowerHex for KfEstimate<Spacecraft>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<T: State> Mul<f64> for KfEstimate<T>

Source§

type Output = KfEstimate<T>

The resulting type after applying the * operator.
Source§

fn mul(self, rhs: f64) -> Self::Output

Performs the * operation. Read more
Source§

impl NavSolution<Spacecraft> for KfEstimate<Spacecraft>

Source§

fn orbital_state(&self) -> Orbit

Source§

fn expected_state(&self) -> Orbit

Returns the nominal state as computed by the dynamics
Source§

impl<T: PartialEq + State> PartialEq for KfEstimate<T>

Source§

fn eq(&self, other: &KfEstimate<T>) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl<T: Copy + State> Copy for KfEstimate<T>

Source§

impl<T: State> StructuralPartialEq for KfEstimate<T>

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> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts 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

§

const ALIGN: usize

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
§

impl<SS, SP> SupersetOf<SS> for SP
where SS: SubsetOf<SP>,

§

fn to_subset(&self) -> Option<SS>

The inverse inclusion map: attempts to construct self from the equivalent element of its superset. Read more
§

fn is_in_subset(&self) -> bool

Checks if self is actually part of its subset T (and can be converted to it).
§

fn to_subset_unchecked(&self) -> SS

Use with care! Same as self.to_subset but without any property checks. Always succeeds.
§

fn from_subset(element: &SS) -> SP

The inclusion map: converts self to the equivalent element of its superset.
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

impl<T> Allocation for T
where T: RefUnwindSafe + Send + Sync,

Source§

impl<T> Scalar for T
where T: 'static + Clone + PartialEq + Debug,

Source§

impl<T> Scalar for T
where T: 'static + Clone + PartialEq + Debug,