姚冰冰,袁志敏,吳 梅
(1.西北工業(yè)大學(xué) 陜西 西安 710129;2.陜西飛機(jī)工業(yè)(集團(tuán))有限公司設(shè)計研究院 陜西 漢中 723213)
隨著現(xiàn)代無人機(jī)的發(fā)展,為了能更好地監(jiān)視無人機(jī)的飛行狀況并對無人機(jī)進(jìn)行控制,人們使用了各種地面設(shè)備,包括人工水平儀、慣性測量單元指示器、3D視景[1]、電子地圖等,來輔助操作員對無人機(jī)的飛行數(shù)據(jù)和任務(wù)設(shè)備進(jìn)行實(shí)時地監(jiān)控。其中電子地圖是伴隨著計算機(jī)技術(shù)的發(fā)展而出現(xiàn)的地圖新形式,Google Earth是其中的典型代表。
傳統(tǒng)的紙質(zhì)地圖在人類歷史上扮演了重要角色,隨著計算機(jī)技術(shù)的發(fā)展,人們發(fā)明了更加精確、靈活的電子地圖。從20世紀(jì)80年代起,歐美很多國家就開始了相關(guān)研究,到現(xiàn)在電子地圖技術(shù)已得到了很大發(fā)展,廣泛的應(yīng)用到了交通和導(dǎo)航領(lǐng)域[2]。
Google Earth是Google公司開發(fā)的一款虛擬地球軟件,它把航拍照片、衛(wèi)星圖像和GIS數(shù)據(jù)整合在一起,形成一個地球的三維模型[3]。Google Earth的數(shù)據(jù)大都來源于美國國家航空航天局(NASA)的衛(wèi)星圖像,用戶可以通過它來足不出戶的瀏覽世界。Google Earth還可以進(jìn)行二次開發(fā),來實(shí)現(xiàn)一些復(fù)雜的應(yīng)用需求。
目前針對Google Earth的開發(fā)主要有兩種方式,第一種是基于Google Earth的API;第二種是基于KML文件[4]。編寫程序時,為了實(shí)現(xiàn)特定功能,需要結(jié)合使用這兩種開發(fā)方式。
Google公司提供了Google Earth API類庫,基于此用戶可以在外部程序中調(diào)用Google Earth的功能。Google Earth API類庫包含十一個類,主要用到的有:
1)IApplicationGE類,該類是Google Earth API的入口類,通過該類可以控制Google Earth客戶端的開啟、關(guān)閉,獲取視圖窗口句柄、主窗口句柄,還可以進(jìn)行獲取地圖視場照相機(jī)對象、Google Earth版本號、轉(zhuǎn)換坐標(biāo)等復(fù)雜操作[3];
2)ICameraInfoGE類,該類表示Google Earth地圖上某一點(diǎn)的視場照相機(jī),通過該類可以獲取并設(shè)置視場照相機(jī)的焦點(diǎn)位置、轉(zhuǎn)角、仰角、方位角等參數(shù);
3)IPointOnTerrainGE類,該類是IApplicationGE類的成員函數(shù) GetPointOnTerrainFromScreenCorrds()的返回類型,通過該類可以將Google Earth坐標(biāo)系內(nèi)一點(diǎn)轉(zhuǎn)化為經(jīng)緯度信息。
其 他 的 類 還 有 :IFeatureGE、IFeatureCollectionGE、IView ExtentsGE、ISearchControllerGE、ITourControllerGE、IAnimation ControllerGE、ITimeGE、ITimeIntervalGE,分別用來實(shí)現(xiàn)不同的功能。
KML是一種基于XML語法與格式的、用于描述和保存地理信息(如點(diǎn)、線、圖像、多邊形、模型等)的編碼規(guī)范,KML文件可以被Google Earth識別并顯示。
像XML一樣,KML使用基于 tag的表達(dá)方式,tag以結(jié)尾。Google Earth定義了種類繁多的tag,包括地標(biāo)、說明、地面疊加層、路徑和多邊形等。本文主要用到的 tag有:Placemark,地標(biāo)元素,包含了其它元素;LookAt,視場照相機(jī)所處位置元素,包含longitude、latitude、altitude、heading、tilt、range 元素;visibility 元素, 可見性;LineString,路徑元素,包含 altitudeMode、coordinates元素;coordinates元素,坐標(biāo)元組,每個包括經(jīng)度、緯度和海拔的浮點(diǎn)值;altitudeMode元素,用來指定如何解釋與之對應(yīng)的coordinates元素中的海拔分量;Style元素,設(shè)定一個樣式;Point元素,點(diǎn)元素,包含altitudeMode、coordinates 元素[5]。
KML文件的tag使用了包含關(guān)系,這樣就可以修改單個Placemark元素的LookAt屬性,或是對單個LineString元素或Point元素的altitudeMode屬性進(jìn)行設(shè)置。
作為監(jiān)控?zé)o人機(jī)飛行狀態(tài)的地面設(shè)備的一部分,導(dǎo)航電子地圖應(yīng)該實(shí)現(xiàn)地圖顯示、地圖定位、規(guī)劃航跡、顯示實(shí)時航跡、重現(xiàn)航跡等功能,本文由于篇幅所限,僅重點(diǎn)實(shí)現(xiàn)一些功能。
這里在Microsoft Visual Studio 2008開發(fā)環(huán)境中基于MFC編寫程序?qū)崿F(xiàn)所需功能,主要包括視圖嵌入、繪制航跡、查看航跡等功能。
1)將所用到的類導(dǎo)入到所建項目中。所用到的類型庫為“Google Earth 1.0 Type Library<1.0>”,在項目中添加即可。
2)啟動Google Earth客戶端。先調(diào)用IsInitialized()判斷客戶端是否初始化成功,否則調(diào)用CreateDispatch()來啟動Google Earth客戶端,其中 CreateDispatch()接受一個 CLSID類型的參數(shù),在Google Earth COM API官方文檔可查到Google Earth的CLSID值。
3)將Google Earth視圖窗口嵌入到主程序界面中。分別調(diào)用 GetMainHwnd()和 GetRenderHwnd()得到 Google Earth主窗口句柄和Google Earth視圖窗口句柄,然后調(diào)用Windows API函數(shù) SetWindowPos()函數(shù)將 Google Earth的界面隱藏掉,再調(diào)用Windows API函數(shù)SetParent()函數(shù)將Google Earth視圖窗口嵌入到主程序界面中。
程序執(zhí)行效果圖1所示:
圖1 Google Earth視圖嵌入效果Fig.1 Embedded effect of the Google Earth view window
規(guī)劃航跡要將一些地點(diǎn)加入到航跡中,這里用兩種方式實(shí)現(xiàn)添加航跡點(diǎn):1,在Google Earth視圖中添加;2,輸入經(jīng)緯度來添加。第一種方式需要使用鉤子技術(shù),彈出右鍵菜單功能,轉(zhuǎn)換坐標(biāo)方法等,兩種方式都要用到KML文件。
2.2.1 鉤子技術(shù)
瀏覽Google Earth視圖是了解某一地區(qū)地形和相對位置最直觀的方式,有時需要將某個地點(diǎn)加入到航跡中,這里實(shí)現(xiàn)右鍵彈出菜單的功能,在菜單中決定是否將選中地點(diǎn)加入航跡。
Google Earth沒有提供和鼠標(biāo)按鍵有關(guān)的接口函數(shù)[6],需要通過響應(yīng)鼠標(biāo)右鍵消息來進(jìn)行相應(yīng)動作,但鼠標(biāo)在Google Earth視圖窗口中點(diǎn)擊產(chǎn)生的消息會被Google Earth攔截,導(dǎo)致響應(yīng)不了自定義的右擊消息的響應(yīng)。要實(shí)現(xiàn)上述功能需要使用鉤子(Hook)技術(shù)。
Windows系統(tǒng)是建立在以消息為基礎(chǔ)的事件驅(qū)動機(jī)制上的,操作系統(tǒng)將硬件產(chǎn)生的消息(如鼠標(biāo)移動或鍵盤按下)、操作系統(tǒng)產(chǎn)生的消息和其他Windows程序傳送過來的消息放在消息隊列中,等待應(yīng)用程序調(diào)用[7]。而鉤子可以截獲并處理這些消息,以實(shí)現(xiàn)自己期望的功能。鉤子分為線程鉤子和系統(tǒng)鉤子,線程鉤子只能攔截當(dāng)前線程的消息,而系統(tǒng)鉤子則能攔截系統(tǒng)中所有線程的事件消息。因為系統(tǒng)鉤子會影響系統(tǒng)中所有的應(yīng)用程序,其鉤子函數(shù)需要放在動態(tài)鏈接庫(dll)中。系統(tǒng)鉤子原理如圖2所示。
對本文的程序來說,Google Earth視圖窗口嵌入到主程序的界面后,Google Earth在后臺運(yùn)行,當(dāng)前線程所屬進(jìn)程是主程序,綜上考慮需要采用系統(tǒng)鉤子。
在MFC下實(shí)現(xiàn)右鍵彈出菜單,可以選擇響應(yīng)WM_RBUTTONDOWN、WM_RBUTTONUP或 WM_CONTEXTMENU消息,這里選擇響應(yīng)WM_CONTEXTMENU消息。
在動態(tài)鏈接庫中編寫鉤子處理函數(shù),攔截到WM_RBUTTONUP消息后,向主窗口發(fā)送WM_CONTEXTMENU消息;主程序中在WM_CONTEXTMENU消息的處理函數(shù)中進(jìn)行彈出菜單的動作。程序執(zhí)行效果如圖3所示。
圖2 系統(tǒng)鉤子原理Fig.2 Principle of system hook
圖3 Google Earth視圖窗口右鍵效果Fig.3 Effect of right button clicked on Google Earth view window
2.2.2 Google Earth坐標(biāo)系與屏幕坐標(biāo)系
在Google Earth視圖中將選中地點(diǎn)添加到航跡時,還需要取得選中地點(diǎn)的屏幕坐標(biāo),傳遞給主程序,一方面WM_CONTEXTMENU消息的處理函數(shù)需要這個數(shù)值,以在鼠標(biāo)右鍵點(diǎn)擊的地點(diǎn)彈出菜單;另一方面,需要將該所選地點(diǎn)的屏幕坐標(biāo)轉(zhuǎn)換為經(jīng)緯度信息寫入KML文件,以進(jìn)一步使用。
Google Earth沒有提供獲取屏幕坐標(biāo)的函數(shù),也沒有提供從屏幕坐標(biāo)系向地理坐標(biāo)系轉(zhuǎn)換的函數(shù),只提供了從Google Earth坐標(biāo)系向地理坐標(biāo)系轉(zhuǎn)換的Get Point On Terrain From ScreenCoords()[6]函數(shù),該函數(shù)在 IApplicationGE類中定義,接受兩個參數(shù),分別是選中地點(diǎn)在Google Earth坐標(biāo)系中的橫坐標(biāo)和縱坐標(biāo),因此需要先得到這兩個參數(shù)的值。
Google Earth坐標(biāo)系和屏幕坐標(biāo)系對應(yīng)關(guān)系如圖4所示。
圖中xoy為Google Earth坐標(biāo)系,橫坐標(biāo)與縱坐標(biāo)范圍都為-1到1;XOY為屏幕坐標(biāo)系,虛線部分為Google Earth視圖窗口,(L,T)為其左上角頂點(diǎn)在屏幕坐標(biāo)系坐標(biāo),(R,B)為其右下角頂點(diǎn)在屏幕坐標(biāo)系坐標(biāo),(Ox,Oy)為視圖中心在屏幕坐標(biāo)系坐標(biāo)。
通過圖4所示對應(yīng)關(guān)系,可以得到屏幕坐標(biāo)系中一點(diǎn)(x,y)與 Google Earth 坐標(biāo)系中對應(yīng)點(diǎn)(GEx,GEy)的關(guān)系:
(x-Ox)/(R-L)=(GEx-0)/(1-(-1)),
圖4 Google Earth坐標(biāo)系和屏幕坐標(biāo)系對應(yīng)關(guān)系Fig.4 Correspondence of google earth coordinate and screen coordinate
(Oy-y)/(B-T)=(GEy-0)/(1-(-1))。
其中,屏幕坐標(biāo)(x,y)由鉤子程序取得,傳給主程序;頂點(diǎn)坐標(biāo) (L,T)、(R,B) 可調(diào)用 Windows API函數(shù) Get Window Rect()得到;視圖中心坐標(biāo)(Ox,Oy)可由(L,T)、(R,B)計算得到,由此可計算出 Google Earth坐標(biāo)(GEx,GEy)。然后用上面提到的函數(shù)Get Point On Terrain From ScreenCoords()將之轉(zhuǎn)化為地理坐標(biāo),寫入KML文件中。
2.2.3 讀寫KML文件
KML文件本質(zhì)上還是XML文件,讀寫XML文件的方法有很多,這里使用CMarkUp類來修改KML文件內(nèi)容。
添加航線和航跡點(diǎn)時,可以事先在KML文件中預(yù)先寫好一定數(shù)量的LineString元素和Point元素,在添加時按次序修改。但由于每次要添加的航線數(shù)和航跡點(diǎn)數(shù)是不同的,上述方法并不合適,這里根據(jù)KML語法特征構(gòu)建一個線模版KML文件和一個點(diǎn)模版KML文件[8],添加航線或航跡點(diǎn)時,復(fù)制該模版文件,然后修改所復(fù)制的文件的相應(yīng)元素。
對于所添加航跡點(diǎn),要設(shè)置標(biāo)記來突出顯示,這可以通過使用Style元素來實(shí)現(xiàn)。
添加航線流程圖如圖5所示。
圖5 添加航線流程圖Fig.5 Flow chart of adding track routes
流程圖中,l用來計數(shù)當(dāng)前添加的是第幾條航線;p用來計數(shù)當(dāng)前添加的是第幾個航跡點(diǎn),以給復(fù)制的文件命名及之后調(diào)用。
添加新航線之前,應(yīng)隱藏上一條添加的航線和航跡點(diǎn),這可以通過修改KML文件的visibility元素的值做到,其值為1表示可見,為0表示不可見。
讀KML文件時,使用IApplicationGE類的OpenKmlFile()函數(shù),該函數(shù)接受兩個參數(shù),第一個參數(shù)為要讀取的KML文件的絕對路徑,第二個參數(shù)為1。每次添加航跡點(diǎn)后,都需要讀取l-p.kml,使選中的地點(diǎn)顯示出標(biāo)記效果。
完成添加航跡點(diǎn)后,使用OpenKmlFile()函數(shù)讀取l.kml文件,即可在Google Earth視圖上形成航跡,繪制航跡效果如圖6所示。
圖6 繪制航跡效果圖Fig.6 Effect of drawing track route
完成添加航線后,有時需要查看已經(jīng)規(guī)劃好的航跡,可以在地圖上直觀查看其地理位置或者查看某條航跡上的航跡點(diǎn)信息,這些需要用到一個帶復(fù)選框的List Box控件。MFC沒有提供帶復(fù)選框的List Box控件,可以修改其Owner Draw屬性和Has Strings屬性,并將綁定的控件類型改為CCheckListBox即可。
每次添加新航線后,要在List Box控件中生成一個新條目,以便全部添加完成后查看該航線信息。
通過勾選條目之前的復(fù)選框狀態(tài),來決定是否在地圖上顯示某航跡。復(fù)選框狀態(tài)改變后,會發(fā)送ON_LBN_SELCHANGE消息,在該消息的處理函數(shù)OnSelchangeList()中添加代碼,實(shí)現(xiàn)顯示某條航線的功能。顯示航線流程圖如圖7所示。
流程圖中,i和j分別用來給條目和航跡點(diǎn)計數(shù),由于條目編號從0開始,而航線編號從1開始,因此條目i對應(yīng)的航線號為i+1。
通過雙擊條目來顯示某條航跡的詳細(xì)信息。雙擊List Box會發(fā)送ON_LBN_DBLCLK消息,在該消息的處理函數(shù)OnBnDBClickedListBox()添加代碼,通過 CMarkUp類來讀取所點(diǎn)擊航線對應(yīng)的KML文件,獲取其coordinates元素信息,經(jīng)過字符串處理,就能得到該航線各個航跡點(diǎn)的經(jīng)度、緯度和海拔值。
顯示實(shí)時航跡就是要在電子地圖上動態(tài)顯示無人機(jī)的飛行過程,以檢驗飛行效果和任務(wù)執(zhí)行情況。這里需要讀取保存無人機(jī)飛行數(shù)據(jù)的EXCEL文件,讀取EXCEL文件的方法有很多,本文選用BasicExcel類來讀取[9]。
圖7 顯示航線流程圖Fig.7 Flow chart of displaying track route
首先建立一個包含Point元素和Style元素的KML文件,其LookAt元素和coordinates元素修改為無人機(jī)的初始位置,設(shè)置Style元素標(biāo)記用來表示無人機(jī);使用LineStyle元素來給表示實(shí)時航跡的線條設(shè)置不同的顏色和粗細(xì)度,以區(qū)別于規(guī)劃的航跡。
每隔固定時間,通過讀取EXCEL文件得到經(jīng)緯度信息,依此來修改KML文件中coordinates元素的值,然后讀取KML文件。這樣每次讀取,無人機(jī)標(biāo)記就會顯示在其實(shí)際飛行位置。實(shí)時航跡顯示效果如圖8所示。
圖8 實(shí)時航跡顯示效果圖Fig.8 Effect of Real-time track routes display
圖中,細(xì)線為規(guī)劃的航跡,粗線為實(shí)際飛行航跡。
Google Earth是Google公司開發(fā)的一款優(yōu)秀軟件,普通用戶可以通過它來免費(fèi)瀏覽全球各地的高清晰度衛(wèi)星圖片。而有特殊需求的用戶則可以通過二次開發(fā)做出特定功能。本文基于Visual Studio 2008平臺,利用Google Earth API和KML文件,編寫程序?qū)崿F(xiàn)了規(guī)劃航跡、查看航跡和顯示實(shí)時航跡等功能。
[1]DanielPerez,Ivan Maza, Fernando Caballero, David Scarlatti, Enrique Casado, Anibal Ollero.A Ground Control Station for a Multi-UAV Surveillance System[J].Journal of Intelligent&Robotic Systems,2013,69(1-4):119-130.
[2]王倩.基于GIS的電子導(dǎo)航圖和任務(wù)規(guī)劃[D].西安:西北工業(yè)大學(xué),2007.
[3]江寬,龔小鵬.Google API開發(fā)詳解:Google Maps與Google Earth雙劍合璧[M].北京:電子工業(yè)出版社,2008.
[4]馬俊.基于GoogleEarth的無人機(jī)地面站監(jiān)控系統(tǒng)[D].南京:南京航空航天大學(xué),2011.
[5]Google.Google Developers:Keyhole 標(biāo) 記 語 言 [EB/OL].(2013-09-30)[2013-11-08].https://developers.google.com/kml/documentation/kmlreference?hl=zh-CN.
[6]馬謙.智慧地圖:Google Earth/Maps/KML核心開發(fā)技術(shù)揭秘[M].北京:電子工業(yè)出版社,2010.
[7]侯俊杰.深入淺出MFC[M].武漢:華中科技大學(xué)出版社,2002.
[8]楊鑫,鄭新奇.Google Earth二次開發(fā)制圖接口設(shè)計與實(shí)現(xiàn)[J].中國科技論文在線精品論文,2011,4(18):1692-1696.YANG Xin,ZHENG Xin-qi.An interface for drawing features in secondary development of Google Earth[J].Highlights of Sciencepaper Online,2011,4(18):1692-1696.
[9]劉瑞通,茍先太,馬超,等.基于BasicExcel的讀寫Excel方法研究[J].計算機(jī)與現(xiàn)代化,2011(8):198-200.LIU Rui-tong,GOU Xian-tai,MA Chao,et al.Methods of accessexcelbased on basicExcel [J].Computerand Modernization,2011(8):198-200.