/* time to gps time ------------------------------------------------------------ * convert gtime_t struct to week and tow in gps time * args : gtime_t t I gtime_t struct * int *week IO week number in gps time (NULL: no output) * return : time of week in gps time (s) *-----------------------------------------------------------------------------*/ static double time2gpst(gtime_t t, ref int week) { gtime_t t0 = epoch2time(gpst0); uint sec = t.time - t0.time; int w = (int)(sec / (86400 * 7)); week = w; return (double)(sec - w * 86400 * 7) + t.sec; }
/* 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) *-----------------------------------------------------------------------------*/ static gtime_t epoch2time(double[] ep) { int[] doy = new int[] { 1, 32, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 }; gtime_t time = new gtime_t(); 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)Math.Floor(ep[5]); time.time = (uint)(days * 86400 + (int)ep[3] * 3600 + (int)ep[4] * 60 + sec); time.sec = ep[5] - sec; return time; }
/* ionosphere model ------------------------------------------------------------ * compute ionospheric delay by broadcast ionosphere model (klobuchar model) * args : gtime_t t I time (gpst) * double *ion I iono model parameters {a0,a1,a2,a3,b0,b1,b2,b3} * double *pos I receiver position {lat,lon,h} (rad,m) * double *azel I azimuth/elevation angle {az,el} (rad) * return : ionospheric delay (L1) (m) *-----------------------------------------------------------------------------*/ static double ionmodel(gtime_t t, double[] ion, double[] pos, double[] azel) { double[] ion_default = new double[] { /* 2004/1/1 */ 0.1118E-07,-0.7451E-08,-0.5961E-07, 0.1192E-06, 0.1167E+06,-0.2294E+06,-0.1311E+06, 0.1049E+07 }; double tt, f, psi, phi, lam, amp, per, x; int week = 0; if (pos[2] < -1E3 || azel[1] <= 0) return 0.0; if (norm(ion, 8) <= 0.0) ion = ion_default; // trace(1,"ion %f %f %f %f %f %f %f %f\n", ion[0], ion[1], ion[2], ion[3], ion[4], ion[5], ion[6], ion[7]); //ion = ion_default; /* earth centered angle (semi-circle) */ psi = 0.0137 / (azel[1] / PI + 0.11) - 0.022; /* subionospheric latitude/longitude (semi-circle) */ phi = pos[0] / PI + psi * cos(azel[0]); if (phi > 0.416) phi = 0.416; else if (phi < -0.416) phi = -0.416; lam = pos[1] / PI + psi * sin(azel[0]) / cos(phi * PI); /* geomagnetic latitude (semi-circle) */ phi += 0.064 * cos((lam - 1.617) * PI); /* local time (s) */ tt = 43200.0 * lam + time2gpst(t, ref week); tt -= floor(tt / 86400.0) * 86400.0; /* 0<=tt<86400 */ /* slant factor */ f = 1.0 + 16.0 * pow(0.53 - azel[1] / PI, 3.0); /* ionospheric delay */ amp = ion[0] + phi * (ion[1] + phi * (ion[2] + phi * ion[3])); per = ion[4] + phi * (ion[5] + phi * (ion[6] + phi * ion[7])); amp = amp < 0.0 ? 0.0 : amp; per = per < 72000.0 ? 72000.0 : per; x = 2.0 * PI * (tt - 50400.0) / per; return CLIGHT * f * (fabs(x) < 1.57 ? 5E-9 + amp * (1.0 + x * x * (-0.5 + x * x / 24.0)) : 5E-9); }