学习rtklib(四)

有了之前的函数做铺垫,接下来的代码就好读多了。其实rtklib的代码构成和我们平时写程序的代码构成是一致的,先是写出一个一个最底层的函数,然后再写出中层的函数,最后利用高层的函数将这些函数一个一个组建起来。就像搭积木一样,先造积木块,然后搭房子,最后组成社区。(hiahiahiahia,强行比喻( ̄▽ ̄)/)

1.readrnxobsb函数

static int readrnxobsb(FILE *fp, const char *opt, double ver, char tobs[][MAXOBSTYPE][4], int *flag, obsd_t *data)

这个函数就是读取o文件中的观测值记录(除了文件头剩下的部分)的函数了。严格地说,这个函数只是读取一个观测历元的观测数据。

/* set signal index */
    set_index(ver,SYS_GPS,opt,tobs[0],index  );
    set_index(ver,SYS_GLO,opt,tobs[1],index+1);
    set_index(ver,SYS_GAL,opt,tobs[2],index+2);
    set_index(ver,SYS_QZS,opt,tobs[3],index+3);
    set_index(ver,SYS_SBS,opt,tobs[4],index+4);
    set_index(ver,SYS_CMP,opt,tobs[5],index+5);

首先,按照上面的方式建立索引。将三维观测值类型数组退化成二维数组,建立一个索引数组。
然后剩下的所有代码就是读取这个历元中的数据了。
在读取的过程中,读取历元头,然后读取观测数据。答题思路就是这样的,代码也简洁易懂,没什么坑。

2.readrnxobs函数

static int readrnxobs(FILE *fp, gtime_t ts, gtime_t te, double tint,
                      const char *opt, int rcv, double ver, int tsys,
                      char tobs[][MAXOBSTYPE][4], obs_t *obs)

这个函数就是读取o文件中整个观测值数据了,也就是除了文件头之外的所有部分。readrnxobsb函数只读取一个历元的观测值,因此在readrnxobs函数中,添加了内存分配语句之后,便是重复调用readrnxobsb函数,直到所有的观测值全被读完,或者是出现了某个历元没有卫星的情况为止。

3.decode_eph函数

在rtklib.h文件中定义的关于卫星星历的结构体eph_t。

typedef struct {        /* GPS/QZS/GAL broadcast ephemeris type */
    int sat;            /* satellite number */
    int iode,iodc;      /* IODE,IODC */
    int sva;            /* SV accuracy (URA index) */
    int svh;            /* SV health (0:ok) */
    int week;           /* GPS/QZS: gps week, GAL: galileo week */
    int code;           /* GPS/QZS: code on L2, GAL/CMP: data sources */
    int flag;           /* GPS/QZS: L2 P data flag, CMP: nav type */
    gtime_t toe,toc,ttr; /* Toe,Toc,T_trans */
                        /* SV orbit parameters */
    double A,e,i0,OMG0,omg,M0,deln,OMGd,idot;
    double crc,crs,cuc,cus,cic,cis;
    double toes;        /* Toe (s) in week */
    double fit;         /* fit interval (h) */
    double f0,f1,f2;    /* SV clock parameters (af0,af1,af2) */
    double tgd[4];      /* group delay parameters */
                        /* GPS/QZS:tgd[0]=TGD */
                        /* GAL    :tgd[0]=BGD E5a/E1,tgd[1]=BGD E5b/E1 */
                        /* CMP    :tgd[0]=BGD1,tgd[1]=BGD2 */
} eph_t;

从结构体的定义可以看出,eph_t中存储了卫星星历中的卫星参数,也就是说把星历按照实际意义存储在了结构体中。

static int decode_eph(double ver, int sat, gtime_t toc, const double *data,
                      eph_t *eph)

从函数原型可以看出,data是没有经过分类的原始卫星数据,没有任何的物理意义,只是单纯的数据。至于它是怎么得到的,下面的函数可以看到。参数eph是将data归类后的结果。函数本身没有什么特别的坑,主要思想就是将星历中相同的参数提取出来,由于各个卫星系统中还有不一样的数据,因此需要利用if语句将每个系统特有的数据提取出来。
下面的两个函数是针对GLONASS系统和GALILEO系统特别的星历归类函数。因此就不特别的进行说明了。

static int decode_geph(double ver, int sat, gtime_t toc, double *data,
                       geph_t *geph);
static int decode_seph(double ver, int sat, gtime_t toc, double *data,
                       seph_t *seph);

4.readrnxnavb函数

首先,还是先说明一下用到的几个子函数。satid2no函数之前已经说过了,就是将卫星的id号转换为唯一的一个整数类型号码,作为卫星的唯一标识。

4.1 str2time函数

还是老样子,这个函数也是定义在rtkcnm.h中的一个函数。函数原型如下

extern int str2time(const char *s, int i, int n, gtime_t *t)
{
    double ep[6];
    char str[256],*p=str;
    
    if (i<0||(int)strlen(s)=0;) *p++=*s++; *p='\0';
    if (sscanf(str,"%lf %lf %lf %lf %lf %lf",ep,ep+1,ep+2,ep+3,ep+4,ep+5)<6)
        return -1;
    if (ep[0]<100.0) ep[0]+=ep[0]<80.0?2000.0:1900.0;
    *t=epoch2time(ep);
    return 0;
}

函数不长,利用了sscanf函数格式化读取字符串中的内容,并且将读取到的数组转化成gtime_t类型的结构体输出。

4.2 str2num函数

这个函数之前也说过,之所以把它单独列出来就是因为这个函数比较重要,建议记住。

里面的子函数清楚了,接下来可以研究主函数了。主函数实际上用一次就读取一个卫星的星历,是利用i来控制是否读完了一个历元的数据。设计的思想很巧妙,由于GLONASS和GALILEO的卫星星历比较特殊,所以要控制单独判断。这个函数就是先读取卫星星历数据到data中,然后再对data进行解码。只要上面的函数清楚了,这个函数就没有什么疑惑的地方了。

5.add_eph,add_geph,add_seph函数

这三个函数其实和前面添加观测值的函数类似,都是判断结构体的大小是否够用,然后将新一个卫星的星历添加到原有的观测值结构体中。

6.readrnxnav函数

static int readrnxnav(FILE *fp, const char *opt, double ver, int sys,
                      nav_t *nav)

这个函数也没有什么好说的,就是将之前所有的读取星历文件的函数整理一下,根据文件头的标识符判断文件是哪一种卫星系统的星历文件,利用相应的函数读取并添加星历。但是一定要注意,这个函数并非是读取整个星历文件,它只能读取星历文件的数据记录,不能读取文件头,读取文件头的函数在之前已经介绍过了。

7.readrnxfp函数

static int readrnxfp(FILE *fp, gtime_t ts, gtime_t te, double tint,
                     const char *opt, int flag, int index, char *type,
                     obs_t *obs, nav_t *nav, sta_t *sta)

这个函数就是真正能够读取真个RINEX文件的函数,它能读取包括o文件,n文件等等的一系列文件,也就是之前函数的整合。没什么好说的。

static int readrnxfile(const char *file, gtime_t ts, gtime_t te, double tint,
                       const char *opt, int flag, int index, char *type,
                       obs_t *obs, nav_t *nav, sta_t *sta)

这个函数就是增加了一个解压的功能,然后再进行读取。
由于我还没有接触RINEX文件中的钟差文件,因此就不进行有关于中读取钟差文件的函数记录了。哎,要去写课程作业了,这个可能要抽空闲时间弄了/(ㄒoㄒ)/~~

你可能感兴趣的:(学习rtklib(四))