rtklib——PPP Learning

目录

前置知识

卫星系统频点解读

一些C语言高级编程

static和const用法

Trace and debug

malloc函数和realloc函数

函数指针(回调函数)

根据条件截取矩阵

单精度float赋值

qosrt函数——快速排序

读取文件的一些函数

fopen和fgets

vfprintf、vprintf、vsprintf

strrchr和strcmp

strstr和strncpy

sscanf和strtok

字符串截取技巧

结构体模块化存储

存储一行多个结构相同的数据类型

 读取sp3-body核心代码

按位与(&)和按位或(|)的应用

uint_8的使用

RTKLIB时间转换工具

epoch2time

RTKLIB矩阵

Question

Kalman filter

openses

杂记备忘




前置知识

卫星系统频点解读

    理解卫星系统的频点是为了帮助我们对观测值O文件进行解读,下面这篇文章及其参考文献写的很好,可以参考

(250条消息) GNSS RINEX文件中的观测量o文件学习记录_rinex数据o文件_不止敲代码的博客-CSDN博客https://blog.csdn.net/wanglei00001/article/details/127421903这里列举几个常用的(GPS):

rinex2rinex3
C1C1C
C2

C2W/C2X

P1C1W
P2C2W
L1L1C
L2L2W


一些C语言高级编程

static和const用法

static

(244条消息) c语言中static关键字用法详解_guotianqing的博客-CSDN博客https://blog.csdn.net/guotianqing/article/details/79828100静态局部变量的效果跟全局变量有一拼,但是位于函数体内部,就极有利于程序的模块化了。

在定义不需要与其他文件共享的全局变量时,加上static关键字能够有效地降低程序模块之间的耦合,避免不同文件同名变量的冲突,且不会误使用。

非静态函数可以在另一个文件中直接引用,甚至不必使用extern声明

const用法


Trace and debug

https://www.electronicdesign.com/technologies/test-measurement/article/21242425/electronic-design-trace-and-debugging-an-explanation-techniques-and-applicationshttps://www.electronicdesign.com/technologies/test-measurement/article/21242425/electronic-design-trace-and-debugging-an-explanation-techniques-and-applicationsdefinition:monitor software in real-time debug

advantage:        1、in both debug and logging mode(release mode)

                          2、 doesn't impact the main code thread

RTKLIB中的trace工具

用到了C语言的可变参数(variable-argument)(<stdarg.h>)

//rtkcmn.c
extern void trace(int level, const char *format, ...)
{
    va_list ap;
    
    /* print error message to stderr */
    if (level<=1) {
        va_start(ap,format); vfprintf(stderr,format,ap); va_end(ap);
    }
    if (!fp_trace||level>level_trace) return;
    traceswap();	
    fprintf(fp_trace,"%d ",level);
    va_start(ap,format); vfprintf(fp_trace,format,ap); va_end(ap);
    fflush(fp_trace);
}

malloc函数和realloc函数

void *malloc(int size);

  说明:malloc 向系统申请分配指定size个字节的内存空间。返回类型是 void* 类型。void* 表示未确定类型的指针。C,C++规定,void* 类型可以强制转换为任何其它类型的指针。

/* new matrix ------------------------------------------------------------------
* allocate memory of matrix 
* args   : int    n,m       I   number of rows and columns of matrix
* return : matrix pointer (if n<=0 or m<=0, return NULL)
*-----------------------------------------------------------------------------*/
extern double *mat(int n, int m)
{
    double *p;
    
    if (n<=0||m<=0) return NULL;
    if (!(p=(double *)malloc(sizeof(double)*n*m))) {
        fatalerr("matrix memory allocation error: n=%d,m=%d\n",n,m);
    }
    return p;
}

 void *realloc(void *ptr, size_t size) 

尝试重新调整之前调用 malloc 或 calloc 所分配的 ptr 所指向的内存块的大小。

下面函数combpclk()实现了重新分配内存,原来读取数据时,size=sizeof(pclk_t)*nav->ncmax,而在组合精密钟差时,用的是size=sizeof(pclk_t)*nav->nc,其内存空间减小了

    nav->nc=i+1;
    
    if (!(nav_pclk=(pclk_t *)realloc(nav->pclk,sizeof(pclk_t)*nav->nc))) {
        free(nav->pclk); nav->pclk=NULL; nav->nc=nav->ncmax=0;
        trace(1,"combpclk malloc error nc=%d\n",nav->nc);
        return;
    }
    nav->pclk=nav_pclk;
    nav->ncmax=nav->nc;


函数指针(回调函数)

回调函数的目的是为了低耦合

