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}