RTKLIB源码调试.trace文件解析&.stat文件解析

.trace文件是调试文件,帮助用户在程序、输入数据时,进行分析的一个很好的提示!

.trace文件的生成、trace文件内容的生成,均在execses中!

以单点定位为例,大体流程为:

  • 生成.trace文件:raceopen(tracefile); //开始对 trace文件进行写处理
  • 读取观测文件、导航文件,将调试信息放入.trace文件中;

    /* read obs and nav data */
    if (!readobsnav(ts,te,ti,infile,index,n,&popt_,&obss,&navs,stas)) return 0;

  • 生成解决方案文件/日志流:open solution status file

    /* open solution statistics */
    if (flag&&sopt->sstat>0) { /* solution statistics level (0:off,1:states,2:residuals) */
        strcpy(statfile,outfile);
        strcat(statfile,".stat");
        rtkclosestat();
        rtkopenstat(statfile,sopt->sstat);
    }

 

一、设置trace/debug 1-5

在Visual Studio中修改、调试代码时,如下设置:

sopt.trace = 5;          /* debug trace level (0:off,1-5:debug) */

单基站、移动站等数据作为输入时,.trace文件的生成是:

/* execute processing session ------------------------------------------------*/
static int execses(gtime_t ts, gtime_t te, double ti, const prcopt_t *popt,
                   const solopt_t *sopt, const filopt_t *fopt, int flag,
                   char **infile, const int *index, int n, char *outfile)
{
    FILE *fp;
    prcopt_t popt_=*popt;
    char tracefile[1024],statfile[1024],path[1024],*ext;
    
    trace(3,"execses : n=%d outfile=%s\n",n,outfile);
    
    /* open debug trace */
    if (flag&&sopt->trace>0) {
        if (*outfile) {
            strcpy(tracefile,outfile);
            strcat(tracefile,".trace"); //输出文件名,后加.trace
        }
        else {
            strcpy(tracefile,fopt->trace);
        }
        traceclose(); //关闭记录文件
        traceopen(tracefile); //开始对 trace文件进行写处理
        tracelevel(sopt->trace); //读取调试等级
    } //以上执行完后,.trace文件为空
    /* read ionosphere data file */
	//目前的输入文件中,文件输入为:filopt_t fopt = { 0 };  
    if (*fopt->iono&&(ext=strrchr(fopt->iono,'.'))) {
        if (strlen(ext)==4&&(ext[3]=='i'||ext[3]=='I')) {
            reppath(fopt->iono,path,ts,"","");
            readtec(path,&navs,1);
        }
    }
    /* read erp data */
    if (*fopt->eop) {
        free(navs.erp.data); navs.erp.data=NULL; navs.erp.n=navs.erp.nmax=0;
        reppath(fopt->eop,path,ts,"","");
        if (!readerp(path,&navs.erp)) {
            showmsg("error : no erp data %s",path);
            trace(2,"no erp data %s\n",path);
        }
    }
    /* read obs and nav data */
    if (!readobsnav(ts,te,ti,infile,index,n,&popt_,&obss,&navs,stas)) return 0;
    
    /* read dcb parameters */
    if (*fopt->dcb) {
        reppath(fopt->dcb,path,ts,"","");
        readdcb(path,&navs,stas);
    }
    /* set antenna paramters 设置天线参数*/
    if (popt_.mode!=PMODE_SINGLE) {
        setpcv(obss.n>0?obss.data[0].time:timeget(),&popt_,&navs,&pcvss,&pcvsr,
               stas);
    }
    /* read ocean tide loading parameters 设置潮汐参数*/
    if (popt_.mode>PMODE_SINGLE&&*fopt->blq) {
        readotl(&popt_,fopt->blq,stas);
    }
    /* rover/reference fixed position 获取基准站坐标*/
    if (popt_.mode==PMODE_FIXED) {
        if (!antpos(&popt_,1,&obss,&navs,stas,fopt->stapos)) {
            freeobsnav(&obss,&navs);
            return 0;
        }
    }
	/*定位模式:PMODE_DGPS PMODE_KINEMA  PMODE_STATIC */
    else if (PMODE_DGPS<=popt_.mode&&popt_.mode<=PMODE_STATIC) {
        if (!antpos(&popt_,2,&obss,&navs,stas,fopt->stapos)) {
            freeobsnav(&obss,&navs);
            return 0;
        }
    }
    /* open solution statistics */
    if (flag&&sopt->sstat>0) { /* solution statistics level (0:off,1:states,2:residuals) */
        strcpy(statfile,outfile);
        strcat(statfile,".stat");
        rtkclosestat();
        rtkopenstat(statfile,sopt->sstat);
    }
    /* write header to output file */
    if (flag&&!outhead(outfile,infile,n,&popt_,sopt)) {
        freeobsnav(&obss,&navs);
        return 0;
    }
    iobsu=iobsr=isbs=ilex=revs=aborts=0;
    
    if (popt_.mode==PMODE_SINGLE||popt_.soltype==0) {//在kinematic模式下,如果前向处理则进行单点定位
        if ((fp=openfile(outfile))) {
            procpos(fp,&popt_,sopt,0); /* forward前向处理 */
            fclose(fp);
        }
    }
    else if (popt_.soltype==1) {
        if ((fp=openfile(outfile))) {
            revs=1; iobsu=iobsr=obss.n-1; isbs=sbss.n-1; ilex=lexs.n-1;
            procpos(fp,&popt_,sopt,0); /* backward */
            fclose(fp);
        }
    }
    else { /* combined */
        solf=(sol_t *)malloc(sizeof(sol_t)*nepoch);
        solb=(sol_t *)malloc(sizeof(sol_t)*nepoch);
        rbf=(double *)malloc(sizeof(double)*nepoch*3);
        rbb=(double *)malloc(sizeof(double)*nepoch*3);
        
        if (solf&&solb) {
            isolf=isolb=0;
            procpos(NULL,&popt_,sopt,1); /* forward */
            revs=1; iobsu=iobsr=obss.n-1; isbs=sbss.n-1; ilex=lexs.n-1;
            procpos(NULL,&popt_,sopt,1); /* backward */
            
            /* combine forward/backward solutions */
            if (!aborts&&(fp=openfile(outfile))) {
                combres(fp,&popt_,sopt);
                fclose(fp);
            }
        }
        else showmsg("error : memory allocation");
        free(solf);
        free(solb);
        free(rbf);
        free(rbb);
    }
    /* free obs and nav data */
    freeobsnav(&obss,&navs);
    
    return aborts?1:0;
}

