ar-drone:GitHub上劫持控制无人机的开源项目

ar-drone:GitHub上劫持控制无人机的开源项目

ar-drone是Parrot ARDrone 2.0使用协议的实现方式,同时也兼容1.0版本。

通过Github安装最新版本:

npm install git://github.com/felixge/node-ar-drone.git

或者,用户不需要一些前沿的功能,也可以使用以下命令进行安装:

npm install ar-drone

简介

AR Drone是一种价格实惠、功能完善的四轴飞行器,使用一种专有的固件,使用户可以通过官方的FreeFlight手机应用借助WIFI进行控制。

不同于固件,它的客户端协议是开源的,Parrot发布了一款包含大量文档和C代码的SDK。他们的目标用户是移动开发人员,使他们可以使用该SDK开发可以无线控制的游戏和应用。同时,该协议也可用于接收视频和传感器数据,使开发人员可以编写自动化程序,应对即将到来的“机器人革命”。

状态

该协议仍处于开发过程中,所以可能会出现功能缺失。但是,已开发部分已通过测试,并且在大多数地区可以正常工作。

客户端

该部分提供了一个高级的客户端API,以便支持所有的无人机功能。

启动的最好方式使创建一个repl.js文件:

var arDrone =require('ar-drone');  var client  = arDrone.createClient();  client.createRepl();

使用REPL,其中包含一些功能:

$ node repl.js // Make the drone takeoff  drone> takeoff()  true // Wait for the drone to takeoff  drone> clockwise(0.5)  0.5 // Let the drone spin for a while  drone> land()  true // Wait for the drone to land

下面,开发人员就可以编写自动化程序实现上述功能:

var arDrone = require('ar-drone');  var client  = arDrone.createClient();    client.takeoff();    client    .after(5000, function() {      this.clockwise(0.5);    })    .after(3000, function() {      this.stop();      this.land();    });

然后,怎样实现无人机的交互?首先,需要查看传感器数据:

client.on('navdata', console.log);

这些并不都是通过客户端库处理的,但是至少,开发人员可以接收droneState 和demo数据。在首次尝试时,开发人员可以使用navdata.demo.altitudeMeters功能升到一定的高度。成功后,可以进行下一步尝试:查看摄像头照片。PngBuffers函数可以帮助实现该功能(要求$PATH变量中包含最近版本的ffmpeg):

var pngStream = client.getPngStream();  pngStream.on('data', console.log);

首次尝试可能只是将这些Png图像暴露为http节点服务器。然后,就可以将他们注入到opencv模块。

客户端API

arDrone.createClient([options])

返回一个新的Client对象,其中的options包含:

ip:无人机的IP,默认为“192.168.1.1”

frameRate:PngEncoder的帧速率,默认为5

imageSize:PngEncoder生成的图像大小,默认为NULL

client.createREPL():启动交互式界面,其中包含在有效范围内可用的所有客户端方法。另外,client解析为client实例。

client.getPngStream():返回PngEncoder对象,以data事件的形式发出独立的png图像缓冲区。多个调用返回相同的对象。Connection的声明周期由客户端管理。

client.getVideoStream():返回TcpVideoStream对象,以data事件的形式发出原始TCP数据包。多个调用返回相同的对象。Connection的声明周期由客户端管理。

client.takeoff(callback):将内部fly状态设为true,当无人机报告为盘旋状态时,调用callback。

client.land(callback):将内部fly状态设为true,当无人机报告为着陆状态时,调用callback。

client.up(speed) / client.down(speed):控制无人机增加或降低高度,speed值在0至1之间。

client.clockwise(speed) /client.counterClockwise(speed):使无人机旋转,speed值在0至1之间。

client.front(speed) / client.back(speed):控制定位,以摄像头为参考点的水平运动,speed值在0至1之间。

client.left(speed) / client.right(speed):控制转动,以摄像头为参考点的水平运动,speed值在0至1之间。

client.stop():将无人机所有的运动命令设置为0,使其在适当的位置盘旋。

client.calibrate(device_num):要求无人机校准设备,当前AR.Drone固件只支持一个设备校准:设备号为0的磁传感器。该磁传感器只有在无人机飞行时才能被校准,并且会使无人机360度偏航。

client.config(key, value, callback):向无人机发送配置命令,用户需要下载SDK,来获取ARDrone_Developer_Guide.pdf中完整的命令列表。

例如,以下命令会要求无人机发送完整的导航数据:

client.config(‘general:navdata_demo’,’FALSE’);

当无人机接收该配置请求或时间超时时,会调用callback。

或者,也可以传递一个包含以下成员的选项对象:

key:配置键

value:配置值

timeout:等待无人机ACK响应的时间,以毫秒为单位

例如:

var callback = function(err) { if (err) console.log(err); };  client.config({ key: 'general:navdata_demo', value: 'FALSE', timeout: 1000 }, callback);

client.animate(animation,duration)

根据给定的duration(毫秒为单位)执行预定的飞行序列,animation可以为以下值:

