use astrodyn::{Acceleration, AngularAcceleration, BodyFrame, RootInertial, SelfRef};
use bevy::prelude::*;
use glam::DVec3;
use crate::components::*;
#[allow(clippy::type_complexity)]
pub fn force_collection_system(
mut query: Query<
(
&mut TotalForceC,
Option<&mut FrameDerivativesC>,
Option<&GravityAccelerationC>,
Option<&RotationalStateC>,
Option<&MassPropertiesC>,
Option<&AerodynamicForceC>,
Option<&RadiationForceC>,
Option<&GravityTorqueC>,
Option<&StructuralTransformC>,
Option<&ExternalForceC>,
Option<&ExternalTorqueC>,
),
Without<crate::DetachedSubtreeStateC>,
>,
) {
for (
mut total,
derivs,
grav,
rot_state,
mass,
aero,
srp,
grav_torque,
struct_xform,
ext_force,
ext_torque,
) in &mut query
{
let t_struct_body = struct_xform.map_or(glam::DMat3::IDENTITY, |s| *s.0.matrix_ref());
let grav_accel = grav.map_or(DVec3::ZERO, |g| g.grav_accel.raw_si());
let aero_ref = aero.map(|a| astrodyn::AerodynamicForce {
force: a.force,
torque: a.torque,
});
let srp_ref = srp.map(|s| astrodyn::RadiationForce {
force: s.force,
torque: s.torque,
});
let gravity_torque_val = grav_torque.map(|gt| gt.0.raw_si());
let rot_untyped = rot_state.map(|r| astrodyn::typed_bridge::rot_typed_to_raw(&r.0));
let mass_untyped = mass.map(|m| astrodyn::typed_bridge::mass_typed_to_raw(&m.0));
let (collected, frame_derivs_raw) = astrodyn::collect_and_resolve_forces(
aero_ref.as_ref(),
srp_ref.as_ref(),
gravity_torque_val,
rot_untyped.as_ref(),
t_struct_body,
mass_untyped.as_ref(),
grav_accel,
);
total.0 =
astrodyn::TotalForceTyped::<astrodyn::SelfRef, RootInertial>::from_untyped_unchecked(
&collected,
);
let mut frame_derivs =
astrodyn::FrameDerivativesTyped::<RootInertial, astrodyn::SelfRef>::from_untyped_unchecked(
&frame_derivs_raw,
);
if let Some(ef) = ext_force {
if ef.0.raw_si() != DVec3::ZERO {
total.0.force += ef.0;
if let Some(mass) = mass {
let accel_contrib = ef.0.raw_si() * mass.0.inverse_mass;
frame_derivs.trans_accel +=
Acceleration::<RootInertial>::from_raw_si(accel_contrib);
}
}
}
if let Some(et) = ext_torque {
if et.0.raw_si() != DVec3::ZERO {
total.0.torque += et.0;
if let Some(mass) = mass {
let alpha_contrib = mass.0.inverse_inertia * et.0.raw_si();
frame_derivs.rot_accel +=
AngularAcceleration::<BodyFrame<SelfRef>>::from_raw_si(alpha_contrib);
}
}
}
if let Some(mut derivs) = derivs {
derivs.0 = frame_derivs;
}
}
}