目录

前置知识

卫星系统频点解读

一些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):

rinex2 rinex3
C1 C1C
C2

C2W/C2X

P1 C1W
P2 C2W
L1 L1C
L2 L2W

一些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.ctypedef 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

rtklib——PPP Learning相关推荐

  1. RTKlib PPP代码解析

    我所基于的代码版本是RTKlib 2.4.3的一个拓展版本RTKexplore Demo5,这个版本主要针对低成本的GNSS进行了一些改进完善. 文章目录 pppos udstate_ppp udbi ...

  2. RTKLIB ppp rtk_post

    1.实时ppp:IGS/MGEX数据处理中心的播发的实时轨道钟差产品,结合广播星历,实现实时定位 2.事后的(近似实时):下载精密星历.钟差产品,结合其他的精密改正信息,实现定位. 延迟一天CNES实 ...

  3. 【翻译】20180508利用 SSR信息在RTKLIB 中进行PPP解算

    原文作者为rtklibexplorer,写作时间为2018年,非最近更新文章.原文地址: using-ssr-corrections-with-rtklib-for-ppp-solutions这里只是 ...

  4. 关于PPP-RTK技术优势的一些思考与总结

    文章目录 一.前言 二.SSR修正与PPP 三.RTK与PPP-RTK的对比 四.PPP-RTK的技术优势 五.总结 参考文章 欢迎关注个人公众号:导航员学习札记 一.前言 感觉近几年PPP和PPP- ...

  5. 使用编译版rtklib过程中如何进行main的调试(spp ppp)

    使用编译版rtklib过程中如何进行main的调试(spp ppp) 在编译版rtklib的调试过程中,需要在main函数中定义一些参数. 在进行spp(伪距单点定位)的时候,我们通常这样设定相关参数 ...

  6. 使用rtklib进行实时PPP定位

    rtklib中rtknavi模块支持实时PPP定位,使用gui配置实时PPP较为方便.本文为小白介绍一下如何进行第一次实时PPP定位. 一.注册Ntrip账号 目前我主要使用的caster有三个 武汉 ...

  7. RTKLIB超详细调试(VS),手把手教你全过程~(以PPP为例)第一篇——读取配置文件、精密星历、精密钟差篇

    最近呢,由于科研中需要用到RTKLIB,之前用过它的GUI版本,功能很强大,但是要了解深入的逻辑,光是用那肯定是远远不够的,所以开这篇博客,记录一下调试过程 调试的版本:RTKLIB demo5版本( ...

  8. 用RTKLIB中的rtkpost进行ppp和spp定位(附用CUI rnx2rtkp 编译)

    目录 rtkpost ppp spp VS2019编译rnx2rtkp 使用crx2rnx.exe .bat批量化处理rnx2rtkp.exe RTKLIB中调用LAPACK库 rtkpost rtk ...

  9. RTKLIB 2.4.2后处理PPP设置参数简介

    RTKLIB 2.4.2后处理PPP设置参数简介 添加必选文件 通过Options界面配置解算参数并添加可选文件 Setting1选项卡配置参数输入 Setting2选项卡设置整周模糊度固定策略 Ou ...

最新文章

  1. 以太经典(ETC)逆势上涨,将逆袭反超以太坊(ETH)?
  2. 核试验计算机模拟,随着信息技术的发展,包括核试验在内的许多科学研究都可以用计算机模拟...
  3. python深浅拷贝 面试_python基础-深浅拷贝
  4. 多线程在任何情况下均能提高效率吗?
  5. Java交流|面试最后一问:你有什么问题想问我吗?
  6. Symbol Mc1000 Text文本阅读器整体代码
  7. Android应用开发:CardView的使用及兼容
  8. Debian下RPM包安装
  9. windows 开启mysql日志记录_Windows下MySQL开启历史记录
  10. Redis的高可用详解:Redis哨兵、复制、集群的设计原理,以及区别
  11. android秋招面试题及答案,阿里巴巴2019秋招客户端开发工程师在线笔试题和面试题答案...
  12. java map类转javabean_JavaBean和Map转换封装类的方法
  13. 微型计算机常用的输入设备分别是,微型计算机常见的基本输入输出设备有哪些?...
  14. 视频文件格式扩展名/专用名词详解
  15. 清除COOKIES有什么好处
  16. 【AEC】【拍乐云Pano 】回声消除(AEC)怎么理解?
  17. 图形学经典参考书籍 电子书下载
  18. NLM_P-Parameter-Free Fast Pixelwise Non-Local Means Denoising分享
  19. 计算机网络与物流论文题目,电子商务与现代物流关系浅析毕业论文.docx
  20. 配置Hibernate环境

热门文章

  1. 华为哪些手机配备了鸿蒙系统,手机升级成为鸿蒙系统第一手体验怎么样?
  2. 用 sed 去除文件中的 ASCII 控制字符乱码
  3. C++:从口袋中抓三个不同颜色的球,求有多少种取法
  4. 湘潭校赛 Hard Wuxing
  5. 为什么微信聊天记录不能云备份呢?
  6. java修改文件只读_创建文件并将其属性更改为Java中的只读
  7. iMovie学习笔记
  8. (转)红包随机算法微信群红包随机算法
  9. svn命令问题:npm WARN ajv-keywords@3.5.0 requires a peer of ajv@^6.9.1 but none is installed. You must in
  10. 软件性能测试分析与调优实践之路---性能测试系列-java gc调优