use astrodyn_frames::{RefFrameRot, RefFrameState, RefFrameTrans};
use astrodyn_math::JeodQuat;
use astrodyn_quantities::aliases::{AngularVelocity, Position, Velocity};
use astrodyn_quantities::body_attitude::BodyAttitude;
use astrodyn_quantities::ext::Vec3Ext;
use astrodyn_quantities::frame::{BodyFrame, RootInertial, SelfRef};
use astrodyn_quantities::quat::NormalizedQuat;
use glam::DVec3;
#[derive(Debug, Clone, Copy)]
pub struct DetachedSubtreeState {
pub composite_position: Position<RootInertial>,
pub composite_velocity: Velocity<RootInertial>,
pub composite_attitude: BodyAttitude<SelfRef>,
pub composite_ang_vel_body: DVec3,
}
impl DetachedSubtreeState {
pub fn to_ref_frame_state(&self) -> RefFrameState {
let q = self.composite_attitude.to_jeod_quat();
RefFrameState {
trans: RefFrameTrans {
position: self.composite_position.raw_si(),
velocity: self.composite_velocity.raw_si(),
},
rot: RefFrameRot {
q_parent_this: q,
t_parent_this: self
.composite_attitude
.as_witness()
.left_quat_to_transformation(),
ang_vel_this: self.composite_ang_vel_body,
},
}
}
pub fn from_ref_frame_state(state: &RefFrameState) -> Self {
let q = NormalizedQuat::new(state.rot.q_parent_this).unwrap_or_else(|err| {
panic!(
"DetachedSubtreeState::from_ref_frame_state: q_parent_this is not unit-norm: {err}"
)
});
Self {
composite_position: state.trans.position.m_at::<RootInertial>(),
composite_velocity: state.trans.velocity.m_per_s_at::<RootInertial>(),
composite_attitude: BodyAttitude::from_witness(q),
composite_ang_vel_body: state.rot.ang_vel_this,
}
}
pub fn attitude_from_raw_jeod_quat(q: JeodQuat) -> BodyAttitude<SelfRef> {
let witness = NormalizedQuat::new(q).unwrap_or_else(|err| {
panic!("DetachedSubtreeState::attitude_from_raw_jeod_quat: q is not unit-norm: {err}")
});
BodyAttitude::from_witness(witness)
}
pub fn step_ballistic(&mut self, dt: f64) {
let new_pos = (self.composite_position.raw_si() + self.composite_velocity.raw_si() * dt)
.m_at::<RootInertial>();
self.composite_position = new_pos;
let omega: AngularVelocity<BodyFrame<SelfRef>> =
AngularVelocity::<BodyFrame<SelfRef>>::from_raw_si(self.composite_ang_vel_body);
self.composite_attitude = self.composite_attitude.advance_under_body_rate(omega, dt);
}
}