use simple_bitset::BitSet64;
use vqm::{Quaternionf32, Vector3f32, Vector4f32};
#[derive(Clone, Copy, Debug, PartialEq)]
#[repr(C)]
pub struct GyroPidMessage {
pub orientation: Quaternionf32,
pub motor_commands: Vector4f32,
pub acc: Vector3f32,
pub gyro_rps: Vector3f32,
pub gyro_rps_unfiltered: Vector3f32,
pub pid_errors_p: [f32; Self::RPY_AXIS_COUNT],
pub pid_errors_i: [f32; Self::RPY_AXIS_COUNT],
pub pid_errors_d: [f32; Self::RP_AXIS_COUNT],
pub time_us: u64,
}
const _: () = assert!(core::mem::size_of::<GyroPidMessage>() == 112);
impl Default for GyroPidMessage {
fn default() -> Self {
Self::new()
}
}
impl GyroPidMessage {
pub const RPY_AXIS_COUNT: usize = 3;
pub const RP_AXIS_COUNT: usize = 2;
#[must_use]
pub const fn new() -> Self {
Self {
orientation: Quaternionf32::new(0.0, 0.0, 0.0, 0.0),
motor_commands: Vector4f32::new(0.0, 0.0, 0.0, 0.0),
acc: Vector3f32::new(0.0, 0.0, 0.0),
gyro_rps: Vector3f32::new(0.0, 0.0, 0.0),
gyro_rps_unfiltered: Vector3f32::new(0.0, 0.0, 0.0),
pid_errors_p: [0f32; Self::RPY_AXIS_COUNT],
pid_errors_i: [0f32; Self::RPY_AXIS_COUNT],
pid_errors_d: [0f32; Self::RP_AXIS_COUNT],
time_us: 0,
}
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
#[repr(C)]
pub struct SetpointMessage {
pub setpoints: [f32; Self::SETPOINT_COUNT],
pub pid_errors_s: [f32; Self::RPY_AXIS_COUNT],
pub pid_errors_k: [f32; Self::RPY_AXIS_COUNT],
pub rc_commands: [u16; Self::RC_COMMAND_COUNT],
#[cfg(feature = "dshot_telemetry")]
pub motor_rpm_d2: [i16; Self::MAX_SUPPORTED_MOTOR_COUNT], #[cfg(feature = "servos")]
pub servos: [i16; Self::MAX_SUPPORTED_SERVO_COUNT],
pub time_us: u64,
pub rc_modes: BitSet64,
pub gps_state_flags: u8,
pub failsafe_phase: u8,
pub rx_signal_received: bool,
pub rx_flight_channel_is_valid: bool,
}
impl Default for SetpointMessage {
fn default() -> Self {
Self::new()
}
}
#[allow(unused)]
impl SetpointMessage {
pub const RC_COMMAND_COUNT: usize = 4;
pub const SETPOINT_COUNT: usize = 4;
pub const THROTTLE: usize = 3;
pub const RPY_AXIS_COUNT: usize = 3;
#[cfg(feature = "eight_motors")]
pub const MAX_SUPPORTED_MOTOR_COUNT: usize = 8;
#[cfg(not(feature = "eight_motors"))]
pub const MAX_SUPPORTED_MOTOR_COUNT: usize = 4;
#[cfg(feature = "servos")]
pub const MAX_SUPPORTED_SERVO_COUNT: usize = 8;
#[must_use]
pub const fn new() -> Self {
Self {
setpoints: [0.0; Self::SETPOINT_COUNT],
pid_errors_s: [0.0; Self::RPY_AXIS_COUNT],
pid_errors_k: [0.0; Self::RPY_AXIS_COUNT],
rc_commands: [1500, 1500, 1500, 1000],
#[cfg(feature = "dshot_telemetry")]
motor_rpm_d2: [0i16; Self::MAX_SUPPORTED_MOTOR_COUNT],
#[cfg(feature = "servos")]
servos: [0i16; Self::MAX_SUPPORTED_SERVO_COUNT],
time_us: 0,
rc_modes: BitSet64::new(),
gps_state_flags: 0,
failsafe_phase: 0,
rx_signal_received: false,
rx_flight_channel_is_valid: false,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
fn _is_normal<T: Sized + Send + Sync + Unpin>() {}
fn is_full<T: Sized + Send + Sync + Unpin + Copy + Clone + Default + PartialEq>() {}
#[test]
fn normal_types() {
is_full::<GyroPidMessage>();
is_full::<SetpointMessage>();
}
#[test]
fn sizeof() {
assert_eq!(112, core::mem::size_of::<GyroPidMessage>());
#[cfg(all(feature = "dshot_telemetry", not(any(feature = "servos", feature = "eight_motors"))))]
assert_eq!(80, core::mem::size_of::<SetpointMessage>());
}
#[test]
fn gyro_pid_message_new() {
let telemetry_data = GyroPidMessage::default();
assert_eq!(0, telemetry_data.time_us);
}
}