melvin_ob/scheduling/
end_condition.rs

1use crate::flight_control::{FlightState, orbit::BurnSequence};
2use chrono::{DateTime, TimeDelta, Utc};
3use fixed::types::I32F32;
4
5/// Represents a scheduling boundary condition for dynamic orbit planning and task execution.
6///
7/// `EndCondition` defines a specific point in time where the spacecraft must be in a
8/// given `FlightState` with at least a specified charge level. This is primarily used
9/// when planning tasks (e.g. burns, communication, imaging) to ensure mission-critical
10/// resources are met.
11///
12/// Typically passed to the scheduler to guide the final phase of planning.
13pub struct EndCondition {
14    /// The desired scheduling terminal charge
15    charge: I32F32,
16    /// The desired scheduling terminal [`FlightState`]
17    state: FlightState,
18    /// The desired end of scheduling
19    time: DateTime<Utc>,
20}
21
22impl EndCondition {
23    /// Creates an [`EndCondition`] from a given burn sequence.
24    ///
25    /// The resulting condition requires being in `Acquisition` mode with
26    /// the burn's `min_charge()` at its start time.
27    ///
28    /// # Arguments
29    /// - `burn`: A reference to the [`BurnSequence`] from which to derive the end condition.
30    ///
31    /// # Returns
32    /// - A new [`EndCondition`] configured for the start of the burn.
33    pub fn from_burn(burn: &BurnSequence) -> Self {
34        Self {
35            time: burn.start_i().t(),
36            charge: burn.min_charge(),
37            state: FlightState::Acquisition,
38        }
39    }
40
41    /// Returns the absolute time of the end condition.
42    pub fn time(&self) -> DateTime<Utc> { self.time }
43    /// Returns the required battery level at the end condition time.
44    pub fn charge(&self) -> I32F32 { self.charge }
45    /// Returns the expected flight state at the end condition time.
46    pub fn state(&self) -> FlightState { self.state }
47
48    /// Computes the absolute `TimeDelta` required to charge from 0 to the required `charge()` level.
49    ///
50    /// This is based on the charge rate defined for `FlightState::Charge`.
51    ///
52    /// # Returns
53    /// - A `TimeDelta` representing the time needed to reach the required charge level.
54    pub fn abs_charge_dt(&self) -> TimeDelta {
55        let secs = (self.charge() / FlightState::Charge.get_charge_rate()).round().to_num::<i64>();
56        TimeDelta::seconds(secs)
57    }
58}