IERSConventions.cpp

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

Generated on Wed Jun 19 03:31:06 2013 for GPS ToolKit Software Library by  doxygen 1.3.9.1