導讀 本設計主要研究基于WIFI網(wǎng)絡(luò )的可視化無(wú)線(xiàn)遙控搬運機器人,利用WIFI網(wǎng)絡(luò )高速傳輸實(shí)時(shí)視頻圖像采集,通過(guò)機器人安裝的傳感器實(shí)現數據采集。采用WIFI網(wǎng)絡(luò )通訊使得控制端多樣化,可用手機,電腦等具備WIFI功能的設備進(jìn)行控制。此外,還可將機器人接入Internet實(shí)現更遠距離的控制。本設計在S3C6410平臺上移植了Linux操作系統用于接收命令并對硬件設備進(jìn)行控制,其中移植了MJPGstreamer作為視頻服務(wù)器,移植了BOA服務(wù)器作為WEB服務(wù)器。本文將從硬件設計,驅動(dòng)程序編寫(xiě),服務(wù)器移植,服務(wù)程序編寫(xiě),Android應用程序編寫(xiě),Web應用程序編寫(xiě)等方面來(lái)講述本設計的功能實(shí)現。 功能框圖 總體設計及硬件選型和電路部分:可視化WIFI遙控搬運機器人(1):硬件部分 驅動(dòng)程序編寫(xiě),服務(wù)器移植,服務(wù)程序編寫(xiě)部分:可視化WIFI遙控搬運機器人(2):服務(wù)器搭建 4 客戶(hù)端程序設計 4.1 Android客戶(hù)端設計 4.1.1 Android客戶(hù)端軟件流程圖 圖 4-1 Android應用程序流程圖 如圖4-1所示,Android端的應用程序采用多線(xiàn)程技術(shù),其中一個(gè)子線(xiàn)程每60S向服務(wù)器發(fā)送一個(gè)獲取電量的命令并根據收到的數據進(jìn)行更新顯示,另一個(gè)線(xiàn)程根據MJPEG協(xié)議來(lái)解析出圖像數據并更新顯示,主線(xiàn)程主要完成用戶(hù)操控事件的監聽(tīng),并根據用戶(hù)的實(shí)際操控發(fā)送相應的命令給服務(wù)器并從服務(wù)器獲得機器人的最新數據來(lái)實(shí)時(shí)更新。其命令的發(fā)送方式采用HTTP協(xié)議中的GET方法。 4.1.2 HTTP GET方法簡(jiǎn)介 GET方法是HTTP協(xié)議中定義的多種與服務(wù)器進(jìn)行交互的方法之一,它一般用于獲取/查詢(xún)資源信息。該方法請求的數據會(huì )附在URL之后,并且提交的數據最多只能是1024字節,但是本設計中只需要傳送命令字即可,因此采用GET方法來(lái)傳送命令字與獲取機器人數據信息。使用該方法來(lái)發(fā)送命令,服務(wù)器端的CGI程序可以在QUERY-STRING環(huán)境變量中非常方便的獲取到客戶(hù)端傳送給服務(wù)器的數據,并且客戶(hù)端應用程序可以在HttpResponse中獲得服務(wù)器端返回的數據。 4.1.3 HTTP GET方法實(shí)現 Android應用中HTTP GET方法實(shí)現部分代碼如下: public String doGet(String url){ //參數設置 ... //創(chuàng )建 HttpClient 的實(shí)例 HttpClient httpClient = new DefaultHttpClient(httpParams); // GET HttpGet httpGet = new HttpGet(url); try { HttpResponse response = httpClient.execute(httpGet); if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK){ // 使用getEntity方法獲得返回結果 return EntityUtils.toString(response.getEntity()); } ... } 4.1.4 Mjpeg協(xié)議介紹 Mjpeg即Motion JPEG。MJPEG將服務(wù)器端發(fā)送來(lái)的一張張JPG圖像數據發(fā)送給客戶(hù)端,客戶(hù)端不斷的接收圖像數據并顯示更新即形成了動(dòng)態(tài)的圖像。MJPEG在HTTP中mjpg的在http的mime type是"x-mixed-replace"。獲取視頻圖像數據時(shí),客戶(hù)端首先發(fā)一個(gè)GET方法,如果服務(wù)器接收響應則會(huì )設置context type的boundary子屬性來(lái)指明。然后服務(wù)器端開(kāi)始發(fā)送圖片數據,在數據頭部會(huì )有圖片類(lèi)型以及大小信息,其中Content-Length字段指明圖像數據的長(cháng)度,Content-Type字段指明圖像的類(lèi)型其值為image/jpeg。當一幀圖像數據發(fā)送完畢后,服務(wù)器端將會(huì )發(fā)送邊界字符串來(lái)表示一幀圖像發(fā)送結束。 4.1.5 Mjpeg解析圖像數據流程圖 圖 4-2 Mjpeg解析圖像流程圖 4.1.6 Mjpeg解析圖像數據代碼 在A(yíng)ndroid客戶(hù)端需要根據Mjpeg協(xié)議來(lái)編寫(xiě)代碼實(shí)現圖像數據的解析,其中部分代碼如下: Socket server = new Socket(url.getHost(), url.getPort()); OutputStream os = server.getOutputStream(); InputStream is = server.getInputStream(); StringBuffer request = new StringBuffer(); request.append("GET " + url.getFile() + " HTTP/1.0\r\n"); request.append("Host: " + url.getHost() + "\r\n"); request.append("\r\n"); os.write(request.toString().getBytes(), 0, request.length());//請求返回File StreamSplit localStreamSplit = new StreamSplit(new DataInputStream(new BufferedInputStream(is))); Hashtable localHashtable = localStreamSplit.readHeaders();//獲得文件的信息頭 String str3 = (String)localHashtable.get("content-type");//獲得content-type以后的數據 int n = str3.indexOf("boundary=");//定位邊界字符串 Object localObject2 = "--"; if (n != -1){ localObject2 = str3.substring(n + 9);//指定到boundary子屬性 str3 = str3.substring(0, n); if (!((String)localObject2).startsWith("--")) localObject2 = "--" + (String)localObject2;} if (str3.startsWith("multipart/x-mixed-replace")){//判斷MIME類(lèi)型 localStreamSplit.skipToBoundary((String)localObject2);//定位到圖像數據部分 }do{ if (localObject2 != null){ localHashtable = localStreamSplit.readHeaders(); if (localStreamSplit.isAtStreamEnd()) break; str3 = (String)localHashtable.get("content-type"); if (str3 == null) throw new Exception("No part content type"); } if (str3.startsWith("multipart/x-mixed-replace")){ n = str3.indexOf("boundary="); localObject2 = str3.substring(n + 9);//獲得 localStreamSplit.skipToBoundary((String)localObject2); }else{ byte[] localObject3 = localStreamSplit.readToBoundary((String)localObject2); if (localObject3.length == 0) break; Message message = Message.obtain(); message.arg1 = 0; message.obj = BitmapFactory.decodeByteArray(localObject3, 0, localObject3.length); messageHandler.sendMessage(message);//顯示消息 } fps++; try{ Thread.sleep(10L); }catch (InterruptedException localInterruptedException){ } 4.2 Web客戶(hù)端設計 4.2.1 Web客戶(hù)端程序流程圖 如圖4-3所示,WEB客戶(hù)端采用AJAX技術(shù),其功能模塊大體上分為3個(gè)部分:第一部分主要是監測用戶(hù)的操作并采用HTTP GET方法來(lái)發(fā)送控制命令,最后將服務(wù)器返回的信息更新顯示。第二部分主要為120S定時(shí)發(fā)送獲取電源電量值得命令,并將獲得的數據更新顯示。第三部分獲取圖像數據并顯示。 圖 4-3 WEB客戶(hù)端流程圖 4.2.2 AJAX技術(shù)簡(jiǎn)介 AJAX(Asynchronous Javascript + XML)即異步JavaScript和XML技術(shù)的簡(jiǎn)稱(chēng),它可以實(shí)現網(wǎng)頁(yè)異步更新。采用該方法來(lái)設計WEB應用,可以只對網(wǎng)頁(yè)的部分內容進(jìn)行更新,而不需要重新對整個(gè)頁(yè)面進(jìn)行加載。其工作原理如下圖所示: 圖 4-4 AJAX工作原理 4.2.3 圖像數據顯示實(shí)現 采用WEB瀏覽器來(lái)顯示的時(shí)候只需要添加如下代碼: 4.2.4 利用AJAX技術(shù)實(shí)現命令發(fā)送與數據更新 XMLHttpRequest 是 AJAX 的最基礎的部分,本設計中的部分代碼如下: function SendCmd(cmd) { var xmlhttp; if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari xmlhttp=new XMLHttpRequest(); } else {// code for IE6, IE5 xmlhttp=new ActiveXObject("Microsoft.XMLHTTP"); } xmlhttp.open("GET","./car.cgi?"+cmd,true); xmlhttp.send(); xmlhttp.onreadystatechange=function() { if (xmlhttp.readyState==4 && xmlhttp.status==200) { var rec=xmlhttp.responseText; if( rec.indexOf("PRE") == 0) { document.getElementById("Pressure").innerHTML="壓力:"+rec.substr(4); } if( rec.indexOf("POW") == 0) { var get_power=parseFloat(rec.substr(4)); get_power=9.9*get_power/1024; if(power == 0) power=get_power; if(get_power8.3) document.getElementById("Power").innerHTML="電量:100%"; else if(power>8.2) ... } } } } } 5 結束語(yǔ) 本文從硬件選型,硬件電路設計,系統移植,驅動(dòng)程序移植編寫(xiě),服務(wù)器搭建,服務(wù)器程序編寫(xiě),以及Android客戶(hù)端和Web客戶(hù)端應用程序編寫(xiě)方面進(jìn)行了較為詳細的介紹。通過(guò)自己的努力,完成了最低層的硬件設計到最上層軟件開(kāi)發(fā),實(shí)現了本設計的基本功能。最終用戶(hù)能夠通過(guò)Android客戶(hù)端和Web客戶(hù)端對機器人進(jìn)行夾持,運輸,擺放動(dòng)作的控制,并且能夠實(shí)時(shí)地返回機器人采集到的圖像數據和傳感器數據。 由于本設計基于成本的考慮,并沒(méi)有采用大功率高精度的硬件設備,所以只能作為一種功能演示以及技術(shù)可行性演示。在后續的工作中還可以提升硬件設備,調整應用程序來(lái)獲得更好的使用價(jià)值以及更好的用戶(hù)體驗。 可視化WIFI遙控搬運機器人(1):硬件部分 可視化WIFI遙控搬運機器人(2):服務(wù)器搭建 |