fatalfunc就是一个函数指针,同时,它也是回调函数

fatalerr 函数 :致命错误的处理,接收可变参数。如果没提供fatalfunc回调函数,则stderr错误消息,并以-9形式退出程序;如果提供了fatalfunc回调函数,则把msg交给fatalfunc回调函数处理,并以-9形式退出程序。

//from rtkcmn.c

typedef void fatalfunc_t(const char *); /* fatal callback function type */
static fatalfunc_t *fatalfunc=NULL; /* fatal callback function */



/* fatal error ---------------------------------------------------------------*/
static void fatalerr(const char *format, ...)
{
    char msg[1024];
    va_list ap;
    va_start(ap,format); vsprintf(msg,format,ap); va_end(ap);
    if (fatalfunc) fatalfunc(msg);
    else fprintf(stderr,"%s",msg);
    exit(-9);
}
/* add fatal callback function -------------------------------------------------
* add fatal callback function for mat(),zeros(),imat()
* args   : fatalfunc_t *func I  callback function
* return : none
* notes  : if malloc() failed in return : none
*-----------------------------------------------------------------------------*/
extern void add_fatal(fatalfunc_t *func)
{
    fatalfunc=func;
}

回调函数(图解)具体可上网查找


根据条件截取矩阵

因为x[i]==0的部分不参与状态更新,因此我们要选出x[i]!=0时的x_  P_   H_

如下代码所示,要选出x[i]!=0的对应矩阵,ix存储的是i[x]!=0的x索引值,k是总共个数;

之后由ix和k去获取P和H的对应矩阵

//from rtkcmn.c Kalman Filter
/*notes  : matirix stored by column-major order (fortran convention)
*          if state x[i]==0.0, not updates state x[i]/P[i+i*n]*/

