大疆旗下最便宜的无人机品牌 tello 采用了英特尔的视觉处理芯片,虽然相比于大疆御、悟等系列,功能简陋。但比起与其它如小米和华强北的众多品牌,可算的上非常有用的玩具了。
大疆的 tello 无人机也提供了可编程的接口,官方已经支持了 Scratch 图形化编程。由此分析,我们可以得出 tello 无人机实际上提供了 2 个接口:tello 无人机应用程序使用的基于文本的接口,以及一个非公共接口。因为提供了开放的接口,才能和图形化编程进行文本交互,实现用户的编程控制。在 tellopilots 论坛(微信公众号不能贴连接,请自行搜索),有玩家做了很棒的工作,对 tello edu app 的编程界面进行了反向工程,从而可以支持其它诸如 python、golang 等……
但本文讨论的主角是 Rust。
因为 tello 无人机是通过网络协议与操作器(手机、手柄等)交互通信的。因此,我们可以结合其网络协议与无人机进行通信,并获得可用的元数据。
当然,籍此拓展思维之上,我们也可以提供一个远程控制框架,用键盘或操纵杆来控制。甚至更为简化,命令组合为批处理方式,然后简单触发(想象一下好莱坞大片)。
我们简单尝试下,从原理分析,到编码实现——
和 tello 无人机通信
首先,请保证无人机在明亮的环境中翻转、反弹……
其次,我们分析下和 tello 无人机的沟通原理:当 tello 无人机得到一个启动命令包(drone.connect(11111);)时,tello 无人机会在两个 UDP 通道上发送数据。命令通道 A(端口:8889)和视频通道 B(WIP)(端口:11111)。在 AP 模式下,tello 无人机将以默认 ip 192.168.10.1 出现。
再次,所有发送、呼叫都是同步完成的。如果要接收数据,则必须轮询无人机。如下示例:
use tello::{Drone, Message, Package, PackageData, ResponseMsg};
use std::time::Duration;
fn main() -> Result<(), String> {
let mut drone = Drone::new("192.168.10.1:8889");
drone.connect(11111);
loop {
if let Some(msg) = drone.poll() {
match msg {
Message::Data(Package {data: PackageData::FlightData(d), ..}) => {
println!("battery {}", d.battery_percentage);
}
Message::Response(ResponseMsg::Connected(_)) => {
println!("connected");
drone.throw_and_go().unwrap();
}
_ => ()
}
}
::std::thread::sleep(Duration::new(0, 1_000_000_000u32 / 20));
}
}
远程控制
对无人机轮询时,不仅要接收来自无人机的消息,还将发送一些默认设置、回复确认、触发关键帧,或发送实时移动命令等远程控制状态。
我们可以使用 SDL 打开窗口,处理键盘输入,并显示如何连接游戏板或操纵杆等。
但我要出门试验去了,远程控制放以后讨论 :-)。
谢谢您的阅读。