二、trace文件说明:位于execses函数中

以单点定位为例,即输入两个文件,分别为:观测文件、导航文件;

首先读取观测文件,在trace中相关信息如下:

1、函数readobsnav,输出第一条trace信息:

在readobsnav中,循环读取观测文件、导航文件;先读取观测文件……

1.1、函数readrnxt中,trace中显示输入观测文件路径和接收机数量

1.2、readrnxh为读取Rinex文件头的信息,进入readrnxh程序,输出信息:3 readrnxh:

其中,trace中每一行的开头都标记有函数信息,即调用时间顺序!

1.3、decode_obsh为读取Rinex文件头的信息,每次读取一行,进入decode_obsh程序,输出一行信息:

4 decode_obsh: ver=3.03

示意如下:

3 readobsnav: ts=2019/04/01 00:00:00 n=2
3 readrnxt: file=E:\专业资料\网友交流\Curtin GNSS Research Centre\CUT00\CUT000AUS_R_20190910000_01D_30S_MO.rnx rcv=1
3 expath  : path=E:\专业资料\网友交流\Curtin GNSS Research Centre\CUT00\CUT000AUS_R_20190910000_01D_30S_MO.rnx nmax=1024
3 expath  : file=E:\专业资料\网友交流\Curtin GNSS Research Centre\CUT00\CUT000AUS_R_20190910000_01D_30S_MO.rnx
3 readrnxfile: file=E:\专业资料\网友交流\Curtin GNSS Research Centre\CUT00\CUT000AUS_R_20190910000_01D_30S_MO.rnx flag=0 index=1
3 rtk_uncompress: file=E:\专业资料\网友交流\Curtin GNSS Research Centre\CUT00\CUT000AUS_R_20190910000_01D_30S_MO.rnx
3 rtk_uncompress: stat=0
3 readrnxfp: flag=0 index=1
3 readrnxh:
4 decode_obsh: ver=3.03
4 decode_obsh: ver=3.03
4 decode_obsh: ver=3.03
4 decode_obsh: ver=3.03
4 decode_obsh: ver=3.03
4 decode_obsh: ver=3.03
忽略重复的数据,此图仅仅是示意

1.4、读取观测文件body,

函数: readrnxobs;

然后输出:readrnxobs: rcv=1 ver=3.03 tsys=13830824

4.1 readrnxobsb

然后进入函数:readrnxobsb 中,首先实现的功能是将 读取观测文件头时保存的观测类型/OBS TYPES,从变量

tobs变为index, 在具体实现时:

1、设置了每一个系统观测类型频率的优先级;

2、每一个频率只保留优先级最高的数据;(扔掉的数据在trace中出现,如下)