extern int filter(double *x, double *P, const double *H, const double *v,
                  const double *R, int n, int m)
{
    double *x_,*xp_,*P_,*Pp_,*H_;	//存储x[i]!=0时相应观测值
    int i,j,k,info,*ix;
    
    ix=imat(n,1); for (i=k=0;i<n;i++) if (x[i]!=0.0&&P[i+i*n]>0.0) ix[k++]=i;
    x_=mat(k,1); xp_=mat(k,1); P_=mat(k,k); Pp_=mat(k,k); H_=mat(k,m);
    for (i=0;i<k;i++) {
        x_[i]=x[ix[i]];
        for (j=0;j<k;j++) P_[i+j*k]=P[ix[i]+ix[j]*n];
        for (j=0;j<m;j++) H_[i+j*k]=H[ix[i]+j*n];
    }

单精度float赋值

//结构体
typedef struct {        /* precise ephemeris type */
    gtime_t time;       /* time (GPST) */
    int index;          /* ephemeris index for multiple files */
    double pos[MAXSAT][4]; /* satellite position/clock (ecef) (m|s) */
    float  std[MAXSAT][4]; /* satellite position/clock std (m|s) */
    double vel[MAXSAT][4]; /* satellite velocity/clk-rate (m/s|s/s) */
    float  vst[MAXSAT][4]; /* satellite velocity/clk-rate std (m/s|s/s) */
    float  cov[MAXSAT][3]; /* satellite position covariance (m^2) */
    float  vco[MAXSAT][3]; /* satellite velocity covariance (m^2) */
} peph_t;


//赋值
peph.pos[i][j]=0.0;
peph.std[i][j]=0.0f;

因为C语言中默认的浮点型常量类型为double类型,所以这样写程序执行时会存在一个将双精度浮点型变量转化为单精度浮点型变量的过程,这个过程可以通过如下的方式去除掉。

虽然这个转化的过程可以被某些高端的编译软件过滤掉,但是第二种写法是更稳妥的方式。

peph.std[i][j]=0.0f;

qosrt函数——快速排序

(249条消息) C语言qsort函数用法_zhao888789的博客-CSDN博客

功能: 使用快速排序(二分法)例程进行排序
  头文件:stdlib.h
  用法:  void qsort(void* base,size_t num,size_t width,int(__cdecl*compare)(const void*,const void*)); 
  参数: 1 待排序数组,排序之后的结果仍放在这个数组中
      2 数组中待排序元素数量
        3 各元素的占用空间大小(单位为字节)
             4 指向函数的指针,用于确定排序的顺序(需要用户自定义一个比较函数)
 

/*精密星历比较及排序demo*/
static int cmppeph(const void *p1, const void *p2)
{
    peph_t *q1=(peph_t *)p1,*q2=(peph_t *)p2;
    double tt=timediff(q1->time,q2->time);
    return tt<-1E-9?-1:(tt>1E-9?1:q1->index-q2->index);
}

//调用qsort函数
qsort(nav->peph,nav->ne,sizeof(peph_t),cmppeph);


读取文件的一些函数

//常用函数如下:
strlen求字符串长度
strcmp比较2个字符串是否一样
strcat字符串连接操作
strcpy字符串拷贝操作
strncat字符串连接操作(前n个字符)
strncpy字符串拷贝操作(前n个字符)
strchr查询字串
strstr 查询子串

//rtklib见到的函数append
remove删除文件

fopen和fgets

fopen——打开文件

fgets——读取行

fclose——关闭文件

    FILE *fp;
    char buff[256];
    
    trace(3,"readantex: file=%s\n",file);
    
    if (!(fp=fopen(file,"r"))) {
        trace(2,"antex pcv file open error: %s\n",file);
        return 0;
    }
    while (fgets(buff,sizeof(buff),fp))
    
    fclose(fp);

vfprintf、vprintf、vsprintf

一、vfprintf(见上文trace)

  功 能: 格式化的数据输出到指定的数据流中

  用 法: int vfprintf(FILE *stream, char *format, va_list param);

  函数说明:vfprintf()会根据参数format字符串来转换并格式化数据,然后将结果输出到参数stream指定的文件中,直到出现字符串结束  (‘/0’)为止。关于参数format字符串的格式请参 考printf()。

  返回值:成功则返回实际输出的字符数,失败则返回-1,错误原因存于errno中。

二、vprintf函数

     函数名: vprintf

  功 能: 送格式化输出到stdout中

  用 法: int vprintf(char *format, va_list param);

三、vsprintf函数(见下面代码段)

     功 能: 送格式化输出到串中

  用 法: int vsprintf(char *string, char *format, va_list param);

/* fatal error ---------------------------------------------------------------*/
static void fatalerr(const char *format, ...)
{
    char msg[1024];
    va_list ap;
    va_start(ap,format); vsprintf(msg,format,ap); va_end(ap);
    if (fatalfunc) fatalfunc(msg);
    else fprintf(stderr,"%s",msg);
    exit(-9);
}

(245条消息) vfprintf、vprintf和vsprintf函数_sherlockhua的博客-CSDN博客


strrchr和strcmp

读取扩展名并选择相应读取函数

strchr() 用于查找字符串中的一个字符,并返回该字符在字符串中第一次出现的位置。

strcmp——如果返回值 = 0,则表示 str1 等于 str2

//读取扩展名并选择相应读取函数
if (!(ext=strrchr(file,'.'))) ext="";
    
if (!strcmp(ext,".atx")||!strcmp(ext,".ATX")) {
    stat=readantex(file,pcvs);
}
else{
      stat=readngspcv(file,pcvs);
    }

strstr和strncpy

strstr()——用来匹配行

1、函数搜索一个字符串在另一个字符串中的第一次出现。
2、找到所搜索的字符串,则该函数返回第一次匹配的字符串的地址;
3、如果未找到所搜索的字符串,则返回NULL。

strncpy用来截取行,获得的是字符串

把 src 所指向的字符串复制到 dest,最多复制 n 个字符。当 src 的长度小于 n 时,dest 的剩余部分将用空字节填充。

说明:此函数功能即比较字符串str1和str2的前maxlen个字符。如果前maxlen字节完全相等,返回值就=0;在前maxlen字节比较过程中,如果出现str1[n]与str2[n]不等,则返回(str1[n]-str2[n])。

/*strstr和strncpy*/
if (strstr(buff+60,"TYPE / SERIAL NO")) {
            strncpy(pcv.type,buff   ,20); pcv.type[20]='\0';
            strncpy(pcv.code,buff+20,20); pcv.code[20]='\0';
            if (!strncmp(pcv.code+3,"        ",8)) {
                pcv.sat=satid2no(pcv.code);
            }
}

sscanf和strtok

sscanf——用来将得到的字符串按照指定格式输入变量

如果成功,该函数返回成功匹配和赋值的个数。如果到达文件末尾或发生读错误,则返回 EOF。

if (sscanf(str,"%lf %lf %lf %lf %lf %lf",ep,ep+1,ep+2,ep+3,ep+4,ep+5)<6)
        return -1;

strtok——分解字符串为一组字符串。s为要分解的字符串,delim为分隔符字符串。

每次都可以提取出单独的变量对其进行变换,如下面每次都对其缩小1000倍

/* decode antenna parameter field --------------------------------------------*/
static int decodef(char *p, int n, double *v)
{
    int i;
    
    for (i=0;i<n;i++) v[i]=0.0;
    for (i=0,p=strtok(p," ");p&&i<n;p=strtok(NULL," ")) {
        v[i++]=atof(p)*1E-3;
    }
    return i;
}

字符串截取技巧

/*将输入字符串按照position和width要求截取保存在str中*/

例如:如果截取1-43位字符——str2time(buff,0,43,&pcv.ts),

extern int str2time(const char *s, int i, int n, gtime_t *t)
{
    double ep[6];
    char str[256],*p=str;
    /*将输入字符串按照position和width要求截取保存在str中*/
    if (i<0||(int)strlen(s)<i||(int)sizeof(str)-1<i) return -1;
    for (s+=i;*s&&--n>=0;) *p++=*s++;
    *p='\0';
}

结构体模块化存储

如下,初始化n和nmax都为0,而我们只需要重复调用addpcv,就能将pcv存入pcvs->pcv里面

这行代码可以学习

pcvs->pcv[pcvs->n++]=*pcv;
/* add antenna parameter -----------------------------------------------------*/
static void addpcv(const pcv_t *pcv, pcvs_t *pcvs)
{
    pcv_t *pcvs_pcv;
    
    if (pcvs->nmax<=pcvs->n) {
        pcvs->nmax+=256;
        if (!(pcvs_pcv=(pcv_t *)realloc(pcvs->pcv,sizeof(pcv_t)*pcvs->nmax))) {
            trace(1,"addpcv: memory allocation error\n");
            free(pcvs->pcv); pcvs->pcv=NULL; pcvs->n=pcvs->nmax=0;
            return;
        }
        pcvs->pcv=pcvs_pcv;
    }
    pcvs->pcv[pcvs->n++]=*pcv;
}
typedef struct {        /* antenna parameter type */
    int sat;            /* satellite number (0:receiver) */
    char type[MAXANT];  /* antenna type */
    char code[MAXANT];  /* serial number or satellite code */
    gtime_t ts,te;      /* valid time start and end */
    double off[NFREQ][ 3]; /* phase center offset e/n/u or x/y/z (m) */
    double var[NFREQ][19]; /* phase center variation (m) */
                        /* el=90,85,...,0 or nadir=0,1,2,3,... (deg) */
} pcv_t;

typedef struct {        /* antenna parameters type */
    int n,nmax;         /* number of data/allocated */
    pcv_t *pcv;         /* antenna parameters data */
} pcvs_t;

存储一行多个结构相同的数据类型

else if (!strncmp(buff,"+ ",2)) { /* satellite id */
            if (ns==0) {
                ns=(int)str2num(buff,4,2);
            }
            for (j=0;j<17&&k<ns;j++) {
                sys=code2sys(buff[9+3*j]);
                prn=(int)str2num(buff,10+3*j,2);
                if (k<MAXSAT) sats[k++]=satno(sys,prn);
            }
        }

存储的数据(精密轨道文件——sp3-d


 读取sp3-body核心代码

这段代码读取一行,其同时实现剔除错误值和单位转换,可以学习

for (j=0;j<4;j++) {
                val=str2num(buff, 4+j*14,14);
                std=str2num(buff,61+j* 3,j<3?2:3);
                
                if (buff[0]=='P') { /* position */
                    if (val!=0.0&&fabs(val-999999.999999)>=1E-6) {
                        peph.pos[sat-1][j]=val*(j<3?1000.0:1E-6);
                        v=1; /* valid epoch */
                    }
                    if ((base=bfact[j<3?0:1])>0.0&&std>0.0) {
                        peph.std[sat-1][j]=(float)(pow(base,std)*(j<3?1E-3:1E-12));
                    }
                }
            }

按位与(&)和按位或(|)的应用

按位与操作,按二进制位进行"与"运算。

以下面卫星系统设置来说明该(&)的应用

#define SYS_NONE    0x00                /* navigation system: none */
#define SYS_GPS     0x01                /* navigation system: GPS */
#define SYS_SBS     0x02                /* navigation system: SBAS */
#define SYS_GLO     0x04                /* navigation system: GLONASS */
#define SYS_GAL     0x08                /* navigation system: Galileo */
#define SYS_QZS     0x10                /* navigation system: QZSS */
#define SYS_CMP     0x20                /* navigation system: BeiDou */
#define SYS_IRN     0x40                /* navigation system: IRNS */
#define SYS_LEO     0x80                /* navigation system: LEO */
#define SYS_ALL     0xFF                /* navigation system: all */

        比如:如果我们需要选择几个卫星系统,我们只需要设置opt |=(卫星系统)那么将opt与获得的卫星按位与操作,我们就能判断该卫星是否是我们需要的

       如下,mask返回其参数设置的卫星系统,将其与观测值的卫星系统按位与操作,我们就可以判断该卫星是否是我们需要的

/* set system mask -----------------------------------------------------------*/
static int set_sysmask(const char *opt)
{
    const char *p;
    int mask=SYS_NONE;
    
    if (!(p=strstr(opt,"-SYS="))) return SYS_ALL;
    
    for (p+=5;*p&&*p!=' ';p++) {
        switch (*p) {
            case 'G': mask|=SYS_GPS; break;
            case 'R': mask|=SYS_GLO; break;
            case 'E': mask|=SYS_GAL; break;
            case 'J': mask|=SYS_QZS; break;
            case 'C': mask|=SYS_CMP; break;
            case 'I': mask|=SYS_IRN; break;
            case 'S': mask|=SYS_SBS; break;
        }
    }
    return mask;
}


uint_8的使用

(190条消息) 浅析C语言之uint8_t / uint16_t / uint32_t /uint64_t_海阔天空sky1992的博客-CSDN博客https://blog.csdn.net/mary19920410/article/details/71518130

总结:使用这些类型的原因:方便代码的维护,在涉及到跨平台时,不同的平台会有不同的字长

但是有个问题,uint8_t是无符号字符型,为什么可以和int类型进行比较呢(这里笔者还不知道)

extern char *code2obs(uint8_t code)
{
    if (code<=CODE_NONE||MAXCODE<code) return "";
    return obscodes[code];
}


RTKLIB时间转换工具

epoch2time

其实该结构体储存的是自1970年1月1日0时0分0秒至目标时间的秒数time及不足整秒sec,结构体time_t为一个64位的整型。

typedef struct {        /* time struct */
    time_t time;        /* time (s) expressed by standard time_t */
    double sec;         /* fraction of second under 1 s */
} gtime_t;

epoch2time 是将日历时间(年,月,日,时,分,秒)转换为gtime形式

其中,下面行代码值得学习

const int doy[]={1,32,60,91,121,152,182,213,244,274,305,335};
days=(year-1970)*365+(year-1969)/4+doy[mon-1]+day-2+(year%4==0&&mon>=3?1:0);
/* convert calendar day/time to time -------------------------------------------
* convert calendar day/time to gtime_t struct
* args   : double *ep       I   day/time {year,month,day,hour,min,sec}
* return : gtime_t struct
* notes  : proper in 1970-2037 or 1970-2099 (64bit time_t)
*-----------------------------------------------------------------------------*/
extern gtime_t epoch2time(const double *ep)
{
    const int doy[]={1,32,60,91,121,152,182,213,244,274,305,335};
    gtime_t time={0};
    int days,sec,year=(int)ep[0],mon=(int)ep[1],day=(int)ep[2];
    
    if (year<1970||2099<year||mon<1||12<mon) return time;
    
    /* leap year if year%4==0 in 1901-2099 */
    days=(year-1970)*365+(year-1969)/4+doy[mon-1]+day-2+(year%4==0&&mon>=3?1:0);
    sec=(int)floor(ep[5]);
    time.time=(time_t)days*86400+(int)ep[3]*3600+(int)ep[4]*60+sec;
    time.sec=ep[5]-sec;
    return time;
}

RTKLIB矩阵

GNSS处理的数据都是矩阵数据,RTKLIB的 rtkcmn.c中写了一些矩阵运算的函数。
也可看 manual的 Appendix C API References,里面有RTKLIB函数功能的简单描述

(245条消息) RTKLIB学习总结(一)VS配置RTKLIB、manual、矩阵、最小二乘和Kalman滤波基本函数_rtklib 命令行_李郑骁学导航的博客-CSDN博客https://blog.csdn.net/daoge2666/article/details/129339677?spm=1001.2014.3001.5502

notice:matrix strored by column-majored order(fortran convention)

 以以上矩阵中的数字为例,其数组下标为mat[0],mat[2],mat[4]

下面的代码可学习

/* multiply matrix -----------------------------------------------------------*/
extern void matmul(const char *tr, int n, int k, int m, double alpha,
                   const double *A, const double *B, double beta, double *C)
{
    double d;
    int i,j,x,f=tr[0]=='N'?(tr[1]=='N'?1:2):(tr[1]=='N'?3:4);
    
    for (i=0;i<n;i++) for (j=0;j<k;j++) {
        d=0.0;
        switch (f) {
            case 1: for (x=0;x<m;x++) d+=A[i+x*n]*B[x+j*m]; break;
            case 2: for (x=0;x<m;x++) d+=A[i+x*n]*B[j+x*k]; break;
            case 3: for (x=0;x<m;x++) d+=A[x+i*m]*B[x+j*m]; break;
            case 4: for (x=0;x<m;x++) d+=A[x+i*m]*B[j+x*k]; break;
        }
        if (beta==0.0) C[i+j*n]=alpha*d; else C[i+j*n]=alpha*d+beta*C[i+j*n];
    }
}

关于矩阵求逆,下次有时间琢磨下

smoother也还未开,不知道有什么具体应用场景吗


Question

Kalman filter

notes  : matirix stored by column-major order (fortran convention)
*          if state x[i]==0.0, not updates state x[i]/P[i+i*n]

为什么x[i]==0,就不用再更新值了呢


openses

/* read satellite antenna parameters */
    if (*fopt->satantp&&!(readpcv(fopt->satantp,pcvs))) {
        showmsg("error : no sat ant pcv in %s",fopt->satantp);
        trace(1,"sat antenna pcv read error: %s\n",fopt->satantp);
        return 0;
    }
/* read receiver antenna parameters */
    if (*fopt->rcvantp&&!(readpcv(fopt->rcvantp,pcvr))) {
        showmsg("error : no rec ant pcv in %s",fopt->rcvantp);
        trace(1,"rec antenna pcv read error: %s\n",fopt->rcvantp);
        return 0;
    }

上面接收机和卫星调用的都是readpcv函数,它们的pcv值是一样的吗,我记得ppph里面貌似对这两个有所区分

note: opt用来设置选择的系统

在写函数发现的一个问题,静态变量和函数的参数不能设置成一样,不然会导致数据存储错误,后面还需要探讨下原因我当时用的是&pcvss,可能这传的是值而不是址,后面还需要再仔细探讨下

/*存储观测的数据*/
static pcvs_t pcvss = { 0 };        /* receiver antenna parameters */
static pcvs_t pcvsr = { 0 };        /* satellite antenna parameters */
static obs_t obss = { 0 };          /* observation data */
static nav_t navs = { 0 };          /* navigation data */
static sta_t stas[MAXRCV];      /* station infomation */

const prcopt_t prcopt_default = { /* defaults processing options */
	PMODE_SINGLE,0,2,SYS_GPS,   /* mode,soltype,nf,navsys */
	15.0*D2R,{ { 0,0 } },           /* elmin,snrmask */
	0,1,1,5,0,10,               /* sateph,modear,glomodear,maxout,minlock,minfix */
	0,0,0,0,                    /* estion,esttrop,dynamics,tidecorr */
	1,0,0,0,0,                  /* niter,codesmooth,intpref,sbascorr,sbassatsel */
	0,0,                        /* rovpos,refpos */
	{ 100.0,100.0 },              /* eratio[] */
	{ 100.0,0.003,0.003,0.0,1.0 }, /* err[] */
	{ 30.0,0.03,0.3 },            /* std[] */
	{ 1E-4,1E-3,1E-4,1E-1,1E-2 }, /* prn[] */
	5E-12,                      /* sclkstab */
	{ 3.0,0.9999,0.20 },          /* thresar */
	0.0,0.0,0.05,               /* elmaskar,almaskhold,thresslip */
	30.0,30.0,30.0,             /* maxtdif,maxinno,maxgdop */
	{ 0 },{ 0 },{ 0 },                /* baseline,ru,rb */
	{ "","" },                    /* anttype */
	{ { 0 } },{ { 0 } },{ 0 }             /* antdel,pcv,exsats */
};
const solopt_t solopt_default = { /* defaults solution output options */
	SOLF_LLH,TIMES_GPST,1,3,    /* posf,times,timef,timeu */
	0,1,0,0,0,0,                /* degf,outhead,outopt,datum,height,geoid */
	0,0,0,                      /* solstatic,sstat,trace */
	{ 0.0,0.0 },                  /* nmeaintv */
	" ",""                      /* separator/program name */
};


/*模块一:输入数据*/
int importData(const filopt_t *fopt, const prcopt_t *prcopt,pcvs_t *pcvs, pcvs_t *pcvr, 
	obs_t *obs, nav_t *nav,sta_t *sta)
{
	gtime_t ts = { 0 }, te = { 0 };
	int ret;

	trace(3, "Import Data");

	/* read satellite antenna parameters */
	if (*fopt->satantp&&!(readpcv(fopt->satantp, pcvs))) {
		showmsg("error : no sat ant pcv in %s", fopt->satantp);
		trace(1, "sat antenna pcv read error: %s\n", fopt->satantp);
		return 0;
	}
	/* read receiver antenna parameters */
	if (*fopt->rcvantp&&!(readpcv(fopt->rcvantp, pcvr))) {
		showmsg("error : no rec ant pcv in %s", fopt->rcvantp);
		trace(1, "rec antenna pcv read error: %s\n", fopt->rcvantp);
		return 0;
	}

	/*读取sp3精密星历*/
	readsp3(fopt->sp3, nav, 0);

	/*读取钟差文件*/
	readrnxc(fopt->clk, nav);

	/*读取观测值文件*/
	obs->data = NULL; obs->n = obs->nmax = 0;
	ret = readrnxt(fopt->obs, 1, ts, te, 0.0, prcopt->rnxopt[0], obs,nav,sta);
}

杂记备忘

 PMODE_???(定位模式)

  • PMODE_SINGLE:单点定位模式。
  • PMODE_KINEMA:动态定位模式。
  • PMODE_STATIC:静态定位模式。
  • PMODE_PPP_KINEMA:PPP动态定位模式。
  • PMODE_PPP_STATIC:PPP静态定位模式。
  • PMODE_MOVEBANK:运动载体定位模式。
  • PMODE_FIXED:固定解模式。
  • PMODE_PPP_FIXED:PPP固定解模式。
  • PMODE_INS_MECH:惯性组合定位模式。
  • PMODE_INS_GPS:INS/GPS组合定位模式。
  • PMODE_INS_GPS_PP:INS/GPS组合PPP定位模式。

post-processing position

ti   processing interval  (s) (0:all)——当ti不等于0时,RTKLIB会在处理历元数据时,每隔ti秒进行一次定位解算。

tu  processing unit time (s) (0:all) ——当tu不等于0时,RTKLIB会将所有历元数据分割成多个单元,每个单元包含了多个历元数据,每个单元内的历元数据的时间跨度不超过tu。

                                                                处理单元的时间跨度过小可能会导致定位解算的实时性较差,处理单元的时间跨度过大可能会导致定位解算的精度较差。

dynamics

在RTKLIB中,dynamics是一个选项,表示在卡尔曼滤波器中使用的动力学模型类型。

具体来说,该选项有三种可能的取值:

  • dynamics=0 表示不考虑动力学模型,即采用静态模型。
  • dynamics=1 表示采用一阶运动模型,即假设接收机在运动过程中的速度保持恒定,加速度为0。
  • dynamics=2 表示采用二阶运动模型,即假设接收机在运动过程中存在加速度,速度和位置随时间变化。

niter

在RTKLIB中,niter是一个选项,表示卡尔曼滤波器的迭代次数。

具体来说,卡尔曼滤波器是一种常用于实时或后处理GNSS定位中的数据处理技术,可以用来估计接收机的位置、速度、钟差等参数。在每一次更新卡尔曼滤波器状态时,都需要进行一定次数的迭代计算,以逐步优化状态估计值和协方差矩阵。

niter选项就是控制卡尔曼滤波器迭代次数的参数。在RTKLIB中,默认值为5,表示每次更新时进行5次迭代计算。通过适当调整该值,可以平衡定位精度和计算速度,从而获得满意的定位结果。

PCV

stands for "Phase Center Variation"——天线相位中心变换

天线相位两种格式:

".atx" or ".ATX"——ANTEX is a widely used format for storing and exchanging GNSS antenna phase center information.

"NGS antenna parameters"——The National Geodetic Survey (NGS) is a U.S. government agency that provides a range of geodetic services, including maintaining a database of antenna models and parameters.

Explain arguments

args   : char *file    I      file (wild-card * expanded)——

For example, if the argument "data/.obs" is passed to a RTKLIB function, it will expand the wildcard to match all files in the "data" directory with the ".obs" extension, and process them all.

This feature can be useful for processing large datasets that are stored in multiple files with similar naming conventions.

NNSS Transit System

was a satellite-based navigation system operated by the U.S. Navy from 1964 to 1996.

The system used a constellation of satellites in low Earth orbit to provide accurate position, velocity, and timing information to military and civilian users.

ION  ALPHA

 Ionosphere parameters A0-A3 of almanac 

In the RINEX 2 navigation file, the ionosphere parameters A0-A3 are used to model the ionospheric delay in the satellite signal propagation. The ionosphere is a layer of the Earth's atmosphere that contains charged particles that can delay the satellite signal as it passes through.

The A0-A3 parameters are coefficients used in the polynomial expression for the ionospheric delay, which is given by:

IONO_delay = A0 + A1 * t + A2 * t^2 + A3 * t^3

where t is the signal transmission time in seconds of the GPS week. The A0 parameter represents the ionospheric delay at the reference time, while A1-A3 represent the rate of change of the delay with time.

Ionosphere TEC grid file

TEC stands for Total Electron Content.

Ionosphere TEC (Total Electron Content) grid files are a type of data file that contains information on the electron content of the ionosphere. These files provide a way to model and predict the effect of ionospheric delay on satellite signals in GNSS applications. TEC grid files typically contain information on the electron content of the ionosphere at various points in space and time, and can be used to interpolate TEC values for a given location and time.

GPS2UTC

  • A0: the constant term of the polynomial that describes the difference between GPS time and UTC time
  • A1: the linear term of the polynomial
  • ToW: the reference time of the polynomial in seconds (seconds of the GPS week)
  • WNt: the GPS week number of the reference time
  • dt_LS: the time difference between GPS time and UTC time at the end of the current leap second
  • WN_LSF: the GPS week number of the end of the current leap second
  • DN: the day of the week of the end of the current leap second
  • dt_LSF: the time difference between GPS time and UTC time at the beginning of the next leap second

DCB(differential code bias)

DCB (Differential Code Bias) files are used in GNSSto correct the measurement errors caused by the satellite and receiver hardware biases.

DCB差分码偏差https://blog.csdn.net/tyst08/article/details/103950331

DCB(Differential Code Bias 差分码偏差)是全球卫星导航系统(GNSS)中,通过不同信号得到的观测值之间存在的系统性偏差。

DCB是由卫星和接收机硬件延迟的影响造成的。一般来说接收机端的DCB可以跟接收机钟差一起解算,被接收机钟差所吸收;而卫星端的DCB在精密定位中必须得到补偿。

DCB主要有两种,即相同频率不同码之间存在的偏差(如P1-C1、P2-C2等),以及不同频率之间存在的偏差(如P1-P2)

ERP(Earth Rotation Parameters)

In GNSS, the Earth Rotation Parameters (ERP) file is used to model the rotational motion of the Earth.

各国prn号

MIN:

  • QZSS-193
  • SBAS-100
  • 其他各国都是从1开始

Number:

Galileo:36

GPS:32

GLONASS:27

QZSS:10

BeiDou:63

IRNSS:14

LLI(Loss of Lock Indicator)     信号失锁

Epoch Flag(Observation File)

 Explain:

When epoch flag is set to 6, it means that there are cycle slip records following the observation data. Cycle slips occur when there is a sudden interruption in the phase of the carrier wave, which results in a loss of measurement accuracy.

Specifically, the cycle slip records have the following format:

> 2015 10 28 0 0 30.0000000  0  6
> G06  0.0000000  3         3 3 3
> G10  0.0000000  3         3 3 3
> R03  0.0000000  0         0 0 0
> R04  0.0000000  0         0 0 0
> E12  0.0000000  0         0 0 0

In this example, the first line is the epoch information, the second line contains information about the cycle slip for the GPS satellite G06, and the third line contains information about the cycle slip for the GPS satellite G10. The fourth and fifth lines contain information about the cycle slip for the GLONASS satellites R03 and R04, and the sixth line contains information about the cycle slip for the Galileo satellite E12.

The second column in each cycle slip record contains the phase measurement for the corresponding satellite and observation type at the current epoch. If a cycle slip is detected, the phase measurement is replaced with the character 'S'. The third column indicates whether the cycle slip has been repaired (0 = not repaired, 1 = repaired).

The last three columns are for LLI (Loss of Lock Indicator) and signal strength, which are not used in cycle slip records and are therefore left blank or set to zero.

The last three columns of LLI and signal strength represent the quality of the received signal.

The first column represents the LLI, which indicates whether or not the receiver has lost lock with the satellite at some point during the epoch. The value of 3 indicates that no loss of lock has been detected.

The second column represents the signal strength, which is a measure of the power of the received signal. The value of 3 indicates that the signal strength is unknown or not applicable.

The third column represents another type of LLI, which is used for some specific applications. The value of 3 in this column means that this LLI is not applicable or not used.

关于历法

格里高利历(Gregorian Calendar)

世界上最广泛使用,即我们所说的阳历

儒略历(Julian Calendar)

一种采用连续数值标示时间的方法,简称JD,还有MJD(Modified)约化儒略日

我国的农历

(Chinese Traditional Calendar)

其他常用时间系统还有:

年纪日,GPS时

Temp

  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值