use crate::frametransform;
use crate::mathtypes::*;
use crate::Frame;
use crate::Instant;
#[derive(Debug, Clone)]
pub struct ContinuousThrust {
pub accel: Vector3,
pub frame: Frame,
pub start: Instant,
pub end: Instant,
}
impl ContinuousThrust {
pub fn new(accel: Vector3, frame: Frame, start: Instant, end: Instant) -> Self {
Self {
accel,
frame,
start,
end,
}
}
pub fn is_active(&self, time: &Instant) -> bool {
*time >= self.start && *time <= self.end
}
pub fn accel_gcrf(&self, time: &Instant, pos_gcrf: &Vector3, vel_gcrf: &Vector3) -> Option<Vector3> {
if !self.is_active(time) {
return None;
}
Some(match self.frame {
Frame::GCRF => self.accel,
Frame::RTN => {
let dcm = frametransform::rtn_to_gcrf(pos_gcrf, vel_gcrf);
dcm * self.accel
}
Frame::NTW => {
let dcm = frametransform::ntw_to_gcrf(pos_gcrf, vel_gcrf);
dcm * self.accel
}
Frame::LVLH => {
let dcm = frametransform::lvlh_to_gcrf(pos_gcrf, vel_gcrf);
dcm * self.accel
}
Frame::ITRF
| Frame::TIRS
| Frame::CIRS
| Frame::TEME
| Frame::EME2000
| Frame::ICRF => panic!(
"Unsupported frame for thrust: {}. Must be GCRF, RTN, NTW, or LVLH",
self.frame
),
})
}
}
#[derive(Debug, Clone, Default)]
pub struct ThrustProfile {
pub thrusts: Vec<ContinuousThrust>,
}
impl ThrustProfile {
pub fn new(thrusts: Vec<ContinuousThrust>) -> Self {
Self { thrusts }
}
pub fn accel_gcrf(
&self,
time: &Instant,
pos_gcrf: &Vector3,
vel_gcrf: &Vector3,
) -> Option<Vector3> {
let mut total = Vector3::zeros();
let mut active = false;
for t in &self.thrusts {
if let Some(a) = t.accel_gcrf(time, pos_gcrf, vel_gcrf) {
total += a;
active = true;
}
}
active.then_some(total)
}
pub fn is_empty(&self) -> bool {
self.thrusts.is_empty()
}
}