IERSConventions.cpp

Go to the documentation of this file.
00001 #pragma ident "$Id: IERSConventions.cpp 2957 2011-10-30 18:15:34Z yanweignss $"
00002 
00008 //============================================================================
00009 //
00010 //  This file is part of GPSTk, the GPS Toolkit.
00011 //
00012 //  The GPSTk is free software; you can redistribute it and/or modify
00013 //  it under the terms of the GNU Lesser General Public License as published
00014 //  by the Free Software Foundation; either version 2.1 of the License, or
00015 //  any later version.
00016 //
00017 //  The GPSTk is distributed in the hope that it will be useful,
00018 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00019 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020 //  GNU Lesser General Public License for more details.
00021 //
00022 //  You should have received a copy of the GNU Lesser General Public
00023 //  License along with GPSTk; if not, write to the Free Software Foundation,
00024 //  Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00025 //
00026 //  Wei Yan - Chinese Academy of Sciences . 2011
00027 //
00028 //============================================================================
00029 
00030 
00031 #include "IERSConventions.hpp"
00032 #include "Logger.hpp"
00033 
00034 namespace gpstk
00035 {
00036    using namespace std;
00037    
00038       // Reference epoch (J2000)
00039    const DayTime J2000(2000,1,1,12,0,0.0);
00040 
00041    const double PI = std::atan(1.0)*4.0;    // 3.1415926535897932; 
00042       // 2PI
00043    const double D2PI = PI+PI;               // 6.283185307179586476925287;
00044 
00045       // Days per Julian century 
00046    const double DJC = 36525.0;
00047 
00048       // Arcseconds to radians 
00049    const double DAS2R = PI/180.0/3600.0;    // 4.848136811095359935899141e-6;
00050 
00051       // seconds to radians
00052    const double DS2R = PI/43200.0;          // 7.272205216643039903848712e-5;
00053 
00054 
00055    // IERS Data Handling
00056    //--------------------------------------------------------------------------
00057    
00058    class TAImUTCData : public map<DayTime,int>
00059    {     
00060    public:
00061       void leapHistory(int year, int month, int day,int leap)
00062       { (*this)[ DayTime(year,month,day,0,0,0.0) ] = leap; }  
00063       
00064       TAImUTCData()
00065       {         
00066          leapHistory( 1972, 1, 1, 10 );
00067          leapHistory( 1972, 7, 1, 11 );
00068          leapHistory( 1973, 1, 1, 12 );
00069          leapHistory( 1974, 1, 1, 13 );
00070          leapHistory( 1975, 1, 1, 14 );
00071          leapHistory( 1976, 1, 1, 15 );
00072          leapHistory( 1977, 1, 1, 16 );
00073          leapHistory( 1978, 1, 1, 17 );
00074          leapHistory( 1979, 1, 1, 18 );
00075          leapHistory( 1980, 1, 1, 19 );
00076          leapHistory( 1981, 7, 1, 20 );
00077          leapHistory( 1982, 7, 1, 21 );
00078          leapHistory( 1983, 7, 1, 22 );
00079          leapHistory( 1985, 7, 1, 23 );
00080          leapHistory( 1988, 1, 1, 24 );
00081          leapHistory( 1990, 1, 1, 25 );
00082          leapHistory( 1991, 1, 1, 26 );
00083          leapHistory( 1992, 7, 1, 27 );
00084          leapHistory( 1993, 7, 1, 28 );
00085          leapHistory( 1994, 7, 1, 29 );
00086          leapHistory( 1996, 1, 1, 30 );
00087          leapHistory( 1997, 7, 1, 31 );
00088          leapHistory( 1999, 1, 1, 32 );
00089          leapHistory( 2006, 1, 1, 33 );
00090          leapHistory( 2009, 1, 1, 34 );
00091 
00092          // more leap seconds should be appended here
00093          // ...
00094       }
00095    };
00096       // Leap seconds data table
00097    static const TAImUTCData  lsDataTable;
00098 
00099    int TAImUTC(DayTime UTC)
00100       throw(InvalidRequest)
00101    {
00102       if( UTC < DayTime(1972,1,1,0,0,0.0) )
00103       {  
00104          GPSTK_THROW(
00105             InvalidRequest( "There are no leap second data for the epoch"
00106                            +UTC.asString()) );
00107       }
00108       
00109       // it point to the iterator >= utc
00110       TAImUTCData::const_iterator it = lsDataTable.lower_bound(UTC);
00111 
00112       if( (it == lsDataTable.end()) || (it->first != UTC) )
00113       {
00114          it--;
00115          return it->second;
00116       }
00117       else if( it->first == UTC )
00118       {
00119          return it->second;
00120       }
00121       
00122       // it should  never go here
00123       GPSTK_THROW(Exception("My God, it should never go here!"));
00124       
00125    }
00126 
00127    double TTmTAI(){ return 32.184; }
00128 
00129    double TAImGPST(){ return 19.0; }
00130 
00131 
00132    static EOPDataStore eopDataTable;
00133 
00134       // 'finals.data' from http://maia.usno.navy.mil/
00135    void LoadIERSFile(const std::string& fileName)
00136    {
00137       eopDataTable.clear();
00138       try { eopDataTable.loadIERSFile(fileName); }
00139       catch(...)
00140       {
00141          GPSTK_WARNING_F1("","Failed to load the IERS ERP File '%s'.", fileName );
00142       }
00143    }
00144 
00145       // ERP data file from IGS
00146    void LoadIGSFile(const std::string& fileName)
00147    {
00148       eopDataTable.clear();
00149       try { eopDataTable.loadIGSFile(fileName); }
00150       catch(...)
00151       {
00152          GPSTK_WARNING_F1("","Failed to load the IGS ERP File '%s'.", fileName );
00153       }
00154    }
00155 
00156       // ERP data file from STK 
00157    void LoadSTKFile(const std::string& fileName)
00158    {
00159       eopDataTable.clear();
00160       try { eopDataTable.loadSTKFile(fileName); }
00161       catch(...)
00162       {
00163          GPSTK_WARNING_F1("","Failed to load the STK ERP File '%s'.", fileName );
00164       }
00165    }
00166 
00167 
00168       // Request EOP Data
00169    EOPDataStore::EOPData EOPData(const DayTime& UTC)
00170       throw(InvalidRequest)
00171    {
00172       return eopDataTable.getEOPData(UTC);
00173    }
00174 
00175       // in arcsecond
00176    double PolarMotionX(const DayTime& UTC)
00177    {
00178       try { return EOPData(UTC).xp; }
00179       catch(...) 
00180       { 
00181          GPSTK_WARNING_F1("","Failed to get EOP data on %s, and xp = 0.0 is returned.",
00182                           UTC.asString());
00183 
00184          return 0.0;
00185       }
00186    }
00187 
00188       // in arcsecond
00189    double PolarMotionY(const DayTime& UTC)
00190    {
00191       try { return EOPData(UTC).yp; }
00192       catch(...) 
00193       {
00194          GPSTK_WARNING_F1("","Failed to get EOP data on %s, and yp = 0.0 is returned.",
00195                           UTC.asString());
00196 
00197          return 0.0;
00198       }
00199    }
00200 
00201       // in second
00202    double UT1mUTC(const DayTime& UTC)
00203    {
00204       try { return EOPData(UTC).UT1mUTC; }
00205       catch(...) 
00206       { 
00207          GPSTK_WARNING_F1("","Failed to get EOP data on %s, and UT1mUTC = 0.0 is returned.",
00208                           UTC.asString());
00209 
00210          return 0.0;
00211       }
00212    }
00213 
00214       // in arcsecond
00215    double NutationDPsi(const DayTime& UTC)
00216    {
00217       try { return EOPData(UTC).dPsi; }
00218       catch(...) 
00219       {
00220          GPSTK_WARNING_F1("","Failed to get EOP data on %s, and dPsi = 0.0 is returned.",
00221                           UTC.asString());
00222 
00223          return 0.0;
00224       }
00225    }
00226 
00227       // in arcsecond
00228    double NutationDEps(const DayTime& UTC)
00229    {
00230       try { return EOPData(UTC).dEps; }
00231       catch(...) 
00232       {
00233          GPSTK_WARNING_F1("","Failed to get EOP data on %s, and dEps = 0.0 is returned.",
00234                           UTC.asString());
00235 
00236          return 0.0;
00237       }
00238    }
00239 
00240    // Time System Handling
00241    //--------------------------------------------------------------------------
00242    
00243    DayTime ConvertTimeSystem(const DayTime& time, TimeSystem from, TimeSystem to)
00244    {
00245       if(from==to) return time;
00246 
00247       static std::map<TimeSystem,std::string> mapTSName;
00248       if(mapTSName.size()==0)
00249       {
00250          mapTSName[TS_UTC] = "UTC";
00251          mapTSName[TS_UT1] = "UT1";
00252          mapTSName[TS_GPST]= "GPST";
00253          mapTSName[TS_TAI] = "TAI";
00254          mapTSName[TS_TT]  = "TT";
00255       }     
00256       
00257       std::map<TimeSystem,std::string>::const_iterator itf,itt,ite;
00258       itf = mapTSName.find(from);
00259       itt = mapTSName.find(to);
00260       ite = mapTSName.end();
00261       
00262       if( (itf==ite) || (itt==ite) )
00263       {
00264          Exception e("Can't convert the Time System from "
00265             + ((itf==ite)?"Unknown":itf->second) + std::string(" to")
00266             + ((itt==ite)?"Unknown":itt->second) + std::string("."));
00267 
00268          GPSTK_THROW(e);
00269       }
00270 
00271       typedef DayTime (*ConvertFunPtr)(const DayTime&);
00272       
00273       ConvertFunPtr funPtr1(0);
00274       if( itf->first == TS_UT1) funPtr1 = UT12UTC;
00275       if( itf->first == TS_GPST)funPtr1 = GPST2UTC;
00276       if( itf->first == TS_TAI) funPtr1 = TAI2UTC;
00277       if( itf->first == TS_TT)  funPtr1 = TT2UTC;
00278 
00279       DayTime utc = funPtr1 ? funPtr1(time) : time;
00280       
00281       ConvertFunPtr funPtr2(0);
00282       if( itt->first == TS_UT1) funPtr2 = UTC2UT1;
00283       if( itt->first == TS_GPST)funPtr2 = UTC2GPST;
00284       if( itt->first == TS_TAI) funPtr2 = UTC2TAI;
00285       if( itt->first == TS_TT)  funPtr2 = UTC2TT;
00286 
00287       DayTime dest = funPtr2 ? funPtr2(utc) : utc;
00288 
00289       return dest;
00290    }
00291 
00292    DayTime GPST2UTC(const DayTime& GPST)
00293    {
00294       // the input should be UTC
00295       int leapSec = TAImUTC(GPST);   
00296       DayTime UTC = GPST;
00297       UTC += (19.0 - double(leapSec));
00298 
00299       leapSec = TAImUTC(UTC);
00300       UTC = GPST;
00301       UTC += (19.0 - double(leapSec));
00302 
00303       return UTC;
00304    }
00305    DayTime UTC2GPST(const DayTime& UTC)
00306    {
00307       DayTime GPST(UTC);
00308       GPST += TAImUTC(UTC);   // TAI
00309       GPST +=-TAImGPST();     // GPST
00310       return GPST;
00311    }
00312 
00313    DayTime UT12UTC(const DayTime& UT1)
00314    {
00315       DayTime UTC(UT1);
00316       UTC -= UT1mUTC(UT1);   // input should be utc
00317       
00318       DayTime T(UT1);
00319       T -= UT1mUTC(UTC);
00320 
00321       UTC = UT1;
00322       UTC -= UT1mUTC(T);
00323 
00324       return UTC;
00325    }
00326    DayTime UTC2UT1(const DayTime& UTC)
00327    {
00328       DayTime UT1(UTC);
00329       UT1 += UT1mUTC(UTC);
00330 
00331       return UT1;
00332    }
00333 
00334    DayTime UT12UTC(const DayTime& UT1,double ut1mutc)
00335    {
00336       DayTime UTC(UT1);
00337       UTC -= ut1mutc;
00338 
00339       return UTC;
00340    }
00341    DayTime UTC2UT1(const DayTime& UTC,double ut1mutc)
00342    {
00343       DayTime UT1(UTC);
00344       UT1 += ut1mutc;
00345 
00346       return UT1;
00347    }
00348 
00349    DayTime TT2UTC(const DayTime& TT)
00350    {
00351       DayTime TAI  = TT;          // TT
00352       TAI -= TTmTAI();       // TAI
00353 
00354       DayTime UTC = TAI;
00355       UTC -= TAImUTC(TAI); // input should be UTC     
00356 
00357       DayTime UTC2(UTC);
00358 
00359       UTC = TAI;
00360       UTC -= TAImUTC(UTC2);
00361 
00362       UTC2 = UTC;
00363 
00364       UTC = TAI;
00365       UTC -= TAImUTC(UTC2);
00366 
00367       return UTC;
00368    }
00369    DayTime UTC2TT(const DayTime& UTC)
00370    {
00371       DayTime TAI(UTC);
00372       TAI += TAImUTC(UTC);
00373 
00374       DayTime TT(TAI);
00375       TT += TTmTAI();
00376       
00377       return TT;
00378    }
00379 
00380    DayTime TAI2UTC(const DayTime& TAI)
00381    {
00382       DayTime UTC(TAI);
00383       UTC -= TAImUTC(TAI); // input should be UTC     
00384 
00385       DayTime UTC2 = TAI;
00386       UTC2 -= TAImUTC(UTC);
00387 
00388       UTC = TAI;
00389       UTC -= TAImUTC(UTC2);
00390 
00391       return UTC;
00392    }
00393    DayTime UTC2TAI(const DayTime& UTC)
00394    {
00395       DayTime TAI(UTC);
00396       TAI += TAImUTC(UTC);      // TAI
00397 
00398       return TAI;
00399    }
00400 
00401    DayTime BDT2UTC(const DayTime& BDT)
00402    {
00403       DayTime GPST(BDT);
00404       GPST += 14.0;
00405 
00406       return GPST2UTC(GPST);
00407    }
00408    DayTime UTC2BDT(const DayTime& UTC)
00409    {
00410       DayTime BDT = UTC2GPST(UTC);  
00411       BDT -= 14.0;
00412 
00413       return BDT;
00414    }
00415 
00416    // Reference System Handling
00417    //--------------------------------------------------------------------------
00418 
00419    Triple J2kPosToECEF(const Triple& j2kPos, const DayTime& time, TimeSystem sys)
00420    {
00421       Vector<double> j2kR(3,0.0);
00422       j2kR[0] = j2kPos[0];
00423       j2kR[1] = j2kPos[1];
00424       j2kR[2] = j2kPos[2];
00425       
00426       DayTime UTC = ConvertTimeSystem(time, sys, TS_UTC);
00427       Vector<double> ecefR = J2kPosToECEF(UTC,j2kR);
00428 
00429       return Triple(ecefR[0], ecefR[1], ecefR[2]);
00430    }
00431 
00432    Triple ECEFPosToJ2k(const Triple& ecefPos, const DayTime& time, TimeSystem sys)
00433    {
00434       Vector<double> ecefR(3,0.0);
00435       ecefR[0] = ecefPos[0];
00436       ecefR[1] = ecefPos[1];
00437       ecefR[2] = ecefPos[2];
00438 
00439       DayTime UTC = ConvertTimeSystem(time, sys, TS_UTC);
00440       Vector<double> j2kR = ECEFPosToJ2k(UTC,ecefR);
00441 
00442       return Triple(j2kR[0], j2kR[1], j2kR[2]);
00443    }
00444 
00445 
00446    double iauNut80Args(const DayTime& TT,double& eps, double& dpsi,double& deps)
00447       throw(Exception)
00448    {
00449       static const double nut[106][10]={
00450          {   0,   0,   0,   0,   1, -6798.4, -171996, -174.2, 92025,   8.9},
00451          {   0,   0,   2,  -2,   2,   182.6,  -13187,   -1.6,  5736,  -3.1},
00452          {   0,   0,   2,   0,   2,    13.7,   -2274,   -0.2,   977,  -0.5},
00453          {   0,   0,   0,   0,   2, -3399.2,    2062,    0.2,  -895,   0.5},
00454          {   0,  -1,   0,   0,   0,  -365.3,   -1426,    3.4,    54,  -0.1},
00455          {   1,   0,   0,   0,   0,    27.6,     712,    0.1,    -7,   0.0},
00456          {   0,   1,   2,  -2,   2,   121.7,    -517,    1.2,   224,  -0.6},
00457          {   0,   0,   2,   0,   1,    13.6,    -386,   -0.4,   200,   0.0},
00458          {   1,   0,   2,   0,   2,     9.1,    -301,    0.0,   129,  -0.1},
00459          {   0,  -1,   2,  -2,   2,   365.2,     217,   -0.5,   -95,   0.3},
00460          {  -1,   0,   0,   2,   0,    31.8,     158,    0.0,    -1,   0.0},
00461          {   0,   0,   2,  -2,   1,   177.8,     129,    0.1,   -70,   0.0},
00462          {  -1,   0,   2,   0,   2,    27.1,     123,    0.0,   -53,   0.0},
00463          {   1,   0,   0,   0,   1,    27.7,      63,    0.1,   -33,   0.0},
00464          {   0,   0,   0,   2,   0,    14.8,      63,    0.0,    -2,   0.0},
00465          {  -1,   0,   2,   2,   2,     9.6,     -59,    0.0,    26,   0.0},
00466          {  -1,   0,   0,   0,   1,   -27.4,     -58,   -0.1,    32,   0.0},
00467          {   1,   0,   2,   0,   1,     9.1,     -51,    0.0,    27,   0.0},
00468          {  -2,   0,   0,   2,   0,  -205.9,     -48,    0.0,     1,   0.0},
00469          {  -2,   0,   2,   0,   1,  1305.5,      46,    0.0,   -24,   0.0},
00470          {   0,   0,   2,   2,   2,     7.1,     -38,    0.0,    16,   0.0},
00471          {   2,   0,   2,   0,   2,     6.9,     -31,    0.0,    13,   0.0},
00472          {   2,   0,   0,   0,   0,    13.8,      29,    0.0,    -1,   0.0},
00473          {   1,   0,   2,  -2,   2,    23.9,      29,    0.0,   -12,   0.0},
00474          {   0,   0,   2,   0,   0,    13.6,      26,    0.0,    -1,   0.0},
00475          {   0,   0,   2,  -2,   0,   173.3,     -22,    0.0,     0,   0.0},
00476          {  -1,   0,   2,   0,   1,    27.0,      21,    0.0,   -10,   0.0},
00477          {   0,   2,   0,   0,   0,   182.6,      17,   -0.1,     0,   0.0},
00478          {   0,   2,   2,  -2,   2,    91.3,     -16,    0.1,     7,   0.0},
00479          {  -1,   0,   0,   2,   1,    32.0,      16,    0.0,    -8,   0.0},
00480          {   0,   1,   0,   0,   1,   386.0,     -15,    0.0,     9,   0.0},
00481          {   1,   0,   0,  -2,   1,   -31.7,     -13,    0.0,     7,   0.0},
00482          {   0,  -1,   0,   0,   1,  -346.6,     -12,    0.0,     6,   0.0},
00483          {   2,   0,  -2,   0,   0, -1095.2,      11,    0.0,     0,   0.0},
00484          {  -1,   0,   2,   2,   1,     9.5,     -10,    0.0,     5,   0.0},
00485          {   1,   0,   2,   2,   2,     5.6,      -8,    0.0,     3,   0.0},
00486          {   0,  -1,   2,   0,   2,    14.2,      -7,    0.0,     3,   0.0},
00487          {   0,   0,   2,   2,   1,     7.1,      -7,    0.0,     3,   0.0},
00488          {   1,   1,   0,  -2,   0,   -34.8,      -7,    0.0,     0,   0.0},
00489          {   0,   1,   2,   0,   2,    13.2,       7,    0.0,    -3,   0.0},
00490          {  -2,   0,   0,   2,   1,  -199.8,      -6,    0.0,     3,   0.0},
00491          {   0,   0,   0,   2,   1,    14.8,      -6,    0.0,     3,   0.0},
00492          {   2,   0,   2,  -2,   2,    12.8,       6,    0.0,    -3,   0.0},
00493          {   1,   0,   0,   2,   0,     9.6,       6,    0.0,     0,   0.0},
00494          {   1,   0,   2,  -2,   1,    23.9,       6,    0.0,    -3,   0.0},
00495          {   0,   0,   0,  -2,   1,   -14.7,      -5,    0.0,     3,   0.0},
00496          {   0,  -1,   2,  -2,   1,   346.6,      -5,    0.0,     3,   0.0},
00497          {   2,   0,   2,   0,   1,     6.9,      -5,    0.0,     3,   0.0},
00498          {   1,  -1,   0,   0,   0,    29.8,       5,    0.0,     0,   0.0},
00499          {   1,   0,   0,  -1,   0,   411.8,      -4,    0.0,     0,   0.0},
00500          {   0,   0,   0,   1,   0,    29.5,      -4,    0.0,     0,   0.0},
00501          {   0,   1,   0,  -2,   0,   -15.4,      -4,    0.0,     0,   0.0},
00502          {   1,   0,  -2,   0,   0,   -26.9,       4,    0.0,     0,   0.0},
00503          {   2,   0,   0,  -2,   1,   212.3,       4,    0.0,    -2,   0.0},
00504          {   0,   1,   2,  -2,   1,   119.6,       4,    0.0,    -2,   0.0},
00505          {   1,   1,   0,   0,   0,    25.6,      -3,    0.0,     0,   0.0},
00506          {   1,  -1,   0,  -1,   0, -3232.9,      -3,    0.0,     0,   0.0},
00507          {  -1,  -1,   2,   2,   2,     9.8,      -3,    0.0,     1,   0.0},
00508          {   0,  -1,   2,   2,   2,     7.2,      -3,    0.0,     1,   0.0},
00509          {   1,  -1,   2,   0,   2,     9.4,      -3,    0.0,     1,   0.0},
00510          {   3,   0,   2,   0,   2,     5.5,      -3,    0.0,     1,   0.0},
00511          {  -2,   0,   2,   0,   2,  1615.7,      -3,    0.0,     1,   0.0},
00512          {   1,   0,   2,   0,   0,     9.1,       3,    0.0,     0,   0.0},
00513          {  -1,   0,   2,   4,   2,     5.8,      -2,    0.0,     1,   0.0},
00514          {   1,   0,   0,   0,   2,    27.8,      -2,    0.0,     1,   0.0},
00515          {  -1,   0,   2,  -2,   1,   -32.6,      -2,    0.0,     1,   0.0},
00516          {   0,  -2,   2,  -2,   1,  6786.3,      -2,    0.0,     1,   0.0},
00517          {  -2,   0,   0,   0,   1,   -13.7,      -2,    0.0,     1,   0.0},
00518          {   2,   0,   0,   0,   1,    13.8,       2,    0.0,    -1,   0.0},
00519          {   3,   0,   0,   0,   0,     9.2,       2,    0.0,     0,   0.0},
00520          {   1,   1,   2,   0,   2,     8.9,       2,    0.0,    -1,   0.0},
00521          {   0,   0,   2,   1,   2,     9.3,       2,    0.0,    -1,   0.0},
00522          {   1,   0,   0,   2,   1,     9.6,      -1,    0.0,     0,   0.0},
00523          {   1,   0,   2,   2,   1,     5.6,      -1,    0.0,     1,   0.0},
00524          {   1,   1,   0,  -2,   1,   -34.7,      -1,    0.0,     0,   0.0},
00525          {   0,   1,   0,   2,   0,    14.2,      -1,    0.0,     0,   0.0},
00526          {   0,   1,   2,  -2,   0,   117.5,      -1,    0.0,     0,   0.0},
00527          {   0,   1,  -2,   2,   0,  -329.8,      -1,    0.0,     0,   0.0},
00528          {   1,   0,  -2,   2,   0,    23.8,      -1,    0.0,     0,   0.0},
00529          {   1,   0,  -2,  -2,   0,    -9.5,      -1,    0.0,     0,   0.0},
00530          {   1,   0,   2,  -2,   0,    32.8,      -1,    0.0,     0,   0.0},
00531          {   1,   0,   0,  -4,   0,   -10.1,      -1,    0.0,     0,   0.0},
00532          {   2,   0,   0,  -4,   0,   -15.9,      -1,    0.0,     0,   0.0},
00533          {   0,   0,   2,   4,   2,     4.8,      -1,    0.0,     0,   0.0},
00534          {   0,   0,   2,  -1,   2,    25.4,      -1,    0.0,     0,   0.0},
00535          {  -2,   0,   2,   4,   2,     7.3,      -1,    0.0,     1,   0.0},
00536          {   2,   0,   2,   2,   2,     4.7,      -1,    0.0,     0,   0.0},
00537          {   0,  -1,   2,   0,   1,    14.2,      -1,    0.0,     0,   0.0},
00538          {   0,   0,  -2,   0,   1,   -13.6,      -1,    0.0,     0,   0.0},
00539          {   0,   0,   4,  -2,   2,    12.7,       1,    0.0,     0,   0.0},
00540          {   0,   1,   0,   0,   2,   409.2,       1,    0.0,     0,   0.0},
00541          {   1,   1,   2,  -2,   2,    22.5,       1,    0.0,    -1,   0.0},
00542          {   3,   0,   2,  -2,   2,     8.7,       1,    0.0,     0,   0.0},
00543          {  -2,   0,   2,   2,   2,    14.6,       1,    0.0,    -1,   0.0},
00544          {  -1,   0,   0,   0,   2,   -27.3,       1,    0.0,    -1,   0.0},
00545          {   0,   0,  -2,   2,   1,  -169.0,       1,    0.0,     0,   0.0},
00546          {   0,   1,   2,   0,   1,    13.1,       1,    0.0,     0,   0.0},
00547          {  -1,   0,   4,   0,   2,     9.1,       1,    0.0,     0,   0.0},
00548          {   2,   1,   0,  -2,   0,   131.7,       1,    0.0,     0,   0.0},
00549          {   2,   0,   0,   2,   0,     7.1,       1,    0.0,     0,   0.0},
00550          {   2,   0,   2,  -2,   1,    12.8,       1,    0.0,    -1,   0.0},
00551          {   2,   0,  -2,   0,   1,  -943.2,       1,    0.0,     0,   0.0},
00552          {   1,  -1,   0,  -2,   0,   -29.3,       1,    0.0,     0,   0.0},
00553          {  -1,   0,   0,   1,   1,  -388.3,       1,    0.0,     0,   0.0},
00554          {  -1,  -1,   0,   2,   1,    35.0,       1,    0.0,     0,   0.0},
00555          {   0,   1,   0,   1,   0,    27.3,       1,    0.0,     0,   0.0}
00556       };
00557 
00558       static const double fc[][5]={ /* coefficients for iau 1980 nutation */
00559          { 134.96340251, 1717915923.2178,  31.8792,  0.051635, -0.00024470},
00560          { 357.52910918,  129596581.0481,  -0.5532,  0.000136, -0.00001149},
00561          {  93.27209062, 1739527262.8478, -12.7512, -0.001037,  0.00000417},
00562          { 297.85019547, 1602961601.2090,  -6.3706,  0.006593, -0.00003169},
00563          { 125.04455501,   -6962890.2665,   7.4722,  0.007702  -0.00005939}
00564       };
00565 
00566       eps = 0.0;
00567       dpsi = 0.0; 
00568       deps = 0.0;
00569       
00570       // Julian cent. since J2000
00571       const double T = (TT-J2000)/86400.0/36525.0;
00572       
00573       eps = (84381.448-46.8150*T-0.00059*T*T+0.001813*T*T*T)*DAS2R;  // eps
00574 
00575       double f[5]={0.0};
00576       {
00577          double tt[4]={0.0}; tt[0] = T;
00578          for ( int i=1; i<4; i++) tt[i]=tt[i-1]*T;
00579          for (int i=0; i<5; i++) 
00580          {
00581             f[i]=fc[i][0]*3600.0;
00582             for (int j=0; j<4; j++) f[i]+=fc[i][j+1]*tt[j];
00583             f[i]=fmod(f[i]*DAS2R, 2.0*PI);
00584          }
00585       }
00586       
00587       for(int i = 0; i < 106; i++) 
00588       {
00589          double ang(0.0);
00590          for(int j=0; j<5; j++) ang+=nut[i][j]*f[j];
00591          
00592          dpsi+=(nut[i][6]+nut[i][7]*T)*std::sin(ang);
00593          deps+=(nut[i][8]+nut[i][9]*T)*std::cos(ang);
00594       }
00595 
00596       dpsi *= 1E-4*DAS2R; /* 0.1 mas -> rad */
00597       deps *= 1E-4*DAS2R;
00598 
00599       return f[4];
00600 
00601    }  // End of method 'iauNut80Args()'
00602 
00603 
00604    void J2kToECEFMatrix(const DayTime& UTC, 
00605                         const EOPDataStore::EOPData& ERP,
00606                         Matrix<double>& POM, 
00607                         Matrix<double>& Theta, 
00608                         Matrix<double>& NP)
00609       throw(Exception)
00610    {
00611       double xp = ERP.xp * DAS2R;
00612       double yp = ERP.yp * DAS2R;
00613       double ut1_utc = ERP.UT1mUTC;
00614       double ddeps = ERP.dEps * DAS2R;
00615       double ddpsi = ERP.dPsi * DAS2R;
00616       
00617       DayTime TT = UTC2TT(UTC);
00618       DayTime UT1 = UTC2UT1(UTC,ut1_utc);
00619       
00620       // IAU 1976 precession matrix 
00621       Matrix<double> P = iauPmat76(TT);
00622 
00623       // IAU 1980 nutation matrix 
00624       double eps(0.0),dpsi(0.0),deps(0.0);
00625       double f = iauNut80Args(TT,eps,dpsi,deps);
00626 
00627       Matrix<double> N = iauNmat(eps, dpsi + ddpsi, deps + ddeps);
00628 
00629       NP = N * P;                     // output NP
00630 
00631       double  ut1_sec = UT1.DOYsecond();
00632       DayTime ut1_day(UT1.year(),UT1.DOY(),0.0); 
00633       const double t = (ut1_day-J2000) / 86400.0 / DJC;
00634    
00635       double temp = 24110.54841+8640184.812866*t+0.093104*(t*t)-6.2E-6*(t*t*t)
00636                    +1.002737909350795*ut1_sec;
00637       double gmst = fmod(temp,86400.0)*DS2R;
00638       double ee = dpsi * std::cos(eps) 
00639                 + (0.00264 * std::sin(f) + 0.000063 * std::sin(f+f))*DAS2R;
00640       double gast = normalizeAngle(gmst + ee);
00641      
00642       Theta = Rz(gast);               // output Theta
00643 
00644       // Polar motion matrix
00645       POM = Ry(-xp) * Rx(-yp);        // output POM
00646 
00647       //GPSTK_DEBUG_MAT("",Theta,20,12,"Theta");
00648    }
00649 
00650    // ECI to ECF transform matrix, POM * Theta * NP 
00651    Matrix<double> J2kToECEFMatrix(const DayTime& UTC,const EOPDataStore::EOPData& ERP)
00652    {
00653       Matrix<double> POM, Theta, NP;
00654       J2kToECEFMatrix(UTC,ERP,POM,Theta,NP);
00655       
00656       return (POM * Theta * NP);
00657    }
00658 
00659       // Convert position from J2000 to ECEF.
00660    Vector<double> J2kPosToECEF(const DayTime& UTC, const Vector<double>& j2kPos)
00661       throw(Exception)
00662    {
00663       EOPDataStore::EOPData ERP = EOPData(UTC);
00664       Matrix<double> c2tMat = J2kToECEFMatrix(UTC,ERP);
00665       return c2tMat * j2kPos;
00666    }
00667 
00668 
00669       // Convert position from ECEF to J2000.
00670    Vector<double> ECEFPosToJ2k(const DayTime& UTC, const Vector<double>& ecefPos)
00671       throw(Exception)
00672    {
00673       EOPDataStore::EOPData ERP = EOPData(UTC);
00674       Matrix<double> c2tMat = J2kToECEFMatrix(UTC,ERP);
00675       return transpose(c2tMat) * ecefPos;
00676    }
00677 
00678    // Convert position and velocity from J2000 to ECEF.
00679    Vector<double> J2kPosVelToECEF(const DayTime& UTC, const Vector<double>& j2kPosVel)
00680       throw(Exception)
00681    {
00682       EOPDataStore::EOPData ERP = EOPData(UTC);
00683 
00684       Matrix<double> POM, Theta, NP;
00685       J2kToECEFMatrix(UTC,ERP,POM,Theta,NP);
00686 
00687       const double dera = earthRotationAngleRate1( UTC2TT(UTC) );
00688 
00689       // Derivative of Earth rotation 
00690       Matrix<double> S(3,3,0.0);
00691       S(0,1) = 1.0; S(1,0) = -1.0;      
00692 
00693       Matrix<double> dTheta = dera * S * Theta;
00694 
00695       Matrix<double> c2t = POM * Theta * NP;
00696       Matrix<double> dc2t = POM * dTheta * NP;
00697 
00698       Vector<double> j2kPos(3, 0.0), j2kVel(3, 0.0);
00699       for(int i=0; i<3; i++)
00700       {
00701          j2kPos(i) = j2kPosVel(i);
00702          j2kVel(i) = j2kPosVel(i+3);
00703       }
00704 
00705       Vector<double> ecefPos = c2t * j2kPos;
00706       Vector<double> ecefVel = c2t * j2kVel + dc2t * j2kPos;
00707 
00708       Vector<double> ecefPosVel(6,0.0);
00709       for(int i=0; i<3; i++)
00710       {
00711          ecefPosVel(i) = ecefPos(i);
00712          ecefPosVel(i+3) = ecefVel(i);
00713       }
00714 
00715       return ecefPosVel;
00716    }
00717 
00718    // Convert position and velocity from ECEF to J2000.
00719    Vector<double> ECEFPosVelToJ2k(const DayTime& UTC, const Vector<double>& ecefPosVel)
00720       throw(Exception)
00721    {
00722       EOPDataStore::EOPData ERP = EOPData(UTC);
00723 
00724       Matrix<double> POM, Theta, NP;
00725       J2kToECEFMatrix(UTC,ERP,POM,Theta,NP);
00726 
00727       const double dera = earthRotationAngleRate1( UTC2TT(UTC) );
00728 
00729       // Derivative of Earth rotation 
00730       Matrix<double> S(3,3,0.0);
00731       S(0,1) = 1.0; S(1,0) = -1.0;      
00732 
00733       Matrix<double> dTheta = dera * S * Theta;
00734 
00735       Matrix<double> c2t = POM * Theta * NP;
00736       Matrix<double> dc2t = POM * dTheta * NP;
00737 
00738       Vector<double> ecefPos(3, 0.0), ecefVel(3, 0.0);
00739       for(int i=0; i<3; i++)
00740       {
00741          ecefPos(i) = ecefPosVel(i);
00742          ecefVel(i) = ecefPosVel(i+3);
00743       }
00744 
00745       Vector<double> j2kPos = transpose(c2t) * ecefPos;
00746       Vector<double> j2kVel = transpose(c2t) * ecefVel 
00747          +transpose(dc2t)* ecefPos;
00748 
00749       Vector<double> j2kPosVel(6,0.0);
00750       for(int i=0; i<3; i++)
00751       {
00752          j2kPosVel(i) = j2kPos(i);
00753          j2kPosVel(i+3) = j2kVel(i);
00754       }
00755 
00756       return j2kPosVel;
00757    }
00758 
00759 
00760    Vector<double> sunJ2kPosition(const DayTime& TT)
00761    {
00762       // P70~P73
00763 
00764       // Obliquity of J2000 ecliptic
00765       const double eps = 23.43929111 * PI / 180.0;
00766 
00767       // Julian cent. since J2000
00768       const double T = (TT-J2000)/86400.0/36525.0;  
00769 
00770       // [rad] Eq 3.43
00771       double M = std::fmod(0.9931267 + 99.9973583*T,1.0)*D2PI;   
00772 
00773       // Ecliptic longitude [rad]
00774       double L = std::fmod( 0.7859444 + M/D2PI 
00775          +(6892.0*std::sin(M)+72.0*std::sin(2.0*M))/1296.0e3
00776          ,1.0)*D2PI; 
00777 
00778       // Distance [m] Eq 3.44
00779       double r = 149.619e9-2.499e9*std::cos(M)-0.021e9*std::cos(2.0*M);    
00780 
00781 
00782       return Triple(r*std::cos(L),r*std::sin(L),0.0).R1(-eps*180.0/PI).toVector();
00783    }
00784 
00785    Vector<double> moonJ2kPosition(const DayTime& TT)
00786    {
00787       // Obliquity of J2000 ecliptic
00788       const double eps = 23.43929111 * PI / 180.0;
00789       const double Arcs = 3600.0*180.0/PI;
00790 
00791       // Julian cent. since J2000
00792       const double T = (TT-J2000)/86400.0/36525.0;  
00793 
00794       // Mean elements of lunar orbit
00795 
00796       // Eq 3.47
00797       double L0 = std::fmod(0.606433 + 1336.851344*T, 1.0);
00798       double l  = std::fmod( 0.374897 + 1325.552410*T,1.0)*D2PI;
00799       double lp = std::fmod( 0.993133 +   99.997361*T,1.0)*D2PI;
00800       double F  = std::fmod( 0.259086 + 1342.227825*T,1.0)*D2PI;
00801       double D  = std::fmod( 0.827361 + 1236.853086*T,1.0)*D2PI;
00802 
00803       // Ecliptic longitude (w.r.t. equinox of J2000)
00804 
00805       // Eq 3.48
00806       double dL = +22640.0*std::sin(l)-4586.0*std::sin(l-2*D)+2370.0*std::sin(2*D)
00807          +769.0*std::sin(2.0*l)-668.0*std::sin(lp)-412.0*std::sin(2.0*F)
00808          -212.0*std::sin(2.0*l-2.0*D)-206.0*std::sin(l+lp-2.0*D)
00809          +192.0*std::sin(l+2.0*D)-165.0*std::sin(lp-2.0*D)-125.0*std::sin(D) 
00810          -110.0*std::sin(l+lp)+148.0*std::sin(l-lp)-55.0*std::sin(2.0*F-2.0*D);
00811 
00812       double L = std::fmod( L0 + dL/1296.0e3, 1.0)*D2PI;  // [rad]
00813 
00814       // Ecliptic latitude
00815 
00816       // Eq 3.49
00817       double S = F + (dL+412.0*std::sin(2.0*F)+541.0*std::sin(lp)) / Arcs; 
00818       double h = F-2.0*D;
00819       double N =-526.0*std::sin(h) + 44.0*std::sin(l+h)-31.0*std::sin(-l+h)-23.0*std::sin(lp+h) 
00820          +11.0*std::sin(-lp+h)-25.0*std::sin(-2.0*l+F)+21.0*std::sin(-l+F);
00821 
00822       double B = (18520.0*std::sin(S)+N) / Arcs;   // [rad]
00823 
00824       // Distance [m] Eq 3.50
00825 
00826       double R = 385000e3-20905e3*std::cos(l)-3699e3*std::cos(2.0*D-l)
00827          -2956e3*std::cos(2.0*D)-570e3*std::cos(2.0*l)+246e3*std::cos(2.0*l-2.0*D) 
00828          -205e3*std::cos(lp-2.0*D)-171e3*std::cos(l+2.0*D)-152e3*std::cos(l+lp-2.0*D);   
00829 
00830       // Eq 3.51
00831       Triple rMoon(R*std::cos(L)*std::cos(B),
00832          R*std::sin(L)*std::cos(B),
00833          R*std::sin(B));
00834 
00835       return rMoon.R1(-eps*180.0/PI).toVector();
00836    }
00837 
00838 
00840    
00841       // Normalize angle into the range -pi <= a < +pi.
00842    double normalizeAngle(double a)
00843    {
00844       double w = fmod(a, D2PI);
00845       if (fabs(w) >= (D2PI*0.5)) 
00846       {
00847          w-= ((a<0.0)?-D2PI:D2PI);
00848       }
00849 
00850       return w;
00851    }
00852 
00853 
00854    // Rotate an r-matrix about the x-axis.
00855    Matrix<double> Rx(const double& angle)
00856    {
00857       const double s = std::sin(angle);
00858       const double c = std::cos(angle);
00859 
00860       const double a[9] = { 1, 0, 0, 0, c, s, 0,-s, c };
00861 
00862       Matrix<double> r(3,3,0.0);
00863       r = a;
00864 
00865       return r;
00866    }
00867 
00868    // Rotate an r-matrix about the y-axis.
00869    Matrix<double> Ry(const double& angle)
00870    {
00871       const double s = std::sin(angle);
00872       const double c = std::cos(angle);
00873 
00874       const double a[9] = { c, 0,-s, 0, 1, 0, s, 0, c };
00875 
00876       Matrix<double> r(3,3,0.0);
00877       r = a;
00878 
00879       return r;
00880    }
00881 
00882    // Rotate an r-matrix about the z-axis.
00883    Matrix<double> Rz(const double& angle)
00884    {
00885       const double s = std::sin(angle);
00886       const double c = std::cos(angle);
00887 
00888       const double a[9] = { c, s, 0,-s, c, 0, 0, 0, 1 };
00889 
00890       Matrix<double> r(3,3,0.0);
00891       r = a;
00892 
00893       return r;
00894    }
00895 
00896    Matrix<double> iauPmat76(const DayTime& TT)
00897    {
00898       // Interval between fundamental epoch J2000.0 and start epoch (JC). 
00899       const double t0 = 0.0;
00900 
00901       // Interval over which precession required (JC). 
00902       const double t = ( TT - J2000 ) / 86400.0 / DJC;
00903 
00904       // Euler angles. 
00905       const double tas2r = t * DAS2R;
00906       const double w = 2306.2181 + (1.39656 - 0.000139 * t0) * t0;
00907 
00908       double zeta = (w + ((0.30188 - 0.000344 * t0) + 0.017998 * t) * t) * tas2r;
00909 
00910       double z = (w + ((1.09468 + 0.000066 * t0) + 0.018203 * t) * t) * tas2r;
00911 
00912       double theta = ((2004.3109 + (-0.85330 - 0.000217 * t0) * t0)
00913          + ((-0.42665 - 0.000217 * t0) - 0.041833 * t) * t) * tas2r;
00914 
00915       return ( Rz(-z) * Ry(theta) * Rz(-zeta) );
00916 
00917    }  // End of method 'iauPmat76()'
00918 
00919 
00920    void nutationAngles(DayTime TT, double& dpsi, double& deps)
00921    {
00922       // Units of 0.1 milliarcsecond to radians 
00923       const double U2R = DAS2R / 1e4;
00924 
00925       // Table of multiples of arguments and coefficients 
00926       // ------------------------------------------------ 
00927 
00928       // The units for the sine and cosine coefficients are 0.1 mas and 
00929       // the same per Julian century 
00930 
00931       static const struct 
00932       {
00933          int nl,nlp,nf,nd,nom; // coefficients of l,l',F,D,Om 
00934          double sp,spt;        // longitude sine, 1 and t coefficients 
00935          double ce,cet;        // obliquity cosine, 1 and t coefficients 
00936       } x[] = {
00937 
00938          /* 1-10 */
00939          {  0,  0,  0,  0,  1, -171996.0, -174.2,  92025.0,    8.9 },
00940          {  0,  0,  0,  0,  2,    2062.0,    0.2,   -895.0,    0.5 },
00941          { -2,  0,  2,  0,  1,      46.0,    0.0,    -24.0,    0.0 },
00942          {  2,  0, -2,  0,  0,      11.0,    0.0,      0.0,    0.0 },
00943          { -2,  0,  2,  0,  2,      -3.0,    0.0,      1.0,    0.0 },
00944          {  1, -1,  0, -1,  0,      -3.0,    0.0,      0.0,    0.0 },
00945          {  0, -2,  2, -2,  1,      -2.0,    0.0,      1.0,    0.0 },
00946          {  2,  0, -2,  0,  1,       1.0,    0.0,      0.0,    0.0 },
00947          {  0,  0,  2, -2,  2,  -13187.0,   -1.6,   5736.0,   -3.1 },
00948          {  0,  1,  0,  0,  0,    1426.0,   -3.4,     54.0,   -0.1 },
00949 
00950          /* 11-20 */
00951          {  0,  1,  2, -2,  2,    -517.0,    1.2,    224.0,   -0.6 },
00952          {  0, -1,  2, -2,  2,     217.0,   -0.5,    -95.0,    0.3 },
00953          {  0,  0,  2, -2,  1,     129.0,    0.1,    -70.0,    0.0 },
00954          {  2,  0,  0, -2,  0,      48.0,    0.0,      1.0,    0.0 },
00955          {  0,  0,  2, -2,  0,     -22.0,    0.0,      0.0,    0.0 },
00956          {  0,  2,  0,  0,  0,      17.0,   -0.1,      0.0,    0.0 },
00957          {  0,  1,  0,  0,  1,     -15.0,    0.0,      9.0,    0.0 },
00958          {  0,  2,  2, -2,  2,     -16.0,    0.1,      7.0,    0.0 },
00959          {  0, -1,  0,  0,  1,     -12.0,    0.0,      6.0,    0.0 },
00960          { -2,  0,  0,  2,  1,      -6.0,    0.0,      3.0,    0.0 },
00961 
00962          /* 21-30 */
00963          {  0, -1,  2, -2,  1,      -5.0,    0.0,      3.0,    0.0 },
00964          {  2,  0,  0, -2,  1,       4.0,    0.0,     -2.0,    0.0 },
00965          {  0,  1,  2, -2,  1,       4.0,    0.0,     -2.0,    0.0 },
00966          {  1,  0,  0, -1,  0,      -4.0,    0.0,      0.0,    0.0 },
00967          {  2,  1,  0, -2,  0,       1.0,    0.0,      0.0,    0.0 },
00968          {  0,  0, -2,  2,  1,       1.0,    0.0,      0.0,    0.0 },
00969          {  0,  1, -2,  2,  0,      -1.0,    0.0,      0.0,    0.0 },
00970          {  0,  1,  0,  0,  2,       1.0,    0.0,      0.0,    0.0 },
00971          { -1,  0,  0,  1,  1,       1.0,    0.0,      0.0,    0.0 },
00972          {  0,  1,  2, -2,  0,      -1.0,    0.0,      0.0,    0.0 },
00973 
00974          /* 31-40 */
00975          {  0,  0,  2,  0,  2,   -2274.0,   -0.2,    977.0,   -0.5 },
00976          {  1,  0,  0,  0,  0,     712.0,    0.1,     -7.0,    0.0 },
00977          {  0,  0,  2,  0,  1,    -386.0,   -0.4,    200.0,    0.0 },
00978          {  1,  0,  2,  0,  2,    -301.0,    0.0,    129.0,   -0.1 },
00979          {  1,  0,  0, -2,  0,    -158.0,    0.0,     -1.0,    0.0 },
00980          { -1,  0,  2,  0,  2,     123.0,    0.0,    -53.0,    0.0 },
00981          {  0,  0,  0,  2,  0,      63.0,    0.0,     -2.0,    0.0 },
00982          {  1,  0,  0,  0,  1,      63.0,    0.1,    -33.0,    0.0 },
00983          { -1,  0,  0,  0,  1,     -58.0,   -0.1,     32.0,    0.0 },
00984          { -1,  0,  2,  2,  2,     -59.0,    0.0,     26.0,    0.0 },
00985 
00986          /* 41-50 */
00987          {  1,  0,  2,  0,  1,     -51.0,    0.0,     27.0,    0.0 },
00988          {  0,  0,  2,  2,  2,     -38.0,    0.0,     16.0,    0.0 },
00989          {  2,  0,  0,  0,  0,      29.0,    0.0,     -1.0,    0.0 },
00990          {  1,  0,  2, -2,  2,      29.0,    0.0,    -12.0,    0.0 },
00991          {  2,  0,  2,  0,  2,     -31.0,    0.0,     13.0,    0.0 },
00992          {  0,  0,  2,  0,  0,      26.0,    0.0,     -1.0,    0.0 },
00993          { -1,  0,  2,  0,  1,      21.0,    0.0,    -10.0,    0.0 },
00994          { -1,  0,  0,  2,  1,      16.0,    0.0,     -8.0,    0.0 },
00995          {  1,  0,  0, -2,  1,     -13.0,    0.0,      7.0,    0.0 },
00996          { -1,  0,  2,  2,  1,     -10.0,    0.0,      5.0,    0.0 },
00997 
00998          /* 51-60 */
00999          {  1,  1,  0, -2,  0,      -7.0,    0.0,      0.0,    0.0 },
01000          {  0,  1,  2,  0,  2,       7.0,    0.0,     -3.0,    0.0 },
01001          {  0, -1,  2,  0,  2,      -7.0,    0.0,      3.0,    0.0 },
01002          {  1,  0,  2,  2,  2,      -8.0,    0.0,      3.0,    0.0 },
01003          {  1,  0,  0,  2,  0,       6.0,    0.0,      0.0,    0.0 },
01004          {  2,  0,  2, -2,  2,       6.0,    0.0,     -3.0,    0.0 },
01005          {  0,  0,  0,  2,  1,      -6.0,    0.0,      3.0,    0.0 },
01006          {  0,  0,  2,  2,  1,      -7.0,    0.0,      3.0,    0.0 },
01007          {  1,  0,  2, -2,  1,       6.0,    0.0,     -3.0,    0.0 },
01008          {  0,  0,  0, -2,  1,      -5.0,    0.0,      3.0,    0.0 },
01009 
01010          /* 61-70 */
01011          {  1, -1,  0,  0,  0,       5.0,    0.0,      0.0,    0.0 },
01012          {  2,  0,  2,  0,  1,      -5.0,    0.0,      3.0,    0.0 },
01013          {  0,  1,  0, -2,  0,      -4.0,    0.0,      0.0,    0.0 },
01014          {  1,  0, -2,  0,  0,       4.0,    0.0,      0.0,    0.0 },
01015          {  0,  0,  0,  1,  0,      -4.0,    0.0,      0.0,    0.0 },
01016          {  1,  1,  0,  0,  0,      -3.0,    0.0,      0.0,    0.0 },
01017          {  1,  0,  2,  0,  0,       3.0,    0.0,      0.0,    0.0 },
01018          {  1, -1,  2,  0,  2,      -3.0,    0.0,      1.0,    0.0 },
01019          { -1, -1,  2,  2,  2,      -3.0,    0.0,      1.0,    0.0 },
01020          { -2,  0,  0,  0,  1,      -2.0,    0.0,      1.0,    0.0 },
01021 
01022          /* 71-80 */
01023          {  3,  0,  2,  0,  2,      -3.0,    0.0,      1.0,    0.0 },
01024          {  0, -1,  2,  2,  2,      -3.0,    0.0,      1.0,    0.0 },
01025          {  1,  1,  2,  0,  2,       2.0,    0.0,     -1.0,    0.0 },
01026          { -1,  0,  2, -2,  1,      -2.0,    0.0,      1.0,    0.0 },
01027          {  2,  0,  0,  0,  1,       2.0,    0.0,     -1.0,    0.0 },
01028          {  1,  0,  0,  0,  2,      -2.0,    0.0,      1.0,    0.0 },
01029          {  3,  0,  0,  0,  0,       2.0,    0.0,      0.0,    0.0 },
01030          {  0,  0,  2,  1,  2,       2.0,    0.0,     -1.0,    0.0 },
01031          { -1,  0,  0,  0,  2,       1.0,    0.0,     -1.0,    0.0 },
01032          {  1,  0,  0, -4,  0,      -1.0,    0.0,      0.0,    0.0 },
01033 
01034          /* 81-90 */
01035          { -2,  0,  2,  2,  2,       1.0,    0.0,     -1.0,    0.0 },
01036          { -1,  0,  2,  4,  2,      -2.0,    0.0,      1.0,    0.0 },
01037          {  2,  0,  0, -4,  0,      -1.0,    0.0,      0.0,    0.0 },
01038          {  1,  1,  2, -2,  2,       1.0,    0.0,     -1.0,    0.0 },
01039          {  1,  0,  2,  2,  1,      -1.0,    0.0,      1.0,    0.0 },
01040          { -2,  0,  2,  4,  2,      -1.0,    0.0,      1.0,    0.0 },
01041          { -1,  0,  4,  0,  2,       1.0,    0.0,      0.0,    0.0 },
01042          {  1, -1,  0, -2,  0,       1.0,    0.0,      0.0,    0.0 },
01043          {  2,  0,  2, -2,  1,       1.0,    0.0,     -1.0,    0.0 },
01044          {  2,  0,  2,  2,  2,      -1.0,    0.0,      0.0,    0.0 },
01045 
01046          /* 91-100 */
01047          {  1,  0,  0,  2,  1,      -1.0,    0.0,      0.0,    0.0 },
01048          {  0,  0,  4, -2,  2,       1.0,    0.0,      0.0,    0.0 },
01049          {  3,  0,  2, -2,  2,       1.0,    0.0,      0.0,    0.0 },
01050          {  1,  0,  2, -2,  0,      -1.0,    0.0,      0.0,    0.0 },
01051          {  0,  1,  2,  0,  1,       1.0,    0.0,      0.0,    0.0 },
01052          { -1, -1,  0,  2,  1,       1.0,    0.0,      0.0,    0.0 },
01053          {  0,  0, -2,  0,  1,      -1.0,    0.0,      0.0,    0.0 },
01054          {  0,  0,  2, -1,  2,      -1.0,    0.0,      0.0,    0.0 },
01055          {  0,  1,  0,  2,  0,      -1.0,    0.0,      0.0,    0.0 },
01056          {  1,  0, -2, -2,  0,      -1.0,    0.0,      0.0,    0.0 },
01057 
01058          /* 101-106 */
01059          {  0, -1,  2,  0,  1,      -1.0,    0.0,      0.0,    0.0 },
01060          {  1,  1,  0, -2,  1,      -1.0,    0.0,      0.0,    0.0 },
01061          {  1,  0, -2,  2,  0,      -1.0,    0.0,      0.0,    0.0 },
01062          {  2,  0,  0,  2,  0,       1.0,    0.0,      0.0,    0.0 },
01063          {  0,  0,  2,  4,  2,      -1.0,    0.0,      0.0,    0.0 },
01064          {  0,  1,  0,  1,  0,       1.0,    0.0,      0.0,    0.0 }
01065       };
01066 
01067       // Number of terms in the series 
01068       const int NT = (int) (sizeof x / sizeof x[0]);
01069 
01070 
01071       // Interval between fundamental epoch J2000.0 and given date (JC). 
01072       const double t = ( TT - J2000 ) / 86400.0 / DJC;
01073 
01074       // Fundamental arguments 
01075       // --------------------- 
01076 
01077       // Mean longitude of Moon minus mean longitude of Moon's perigee. 
01078       double el = normalizeAngle(
01079          (485866.733 + (715922.633 + (31.310 + 0.064 * t) * t) * t)
01080          * DAS2R + fmod(1325.0 * t, 1.0) * D2PI);
01081 
01082       // Mean longitude of Sun minus mean longitude of Sun's perigee. 
01083       double elp = normalizeAngle(
01084          (1287099.804 + (1292581.224 + (-0.577 - 0.012 * t) * t) * t)
01085          * DAS2R + fmod(99.0 * t, 1.0) * D2PI);
01086 
01087       // Mean longitude of Moon minus mean longitude of Moon's node. 
01088       double f = normalizeAngle(
01089          (335778.877 + (295263.137 + (-13.257 + 0.011 * t) * t) * t)
01090          * DAS2R + fmod(1342.0 * t, 1.0) * D2PI);
01091 
01092       // Mean elongation of Moon from Sun. 
01093       double d = normalizeAngle(
01094          (1072261.307 + (1105601.328 + (-6.891 + 0.019 * t) * t) * t)
01095          * DAS2R + fmod(1236.0 * t, 1.0) * D2PI);
01096 
01097       // Longitude of the mean ascending node of the lunar orbit on the 
01098       // ecliptic, measured from the mean equinox of date. 
01099       double om = normalizeAngle(
01100          (450160.280 + (-482890.539 + (7.455 + 0.008 * t) * t) * t)
01101          * DAS2R + fmod(-5.0 * t, 1.0) * D2PI);
01102 
01103 
01104       // Nutation series 
01105       // --------------- 
01106 
01107       // Initialize nutation components. 
01108       double dp = 0.0;
01109       double de = 0.0;
01110 
01111       // Sum the nutation terms, ending with the biggest. 
01112       for (int j = NT-1; j >= 0; j--) 
01113       {
01114 
01115          // Form argument for current term. 
01116          double arg = (double)x[j].nl  * el
01117             + (double)x[j].nlp * elp
01118             + (double)x[j].nf  * f
01119             + (double)x[j].nd  * d
01120             + (double)x[j].nom * om;
01121 
01122          // Accumulate current nutation term. 
01123          double s = x[j].sp + x[j].spt * t;
01124          double c = x[j].ce + x[j].cet * t;
01125          if (s != 0.0) dp += s * std::sin(arg);
01126          if (c != 0.0) de += c * std::cos(arg);
01127       }
01128 
01129       // Convert results from 0.1 mas units to radians. 
01130       dpsi = dp * U2R;
01131       deps = de * U2R;
01132 
01133    }  // End of 'nutationAngles()'
01134 
01135 
01136    double meanObliquity(DayTime TT)
01137    {
01138       // Interval between fundamental epoch J2000.0 and given date (JC)
01139       const double t = ( TT - J2000 ) / 86400.0 / DJC;
01140       const double t2 = t*t;
01141       const double t3 = t2*t;
01142 
01143       return (84381.448-46.8150*t-0.00059*t2+0.001813*t3)*DAS2R;
01144    }
01145 
01146    double iauEqeq94(DayTime TT,double eps,double dPsi)
01147    {
01148       // Interval between fundamental epoch J2000.0 and given date (JC). 
01149       double t = ( TT - J2000 ) / 86400.0 / DJC;
01150 
01151       // Longitude of the mean ascending node of the lunar orbit on the 
01152       // ecliptic, measured from the mean equinox of date. 
01153       double om = normalizeAngle((450160.280 + (-482890.539
01154          + (7.455 + 0.008 * t) * t) * t) * DAS2R
01155          + fmod(-5.0 * t, 1.0) * D2PI);
01156 
01157       // Nutation components and mean obliquity. 
01158       //double dpsi(0.0), deps(0.0);
01159       //nutationAngles(TT, dpsi, deps);
01160 
01161       //double eps0 = meanObliquity(TT);
01162 
01163       // Equation of the equinoxes. 
01164       double ee = dPsi * std::cos(eps) 
01165          + DAS2R*(0.00264 * std::sin(om) + 0.000063 * std::sin(om + om));
01166 
01167       return ee;
01168    }
01169 
01170    double iauGmst82(DayTime UT1)
01171    {
01172       // Coefficients of IAU 1982 GMST-UT1 model 
01173       const double A = 24110.54841  -  86400.0 / 2.0;
01174       const double B = 8640184.812866;
01175       const double C = 0.093104;
01176       const double D =  -6.2e-6;
01177 
01178       // Note: the first constant, A, has to be adjusted by 12 hours 
01179       // because the UT1 is supplied as a Julian date, which begins  
01180       // at noon.                                                    
01181 
01182       // Julian centuries since fundamental epoch. 
01183       double d2 = DayTime::JD_TO_MJD;
01184       double d1 = UT1.MJD();
01185       double t = ( UT1.MJD() - J2000.MJD() ) / DJC;
01186 
01187       // Fractional part of JD(UT1), in seconds. 
01188       double f = 86400.0 * (fmod(d1, 1.0) + fmod(d2, 1.0));
01189 
01190       // GMST at this UT1. 
01191       double gmst = normalizeAngle(
01192          DS2R * ((A + (B + (C + D * t) * t) * t) + f));
01193 
01194       return gmst;
01195 
01196    }  // End of method 'iauGmst82()'
01197 
01198       // Greenwich mean sidereal time by IAU 2000 model
01199    double iauGmst00(DayTime UT1,DayTime TT)
01200    {
01201 
01202       // TT Julian centuries since J2000.0. 
01203       double t = ( TT - J2000 ) / 86400.0 / DJC;
01204 
01205       /* Greenwich Mean Sidereal Time, IAU 2000. */
01206       double gmst = normalizeAngle(earthRotationAngle(UT1) +
01207          (     0.014506   +
01208          (  4612.15739966 +
01209          (     1.39667721 +
01210          (    -0.00009344 +
01211          (     0.00001882 )
01212          * t) * t) * t) * t) * DAS2R);
01213 
01214       return gmst;
01215 
01216    }  // End of method 'ReferenceFrames::iauGmst00()'
01217 
01218 
01219    // Nutation matrix from nutation angles
01220    Matrix<double> iauNmat(const double& eps, const double& dpsi, const double& deps)
01221    {
01222       return ( Rx(-(eps+deps)) * Rz(-dpsi) * Rx(eps) );
01223    }
01224 
01225 
01226       // Get earth rotation angle
01227    double earthRotationAngle(DayTime UT1)
01228    {
01229       // IAU 2000 model
01230       double t = (UT1 -J2000)/86400.0;
01231       double f = fmod(UT1.MJD(),1.0) + fmod(DayTime::JD_TO_MJD, 1.0);
01232 
01233       double era = normalizeAngle(D2PI*(f+0.7790572732640+0.00273781191135448*t));
01234 
01235       return era;
01236    }
01237 
01238       /*Earth rotation angle first order rate.
01239        *  @param mjdTT         Modified Julian Date in TT
01240        *  @return              d(GAST)/d(t) in [rad]
01241        */
01242    double earthRotationAngleRate1(DayTime TT)
01243    {
01244       double T = ( TT - J2000 )/86400.0/36525.0;
01245       double dera = (1.002737909350795 + 5.9006e-11 * T - 5.9e-15 * T * T ) 
01246          * D2PI / 86400.0;
01247 
01248       return dera;
01249    }
01250 
01251 
01252    
01253  
01254 } // end namespace gpstk

Generated on Tue May 22 03:30:58 2012 for GPS ToolKit Software Library by  doxygen 1.3.9.1