/* read obs and nav data -----------------------------------------------------*/ static int readobsnav(gtime_t ts, gtime_t te, double ti, char **infile, const int *index, int n, const prcopt_t *prcopt, obs_t *obs, nav_t *nav, sta_t *sta) { int i,j,ind=0,nobs=0,rcv=1; trace(3,"readobsnav: ts=%s n=%d\n",time_str(ts,0),n); obs->data=NULL; obs->n =obs->nmax =0; nav->eph =NULL; nav->n =nav->nmax =0; nav->geph=NULL; nav->ng=nav->ngmax=0; nav->seph=NULL; nav->ns=nav->nsmax=0; nepoch=0; for (i=0;i<n;i++) { if (checkbrk("")) return 0; if (index[i]!=ind) { if (obs->n>nobs) rcv++; ind=index[i]; nobs=obs->n; } /* read rinex obs and nav file */ if (readrnxt(infile[i],rcv,ts,te,ti,prcopt->rnxopt[rcv<=1?0:1],obs,nav, rcv<=2?sta+rcv-1:NULL)<0) { checkbrk("error : insufficient memory"); trace(1,"insufficient memory\n"); return 0; } } if (obs->n<=0) { checkbrk("error : no obs data"); trace(1,"no obs data\n"); return 0; } if (nav->n<=0&&nav->ng<=0&&nav->ns<=0) { checkbrk("error : no nav data"); trace(1,"no nav data\n"); return 0; } /* sort observation data */ nepoch=sortobs(obs); /* delete duplicated ephemeris */ uniqnav(nav); /* set time span for progress display */ if (ts.time==0||te.time==0) { for (i=0; i<obs->n;i++) if (obs->data[i].rcv==1) break; for (j=obs->n-1;j>=0;j--) if (obs->data[j].rcv==1) break; if (i<j) { if (ts.time==0) ts=obs->data[i].time; if (te.time==0) te=obs->data[j].time; settspan(ts,te); } } return 1; }
/* execute processing session for each base station --------------------------*/ static int execses_b(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, const char *rov, const char *base) { gtime_t t0={0}; int i,stat=0; char *ifile[MAXINFILE],ofile[1024],*base_,*p,*q,s[64]; trace(3,"execses_b: n=%d outfile=%s\n",n,outfile); /* read prec ephemeris and sbas data */ readpreceph(infile,n,popt,&navs,&sbss,&lexs); for (i=0;i<n;i++) if (strstr(infile[i],"%b")) break; if (i<n) { /* include base station keywords */ if (!(base_=(char *)malloc(strlen(base)+1))) { freepreceph(&navs,&sbss,&lexs); return 0; } strcpy(base_,base); for (i=0;i<n;i++) { if (!(ifile[i]=(char *)malloc(1024))) { free(base_); for (;i>=0;i--) free(ifile[i]); freepreceph(&navs,&sbss,&lexs); return 0; } } for (p=base_;;p=q+1) { /* for each base station */ if ((q=strchr(p,' '))) *q='\0'; if (*p) { strcpy(proc_base,p); if (ts.time) time2str(ts,s,0); else *s='\0'; if (checkbrk("reading : %s",s)) { stat=1; break; } for (i=0;i<n;i++) reppath(infile[i],ifile[i],t0,"",p); reppath(outfile,ofile,t0,"",p); stat=execses_r(ts,te,ti,popt,sopt,fopt,flag,ifile,index,n,ofile,rov); } if (stat==1||!q) break; } free(base_); for (i=0;i<n;i++) free(ifile[i]); } else { stat=execses_r(ts,te,ti,popt,sopt,fopt,flag,infile,index,n,outfile,rov); } /* free prec ephemeris and sbas data */ freepreceph(&navs,&sbss,&lexs); return stat; }
/* execute processing session for each rover ---------------------------------*/ static int execses_r(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, const char *rov) { gtime_t t0={0}; int i,stat=0; char *ifile[MAXINFILE],ofile[1024],*rov_,*p,*q,s[64]=""; trace(3,"execses_r: n=%d outfile=%s\n",n,outfile); for (i=0;i<n;i++) if (strstr(infile[i],"%r")) break; if (i<n) { /* include rover keywords */ if (!(rov_=(char *)malloc(strlen(rov)+1))) return 0; strcpy(rov_,rov); for (i=0;i<n;i++) { if (!(ifile[i]=(char *)malloc(1024))) { free(rov_); for (;i>=0;i--) free(ifile[i]); return 0; } } for (p=rov_;;p=q+1) { /* for each rover */ if ((q=strchr(p,' '))) *q='\0'; if (*p) { strcpy(proc_rov,p); if (ts.time) time2str(ts,s,0); else *s='\0'; if (checkbrk("reading : %s",s)) { stat=1; break; } for (i=0;i<n;i++) reppath(infile[i],ifile[i],t0,p,""); reppath(outfile,ofile,t0,p,""); /* execute processing session */ stat=execses(ts,te,ti,popt,sopt,fopt,flag,ifile,index,n,ofile); } if (stat==1||!q) break; } free(rov_); for (i=0;i<n;i++) free(ifile[i]); } else { /* execute processing session */ stat=execses(ts,te,ti,popt,sopt,fopt,flag,infile,index,n,outfile); } return stat; }
/* input obs data, navigation messages and sbas correction -------------------*/ static int inputobs(obsd_t *obs, int solq, const prcopt_t *popt) { gtime_t time={0}; char path[1024]; 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 */ if ((nu=nextobsf(&obss,&iobsu,1))<=0) return -1; if (popt->intpref) { 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) if (timediff(obss.data[i].time,obss.data[iobsu].time)>DTTOL) break; } nr=nextobsf(&obss,&iobsr,2); for (i=0;i<nu&&n<MAXOBS;i++) obs[n++]=obss.data[iobsu+i]; for (i=0;i<nr&&n<MAXOBS;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 corrections */ if (*rtcm_file) { /* open or swap rtcm file */ reppath(rtcm_file,path,obs[0].time,"",""); if (strcmp(path,rtcm_path)) { strcpy(rtcm_path,path); if (fp_rtcm) fclose(fp_rtcm); fp_rtcm=fopen(path,"rb"); if (fp_rtcm) { rtcm.time=obs[0].time; input_rtcm3f(&rtcm,fp_rtcm); trace(2,"rtcm file open: %s\n",path); } } if (fp_rtcm) { while (timediff(rtcm.time,obs[0].time)<0.0) { if (input_rtcm3f(&rtcm,fp_rtcm)<-1) break; } for (i=0;i<MAXSAT;i++) navs.ssr[i]=rtcm.ssr[i]; } } } 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;i++) obs[n++]=obss.data[iobsu-nu+1+i]; for (i=0;i<nr&&n<MAXOBS;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; }
/* post-processing positioning ------------------------------------------------- * post-processing positioning * args : gtime_t ts I processing start time (ts.time==0: no limit) * : gtime_t te I processing end time (te.time==0: no limit) * double ti I processing interval (s) (0:all) * double tu I processing unit time (s) (0:all) * prcopt_t *popt I processing options * solopt_t *sopt I solution options * filopt_t *fopt I file options * char **infile I input files (see below) * int n I number of input files * char *outfile I output file ("":stdout, see below) * char *rov I rover id list (separated by " ") * char *base I base station id list (separated by " ") * return : status (0:ok,0>:error,1:aborted) * notes : input files should contain observation data, navigation data, precise * ephemeris/clock (optional), sbas log file (optional), ssr message * log file (optional) and tec grid file (optional). only the first * observation data file in the input files is recognized as the rover * data. * * the type of an input file is recognized by the file extention as ] * follows: * .sp3,.SP3,.eph*,.EPH*: precise ephemeris (sp3c) * .sbs,.SBS,.ems,.EMS : sbas message log files (rtklib or ems) * .lex,.LEX : qzss lex message log files * .rtcm3,.RTCM3 : ssr message log files (rtcm3) * .*i,.*I : tec grid files (ionex) * others : rinex obs, nav, gnav, hnav, qnav or clock * * inputs files can include wild-cards (*). if an file includes * wild-cards, the wild-card expanded multiple files are used. * * inputs files can include keywords. if an file includes keywords, * the keywords are replaced by date, time, rover id and base station * id and multiple session analyses run. refer reppath() for the * keywords. * * the output file can also include keywords. if the output file does * not include keywords. the results of all multiple session analyses * are output to a single output file. * * ssr corrections are valid only for forward estimation. *-----------------------------------------------------------------------------*/ extern int postpos(gtime_t ts, gtime_t te, double ti, double tu, const prcopt_t *popt, const solopt_t *sopt, const filopt_t *fopt, char **infile, int n, char *outfile, const char *rov, const char *base) { gtime_t tts,tte,ttte; double tunit,tss; int i,j,k,nf,stat=0,week,flag=1,index[MAXINFILE]={0}; char *ifile[MAXINFILE],ofile[1024],*ext; trace(3,"postpos : ti=%.0f tu=%.0f n=%d outfile=%s\n",ti,tu,n,outfile); /* open processing session */ if (!openses(popt,sopt,fopt,&navs,&pcvss,&pcvsr)) return -1; if (ts.time!=0&&te.time!=0&&tu>=0.0) { if (timediff(te,ts)<0.0) { showmsg("error : no period"); closeses(&navs,&pcvss,&pcvsr); return 0; } for (i=0;i<MAXINFILE;i++) { if (!(ifile[i]=(char *)malloc(1024))) { for (;i>=0;i--) free(ifile[i]); closeses(&navs,&pcvss,&pcvsr); return -1; } } if (tu==0.0||tu>86400.0*MAXPRCDAYS) tu=86400.0*MAXPRCDAYS; settspan(ts,te); tunit=tu<86400.0?tu:86400.0; tss=tunit*(int)floor(time2gpst(ts,&week)/tunit); for (i=0;;i++) { /* for each periods */ tts=gpst2time(week,tss+i*tu); tte=timeadd(tts,tu-DTTOL); if (timediff(tts,te)>0.0) break; if (timediff(tts,ts)<0.0) tts=ts; if (timediff(tte,te)>0.0) tte=te; strcpy(proc_rov ,""); strcpy(proc_base,""); if (checkbrk("reading : %s",time_str(tts,0))) { stat=1; break; } for (j=k=nf=0;j<n;j++) { ext=strrchr(infile[j],'.'); if (ext&&(!strcmp(ext,".rtcm3")||!strcmp(ext,".RTCM3"))) { strcpy(ifile[nf++],infile[j]); } else { /* include next day precise ephemeris or rinex brdc nav */ ttte=tte; if (ext&&(!strcmp(ext,".sp3")||!strcmp(ext,".SP3")|| !strcmp(ext,".eph")||!strcmp(ext,".EPH"))) { ttte=timeadd(ttte,3600.0); } else if (strstr(infile[j],"brdc")) { ttte=timeadd(ttte,7200.0); } nf+=reppaths(infile[j],ifile+nf,MAXINFILE-nf,tts,ttte,"",""); } while (k<nf) index[k++]=j; if (nf>=MAXINFILE) { trace(2,"too many input files. trancated\n"); break; } } if (!reppath(outfile,ofile,tts,"","")&&i>0) flag=0; /* execute processing session */ stat=execses_b(tts,tte,ti,popt,sopt,fopt,flag,ifile,index,nf,ofile, rov,base); if (stat==1) break; } for (i=0;i<MAXINFILE;i++) free(ifile[i]); } else if (ts.time!=0) { for (i=0;i<n&&i<MAXINFILE;i++) { if (!(ifile[i]=(char *)malloc(1024))) { for (;i>=0;i--) free(ifile[i]); return -1; } reppath(infile[i],ifile[i],ts,"",""); index[i]=i; } reppath(outfile,ofile,ts,"",""); /* execute processing session */ stat=execses_b(ts,te,ti,popt,sopt,fopt,1,ifile,index,n,ofile,rov, base); for (i=0;i<n&&i<MAXINFILE;i++) free(ifile[i]); } else { for (i=0;i<n;i++) index[i]=i; /* execute processing session */ stat=execses_b(ts,te,ti,popt,sopt,fopt,1,infile,index,n,outfile,rov, base); } /* close processing session */ closeses(&navs,&pcvss,&pcvsr); return stat; }
/* 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; char str[32]; 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 */ if ((nu=nextobsf(&obss,&iobsu,1))<=0) return -1; if (popt->intpref) { 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) if (timediff(obss.data[i].time,obss.data[iobsu].time)>DTTOL) break; } nr=nextobsf(&obss,&iobsr,2); for (i=0;i<nu&&n<MAXOBS;i++) obs[n++]=obss.data[iobsu+i]; for (i=0;i<nr&&n<MAXOBS;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 corrections */ if (fp_rtcm) { if (rtcm.time.time==0) rtcm.time=obs[0].time; #if 1 while (timediff(rtcm.time,obs[0].time)<-1.0) { #else while (timediff(rtcm.time,obs[0].time)<5.0) { #endif if (input_rtcm3f(&rtcm,fp_rtcm)==-2) break; } for (i=0;i<MAXSAT;i++) navs.ssr[i]=rtcm.ssr[i]; } } 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;i++) obs[n++]=obss.data[iobsu-nu+1+i]; for (i=0;i<nr&&n<MAXOBS;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; } /* process positioning -------------------------------------------------------*/ static void procpos(FILE *fp, const prcopt_t *popt, const solopt_t *sopt, int mode) { gtime_t time={0}; sol_t sol={{0}}; rtk_t rtk; obsd_t obs[MAXOBS]; double rb[3]={0}; int i,nobs,n,solstatic,pri[]={0,1,2,3,4,5,1,6}; trace(3,"procpos : mode=%d\n",mode); solstatic=sopt->solstatic&& (popt->mode==PMODE_STATIC||popt->mode==PMODE_PPP_STATIC); rtkinit(&rtk,popt); while ((nobs=inputobs(obs,rtk.sol.stat,popt))>=0) { /* exclude satellites */ for (i=n=0;i<nobs;i++) { if ((satsys(obs[i].sat,NULL)&popt->navsys)&& popt->exsats[obs[i].sat-1]!=1) obs[n++]=obs[i]; } if (n<=0) continue; if (!rtkpos(&rtk,obs,n,&navs)) continue; if (mode==0) { /* forward/backward */ if (!solstatic) { outsol(fp,&rtk.sol,rtk.rb,sopt); } else if (time.time==0||pri[rtk.sol.stat]<=pri[sol.stat]) { sol=rtk.sol; for (i=0;i<3;i++) rb[i]=rtk.rb[i]; if (time.time==0||timediff(rtk.sol.time,time)<0.0) { time=rtk.sol.time; } } } else if (!revs) { /* combined-forward */ if (isolf>=nepoch) return; solf[isolf]=rtk.sol; for (i=0;i<3;i++) rbf[i+isolf*3]=rtk.rb[i]; isolf++; } else { /* combined-backward */ if (isolb>=nepoch) return; solb[isolb]=rtk.sol; for (i=0;i<3;i++) rbb[i+isolb*3]=rtk.rb[i]; isolb++; } } if (mode==0&&solstatic&&time.time!=0.0) { sol.time=time; outsol(fp,&sol,rb,sopt); } rtkfree(&rtk); }