本文是 RTKLlib詳解 系列文章的一篇,目前該系列文章還在持續總結寫作中,以發表的如下,有興趣的可以翻閱。
[學習] RTKlib詳解:功能、工具與源碼結構解析
[學習]RTKLib詳解:pntpos.c與postpos.c
[學習]RTKLib詳解:rtkcmn.c與rtkpos.c
[學習]RTKLib詳解:ppp.c與ppp_ar.c
[學習]RTKLib詳解:ephemeris.c與rinex.c
文章目錄
- Part A: convkml.c 文件解析
- 一、文件整體說明
- 二、執行流程與函數調用關系
- 三、主要函數說明
- 3.1 `main`
- 3.2 `readcmdline`
- 3.3 `readobsfile`
- 3.4 `convkml`
- 3.5 `writekmlhead`
- 3.6 `writekmlbody`
- 3.7 `writekmltail`
- 四、關鍵算法數學原理與推導
- 地理坐標系到 ECEF 的轉換
- Part B: convrnx.c 文件解析
- 一、文件整體說明
- 二、執行流程與函數調用關系
- 三、主要函數說明
- 3.1 `main`
- 3.2 `readcmdline`
- 3.3 `initrnx`
- 3.4 `openfiles`
- 3.5 `convertrnx`
- 3.6 `readrawdata`
- 3.7 `outputrnx`
- 3.8 `closefiles`
- 四、關鍵算法數學原理與推導
- 時間系統轉換
- Part C: geoid.c 文件解析
- 一、文件整體說明
- 二、執行流程與函數調用關系
- 三、主要函數說明
- 3.1 `geoid_hgt`
- 3.2 `load_geoid`
- 3.3 `interp_geoid`
- 3.4 `bilin_interp`
- 四、關鍵算法數學原理與推導
- 雙線性插值
Part A: convkml.c 文件解析
一、文件整體說明
convkml.c
是 RTKLIB 中用于將 GNSS 數據轉換為 KML(Keyhole Markup Language)格式的工具,便于在 Google Earth 等地理可視化軟件中展示軌跡、觀測點等信息。該文件主要實現了從 RINEX 或 RTKLIB 內部數據結構到 KML 標記語言的轉換。
主要功能:
- 將 GNSS 觀測數據轉換為 KML 格式。
- 支持多種顯示樣式,如路徑、標記點、高度剖面圖等。
- 可選輸出模式包括靜態點、動態路徑等。
主要特色:
- 支持多頻段和多系統數據。
- 提供靈活的樣式配置選項。
- 可導出不同時間分辨率的數據點。
二、執行流程與函數調用關系
程序執行流程如下:
- 初始化參數設置。
- 讀取輸入數據(如 RINEX 文件)。
- 處理數據并提取位置信息。
- 生成 KML 文件內容。
- 寫入 KML 文件并關閉資源。
函數調用關系如下所示:
其中:
readcmdline
: 解析命令行參數。initopt
: 初始化輸出選項。readobsfile
: 讀取觀測文件(RINEX等)。convkml
: 主要轉換邏輯入口。writekml*
函數負責生成 KML 的各個部分。
三、主要函數說明
3.1 main
int main(int argc, char *argv[])
功能:
主函數,負責接收命令行參數并調度各模塊完成 KML 轉換。
輸入參數:
argc
: 命令行參數個數。argv[]
: 命令行參數數組。
輸出參數:
- 返回狀態碼(0 表示成功,非零表示錯誤)。
3.2 readcmdline
void readcmdline(int argc, char *argv[], opt_t *opt)
功能:
解析命令行參數并填充配置結構體 opt
。
輸入參數:
argc
,argv[]
: 命令行參數。opt
: 輸出參數,包含所有配置選項。
3.3 readobsfile
int readobsfile(const char *file, obs_t *obs, nav_t *nav, opt_t *opt)
功能:
讀取觀測文件(如 RINEX),并將數據存儲到 obs
和 nav
結構體中。
輸入參數:
file
: 輸入文件路徑。obs
: 存儲觀測數據的結構體指針。nav
: 存儲導航數據的結構體指針。opt
: 配置選項。
返回值:
- 成功返回 1,失敗返回 0。
3.4 convkml
int convkml(FILE *fp, const obs_t *obs, const nav_t *nav, const opt_t *opt)
功能:
核心轉換函數,將 GNSS 數據轉換為 KML 格式并寫入文件。
輸入參數:
fp
: 文件指針。obs
,nav
,opt
: 輸入數據與配置。
返回值:
- 成功返回 1,失敗返回 0。
3.5 writekmlhead
void writekmlhead(FILE *fp, const opt_t *opt)
功能:
寫入 KML 文件頭部信息,包括文檔聲明、命名空間等。
輸入參數:
fp
: 文件指針。opt
: 配置信息。
3.6 writekmlbody
void writekmlbody(FILE *fp, const obs_t *obs, const nav_t *nav, const opt_t *opt)
功能:
寫入 KML 主體內容,包括路徑、標記點等。
輸入參數:
fp
,obs
,nav
,opt
: 同上。
3.7 writekmltail
void writekmltail(FILE *fp)
功能:
寫入 KML 文件尾部標簽,結束文檔。
輸入參數:
fp
: 文件指針。
四、關鍵算法數學原理與推導
地理坐標系到 ECEF 的轉換
GNSS 接收機通常輸出經緯度和高度(LLH),但 KML 使用的是地心坐標系(ECEF)。因此需要進行 LLH 到 ECEF 的轉換。
公式如下:
N = a 1 ? e 2 sin ? 2 ( ? ) x = ( N + h ) cos ? ( ? ) cos ? ( λ ) y = ( N + h ) cos ? ( ? ) sin ? ( λ ) z = [ N ( 1 ? e 2 ) + h ] sin ? ( ? ) \begin{aligned} &N = \frac{a}{\sqrt{1 - e^2 \sin^2(\phi)}} \\ &x = (N + h)\cos(\phi)\cos(\lambda) \\ &y = (N + h)\cos(\phi)\sin(\lambda) \\ &z = \left[N(1 - e^2) + h\right]\sin(\phi) \end{aligned} ?N=1?e2sin2(?)?a?x=(N+h)cos(?)cos(λ)y=(N+h)cos(?)sin(λ)z=[N(1?e2)+h]sin(?)?
其中:
- ? \phi ?: 緯度(弧度)
- λ \lambda λ: 經度(弧度)
- h h h: 橢球高
- a a a: WGS84 長半軸
- e 2 = 1 ? b 2 a 2 e^2 = 1 - \frac{b^2}{a^2} e2=1?a2b2?: 第一偏心率平方
這個轉換是繪制軌跡的基礎。
Part B: convrnx.c 文件解析
一、文件整體說明
convrnx.c
是 RTKLIB 中用于將各種原始觀測數據(如 BINEX、UBX、RTCM 等)轉換為 RINEX 格式的工具。RINEX 是 GNSS 數據的標準格式,廣泛用于后處理和分析。
主要功能:
- 多種原始數據格式轉 RINEX。
- 支持多頻段、多系統。
- 自動識別輸入數據格式。
主要特色:
- 支持自動探測輸入數據類型。
- 提供靈活的時間過濾與輸出選項。
- 可以輸出壓縮的 RINEX(.crx/.gz)。
二、執行流程與函數調用關系
程序執行流程如下:
- 解析命令行參數。
- 打開輸入/輸出文件。
- 讀取并解析原始數據流。
- 轉換為 RINEX 格式并寫入文件。
- 清理資源并退出。
函數調用關系如下:
三、主要函數說明
3.1 main
int main(int argc, char *argv[])
功能:
主函數,解析命令行參數并控制整個轉換流程。
輸入輸出:
- 同前文。
3.2 readcmdline
void readcmdline(int argc, char *argv[], rnxopt_t *opt)
功能:
解析命令行參數并填充 rnxopt_t
結構體。
輸入輸出:
- 同前文。
3.3 initrnx
int initrnx(rnxopt_t *opt)
功能:
根據用戶配置初始化 RINEX 轉換參數。
輸入參數:
opt
: 轉換配置結構體。
3.4 openfiles
int openfiles(const char *infile, const char *outfile, FILE **fpin, FILE **fpout, rnxopt_t *opt)
功能:
打開輸入和輸出文件,支持壓縮格式。
輸入參數:
infile
,outfile
: 文件路徑。fpin
,fpout
: 文件指針地址。opt
: 配置。
3.5 convertrnx
int convertrnx(FILE *fpin, FILE *fpout, rnxopt_t *opt)
功能:
主轉換循環,讀取原始數據并寫入 RINEX。
輸入輸出:
- 同上。
3.6 readrawdata
int readrawdata(FILE *fp, unsigned char *buff, int nmax, int format, raw_t *raw)
功能:
讀取原始觀測數據并解析為內部結構。
輸入參數:
fp
: 輸入文件指針。buff
: 緩沖區。nmax
: 最大讀取長度。format
: 數據格式(如 RTCM3, UBX 等)。raw
: 輸出解析后的數據。
返回值:
- 成功返回字節數,失敗返回負值。
3.7 outputrnx
int outputrnx(FILE *fp, const raw_t *raw, const rnxopt_t *opt)
功能:
將解析后的數據按 RINEX 格式寫入輸出文件。
輸入參數:
fp
,raw
,opt
: 同上。
3.8 closefiles
void closefiles(FILE *fpin, FILE *fpout)
功能:
關閉輸入輸出文件句柄。
四、關鍵算法數學原理與推導
時間系統轉換
原始數據中的時間戳可能使用 GPS 時間、UTC、本地時間等,而 RINEX 要求使用 GPS 時間或 UTC。因此需要進行時間系統轉換。
GPS 時間與 UTC 的關系為:
t G P S = t U T C + Δ t l e a p t_{GPS} = t_{UTC} + \Delta t_{leap} tGPS?=tUTC?+Δtleap?
其中 Δ t l e a p \Delta t_{leap} Δtleap? 是閏秒修正值,需通過星歷或頭文件獲取。
Part C: geoid.c 文件解析
一、文件整體說明
geoid.c
實現了大地高與正常高的相互轉換,依賴于大地水準面模型(如 EGM96、EGM2008)。它提供了基于插值方法的大地高與正高之間的轉換功能。
主要功能:
- 計算某一點的大地水準面高(N)。
- 支持多種大地水準面模型。
- 提供雙線性插值功能。
主要特色:
- 支持網格化模型數據。
- 可擴展性強,易于添加新模型。
- 高效的插值算法。
二、執行流程與函數調用關系
程序執行流程如下:
- 加載大地水準面模型文件。
- 對給定的地理坐標進行插值計算。
- 輸出大地水準面高。
函數調用關系如下:
三、主要函數說明
3.1 geoid_hgt
double geoid_hgt(double lat, double lon, const char *model)
功能:
對外接口,輸入經緯度和模型名,返回大地水準面高。
輸入參數:
lat
,lon
: 地理緯度和經度(十進制度)。model
: 模型名稱(如 “egm96_15”)。
返回值:
- 大地水準面高 N(米)。
3.2 load_geoid
int load_geoid(const char *model, geoid_t *geoid)
功能:
加載指定模型的網格數據到內存。
輸入參數:
model
: 模型名。geoid
: 存儲模型數據的結構體。
返回值:
- 成功返回 1,失敗返回 0。
3.3 interp_geoid
double interp_geoid(double lat, double lon, const geoid_t *geoid)
功能:
調用雙線性插值函數計算某點的大地水準面高。
輸入參數:
lat
,lon
: 插值點坐標。geoid
: 模型數據結構體。
返回值:
- 插值結果(米)。
3.4 bilin_interp
double bilin_interp(double x, double y, double *v, int nx, int ny)
功能:
實現雙線性插值算法。
輸入參數:
x
,y
: 插值點坐標。v
: 網格數據數組。nx
,ny
: 網格尺寸。
返回值:
- 插值結果。
四、關鍵算法數學原理與推導
雙線性插值
設四個角點分別為:
- f ( x 1 , y 1 ) f(x_1, y_1) f(x1?,y1?)
- f ( x 2 , y 1 ) f(x_2, y_1) f(x2?,y1?)
- f ( x 1 , y 2 ) f(x_1, y_2) f(x1?,y2?)
- f ( x 2 , y 2 ) f(x_2, y_2) f(x2?,y2?)
目標點 ( x , y ) (x, y) (x,y) 在矩形區域內,則插值公式為:
f ( x , y ) = ( x 2 ? x ) ( y 2 ? y ) Δ x Δ y f ( x 1 , y 1 ) + ( x ? x 1 ) ( y 2 ? y ) Δ x Δ y f ( x 2 , y 1 ) + ( x 2 ? x ) ( y ? y 1 ) Δ x Δ y f ( x 1 , y 2 ) + ( x ? x 1 ) ( y ? y 1 ) Δ x Δ y f ( x 2 , y 2 ) f(x,y) = \frac{(x_2 - x)(y_2 - y)}{\Delta x \Delta y} f(x_1,y_1) + \frac{(x - x_1)(y_2 - y)}{\Delta x \Delta y} f(x_2,y_1) + \frac{(x_2 - x)(y - y_1)}{\Delta x \Delta y} f(x_1,y_2) + \frac{(x - x_1)(y - y_1)}{\Delta x \Delta y} f(x_2,y_2) f(x,y)=ΔxΔy(x2??x)(y2??y)?f(x1?,y1?)+ΔxΔy(x?x1?)(y2??y)?f(x2?,y1?)+ΔxΔy(x2??x)(y?y1?)?f(x1?,y2?)+ΔxΔy(x?x1?)(y?y1?)?f(x2?,y2?)
其中 Δ x = x 2 ? x 1 \Delta x = x_2 - x_1 Δx=x2??x1?, Δ y = y 2 ? y 1 \Delta y = y_2 - y_1 Δy=y2??y1?。
此方法用于大地水準面模型的離散數據插值。
研究學習不易,點贊易。
工作生活不易,收藏易,點收藏不迷茫 :)