「讀一份好源碼,就是和許多智慧的人談話「。
本文記錄了幾位筆者學習 RTKLIB 開源軟體,與同學交流探討,獲得的一些初步經驗和心得。如果你對衛星導航定位有興趣,需要用到相關技術,這篇文章正好就是你的菜。
全文約7000字,含9副圖和2個表格,閱讀時間大約22分鐘。
內容目錄1. 簡單介紹2. 代碼特點3. 疑似bugs4. 優化tips5. 簡單測試6. 20個問與答7. 寫在最後
簡單介紹RTKLIB是日本東京海洋科技大學(Tokyo University of Marine Science and Technology)高須知二(Tomoji Takasu)採用C/C++語言開發的,開源用戶端高精度GNSS數據處理軟體。提供從標準單點定位、精密單點定位、偽距差分定位到高精度雙差相對定位,豐富的數據處理功能。支持實時和事後處理模式。支持GPS、GLONASS、GALILEO、BEIDOU、QZSS、IRNSS等導航衛星系統和常用的 RINEX 2、3 等文件格式。在定位程序之外,還提供了用於觀測值和星曆下載的rtkget,對觀測數據和解算結果進行繪圖顯示的rtkplot程序等。
軟體代碼同時託管在 RTKLIB 官網和GitHub上,當前正式版為2013年4月發布的v2.4.2,最近一次發布p13補丁的時間為2018年1月。當前最新開發版為v2.4.3 beta 32,更新時間為2019年5月。
RTKLIB 功能強大而且完善,提供了從數據讀寫、觀測值預處理、誤差改正,到定位解算、結果分析的一整套GNSS精密定位領域主流和常用的算法實現。算法穩健可靠,代碼風格統一、可讀性高、模塊化強、容易擴展。除了提供所有原始碼、Windows平臺編譯生成的可執行文件外,還附帶一份詳細的180頁的英文說明手冊,對程序功能、如何使用,及算法基本原理都做了詳細的介紹。
正因為如此,從一推出開始,RTKLIB就受到了國內外學生和研究人員的廣泛關注。多年前筆者剛讀研時,博士師兄 YXW 介紹了該軟體給我。直到現在,當有師弟師妹求推薦PPP,或是相對定位方向的開原始碼時,周圍不少老師、師兄(還有我)首先推薦的就是RTKLIB。
在公開可獲取的資料中,筆者已知有以下的網站、服務、軟體、論文參考或致謝了RTKLIB:
【網站】
http://rtkexplorer.com/ (Exploring high precision GPS/GNSS with low-cost hardware and software solutions)
【軟體】
[1] GAMP 軟體,基於RTKLIB二次開發;
[2] PRIDE-PPPAR軟體,使用了rnx2rtkp可執行程序計算測站初值坐標;
[3] pppwizard軟體 (http://www.ppp-wizard.net/package.html);
[4] ignav (integrated navigation for ins and gnss,https://github.com/Erensu/ignav)
【學位論文】
[1] 範姜士彥 (2016) 使用開源軟體RTKLIB探討GPS連續站地球科學應用案例[D]. 國立中正大學,臺灣,嘉義;
[2] 李盼 (2016) GNSS精密單點定位模糊度快速固定技術和方法研究[D]. 武漢大學,湖北,武漢;
[3] 劉帥 (2017) 模糊度固定解PPP+INS緊組合理論與方法[D]. 解放軍信息工程大學,河南,鄭州;
[4] Paulo Sérgio de Oliveira Junior (2017) Definition and implementation of a new service for precise GNSS positioning [D]. Universidade Estadual Paulista, France;
此外,據筆者了解,有不少同學站在巨人的肩膀上,對 RTKLIB 做了深度的私人訂製,實現了:大氣延遲(對流層/電離層)的提取、建模;GNSS+INS組合;事後LSQ模式PPP;PPP模糊度固定;精密衛星鐘差估計;DCB、UPD等BIAS產品的估計等等。
另外值得一提的是,RTKLIB並非是高須知二唯一的開源軟體。2006-2009年期間,高須同時開源了基於MATLAB開發的GPS/GNSS精密分析軟體包GpsTools (GT) 和RTKLIB。GT支持用戶端單站PPP,也支持多基站網解,更主要面向服務端數據處理,支持GPS精密定軌和鐘差估計!!並達到了較高的精度。源碼裡附帶的一些c文件和函數和RTKLIB的較為接近。不過有geograv_e.c, satorbit.c, satorbit_e.c, satorbit_s.c, shadowfunc.c, shadowfunc_e.c 這6個文件未開源,僅提供二進位文件。2009年,GT發布了最後一個版本0.6.4後,作者開源的重點便轉向了RTKLIB,去掉了服務端數據處理功能,專門針對用戶端的PPP/RTK數據處理。
代碼特點RTKLIB 的代碼風格總結如下:
基於原生C語言,無外部依賴庫;
跨Windows和Linux平臺;
src文件夾下c文件裡所有函數的聲明都在rtklib.h一個頭文件裡;
多數函數具有清晰的注釋,說明函數功能,輸入變量,輸出變量,參考文獻;
函數和變量都使用小寫字母+縮寫的命名方式,風格統一;
結構體都是用"小寫字母+縮寫"+"_t"的命名方式;
只用到了基本數據類型,如int,bool,double,char等及其組合,基本靜態、動態數組簡單數據結構,二分查找,快速排序這些簡單但高效的算法。沒用使用標準模板類庫(STL),無複雜語言特性;
rtkpost等工程代碼使用 C++面向對象設計;
模塊化程度高,一個函數隻做一件事情;
……
軟體各模塊的文件數,代碼量信息如下:
以上統計沒有考慮空白行與注釋行。總共441個函數,平均每個函數26行代碼,短小精悍。閱讀起來比較舒服。
除了上述文件外,實時數據流處理相關的文件有 rcvraw, rtcm, rtcm2, rtcm3, rtcm3e, rtksvr, stream, streamvsr。其他非核心功能的 c 文件還有12個左右。
疑似bugsDoppler觀測值計算速度的bugs
用 IGS網 帶都卜勒觀測值的測站計算速度,有些站速度估值超過100m/s,如2019年第150天的albh、bake、chur、dubo、flin、hlfx、iqal、nrc1、prds、sch2、stjo、whit、vald、yell等測站,結果顯然是不對的。
匹配大寫後綴精密產品出錯
preceph.c 的readsp3函數如下行:
if (!strstr(ext+1,"sp3")&&!strstr(ext+1,".SP3")&&
!strstr(ext+1,"eph")&&!strstr(ext+1,".EPH")) continue;
讀衛星數不固定的精密衛星軌道文件有問題
preceph.c 的readsp3b函數;
SPP定權公式sin(el)沒有開方
pntpos.c 第42行:
varr=SQR(opt->err[0])*(SQR(opt->err[1])+SQR(opt->err[2])/sin(el));
PPP使用CA碼且沒改正DCB時,沒對偽距降權
ppp.c 文件的 corr_meas 函數。
atx文件中,接收機端存在GPS和GLO雙系統PCO/PCV時,會用GLO系統的值覆蓋GPS
rtkcmn.c 文件的 readantex 函數。
優化tips更穩健的Kalman濾波公式;
Kalman濾波量測更新計算估值方差協方差的公式為Pp=(I-KH')P,計算機處理時可能由於截斷誤差導致Pp矩陣不對稱。使用等效的計算公式Pp=(I-KH')P(I-KH')'+KRK' 更穩健。
增加DIA質量控制;
數據預處理過程是無法正確識別出所有周跳的。一種常用的思路是,預處理部分設置略微寬鬆一點的閾值,然後對PPP的殘差等信息進行診斷,識別出漏判的周跳,再進行迭代處理。RTKLIB對此支持不太好。
天線文件只需要讀一次;
源碼中需對衛星和測站各指定一個atx文件,分別讀取。實際上標準的igs的天線文件同時提供了衛星和接收機的PCO、PCV信息。讀取一次即可。
鍾跳探測與修復;
採用價格較為低廉的石英鐘的大地測量型與導航型 GNSS 接收機,為了儘可能地保持接收機內部時鐘與 GPS時同步,當接收機鐘差漂移到某一閾值時,大多數接收機廠商通過對其插入時鐘跳躍進行控制。
鍾跳可能造成觀測值不連續,使得周跳探測模塊將所有衛星都標記為周跳,引起模糊度重置,影響解算效果。所以必須先進行鍾跳探測和修復後再探測周跳。具體修復算法可以參考Fei Guo 有關論文[1]。其論文也表明,IGS站網中就有 10+以上 測站存在鍾跳。
對各系統分別設置不同的偽距和載波噪聲;
GRECJ這5大衛導系統的觀測值精度、精密產品精度差別比較大。不分系統設置一套偽距/載波的測量誤差值不合理。
模糊度過程噪聲過大;
rtkpost.exe可執行程序默認的模糊度過程噪聲為1e-4m/sqrt(s),和對流層一樣。筆者經驗為應將該值直接設置為0,或者降低幾個數量級。
簡單測試筆者在win7平臺下用 Python調用 rnx2rtkp.exe,對2019年5月30日MGEX網的225個測站的GPS數據進行動態PPP浮點解解算。所用的計算機的配置為:Intel i7-4710MQ @ 2.50GHz + 12G DDR3 1600Mhz內存 + 機械硬碟。成功生成了每個測站的.pos定位結果文件,總共計算耗時為1478s,平均每個測站計算時間為6.6s。
具體參數設置的配置文件如下圖所示:
筆者將相同曆元,所有測站的結果取平方平均(Quadratic mean),得到了如下圖所示的位置收斂圖。以連續10個曆元優於1dm作為判斷收斂的條件,E、N、U三個分量收斂時間分別為33.5、16.5、44.5分鐘。
認為各個測站2h以後已經充分收斂。將所有測站2h往後的,共約595000個曆元的E、N、U分量的定位誤差序列進行匯總,繪製分布直方圖如下:
可以看出,基於原始代碼的 rnx2rtkp.exe, RTKLIB 動態PPP 的收斂時間約為40分鐘,三個分量定位精度約為3.0cm, 2.1cm和4.6cm。
筆者也按上面兩個小節 「疑似bugs」 和 「優化tips」 中給出的建議對rnx2rtkp做了優化工作,在相同的數據集上,大致按同樣的參數設置重新解算了一次。總共計算時間為1259s, 平均每個數據運行時間減少了1s左右(上述tips有的能減少運算時間,有的會增加時間)。同樣對收斂時間和E、N、U三分量定位誤差進行統計。其結果如下兩幅圖所示。
修改後RTKLIB 動態PPP 的三個分量收斂時間為30.5、18.5和33.0分鐘,三個分量定位精度約為2.1cm, 1.6cm和3.8cm。對比修改前後的結果,表明上文中的修改建議可以有效改善RTKLIB的動態PPP解算質量。
相信還有更多聰明、勤奮的GNSSer們,找出了更多的bugs,和優化的tips。歡迎在後臺留言與我們分享。
20個問與答這一小節收集、匯總了筆者在線上、線下和各位師兄弟姐妹經常討論的問題。
關於作者
問1:RTKLIB是Takasu一個人寫的還是一個團隊寫的?
>>> 是作者高須一個人寫的,所以更能保持代碼風格的統一。據了解高須在進入東京海洋科技大學工作前,曾經在GNSS軟體公司呆過十年以上時間,做相關算法開發工作,所以具有很強、很專業的寫代碼的能力。
問2:Takasu當初是什麼初心讓他寫了並開源了這麼一套RTKLIB?感覺工作量太大。
>>> 日本在不少觀念和習慣方面和歐美比較接近,不少軟體開發者接受「開源」的理念。這在日本可能是一件比較平常的事情。筆者周圍的人沒有聽高須談過為何開源的問題。僅從筆者的角度,推測高須開源的動機有:(1)開放的系統更有生命力,能夠被更多的人使用,和外部產生更多的連接。封閉的系統如果用的人還少,很容易走向滅亡。(2)持續的改進。開原始碼人人都可以公開訪問,集合眾人的力量更容易發現程序原始碼中的錯誤。軟體開發者可以匯總反饋幫助持續改善軟體。(3)個人宣傳。好的開原始碼是作者的一張名片。有時比別人的介紹和自己的簡歷更加管用。
關於入門
問3:關於結構體的定義以及代碼整體框架的設計,是先構思好然後再去完善的嗎?我們平時寫代碼的時候,總是想到哪寫到哪,需要再加個小功能時就得大改。
>>> 數據的組織和結構設計是程序開發一項重要的基本功。好的設計會使程序的執行過程更為流暢,函數的交互更為簡潔和清晰。要鍛鍊這方面的能力,筆者的建議就是三多——多讀優秀的源碼,多總結經驗,和多編程實踐。
問4:怎麼學習 RTKLIB 更高效?怎麼基於 RTKLIB 二次開發?如何快速上手RTKLIB?
>>> 依筆者愚見,學習RTKLIB的第一手資料是隨源碼提供的manual手冊,和Windows下的帶界面的可執行程序。了解基本原理後,通過親自實踐,一步一步修改、調整、熟悉參數設置,使用rtkplot工具對結果進行分析,找出影響解算質量的因素。這一步的目的是增加對軟體的熟悉度和形成對算法的初步理解。
接下來了解RTKLIB已支持的模型和算法,匯總還沒支持的通用的,和新提出的模型、算法,根據自己的研究方向開始修改源碼,輸出自己需要的結果,增加自己所需的功能。
再然後就是一個不斷循環的迭代過程了——多做數據處理與分析,多寫代碼實踐,多閱讀文獻和與人交流。
問5:對於初學者來說,學習RTKLIB應避免哪些主要問題?
>>> 筆者觀察到周圍師弟師妹有一個小誤區——大家會在定位上花費過多的精力。這可能是由於RTKLIB主要關注的是位置估計,對用戶展示的也主要是位置信息。而且關於GNSS大家首先想到的就是位置服務,覺得這一塊最有應用價值。但其實做定位的人最多,競爭壓力也最大,且這一塊相對較為成熟,單純做衛星精密定位也難有突破。
因此,學生在使用RTKLIB時應聚焦在自己的研究方向上。如關注對流層的,可以多輸出一些投影函數、zhd、zwd的信息,加入新的GPT2模型,VMF投影函數模型等,結合特殊天氣事件做對流層的精細處理與應用等等,做更深入的研究。在這些研究中,定位可以作為一個基本的檢驗模型和算法是否可靠的手段,能達到當前主流的解算質量就行。並不需要算到比做定位的人更好的地步。
關於圖形顯示
問6.1:想利用lib畫星下點軌跡該用到哪些函數?
問6.2:rtkplot繪製保存的天空圖像素較低,怎麼樣畫高像素圖?能否輸出需要的圖片格式?
>>> LIB不支持繪製星下點軌跡,需要大家自己開發相應功能。
rtkplot有c++ builder和QT兩個不同的項目工程,分別使用內置的 TJPEGImage類和QPixmap類,做圖片的顯示、存儲等工作,沒有提供更多的解析度調節和格式轉換等選項。所以適合於簡單的數據分析,不適合於專業的結果展示。
筆者建議使用RTKLIB生成相關數據,用其他成熟的繪圖工具、腳本如Matlab,Python的Matplotlib模塊等,按個人需要設置不同圖片格式,大小和解析度等,實現更為專業的繪圖功能。對Python畫圖感興趣的同學可以閱讀歷史文章——「我用Python之科學繪圖17問」。
關於支持的系統和解算模式
問7:是否支持GRCE獨立進行PPP?是否支持網解,精密衛星鐘差估計和定軌計算?
>>> RTKLIB針對的是用戶端的數據處理,支持GREC單系統PPP。不支持後面三種處理模式。
問8:是否支持PPP模糊度固定?
>>> 2.4.1及之前的版本不支持PPP-AR,2.4.3 b9及之後的版本有pppar.c文件,不過裡面的函數只有一個return語句。這中間的版本,2.4.2和2.4.3 b1-8 版本中給出了pppar.c文件,實現了基本的PPP-AR算法,支持使用GRG整數衛星鐘差的PPP模糊度固定解。
問9:模糊度固定是使用什麼方法實現的?
>>> LIB支持最經典的Lambda方法,不支持取整、Bootstapping、TCAR等模糊度固定方法。
關於解算精度
問10:長、中、短基線相對定位的效果咋樣?
>>> LIB具備長、中、短基線相對定位功能,支持設置不同的對流層、電離層處理模式,和其他處理策略。中短基線模型較為簡單,LIB的定位性能較好。長基線需要對大氣延遲、周跳等進行更為精細的處理,LIB的效果還有待改進,尤其是長基線動態定位。
問11.1:RTKLIB定位精度和穩定性怎麼樣?
問11.2:RTKLIB的PPP算法可信度是否很高,相對於其他GNSS開源軟體有何優勢與劣勢?
>>> 對可視衛星多,質量較好的數據處理效果不錯。對部分質量較差、電離層很活躍的一些數據,定位結果會差一些。
在GNSS開源軟體中,RTKLIB的優勢在於:高穩健性、代碼可讀性高、容易擴展,解算質量也是屬於最好的之一。劣勢在於:有的函數嵌套比較深;2.4.2版本以後更新太慢;具體算法方面,周跳探測算法略顯簡單,殘差編輯比較粗糙等(不過似乎其他GNSS開源軟體做的也很粗略)。
總體來講LIB在開源的GNSS定位程序中其穩健度、解算質量、代碼可擴展性是屬於最好的之一。與成熟的商用軟體如 IE 等相比還有一些(較大的)差距,有進一步完善的空間。
軟體在數據預處理、鍾跳探測與修復、周跳探測、質量控制(驗前驗後殘差控制、raim多粗差檢測)、部分模糊度固定、模糊度檢驗、中長基線TCAR算法等等方面還可以進一步完善。
關於代碼/算法優化
問12:想處理北鬥數據,還需要對代碼做哪些優化?
>>> RTKLIB代碼裡固定死了各系統觀測值的權比,需要改進。BDS不區分衛星,認為GEO、IGSO和MEO觀測值精度一致,是一個不太合理的地方。對BDS-2系統偽距觀測值,需要改正衛星端偽距多路徑。
問13:RTKLIB數據預處理做的怎麼樣?是否需要進一步優化?
>>> LIB使用TurboEdit算法做周跳探測,MW閾值固定,GF閾值可設置,默認值為0.05m,對於中低緯度電離層較為活躍地區的測站偏嚴格。對多數可視衛星多,質量較好的數據效果不錯。對部分質量較差、電離層很活躍的一些數據,其數據預處理有進一步優化的空間。
問14:哪些模塊比較影響計算效率,可以如何提高?
>>> 部分優化策略參考「優化tips」小節。除非是為了調試,應該關閉非常耗時的「Output Solution Status / Output Debug Trace」結果輸出。此外,批處理模式下,只讀一次精密軌道、鐘差,antex,DCB文件,能節約不少時間。
關於PPP-AR
問15.1:MW組合需不需要進行偽距差分碼偏差(DCB)改正?據我了解RTKLIB未進行改正,GAMP在輸出寬巷模糊度的時候進行了改正。
問15.2:在固定寬巷模糊度的時候,這裡的小數偏差是否可以直接使用武漢大學或者CNES發布的寬巷FCB?
>>> 可以直接使用這兩個機構的寬巷FCB用於固定寬巷模糊度。
DCB改正模型得和寬巷FCB生成的模型保持一致。筆者所知,目前可用的寬巷FCB產品都做了P1C1 DCB改正。GRG整數鐘差,武漢大學測繪學院SGG 的FCB產品都沒有對MW組合做P1P2 DCB改正。需要說明的是,在P1,P2觀測值上(按係數)改與不改P1P2 DCB改正,都不影響形成的無電離層組合偽距觀測值(兩個偽距上的P1P2 DCB改正會相互抵消)。
不同機構使用的數學模型裡面,模糊度、FCB的符號會有所不同。使得最後生成的寬巷FCB符號不同。使用時需要具體測試是應該加還是減去改正數。
其他
問16:如何將編寫linux下的可執行模塊?
>>> src文件夾下的代碼支持跨平臺。app文件夾下的工程qt工程也可以在win和linux系統下使用qtcreator編譯生成不同系統的可執行程序。CUI工程如rnx2rtkp也提供了gcc的makefile文件,可生成linux系統下可執行程序。
問17:可否用Python編譯調用RTKLIB模塊?
>>> RTKLIB的主要功能都有對應的CUI程序,接受用戶從命令行和配置文件輸入參數,可以被諸如Python之類的腳本調用。在上面的「簡單測試」小結中,筆者就是用Python調用rnx2rtkp.exe。
問18:定位結果不佳除了DOP值,該從哪幾個方面作為切入口快速查找原因?
>>> 驗後殘差是做質量控制的重要檢驗量。也可以用rtkplot查看該時刻觀測衛星數,周跳衛星數等信息。
問19:RTKLIB以後會不會融合慣性數據處理,並對外開放?
>>> 作者在2.4.3的一個beta版本中增加了ins結構體定義,和幾個函數的申明,並未給出具體實現。未來不確定是否會增加支持處理慣導數據。
問20:它有哪些純粹靠經驗設置的地方?
>>> 代碼中固定使用的經驗性的設置有:系統間權比、MW組合探測閾值、對流層模型的先驗方差、驗後殘差檢驗閾值等等。
寫在最後本期關於RTKLIB 開原始碼的總結筆記就到這裡了。如果覺得有用,歡迎轉發、推薦給有需要的同學朋友們。有更多bugs發現和優化tips,也歡迎在後臺留言與我分享。
公眾號後臺寫下你感興趣的 GNSS數據處理、攝影測量、計算機視覺等 方向的開源軟體名,筆者(我不是一個人:-))將搜集和統計,或許會成為下一期『源碼閱讀記』學習的對象。
寫到這裡還想和大家談一談的是,幾位筆者開設「源碼閱讀記」的初衷,是為了敦促自己多多閱讀行業內的開源軟體,開闊眼界,向優秀的人們學習,同時分享自己的一些小經驗、小心得,和大家交流探討,共同進步。由於我們的能力有限,時間也不充裕,對一些感興趣的代碼的研讀計劃還難以啟動,比如有名的,西北工業大學嚴恭敏老師的 捷聯慣導仿真軟體 PSINS。所以也希望有分享精神的讀者共同參與到源碼學習中來,不吝賜稿,分享你的學習經驗。
最後祝大家學業有成!事業順利!
[1]: Fei Guo, Xiaohong Zhang (2014) Real-time clock jump compensation for precise point positioning. GPS Solutions, 18, 1: 41-50
[長按圖片識別二維碼,即可快速關注]