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