readrnxobs: rcv=1 ver=3.03 tsys=13830824
4 reject obs type: sys= 1, obs=C2X
4 reject obs type: sys= 1, obs=D2X
4 reject obs type: sys= 1, obs=L2X
4 reject obs type: sys= 1, obs=S2X
4 reject obs type: sys= 4, obs=C1C
4 reject obs type: sys= 4, obs=C2C
4 reject obs type: sys= 4, obs=D1C
4 reject obs type: sys= 4, obs=D2C
4 reject obs type: sys= 4, obs=L1C
4 reject obs type: sys= 4, obs=L2C
4 reject obs type: sys= 4, obs=S1C
4 reject obs type: sys= 4, obs=S2C
4 reject obs type: sys= 8, obs=C7X
4 reject obs type: sys= 8, obs=C8X
4 reject obs type: sys= 8, obs=D7X
4 reject obs type: sys= 8, obs=D8X
4 reject obs type: sys= 8, obs=L7X
4 reject obs type: sys= 8, obs=L8X
4 reject obs type: sys= 8, obs=S7X
4 reject obs type: sys= 8, obs=S8X
4 reject obs type: sys=16, obs=C1X
4 reject obs type: sys=16, obs=C1Z
4 reject obs type: sys=16, obs=C6L
4 reject obs type: sys=16, obs=D1X
4 reject obs type: sys=16, obs=D1Z
4 reject obs type: sys=16, obs=D6L
4 reject obs type: sys=16, obs=L1X
4 reject obs type: sys=16, obs=L1Z
4 reject obs type: sys=16, obs=L6L
4 reject obs type: sys=16, obs=S1X
4 reject obs type: sys=16, obs=S1Z
4 reject obs type: sys=16, obs=S6L

附:频率优先级:

static char codepris[7][MAXFREQ][16]={  /* code priority table */
   
   /* L1/E1      L2/B1        L5/E5a/L3 E6/LEX/B3 E5b/B2    E5(a+b)  S */
    {"CPYWMNSL","PYWCMNDSLX","IQX"     ,""       ,""       ,""      ,""    }, /* GPS */
    {"PC"      ,"PC"        ,"IQX"     ,""       ,""       ,""      ,""    }, /* GLO */
    {"CABXZ"   ,""          ,"IQX"     ,"ABCXZ"  ,"IQX"    ,"IQX"   ,""    }, /* GAL */
    {"CSLXZ"   ,"SLX"       ,"IQX"     ,"SLX"    ,""       ,""      ,""    }, /* QZS */
    {"C"       ,""          ,"IQX"     ,""       ,""       ,""      ,""    }, /* SBS */
    {"IQX"     ,"IQX"       ,"IQX"     ,"IQX"    ,"IQX"    ,""      ,""    }, /* BDS */
    {""        ,""          ,"ABCX"    ,""       ,""       ,""      ,"ABCX"}  /* IRN */
};

RTKLIB Manual中描述:

从函数readrnxobsb中,开始循环读取每一个历元的观测数据:

 

1.5、解码decode_obsepoch

decode_obsepoch

首先 读取此历元的观测卫星数目,并在trace中输出:分别为进入函数和结束函数时的输出!

4 decode_obsepoch: ver=3.03

4 decode_obsepoch: time=2019/04/01 00:00:00.000 flag=0

然后开始对每历元中卫星相关数据进行读取:函数为decode_obsdata;读取每行时,输出信息:

4 decode_obsdata: ver=3.03
4 decode_obsdata: time=2019/04/01 00:00:00 sat=97 //此时的sat是各个卫星系统累加值

循环用decode_obsdata读取,以上两条信息重复显示,最终如下:

