mod gyroscope;
mod magnetometer;
pub mod noise;
mod star_tracker;
mod sun_sensor;
use arika::epoch::Epoch;
use crate::SpacecraftState;
use crate::plugin::tick_input::Sensors;
pub use gyroscope::Gyroscope;
pub use magnetometer::Magnetometer;
pub use star_tracker::StarTracker;
pub use sun_sensor::SunSensor;
pub struct SensorBundle {
pub magnetometers: Vec<Magnetometer>,
pub gyroscopes: Vec<Gyroscope>,
pub star_trackers: Vec<StarTracker>,
pub sun_sensors: Vec<SunSensor>,
}
impl SensorBundle {
pub fn new() -> Self {
Self {
magnetometers: Vec::new(),
gyroscopes: Vec::new(),
star_trackers: Vec::new(),
sun_sensors: Vec::new(),
}
}
pub fn evaluate(&mut self, state: &SpacecraftState, epoch: &Epoch) -> Sensors {
Sensors {
magnetometers: self
.magnetometers
.iter_mut()
.map(|m| m.measure(state, epoch))
.collect(),
gyroscopes: self
.gyroscopes
.iter_mut()
.map(|g| g.measure(state, epoch))
.collect(),
star_trackers: self
.star_trackers
.iter_mut()
.map(|s| s.measure(state, epoch))
.collect(),
sun_sensors: self
.sun_sensors
.iter_mut()
.map(|s| s.measure(state, epoch))
.collect(),
}
}
}
impl Default for SensorBundle {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::attitude::AttitudeState;
use crate::orbital::OrbitalState;
use nalgebra::{Vector3, Vector4};
use std::sync::Arc;
use tobari::magnetic::TiltedDipole;
fn make_state() -> SpacecraftState {
SpacecraftState {
orbit: OrbitalState::new(Vector3::new(7000.0, 0.0, 0.0), Vector3::new(0.0, 7.5, 0.0)),
attitude: AttitudeState {
quaternion: Vector4::new(1.0, 0.0, 0.0, 0.0),
angular_velocity: Vector3::new(0.1, 0.05, -0.03),
},
mass: 50.0,
}
}
#[test]
fn empty_bundle_produces_empty_vecs() {
let mut bundle = SensorBundle::new();
let epoch = Epoch::j2000();
let state = make_state();
let readings = bundle.evaluate(&state, &epoch);
assert!(readings.magnetometers.is_empty());
assert!(readings.gyroscopes.is_empty());
assert!(readings.star_trackers.is_empty());
}
#[test]
fn single_sensor_produces_one_reading() {
let mut bundle = SensorBundle {
magnetometers: vec![Magnetometer::new(Arc::new(TiltedDipole::earth()))],
gyroscopes: vec![Gyroscope::new()],
star_trackers: Vec::new(),
sun_sensors: Vec::new(),
};
let epoch = Epoch::j2000();
let state = make_state();
let readings = bundle.evaluate(&state, &epoch);
assert_eq!(readings.magnetometers.len(), 1);
assert_eq!(readings.gyroscopes.len(), 1);
assert!(readings.star_trackers.is_empty());
}
#[test]
fn multiple_gyroscopes() {
let mut bundle = SensorBundle {
magnetometers: Vec::new(),
gyroscopes: vec![Gyroscope::new(), Gyroscope::new()],
star_trackers: Vec::new(),
sun_sensors: Vec::new(),
};
let epoch = Epoch::j2000();
let state = make_state();
let readings = bundle.evaluate(&state, &epoch);
assert_eq!(readings.gyroscopes.len(), 2);
assert_eq!(readings.gyroscopes[0], readings.gyroscopes[1]);
}
}