mod communication;
mod navdata;
mod droneconfig;
mod internal_config;
mod format;
pub use navdata::*;
pub use format::*;
pub use communication::*;
pub use internal_config::*;
pub enum VideoCodec {
MP4_360p,
H264_360p,
MP4_360pH264_720p,
MP4_360pH264_360p,
H264_720p,
}
pub struct Drone {
communication: communication::Communication,
navdata: navdata::NavData,
config: droneconfig::DroneConfig,
i_config: internal_config::InternalConfig,
}
impl Drone {
pub fn new() -> Drone {
Drone {
communication: communication::Communication::new(),
navdata: navdata::NavData::new(),
config: droneconfig::DroneConfig::new(),
i_config: internal_config::InternalConfig::new(),
}
}
pub fn startup(&mut self) -> Result<(), String> {
if !self.communication.try_connection() {
return Err(String::from("Drone is not online!"));
}
match self.communication.start_connection(&self.i_config.show_commands) {
Ok(()) => { }
Err(s) => { return Err(s); }
}
match self.communication.get_ctl_tcp_connection() {
Ok(stream) => { self.config.start_config_listening_thread(stream); }
Err(s) => { return Err(s); }
}
match self.communication.get_navdata_udp_connection() {
Ok(stream) => { self.navdata.start_navdata_listening_thread(stream, self.i_config.debug)}
Err(s) => { return Err(s); }
}
self.use_demo_mode(true);
self.communication.command_str("CTRL", vec!["5", "0"]);
self.set_config_str("custom:session_id", "-all");
self.communication.command_str("CTRL", vec!["5", "0"]);
self.update_config();
Ok(())
}
fn shutdown(&mut self) {
self.navdata.stop_navdata_listening_thread();
self.config.stop_config_listening_thread();
self.communication.shutdown_connection();
}
pub fn trim(&mut self) {
self.communication.command("FTRIM", Vec::new());
}
pub fn mtrim(&mut self) {
self.communication.command("CALIB", vec![String::from("0")]);
}
pub fn mantrim(&mut self, theta: f32, phi: f32, yaw: f32) {
self.communication.command(
"MTRIM",
vec![format_float(theta),
format_float(phi),
format_float(yaw)]
);
}
pub fn mov(&mut self, left_right: f32, back_front: f32, down_up: f32, turn_left_right: f32) {
let mut l_r = left_right;
let mut b_f = back_front;
let mut d_u = down_up;
let mut t_l_r = turn_left_right;
if left_right.abs() > 1.0 {
l_r = left_right / left_right.abs();
}
if back_front.abs() > 1.0 {
b_f = back_front / back_front.abs();
}
if down_up.abs() > 1.0 {
d_u = down_up / down_up.abs();
}
if t_l_r.abs() > 1.0 {
t_l_r = turn_left_right / turn_left_right.abs();
}
self.communication.command("PCMD",
vec![
format_int(3),
format_float(l_r),
format_float(-b_f),
format_float(d_u),
format_float(t_l_r)
]);
}
pub fn rel_mov(&mut self, left_right: f32, back_front: f32, down_up: f32, turn_left_right: f32, east_west: f32, north_ta_accuracy: f32) {
let mut l_r = left_right;
let mut b_f = back_front;
let mut d_u = down_up;
let mut t_l_r = turn_left_right;
let mut e_w = east_west;
let mut n_ta_a = north_ta_accuracy;
if left_right.abs() > 1.0 {
l_r = left_right / left_right.abs();
}
if back_front.abs() > 1.0 {
b_f = back_front / back_front.abs();
}
if down_up.abs() > 1.0 {
d_u = down_up / down_up.abs();
}
if turn_left_right.abs() > 1.0 {
t_l_r = turn_left_right / turn_left_right.abs();
}
if east_west.abs() > 1.0 {
e_w = east_west / east_west.abs();
}
if north_ta_accuracy.abs() > 1.0 {
n_ta_a = north_ta_accuracy / north_ta_accuracy.abs();
}
self.communication.command("PCMD_MAG",
vec![
format_int(1),
format_float(l_r),
format_float(-b_f),
format_float(d_u),
format_float(t_l_r),
format_float(e_w),
format_float(n_ta_a)
]);
}
pub fn hover(&mut self) {
self.mov(0.0, 0.0, 0.0, 0.0);
}
pub fn stop(&mut self) {
self.hover();
}
pub fn mov_right(&mut self, speed: f32) {
self.mov(speed, 0.0, 0.0, 0.0);
}
pub fn mov_left(&mut self, speed: f32) {
self.mov(-speed, 0.0, 0.0, 0.0);
}
pub fn mov_forward(&mut self, speed: f32) {
self.mov(0.0, speed, 0.0, 0.0);
}
pub fn mov_backward(&mut self, speed: f32) {
self.mov(0.0, -speed, 0.0, 0.0);
}
pub fn mov_up(&mut self, speed: f32) {
self.mov(0.0, 0.0, speed, 0.0);
}
pub fn mov_down(&mut self, speed: f32) {
self.mov(0.0, 0.0, -speed, 0.0);
}
pub fn move_right(&mut self) {
self.mov(self.i_config.speed, 0.0, 0.0, 0.0);
}
pub fn move_left(&mut self) {
self.mov(-self.i_config.speed, 0.0, 0.0, 0.0);
}
pub fn move_forward(&mut self) {
self.mov(0.0, self.i_config.speed, 0.0, 0.0);
}
pub fn move_backward(&mut self) {
self.mov(0.0, -self.i_config.speed, 0.0, 0.0);
}
pub fn move_up(&mut self) {
self.mov(0.0, 0.0, self.i_config.speed, 0.0);
}
pub fn move_down(&mut self) {
self.mov(0.0, 0.0, -self.i_config.speed, 0.0);
}
pub fn turn_right(&mut self, turn_rate: f32) {
self.mov(0.0, 0.0, 0.0, turn_rate);
}
pub fn turn_left(&mut self, turn_rate: f32) {
self.mov(0.0, 0.0, 0.0, -turn_rate);
}
pub fn takeoff(&mut self) {
self.communication.command("REF", vec![String::from("290718208")]);
}
pub fn land(&mut self) {
self.communication.command("REF", vec![String::from("290717696")]);
}
pub fn reset(&mut self) {
self.communication.command("REF", vec![String::from("290717952")]);
}
pub fn led(&mut self, anim: usize, frequency: f32, duration: i32) {
if anim < 21 && frequency > 0.0 && duration > 0 {
self.communication.command("LED", vec![
format_int(anim as i32),
format_float(frequency),
format_int(duration)]);
}
}
pub fn anim(&mut self, anim: usize, duration: i32) {
if anim < 20 && duration > 0 {
self.communication.command("ANIM", vec![
format_int(anim as i32),
format_int(duration)]);
}
}
pub fn manual_engine(&mut self, fl: u32, fr: u32, rl: u32, rr: u32) {
let mut fl = fl;
if fl > 1023 {
fl = 1023;
}
let mut fr = fr;
if fr > 1023 {
fr = 1023;
}
let mut rl = rl;
if rl > 1023 {
rl = 1023;
}
let mut rr = rr;
if rr > 1023 {
rr = 1023;
}
self.communication.command("PWM", vec![
format_int(fl as i32),
format_int(fr as i32),
format_int(rl as i32),
format_int(rr as i32)
])
}
pub fn aflight(&mut self, flag: bool) {
if flag {
self.communication.command_str("AFLIGHT", vec!["1"]);
} else {
self.communication.command_str("AFLIGHT", vec!["0"]);
}
}
pub fn set_speed(&mut self, speed: f32) {
if speed.abs() > 1.0 {
self.i_config.speed = 1.0;
} else {
self.i_config.speed = speed.abs();
}
}
pub fn update_config(&mut self) {
self.communication.command_str("CTRL", vec!["5", "0"]);
self.communication.command_str("CTRL", vec!["4", "0"]);
}
pub fn get_offline_config(&mut self, config_name: &str) -> Option<String> {
self.config.get_config_str(config_name)
}
pub fn send_config_ids(&mut self) {
self.communication.command("CONFIG_IDS",
vec![
format_string(self.config.session_id.clone()),
format_string(self.config.user_id.clone()),
format_string(self.config.application_id.clone()),
]);
}
pub fn set_config(&mut self, config_name: &str, config_value: String) {
self.communication.command("CONFIG",
vec![
format!("\"{}\"", config_name),
format!("\"{}\"", config_value)
]);
}
pub fn set_config_str(&mut self, config_name: &str, config_value: &str) {
self.communication.command("CONFIG",
vec![
format!("\"{}\"", config_name),
format!("\"{}\"", config_value)
]);
}
pub fn use_demo_mode(&mut self, value: bool) {
if value {
self.set_config_str("general:navdata_demo", "TRUE");
} else {
self.set_config_str("general:navdata_demo", "FALSE");
}
}
pub fn set_video_codec(&mut self, codec: VideoCodec) {
let s;
match codec {
VideoCodec::MP4_360p => {
s = "128";
}
VideoCodec::H264_360p => {
s = "129";
}
VideoCodec::H264_720p => {
s = "131";
}
VideoCodec::MP4_360pH264_720p => {
s = "130";
}
VideoCodec::MP4_360pH264_360p => {
s = "136";
}
}
self.set_config_str("video:video_codec", s);
}
pub fn set_hd_video_stream(&mut self) {
self.set_video_codec(VideoCodec::H264_720p);
}
pub fn set_sd_video_stream(&mut self) {
self.set_video_codec(VideoCodec::H264_360p);
}
pub fn set_mp4_video_stream(&mut self) {
self.set_video_codec(VideoCodec::MP4_360p);
}
pub fn set_hd_video_capture(&mut self) {
self.set_video_codec(VideoCodec::MP4_360pH264_720p);
}
pub fn set_sd_video_capture(&mut self) {
self.set_video_codec(VideoCodec::MP4_360pH264_360p);
}
pub fn set_video_fps(&mut self, fps: u32) {
let mut real_fps = fps;
if fps > 60 || fps == 0 {
real_fps = 60;
}
self.set_config("video:codec_fps", format!("{}", real_fps));
}
pub fn set_video_bitrate(&mut self, bitrate: u32) {
let mut real_bitrate = bitrate;
if bitrate > 20000 {
real_bitrate = 20000;
} else if bitrate < 250 {
real_bitrate = 250;
}
self.set_config("video:bitrate", format!("{}", real_bitrate));
}
pub fn use_front_cam(&mut self) {
self.set_config_str("video:video_channel", "0");
}
pub fn use_ground_cam(&mut self) {
self.set_config_str("video:video_channel", "1");
}
pub fn get_navdata(&mut self, name: &str) -> Option<navdata::NavDataValue> {
self.navdata.get_navdata_str(name)
}
}
impl Drop for Drone {
fn drop(&mut self) {
self.shutdown();
}
}