4 decode_obsepoch: ver=3.03
4 decode_obsepoch: time=2019/04/01 00:00:00.000 flag=0
4 decode_obsdata: ver=3.03
4 decode_obsdata: time=2019/04/01 00:00:00 sat=97
4 decode_obsdata: ver=3.03
4 decode_obsdata: time=2019/04/01 00:00:00 sat=98
4 decode_obsdata: ver=3.03
4 decode_obsdata: time=2019/04/01 00:00:00 sat=99
4 decode_obsdata: ver=3.03
4 decode_obsdata: time=2019/04/01 00:00:00 sat=100
4 decode_obsdata: ver=3.03
4 decode_obsdata: time=2019/04/01 00:00:00 sat=101
4 decode_obsdata: ver=3.03
4 decode_obsdata: time=2019/04/01 00:00:00 sat=102
4 decode_obsdata: ver=3.03
4 decode_obsdata: time=2019/04/01 00:00:00 sat=103
4 decode_obsdata: ver=3.03
4 decode_obsdata: time=2019/04/01 00:00:00 sat=104
4 decode_obsdata: ver=3.03
4 decode_obsdata: time=2019/04/01 00:00:00 sat=106
4 decode_obsdata: ver=3.03
4 decode_obsdata: time=2019/04/01 00:00:00 sat=109
4 decode_obsdata: ver=3.03
4 decode_obsdata: time=2019/04/01 00:00:00 sat=114
4 decode_obsdata: ver=3.03
4 decode_obsdata: time=2019/04/01 00:00:00 sat=61
4 decode_obsdata: ver=3.03
4 decode_obsdata: time=2019/04/01 00:00:00 sat=63
4 decode_obsdata: ver=3.03
4 decode_obsdata: time=2019/04/01 00:00:00 sat=64
4 decode_obsdata: ver=3.03
4 decode_obsdata: time=2019/04/01 00:00:00 sat=68
4 decode_obsdata: ver=3.03
4 decode_obsdata: time=2019/04/01 00:00:00 sat=70
4 decode_obsdata: ver=3.03
4 decode_obsdata: time=2019/04/01 00:00:00 sat=73
4 decode_obsdata: ver=3.03
4 decode_obsdata: time=2019/04/01 00:00:00 sat=84
4 decode_obsdata: ver=3.03
4 decode_obsdata: time=2019/04/01 00:00:00 sat=89
4 decode_obsdata: ver=3.03
4 decode_obsdata: unsupported sat sat=E36
4 decode_obsdata: ver=3.03
4 decode_obsdata: time=2019/04/01 00:00:00 sat=10
4 decode_obsdata: ver=3.03
4 decode_obsdata: time=2019/04/01 00:00:00 sat=15
4 decode_obsdata: ver=3.03
4 decode_obsdata: time=2019/04/01 00:00:00 sat=16
4 decode_obsdata: ver=3.03
4 decode_obsdata: time=2019/04/01 00:00:00 sat=20
4 decode_obsdata: ver=3.03
4 decode_obsdata: time=2019/04/01 00:00:00 sat=21
4 decode_obsdata: ver=3.03
4 decode_obsdata: time=2019/04/01 00:00:00 sat=25
4 decode_obsdata: ver=3.03
4 decode_obsdata: time=2019/04/01 00:00:00 sat=26
4 decode_obsdata: ver=3.03
4 decode_obsdata: time=2019/04/01 00:00:00 sat=27
4 decode_obsdata: ver=3.03
4 decode_obsdata: time=2019/04/01 00:00:00 sat=29
4 decode_obsdata: ver=3.03
4 decode_obsdata: time=2019/04/01 00:00:00 sat=31
4 decode_obsdata: ver=3.03
4 decode_obsdata: time=2019/04/01 00:00:00 sat=90
4 decode_obsdata: ver=3.03
4 decode_obsdata: time=2019/04/01 00:00:00 sat=91
4 decode_obsdata: ver=3.03
4 decode_obsdata: time=2019/04/01 00:00:00 sat=92
4 decode_obsdata: ver=3.03
4 decode_obsdata: time=2019/04/01 00:00:00 sat=37
4 decode_obsdata: ver=3.03
4 decode_obsdata: time=2019/04/01 00:00:00 sat=38
4 decode_obsdata: ver=3.03
4 decode_obsdata: time=2019/04/01 00:00:00 sat=39
4 decode_obsdata: ver=3.03
4 decode_obsdata: time=2019/04/01 00:00:00 sat=42
4 decode_obsdata: ver=3.03
4 decode_obsdata: time=2019/04/01 00:00:00 sat=43
4 decode_obsdata: ver=3.03
4 decode_obsdata: time=2019/04/01 00:00:00 sat=44
4 decode_obsdata: ver=3.03
4 decode_obsdata: time=2019/04/01 00:00:00 sat=45
4 decode_obsdata: ver=3.03
4 decode_obsdata: time=2019/04/01 00:00:00 sat=53
4 decode_obsdata: ver=3.03
4 decode_obsdata: time=2019/04/01 00:00:00 sat=54
4 decode_obsdata: ver=3.03
4 decode_obsdata: time=2019/04/01 00:00:00 sat=55
4 decode_obsdata: ver=3.03
4 decode_obsdata: time=2019/04/01 00:00:00 sat=146
4 decode_obsdata: ver=3.03
4 decode_obsdata: time=2019/04/01 00:00:00 sat=147
4 decode_obsdata: ver=3.03
4 decode_obsdata: time=2019/04/01 00:00:00 sat=148
4 decode_obsdata: ver=3.03
4 decode_obsdata: time=2019/04/01 00:00:00 sat=149
4 decode_obsdata: ver=3.03
4 decode_obsdata: time=2019/04/01 00:00:00 sat=151
4 decode_obsdata: ver=3.03
4 decode_obsdata: time=2019/04/01 00:00:00 sat=156
4 reject obs type: sys= 1, obs=C2X
4 reject obs type: sys= 1, obs=D2X
4 reject obs type: sys= 1, obs=L2X
4 reject obs type: sys= 1, obs=S2X
4 reject obs type: sys= 4, obs=C1C
4 reject obs type: sys= 4, obs=C2C
4 reject obs type: sys= 4, obs=D1C
4 reject obs type: sys= 4, obs=D2C
4 reject obs type: sys= 4, obs=L1C
4 reject obs type: sys= 4, obs=L2C
4 reject obs type: sys= 4, obs=S1C
4 reject obs type: sys= 4, obs=S2C
4 reject obs type: sys= 8, obs=C7X
4 reject obs type: sys= 8, obs=C8X
4 reject obs type: sys= 8, obs=D7X
4 reject obs type: sys= 8, obs=D8X
4 reject obs type: sys= 8, obs=L7X
4 reject obs type: sys= 8, obs=L8X
4 reject obs type: sys= 8, obs=S7X
4 reject obs type: sys= 8, obs=S8X
4 reject obs type: sys=16, obs=C1X
4 reject obs type: sys=16, obs=C1Z
4 reject obs type: sys=16, obs=C6L
4 reject obs type: sys=16, obs=D1X
4 reject obs type: sys=16, obs=D1Z
4 reject obs type: sys=16, obs=D6L
4 reject obs type: sys=16, obs=L1X
4 reject obs type: sys=16, obs=L1Z
4 reject obs type: sys=16, obs=L6L
4 reject obs type: sys=16, obs=S1X
4 reject obs type: sys=16, obs=S1Z
4 reject obs type: sys=16, obs=S6L
4 decode_obsepoch: ver=3.03
4 decode_obsepoch: time=2019/04/01 00:00:30.000 flag=0