['phiM30Deg', 'phi30Deg', 'thetaM30Deg', 'theta30Deg', 'theta20degYaw200deg',  'theta20degYawM200deg', 'turnaround', 'turnaroundGodown', 'yawShake',  'yawDance', 'phiDance', 'thetaDance', 'vzDance', 'wave', 'phiThetaMixed',  'doublePhiThetaMixed', 'flipAhead', 'flipBehind', 'flipLeft', 'flipRight']

例如:

client.animate('flipLeft', 1000);

注:无人机需要比较大的高度和空间执行空翻。

client.animateLeds(animation, hz, duration)

根据给定的hz条件和duration(以秒为单位)执行预定的引导序列,animation可以为以下值:

['blinkGreenRed', 'blinkGreen', 'blinkRed', 'blinkOrange', 'snakeGreenRed',  'fire', 'standard', 'red', 'green', 'redSnake', 'blank', 'rightMissile',  'leftMissile', 'doubleMissile', 'frontLeftGreenOthersRed',  'frontRightGreenOthersRed', 'rearRightGreenOthersRed',  'rearLeftGreenOthersRed', 'leftGreenRightRed', 'leftRedRightGreen',  'blinkStandard']

例如:

client.animateLeds('blinkRed', 5, 2)

client.disableEmergency()

当navdata.droneState.emergencyLanding为0时,将emergencyREF位设成1,可以恢复失去控制的无人机,将红灯更改为绿灯,使其可以重新飞行。当创建更高一级的客户端时,该过程会隐式地完成。

使用以下函数启用演示导航数据:

client.config('general:navdata_demo', 'FALSE');

UdpControl

UdpControl是一个低级API。如果开发人员更倾向于简单的实现,可以参考客户端文档。

可以通过向5556端口发送UDP数据包控制无人机。由于UDP不能保证数据报的顺序和交付,客户端需要重复发送指令,并在每一条指令中包含递增的序列号。

例如,用于takeoff/landing(REF)的命令,序列化为1,参数值为512:

AT*REF=1,512/r

为了减缓这些数据包的创建和发送,该模块使用UdpControl类处理该任务。例如,以下进程可以使无人机起飞并原地盘旋:

var arDrone = require('ar-drone');  var control = arDrone.createUdpControl();    setInterval(function() {    // The emergency: true option recovers your drone from emergency mode that can // be caused by flipping it upside down or the drone crashing into something. // In a real program you probably only want to send emergency: true for one // second in the beginning, otherwise your drone may attempt to takeoff again // after a crash. control.ref({fly: true, emergency: true});    // This command makes sure your drone hovers in place and does not drift. control.pcmd();    // This causes the actual udp message to be send (multiple commands are // combined into one message) control.flush();  }, 30);

如果要降落,可以向pcmd()方法传递一个参数:

control.pcmd({    front: 0.5, // fly forward with 50% speed    up: 0.3, // and also fly up with 30% speed  });

根据以上内容,就可以创建一个简单的程序:

var arDrone = require('ar-drone');  var control = arDrone.createUdpControl();  var start   = Date.now();    var ref  = {};  var pcmd = {};    console.log('Recovering from emergency mode if there was one ...');  ref.emergency = true;  setTimeout(function() {    console.log('Takeoff ...');      ref.emergency = false;    ref.fly = true;    }, 1000);    setTimeout(function() {    console.log('Turning clockwise ...');      pcmd.clockwise = 0.5;  }, 6000);    setTimeout(function() {    console.log('Landing ...');      ref.fly = false;    pcmd = {};  }, 8000);      setInterval(function() {    control.ref(ref);    control.pcmd(pcmd);    control.flush();  }, 30);

UdpControl API

arDrone.createUdpControl([options]) / newarDrone.UdpControl([options])

创建新的包含options的UdpControl实例:

ip:无人机的IP地址,默认为192.168.1.1

port:使用的端口,默认为5556

udpControl.raw(command, [arg1, arg2, …])

入队原始的AT*命令,如果用户想要完全控制权,这是很有必要的。

例如,起飞指令可以下列形式发送:

udpControl.raw('REF', (1 << 9));

udpControl.ref([options])

入队AT*REF命令,选项为:

fly:设置为true可以起飞或暂停;设置为false可以开始降落或停止,默认为false

emergency: true为设置emergency位,false不设置,默认为false。详情请参考SDK官方指南

udpControl.pcmd([options])

入队AT*PCMD命令,选项为:

front或back:以前置摄像头的方向为参考,前进或后退

left或right:以前置摄像头的方向为参考,向左或向右

up或down:增加或减少高度

clockwise或counterClockwise:绕中心轴旋转

每个选项的值都为速度,值在0至1之间,也可以使用负值,例如,{front: -0.5}等同于{back: 0.5}。

udpControl.flush()

将已入队的命令以UDP数据包的形式发送给无人机。

环境变量

DEFAULT_DRONE_IP

摄像头使用

用户可以使用顶部摄像头和底部摄像头,需要更改配置:

//使用顶部摄像头  client.config('video:video_channel', 0);    //使用底部摄像头  client.config('video:video_channel', 3);

*原文地址:github,vul_wish编译,转载请注明来自FreeBuf黑客与极客(FreeBuf.COM)