RTKLIB读取星历文件,观测数据

发布于:2025-07-22 ⋅ 阅读:(16) ⋅ 点赞:(0)

       笔者尝试在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;
      }
      
      


网站公告

今日签到

点亮在社区的每一天
去签到