目录
readrnxobsb()函数
readrnxobs()函数
decode_eph()函数
(1)satid2no函数
(2)str2time函数
(3) str2num函数
add_eph(),add_geph(),add_seph()函数
readrnxfp()函数
init_rnxctr()函数
free_rnxctr()函数
open_rnxctr()函数
input_rnxctr()函数
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);
首先,按照上面的方式建立索引。将三维观测值类型数组退化成二维数组,建立一个索引数组。然后剩下的所有代码就是读取这个历元中的数据了。在读取的过程中,读取历元头,然后读取观测数据。
步骤:
1、先利用fgets()函数缓存一行数据。
2、判断本行是否是历元数据第一行,如果是,则调用decode_obsepoch()函数解码首行数据(包括历元时刻、卫星数、卫星编号、历元状态等信息),并将信息保存;如果不是则调用decode_obsdata()函数对该行观测数据进行数据解码,具体为调用str2num函数,从指定位置一次读取16个字符(每一个卫星的观测数据),并转换为double类型,存入数组。函数声明如下:
double str2num(const char s, int i, int n);
即从i处开始读取,读取n个字符,转换为double类型,存入字符数组中,并用指针s指向数组地址。
3、最后将时间转换为gps时保存,周跳信息保存。O文件读取完毕。
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函数,直到所有的观测值全被读完,或者是出现了某个历元没有卫星的情况为止。
注意:在观测值文件中,所记录的载波相位数据的单位为周,伪距数据的单位为m。观测值所对应的时标(即观测时刻)是依据接收机钟的读数所生成的,而不是标准的GPS时,因而在该时标中含有接收机的钟差。
static int decode_eph(double ver, int sat, gtime_t toc, const double *data,eph_t *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 readrnxnavb(FILE *fp, const char *opt, double ver, int sys,
int *type, eph_t *eph, geph_t *geph, seph_t *seph)
先说明一下用到的几个子函数
(1)satid2no函数
之前已经说过了,就是将卫星的id号转换为唯一的一个整数类型号码,作为卫星的唯一标识
(2)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类型的结构体输出
(3) str2num函数
这个函数之前也说过,之所以把它单独列出来就是因为这个函数比较重要,建议记住。
主函数实际上用一次就读取一个卫星的星历,是利用i来控制是否读完了一个历元的数据。设计的思想很巧妙,由于GLONASS和GALILEO的卫星星历比较特殊,所以要控制单独判断。这个函数就是先读取卫星星历数据到data中,然后再对data进行解码。
add_eph(),add_geph(),add_seph()函数
函数功能:前面添加观测值的函数类似,都是判断结构体的大小是否够用,然后将新一个卫星的星历添加到原有的观测值结构体中。
static int readrnxnav(FILE *fp, const char *opt, double ver, int sys,nav_t *nav)
函数功能:就是将之前所有的读取星历文件的函数整理一下,根据文件头的标识符判断文件是哪一种卫星系统的星历文件,利用相应的函数读取并添加星历。但是一定要注意,这个函数并非是读取整个星历文件,它只能读取星历文件的数据记录,不能读取文件头,读取文件头的函数在之前已经介绍过了
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文件等等的一系列文件,也就是之前函数的整合 ;这个函数就是增加了一个解压的功能,然后再进行读取
extern int init_rnxctr(rnxctr_t *rnx)
有参数的先看参数的意义,然后再看有没有子函数,最后看函数本体。出现了一个以前没有见过的结构体。
typedef struct { /* rinex control struct type */
gtime_t time; /* message time */
double ver; /* rinex version */
char type; /* rinex file type ('O','N',...) */
int sys; /* navigation system */
int tsys; /* time system */
char tobs[6][MAXOBSTYPE][4]; /* rinex obs types */
obs_t obs; /* observation data */
nav_t nav; /* navigation data */
sta_t sta; /* station info */
int ephsat; /* ephemeris satellite number */
char opt[256]; /* rinex dependent options */
} rnxctr_t;
观察结构体定义可以看出,这个结构体就是将之前的导航电文结构体和观测值结构体进行了组合,从而形成了一个能够概括所有RINEX格式文件的结构体。
函数功能:发现函数其实就是将上述的结构体进行初始化,即将指针指向新开辟的内存空间,将其中的各个参数置零 。
extern void free_rnxctr(rnxctr_t *rnx)
{
trace(3,"free_rnxctr:\n");
free(rnx->obs.data); rnx->obs.data=NULL; rnx->obs.n =0;
free(rnx->nav.eph ); rnx->nav.eph =NULL; rnx->nav.n =0;
free(rnx->nav.geph); rnx->nav.geph=NULL; rnx->nav.ng=0;
free(rnx->nav.seph); rnx->nav.seph=NULL; rnx->nav.ns=0;
}
理解:使用完指针和新开辟的内存之后,应该先释放内存,也就是进行free操作,然后将指针指向NULL。这样应该可以避免很多内存泄漏的问题。
extern int open_rnxctr(rnxctr_t *rnx, FILE *fp)
函数功能:它是将RINEX文件头中的信息读入rnx参数中。注意,只是文件头的信息。
extern int input_rnxctr(rnxctr_t *rnx, FILE *fp)
函数功能:这个函数是用来将RINEX文件体的信息读入rnx中。从下面的函数体中可以看出,rnx的类型是已知的,那么我们可以推测在调用这个函数的时候应该先调用open_rnxctr函数,解析头文件,然后再使用这个函数。
后面的内容不再仔细介绍,主要是输出函数:
/*------------------------------------------------------------------------------
* output rinex functions
*-----------------------------------------------------------------------------*/