基于WIFI的四旋翼微型勘测飞行器手机控制端设计

2016-04-26 11:57桂玲李路周黄晴张为民黄明飞王双
科技视界 2016年10期

桂玲+李路+周黄晴+张为民+黄明飞+王双双

【摘 要】本文所设计的控制平台以Android手机为基础,以WIFI为通信网络,从如何搭建Android开发环境入手,通过对界面布局、视频流获取、信息交互、异常捕获、权限控制等几个方面的应用设计,实现对四旋翼微型勘测器飞行等的控制,并能实时准确地对高清摄像头、环境检测传感器所采集的图像和文本数据进行传输与显示,调试结果表明设计结果完全符合设计要求。

【关键词】无线WIFI;Android手机;应用程序设计

0 引言

我国是一个资源大国,野外资源丰富,对野外资源实地勘测任务艰巨。由于野外资源分布广,加之地形复杂恶劣、森林覆盖率大、未知区域居多等这些不利条件都给野外工作人员带来了极大不便。

本系统通过嵌入式Android手机平台远程控制四旋翼微型勘测飞行器,该平台利用高清摄像头来采集作业面环境图像,利用多种环境探测器和GPS定位,探测环境实情;并通过WIFI将视频和勘测信息实时回传给手机,以便直观地掌握当前的勘测情况。

为实现上述功能,整个勘测平台搭载于四旋翼飞行器上,为保证整个平台的稳定,每个重要功能由单独的处理器处理,整个系统构架如图1所示:

其中,飞控主要解算姿态传感器数据以获得当前飞行器的姿态信息并调整电机转速,保持飞行器的平稳和飞行方向控制;主控,主要保证飞行器和控制端的连接稳定,解析和创建数据包,并传递控制指令给飞控。WIFI是建立手持控制端与主控间通信的媒介。手持控制端是控制整个勘测飞行器的工作,在整个系统的大脑,本文将具体对它的设计做阐述。

1 系统分析

现在的智能手机一般有WiFi、蓝牙、移动网络三种通信方式,相比而言WiFi是最合适做控制的短距离通信协议。通信平台通过写入OpenWRT系统的TP-LINKWR703N路由器和手机无线连接。OpenWRT是嵌入式设备上运行的linux系统,附带3000左右的软件包,开发者无需在每一次修改后重新编译,且用户可以方便的自定义功能来制作固件。也可以方便的移植各类功能到openwrt下[1]。而Android操作系统是基于Linux系统研发的一款开源的手机操作系统,由操作系统、中间件、用户界面和应用软件组成。由于Android提供了丰富的封装库,编程时无需在意系统底层设计和兼容性,现已然在现今智能手机操作系统市场占有率为首位。

路由器里的OpenWRT系统带有Mjpeg stream插件,可以把从USB摄像头采集的图像转换成流媒体输出,可以通过文件或者HTTP形式得到视频。路由器带有调试用串口引脚,通过配置系统文件可以让路由器将网络端口(TCP/IP协议)的数据经串口输出,同样也可以把串口的数据传送的到网络端口上。从而下位机(主控)通过串口便可以和上位机(手持控制端,如手机)的网络端口实现信息的透传。由此,手机端需要打开两个连接端口,一个从Mjpeg-stream中获得图像信息,另一个和下位机通信。系统设计流程如图2所示:

2 系统实现

2.1 搭建Android开发环境

2.1.1 安装JDK

根据电脑的操作系统从Oracle公司官网下载对应的JDK;下载完成后根据安装向导提示完成JDK的安装。

2.1.2 环境配置

JDK安装完成后,打开Windows系统的命令窗口,在其中输入“java-version”,若在下面显示了Java的版本号说明已经安装成功;否则要手动配置系统环境。配置过程如下:按如下步骤打开系统环境变量设置窗口,计算机->属性->更改设置->高级->环境变量,然后在系统变量处新建,变量名为“JAVA_HOME”,变量值中填刚才JDK安装的路径,如“C:\Program Files\Java\jdk1.8.0_25”;点击确定后,再新建一个变量名为classpath,变量值为“.;%JAVA_HOME%/lib/rt.jar;%JAVA_HOME%/lib/tools.jar”;点击确定后,找到变量Path,在变量值后加”;%HAVA_HOME%/bin“;最后通过命令窗口验证JDK是否成功安装。

