pub mod coupled;
pub mod dynamics;
pub mod independent;
pub mod prop_group;
pub mod scheduler;
pub mod state;
pub use coupled::{
CoupledGroup, CoupledGroupDynamics, CoupledGroupParts, InterSatelliteForce, InteractionPair,
MutualGravity, PairContext,
};
pub use dynamics::IndependentGroupDynamics;
pub use independent::{IndependentGroup, IntegratorConfig, SatelliteParts};
pub use prop_group::{GroupSnapshot, PropGroup, PropGroupOutcome, SatId, SatelliteTermination};
pub use scheduler::{InteractionSpec, PairPolicy, PairRegime, RegimeConfig, Scheduler};
pub use state::GroupState;
use nalgebra::{Vector3, Vector4};
use utsuroi::OdeState;
use crate::OrbitalState;
pub trait HasPosition {
fn position(&self) -> Vector3<f64>;
}
impl HasPosition for OrbitalState {
fn position(&self) -> Vector3<f64> {
*self.position()
}
}
impl HasPosition for crate::SpacecraftState {
fn position(&self) -> Vector3<f64> {
*self.orbit.position()
}
}
impl HasPosition for crate::effector::AugmentedState<crate::SpacecraftState> {
fn position(&self) -> Vector3<f64> {
*self.plant.orbit.position()
}
}
pub trait FromAcceleration: OdeState {
fn from_acceleration(accel: Vector3<f64>) -> Self;
}
impl FromAcceleration for OrbitalState {
fn from_acceleration(accel: Vector3<f64>) -> Self {
OrbitalState::from_derivative(Vector3::zeros(), accel)
}
}
impl FromAcceleration for crate::SpacecraftState {
fn from_acceleration(accel: Vector3<f64>) -> Self {
crate::SpacecraftState::from_derivative(
Vector3::zeros(),
accel,
Vector4::zeros(),
Vector3::zeros(),
0.0,
)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::attitude::AttitudeState;
use nalgebra::Vector4;
#[test]
fn has_position_state() {
let state = OrbitalState::new(
Vector3::new(7000.0, 100.0, 50.0),
Vector3::new(0.0, 7.5, 0.0),
);
assert_eq!(
HasPosition::position(&state),
Vector3::new(7000.0, 100.0, 50.0)
);
}
#[test]
fn has_position_spacecraft_state() {
let sc = crate::SpacecraftState {
orbit: OrbitalState::new(Vector3::new(7200.0, 0.0, 0.0), Vector3::new(0.0, 7.3, 0.0)),
attitude: AttitudeState {
quaternion: Vector4::new(1.0, 0.0, 0.0, 0.0),
angular_velocity: Vector3::zeros(),
},
mass: 500.0,
};
assert_eq!(sc.position(), Vector3::new(7200.0, 0.0, 0.0));
}
#[test]
fn from_acceleration_state() {
let accel = Vector3::new(1.0, -2.0, 3.0);
let delta = OrbitalState::from_acceleration(accel);
assert_eq!(*delta.position(), Vector3::zeros());
assert_eq!(*delta.velocity(), accel);
}
#[test]
fn from_acceleration_spacecraft_state() {
let accel = Vector3::new(0.001, -0.002, 0.003);
let delta = crate::SpacecraftState::from_acceleration(accel);
assert_eq!(*delta.orbit.position(), Vector3::zeros());
assert_eq!(*delta.orbit.velocity(), accel);
assert_eq!(delta.attitude.quaternion, Vector4::zeros());
assert_eq!(delta.attitude.angular_velocity, Vector3::zeros());
assert_eq!(delta.mass, 0.0);
}
#[test]
fn from_acceleration_axpy_adds_accel_to_derivative() {
let existing_deriv = OrbitalState::from_derivative(
Vector3::new(0.0, 7.5, 0.0), Vector3::new(-0.008, 0.0, 0.0), );
let inter_sat_accel = Vector3::new(0.0, 0.0, 0.001);
let delta = OrbitalState::from_acceleration(inter_sat_accel);
let combined = existing_deriv.axpy(1.0, &delta);
assert_eq!(*combined.position(), Vector3::new(0.0, 7.5, 0.0));
assert!((combined.velocity()[0] - (-0.008)).abs() < 1e-15);
assert!((combined.velocity()[2] - 0.001).abs() < 1e-15);
}
}