循环读取每一个历元数据,最后读取完成;

在readrnxobs函数最后,trace(4,"readrnxobs: nobs=%d stat=%d\n",obs->n,stat);

4 readrnxobs: nobs=5800 stat=1

总的观测数:即有多少个历元!

读取完之后,回到readrnxt函数中,

然后回到readobsnav函数中,进行读取下一个文件,即导航文件!

如果是相对定位,输入两个观测文件,先读移动站观测文件、接着读基准站观测文件:

紧接着读取导航电文:

2.1、函数readrnxt中,trace中显示输入导航文件路径和接收机数量

.trace文件中

开始进行导航文件读取:

2.2、再一次进入readrnxfile中:

4 readrnxobs: nobs=5800 stat=1
3 readrnxt: file=E:\专业资料\网友交流\Curtin GNSS Research Centre\CUT00\CUT000AUS_R_20190910000_01D_MN.rnx rcv=2
3 expath  : path=E:\专业资料\网友交流\Curtin GNSS Research Centre\CUT00\CUT000AUS_R_20190910000_01D_MN.rnx nmax=1024
3 expath  : file=E:\专业资料\网友交流\Curtin GNSS Research Centre\CUT00\CUT000AUS_R_20190910000_01D_MN.rnx
3 readrnxfile: file=E:\专业资料\网友交流\Curtin GNSS Research Centre\CUT00\CUT000AUS_R_20190910000_01D_MN.rnx flag=0 index=2
3 rtk_uncompress: file=E:\专业资料\网友交流\Curtin GNSS Research Centre\CUT00\CUT000AUS_R_20190910000_01D_MN.rnx
3 rtk_uncompress: stat=0

2.3、进入readrnxfp函数中:

3 readrnxfp: flag=0 index=2

2.3.1、进入readrnxh函数中:

在标识“N”中,进入decode_navh中,trace显示:

3 readrnxfp: flag=0 index=2
3 readrnxh:
4 decode_navh:

2.3.2、进入readrnxnav函数中:

3 readrnxh:
4 decode_navh:
3 readrnxnav: ver=3.00 sys=0

2.3.2.1、 进入readrnxnavb函数中:

3 readrnxh:
4 decode_navh:
3 readrnxnav: ver=3.00 sys=0
4 readrnxnavb: ver=3.00 sys=0

decode_eph函数,解码星历:

3 readrnxh:
4 decode_navh:
3 readrnxnav: ver=3.00 sys=0
4 readrnxnavb: ver=3.00 sys=0
4 decode_eph: ver=3.00 sat= 1

readrnxnavb函数一直读取导航文件的每颗卫星星历,并把它添加到对应卫星系统的星历结构体中。

while ((stat=readrnxnavb(fp,opt,ver,sys,&type,&eph,&geph,&seph))>=0) {
        
        /* add ephemeris to navigation data */
        if (stat) {
            switch (type) { //type来判断哪一个卫星系统的星历
                case 1 : stat=add_geph(nav,&geph); break;
                case 2 : stat=add_seph(nav,&seph); break;
                default: stat=add_eph (nav,&eph ); break;
            }
            if (!stat) return 0;
        }
    }

