00001 #pragma ident "$Id: EarthOrientation.cpp 2741 2011-06-22 16:37:02Z nwu $"
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
00048
00049
00050 #include <fstream>
00051
00052 #include "icd_200_constants.hpp"
00053 #include "EarthOrientation.hpp"
00054
00055
00056 using namespace std;
00057
00058 namespace gpstk
00059 {
00060
00061 ostream& operator<<(ostream& os, const EarthOrientation& eo)
00062 {
00063 os << " " << setw(17) << setprecision(6) << eo.xp
00064 << " " << setw(17) << setprecision(6) << eo.yp
00065 << " " << setw(17) << setprecision(7) << eo.UT1mUTC;
00066 return os;
00067 }
00068
00069
00070
00071
00072
00073
00074 int EOPPrediction::loadFile(string filename)
00075 throw(FileMissingException)
00076 {
00077 bool ok;
00078 int n;
00079 string line,word;
00080 ifstream inpf(filename.c_str());
00081 if(!inpf) {
00082 FileMissingException fme("Could not open EOPP file " + filename);
00083 GPSTK_THROW(fme);
00084 }
00085
00086 ok = true;
00087 n = 0;
00088 while(!inpf.eof() && inpf.good()) {
00089 getline(inpf,line);
00090 StringUtils::stripTrailing(line,'\r');
00091 if(inpf.bad()) break;
00092 if(line.size() > 80) { ok=false; break; }
00093 switch(n) {
00094 case 0:
00095 if(line.size() < 76) { ok=false; break; }
00096 word = line.substr( 0,10); ta = StringUtils::asDouble(word);
00097 word = line.substr(10,10); A = StringUtils::asDouble(word);
00098 word = line.substr(20,10); B = StringUtils::asDouble(word);
00099 word = line.substr(30,10); C1 = StringUtils::asDouble(word);
00100 word = line.substr(40,10); C2 = StringUtils::asDouble(word);
00101 word = line.substr(50,10); D1 = StringUtils::asDouble(word);
00102 word = line.substr(60,10); D2 = StringUtils::asDouble(word);
00103 word = line.substr(70, 6); P1 = StringUtils::asDouble(word);
00104 break;
00105 case 1:
00106 if(line.size() < 78) { ok=false; break; }
00107 word = line.substr( 0, 6); P2 = StringUtils::asDouble(word);
00108 word = line.substr( 6,10); E = StringUtils::asDouble(word);
00109 word = line.substr(16,10); F = StringUtils::asDouble(word);
00110 word = line.substr(26,10); G1 = StringUtils::asDouble(word);
00111 word = line.substr(36,10); G2 = StringUtils::asDouble(word);
00112 word = line.substr(46,10); H1 = StringUtils::asDouble(word);
00113 word = line.substr(56,10); H2 = StringUtils::asDouble(word);
00114 word = line.substr(66, 6); Q1 = StringUtils::asDouble(word);
00115 word = line.substr(72, 6); Q2 = StringUtils::asDouble(word);
00116 break;
00117 case 2:
00118 if(line.size() < 70) { ok=false; break; }
00119 word = line.substr( 0,10); tb = StringUtils::asDouble(word);
00120 word = line.substr(10,10); I = StringUtils::asDouble(word);
00121 word = line.substr(20,10); J = StringUtils::asDouble(word);
00122 word = line.substr(30,10); K1 = StringUtils::asDouble(word);
00123 word = line.substr(40,10); K2 = StringUtils::asDouble(word);
00124 word = line.substr(50,10); K3 = StringUtils::asDouble(word);
00125 word = line.substr(60,10); K4 = StringUtils::asDouble(word);
00126 break;
00127 case 3:
00128 if(line.size() < 76) { ok=false; break; }
00129 word = line.substr( 0,10); L1 = StringUtils::asDouble(word);
00130 word = line.substr(10,10); L2 = StringUtils::asDouble(word);
00131 word = line.substr(20,10); L3 = StringUtils::asDouble(word);
00132 word = line.substr(30,10); L4 = StringUtils::asDouble(word);
00133 word = line.substr(40, 9); R1 = StringUtils::asDouble(word);
00134 word = line.substr(49, 9); R2 = StringUtils::asDouble(word);
00135 word = line.substr(58, 9); R3 = StringUtils::asDouble(word);
00136 word = line.substr(67, 9); R4 = StringUtils::asDouble(word);
00137 break;
00138 case 4:
00139 if(line.size() < 16) { ok=false; break; }
00140 word = line.substr( 0, 4); TAIUTC = StringUtils::asInt(word);
00141 word = line.substr( 4, 5); SerialNo = StringUtils::asInt(word);
00142
00143 word = line.substr( 9, 7); tv = StringUtils::asDouble(word);
00144 Info = line.substr(16,19);
00145 break;
00146 }
00147 if(!ok) break;
00148 n++;
00149 };
00150 inpf.close();
00151 if(!ok) {
00152 FileMissingException fme("EOPP File " + filename
00153 + " is corrupted or wrong format");
00154 GPSTK_THROW(fme);
00155 }
00156 if(inpf.bad()) return -1;
00157 return 0;
00158 }
00159
00160
00161
00162
00163 int EOPPrediction::getSerialNumber(DayTime& t)
00164 throw(DayTime::DayTimeException)
00165 {
00166 int w2 = t.GPSfullweek()-1;
00167 if(w2 < 0) {
00168 using namespace StringUtils;
00169 DayTime::DayTimeException dte("Invalid week in EOPP file: "
00170 + asString<short>(w2));
00171 GPSTK_THROW(dte);
00172 }
00173
00174 int yr,w1;
00175 try {
00176 DayTime ht;
00177 ht.setGPSfullweek(w2,475200.0);
00178 yr = ht.year();
00179 ht.setYMDHMS(yr,1,1,0,0,0.0);
00180 w1 = ht.GPSfullweek();
00181 if(ht.dayOfWeek() == 6) w1++;
00182 yr = yr % 10;
00183 }
00184 catch(DayTime::DayTimeException& dte) {
00185 GPSTK_RETHROW(dte);
00186 }
00187 return (100*yr + w2-w1+1);
00188 }
00189
00190
00191
00192
00193 EarthOrientation EOPPrediction::computeEOP(int& mjd) const
00194 throw(DayTime::DayTimeException)
00195 {
00196 DayTime t;
00197 try { t.setMJD(double(mjd)); }
00198 catch(DayTime::DayTimeException& dte) { GPSTK_RETHROW(dte); }
00199 return computeEOP(t);
00200 }
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215 EarthOrientation EOPPrediction::computeEOP(DayTime& ep) const
00216 throw()
00217 {
00218 double t,dt,arg;
00219 EarthOrientation eo;
00220
00221 t = ep.MJD() + ep.secOfDay()/86400.0;
00222
00223
00224 dt = t - ta;
00225 arg = TWO_PI*dt;
00226 eo.xp = A + B*dt + C1*sin(arg/P1) + D1*cos(arg/P1)
00227 + C2*sin(arg/P2) + D2*cos(arg/P2);
00228 eo.yp = E + F*dt + G1*sin(arg/Q1) + H1*cos(arg/Q1)
00229 + G2*sin(arg/Q2) + H2*cos(arg/Q2);
00230
00231 dt = t - tb;
00232 arg = TWO_PI*dt;
00233 eo.UT1mUTC = I + J*dt
00234 + K1*sin(arg/R1) + L1*cos(arg/R1)
00235 + K2*sin(arg/R2) + L2*cos(arg/R2)
00236 + K3*sin(arg/R3) + L3*cos(arg/R3)
00237 + K4*sin(arg/R4) + L4*cos(arg/R4);
00238
00239 return eo;
00240 }
00241
00242
00243
00244 ostream& operator<<(ostream& os, const EOPPrediction& eopp)
00245 {
00246 os << fixed
00247 << setw(10) << setprecision(2) << eopp.ta
00248 << setw(10) << setprecision(6) << eopp.A
00249 << setw(10) << setprecision(6) << eopp.B
00250 << setw(10) << setprecision(6) << eopp.C1
00251 << setw(10) << setprecision(6) << eopp.C2
00252 << setw(10) << setprecision(6) << eopp.D1
00253 << setw(10) << setprecision(6) << eopp.D2
00254 << setw( 6) << setprecision(2) << eopp.P1
00255 << " " << endl;
00256 os << setw( 6) << setprecision(2) << eopp.P2
00257 << setw(10) << setprecision(6) << eopp.E
00258 << setw(10) << setprecision(6) << eopp.F
00259 << setw(10) << setprecision(6) << eopp.G1
00260 << setw(10) << setprecision(6) << eopp.G2
00261 << setw(10) << setprecision(6) << eopp.H1
00262 << setw(10) << setprecision(6) << eopp.H2
00263 << setw( 6) << setprecision(2) << eopp.Q1
00264 << setw( 6) << setprecision(2) << eopp.Q2
00265 << " " << endl;
00266 os << setw(10) << setprecision(2) << eopp.tb
00267 << setw(10) << setprecision(6) << eopp.I
00268 << setw(10) << setprecision(6) << eopp.J
00269 << setw(10) << setprecision(6) << eopp.K1
00270 << setw(10) << setprecision(6) << eopp.K2
00271 << setw(10) << setprecision(6) << eopp.K3
00272 << setw(10) << setprecision(6) << eopp.K4
00273 << " " << endl;
00274 os << setw(10) << setprecision(6) << eopp.L1
00275 << setw(10) << setprecision(6) << eopp.L2
00276 << setw(10) << setprecision(6) << eopp.L3
00277 << setw(10) << setprecision(6) << eopp.L4
00278 << setw( 9) << setprecision(4) << eopp.R1
00279 << setw( 9) << setprecision(4) << eopp.R2
00280 << setw( 9) << setprecision(4) << eopp.R3
00281 << setw( 9) << setprecision(4) << eopp.R4
00282 << " " << endl;
00283 os << setw(4) << eopp.TAIUTC
00284 << setw(5) << eopp.SerialNo
00285 << setw(6) << int(eopp.tv+0.5)
00286 << " " << eopp.Info
00287 << " "
00288 << " "
00289 << " ";
00290 return os;
00291 }
00292
00293
00294
00295
00296
00297
00298 void EOPStore::addEOP(int mjd, EarthOrientation& eop)
00299 throw()
00300 {
00301 mapMJD_EOP[mjd] = eop;
00302
00303 if(begMJD == -1 || endMJD == -1) {
00304 begMJD = endMJD = mjd;
00305 }
00306 else if(mjd < begMJD) {
00307 begMJD = mjd;
00308 }
00309 else if(mjd > endMJD) {
00310 endMJD = mjd;
00311 }
00312 }
00313
00314
00315
00316
00317
00318
00319 int EOPStore::addEOP(int mjd, EOPPrediction& eopp)
00320 throw(DayTime::DayTimeException)
00321 {
00322 EarthOrientation eo;
00323 try {
00324 eo = eopp.computeEOP(mjd);
00325 }
00326 catch(DayTime::DayTimeException& dte)
00327 {
00328 GPSTK_RETHROW(dte);
00329 }
00330
00331 addEOP(mjd,eo);
00332
00333 return 0;
00334 }
00335
00336
00337
00338
00339
00340
00341 void EOPStore::addFile(const string& filename)
00342 throw(FileMissingException)
00343 {
00344 try {
00345 addEOPPFile(filename);
00346 }
00347 catch(FileMissingException& fme)
00348 {
00349 if(StringUtils::matches(fme.getText(),string("wrong format")).empty()) {
00350 GPSTK_RETHROW(fme);
00351 }
00352
00353
00354 try {
00355 addIERSFile(filename);
00356 }
00357 catch(FileMissingException& fme)
00358 {
00359 GPSTK_RETHROW(fme);
00360 }
00361 }
00362 }
00363
00364
00365
00366
00367
00368
00369 void EOPStore::addEOPPFile(const string& filename)
00370 throw(FileMissingException)
00371 {
00372
00373 EOPPrediction eopp;
00374 try {
00375 eopp.loadFile(filename);
00376 }
00377 catch(FileMissingException& fme)
00378 {
00379 GPSTK_RETHROW(fme);
00380 }
00381
00382
00383 int mjd;
00384 mjd = eopp.getValidTime();
00385
00386 for(int i=0; i<7; i++) {
00387 EarthOrientation eo;
00388 eo = eopp.computeEOP(mjd);
00389 addEOP(mjd,eo);
00390 mjd++;
00391 }
00392 }
00393
00394
00395
00396 void EOPStore::addIERSFile(const string& filename)
00397 throw(FileMissingException)
00398 {
00399 bool ok;
00400 int n,mjd;
00401 double fracmjd;
00402 string line,word;
00403
00404 ifstream inpf(filename.c_str());
00405 if(!inpf) {
00406 FileMissingException fme("Could not open IERS file " + filename);
00407 GPSTK_THROW(fme);
00408 }
00409
00410 ok = true;
00411 while(!inpf.eof() && inpf.good()) {
00412 getline(inpf,line);
00413 StringUtils::stripTrailing(line,'\r');
00414 if(inpf.eof()) break;
00415
00416 if(inpf.bad() || line.size() < 70) { ok = false; break; }
00417 EarthOrientation eo;
00418 mjd = StringUtils::asInt(line.substr(7,5));
00419 eo.xp = StringUtils::asDouble(line.substr(18,9));
00420 eo.yp = StringUtils::asDouble(line.substr(37,9));
00421 eo.UT1mUTC = StringUtils::asDouble(line.substr(58,10));
00422
00423 addEOP(mjd,eo);
00424 };
00425 inpf.close();
00426
00427 if(!ok) {
00428 FileMissingException fme("IERS File " + filename
00429 + " is corrupted or wrong format");
00430 GPSTK_THROW(fme);
00431 }
00432 }
00433
00434
00435
00436
00437
00438
00439
00440 void EOPStore::edit(int mjdmin, int mjdmax)
00441 throw()
00442 {
00443 if(mjdmin > mjdmax) {
00444 int m=mjdmin;
00445 mjdmin = mjdmax;
00446 mjdmax = m;
00447 }
00448
00449 if(mjdmin > endMJD) return;
00450 if(mjdmax < begMJD) return;
00451
00452 map<int,EarthOrientation>::iterator it;
00453 it = mapMJD_EOP.lower_bound(mjdmin);
00454 if(it != mapMJD_EOP.begin())
00455 mapMJD_EOP.erase(mapMJD_EOP.begin(), it);
00456
00457 it = mapMJD_EOP.upper_bound(mjdmax);
00458 if(it != mapMJD_EOP.end())
00459 mapMJD_EOP.erase(it, mapMJD_EOP.end());
00460
00461 it = mapMJD_EOP.begin();
00462 if(it == mapMJD_EOP.end())
00463 begMJD = -1;
00464 else
00465 begMJD = it->first;
00466
00467 it = mapMJD_EOP.end();
00468 if(--it == mapMJD_EOP.end())
00469 endMJD = -1;
00470 else
00471 endMJD = it->first;
00472 }
00473
00474
00475
00476
00477
00478
00479 void EOPStore::dump(short detail, ostream& os) const
00480 throw()
00481 {
00482 DayTime tt;
00483 os << "EOPStore dump (" << mapMJD_EOP.size() << " entries):\n";
00484 os << " Time limits: [MJD " << begMJD << " - " << endMJD << "]";
00485 tt.setMJD(double(begMJD));
00486 os << " = [m/d/y " << tt.printf("%m/%d/%Y");
00487 tt.setMJD(double(endMJD));
00488 os << " - " << tt.printf("%m/%d/%Y") << "]" << endl;
00489 if(detail > 0) {
00490 int lastmjd=-1;
00491 map<int,EarthOrientation>::const_iterator it;
00492 for(it=mapMJD_EOP.begin(); it != mapMJD_EOP.end(); it++) {
00493 if(lastmjd != -1 && it->first - lastmjd > 1)
00494 os << " ....." << endl;
00495 os << " " << it->first << " " << it->second
00496 << " (" << setfill('0') << setw(3)
00497 << EOPPrediction::getSerialNumber(it->first) << setfill(' ') << ")"
00498 << endl;
00499 lastmjd = it->first;
00500 }
00501 }
00502 }
00503
00504
00505
00506
00507
00508
00509
00510 EarthOrientation EOPStore::getEOP(DayTime& t) const
00511 throw(InvalidRequest)
00512 {
00513
00514 int loMJD = int(t.MJD());
00515 int hiMJD = loMJD + 1;
00516
00517 map<int,EarthOrientation>::const_iterator hit,lit;
00518 lit = mapMJD_EOP.find(loMJD);
00519 hit = mapMJD_EOP.find(hiMJD);
00520 if(lit == mapMJD_EOP.end() || hit == mapMJD_EOP.end()) {
00521 InvalidRequest ire(string("Time tag (MJD=")
00522 + (lit == mapMJD_EOP.end() ?
00523 StringUtils::asString(loMJD) : StringUtils::asString(hiMJD))
00524 + string(") not found within the EOP store - EOPP files are out-of-date"));
00525 GPSTK_THROW(ire);
00526 }
00527
00528 EarthOrientation eo;
00529 double dt=t.MJD()-double(loMJD);
00530 eo.xp = (1.0-dt) * lit->second.xp + dt * hit->second.xp;
00531 eo.yp = (1.0-dt) * lit->second.yp + dt * hit->second.yp;
00532 eo.UT1mUTC = (1.0-dt) * lit->second.UT1mUTC + dt * hit->second.UT1mUTC;
00533
00534 return eo;
00535 }
00536
00537 }
00538