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}