trace文件中,显示如下:

最后返回到readobsnav函数中;

执行 观测文件排序、删除重复星历两个函数:

    /* sort observation data */
    nepoch=sortobs(obs);
    
    /* delete duplicated ephemeris */
    uniqnav(nav);

.trace中为:

2、生成日志流文件/.stat

读取完观测文件和导航文件后,返回到 execses函数继续运行,如果在配置中打开了“解决方案文件/日志流文件”,则生成后缀为.stat的文件;同时.trace有如下信息输出:

2.1、生成结果文件/.pos

/* write header to output file -----------------------------------------------*/
static int outhead(const char *outfile, char **infile, int n,
                   const prcopt_t *popt, const solopt_t *sopt)
{
    FILE *fp=stdout;
    
    trace(3,"outhead: outfile=%s n=%d\n",outfile,n);
    
    if (*outfile) {
        createdir(outfile);
        
        if (!(fp=fopen(outfile,"w"))) {
            showmsg("error : open output file %s",outfile);
            return 0;
        }
    }
    /* output header */
    outheader(fp,infile,n,popt,sopt);
    
    if (*outfile) fclose(fp);
    
    return 1;
}

并输出结果文件,文件头(如果你设置了输出文件头)

2.2、初始化rtkinit

    rtkinit(&rtk,popt);

3 rtkclosestat:
3 rtkopenstat: file=E:\专业资料\网友交流\Curtin GNSS Research Centre\CUT00\myposbyVS.pos.stat level=1
3 outhead: outfile=E:\专业资料\网友交流\Curtin GNSS Research Centre\CUT00\myposbyVS.pos n=2
3  1370.658: createdir: path=E:\专业资料\网友交流\Curtin GNSS Research Centre\CUT00\myposbyVS.pos
3 outheader: n=2
3 outprcopt:
3 outprcopts:
3 outsolhead:
3 outsolheads:
3 openfile: outfile=E:\专业资料\网友交流\Curtin GNSS Research Centre\CUT00\myposbyVS.pos
3 procpos : mode=0
3 rtkinit :

 

不太明白的地方?

/* input obs data, navigation messages and sbas correction -------------------*/
static int inputobs(obsd_t *obs, int solq, const prcopt_t *popt)
{
    gtime_t time={0};
    int i,nu,nr,n=0;
    
    trace(3,"infunc  : revs=%d iobsu=%d iobsr=%d isbs=%d\n",revs,iobsu,iobsr,isbs);
    
    if (0<=iobsu&&iobsu<obss.n) {
        settime((time=obss.data[iobsu].time));
        if (checkbrk("processing : %s Q=%d",time_str(time,0),solq)) {
            aborts=1; showmsg("aborted"); return -1;
        }
    }
    if (!revs) { /* input forward data */ /* analysis direction (0:forward,1:backward) */
        if ((nu=nextobsf(&obss,&iobsu,1))<=0) return -1; //nu 为移动站历元观测卫星数
        if (popt->intpref) { ///* interpolate reference obs (for post mission) */ 0
            for (;(nr=nextobsf(&obss,&iobsr,2))>0;iobsr+=nr)
                if (timediff(obss.data[iobsr].time,obss.data[iobsu].time)>-DTTOL) break;
        }
        else {
            for (i=iobsr;(nr=nextobsf(&obss,&i,2))>0;iobsr=i,i+=nr)//nr 为基准站历元观测微型数
                if (timediff(obss.data[i].time,obss.data[iobsu].time)>DTTOL) break;
        }
        nr=nextobsf(&obss,&iobsr,2);
        if (nr<=0) {
            nr=nextobsf(&obss,&iobsr,2);
        }
        for (i=0;i<nu&&n<MAXOBS*2;i++) obs[n++]=obss.data[iobsu+i];
        for (i=0;i<nr&&n<MAXOBS*2;i++) obs[n++]=obss.data[iobsr+i];
        iobsu+=nu;
        
        /* update sbas corrections */
        while (isbs<sbss.n) {
            time=gpst2time(sbss.msgs[isbs].week,sbss.msgs[isbs].tow);
            
            if (getbitu(sbss.msgs[isbs].msg,8,6)!=9) { /* except for geo nav */
                sbsupdatecorr(sbss.msgs+isbs,&navs);
            }
            if (timediff(time,obs[0].time)>-1.0-DTTOL) break;
            isbs++;
        }
        /* update lex corrections */
        while (ilex<lexs.n) {
            if (lexupdatecorr(lexs.msgs+ilex,&navs,&time)) {
                if (timediff(time,obs[0].time)>-1.0-DTTOL) break;
            }
            ilex++;
        }
        /* update rtcm ssr corrections */
        if (*rtcm_file) {
            update_rtcm_ssr(obs[0].time);
        }
    }
    else { /* input backward data */
        if ((nu=nextobsb(&obss,&iobsu,1))<=0) return -1;
        if (popt->intpref) {
            for (;(nr=nextobsb(&obss,&iobsr,2))>0;iobsr-=nr)
                if (timediff(obss.data[iobsr].time,obss.data[iobsu].time)<DTTOL) break;
        }
        else {
            for (i=iobsr;(nr=nextobsb(&obss,&i,2))>0;iobsr=i,i-=nr)
                if (timediff(obss.data[i].time,obss.data[iobsu].time)<-DTTOL) break;
        }
        nr=nextobsb(&obss,&iobsr,2);
        for (i=0;i<nu&&n<MAXOBS*2;i++) obs[n++]=obss.data[iobsu-nu+1+i];
        for (i=0;i<nr&&n<MAXOBS*2;i++) obs[n++]=obss.data[iobsr-nr+1+i];
        iobsu-=nu;
        
        /* update sbas corrections */
        while (isbs>=0) {
            time=gpst2time(sbss.msgs[isbs].week,sbss.msgs[isbs].tow);
            
            if (getbitu(sbss.msgs[isbs].msg,8,6)!=9) { /* except for geo nav */
                sbsupdatecorr(sbss.msgs+isbs,&navs);
            }
            if (timediff(time,obs[0].time)<1.0+DTTOL) break;
            isbs--;
        }
        /* update lex corrections */
        while (ilex>=0) {
            if (lexupdatecorr(lexs.msgs+ilex,&navs,&time)) {
                if (timediff(time,obs[0].time)<1.0+DTTOL) break;
            }
            ilex--;
        }
    }
    return n;
}

