趙旭 彭克勤 北京信息科技大學(xué)計(jì)算機(jī)學(xué)院
基于安卓的Multiwii無(wú)人機(jī)控制系統(tǒng)的實(shí)現(xiàn)
趙旭 彭克勤 北京信息科技大學(xué)計(jì)算機(jī)學(xué)院
近來(lái)消費(fèi)級(jí)無(wú)人機(jī)市場(chǎng)的火爆催生了大量無(wú)人機(jī)愛(ài)好者對(duì)例如Multiwii的開源飛控的關(guān)注,而大量開發(fā)者的涌入也將無(wú)人機(jī)的使用范圍大大拓寬,這時(shí)常規(guī)的2.4Ghz遙控器控制方式則顯得捉襟見肘。使用同樣開源的安卓手機(jī)作為控制器可玩性就增加了許多。
Multiwii 無(wú)人機(jī) 安卓 控制器
目前世界上主要的開源飛控系統(tǒng)有Pixhawk,APM,Multiwii,此項(xiàng)目挑選Multiwii飛控作為研究對(duì)象及控制板,主要原因有,Multiwii飛控體積相較APM和Pixhawk來(lái)說(shuō)要小很多,而且價(jià)錢非常便宜,只要APM的一半左右,Pixhawk的三分之一,其次,雖然Multiwii功能比較少,但是用來(lái)控制小型的無(wú)人機(jī)(軸距210mm左右)是完全足夠的,而且使用手機(jī)進(jìn)行基本的控制的話其他的功能是多余的,容易造成浪費(fèi),所以最終決定使用Multiwii飛控作為實(shí)驗(yàn)對(duì)象。
本項(xiàng)目主要使用藍(lán)牙來(lái)控制無(wú)人機(jī),和普通2.4G模塊控制不同,藍(lán)牙使用Serial port來(lái)進(jìn)行通信,而2.4G模塊則是使用普通的pin口,通過(guò)讀取PWM值來(lái)進(jìn)行控制,使用藍(lán)牙的優(yōu)點(diǎn)是手機(jī)本身就自帶藍(lán)牙,所以減少了工作量,而且也無(wú)需再添加2.4G信號(hào)發(fā)射機(jī),但缺點(diǎn)顯而易見,控制距離短,所以本項(xiàng)目控制的對(duì)象為相對(duì)較小的210mm軸距無(wú)人機(jī),可以比較輕松的在室內(nèi)進(jìn)行飛行。
要使用藍(lán)牙控制則需熟悉Multiwii Serial Protocol,串口傳輸協(xié)議,簡(jiǎn)而言之,只要藍(lán)牙發(fā)送的指令格式符合協(xié)議規(guī)定,藍(lán)牙終端就可以與Multiwii飛控板進(jìn)行通信,控制。
使用雙搖桿對(duì)無(wú)人機(jī)進(jìn)行控制;左搖桿主要控制控制油門和偏航(搖桿縱向,搖桿橫向)右搖桿控制俯仰和滾轉(zhuǎn)(搖桿縱向,搖桿橫向)除了左搖桿的縱向(Throt油門控制)其他方向均是放開搖桿后自動(dòng)回中,因?yàn)槿绻烷T舵也回中的話會(huì)對(duì)飛行器高度產(chǎn)生影響,使其不能維持原有高度。每個(gè)舵的舵量范圍為1000到2000,中點(diǎn)為1500。搖桿初始化時(shí)確定搖桿的中點(diǎn)位置,隨后搖桿運(yùn)動(dòng)后經(jīng)過(guò)與中點(diǎn)的差值運(yùn)算算出舵量,再整合到傳輸?shù)膍essage中,傳送至Multiwii飛控板。搖桿有一個(gè)使用范圍,即使手指挪動(dòng)超出這個(gè)范圍搖桿也繼續(xù)在手指移動(dòng)方向的圈上,不超出范圍(確保舵量最大值不超過(guò)2000,最小值不小于1000)。搖桿上方顯示各個(gè)信號(hào)的舵量(Throt油門,Yaw偏航,Pitch俯仰,Roll)使用ProgressBar來(lái)直觀的顯示舵量,方便操作。將ProgressBar的總量設(shè)為舵量的最大值,然后搖桿運(yùn)動(dòng)時(shí)產(chǎn)生的舵量顯示在ProgressBar中。搖桿舵量可以進(jìn)行微調(diào):假設(shè)當(dāng)兩搖桿都在中央(舵量輸出都是1500)但是無(wú)人機(jī)始終會(huì)向一個(gè)方向偏移(或者多個(gè)方向),就說(shuō)明舵量輸出不準(zhǔn)確,使用微調(diào)來(lái)調(diào)整其數(shù)值,使無(wú)人機(jī)正常飛行。
部分包括Rocker和Controller兩部分。Rocker用來(lái)得到用戶所需的各舵的數(shù)值,創(chuàng)建時(shí)首先獲取中心點(diǎn)的坐標(biāo),在移動(dòng)中通過(guò)與中心點(diǎn)坐標(biāo)進(jìn)行運(yùn)算得到各個(gè)舵量的數(shù)值。Controller每經(jīng)過(guò)一小段時(shí)間(50ms)獲取一次搖桿的舵量信息,并進(jìn)行封裝,利用ProtocolSender將整個(gè)控制Message進(jìn)行封裝,然后利用BluetoothService的Binder進(jìn)行發(fā)送控制Message。
藍(lán)牙模塊主要功能為接受Multiwii端發(fā)送的信息和向Multiwii端發(fā)送信息,發(fā)送使用向BlueToothGatt寫入特征值來(lái)實(shí)現(xiàn),而接受消息則使用BlueToothGatt的回調(diào)函數(shù)中的OnCharactiesChange函數(shù)進(jìn)行接收,接受內(nèi)容也是BluetoothGatt中的特征值。次要功能則有,搜索BLE設(shè)備,連接BLE設(shè)備,和斷開BLE設(shè)備。藍(lán)牙模塊為一個(gè)Service,所以有一個(gè)對(duì)應(yīng)的Binder來(lái)作為中間橋梁,作為Activities操作藍(lán)牙的接口。
通訊協(xié)議主要包含協(xié)議的指令集(Protocol),協(xié)議接收模塊(ProtocolHandler),協(xié)議發(fā)送模塊(ProtocolSender)。協(xié)議指令集(Protocol)最主要的功能就是提供對(duì)Multiwii進(jìn)行通信中所需的所有控制指令(Command)和發(fā)送或接收數(shù)據(jù)的數(shù)據(jù)包頭部(Header)。協(xié)議接收模塊(ProtocolHandler)功能為:將藍(lán)牙接收的消息按照Multiwii Serial Protocol進(jìn)行分析,根據(jù)不同的控制指令(Command)來(lái)對(duì)數(shù)據(jù)進(jìn)行處理以得到不同的信息。協(xié)議發(fā)送模塊(ProtocolSender)的功能為將搖桿傳回的舵量,依據(jù)Multiwii Serial Protocol來(lái)進(jìn)行封裝,將數(shù)據(jù)個(gè)數(shù)(舵的個(gè)數(shù)),控制指令(Command),封裝的各個(gè)舵量,校驗(yàn)和封裝為一個(gè)Message,因?yàn)槊看蜗騇ultiwii傳輸?shù)腗essage長(zhǎng)度不都一樣,所以先將Message放入ArrayList中,再調(diào)用listToArray轉(zhuǎn)為byte數(shù)組,至此整個(gè)Message封裝完畢。
RC(RadioControl);RC 部分包括 Channel模塊和Data模塊。Channel為每個(gè)舵量原始值的封裝,通過(guò)搖桿移動(dòng)時(shí),對(duì)搖桿中間的值進(jìn)行運(yùn)算的到的數(shù)值做基本的封裝,Channel部分實(shí)現(xiàn)了輸出舵量在1000-2000之間,微調(diào)時(shí)也是通過(guò)調(diào)整Channel的value來(lái)實(shí)現(xiàn)輸出舵量的變化。Data模塊功能則是將各個(gè)舵量的Channel進(jìn)一步進(jìn)行封裝,為封裝控制Message做準(zhǔn)備。Data分別將四個(gè) Channel(Throt,Yaw,Pitch,Roll)的值取出,然后封裝進(jìn)一個(gè)ArrayList中,再通過(guò)listToArray轉(zhuǎn)換為byte數(shù)組,至此完成封裝。
搖桿的父類為Button,但是修改Button的Shape,修改為圓形。搖桿需要實(shí)現(xiàn)的功能為搖桿隨手指移動(dòng)但是并不是搖桿的中心一直在手指按壓的地方。有一個(gè)活動(dòng)界限,當(dāng)手指移動(dòng)超出活動(dòng)界限時(shí),搖桿依舊在活動(dòng)界限的邊緣。當(dāng)實(shí)例化搖桿時(shí)先獲取搖桿的中心點(diǎn)坐標(biāo)(centerValue_x,centerValue_y)。為實(shí)現(xiàn)搖桿功能,重寫了父類的onTouchEvent方法。實(shí)現(xiàn)隨動(dòng)功能,當(dāng)手指按下時(shí),先獲取按下的坐標(biāo)(x,y),再計(jì)算x,y與centerValue_x, centerValue_y的差值toCenter_x,toCenter_y,然后使搖桿 button invisible。實(shí)際上隨手指移動(dòng)的并不是搖桿本身,而是搖桿的一個(gè)鏡像(ImageView),所以得到toCenter后開啟搖桿的繪圖緩沖,獲取搖桿的 bitmap(Bitmap.createBitmap(getDra wingCache())),隨后便釋放緩存,避免重復(fù)鏡像。隨后添加WindowManager.LayoutParams的參數(shù),主要有g(shù)ravity,x,y(x,y并不是需要繪制的圖形的中心,而是左邊緣和上邊緣),alpha(透明度),width,height。之前已經(jīng)獲取了CenterValue所以x的值為cneterValue_x-getWidth/2,y為 centerValue_y-getHeight/2。之前已經(jīng)獲取了搖桿的bitmap,所以使用setImageBitmap方法初始化拖拽用的imageView,隨后將這個(gè)ImageView利用windowManager的addView添加至屏幕中。拖拽的實(shí)現(xiàn)只需改變layoutParams的x,y再調(diào)用windowManager的updateViewLayout即可。拖拽過(guò)程中隨手指移動(dòng)的imageView的x=moveX - toCenter_x - getWidth()/2,y=moveY - toCenter_y -getHeight()/2 - statusHeight(statusHeight為狀態(tài)欄的高度),只要刷新x,y值就可實(shí)現(xiàn)隨手指移動(dòng)。邊界使用一個(gè)比搖桿大一些的圓形Button,中點(diǎn)與搖桿相同,位置在搖桿下方,可省去觸摸事件分配的代碼量。邊界主要作用是限制搖桿的移動(dòng),以及確保傳出的數(shù)值無(wú)論縱向橫向都是1000-2000。邊界的實(shí)現(xiàn)(舉x方向?yàn)榱校┊?dāng)搖桿移動(dòng)時(shí)的中心在邊界內(nèi)時(shí),按照正常的拖拽即可,當(dāng)超出時(shí),搖桿只會(huì)停留在邊界,但是如果手指在邊界外移動(dòng),搖桿也要在邊界移動(dòng),實(shí)現(xiàn)方法為利用相似三角形定理,moveX到centerValue_x的距離比上搖桿中心到center的距離 = x比上邊界半徑,由此可求出當(dāng)手指移出邊界外,移動(dòng)時(shí),搖桿在邊界上的坐標(biāo),實(shí)現(xiàn)邊界的作用。搖桿移動(dòng)時(shí)需隨時(shí)傳出舵量,搖桿上下移動(dòng)時(shí)舵量的輸出大小是以中點(diǎn)1500來(lái)做運(yùn)算。先得出每像素代表多少舵量(分量),然后用移動(dòng)中的搖桿的中點(diǎn)坐標(biāo)(layoutParams.x,layoutParams.y)減去中心點(diǎn)坐標(biāo)(centerValue_X,centerValue_y)然后乘上分量,加或減去1500(在中點(diǎn)上方,或右方為加。在中點(diǎn)下方或左方為減)。手指離開屏幕時(shí),從WindowManager中移除ImageView然后使原來(lái)的搖桿button visible
BLE和Blutooth2.0的開發(fā)有一 些區(qū)別,由于BLE誕生較晚,所以整體設(shè)計(jì)語(yǔ)言也是以之后的回調(diào)機(jī)制為主,相較更為復(fù)雜,連接不再只是一段代碼,而是將一個(gè)遠(yuǎn)程BLE設(shè)備抽象為一個(gè)BlueToothGatt對(duì)象,連接則變?yōu)榕c這個(gè)Gatt對(duì)象進(jìn)行連接,之后再通獲取Gatt的BlueToothGattService,再 獲 取Service中的BlueToothGattCharacteristic作為傳輸介質(zhì),然后上位機(jī)和下位機(jī)通過(guò)對(duì)BlueToothGattCharacteristic的Value進(jìn)行寫值,從而實(shí)現(xiàn)兩端的通信。在回 調(diào) 類(BluetoothGattCallback) 中 通 過(guò) 重 寫onCharacteristicChanged方法實(shí)現(xiàn)對(duì)接受到的信息進(jìn)行處理。掃描設(shè)備同樣采用了回調(diào)機(jī)制(scanCallback),通過(guò)重寫scanCallbakc的onScanResult方法可獲取遠(yuǎn)程BluetoothDevice列表,再通過(guò)用戶選擇來(lái)得到想要的遠(yuǎn)程BluetoothGatt。
Multiwii Serial Protocol。要是想與FC進(jìn)行通信,Message就必須遵循一定的格式,這個(gè)格式就是MSP(Multiwii Serial Protocol),協(xié)議分兩種,一種是向F'C發(fā)送消息,一種是從F'C獲得信息。發(fā)送消息的格式為 <header>,<direction>,<size>,<command>,<data>...,<crc>,Header為 $M 的字符串,direction 確定是從F'C獲取信息還是向Multwii發(fā)送消息,’>’為向FC發(fā)送消息,’<’為從FC獲取消息。size為data的數(shù)據(jù)長(zhǎng)度,crc為Message的校驗(yàn)和,校驗(yàn)和的算法為:先將校驗(yàn)和初始為(char)0再依次與size,command,每個(gè)data作異或運(yùn)算(^=)最后得出校驗(yàn)和。例如,我想獲取FC的版本,這條指令是想從FC獲取信息,所以direction為’<’,查詢MSP(MSP_IDENT)得command(MSP文檔中為message_id)為100(0x64)所以,因?yàn)槭谦@取信息,所以data為空,crc為command,所以整合得一個(gè)獲取FC版本的Message為”$M<0dd”(字符d的ascii碼為100)。
安卓端使用搖桿控制無(wú)人機(jī)只是一種最基本的用法,這也就意味著在安卓端實(shí)現(xiàn)了了一個(gè)控制接口,而擁有控制接口之后就可以進(jìn)行一些很有趣的拓展,例如在手機(jī)端實(shí)現(xiàn)一個(gè)環(huán)境的建模,手機(jī)就可以針對(duì)這個(gè)環(huán)境規(guī)劃這個(gè)環(huán)境的飛行路線,從而做到自動(dòng)控制。
[1]郭霖.第一行代碼,北京: 人民郵電出版社,2016-12-01
[2]張?jiān)?深入理解Android系統(tǒng),北京:清華大學(xué)書版社,2015-5
[3]Multiwii 官方文檔http://www.multiwii.com/wiki/index.php?title=Multiwii_Serial_Protocol
[4][美] Michael Margolis 著;楊昆云 譯.Arduino權(quán)威指南(第2版),北京: 人民郵電出版社,2015-03-01
本文由計(jì)算機(jī)學(xué)院大學(xué)生創(chuàng)新實(shí)踐基地建設(shè)項(xiàng)目資助,項(xiàng)目號(hào):5111723400。
趙旭,男,本科,北京信息科技大學(xué)計(jì)算機(jī)學(xué)院。彭克勤,女,碩士,副教授,北京信息科技大學(xué)計(jì)算機(jī)學(xué)院。