melvin_ob/flight_control/orbit/
characteristics.rs

1use super::{closed_orbit::ClosedOrbit, index::IndexedOrbitPosition};
2use crate::util::Vec2D;
3use crate::flight_control::FlightComputer;
4use crate::info;
5use fixed::types::I32F32;
6use tokio::sync::RwLock;
7
8/// Represents the characteristics of an orbital path including imaging frequency,
9/// orbital period, and the entry position. This struct provides utilities to initialize
10/// and manage orbital parameters over time.
11#[derive(Debug, Copy, Clone)]
12pub struct OrbitCharacteristics {
13    /// The maximum time interval between image captures.
14    img_dt: I32F32,
15    /// The full period of the orbit in terms of iterations.
16    orbit_full_period: usize,
17    /// The entry position of the orbit indexed in time and position.
18    i_entry: IndexedOrbitPosition,
19    /// The already performed number of fsm mode switches
20    mode_switches: usize,
21}
22
23#[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)]
24impl OrbitCharacteristics {
25    /// Creates a new `OrbitCharacteristics` instance using data from a provided closed orbit
26    /// and a flight computer.
27    ///
28    /// # Arguments
29    /// - `c_orbit`: A reference to the `ClosedOrbit` to derive orbital parameters.
30    /// - `f_cont`: A reference to a thread-safe, asynchronous flight computer instance.
31    ///
32    /// # Returns
33    /// A new `OrbitCharacteristics` instance.
34    ///
35    /// # Panics
36    /// This function will panic if the `ClosedOrbit`'s period cannot be converted to an
37    /// `usize` or `i64`.
38    pub async fn new(c_orbit: &ClosedOrbit, f_cont: &RwLock<FlightComputer>) -> Self {
39        let img_dt = c_orbit.max_image_dt();
40        let orbit_full_period = c_orbit.period().0.to_num::<usize>();
41        let i_entry =
42            IndexedOrbitPosition::new(0, orbit_full_period, f_cont.read().await.current_pos());
43        Self { img_dt, orbit_full_period, i_entry, mode_switches: 0}
44    }
45
46    /// Retrieves the maximum image capture time interval.
47    pub fn img_dt(&self) -> I32F32 { self.img_dt }
48
49    /// Retrieves the full orbital period.
50    pub fn orbit_full_period(&self) -> usize { self.orbit_full_period }
51
52    /// Retrieves the indexed entry position of the current orbit entry.
53    pub fn i_entry(&self) -> IndexedOrbitPosition { self.i_entry }
54
55    /// Returns the number of mode switches already performed
56    pub fn mode_switches(&self) -> usize { self.mode_switches }
57    /// Marks the end of an orbital mode and updates the entry position.
58    ///
59    /// # Arguments
60    /// - `now`: The new `IndexedOrbitPosition` representing the current state.
61    pub fn finish(&mut self, now_pos: Vec2D<I32F32>, rationale: &str) {
62        let now = self.i_entry.new_from_pos(now_pos);
63        info!(
64            "Finished Phase after: {}s, due to: {rationale}",
65            (now.t() - self.i_entry.t()).num_seconds()
66        );
67        self.i_entry = now;
68        self.mode_switches += 1;
69    }
70
71    /// Marks the end of an orbital mode after re-entering the orbit.
72    ///
73    /// # Arguments
74    /// * `now_pos`: The current position
75    /// * `index`: The return index where re-entering was performed 
76    pub fn finish_entry(&mut self, now_pos: Vec2D<I32F32>, index: usize) {
77        let now = IndexedOrbitPosition::new(index, self.orbit_full_period, now_pos);
78        info!(
79            "Finished Phase after: {}s, due to: Orbit Reentry",
80            (now.t() - self.i_entry.t()).num_seconds()
81        );
82        self.i_entry = now;
83        self.mode_switches += 1;
84    }
85}