桂玲+李路+周黃晴+張為民+黃明飛+王雙雙
【摘 要】本文所設(shè)計(jì)的控制平臺(tái)以Android手機(jī)為基礎(chǔ),以WIFI為通信網(wǎng)絡(luò),從如何搭建Android開(kāi)發(fā)環(huán)境入手,通過(guò)對(duì)界面布局、視頻流獲取、信息交互、異常捕獲、權(quán)限控制等幾個(gè)方面的應(yīng)用設(shè)計(jì),實(shí)現(xiàn)對(duì)四旋翼微型勘測(cè)器飛行等的控制,并能實(shí)時(shí)準(zhǔn)確地對(duì)高清攝像頭、環(huán)境檢測(cè)傳感器所采集的圖像和文本數(shù)據(jù)進(jìn)行傳輸與顯示,調(diào)試結(jié)果表明設(shè)計(jì)結(jié)果完全符合設(shè)計(jì)要求。
【關(guān)鍵詞】無(wú)線WIFI;Android手機(jī);應(yīng)用程序設(shè)計(jì)
0 引言
我國(guó)是一個(gè)資源大國(guó),野外資源豐富,對(duì)野外資源實(shí)地勘測(cè)任務(wù)艱巨。由于野外資源分布廣,加之地形復(fù)雜惡劣、森林覆蓋率大、未知區(qū)域居多等這些不利條件都給野外工作人員帶來(lái)了極大不便。
本系統(tǒng)通過(guò)嵌入式Android手機(jī)平臺(tái)遠(yuǎn)程控制四旋翼微型勘測(cè)飛行器,該平臺(tái)利用高清攝像頭來(lái)采集作業(yè)面環(huán)境圖像,利用多種環(huán)境探測(cè)器和GPS定位,探測(cè)環(huán)境實(shí)情;并通過(guò)WIFI將視頻和勘測(cè)信息實(shí)時(shí)回傳給手機(jī),以便直觀地掌握當(dāng)前的勘測(cè)情況。
為實(shí)現(xiàn)上述功能,整個(gè)勘測(cè)平臺(tái)搭載于四旋翼飛行器上,為保證整個(gè)平臺(tái)的穩(wěn)定,每個(gè)重要功能由單獨(dú)的處理器處理,整個(gè)系統(tǒng)構(gòu)架如圖1所示:
其中,飛控主要解算姿態(tài)傳感器數(shù)據(jù)以獲得當(dāng)前飛行器的姿態(tài)信息并調(diào)整電機(jī)轉(zhuǎn)速,保持飛行器的平穩(wěn)和飛行方向控制;主控,主要保證飛行器和控制端的連接穩(wěn)定,解析和創(chuàng)建數(shù)據(jù)包,并傳遞控制指令給飛控。WIFI是建立手持控制端與主控間通信的媒介。手持控制端是控制整個(gè)勘測(cè)飛行器的工作,在整個(gè)系統(tǒng)的大腦,本文將具體對(duì)它的設(shè)計(jì)做闡述。
1 系統(tǒng)分析
現(xiàn)在的智能手機(jī)一般有WiFi、藍(lán)牙、移動(dòng)網(wǎng)絡(luò)三種通信方式,相比而言WiFi是最合適做控制的短距離通信協(xié)議。通信平臺(tái)通過(guò)寫入OpenWRT系統(tǒng)的TP-LINKWR703N路由器和手機(jī)無(wú)線連接。OpenWRT是嵌入式設(shè)備上運(yùn)行的linux系統(tǒng),附帶3000左右的軟件包,開(kāi)發(fā)者無(wú)需在每一次修改后重新編譯,且用戶可以方便的自定義功能來(lái)制作固件。也可以方便的移植各類功能到openwrt下[1]。而Android操作系統(tǒng)是基于Linux系統(tǒng)研發(fā)的一款開(kāi)源的手機(jī)操作系統(tǒng),由操作系統(tǒng)、中間件、用戶界面和應(yīng)用軟件組成。由于Android提供了豐富的封裝庫(kù),編程時(shí)無(wú)需在意系統(tǒng)底層設(shè)計(jì)和兼容性,現(xiàn)已然在現(xiàn)今智能手機(jī)操作系統(tǒng)市場(chǎng)占有率為首位。
路由器里的OpenWRT系統(tǒng)帶有Mjpeg stream插件,可以把從USB攝像頭采集的圖像轉(zhuǎn)換成流媒體輸出,可以通過(guò)文件或者HTTP形式得到視頻。路由器帶有調(diào)試用串口引腳,通過(guò)配置系統(tǒng)文件可以讓路由器將網(wǎng)絡(luò)端口(TCP/IP協(xié)議)的數(shù)據(jù)經(jīng)串口輸出,同樣也可以把串口的數(shù)據(jù)傳送的到網(wǎng)絡(luò)端口上。從而下位機(jī)(主控)通過(guò)串口便可以和上位機(jī)(手持控制端,如手機(jī))的網(wǎng)絡(luò)端口實(shí)現(xiàn)信息的透?jìng)鳌S纱?,手機(jī)端需要打開(kāi)兩個(gè)連接端口,一個(gè)從Mjpeg-stream中獲得圖像信息,另一個(gè)和下位機(jī)通信。系統(tǒng)設(shè)計(jì)流程如圖2所示:
2 系統(tǒng)實(shí)現(xiàn)
2.1 搭建Android開(kāi)發(fā)環(huán)境
2.1.1 安裝JDK
根據(jù)電腦的操作系統(tǒng)從Oracle公司官網(wǎng)下載對(duì)應(yīng)的JDK;下載完成后根據(jù)安裝向?qū)崾就瓿蒍DK的安裝。
2.1.2 環(huán)境配置
JDK安裝完成后,打開(kāi)Windows系統(tǒng)的命令窗口,在其中輸入“java-version”,若在下面顯示了Java的版本號(hào)說(shuō)明已經(jīng)安裝成功;否則要手動(dòng)配置系統(tǒng)環(huán)境。配置過(guò)程如下:按如下步驟打開(kāi)系統(tǒng)環(huán)境變量設(shè)置窗口,計(jì)算機(jī)->屬性->更改設(shè)置->高級(jí)->環(huán)境變量,然后在系統(tǒng)變量處新建,變量名為“JAVA_HOME”,變量值中填剛才JDK安裝的路徑,如“C:\Program Files\Java\jdk1.8.0_25”;點(diǎn)擊確定后,再新建一個(gè)變量名為classpath,變量值為“.;%JAVA_HOME%/lib/rt.jar;%JAVA_HOME%/lib/tools.jar”;點(diǎn)擊確定后,找到變量Path,在變量值后加”;%HAVA_HOME%/bin“;最后通過(guò)命令窗口驗(yàn)證JDK是否成功安裝。
2.1.3 開(kāi)發(fā)工具
從Android下載適合電腦系統(tǒng)的集成ADT的Eclipse開(kāi)發(fā)工具,解壓后便可直接打開(kāi)Eclipse開(kāi)發(fā)平臺(tái)。
2.2 新建Android應(yīng)用程序
在Eclipse項(xiàng)目管理窗口點(diǎn)擊右鍵,依次New->Android Application Project->Next,根據(jù)新建工程向?qū)гO(shè)置應(yīng)用名、工程名、包名和應(yīng)用程序圖標(biāo)等,所有需要設(shè)置的設(shè)置完成之后點(diǎn)擊Finish完成,至此應(yīng)用程序的新建已經(jīng)完成。
2.3 界面布局
顯示和控制是人機(jī)交互的重要環(huán)節(jié)。上位機(jī)UI操作界面包括攝像頭舵機(jī)俯仰左右轉(zhuǎn)動(dòng)、飛行器前后左右飛行、傳感器數(shù)據(jù)顯示和圖像畫面顯示。前三項(xiàng)分別用Button(按鍵)、TextView(文本)、ImageView(圖片)控件即可實(shí)現(xiàn);視頻圖像即通過(guò)繼承SurfaceView類在屏幕上顯示實(shí)時(shí)圖像。
整個(gè)布局以RelativeLayout(相對(duì)布局)為父本,在其中分別放置子控件Button(按鍵控件)、ImageView(圖片控件)和TextView(文本控件),設(shè)置控件大小、添加控件ID和其在父控件的位置。新建MySurfaceView.class繼承SurfaceView類,添加自定義的控件到布局文件里,設(shè)置高度和寬度為“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號(hào)為32位的常量,通常由編譯工具自動(dòng)生成存于R.java里;第2行、3行分別設(shè)置控件寬高,余下4行設(shè)置控件在父本中的位置。
添加自定義的控件:
android:id="@+id/mySurfaceViewVideo" android:layout_width="fill_parent" android:layout_height="fill_parent" /> 至此,界面布局已經(jīng)基本完成,在Activity中加載布局文件即完成了整個(gè)布局的設(shè)置[2-3]。 2.4 視頻流獲取 在對(duì)路由器進(jìn)行開(kāi)發(fā)時(shí),本文在OpenWRT系統(tǒng)中裝了mjpg-streamer應(yīng)用,這樣便能方便地把攝像頭所采集的數(shù)據(jù)轉(zhuǎn)換為視頻流[2]。mjpg-streamer可以通過(guò)文件或者是HTTP方式訪問(wèn)linux UVC兼容攝像頭。為此,要在MySurfaceView.class里新建線程用于接收?qǐng)D像數(shù)據(jù),在接收之前需要建立一塊緩存區(qū),用于存放接收到的數(shù)據(jù)。以URL發(fā)起請(qǐng)求,然后等待服務(wù)器(路由器)返回應(yīng)答。新建單獨(dú)的線程完成視頻流的獲取與圖像顯示[4]。 主要代碼如下: url = new URL(urlstr); urlConn = (HttpURLConnection) url.openConnection(); read = urlConn.getInputStream().read(buffer, 0, readSize); 以上代碼必須捕獲異常。 服務(wù)器應(yīng)答后,接下來(lái)就要解析出圖片數(shù)據(jù)并顯示到屏幕上。由于服務(wù)器應(yīng)答是HTTP超文本傳輸協(xié)議,我們需要解析出圖像數(shù)據(jù)。JPEG圖像每個(gè)標(biāo)記都是由兩個(gè)字節(jié)組成,其中,前一個(gè)字節(jié)固定值0xFF,0xFF 0xD8標(biāo)記圖像開(kāi)始,0xFF 0xD9標(biāo)記圖像結(jié)束。截取中間段即為圖像信息,然后通過(guò)轉(zhuǎn)碼轉(zhuǎn)成Bitmap圖像,轉(zhuǎn)換圖像大小,繪制圖像,主要代碼如下: Canvascanvas = surfaceHolder.lockCanvas() ; //獲得canvas對(duì)象 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生命周期里,啟動(dòng)Activity時(shí)系統(tǒng)會(huì)先調(diào)用onCreate方法,Activity退出時(shí)會(huì)調(diào)用onDestroy方法。通常在onCreate方法里進(jìn)行按鍵綁定、變量初始化等一系列Activity初始化操作,而在onDestroy方法里釋放資源。 2.5.1 綁定按鍵 在MainActivity.class的onCreate方法里為控件綁定監(jiān)聽(tīng)器,這樣當(dāng)這個(gè)按鍵被按下時(shí)系統(tǒng)會(huì)調(diào)用這個(gè)監(jiān)聽(tīng)函數(shù),便可以在按鍵被按下時(shí)做出相應(yīng)的反應(yīng)。 按鍵綁定監(jiān)聽(tīng)器: findViewById(R.id. button_front). setOnClickListener(new View.OnClickListener() { @Override public void onClick(View arg0) { // TODO Auto-generated method stub sendfrontData(); } }); 在onClick方法里寫按鍵操作的代碼,當(dāng)綁定的按鍵被按下此段代碼將會(huì)被調(diào)用。 2.5.2 獲取輸入流和輸出流 新建一個(gè)Socket連接,此連接用來(lái)和下位機(jī)串口間數(shù)據(jù)透?jìng)?。依?jù)OpenWRT里設(shè)置的地址和端口打開(kāi)Secket連接,并獲得Socket的輸入流和輸出流,主要代碼如下: mSocketClient = new Socket(CtrlIp, CtrlPort); inStream = mSocketClient.getInputStream(); outStream = mSocketClient.getOutputStream(); 打開(kāi)Socket連接,獲得當(dāng)前Socket的輸入輸出流。以上代碼必須捕獲異常。新建接收線程,接收下位機(jī)發(fā)來(lái)的數(shù)據(jù),并解析和更新UI。 new Thread(){
@Override
public void run() {
// TODO Auto-generated method stub
super.run();
while(true) {
inStream.read(buffer);
parseData(buffer);
}
}
}.start();
只有在run方法里寫入自己的代碼,當(dāng)線程運(yùn)行后會(huì)直接調(diào)用run方法,整個(gè)代碼在循環(huán)體內(nèi),Socket接收到數(shù)據(jù)后,在線程調(diào)用數(shù)據(jù)解析方法解析數(shù)據(jù)并更新到UI界面。
2.5.3 UI更新
下位機(jī)發(fā)來(lái)的數(shù)據(jù)有狀態(tài)信息和其他數(shù)據(jù)信息,主要顯示方式為文本顯示。Android系統(tǒng)里,文本顯示由TextView控件實(shí)現(xiàn),若要顯示文本到屏幕,首先需要獲得文本控件的ID號(hào),然后再設(shè)置控件顯示的文本內(nèi)容以及字體大小和字體類型、排列方式等,同樣TextView的屬性可以在layout布局文件里設(shè)置。
顯示文本到屏幕:
TextViewbt = (TextView) findViewById(R.id.textv);
bt.setText(str);
第一句獲得文本控件textv的ID,第二句,通過(guò)setText()為此控件設(shè)置文本內(nèi)容。
2.6 異常捕獲
當(dāng)退出應(yīng)用時(shí)用戶需要釋放掉之前使用的資源,在MainActivity.class里復(fù)寫onDestroy方法,在onDestroy方法里斷開(kāi)Socket連接和關(guān)閉輸入輸出流:
try {
if(mSocketClient!=null)
{
mSocketClient.close();
inStream.close();
outStream.close();
mSocketClient = null;
}
} catch (IOException e) {
e.printStackTrace();
}
mThreadClient.interrupt();
2.7 權(quán)限控制
Android 提供了豐富的 SDK(Software development kit),開(kāi)發(fā)人員在對(duì) Android 系統(tǒng)資源的訪問(wèn)需要有相應(yīng)的訪問(wèn)權(quán)限,這個(gè)權(quán)限就稱為 Android 應(yīng)用程序權(quán)限,由AndroidManifest.xml文件管理,它在應(yīng)用程序設(shè)計(jì)時(shí)設(shè)定,在 Android 系統(tǒng)中初次安裝時(shí)即生效。此應(yīng)用需要以下權(quán)限:
<!-- internet -->
STATE"/> STATE"/> 3 應(yīng)用調(diào)試 筆者把該控制平臺(tái)與飛行器一起來(lái)檢測(cè)其工作性能,打開(kāi)手機(jī)調(diào)試功能,連接電腦,并安裝好手機(jī)驅(qū)動(dòng),然后在Eclipse里選中項(xiàng)目右擊,選Run as -> Android Application,直接在手機(jī)上運(yùn)行程序,調(diào)試如圖3所示。測(cè)試表明該平臺(tái)能在Android手機(jī)終端的控制下攝像頭上下左右旋轉(zhuǎn)90°拍攝圖像信息;飛行器能平穩(wěn)地前進(jìn)、后退和左右旋轉(zhuǎn)飛行;并對(duì)有害可燃?xì)怏w濃度檢測(cè)和PM2.5等顆粒污染物環(huán)境參數(shù)信息檢測(cè)快速、準(zhǔn)確;GPS定位系統(tǒng)精準(zhǔn),室內(nèi)精度為2.0m以下而室外為0.5m以下。數(shù)據(jù),視頻顯示正常,各項(xiàng)性能完全符合設(shè)計(jì)的要求并能方便地拓展其功能和應(yīng)用。 【參考文獻(xiàn)】 [1]向誠(chéng),謝峰粹.基于WIFI和Android的智能探測(cè)車設(shè)計(jì)[J].電子技術(shù)應(yīng)用,2013.12:82-85. [2]張余,編著.Android網(wǎng)絡(luò)開(kāi)發(fā)從入門到精通[M].清華大學(xué)出版社,2014. [3]候國(guó)照.基于OpenWrt的無(wú)線傳感器網(wǎng)絡(luò)協(xié)議研究與實(shí)現(xiàn)[D].哈爾濱:哈爾濱工業(yè)大學(xué),2009.02:102-105. [4]王雷,藍(lán)箭,陳雪娟.基于Android 平臺(tái)的無(wú)線WiFi控制方法[J].微型電腦應(yīng)用,2012,7:58-61. [責(zé)任編輯:王楠]