/* sbas ionospheric delay correction ------------------------------------------- * compute sbas ionosphric delay correction * args : gtime_t time I time * nav_t *nav I navigation data * double *pos I receiver position {lat,lon,height} (rad/m) * double *azel I satellite azimuth/elavation angle (rad) * double *delay O slant ionospheric delay (L1) (m) * double *var O variance of ionospheric delay (m^2) * return : status (1:ok, 0:no correction) * notes : before calling the function, sbas ionosphere correction parameters * in navigation data (nav->sbsion) must be set by callig * sbsupdatecorr() *-----------------------------------------------------------------------------*/ extern int sbsioncorr(gtime_t time, const nav_t *nav, const double *pos, const double *azel, double *delay, double *var) { const double re=6378.1363,hion=350.0; int i,err=0; double fp,posp[2],x=0.0,y=0.0,t,w[4]={0}; const sbsigp_t *igp[4]={0}; /* {ws,wn,es,en} */ trace(4,"sbsioncorr: pos=%.3f %.3f azel=%.3f %.3f\n",pos[0]*R2D,pos[1]*R2D, azel[0]*R2D,azel[1]*R2D); *delay=*var=0.0; if (pos[2]<-100.0||azel[1]<=0) return 1; /* ipp (ionospheric pierce point) position */ fp=ionppp(pos,azel,re,hion,posp); /* search igps around ipp */ searchigp(time,posp,nav->sbsion,igp,&x,&y); /* weight of igps */ if (igp[0]&&igp[1]&&igp[2]&&igp[3]) { w[0]=(1.0-x)*(1.0-y); w[1]=(1.0-x)*y; w[2]=x*(1.0-y); w[3]=x*y; } else if (igp[0]&&igp[1]&&igp[2]) { w[1]=y; w[2]=x; if ((w[0]=1.0-w[1]-w[2])<0.0) err=1; } else if (igp[0]&&igp[2]&&igp[3]) { w[0]=1.0-x; w[3]=y; if ((w[2]=1.0-w[0]-w[3])<0.0) err=1; } else if (igp[0]&&igp[1]&&igp[3]) { w[0]=1.0-y; w[3]=x; if ((w[1]=1.0-w[0]-w[3])<0.0) err=1; } else if (igp[1]&&igp[2]&&igp[3]) { w[1]=1.0-x; w[2]=1.0-y; if ((w[3]=1.0-w[1]-w[2])<0.0) err=1; } else err=1; if (err) { trace(2,"no sbas iono correction: lat=%3.0f lon=%4.0f\n",posp[0]*R2D, posp[1]*R2D); return 0; } for (i=0;i<4;i++) { if (!igp[i]) continue; t=timediff(time,igp[i]->t0); *delay+=w[i]*igp[i]->delay; *var+=w[i]*varicorr(igp[i]->give)*9E-8*fabs(t); } *delay*=fp; *var*=fp*fp; trace(5,"sbsioncorr: dion=%7.2f sig=%7.2f\n",*delay,sqrt(*var)); return 1; }
/* ionosphere delay by tec grid data -----------------------------------------*/ static int iondelay(gtime_t time, const tec_t *tec, const double *pos, const double *azel, int opt, double *delay, double *var) { const double fact=40.30E16/FREQ1/FREQ1; /* tecu->L1 iono (m) */ double fs,posp[3]={0},vtec,rms,hion,rp; int i; trace(3,"iondelay: time=%s pos=%.1f %.1f azel=%.1f %.1f\n",time_str(time,0), pos[0]*R2D,pos[1]*R2D,azel[0]*R2D,azel[1]*R2D); *delay=*var=0.0; for (i=0;i<tec->ndata[2];i++) { /* for a layer */ hion=tec->hgts[0]+tec->hgts[2]*i; /* ionospheric pierce point position */ fs=ionppp(pos,azel,tec->rb,hion,posp); if (opt&2) { /* modified single layer mapping function (M-SLM) ref [2] */ rp=tec->rb/(tec->rb+hion)*sin(0.9782*(PI/2.0-azel[1])); fs=1.0/sqrt(1.0-rp*rp); } if (opt&1) { /* earth rotation correction (sun-fixed coordinate) */ posp[1]+=2.0*PI*timediff(time,tec->time)/86400.0; } /* interpolate tec grid data */ if (!interptec(tec,i,posp,&vtec,&rms)) return 0; *delay+=fact*fs*vtec; *var+=fact*fact*fs*fs*rms*rms; } trace(4,"iondelay: delay=%7.2f std=%6.2f\n",*delay,sqrt(*var)); return 1; }