use crate::dialect::position_target_typemask as bits;
use crate::dialect::{SetPositionTargetGlobalInt, SetPositionTargetLocalNed};
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct TypeMask(u16);
impl TypeMask {
const ALL_IGNORE: u16 = bits::X_IGNORE
| bits::Y_IGNORE
| bits::Z_IGNORE
| bits::VX_IGNORE
| bits::VY_IGNORE
| bits::VZ_IGNORE
| bits::AX_IGNORE
| bits::AY_IGNORE
| bits::AZ_IGNORE
| bits::YAW_IGNORE
| bits::YAW_RATE_IGNORE;
pub fn ignore_all() -> Self {
TypeMask(Self::ALL_IGNORE)
}
pub fn use_position(mut self) -> Self {
self.0 &= !(bits::X_IGNORE | bits::Y_IGNORE | bits::Z_IGNORE);
self
}
pub fn use_velocity(mut self) -> Self {
self.0 &= !(bits::VX_IGNORE | bits::VY_IGNORE | bits::VZ_IGNORE);
self
}
pub fn use_acceleration(mut self) -> Self {
self.0 &= !(bits::AX_IGNORE | bits::AY_IGNORE | bits::AZ_IGNORE);
self
}
pub fn use_yaw(mut self) -> Self {
self.0 &= !bits::YAW_IGNORE;
self
}
pub fn use_yaw_rate(mut self) -> Self {
self.0 &= !bits::YAW_RATE_IGNORE;
self
}
pub fn force(mut self) -> Self {
self.0 |= bits::FORCE_SET;
self
}
pub fn bits(self) -> u16 {
self.0
}
}
impl SetPositionTargetLocalNed {
pub fn position(
time_boot_ms: u32,
coordinate_frame: u8,
target_system: u8,
target_component: u8,
x: f32,
y: f32,
z: f32,
) -> Self {
SetPositionTargetLocalNed {
time_boot_ms,
x,
y,
z,
type_mask: TypeMask::ignore_all().use_position().bits(),
target_system,
target_component,
coordinate_frame,
..Self::zeroed()
}
}
pub fn velocity(
time_boot_ms: u32,
coordinate_frame: u8,
target_system: u8,
target_component: u8,
vx: f32,
vy: f32,
vz: f32,
) -> Self {
SetPositionTargetLocalNed {
time_boot_ms,
vx,
vy,
vz,
type_mask: TypeMask::ignore_all().use_velocity().bits(),
target_system,
target_component,
coordinate_frame,
..Self::zeroed()
}
}
}
impl SetPositionTargetGlobalInt {
pub fn position(
time_boot_ms: u32,
coordinate_frame: u8,
target_system: u8,
target_component: u8,
lat_int: i32,
lon_int: i32,
alt: f32,
) -> Self {
SetPositionTargetGlobalInt {
time_boot_ms,
lat_int,
lon_int,
alt,
type_mask: TypeMask::ignore_all().use_position().bits(),
target_system,
target_component,
coordinate_frame,
..Self::zeroed()
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::dialect::mav_frame;
#[test]
fn ignore_all_sets_every_dimension_but_the_force_flag() {
let mask = TypeMask::ignore_all().bits();
assert_eq!(mask & bits::X_IGNORE, bits::X_IGNORE);
assert_eq!(mask & bits::VZ_IGNORE, bits::VZ_IGNORE);
assert_eq!(mask & bits::YAW_RATE_IGNORE, bits::YAW_RATE_IGNORE);
assert_eq!(mask & bits::FORCE_SET, 0);
}
#[test]
fn a_position_mask_enables_only_the_position_bits() {
let mask = TypeMask::ignore_all().use_position().bits();
assert_eq!(mask & (bits::X_IGNORE | bits::Y_IGNORE | bits::Z_IGNORE), 0);
assert_eq!(mask & bits::VX_IGNORE, bits::VX_IGNORE);
assert_eq!(mask & bits::AX_IGNORE, bits::AX_IGNORE);
assert_eq!(mask & bits::YAW_IGNORE, bits::YAW_IGNORE);
assert_eq!(mask, TypeMask::ALL_IGNORE & !(1 | 2 | 4));
}
#[test]
fn a_velocity_setpoint_ignores_position() {
let setpoint =
SetPositionTargetLocalNed::velocity(1000, mav_frame::LOCAL_NED, 1, 1, 0.5, 0.0, -0.2);
assert_eq!(setpoint.vx, 0.5);
assert_eq!(setpoint.vz, -0.2);
assert_eq!(setpoint.type_mask & bits::X_IGNORE, bits::X_IGNORE);
assert_eq!(setpoint.type_mask & bits::VX_IGNORE, 0);
}
#[test]
fn a_global_position_setpoint_carries_scaled_coordinates() {
let setpoint = SetPositionTargetGlobalInt::position(
2000,
mav_frame::GLOBAL_RELATIVE_ALT_INT,
1,
1,
473_977_418,
85_455_939,
10.0,
);
assert_eq!(setpoint.lat_int, 473_977_418);
assert_eq!(setpoint.alt, 10.0);
assert_eq!(
setpoint.type_mask & (bits::X_IGNORE | bits::Y_IGNORE | bits::Z_IGNORE),
0
);
}
}