2.1.3 开发工具

从Android下载适合电脑系统的集成ADT的Eclipse开发工具,解压后便可直接打开Eclipse开发平台。

2.2 新建Android应用程序

在Eclipse项目管理窗口点击右键,依次New->Android Application Project->Next,根据新建工程向导设置应用名、工程名、包名和应用程序图标等,所有需要设置的设置完成之后点击Finish完成,至此应用程序的新建已经完成。

2.3 界面布局

显示和控制是人机交互的重要环节。上位机UI操作界面包括摄像头舵机俯仰左右转动、飞行器前后左右飞行、传感器数据显示和图像画面显示。前三项分别用Button(按键)、TextView(文本)、ImageView(图片)控件即可实现;视频图像即通过继承SurfaceView类在屏幕上显示实时图像。

整个布局以RelativeLayout(相对布局)为父本,在其中分别放置子控件Button(按键控件)、ImageView(图片控件)和TextView(文本控件),设置控件大小、添加控件ID和其在父控件的位置。新建MySurfaceView.class继承SurfaceView类,添加自定义的控件到布局文件里,设置高度和宽度为“fill_parent”(填充父本)并添加ID。

添加控制按键:

android:layout_height="wrap_content"

android:layout_alignParentLeft="true"

android:layout_alignParentTop="true"

android:layout_marginLeft="20dp"

android:layout_marginTop="70dp" />

第1行添加控件ID,ID号为32位的常量,通常由编译工具自动生成存于R.java里;第2行、3行分别设置控件宽高,余下4行设置控件在父本中的位置。

添加自定义的控件:

android:id="@+id/mySurfaceViewVideo"

android:layout_width="fill_parent"

android:layout_height="fill_parent" />

至此,界面布局已经基本完成,在Activity中加载布局文件即完成了整个布局的设置[2-3]。

2.4 视频流获取

在对路由器进行开发时,本文在OpenWRT系统中装了mjpg-streamer应用,这样便能方便地把摄像头所采集的数据转换为视频流[2]。mjpg-streamer可以通过文件或者是HTTP方式访问linux UVC兼容摄像头。为此,要在MySurfaceView.class里新建线程用于接收图像数据,在接收之前需要建立一块缓存区,用于存放接收到的数据。以URL发起请求,然后等待服务器(路由器)返回应答。新建单独的线程完成视频流的获取与图像显示[4]。

主要代码如下:

url = new URL(urlstr);

urlConn = (HttpURLConnection) url.openConnection();

read = urlConn.getInputStream().read(buffer, 0, readSize);

以上代码必须捕获异常。

服务器应答后,接下来就要解析出图片数据并显示到屏幕上。由于服务器应答是HTTP超文本传输协议,我们需要解析出图像数据。JPEG图像每个标记都是由两个字节组成,其中,前一个字节固定值0xFF,0xFF 0xD8标记图像开始,0xFF 0xD9标记图像结束。截取中间段即为图像信息,然后通过转码转成Bitmap图像,转换图像大小,绘制图像,主要代码如下:

Canvascanvas = surfaceHolder.lockCanvas() ; //获得canvas对象

Bitmap bmp = BitmapFactory.decodeStream(new ByteArrayInputStream(jpg_buf));

mBitmap = Bitmap.createScaledBitmap(bmp, width, height, false);

canvas.drawBitmap(mBitmap,(mScreenWidth-width)/2,(mScreenHeight-height)/2, null);

surfaceHolder.unlockCanvasAndPost(canvas); //释放canvas锁,并且显示视图

2.5 信息交互

Activity生命周期里,启动Activity时系统会先调用onCreate方法,Activity退出时会调用onDestroy方法。通常在onCreate方法里进行按键绑定、变量初始化等一系列Activity初始化操作,而在onDestroy方法里释放资源。

