use arika::frame::{Body, Vec3};
#[derive(Debug, Clone, PartialEq)]
pub struct Command {
pub magnetic_moment: Option<Vec3<Body>>,
pub rw_torque: Option<Vec3<Body>>,
}
impl Command {
pub fn magnetic_moment(m: Vec3<Body>) -> Self {
Self {
magnetic_moment: Some(m),
rw_torque: None,
}
}
pub fn rw_torque(t: Vec3<Body>) -> Self {
Self {
magnetic_moment: None,
rw_torque: Some(t),
}
}
pub fn is_finite(&self) -> bool {
let mm_ok = self.magnetic_moment.is_none_or(|m| m.is_finite());
let rw_ok = self.rw_torque.is_none_or(|t| t.is_finite());
mm_ok && rw_ok
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn magnetic_moment_finite_detects_nan() {
let good = Command::magnetic_moment(Vec3::new(1.0, -2.0, 0.0));
assert!(good.is_finite());
let nan = Command::magnetic_moment(Vec3::new(1.0, f64::NAN, 0.0));
assert!(!nan.is_finite());
let inf = Command::magnetic_moment(Vec3::new(f64::INFINITY, 0.0, 0.0));
assert!(!inf.is_finite());
}
#[test]
fn rw_torque_finite_detects_nan() {
let good = Command::rw_torque(Vec3::new(0.01, -0.02, 0.0));
assert!(good.is_finite());
let nan = Command::rw_torque(Vec3::new(f64::NAN, 0.0, 0.0));
assert!(!nan.is_finite());
}
#[test]
fn field_access() {
let mm = Command::magnetic_moment(Vec3::new(1.0, 2.0, 3.0));
assert!(mm.magnetic_moment.is_some());
assert!(mm.rw_torque.is_none());
let rw = Command::rw_torque(Vec3::new(0.1, 0.2, 0.3));
assert!(rw.magnetic_moment.is_none());
assert!(rw.rw_torque.is_some());
}
#[test]
fn both_fields_set() {
let cmd = Command {
magnetic_moment: Some(Vec3::new(1.0, 0.0, 0.0)),
rw_torque: Some(Vec3::new(0.0, 0.1, 0.0)),
};
assert!(cmd.is_finite());
assert!(cmd.magnetic_moment.is_some());
assert!(cmd.rw_torque.is_some());
}
#[test]
fn both_fields_nan_in_one() {
let cmd = Command {
magnetic_moment: Some(Vec3::new(f64::NAN, 0.0, 0.0)),
rw_torque: Some(Vec3::new(0.0, 0.1, 0.0)),
};
assert!(!cmd.is_finite());
}
}