use crazyflie_link::Packet;
use flume::Sender;
use crate::{Error, Result};
use crate::crazyflie::COMMANDER_PORT;
use crate::crazyflie::GENERIC_SETPOINT_PORT;
const RPYT_CHANNEL: u8 = 0;
const GENERIC_SETPOINT_CHANNEL: u8 = 0;
const GENERIC_CMD_CHANNEL: u8 = 1;
const TYPE_POSITION: u8 = 7;
const TYPE_VELOCITY_WORLD: u8 = 8;
const TYPE_ZDISTANCE: u8 = 9;
const TYPE_HOVER: u8 = 10;
const TYPE_MANUAL: u8 = 11;
const TYPE_STOP: u8 = 0;
const TYPE_META_COMMAND_NOTIFY_SETPOINT_STOP: u8 = 0;
#[derive(Debug)]
pub struct Commander {
uplink: Sender<Packet>,
}
impl Commander {
pub(crate) fn new(uplink: Sender<Packet>) -> Self {
Self { uplink }
}
}
impl Commander {
pub async fn setpoint_rpyt(&self, roll: f32, pitch: f32, yawrate: f32, thrust: u16) -> Result<()> {
let mut payload = Vec::new();
payload.append(&mut roll.to_le_bytes().to_vec());
payload.append(&mut (-pitch).to_le_bytes().to_vec());
payload.append(&mut yawrate.to_le_bytes().to_vec());
payload.append(&mut thrust.to_le_bytes().to_vec());
let pk = Packet::new(COMMANDER_PORT, RPYT_CHANNEL, payload);
self.uplink
.send_async(pk)
.await
.map_err(|_| Error::Disconnected)?;
Ok(())
}
}
impl Commander {
pub async fn setpoint_position(&self, x: f32, y: f32, z: f32, yaw: f32) -> Result<()> {
let mut payload = Vec::with_capacity(1 + 4 * 4);
payload.push(TYPE_POSITION);
payload.extend_from_slice(&x.to_le_bytes());
payload.extend_from_slice(&y.to_le_bytes());
payload.extend_from_slice(&z.to_le_bytes());
payload.extend_from_slice(&yaw.to_le_bytes());
let pk = Packet::new(GENERIC_SETPOINT_PORT, GENERIC_SETPOINT_CHANNEL, payload);
self.uplink.send_async(pk).await.map_err(|_| Error::Disconnected)?;
Ok(())
}
pub async fn setpoint_velocity_world(&self, vx: f32, vy: f32, vz: f32, yawrate: f32) -> Result<()> {
let mut payload = Vec::with_capacity(1 + 4 * 4);
payload.push(TYPE_VELOCITY_WORLD);
payload.extend_from_slice(&vx.to_le_bytes());
payload.extend_from_slice(&vy.to_le_bytes());
payload.extend_from_slice(&vz.to_le_bytes());
payload.extend_from_slice(&yawrate.to_le_bytes());
let pk = Packet::new(GENERIC_SETPOINT_PORT, GENERIC_SETPOINT_CHANNEL, payload);
self.uplink.send_async(pk).await.map_err(|_| Error::Disconnected)?;
Ok(())
}
pub async fn setpoint_zdistance(&self, roll: f32, pitch: f32, yawrate: f32, zdistance: f32) -> Result<()> {
let mut payload = Vec::with_capacity(1 + 4 * 4);
payload.push(TYPE_ZDISTANCE);
payload.extend_from_slice(&roll.to_le_bytes());
payload.extend_from_slice(&pitch.to_le_bytes());
payload.extend_from_slice(&yawrate.to_le_bytes());
payload.extend_from_slice(&zdistance.to_le_bytes());
let pk = Packet::new(GENERIC_SETPOINT_PORT, GENERIC_SETPOINT_CHANNEL, payload);
self.uplink.send_async(pk).await.map_err(|_| Error::Disconnected)?;
Ok(())
}
pub async fn setpoint_hover(&self, vx: f32, vy: f32, yawrate: f32, zdistance: f32) -> Result<()> {
let mut payload = Vec::with_capacity(1 + 4 * 4);
payload.push(TYPE_HOVER);
payload.extend_from_slice(&vx.to_le_bytes());
payload.extend_from_slice(&vy.to_le_bytes());
payload.extend_from_slice(&yawrate.to_le_bytes());
payload.extend_from_slice(&zdistance.to_le_bytes());
let pk = Packet::new(GENERIC_SETPOINT_PORT, GENERIC_SETPOINT_CHANNEL, payload);
self.uplink.send_async(pk).await.map_err(|_| Error::Disconnected)?;
Ok(())
}
pub async fn setpoint_manual(&self, roll: f32, pitch: f32, yawrate: f32, thrust_percentage: f32, rate: bool) -> Result<()> {
let thrust = 10001.0 + 0.01 * thrust_percentage * (60000.0 - 10001.0);
let thrust_16 = thrust as u16;
let mut payload = Vec::with_capacity(1 + 4 * 3 + 2 + 1);
payload.push(TYPE_MANUAL);
payload.extend_from_slice(&roll.to_le_bytes());
payload.extend_from_slice(&pitch.to_le_bytes());
payload.extend_from_slice(&yawrate.to_le_bytes());
payload.extend_from_slice(&thrust_16.to_le_bytes());
payload.push(rate as u8);
let pk = Packet::new(GENERIC_SETPOINT_PORT, GENERIC_SETPOINT_CHANNEL, payload);
self.uplink.send_async(pk).await.map_err(|_| Error::Disconnected)?;
Ok(())
}
pub async fn setpoint_stop(&self) -> Result<()> {
let payload = vec![TYPE_STOP];
let pk = Packet::new(GENERIC_SETPOINT_PORT, GENERIC_SETPOINT_CHANNEL, payload);
self.uplink.send_async(pk).await.map_err(|_| Error::Disconnected)?;
Ok(())
}
pub async fn notify_setpoint_stop(&self, remain_valid_milliseconds: u32) -> Result<()> {
let mut payload = Vec::with_capacity(1 + 4);
payload.push(TYPE_META_COMMAND_NOTIFY_SETPOINT_STOP);
payload.extend_from_slice(&remain_valid_milliseconds.to_le_bytes());
let pk = Packet::new(GENERIC_SETPOINT_PORT, GENERIC_CMD_CHANNEL, payload);
self.uplink.send_async(pk).await.map_err(|_| Error::Disconnected)?;
Ok(())
}
}