2.5.1 绑定按键

在MainActivity.class的onCreate方法里为控件绑定监听器,这样当这个按键被按下时系统会调用这个监听函数,便可以在按键被按下时做出相应的反应。

按键绑定监听器:

findViewById(R.id. button_front).

setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View arg0) {

// TODO Auto-generated method stub

sendfrontData();

}

});

在onClick方法里写按键操作的代码,当绑定的按键被按下此段代码将会被调用。

2.5.2 获取输入流和输出流

新建一个Socket连接,此连接用来和下位机串口间数据透传。依据OpenWRT里设置的地址和端口打开Secket连接,并获得Socket的输入流和输出流,主要代码如下:

mSocketClient = new Socket(CtrlIp, CtrlPort);

inStream = mSocketClient.getInputStream();

outStream = mSocketClient.getOutputStream();

打开Socket连接,获得当前Socket的输入输出流。以上代码必须捕获异常。新建接收线程,接收下位机发来的数据,并解析和更新UI。

new Thread(){

@Override

public void run() {

// TODO Auto-generated method stub

super.run();

while(true) {

inStream.read(buffer);

parseData(buffer);

}

}

}.start();

只有在run方法里写入自己的代码,当线程运行后会直接调用run方法,整个代码在循环体内,Socket接收到数据后,在线程调用数据解析方法解析数据并更新到UI界面。

2.5.3 UI更新

下位机发来的数据有状态信息和其他数据信息,主要显示方式为文本显示。Android系统里,文本显示由TextView控件实现,若要显示文本到屏幕,首先需要获得文本控件的ID号,然后再设置控件显示的文本内容以及字体大小和字体类型、排列方式等,同样TextView的属性可以在layout布局文件里设置。

显示文本到屏幕:

TextViewbt = (TextView) findViewById(R.id.textv);

bt.setText(str);

第一句获得文本控件textv的ID,第二句,通过setText()为此控件设置文本内容。

2.6 异常捕获

当退出应用时用户需要释放掉之前使用的资源,在MainActivity.class里复写onDestroy方法,在onDestroy方法里断开Socket连接和关闭输入输出流:

try {

if(mSocketClient!=null)

{

mSocketClient.close();

inStream.close();

outStream.close();

mSocketClient = null;

}

} catch (IOException e) {

e.printStackTrace();

}

mThreadClient.interrupt();

2.7 权限控制

Android 提供了丰富的 SDK(Software development kit),开发人员在对 Android 系统资源的访问需要有相应的访问权限,这个权限就称为 Android 应用程序权限,由AndroidManifest.xml文件管理,它在应用程序设计时设定,在 Android 系统中初次安装时即生效。此应用需要以下权限:

<!-- internet -->

STATE"/>

STATE"/>

3 应用调试

笔者把该控制平台与飞行器一起来检测其工作性能,打开手机调试功能,连接电脑,并安装好手机驱动,然后在Eclipse里选中项目右击,选Run as -> Android Application,直接在手机上运行程序,调试如图3所示。测试表明该平台能在Android手机终端的控制下摄像头上下左右旋转90°拍摄图像信息;飞行器能平稳地前进、后退和左右旋转飞行;并对有害可燃气体浓度检测和PM2.5等颗粒污染物环境参数信息检测快速、准确;GPS定位系统精准,室内精度为2.0m以下而室外为0.5m以下。数据,视频显示正常,各项性能完全符合设计的要求并能方便地拓展其功能和应用。

【参考文献】

[1]向诚,谢峰粹.基于WIFI和Android的智能探测车设计[J].电子技术应用,2013.12:82-85.

[2]张余,编著.Android网络开发从入门到精通[M].清华大学出版社,2014.

[3]候国照.基于OpenWrt的无线传感器网络协议研究与实现[D].哈尔滨:哈尔滨工业大学,2009.02:102-105.

[4]王雷,蓝箭,陈雪娟.基于Android 平台的无线WiFi控制方法[J].微型电脑应用,2012,7:58-61.

[责任编辑:王楠]