RTKLIB读取星历文件,观测数据
笔者尝试在RTKLIB的基础上进行各种功能的测试,首先想通过利用RTKLIB,读取广播星历文件,在利用星历解析函数计算出星历文件中卫星的位置信息等等。但过程及其曲折,问题频出。考虑了文件本身原因,程序问题。后来分开单独测试,通过内部手动设置模拟导航数据测试eph2pos函数,发现是可以成功的。然后单独测试文件读取,就一直读取失败。
检测发现文件时能读到的,但有时候是直接读不出来;或者是读取后发现读了一点就卡死了。最后偶然发现是文件路径包含中文。
✅ 问题核心:为什么中文路径导致 readrnx()
读取失败?
这是因为 RTKLIB(尤其是 demo5 分支中的原生实现)使用的是标准 C 函数来处理文件路径,比如:
FILE *fp = fopen(filepath, "r");
这些函数默认使用 ANSI(GBK)编码读取路径,而不是 UTF-8 或 Unicode。
💥 所以当路径中含有中文字符(如“桌面”)时,会导致:
fopen()
打开失败;readrnx()
返回失败(-1);报错:"读取观测文件失败"。
✅ 解决方法:
你已经找到了最直接的方案:
✅ 把路径改成全英文目录路径,例如:
D:\RTKLIB_TEST\xxx.obs
也可以选用以下方案之一(进阶):
使用 VS 工程中设置为 UTF-8 编译,并使用
_wfopen
打开 Unicode 路径(需修改 RTKLIB 源码);把数据放在全英文目录路径下再运行;
避免在中文用户名、桌面路径下运行 RTKLIB 程序。
🧪 2. 尝试用 satid()
打印卫星编号失败
原代码使用了
satid(sat)
,但satid()
并不是 RTKLIB 正式暴露的函数(或未包含头文件);报错为 “implicit declaration of function 'satid'”;
改用
satsys()
成功获取了卫星系统和 PRN。
✅ 3. 成功读取数据,打印前5个历元信息
int stat = readrnx(rnx_file, 1, "", &obs, &nav, &sta);
使用 VS 工程中设置为 UTF-8 编译,并使用
_wfopen
打开 Unicode 路径(需修改 RTKLIB 源码);把数据放在全英文目录路径下再运行;
避免在中文用户名、桌面路径下运行 RTKLIB 程序。
🧪 1. 初次尝试读取观测文件失败
int stat = readrnx(rnx_file, 1, "", &obs, &nav, &sta);
观测文件路径含中文,如:
D:\Users\Wang\桌面\RTKLIB\...
报错信息为:“读取观测文件失败!”
实际是
fopen()
无法识别中文路径。原代码使用了
satid(sat)
,但satid()
并不是 RTKLIB 正式暴露的函数(或未包含头文件);报错为 “implicit declaration of function 'satid'”;
改用
satsys()
成功获取了卫星系统和 PRN。成功输出如下:
📌 代码模板(可收藏复用)读取成功,观测历元总数:948
历元 1 时间:2005/04/02 00:00:00.000 卫星:G03
频点1: P = 24767686.375
频点2: P = 24767684.822
...#include <stdio.h> #include "rtklib.h"int main(void) {obs_t obs = {0};nav_t nav = {0};sta_t sta = {0};const char *rnx_file = "d:\\RTKLIB_TEST\\yourfile.obs"; // 英文路径int stat = readrnx(rnx_file, 1, "", &obs, &nav, &sta);if (stat <= 0) {printf("读取观测文件失败!请检查路径或文件格式\n");return -1;}printf("读取成功,观测历元总数:%d\n", obs.n);for (int i = 0; i < obs.n && i < 5; i++) {gtime_t t = obs.data[i].time;double ep[6];time2epoch(t, ep);int prn;int sys = satsys(obs.data[i].sat, &prn);const char *sys_id = sys == SYS_GPS ? "G" :sys == SYS_GLO ? "R" :sys == SYS_GAL ? "E" :sys == SYS_QZS ? "J" :sys == SYS_CMP ? "C" : "?";printf("历元 %d 时间:%04.0f/%02.0f/%02.0f %02.0f:%02.0f:%06.3f 卫星:%s%02d\n",i + 1, ep[0], ep[1], ep[2], ep[3], ep[4], ep[5], sys_id, prn);for (int j = 0; j < NFREQ && j < 3; j++) {if (obs.data[i].P[j] != 0.0)printf(" 频点%d: P = %.3f\n", j + 1, obs.data[i].P[j]);}}free(obs.data);free(nav.eph);free(nav.geph);return 0; }