use serde::Serialize;
#[derive(Serialize)]
pub struct Msg {
timestamp: f64,
imu: Imu,
position: [f64; 3],
velocity: [f64; 3],
quaternion: [f64; 4],
#[serde(skip_serializing_if = "Option::is_none")]
rng_1: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
rng_2: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
rng_3: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
rng_4: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
rng_5: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
rng_6: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
windvane: Option<Windvane>,
#[serde(skip_serializing_if = "Option::is_none")]
velocity_wind: Option<[f64; 3]>,
#[serde(skip_serializing_if = "Option::is_none")]
airspeed: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
rc: Option<RcInput>,
#[serde(skip_serializing_if = "Option::is_none")]
battery: Option<Battery>,
}
#[derive(Serialize)]
struct Imu {
gyro: [f64; 3],
accel_body: [f64; 3],
}
impl Imu {
fn new(gyro: [f64; 3], acc: [f64; 3]) -> Self {
Self {
gyro,
accel_body: acc,
}
}
}
#[derive(Serialize)]
pub struct Windvane {
direction: f64,
speed: f64,
}
impl Windvane {
pub fn new(direction: f64, speed: f64) -> Self {
Self { direction, speed }
}
}
#[derive(Serialize)]
pub struct RcInput {
rc_1: u16,
rc_2: u16,
rc_3: u16,
rc_4: u16,
rc_5: u16,
rc_6: u16,
rc_7: u16,
rc_8: u16,
rc_9: u16,
rc_10: u16,
rc_11: u16,
rc_12: u16,
}
impl RcInput {
pub fn new(channels: [u16; 12]) -> Self {
Self {
rc_1: channels[0],
rc_2: channels[1],
rc_3: channels[2],
rc_4: channels[3],
rc_5: channels[4],
rc_6: channels[5],
rc_7: channels[6],
rc_8: channels[7],
rc_9: channels[8],
rc_10: channels[9],
rc_11: channels[10],
rc_12: channels[11],
}
}
}
#[derive(Serialize)]
pub struct Battery {
voltage: f64,
current: f64,
}
impl Battery {
pub fn new(voltage: f64, current: f64) -> Self {
Self { voltage, current }
}
}
impl Msg {
pub fn new(
timestamp: f64,
gyro: [f64; 3],
accel_body: [f64; 3],
position: [f64; 3],
velocity: [f64; 3],
quaternion: [f64; 4],
) -> Self {
Self {
timestamp,
imu: Imu::new(gyro, accel_body),
position,
velocity,
quaternion,
rng_1: None,
rng_2: None,
rng_3: None,
rng_4: None,
rng_5: None,
rng_6: None,
windvane: None,
velocity_wind: None,
airspeed: None,
rc: None,
battery: None,
}
}
pub fn with_rangefinder(mut self, idx: usize, meters: f64) -> Self {
match idx {
1 => self.rng_1 = Some(meters),
2 => self.rng_2 = Some(meters),
3 => self.rng_3 = Some(meters),
4 => self.rng_4 = Some(meters),
5 => self.rng_5 = Some(meters),
6 => self.rng_6 = Some(meters),
_ => panic!("rangefinder index must be 1..=6"),
}
self
}
pub fn with_windvane(mut self, direction: f64, speed: f64) -> Self {
self.windvane = Some(Windvane::new(direction, speed));
self
}
pub fn with_wind_velocity(mut self, velocity: [f64; 3]) -> Self {
self.velocity_wind = Some(velocity);
self
}
pub fn with_airspeed(mut self, airspeed: f64) -> Self {
self.airspeed = Some(airspeed);
self
}
pub fn with_rc(mut self, channels: [u16; 12]) -> Self {
self.rc = Some(RcInput::new(channels));
self
}
pub fn with_battery(mut self, voltage: f64, current: f64) -> Self {
self.battery = Some(Battery::new(voltage, current));
self
}
}