nyx_space/md/events/
mod.rs1pub mod details;
20pub mod evaluators;
21pub mod search;
22use super::StateParameter;
23use crate::errors::EventError;
24use crate::linalg::allocator::Allocator;
25use crate::linalg::DefaultAllocator;
26use crate::time::{Duration, Unit};
27use crate::State;
28use anise::prelude::{Almanac, Frame};
29use anise::structure::planetocentric::ellipsoid::Ellipsoid;
30use serde::{Deserialize, Serialize};
31
32use std::default::Default;
33use std::fmt;
34use std::sync::Arc;
35
36pub trait EventEvaluator<S: State>: fmt::Display + Send + Sync
38where
39 DefaultAllocator: Allocator<S::Size> + Allocator<S::Size, S::Size> + Allocator<S::VecLength>,
40{
41 fn eval_crossing(
43 &self,
44 prev_state: &S,
45 next_state: &S,
46 almanac: Arc<Almanac>,
47 ) -> Result<bool, EventError> {
48 let prev = self.eval(prev_state, almanac.clone())?;
49 let next = self.eval(next_state, almanac)?;
50
51 Ok(prev * next < 0.0)
52 }
53
54 fn eval(&self, state: &S, almanac: Arc<Almanac>) -> Result<f64, EventError>;
56 fn eval_string(&self, state: &S, almanac: Arc<Almanac>) -> Result<String, EventError>;
58 fn epoch_precision(&self) -> Duration;
59 fn value_precision(&self) -> f64;
60}
61
62#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
64pub struct Event {
65 pub parameter: StateParameter,
67 pub desired_value: f64,
69 pub epoch_precision: Duration,
71 pub value_precision: f64,
73 pub obs_frame: Option<Frame>,
75}
76
77impl fmt::Display for Event {
78 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
79 write!(f, "{:?}", self.parameter)?;
80 if self.parameter != StateParameter::Apoapsis && self.parameter != StateParameter::Periapsis
81 {
82 if self.desired_value.abs() > 1e3 {
83 write!(
84 f,
85 " = {:e} {} (± {:e} {})",
86 self.desired_value,
87 self.parameter.unit(),
88 self.value_precision,
89 self.parameter.unit()
90 )?;
91 } else {
92 write!(
93 f,
94 " = {} {} (± {} {})",
95 self.desired_value,
96 self.parameter.unit(),
97 self.value_precision,
98 self.parameter.unit()
99 )?;
100 }
101 }
102 if let Some(frame) = self.obs_frame {
103 write!(f, "in frame {frame}")?;
104 }
105 fmt::Result::Ok(())
106 }
107}
108
109impl Event {
110 pub fn new(parameter: StateParameter, desired_value: f64) -> Self {
115 Self::within_tolerance(
116 parameter,
117 desired_value,
118 parameter.default_event_precision(),
119 )
120 }
121
122 pub fn within_tolerance(
124 parameter: StateParameter,
125 desired_value: f64,
126 value_precision: f64,
127 ) -> Self {
128 Self::specific(parameter, desired_value, value_precision, Unit::Millisecond)
129 }
130
131 pub fn specific(
133 parameter: StateParameter,
134 desired_value: f64,
135 value_precision: f64,
136 unit_precision: Unit,
137 ) -> Self {
138 Self {
139 parameter,
140 desired_value,
141 epoch_precision: 1 * unit_precision,
142 value_precision,
143 obs_frame: None,
144 }
145 }
146
147 pub fn periapsis() -> Self {
149 Self::new(StateParameter::Periapsis, 0.0)
150 }
151
152 pub fn apoapsis() -> Self {
154 Self::new(StateParameter::Apoapsis, 180.0)
155 }
156
157 pub fn mean_surface(body: &Ellipsoid) -> Self {
160 Self::new(StateParameter::Rmag, body.mean_equatorial_radius_km())
161 }
162
163 pub fn in_frame(parameter: StateParameter, desired_value: f64, target_frame: Frame) -> Self {
165 warn!("Searching for an event in another frame is slow: you should instead convert the trajectory into that other frame");
166 Self {
167 parameter,
168 desired_value,
169 epoch_precision: Unit::Millisecond * 1,
170 value_precision: 1e-3,
171 obs_frame: Some(target_frame),
172 }
173 }
174}
175
176impl Default for Event {
177 fn default() -> Self {
178 Self {
179 parameter: StateParameter::Periapsis,
180 desired_value: 0.0,
181 value_precision: 1e-3,
182 epoch_precision: Unit::Second * 1,
183 obs_frame: None,
184 }
185 }
186}