diff --git a/src/options.c b/src/options.c index 5241fd941abfdd79d8609cf580e5c0cae5672889..104b5596401ded8616bd8b6b37299a175d17e04d 100644 --- a/src/options.c +++ b/src/options.c @@ -47,6 +47,7 @@ static char snrmask_[NFREQ][1024]; #define EPHOPT "0:brdc,1:precise,2:brdc+sbas,3:brdc+ssrapc,4:brdc+ssrcom" #define NAVOPT "1:gps+2:sbas+4:glo+8:gal+16:qzs+32:comp" #define GAROPT "0:off,1:on,2:autocal,3:fix-and-hold" +#define WEIGHTOPT "0:elevation,1:snr" #define SOLOPT "0:llh,1:xyz,2:enu,3:nmea" #define TSYOPT "0:gpst,1:utc,2:jst" #define TFTOPT "0:tow,1:hms" @@ -87,7 +88,7 @@ EXPORT opt_t sysopts[]={ {"pos2-armode", 3, (void *)&prcopt_.modear, ARMOPT }, {"pos2-gloarmode", 3, (void *)&prcopt_.glomodear, GAROPT }, {"pos2-bdsarmode", 3, (void *)&prcopt_.bdsmodear, SWTOPT }, - {"pos2-arfilter", 3, (void *)&prcopt_.arfilter, SWTOPT }, + {"pos2-arfilter", 3, (void *)&prcopt_.arfilter, SWTOPT }, {"pos2-arthres", 1, (void *)&prcopt_.thresar[0], "" }, {"pos2-arthres1", 1, (void *)&prcopt_.thresar[1], "" }, {"pos2-arthres2", 1, (void *)&prcopt_.thresar[2], "" }, @@ -96,10 +97,10 @@ EXPORT opt_t sysopts[]={ {"pos2-varholdamb", 1, (void *)&prcopt_.varholdamb, "cyc^2"}, {"pos2-gainholdamb",1, (void *)&prcopt_.gainholdamb,"" }, {"pos2-arlockcnt", 0, (void *)&prcopt_.minlock, "" }, - {"pos2-minfixsats", 0, (void *)&prcopt_.minfixsats, "" }, - {"pos2-minholdsats",0, (void *)&prcopt_.minholdsats,"" }, + {"pos2-minfixsats", 0, (void *)&prcopt_.minfixsats, "" }, + {"pos2-minholdsats",0, (void *)&prcopt_.minholdsats,"" }, {"pos2-mindropsats",0, (void *)&prcopt_.mindropsats,"" }, - {"pos2-rcvstds", 3, (void *)&prcopt_.rcvstds, SWTOPT }, + {"pos2-rcvstds", 3, (void *)&prcopt_.rcvstds, SWTOPT }, {"pos2-arelmask", 1, (void *)&elmaskar_, "deg" }, {"pos2-arminfix", 0, (void *)&prcopt_.minfix, "" }, {"pos2-armaxiter", 0, (void *)&prcopt_.armaxiter, "" }, @@ -132,12 +133,14 @@ EXPORT opt_t sysopts[]={ {"out-nmeaintv2", 1, (void *)&solopt_.nmeaintv[1],"s" }, {"out-outstat", 3, (void *)&solopt_.sstat, STSOPT }, + {"stats-weightmode",3, (void *)&prcopt_.weightmode, WEIGHTOPT}, {"stats-eratio1", 1, (void *)&prcopt_.eratio[0], "" }, {"stats-eratio2", 1, (void *)&prcopt_.eratio[1], "" }, {"stats-errphase", 1, (void *)&prcopt_.err[1], "m" }, {"stats-errphaseel",1, (void *)&prcopt_.err[2], "m" }, {"stats-errphasebl",1, (void *)&prcopt_.err[3], "m/10km"}, {"stats-errdoppler",1, (void *)&prcopt_.err[4], "Hz" }, + {"stats-snrmax", 1, (void *)&prcopt_.err[5], "dB.Hz"}, {"stats-stdbias", 1, (void *)&prcopt_.std[0], "m" }, {"stats-stdiono", 1, (void *)&prcopt_.std[1], "m" }, {"stats-stdtrop", 1, (void *)&prcopt_.std[2], "m" }, diff --git a/src/pntpos.c b/src/pntpos.c index bbf8d90a8286ae84c079b77852ef40973890dccd..630cee04a8153c133a56170d6a2e56895f8ccc26 100644 --- a/src/pntpos.c +++ b/src/pntpos.c @@ -23,6 +23,7 @@ /* constants -----------------------------------------------------------------*/ #define SQR(x) ((x)*(x)) +#define MAX(x,y) ((x)>=(y)?(x):(y)) #define NX (4+3) /* # of estimated parameters */ @@ -35,13 +36,32 @@ #define REL_HUMI 0.7 /* relative humidity for saastamoinen model */ /* pseudorange measurement error variance ------------------------------------*/ -static double varerr(const prcopt_t *opt, double el, int sys) +static double varerr(const prcopt_t *opt, double el, double snr_rover, int sys) { - double fact,varr; - fact=sys==SYS_GLO?EFACT_GLO:(sys==SYS_SBS?EFACT_SBS:EFACT_GPS); - varr=SQR(opt->err[0])*(SQR(opt->err[1])+SQR(opt->err[2])/sin(el)); - if (opt->ionoopt==IONOOPT_IFLC) varr*=SQR(3.0); /* iono-free */ - return SQR(fact)*varr; + double a, b, snr_max; + double fact = opt->err[0]; + double sinel = sin(el); + + switch (sys) { + case SYS_GPS: fact *= EFACT_GPS; break; + case SYS_GLO: fact *= EFACT_GLO; break; + case SYS_SBS: fact *= EFACT_SBS; break; + default: fact *= EFACT_GPS; break; + } + + a = fact * opt->err[1]; + b = fact * opt->err[2]; + snr_max = opt->err[5]; + + /* note: SQR(3.0) is approximated scale factor for error variance + in the case of iono-free combination */ + fact = (opt->ionoopt == IONOOPT_IFLC) ? SQR(3.0) : 1.0; + switch (opt->weightmode) { + case WEIGHTOPT_ELEVATION: return fact * ( SQR(a) + SQR(b / sinel) ); + case WEIGHTOPT_SNR : return fact * SQR(a) * pow(10, 0.1 * MAX(snr_max - snr_rover, 0)); + ; + default: return 0; + } } /* get tgd parameter (m) -----------------------------------------------------*/ static double gettgd(int sat, const nav_t *nav) @@ -198,10 +218,11 @@ extern int tropcorr(gtime_t time, const nav_t *nav, const double *pos, static int rescode(int iter, const obsd_t *obs, int n, const double *rs, const double *dts, const double *vare, const int *svh, const nav_t *nav, const double *x, const prcopt_t *opt, - double *v, double *H, double *var, double *azel, int *vsat, - double *resp, int *ns) + const ssat_t *ssat, double *v, double *H, double *var, + double *azel, int *vsat, double *resp, int *ns) { double r,dion,dtrp,vmeas,vion,vtrp,rr[3],pos[3],dtr,e[3],P,lam_L1; + double snr_rover = (ssat) ? 0.25 * ssat->snr_rover[0] : opt->err[5]; int i,j,nv=0,sys,mask[4]={0}; trace(3,"resprng : n=%d\n",n); @@ -261,7 +282,7 @@ static int rescode(int iter, const obsd_t *obs, int n, const double *rs, vsat[i]=1; resp[i]=v[nv]; (*ns)++; /* error variance */ - var[nv++]=varerr(opt,azel[1+i*2],sys)+vare[i]+vmeas+vion+vtrp; + var[nv++]=varerr(opt,azel[1+i*2],snr_rover,sys)+vare[i]+vmeas+vion+vtrp; 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])); @@ -308,8 +329,8 @@ static int valsol(const double *azel, const int *vsat, int n, /* estimate receiver position ------------------------------------------------*/ 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) + const prcopt_t *opt, const ssat_t *ssat, sol_t *sol, double *azel, + int *vsat, double *resp, char *msg) { double x[NX]={0},dx[NX],Q[NX*NX],*v,*H,*var,sig; int i,j,k,info,stat,nv,ns; @@ -323,7 +344,7 @@ static int estpos(const obsd_t *obs, int n, const double *rs, const double *dts, for (i=0;i<MAXITR;i++) { /* pseudorange residuals */ - nv=rescode(i,obs,n,rs,dts,vare,svh,nav,x,opt,v,H,var,azel,vsat,resp, + nv=rescode(i,obs,n,rs,dts,vare,svh,nav,x,opt,ssat,v,H,var,azel,vsat,resp, &ns); if (nv<NX) { @@ -376,8 +397,8 @@ static int estpos(const obsd_t *obs, int n, const double *rs, const double *dts, /* raim fde (failure detection and exclution) -------------------------------*/ static int raim_fde(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) + const nav_t *nav, const prcopt_t *opt, const ssat_t *ssat, + sol_t *sol, double *azel, int *vsat, double *resp, char *msg) { obsd_t *obs_e; sol_t sol_e={{0}}; @@ -403,7 +424,7 @@ static int raim_fde(const obsd_t *obs, int n, const double *rs, svh_e[k++]=svh[j]; } /* estimate receiver position without a satellite */ - if (!estpos(obs_e,n-1,rs_e,dts_e,vare_e,svh_e,nav,opt,&sol_e,azel_e, + if (!estpos(obs_e,n-1,rs_e,dts_e,vare_e,svh_e,nav,opt,ssat,&sol_e,azel_e, vsat_e,resp_e,msg_e)) { trace(3,"raim_fde: exsat=%2d (%s)\n",obs[i].sat,msg); continue; @@ -556,6 +577,15 @@ extern int pntpos(const obsd_t *obs, int n, const nav_t *nav, rs=mat(6,n); dts=mat(2,n); var=mat(1,n); azel_=zeros(2,n); resp=mat(1,n); + if (ssat) { + for (i=0;i<MAXSAT;i++) { + ssat[i].snr_rover[0]=0; + ssat[i].snr_base[0] =0; + } + for (i=0;i<n;i++) + ssat[obs[i].sat-1].snr_rover[0]=obs[i].SNR[0]; + } + if (opt_.mode!=PMODE_SINGLE) { /* for precise positioning */ #if 0 opt_.sateph =EPHOPT_BRDC; @@ -567,11 +597,11 @@ extern int pntpos(const obsd_t *obs, int n, const nav_t *nav, satposs(sol->time,obs,n,nav,opt_.sateph,rs,dts,var,svh); /* estimate receiver position with pseudorange */ - stat=estpos(obs,n,rs,dts,var,svh,nav,&opt_,sol,azel_,vsat,resp,msg); + stat=estpos(obs,n,rs,dts,var,svh,nav,&opt_,ssat,sol,azel_,vsat,resp,msg); /* raim fde */ if (!stat&&n>=6&&opt->posopt[4]) { - stat=raim_fde(obs,n,rs,dts,var,svh,nav,&opt_,sol,azel_,vsat,resp,msg); + stat=raim_fde(obs,n,rs,dts,var,svh,nav,&opt_,ssat,sol,azel_,vsat,resp,msg); } /* estimate receiver velocity with doppler */ if (stat) estvel(obs,n,rs,dts,nav,&opt_,sol,azel_,vsat); @@ -584,12 +614,10 @@ extern int pntpos(const obsd_t *obs, int n, const nav_t *nav, ssat[i].vs=0; ssat[i].azel[0]=ssat[i].azel[1]=0.0; ssat[i].resp[0]=ssat[i].resc[0]=0.0; - ssat[i].snr[0]=0; } for (i=0;i<n;i++) { ssat[obs[i].sat-1].azel[0]=azel_[ i*2]; ssat[obs[i].sat-1].azel[1]=azel_[1+i*2]; - ssat[obs[i].sat-1].snr[0]=obs[i].SNR[0]; if (!vsat[i]) continue; ssat[obs[i].sat-1].vs=1; ssat[obs[i].sat-1].resp[0]=resp[i]; diff --git a/src/ppp.c b/src/ppp.c index bc48d2e9e60fc40e6f644fc047c03af4ffc44178..82317db56dd84811dac839105a7bdf88ea90a6c9 100644 --- a/src/ppp.c +++ b/src/ppp.c @@ -318,19 +318,39 @@ static int model_phw(gtime_t time, int sat, const char *type, int opt, return 1; } /* measurement error variance ------------------------------------------------*/ -static double varerr(int sat, int sys, double el, int freq, int type, - const prcopt_t *opt) +static double varerr(int sat, int sys, double el, double snr_rover, int freq, + int type, const prcopt_t *opt) { - double fact=1.0,sinel=sin(el); + double a, b, snr_max; + double fact = 1.0; + double sinel = sin(el); - if (type==1) fact*=opt->eratio[freq==0?0:1]; - fact*=sys==SYS_GLO?EFACT_GLO:(sys==SYS_SBS?EFACT_SBS:EFACT_GPS); + if (type == 1) fact *= opt->eratio[(freq == 0) ? 0 : 1]; - if (sys==SYS_GPS||sys==SYS_QZS) { - if (freq==2) fact*=EFACT_GPS_L5; /* GPS/QZS L5 error factor */ + switch (sys) { + case SYS_GPS: fact *= EFACT_GPS; break; + case SYS_GLO: fact *= EFACT_GLO; break; + case SYS_SBS: fact *= EFACT_SBS; break; + default: fact *= EFACT_GPS; break; + } + + if ( (sys == SYS_GPS) || (sys == SYS_QZS) ) { + if (freq==2) fact *= EFACT_GPS_L5; /* GPS/QZS L5 error factor */ + } + + a = fact * opt->err[1]; + b = fact * opt->err[2]; + snr_max = opt->err[5]; + + /* note: SQR(3.0) is approximated scale factor for error variance + in the case of iono-free combination */ + fact = (opt->ionoopt == IONOOPT_IFLC) ? SQR(3.0) : 1.0; + switch (opt->weightmode) { + case WEIGHTOPT_ELEVATION: return fact * ( SQR(a) + SQR(b / sinel) ); + case WEIGHTOPT_SNR : return fact * SQR(a) * pow(10, 0.1 * MAX(snr_max - snr_rover, 0)); + ; + default: return 0; } - if (opt->ionoopt==IONOOPT_IFLC) fact*=3.0; - return SQR(fact*opt->err[1])+SQR(fact*opt->err[2]/sinel); } /* initialize state and covariance -------------------------------------------*/ static void initx(rtk_t *rtk, double xi, double var, int i) @@ -1038,7 +1058,7 @@ static int ppp_res(int post, const obsd_t *obs, int n, const double *rs, else rtk->ssat[sat-1].resp[j/2]=v[nv]; /* variance */ - var[nv]=varerr(obs[i].sat,sys,azel[1+i*2],j/2,j%2,opt)+ + var[nv]=varerr(obs[i].sat,sys,azel[1+i*2],0.25*rtk->ssat[sat-1].snr_rover[j/2],j/2,j%2,opt)+ vart+SQR(C)*vari+var_rs[i]; if (sys==SYS_GLO&&j%2==1) var[nv]+=VAR_GLO_IFB; @@ -1126,7 +1146,8 @@ static void update_stat(rtk_t *rtk, const obsd_t *obs, int n, int stat) rtk->sol.dtr[1]=rtk->x[IC(1,opt)]-rtk->x[IC(0,opt)]; for (i=0;i<n&&i<MAXOBS;i++) for (j=0;j<opt->nf;j++) { - rtk->ssat[obs[i].sat-1].snr[j]=obs[i].SNR[j]; + rtk->ssat[obs[i].sat-1].snr_rover[j]=obs[i].SNR[j]; + rtk->ssat[obs[i].sat-1].snr_base[j] =0; } for (i=0;i<MAXSAT;i++) for (j=0;j<opt->nf;j++) { if (rtk->ssat[i].slip[j]&3) rtk->ssat[i].slipc[j]++; @@ -1170,8 +1191,12 @@ extern void pppos(rtk_t *rtk, const obsd_t *obs, int n, const nav_t *nav) rs=mat(6,n); dts=mat(2,n); var=mat(1,n); azel=zeros(2,n); - for (i=0;i<MAXSAT;i++) for (j=0;j<opt->nf;j++) rtk->ssat[i].fix[j]=0; - + for (i=0;i<MAXSAT;i++) for (j=0;j<opt->nf;j++) { + rtk->ssat[i].fix[j]=0; + rtk->ssat[obs[i].sat-1].snr_rover[j]=obs[i].SNR[j]; + rtk->ssat[obs[i].sat-1].snr_base[j] =0; + } + /* temporal update of ekf states */ udstate_ppp(rtk,obs,n,nav); diff --git a/src/rtkcmn.c b/src/rtkcmn.c index 8013b936bf533348d64bee2c75eeeb89ae5e4490..7316af5124384baa66bcd0dbaf68affc0c618490 100644 --- a/src/rtkcmn.c +++ b/src/rtkcmn.c @@ -197,8 +197,9 @@ const prcopt_t prcopt_default={ /* defaults processing options */ 0,1,0,0,1,0, /* rcvstds,armaxiter,estion,esttrop,dynamics,tidecorr */ 1,0,0,0,0, /* niter,codesmooth,intpref,sbascorr,sbassatsel */ 0,0, /* rovpos,refpos */ + WEIGHTOPT_ELEVATION, /* weightmode */ {300.0,300.0,300.0}, /* eratio[] */ - {100.0,0.003,0.003,0.0,1.0},/* err[] */ + {100.0,0.003,0.003,0.0,1.0,52.0}, /* err[] */ {30.0,0.03,0.3}, /* std[] */ {1E-4,1E-3,1E-4,1E-1,1E-2,0.0}, /* prn[] */ 5E-12, /* sclkstab */ diff --git a/src/rtklib.h b/src/rtklib.h index 80176d7d3fd5ea8566a6cb942332201904430558..988df473f3e3c7f5003918f6304a33e06b3adc7d 100644 --- a/src/rtklib.h +++ b/src/rtklib.h @@ -397,6 +397,9 @@ extern "C" { #define EPHOPT_SSRCOM 4 /* ephemeris option: broadcast + SSR_COM */ #define EPHOPT_LEX 5 /* ephemeris option: QZSS LEX ephemeris */ +#define WEIGHTOPT_ELEVATION 0 /* weighting option: elevation */ +#define WEIGHTOPT_SNR 1 /* weighting option: snr */ + #define ARMODE_OFF 0 /* AR mode: off */ #define ARMODE_CONT 1 /* AR mode: continuous */ #define ARMODE_INST 2 /* AR mode: instantaneous */ @@ -1092,11 +1095,13 @@ typedef struct { /* processing options type */ int refpos; /* base position for relative mode */ /* (0:pos in prcopt, 1:average of single pos, */ /* 2:read from file, 3:rinex header, 4:rtcm pos) */ + int weightmode; /* weighting option (WEIGHTOPT_??) */ double eratio[NFREQ]; /* code/phase error ratio */ - double err[5]; /* measurement error factor */ + double err[6]; /* measurement error factor */ /* [0]:reserved */ /* [1-3]:error factor a/b/c of phase (m) */ /* [4]:doppler frequency (hz) */ + /* [5]: snr max value (dB.Hz) */ double std[3]; /* initial-state std [0]bias,[1]iono [2]trop */ double prn[6]; /* process-noise std [0]bias,[1]iono [2]trop [3]acch [4]accv [5] pos */ double sclkstab; /* satellite clock stability (sec/sec) */ @@ -1209,9 +1214,10 @@ typedef struct { /* satellite status type */ double azel[2]; /* azimuth/elevation angles {az,el} (rad) */ double resp[NFREQ]; /* residuals of pseudorange (m) */ double resc[NFREQ]; /* residuals of carrier-phase (m) */ - double icbias[NFREQ]; /* glonass IC bias (cycles) */ + double icbias[NFREQ]; /* glonass IC bias (cycles) */ unsigned char vsat[NFREQ]; /* valid satellite flag */ - unsigned char snr [NFREQ]; /* signal strength (0.25 dBHz) */ + unsigned char snr_rover [NFREQ]; /* rover signal strength (0.25 dBHz) */ + unsigned char snr_base [NFREQ]; /* base signal strength (0.25 dBHz) */ unsigned char fix [NFREQ]; /* ambiguity fix flag (1:fix,2:float,3:hold) */ unsigned char slip[NFREQ]; /* cycle-slip flag */ unsigned char half[NFREQ]; /* half-cycle valid flag */ diff --git a/src/rtkpos.c b/src/rtkpos.c index ee3e84f8e310cfdca7a6d89ccc8cc461dbecb074..c2f38ef730ac79895101b9fdd9845e365bddfe91 100644 --- a/src/rtkpos.c +++ b/src/rtkpos.c @@ -49,6 +49,7 @@ #define SQR(x) ((x)*(x)) #define SQRT(x) ((x)<=0.0||(x)!=(x)?0.0:sqrt(x)) #define MIN(x,y) ((x)<=(y)?(x):(y)) +#define MAX(x,y) ((x)>=(y)?(x):(y)) #define ROUND(x) (int)floor((x)+0.5) #define VAR_POS SQR(30.0) /* initial variance of receiver pos (m^2) */ @@ -356,7 +357,7 @@ static void outsolstat(rtk_t *rtk,const nav_t *nav) k=IB(i+1,j,&rtk->opt); fprintf(fp_stat,"$SAT,%d,%.3f,%s,%d,%.1f,%.1f,%.4f,%.4f,%d,%.0f,%d,%d,%d,%d,%d,%d,%.2f,%.6f,%.5f,%.5f\n", week,tow,id,j+1,ssat->azel[0]*R2D,ssat->azel[1]*R2D, - ssat->resp[j],ssat->resc[j],ssat->vsat[j],ssat->snr[j]*0.25, + ssat->resp[j],ssat->resc[j],ssat->vsat[j],ssat->snr_rover[j]*0.25, ssat->fix[j],ssat->slip[j]&3,ssat->lock[j],ssat->outc[j], ssat->slipc[j],ssat->rejc[j],dgps?0:rtk->x[k], dgps?0:rtk->P[k+k*rtk->nx],nav->lam[i][j],ssat->icbias[j]); @@ -397,26 +398,37 @@ static double gfobs_L1L5(const obsd_t *obs, int i, int j, const double *lam) double pi=sdobs(obs,i,j,0)*lam[0],pj=sdobs(obs,i,j,2)*lam[2]; return pi==0.0||pj==0.0?0.0:pi-pj; } + /* single-differenced measurement error variance -----------------------------*/ -static double varerr(int sat, int sys, double el, double bl, double dt, int f, - const prcopt_t *opt, const obsd_t *obs) +static double varerr(int sat, int sys, double el, double snr_rover, double snr_base, + double bl, double dt, int f, const prcopt_t *opt, const obsd_t *obs) { - double a,b,c=opt->err[3]*bl/1E4,d=CLIGHT*opt->sclkstab*dt,fact=1.0; - double sinel=sin(el); - int i=sys==SYS_GLO?1:(sys==SYS_GAL?2:0),nf=NF(opt),frq,code; + double a, b, c = opt->err[3] * bl / 1E4; + double snr_max = opt->err[5]; + double d = CLIGHT * opt->sclkstab * dt; + double fact = 1.0; + double sinel = sin(el); + int i, nf = NF(opt), frq, code; frq=f%nf;code=f<nf?0:1; + + switch (sys) { + case SYS_GPS: i = 0; break; + case SYS_GLO: i = 1; break; + case SYS_GAL: i = 2; break; + default: i = 0; break; + } /* extended error model, not currently used */ - if (code&&opt->exterr.ena[0]) { /* code */ - a=opt->exterr.cerr[i][ frq*2]; - b=opt->exterr.cerr[i][1+frq*2]; - if (sys==SYS_SBS) {a*=EFACT_SBS; b*=EFACT_SBS;} + if (code && opt->exterr.ena[0]) { /* code */ + a = opt->exterr.cerr[i][ frq * 2]; + b = opt->exterr.cerr[i][1+frq * 2]; + if (sys == SYS_SBS) { a *= EFACT_SBS; b *= EFACT_SBS; } } - else if (!code&&opt->exterr.ena[1]) { /* phase */ - a=opt->exterr.perr[i][ frq*2]; - b=opt->exterr.perr[i][1+frq*2]; - if (sys==SYS_SBS) {a*=EFACT_SBS; b*=EFACT_SBS;} + else if (!code && opt->exterr.ena[1]) { /* phase */ + a = opt->exterr.perr[i][ frq * 2]; + b = opt->exterr.perr[i][1+frq * 2]; + if (sys == SYS_SBS) {a *= EFACT_SBS; b *= EFACT_SBS;} } else { /* normal error model */ if (opt->rcvstds&& obs->qualL[frq]!='\0'&&obs->qualP[frq]!='\0') { @@ -424,12 +436,28 @@ static double varerr(int sat, int sys, double el, double bl, double dt, int f, if (code) fact=opt->eratio[frq]*obs->qualP[frq]; else fact=obs->qualL[frq]; } else if (code) fact=opt->eratio[frq]; /* use err ratio only */ - if (fact<=0.0) fact=opt->eratio[0]; - fact*=sys==SYS_GLO?EFACT_GLO:(sys==SYS_SBS?EFACT_SBS:EFACT_GPS); - a=fact*opt->err[1]; - b=fact*opt->err[2]; + if (fact <= 0.0) fact = opt->eratio[0]; + switch (sys) { + case SYS_GPS: fact *= EFACT_GPS; break; + case SYS_GLO: fact *= EFACT_GLO; break; + case SYS_SBS: fact *= EFACT_SBS; break; + default: fact *= EFACT_GPS; break; + } + + a = fact * opt->err[1]; + b = fact * opt->err[2]; + } + + /* note: SQR(3.0) is approximated scale factor for error variance + in the case of iono-free combination */ + fact = (opt->ionoopt == IONOOPT_IFLC) ? SQR(3.0) : 1.0; + switch (opt->weightmode) { + case WEIGHTOPT_ELEVATION: return fact * 2.0 * ( SQR(a) + SQR(b / sinel) + SQR(c) ) + SQR(d); + case WEIGHTOPT_SNR : return fact * ( SQR(a) * + (pow(10, 0.1 * MAX(snr_max - snr_rover, 0)) + + pow(10, 0.1 * MAX(snr_max - snr_base, 0))) + SQR(c) ) + SQR(d); + default: return 0; } - return 2.0*(opt->ionoopt==IONOOPT_IFLC?3.0:1.0)*(a*a+b*b/sinel/sinel+c*c)+d*d; } /* baseline length -----------------------------------------------------------*/ static double baseline(const double *ru, const double *rb, double *dr) @@ -891,7 +919,10 @@ static void udstate(rtk_t *rtk, const obsd_t *obs, const int *sat, udpos(rtk,tt); /* temporal update of ionospheric parameters */ - if (rtk->opt.ionoopt>=IONOOPT_EST) { + if ( (rtk->opt.ionoopt == IONOOPT_EST) || (rtk->opt.ionoopt == IONOOPT_TEC) || + (rtk->opt.ionoopt == IONOOPT_QZS) || (rtk->opt.ionoopt == IONOOPT_LEX) || + (rtk->opt.ionoopt == IONOOPT_STEC) ) + { bl=baseline(rtk->x,rtk->rb,dr); udion(rtk,tt,bl,sat,ns); } @@ -1202,7 +1233,10 @@ static int ddres(rtk_t *rtk, const nav_t *nav, const obsd_t *obs, double dt, con - only used if kalman filter contains states for ION and TROP delays usually insignificant for short baselines (<10km)*/ for (i=0;i<ns;i++) { - if (opt->ionoopt>=IONOOPT_EST) { + if ( (rtk->opt.ionoopt == IONOOPT_EST) || (rtk->opt.ionoopt == IONOOPT_TEC) || + (rtk->opt.ionoopt == IONOOPT_QZS) || (rtk->opt.ionoopt == IONOOPT_LEX) || + (rtk->opt.ionoopt == IONOOPT_STEC) ) + { im[i]=(ionmapf(posu,azel+iu[i]*2)+ionmapf(posr,azel+ir[i]*2))/2.0; } if (opt->tropopt>=TROPOPT_EST) { @@ -1220,7 +1254,7 @@ static int ddres(rtk_t *rtk, const nav_t *nav, const obsd_t *obs, double dt, con /* find reference satellite with highest elevation, set to i */ for (i=-1,j=0;j<ns;j++) { sysi=rtk->ssat[sat[j]-1].sys; - if (!test_sys(sysi,m) || sysi==SYS_SBS) continue; + if (!test_sys(sysi,m) || sysi==SYS_SBS) continue; if (!validobs(iu[j],ir[j],f,nf,y)) continue; if (i<0||azel[1+iu[j]*2]>=azel[1+iu[i]*2]) i=j; } @@ -1336,9 +1370,15 @@ static int ddres(rtk_t *rtk, const nav_t *nav, const obsd_t *obs, double dt, con continue; } /* single-differenced measurement error variances */ - Ri[nv]=varerr(sat[i],sysi,azel[1+iu[i]*2],bl,dt,f,opt,&obs[iu[i]]); - Rj[nv]=varerr(sat[j],sysj,azel[1+iu[j]*2],bl,dt,f,opt,&obs[iu[j]]); - + Ri[nv] = varerr(sat[i], sysi, azel[1+iu[i]*2], + 0.25 * rtk->ssat[sat[i]-1].snr_rover[frq], + 0.25 * rtk->ssat[sat[i]-1].snr_base[frq], + bl, dt, f, opt,&obs[iu[i]]); + Rj[nv] = varerr(sat[j], sysj, azel[1+iu[j]*2], + 0.25 * rtk->ssat[sat[j]-1].snr_rover[frq], + 0.25 * rtk->ssat[sat[j]-1].snr_base[frq], + bl, dt, f, opt,&obs[iu[j]]); + /* set valid data flags */ if (opt->mode>PMODE_DGPS) { if (!code) rtk->ssat[sat[i]-1].vsat[frq]=rtk->ssat[sat[j]-1].vsat[frq]=1; @@ -1910,9 +1950,12 @@ static int relpos(rtk_t *rtk, const obsd_t *obs, int nu, int nr, /* init satellite status arrays */ for (i=0;i<MAXSAT;i++) { - rtk->ssat[i].sys=satsys(i+1,NULL); /* gps system */ - for (j=0;j<NFREQ;j++) rtk->ssat[i].vsat[j]=0; /* valid satellite */ - for (j=1;j<NFREQ;j++) rtk->ssat[i].snr [j]=0; + rtk->ssat[i].sys=satsys(i+1,NULL); /* gps system */ + for (j=0;j<NFREQ;j++) { + rtk->ssat[i].vsat[j]=0; /* valid satellite */ + rtk->ssat[i].snr_rover[j]=0; + rtk->ssat[i].snr_base[j] =0; + } } /* compute satellite positions, velocities and clocks */ satposs(time,obs,n,nav,opt->sateph,rs,dts,var,svh); @@ -1943,6 +1986,13 @@ static int relpos(rtk_t *rtk, const obsd_t *obs, int nu, int nr, trace(4,"x(0)="); tracemat(4,rtk->x,1,NR(opt),13,4); + for (i=0;i<ns;i++) for (j=0;j<nf;j++) { + + /* snr of base and rover receiver */ + rtk->ssat[sat[i]-1].snr_rover[j]=obs[iu[i]].SNR[j]; + rtk->ssat[sat[i]-1].snr_base[j] =obs[ir[i]].SNR[j]; + } + /* initialize Pp,xa to zero, xp to rtk->x */ xp=mat(rtk->nx,1); Pp=zeros(rtk->nx,rtk->nx); xa=mat(rtk->nx,1); matcpy(xp,rtk->x,rtk->nx,1); @@ -2116,11 +2166,6 @@ static int relpos(rtk_t *rtk, const obsd_t *obs, int nu, int nr, rtk->ssat[obs[i].sat-1].pt[obs[i].rcv-1][j]=obs[i].time; rtk->ssat[obs[i].sat-1].ph[obs[i].rcv-1][j]=obs[i].L[j]; } - for (i=0;i<ns;i++) for (j=0;j<nf;j++) { - - /* output snr of rover receiver */ - rtk->ssat[sat[i]-1].snr[j]=obs[iu[i]].SNR[j]; - } for (i=0;i<MAXSAT;i++) for (j=0;j<nf;j++) { /* Don't lose track of which sats were used to try and resolve the ambiguities */ /* if (rtk->ssat[i].fix[j]==2&&stat!=SOLQ_FIX) rtk->ssat[i].fix[j]=1; */ diff --git a/src/solution.c b/src/solution.c index 1fffddf27500d3eab5d24ac1829b65555b083cc0..5fc7a64c87ac75956939cb0817b123783f066c42 100644 --- a/src/solution.c +++ b/src/solution.c @@ -1405,7 +1405,7 @@ extern int outnmea_gsv(unsigned char *buff, const sol_t *sol, if (satsys(sats[k],&prn)==SYS_SBS) prn+=33-MINPRNSBS; az =ssat[sats[k]-1].azel[0]*R2D; if (az<0.0) az+=360.0; el =ssat[sats[k]-1].azel[1]*R2D; - snr=ssat[sats[k]-1].snr[0]*0.25; + snr=ssat[sats[k]-1].snr_rover[0]*0.25; p+=sprintf(p,",%02d,%02.0f,%03.0f,%02.0f",prn,el,az,snr); } else p+=sprintf(p,",,,,"); @@ -1430,7 +1430,7 @@ extern int outnmea_gsv(unsigned char *buff, const sol_t *sol, satsys(sats[k],&prn); prn+=64; /* 65-99 */ az =ssat[sats[k]-1].azel[0]*R2D; if (az<0.0) az+=360.0; el =ssat[sats[k]-1].azel[1]*R2D; - snr=ssat[sats[k]-1].snr[0]*0.25; + snr=ssat[sats[k]-1].snr_rover[0]*0.25; p+=sprintf(p,",%02d,%02.0f,%03.0f,%02.0f",prn,el,az,snr); } else p+=sprintf(p,",,,,"); @@ -1455,7 +1455,7 @@ extern int outnmea_gsv(unsigned char *buff, const sol_t *sol, satsys(sats[k],&prn); /* 1-36 */ az =ssat[sats[k]-1].azel[0]*R2D; if (az<0.0) az+=360.0; el =ssat[sats[k]-1].azel[1]*R2D; - snr=ssat[sats[k]-1].snr[0]*0.25; + snr=ssat[sats[k]-1].snr_rover[0]*0.25; p+=sprintf(p,",%02d,%02.0f,%03.0f,%02.0f",prn,el,az,snr); } else p+=sprintf(p,",,,,");