Skip to main content

nyx_space/dynamics/sequence/
config.rs

1/*
2    Nyx, blazing fast astrodynamics
3    Copyright (C) 2018-onwards Christopher Rabotin <christopher.rabotin@gmail.com>
4
5    This program is free software: you can redistribute it and/or modify
6    it under the terms of the GNU Affero General Public License as published
7    by the Free Software Foundation, either version 3 of the License, or
8    (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU Affero General Public License for more details.
14
15    You should have received a copy of the GNU Affero General Public License
16    along with this program.  If not, see <https://www.gnu.org/licenses/>.
17*/
18use anise::frames::FrameUid;
19use serde::{Deserialize, Serialize};
20use serde_dhall::{SimpleType, StaticType};
21use std::collections::HashMap;
22use std::sync::Arc;
23
24use crate::{
25    dynamics::{
26        Drag, PointMasses, SolarPressure,
27        guidance::{Maneuver, ObjectiveEfficiency, ObjectiveWeight},
28    },
29    io::gravity::GravityFieldConfig,
30    propagators::{IntegratorMethod, IntegratorOptions},
31};
32
33use crate::dynamics::sequence::discrete_event::DiscreteEvent;
34
35#[cfg(feature = "python")]
36use pyo3::prelude::*;
37
38#[derive(Clone, Debug, Serialize, Deserialize)]
39pub enum Phase {
40    Terminate,
41    Activity {
42        name: String,
43        propagator: String,
44        guidance: Option<Box<GuidanceConfig>>,
45        /// The discrete event will be applied ONCE before the equation of motions are integrated.
46        on_entry: Option<Box<DiscreteEvent>>,
47        /// Allows disabling a phase without removing it
48        disabled: bool,
49    },
50}
51
52impl StaticType for Phase {
53    fn static_type() -> SimpleType {
54        let mut variants = HashMap::new();
55
56        // Handle the Vector(Vector3<f64>) variant
57        // Most math crates serialize Vector3 as a list of 3 doubles
58        variants.insert("Terminate".to_string(), None);
59
60        //  Activity variant (Record variant)
61        let mut activity_fields = HashMap::new();
62
63        activity_fields.insert("name".to_string(), String::static_type());
64        activity_fields.insert("propagator".to_string(), String::static_type());
65
66        // Use the StaticType impl of the boxed inner types
67        activity_fields.insert(
68            "guidance".to_string(),
69            <Option<GuidanceConfig> as StaticType>::static_type(),
70        );
71
72        activity_fields.insert(
73            "on_entry".to_string(),
74            <Option<DiscreteEvent> as StaticType>::static_type(),
75        );
76
77        activity_fields.insert("disabled".to_string(), bool::static_type());
78
79        variants.insert(
80            "Activity".to_string(),
81            Some(SimpleType::Record(activity_fields)),
82        );
83
84        SimpleType::Union(variants)
85    }
86}
87
88/// Propagator config includes the method, options, and all dynamics
89#[derive(Clone, Debug, Serialize, Deserialize, StaticType)]
90#[cfg_attr(feature = "python", pyclass(from_py_object))]
91pub struct PropagatorConfig {
92    pub method: IntegratorMethod,
93    pub options: IntegratorOptions,
94    pub accel_models: AccelModels,
95    pub force_models: ForceModels,
96}
97
98/// Acceleration models alter the orbital dynamics
99#[derive(Clone, Serialize, Deserialize, Debug)]
100#[cfg_attr(feature = "python", pyclass(from_py_object))]
101pub struct AccelModels {
102    pub point_masses: Option<Arc<PointMasses>>,
103    pub gravity_field: Option<(GravityFieldConfig, FrameUid)>,
104}
105
106/// Force models alter the spacecraft dynamics (they need a mass).
107#[derive(Clone, Serialize, Deserialize, Debug)]
108#[cfg_attr(feature = "python", pyclass(from_py_object))]
109pub struct ForceModels {
110    pub solar_pressure: Option<Arc<SolarPressure>>,
111    pub drag: Option<Arc<Drag>>,
112}
113
114#[derive(Clone, Debug, Serialize, Deserialize, StaticType)]
115pub struct GuidanceConfig {
116    pub thruster_model: String,
117    pub disable_prop_mass: bool,
118    pub law: SteeringLaw,
119}
120
121// NOTE: Steering laws are not yet available in Python =(
122#[derive(Clone, Debug, Serialize, Deserialize, StaticType)]
123pub enum SteeringLaw {
124    FiniteBurn(Maneuver),
125    Kluever {
126        /// Stores the objectives, and their associated weights (set to zero to disable).
127        objectives: Vec<ObjectiveWeight>,
128        /// If defined, coast until vehicle is out of the provided eclipse state.
129        max_eclipse_prct: Option<f64>,
130    },
131    Ruggiero {
132        /// Stores the objectives, and their associated efficiency threshold (set to zero if not minimum efficiency).
133        objectives: Vec<ObjectiveEfficiency>,
134        /// If defined, coast until vehicle is out of the provided eclipse state.
135        max_eclipse_prct: Option<f64>,
136    },
137}
138
139impl StaticType for AccelModels {
140    fn static_type() -> serde_dhall::SimpleType {
141        let mut fields = HashMap::new();
142
143        fields.insert(
144            "point_masses".to_string(),
145            SimpleType::Optional(Box::new(PointMasses::static_type())),
146        );
147
148        #[allow(dead_code)]
149        #[derive(StaticType)]
150        struct GravityFieldDhall(GravityFieldConfig, FrameUid);
151
152        fields.insert(
153            "gravity_field".to_string(),
154            SimpleType::Optional(Box::new(GravityFieldDhall::static_type())),
155        );
156
157        SimpleType::Record(fields)
158    }
159}
160
161impl StaticType for ForceModels {
162    fn static_type() -> serde_dhall::SimpleType {
163        let mut fields = HashMap::new();
164
165        fields.insert(
166            "solar_pressure".to_string(),
167            SimpleType::Optional(Box::new(SolarPressure::static_type())),
168        );
169
170        fields.insert(
171            "drag".to_string(),
172            SimpleType::Optional(Box::new(Drag::static_type())),
173        );
174
175        SimpleType::Record(fields)
176    }
177}