2.3、if (!rtkpos(&rtk,obs,n,&navs)) continue;

输出当前历元观测数据:

traceobs(4,obs,n) 具体实现如下:

extern void traceobs(int level, const obsd_t *obs, int n)
{
    char str[64],id[16];
    int i;
    
    if (!fp_trace||level>level_trace) return;
    for (i=0;i<n;i++) {
        time2str(obs[i].time,str,3);
        satno2id(obs[i].sat,id);
        fprintf(fp_trace," (%2d) %s %-3s rcv%d %13.3f %13.3f %13.3f %13.3f %d %d %d %d %3.1f %3.1f\n",
              i+1,str,id,obs[i].rcv,obs[i].L[0],obs[i].L[1],obs[i].P[0],
              obs[i].P[1],obs[i].LLI[0],obs[i].LLI[1],obs[i].code[0],
              obs[i].code[1],obs[i].SNR[0]*0.25,obs[i].SNR[1]*0.25);
    }
    fflush(fp_trace);
}

输出的顺序为:

(序号)、时间、卫星号、rcv1?2、载波相位1、载波相位2、伪距1、伪距2、LLI1标识、LLI2标识、频率1的obscodes顺序、频率2的obscodes顺序、信噪比1*0.25、信噪比2*0.25

示例如下:

2.3.1、pntpos

1、单点定位之卫星位置、速度、钟差;.trace输出

单点定位中,首先计算卫星位置、速度、钟差;

(1)先计算卫星钟差;包括遍历星历,选择星历;

(2)计算卫星位置;包括查找对应卫星导航系统,解码星历;遍历星历,选择星历;

(3)再次计算卫星位置;用于计算卫星速度;

.trace中的输出为:不断循环

3 satposs : teph=2019/04/01 00:00:00.000 n=10 ephopt=0
4 ephclk  : time=2019/03/31 23:59:59.924 sat=10
4 seleph  : time=2019/04/01 00:00:00.000 sat=10 iode=-1
4 eph2clk : time=2019/03/31 23:59:59.924 sat=10
4 satpos  : time=2019/03/31 23:59:59.924 sat=10 ephopt=0
4 ephpos  : time=2019/03/31 23:59:59.924 sat=10 iode=-1
4 seleph  : time=2019/04/01 00:00:00.000 sat=10 iode=-1
4 eph2pos : time=2019/03/31 23:59:59.924 sat=10
4 kepler: sat=10 e= 0.00446 n= 3 del= 0.000e+00
4 eph2pos : time=2019/03/31 23:59:59.925 sat=10
4 kepler: sat=10 e= 0.00446 n= 3 del= 0.000e+00

 (4)输出卫星相关信息:顺序为:

卫星发射信号时间、卫星号、卫星ECEF下X、Y、Z位置、卫星钟差/m、卫星星历、钟差方差(sat position and clock error variances (m^2))、卫星健康信息(sat health flag (-1:correction not available))

