00001 #pragma ident "$Id: AlmOrbit.cpp 2944 2011-10-27 08:04:41Z yanweignss $"
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00052 #include "icd_200_constants.hpp"
00053 #include "GPSGeoid.hpp"
00054 #include "AlmOrbit.hpp"
00055 #include <cmath>
00056
00057 namespace gpstk
00058 {
00059 AlmOrbit :: AlmOrbit() throw()
00060 {
00061 ecc = i_offset = OMEGAdot = Ahalf = OMEGA0 = w = M0 = AF0 = AF1 = 0.0;
00062
00063 Toa = xmit_time = 0;
00064
00065 week = SV_health = 0;
00066 }
00067
00068 AlmOrbit :: AlmOrbit(short prn, double aEcc, double ai_offset,
00069 double aOMEGAdot, double aAhalf, double aOMEGA0,
00070 double aw, double aM0, double aAF0, double aAF1,
00071 long aToa, long axmit_time, short aweek,
00072 short aSV_health)
00073 : ecc(aEcc), i_offset(ai_offset), OMEGAdot(aOMEGAdot), Ahalf(aAhalf),
00074 OMEGA0(aOMEGA0), w(aw), M0(aM0), AF0(aAF0), AF1(aAF1), Toa(aToa),
00075 xmit_time(axmit_time), week(aweek), SV_health(aSV_health), PRN(prn)
00076 {
00077 }
00078
00079 Xvt AlmOrbit :: svXvt(const DayTime& t) const
00080 throw()
00081 {
00082 Xvt sv;
00083 GPSGeoid geoid;
00084
00085 double elapt;
00086 double A;
00087 double n;
00088 double meana;
00089 double ea;
00090 short loop;
00091 double f,g,delea,q,gsta,gcta;
00092 double dtc;
00093 double ta;
00094 double sinea,cosea,sinu,cosu;
00095 double alat;
00096 double ualat;
00097 double r;
00098 double i;
00099 double anlon;
00100 double xip,yip,can,san,cinc,sinc,xef,yef,zef,dek,dlk,div,domk,duv,
00101 drv,dxp,dyp,vxef,vyef,vzef;
00102 double sqrtgm = ::sqrt(geoid.gm());
00103
00104
00105 elapt = t - getToaTime();
00106
00107
00108 A = Ahalf * Ahalf;
00109 n = sqrtgm / (Ahalf * A);
00110
00111
00112 meana = M0 + elapt * n;
00113 meana = ::fmod(meana, 2.0 * PI);
00114
00115
00116
00117 ea = meana + ecc * ::sin(meana);
00118 loop = 1;
00119
00120 do {
00121 f = meana - (ea - ecc * ::sin(ea));
00122 g = 1.0 - ecc * ::cos(ea);
00123 delea = f / g;
00124 ea += delea;
00125 loop++;
00126 } while ( ::fabs(delea) > 1.0e-11 && (loop <= 20));
00127
00128
00129 dtc = AF0 + elapt * AF1;
00130 sv.dtime = dtc;
00131
00132
00133 q = ::sqrt (1.0e0 - ecc * ecc);
00134 sinea = ::sin(ea);
00135 cosea = ::cos(ea);
00136 gsta = q * sinea;
00137 gcta = cosea - ecc;
00138 ta = ::atan2(gsta,gcta);
00139
00140
00141 alat = ta + w;
00142
00143
00144 ualat = alat;
00145 r = A * (1.0 - ecc * cosea);
00146 i = i_offset + 0.3e0 * PI;
00147
00148
00149 anlon = OMEGA0 +
00150 (OMEGAdot - geoid.angVelocity()) * elapt -
00151 geoid.angVelocity() * (double)Toa;
00152
00153
00154 cosu = ::cos(ualat);
00155 sinu = ::sin(ualat);
00156 xip = r * cosu;
00157 yip = r * sinu;
00158
00159
00160 can = ::cos (anlon);
00161 san = ::sin (anlon);
00162 cinc = ::cos(i);
00163 sinc = ::sin(i);
00164
00165 xef = xip * can - yip * cinc * san;
00166 yef = xip * san + yip * cinc * can;
00167 zef = yip * sinc;
00168
00169 sv.x[0] = xef;
00170 sv.x[1] = yef;
00171 sv.x[2] = zef;
00172
00173
00174 dek = n * A / r;
00175 dlk = sqrtgm * Ahalf * q / (r * r);
00176 div = 0.0e0;
00177 domk = OMEGAdot - geoid.angVelocity();
00178 duv = dlk;
00179 drv = A * ecc * dek * sinea;
00180
00181 dxp = drv * cosu - r * sinu * duv;
00182 dyp = drv * sinu + r * cosu * duv;
00183
00184 vxef = dxp * can - xip * san * domk - dyp * cinc * san
00185 + yip * (sinc * san * div - cinc * can * domk);
00186 vyef = dxp * san + xip * can * domk + dyp * cinc * can
00187 - yip * (sinc * can * div + cinc * san * domk);
00188 vzef = dyp * sinc + yip * cinc * div;
00189
00190 sv.v[0] = vxef;
00191 sv.v[1] = vyef;
00192 sv.v[2] = vzef;
00193
00194 return sv;
00195 }
00196
00197 DayTime AlmOrbit::getTransmitTime() const throw()
00198 {
00199 DayTime transmitTime(0.L);
00200 transmitTime.setGPSfullweek(getFullWeek(), (double)xmit_time);
00201 return transmitTime;
00202 }
00203
00204 short AlmOrbit::getFullWeek() const throw()
00205 {
00206
00207 short xmit_week = week;
00208 double sow_diff = (double)(Toa - xmit_time);
00209 if (sow_diff < -DayTime::HALFWEEK)
00210 xmit_week--;
00211 else if (sow_diff > DayTime::HALFWEEK)
00212 xmit_week++;
00213
00214 return xmit_week;
00215 }
00216
00217 DayTime AlmOrbit::getToaTime() const throw()
00218 {
00219 DayTime toaTime(0.L);
00220 toaTime.setGPSfullweek(week, (double)Toa);
00221 return toaTime;
00222 }
00223
00224 void AlmOrbit::dump(std::ostream& s, int verbosity) const
00225 {
00226 using std::endl;
00227 using std::setw;
00228
00229 s << std::setprecision(4);
00230 s.setf(std::ios::scientific);
00231 switch (verbosity)
00232 {
00233 case 0:
00234 s << PRN << ", "
00235 << Toa << ", "
00236 << week << ", "
00237 << std::hex
00238 << SV_health << ", "
00239 << std::dec
00240 << AF0 << ", "
00241 << AF1 << ", "
00242 << ecc << ", "
00243 << w << ", "
00244 << Ahalf << ", "
00245 << M0 << ", "
00246 << OMEGA0 << ", "
00247 << OMEGAdot << ", "
00248 << i_offset
00249 << endl;
00250 break;
00251
00252 case 1:
00253 s << "PRN:" << PRN
00254 << " Toa:" << Toa
00255 << " H:" << SV_health
00256 << " AFO:" << AF0
00257 << " AF1:" << AF1
00258 << " Ecc:" << ecc
00259 << endl
00260 << " w:" << w
00261 << " Ahalf:" << Ahalf
00262 << " M0:" << M0
00263 << endl
00264 << " OMEGA0:" << OMEGA0
00265 << " OMEGAdot:" << OMEGAdot
00266 << " Ioff:" << i_offset
00267 << endl;
00268 break;
00269
00270 default:
00271 s << "PRN: " << PRN << endl
00272 << "Toa: " << Toa << endl
00273 << "xmit_time: " << xmit_time << endl
00274 << "week: " << week << endl
00275 << "SV_health: " << SV_health << endl
00276 << "AFO: " << setw(12) << AF0 << " sec" << endl
00277 << "AF1: " << setw(12) << AF1 << " sec/sec" << endl
00278 << "Sqrt A: " << setw(12) << Ahalf << " sqrt meters" << endl
00279 << "Eccentricity: " << setw(12) << ecc << endl
00280 << "Arg of perigee: " << setw(12) << w << " rad" << endl
00281 << "Mean anomaly at epoch: " << setw(12) << M0 << " rad" << endl
00282 << "Right ascension: " << setw(12) << OMEGA0 << " rad " << setw(16) << OMEGAdot << " rad/sec" << endl
00283 << "Inclination offset: " << setw(12) << i_offset << " rad " << endl;
00284 }
00285 }
00286
00287 std::ostream& operator<<(std::ostream& s, const AlmOrbit& ao)
00288 {
00289 ao.dump(s);
00290 return s;
00291 }
00292
00293 }