1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
use super::thrustctrl::ThrustControl;
use crate::dimensions::Vector3;
use celestia::State;
#[derive(Copy, Clone, Debug)]
pub struct Thruster {
pub thrust: f64,
pub isp: f64,
}
const NORM_ERR: f64 = 1e-12;
const STD_GRAVITY: f64 = 9.80665;
#[derive(Clone)]
pub struct Propulsion<T: ThrustControl> {
pub thrusters: Vec<Thruster>,
pub decrement_mass: bool,
pub ctrl: T,
}
impl<'a, T: ThrustControl> Propulsion<T> {
pub fn new(ctrl: T, thrusters: Vec<Thruster>, decrement_mass: bool) -> Self {
Self {
thrusters,
decrement_mass,
ctrl,
}
}
pub fn set_state(&mut self, new_orbit: &State) {
self.ctrl.next(new_orbit);
}
pub fn eom(&self, osc: &State) -> (Vector3<f64>, f64) {
let thrust_power = self.ctrl.throttle(osc);
if thrust_power > 0.0 {
let thrust_inertial = self.ctrl.direction(osc);
if (thrust_inertial.norm() - 1.0).abs() > NORM_ERR {
panic!(
"thrust orientation is not a unit vector: norm = {}\n{}",
thrust_inertial.norm(),
thrust_inertial
);
}
let mut total_thrust = 0.0;
let mut fuel_usage = 0.0;
for thruster in &self.thrusters {
total_thrust += thrust_power * thruster.thrust;
fuel_usage += thrust_power * thruster.thrust / (thruster.isp * STD_GRAVITY);
}
total_thrust *= 1e-3;
(
thrust_inertial * total_thrust,
if self.decrement_mass {
-fuel_usage
} else {
0.0
},
)
} else {
(Vector3::zeros(), 0.0)
}
}
}