2、单点定位之利用伪距计算接收机位置;.trace输出

实现函数:estpos

static int estpos(const obsd_t *obs, int n, const double *rs, const double *dts,
                  const double *vare, const int *svh, const nav_t *nav,
                  const prcopt_t *opt, sol_t *sol, double *azel, int *vsat,
                  double *resp, char *msg)

(1)首先计算伪距残差:rescode

        /* pseudorange residuals */ //ns 为参与定位的卫星的个数
        nv=rescode(i,obs,n,rs,dts,vare,svh,nav,x,opt,v,H,var,azel,vsat,resp,
                   &ns);

在rescode函数中,输出大部分信息,信息的输出与设置有关

首先输出:    trace(3,"resprng : n=%d\n",n);

然后 : while(卫星个数)

{

4 ionocorr: time=2019/04/01 00:00:00.000 opt=1 sat=10 pos=-90.000 0.000 azel=0.000 90.000
4 tropcorr: time=2019/04/01 00:00:00.000 opt=1 pos=-90.000 0.000 azel=0.000 90.000
4 sat=10 azel=  0.0 90.0 res=-3608726.259 sig=2.471
4 ionocorr: time=2019/04/01 00:00:00.000 opt=1 sat=15 pos=-90.000 0.000 azel=0.000 90.000
4 tropcorr: time=2019/04/01 00:00:00.000 opt=1 pos=-90.000 0.000 azel=0.000 90.000
4 sat=15 azel=  0.0 90.0 res=-1565446.211 sig=2.471

注释:trace(4,"sat=%2d azel=%5.1f %4.1f res=%7.3f sig=%5.3f\n",obs[i].sat,
              azel[i*2]*R2D,azel[1+i*2]*R2D,resp[i],sqrt(var[nv-1]));
信息为:方位角、高度角、伪距残差、标准差

};

同时在,estpos中,对单点定位有一个迭代计算的过程:

 for (i=0;i<MAXITR;i++)

{

循环输出2.3.2;直到每次迭代的量小于阈值;

再加上:

trace(3,"valsol  : n=%d nv=%d\n",n,nv); // validate solution

}

3、单点定位之利用多普勒计算接收机速度;.trace输出

2.3.2 PMODE_SINGLE

    if (opt->mode==PMODE_SINGLE) {
        outsolstat(rtk);
        return 1;     可以看到,函数执行返回上一级!
    }

.trace文件中输出:outsolstat;

继续执行,输出

迭代循环输出……直到终止!

3 valsol  : n=9 nv=11
3 estvel  : n=9
3 resdop  : n=9
3 resdop  : n=9
3 outsolstat:
3 outsol  :
3 outsols :
3 outpos  :
3 infunc  : revs=0 iobsu=5800 iobsr=5800 isbs=0
3 rtkfree :
3 freeobsnav:
3 freepreceph:
3 free_rtcm:
3 closeses:
3 closegoid:
3 rtkclosestat:

附上三个文件.pos、.stat、.trace 希望对大家有帮助!

RTKLIB代码在VS下调试输出pos.trace.stat文件指南.zip

 

  • 18
    点赞
  • 100
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
http.c是goahead web服务器的核心文件之一,主要负责处理HTTP请求和响应。以下是http.c文件源码解析: 1. 首先,http.c文件包含了一些必要的头文件,例如<sys/stat.h>和<fcntl.h>等。这些头文件提供了一些系统级别的函数和结构体。 2. 接着,http.c中定义了一些常量、宏和全局变量。例如,HTTP请求方法的枚举类型、HTTP响应状态码的宏定义、HTTP请求头部的结构体等。 3. 然后,http.c中定义了一些函数,这些函数负责处理HTTP请求和响应。例如,processHttpRequest()函数用于处理HTTP请求,sendHttpResponse()函数用于发送HTTP响应,parseFirstLine()函数用于解析HTTP请求的第一行等。 4. 在processHttpRequest()函数中,首先解析HTTP请求的第一行,然后解析HTTP请求头部,最后根据HTTP请求方法调用不同的处理函数。例如,如果是GET方法,就调用processGetRequest()函数处理请求。 5. 在processGetRequest()函数中,首先解析HTTP请求的路径,然后判断该路径是否合法,最后打开文件并发送HTTP响应。如果文件无法打开或者发送失败,就发送相应的错误响应。 6. 在sendHttpResponse()函数中,首先根据HTTP响应状态码设置响应头部,然后将响应头部和主体发送给客户端。 7. 最后,在main()函数中,启动goahead web服务器,并监听指定的端口号,等待客户端连接。 以上就是http.c文件源码解析

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值