PlanetEphemeris.cpp

Go to the documentation of this file.
00001 #pragma ident "$Id: PlanetEphemeris.cpp 2950 2011-10-27 16:21:52Z 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 #include "PlanetEphemeris.hpp"
00031 #include "DayTime.hpp"
00032 #include "Matrix.hpp"
00033 #include "Logger.hpp"
00034 #include "DebugUtils.hpp"
00035 
00036 namespace gpstk
00037 {
00038    using namespace std;
00039    using namespace StringUtils;
00040 
00041    void PlanetEphemeris::readASCIIheader(string filename) 
00042       throw(Exception)
00043    {
00044       try 
00045       {
00046          // open the file
00047          ifstream strm;
00048          strm.open(filename.c_str());
00049          if(!strm) 
00050          {
00051             Exception e("Failed to open input file " + filename + ". Abort.");
00052             GPSTK_THROW(e);
00053          }
00054 
00055          // clear existing data
00056          constants.clear();
00057 
00058          // read the file one line at a time, process depending on the value of group
00059          int group=0,n=0;        // n will count lines/items within a group
00060          string line,word;
00061          vector<string> const_names;      // Temporary - name,value stored in map constants
00062          while(1) 
00063          {
00064             getline(strm,line);
00065             stripTrailing(line,'\r');
00066 
00067             // catch new groups
00068             if(line.substr(0,5) == "GROUP") 
00069             {
00070                word = stripFirstWord(line);
00071                group = asInt(stripFirstWord(line));
00072                n = 0;            // n will count lines/items within a group
00073                continue;
00074             }
00075 
00076             // skip blank lines
00077             stripLeading(line," ");
00078             if(line.empty()) 
00079             {
00080                if(strm.eof() || !strm.good()) break;     // if the last line is blank
00081                else continue;
00082             }
00083 
00084             // process entire line at once
00085             // first line (no GROUP)
00086             if(group == 0) 
00087             {
00088                word = stripFirstWord(line);
00089                word = stripFirstWord(line);        // ignore KSIZE
00090                word = stripFirstWord(line);
00091                if(word == "NCOEFF=") 
00092                {
00093                   Ncoeff = asInt(stripFirstWord(line));
00094                   continue;
00095                }
00096                else 
00097                {
00098                   Exception e("Confused on the first line - 3rd word is not NCOEFF=");
00099                   GPSTK_THROW(e);
00100                }
00101             }
00102             // GROUP 1010
00103             else if(group == 1010) 
00104             {
00105                if(n > 2) 
00106                {                         // this should not happen
00107                   Exception e("Too many labels under GROUP 1010");
00108                   GPSTK_THROW(e);
00109                }
00110                else 
00111                {
00112                   stripTrailing(line," ");
00113                   label[n++] = line;
00114                   continue;
00115                }
00116             }
00117             // GROUP 1030
00118             else if(group == 1030) 
00119             {
00120                // start and stop times. These are meaningless here, because they will be
00121                // determined by the data that follows this header, and so are meaningful
00122                // only in the binary file.
00123                startJD = for2doub(stripFirstWord(line));
00124                endJD = for2doub(stripFirstWord(line));
00125                // interval in days covered by each block of coefficients
00126                interval = for2doub(stripFirstWord(line));
00127             }
00128             // GROUP 1070 - end-of-header
00129             else if(group == 1070) 
00130             {
00131                break;
00132             }
00133 
00134             // process the line one (whitespace-separated) word at a time
00135             while(!line.empty()) 
00136             {
00137                word = stripFirstWord(line);
00138 
00139                if(group == 1040) 
00140                {
00141                   if(n++ == 0) 
00142                   {
00143                      Nconst = asInt(word);
00144                   }
00145                   else 
00146                   {
00147                      const_names.push_back(word);
00148                   }
00149                }
00150                else if(group == 1041) 
00151                {
00152                   if(n++ == 0) 
00153                   {
00154                      if(Nconst != asInt(word)) 
00155                      {
00156                         Exception e("Nconst does not match N in GROUP 1041 : " +
00157                            asString(Nconst) + " != " + word);
00158                         GPSTK_THROW(e);
00159                      }
00160                   }
00161                   else
00162                      constants[const_names[n-2]] = for2doub(word);
00163                }
00164                else if(group == 1050) 
00165                {
00166                   if(n < 13) 
00167                   {
00168                      c_offset[n] = asInt(word);
00169                   }
00170                   else if(n < 26) 
00171                   {
00172                      c_ncoeff[n-13] = asInt(word);
00173                   }
00174                   else 
00175                   {
00176                      c_nsets[n-26] = asInt(word);
00177                   }
00178                   n++;
00179                }
00180                else 
00181                {
00182                   Exception e("Confused about GROUP : " + asString(group));
00183                   GPSTK_THROW(e);
00184                }
00185             }  // end loop over words
00186 
00187             if(strm.eof() || !strm.good()) break;     // if the last line is not blank
00188 
00189          }  // end read loop over lines
00190 
00191          strm.clear();
00192          strm.close();
00193 
00194          // test that we got a full header
00195          if(group != 1070) 
00196          {
00197             Exception e("Premature end of header");
00198             GPSTK_THROW(e);
00199          }
00200 
00201          // EphemerisNumber != -1 means the header is complete
00202          EphemerisNumber = int(constants["DENUM"]);
00203 
00204          // clear the data arrays
00205          store.clear();
00206       }
00207       catch(Exception& e) { GPSTK_RETHROW(e); }
00208       catch(exception& e) { Exception E("std except: "+string(e.what())); GPSTK_THROW(E); }
00209       catch(...) { Exception e("Unknown exception"); GPSTK_THROW(e); }
00210 
00211    }  // End of method 'PlanetEphemeris::readASCIIheader()'
00212 
00213 
00214    int PlanetEphemeris::readASCIIdata(vector<string>& filenames) 
00215       throw(Exception)
00216    {
00217       try 
00218       {
00219          int i,n;
00220          double jd;
00221 
00222          if(filenames.size() == 0) return 0;
00223 
00224          // read the files, in any order; the data map will be sorted on time
00225          for(i=0; i<filenames.size(); i++) 
00226          {
00227             int iret = readASCIIdata(filenames[i]);
00228             if(iret) return iret;
00229          }
00230 
00231          // set the start and stop times in the header
00232          map<double,vector<double> >::iterator it = store.begin();
00233          startJD = it->second[0];
00234          it = store.end(); it--;
00235          endJD = it->second[1];
00236 
00237          // Mod the header labels to reflect the new time limits
00238          ostringstream oss;
00239          DayTime tt;
00240          tt.setMJD(startJD - DayTime::JD_TO_MJD);
00241          oss << "Start Epoch: JED= " << fixed << setw(10) << setprecision(1) << startJD
00242             << tt.printf(" %4Y %b %2d %02H:%02M:%02S");
00243          label[1] = leftJustify(oss.str(),81);
00244          oss.seekp(ios_base::beg);
00245          tt.setMJD(endJD - DayTime::JD_TO_MJD);
00246          oss << "Final Epoch: JED= " << fixed << setw(10) << setprecision(1) << endJD
00247             << tt.printf(" %4Y %b %2d %02H:%02M:%02S");
00248          label[2] = leftJustify(oss.str(),81);
00249 
00250          return 0;
00251       }
00252       catch(Exception& e) { GPSTK_RETHROW(e); }
00253       catch(exception& e) { Exception E("std except: "+string(e.what())); GPSTK_THROW(E); }
00254       catch(...) { Exception e("Unknown exception"); GPSTK_THROW(e); }
00255 
00256    }  // End of method 'PlanetEphemeris::readASCIIdata()'
00257 
00258 
00259    int PlanetEphemeris::readASCIIdata(string filename) 
00260       throw(Exception)
00261    {
00262       try 
00263       {
00264          if(EphemerisNumber < 0) 
00265          {
00266             Exception e("readASCIIdata called before header read");
00267             GPSTK_THROW(e);
00268          }
00269 
00270          int iret=0;
00271          string line,word;
00272          ifstream strm;
00273 
00274          // open the file
00275          strm.open(filename.c_str());
00276          if(!strm) 
00277          {
00278             Exception e("Could not open file " + filename);
00279             GPSTK_THROW(e);
00280          }
00281 
00282          // expect this many lines per record
00283          int nmax = Ncoeff/3 + (Ncoeff % 3 ? 1 : 0);
00284 
00285          // loop over lines in the file
00286          int ntot=0;                      // counts the total number of lines
00287          int n=0;                         // counts the lines within a set of coefficients
00288          int nc=0;                        // count coefficients within a record
00289          int rec;
00290          vector<double> data_vector;
00291          while(1) 
00292          {
00293             getline(strm,line);
00294             stripTrailing(line,'\r');
00295 
00296             if(line.empty()) 
00297             {
00298                if(strm.eof()) break;
00299                if(!strm.good()) { iret = -1; break; }
00300                continue;
00301             }
00302 
00303             if(n == 0) 
00304             {
00305                rec = asInt(stripFirstWord(line));           // 1st word is the record number
00306                int ncc = asInt(stripFirstWord(line));       // 2nd word is ncoeff
00307                if(ncc != Ncoeff) 
00308                {
00309                   Exception e("readASCIIdata finds conflicting sizes in header ("
00310                      + asString(Ncoeff) + ") and data (" + asString(ncc) + ") in file "
00311                      + filename + " at line #" + asString(ntot));
00312                   GPSTK_THROW(e);
00313                }
00314                nc = 0;
00315             }
00316             else 
00317             {
00318                for(int j=0; j<3; j++) 
00319                {
00320                   double coeff = for2doub(stripFirstWord(line));
00321                   nc++;
00322                   data_vector.push_back(coeff);
00323                   if(nc >= Ncoeff) 
00324                   {
00325                      vector<double> dtemp=data_vector;
00326                      store[data_vector[0]] = dtemp;
00327                      data_vector.clear();
00328                      break;
00329                   }
00330                }
00331             }
00332 
00333             if(strm.eof()) break;
00334             if(!strm.good()) { iret = -1; break; }
00335 
00336             if(n == nmax) n=0; else n++;
00337             ntot++;
00338          }
00339 
00340          strm.close();
00341 
00342          return iret;
00343       }
00344       catch(Exception& e) { GPSTK_RETHROW(e); }
00345       catch(exception& e) { Exception E("std except: "+string(e.what())); GPSTK_THROW(E); }
00346       catch(...) { Exception e("Unknown exception"); GPSTK_THROW(e); }
00347 
00348    }  // End of method 'PlanetEphemeris::readASCIIdata()'
00349 
00350 
00351    int PlanetEphemeris::writeASCIIheader(ostream& os) 
00352       throw(Exception)
00353    {
00354       try 
00355       {
00356          if(EphemerisNumber < 0) return -4;
00357 
00358          int i;
00359          string str;
00360          string blank(81,' '); blank += string("\n");
00361          ostringstream oss;
00362 
00363          oss << "KSIZE= 0000    NSIZE=" << setw(5) << Ncoeff << blank;
00364          os << leftJustify(oss.str(),81) << endl << blank; oss.seekp(ios_base::beg);
00365 
00366          os << leftJustify("GROUP   1010",81) << endl << blank;
00367          for(i=0; i<3; i++) 
00368          {
00369             str = label[i];
00370             os << leftJustify(str,81) << endl;
00371          }
00372          os << blank;
00373 
00374          os << leftJustify("GROUP   1030",81) << endl << blank;
00375          oss << fixed << setprecision(2) << setw(12) << startJD
00376             << setw(12) << endJD << setw(12) << interval << blank;
00377          os << leftJustify(oss.str(),81) << endl << blank; oss.seekp(ios_base::beg);
00378 
00379          os << leftJustify("GROUP   1040",81) << endl << blank;
00380          oss << setw(6) << Nconst << blank;
00381          os << leftJustify(oss.str(),81) << endl; oss.seekp(ios_base::beg);
00382 
00383          map<string,double>::const_iterator it=constants.begin();
00384          for(i=0; it != constants.end(); it++,i++) 
00385          {
00386             oss << leftJustify("  " + it->first,8);
00387             if((i+1)%10 == 0) 
00388             {
00389                oss << blank;
00390                os << leftJustify(oss.str(),81) << endl;
00391                oss.seekp(ios_base::beg);
00392             }
00393          }
00394          if(Nconst%10 != 0) 
00395          {
00396             oss << blank;
00397             os << leftJustify(oss.str(),81) << endl;
00398             oss.seekp(ios_base::beg);
00399          }
00400          os << blank;
00401 
00402          os << leftJustify("GROUP   1041",81) << endl << blank;
00403          oss << setw(6) << Nconst << blank;
00404          os << leftJustify(oss.str(),81) << endl; oss.seekp(ios_base::beg);
00405 
00406          for(i=0,it=constants.begin(); it != constants.end(); it++,i++) 
00407          {
00408             oss << leftJustify("  " + doub2for(it->second,24,2),26);
00409             if((i+1)%3 == 0) 
00410             {
00411                oss << blank;
00412                os << leftJustify(oss.str(),81) << endl;
00413                oss.seekp(ios_base::beg);
00414             }
00415          }
00416          if(Nconst%3 != 0) 
00417          {
00418             i--;
00419             while((i+1)%3 != 0) { oss << leftJustify("  " + doub2for(0.0,24,2),26); i++; }
00420             oss << blank;
00421             os << leftJustify(oss.str(),81) << endl;
00422             oss.seekp(ios_base::beg);
00423          }
00424          os << blank;
00425 
00426          os << leftJustify("GROUP   1050",81) << endl << blank;
00427          for(i=0; i<13; i++) oss << rightJustify(asString(c_offset[i]),6);
00428          oss << blank; os << leftJustify(oss.str(),81) << endl; oss.seekp(ios_base::beg);
00429          for(i=0; i<13; i++) oss << rightJustify(asString(c_ncoeff[i]),6);
00430          oss << blank; os << leftJustify(oss.str(),81) << endl; oss.seekp(ios_base::beg);
00431          for(i=0; i<13; i++) oss << rightJustify(asString(c_nsets[i]),6);
00432          oss << blank; os << leftJustify(oss.str(),81) << endl; oss.seekp(ios_base::beg);
00433          os << blank;
00434 
00435          os << leftJustify("GROUP   1070",81) << endl << blank;
00436          os << blank;
00437 
00438          return 0;
00439       }
00440       catch(Exception& e) { GPSTK_RETHROW(e); }
00441       catch(exception& e) { Exception E("std except: "+string(e.what())); GPSTK_THROW(E); }
00442       catch(...) { Exception e("Unknown exception"); GPSTK_THROW(e); }
00443 
00444    }  // End of method 'PlanetEphemeris::writeASCIIheader()'
00445 
00446 
00447    int PlanetEphemeris::writeASCIIdata(ostream& os) 
00448       throw(Exception)
00449    {
00450       try 
00451       {
00452          if(EphemerisNumber < 0) return -4;
00453 
00454          string blank(81,' '); blank += string("\n");
00455          int i,nrec;
00456          ostringstream oss;
00457 
00458          map<double,vector<double> >::iterator jt;
00459          for(nrec=1,jt=store.begin(); jt != store.end(); jt++,nrec++) 
00460          {
00461             os << setw(6) << nrec << setw(6) << Ncoeff << " " << endl;
00462             for(i=0; i<Ncoeff; i++) 
00463             {
00464                oss << leftJustify("  " + doub2for(jt->second[i],24,2),26);
00465                if((i+1)%3 == 0) 
00466                {
00467                   oss << blank;
00468                   os << leftJustify(oss.str(),81) << endl;
00469                   oss.seekp(ios_base::beg);
00470                }
00471             }
00472             if(Ncoeff % 3 != 0) 
00473             {
00474                i--;
00475                while((i+1)%3 != 0) 
00476                {
00477                   oss << leftJustify("  " + doub2for(0.0,24,2),26);
00478                   i++;
00479                }
00480                oss << blank;
00481                os << leftJustify(oss.str(),81) << endl;
00482                oss.seekp(ios_base::beg);
00483             }
00484          }
00485 
00486          // TD clear the array after writing
00487          //store.clear();
00488 
00489          return 0;
00490       }
00491       catch(Exception& e) { GPSTK_RETHROW(e); }
00492       catch(exception& e) { Exception E("std except: "+string(e.what())); GPSTK_THROW(E); }
00493       catch(...) { Exception e("Unknown exception"); GPSTK_THROW(e); }
00494 
00495    }  // End of method 'PlanetEphemeris::writeASCIIdata(ostream& os) '
00496 
00497 
00498    int PlanetEphemeris::writeBinaryFile(string filename) 
00499       throw(Exception)
00500    {
00501       try 
00502       {
00503          int i,recLength;
00504          string str;
00505 
00506          if(EphemerisNumber <= 0) return -4;
00507 
00508          // open the output file
00509          ofstream strm;
00510          strm.open(filename.c_str(),ios::out | ios::binary);
00511          if(!strm) 
00512          {
00513             Exception e("Failed to open output file " + filename + ". Abort.");
00514             GPSTK_THROW(e);
00515          }
00516 
00517          // write the header records: two of them, both of length Ncoeff*sizeof(double)
00518          // the structure and ordering taken from the JPL code
00519          recLength = 0;
00520 
00521          // first header record -------------------------------------------------
00522          // 1. 3 labels each of length 84
00523          for(i=0; i<3; i++) 
00524          {
00525             str = label[i];
00526             writeBinary(strm,leftJustify(str,84).c_str(),84);
00527             recLength += 84;
00528          }
00529 
00530          // 2. 400 keys from the const array, each of length 6
00531          map<string,double>::const_iterator it=constants.begin();
00532          for(i=0; i<400; i++) 
00533          {
00534             if(it != constants.end()) 
00535             {
00536                str = it->first;
00537                writeBinary(strm,leftJustify(str,6).c_str(),6);
00538                it++;
00539             }
00540             else
00541                writeBinary(strm,"      ",6);
00542             recLength += 6;
00543          }
00544 
00545          // 3. the three times
00546          writeBinary(strm,(char *)&startJD,sizeof(double));
00547          writeBinary(strm,(char *)&endJD,sizeof(double));
00548          writeBinary(strm,(char *)&interval,sizeof(double));
00549          recLength += 3*sizeof(double);
00550 
00551          // 4. Ncoeff
00552          writeBinary(strm,(char *)&Ncoeff,sizeof(int));
00553          recLength += sizeof(int);
00554 
00555          // 5. AU and EMRAT
00556          writeBinary(strm,(char *)&constants["AU"],sizeof(double));
00557          writeBinary(strm,(char *)&constants["EMRAT"],sizeof(double));
00558          recLength += 2*sizeof(double);
00559 
00560          // 6. c_arrays for the first 12 planets
00561          for(i=0; i<12; i++) {
00562             writeBinary(strm,(char *)&c_offset[i],sizeof(int));
00563             writeBinary(strm,(char *)&c_ncoeff[i],sizeof(int));
00564             writeBinary(strm,(char *)&c_nsets[i],sizeof(int));
00565             recLength += 3*sizeof(int);
00566          }
00567 
00568          // 7. DENUM
00569          writeBinary(strm,(char *)&constants["DENUM"],sizeof(double));
00570          recLength += sizeof(double);
00571 
00572          // 8. c_arrays for libration
00573          writeBinary(strm,(char *)&c_offset[12],sizeof(int));
00574          writeBinary(strm,(char *)&c_ncoeff[12],sizeof(int));
00575          writeBinary(strm,(char *)&c_nsets[12],sizeof(int));
00576          recLength += 3*sizeof(int);
00577 
00578          // 9. pad
00579          char c=' ';
00580          for(i=0; i < Ncoeff*sizeof(double) - recLength; i++)
00581             writeBinary(strm,&c,1);
00582 
00583          // second header record -------------------------------------------------
00584          // the second header record: 400 values from the const array
00585          double z=0.0;
00586          it = constants.begin();
00587          for(i=0; i<400; i++)
00588          {
00589             if(it != constants.end()) 
00590             {
00591                writeBinary(strm,(char *)&(it->second),sizeof(double));
00592                it++;
00593             }
00594             else
00595                writeBinary(strm,(char *)&z,sizeof(double));
00596          }
00597          for(i=0; i < (400-Nconst)*sizeof(double); i++)
00598             writeBinary(strm,&c,1);
00599 
00600          // data records ---------------------------------------------------------
00601          // the data, in time order
00602          int nrec=1;
00603          map<double,vector<double> >::iterator jt;
00604          for(jt=store.begin(); jt != store.end(); jt++) 
00605          {
00606             for(i=0; i<jt->second.size(); i++)
00607                writeBinary(strm,(char *)&jt->second[i],sizeof(double));
00608             nrec++;
00609          }
00610 
00611          // TD after writing it out, clear the store array
00612          //store.clear();
00613 
00614          strm.clear();
00615          strm.close();
00616 
00617          return 0;
00618       }
00619       catch(Exception& e) { GPSTK_RETHROW(e); }
00620       catch(exception& e) { Exception E("std except: "+string(e.what())); GPSTK_THROW(E); }
00621       catch(...) { Exception e("Unknown exception"); GPSTK_THROW(e); }
00622 
00623    }  // End of method 'PlanetEphemeris::writeBinaryFile()'
00624 
00625 
00626    int PlanetEphemeris::readBinaryFile(string filename) 
00627       throw(Exception)
00628    {
00629       try 
00630       {
00631          int iret;
00632          readBinaryHeader(filename);
00633          iret = readBinaryData(true);  // true: store ALL the data in map
00634 
00635          istrm.clear();
00636          istrm.close();
00637 
00638          return iret;
00639       }
00640       catch(Exception& e) { GPSTK_RETHROW(e); }
00641       catch(exception& e) { Exception E("std except: "+string(e.what())); GPSTK_THROW(E); }
00642       catch(...) { Exception e("Unknown exception"); GPSTK_THROW(e); }
00643 
00644    }  // End of method 'PlanetEphemeris::readBinaryFile(string filename)'
00645 
00646    
00647    int PlanetEphemeris::initializeWithBinaryFile(string filename) 
00648       throw(Exception)
00649    {
00650       try 
00651       {
00652          int iret;
00653 
00654          readBinaryHeader(filename);
00655          iret = readBinaryData(false);    // false: don't store data in map
00656          if(iret == 0) 
00657          {
00658             // EphemerisNumber == -1 means the header has not been read
00659             // EphemerisNumber ==  0 means the fileposMap has not been read (binary)
00660             // EphemerisNumber == constants["DENUM"] means object has been initialized
00661             //                       (binary file), or header read (ASCII file)
00662             EphemerisNumber = int(constants["DENUM"]);
00663          }
00664 
00665          return iret;
00666       }
00667       catch(Exception& e) { GPSTK_RETHROW(e); }
00668       catch(exception& e) { Exception E("std except: "+string(e.what())); GPSTK_THROW(E); }
00669       catch(...) { Exception e("Unknown exception"); GPSTK_THROW(e); }
00670 
00671    }  // End of method 'PlanetEphemeris::initializeWithBinaryFile(string filename) '
00672 
00673 
00674       // return 0 ok, or (from seekToJD)
00675       // -1 out of range : input time is before the first time in file
00676       // -2 out of range : input time is after the last time in file, or in a gap
00677       // -3 stream is not open or not good, or EOF was found prematurely
00678       // -4 EphemerisNumber is not defined
00679       // For -3,-4 : initializeWithBinaryFile() has not been called, or reading failed.
00680    int PlanetEphemeris::computeState( double tt,
00681                                       PlanetEphemeris::Planet target,
00682                                       PlanetEphemeris::Planet center,
00683                                       double PV[6],
00684                                       bool kilometers) 
00685       throw(Exception)
00686    {
00687       try 
00688       {
00689          int iret,i;
00690 
00691          // initialize
00692          for(i=0; i<6; i++) PV[i] = 0.0;
00693 
00694          // trivial; return
00695          if(target == center) return 0;
00696 
00697          // get the right record from the file
00698          iret = seekToJD(tt);
00699          if(iret) return iret;
00700 
00701          // compute Nutations or Librations
00702          if(target == Nutations || target == Librations) 
00703          {
00704             computeState(tt, target==Nutations ? NUTATIONS : LIBRATIONS, PV);
00705             return 0;
00706          }
00707 
00708          // define computeID's for target and center
00709          computeID TARGET,CENTER;
00710 
00711          if(target <= Sun)                        TARGET = computeID(target-1);
00712          else if(target == SolarSystemBarycenter) TARGET = NONE;
00713          else if(target == EarthMoonBarycenter)   TARGET = EMBARY;
00714          // (Nutations and Librations are done above)
00715          if(center <= Sun)                        CENTER = computeID(center-1);
00716          else if(center == SolarSystemBarycenter) CENTER = NONE;
00717          else if(center == EarthMoonBarycenter)   CENTER = EMBARY;
00718 
00719          // Earth and Moon need special treatment
00720          double PVMOON[6],PVEMBARY[6],Eratio,Mratio;
00721 
00722          // special cases of Earth AND Moon: Moon result is always geocentric
00723          if(target == Earth && center == Moon)    TARGET = NONE;
00724          if(center == Earth && target == Moon)    CENTER = NONE;
00725 
00726          // special cases of Earth OR Moon, but not both:
00727          if((target == Earth && center != Moon) || (center == Earth && target != Moon)) 
00728          {
00729             Eratio = 1.0/(1.0 + constants["EMRAT"]);
00730             computeState(tt, MOON, PVMOON);
00731          }
00732          if((target == Moon && center != Earth) || (center == Moon && target != Earth)) 
00733          {
00734             Mratio = constants["EMRAT"]/(1.0 + constants["EMRAT"]);
00735             computeState(tt, EMBARY, PVEMBARY);
00736          }
00737 
00738          // compute states for target and center
00739          double PVTARGET[6],PVCENTER[6];
00740          computeState(tt, TARGET, PVTARGET);
00741          computeState(tt, CENTER, PVCENTER);
00742 
00743          // handle the Earth/Moon special cases
00744          // convert from E-M barycenter to Earth
00745          if(target == Earth && center != Moon)
00746             for(i=0; i<6; i++) PVTARGET[i] -= PVMOON[i]*Eratio;
00747          if(center == Earth && target != Moon)
00748             for(i=0; i<6; i++) PVCENTER[i] -= PVMOON[i]*Eratio;
00749 
00750          if(target == Moon && center != Earth)
00751             for(i=0; i<6; i++) PVTARGET[i] = PVEMBARY[i] + PVTARGET[i]*Mratio;
00752          if(center == Moon && target != Earth)
00753             for(i=0; i<6; i++) PVCENTER[i] = PVEMBARY[i] + PVCENTER[i]*Mratio;
00754 
00755          // final result
00756          for(i=0; i<6; i++) PV[i] = PVTARGET[i] - PVCENTER[i];
00757 
00758          if(!kilometers) {
00759             double AU = constants["AU"];
00760             for(i=0; i<6; i++) PV[i] /= AU;
00761          }
00762 
00763          return 0;
00764       }
00765       catch(Exception& e) { GPSTK_RETHROW(e); }
00766       catch(exception& e) { Exception E("std except: "+string(e.what())); GPSTK_THROW(E); }
00767       catch(...) { Exception e("Unknown exception"); GPSTK_THROW(e); }
00768 
00769    }  // End of method 'PlanetEphemeris::computeState()'
00770 
00771 
00772    void PlanetEphemeris::writeBinary(ofstream& strm, const char *ptr, size_t size)
00773       throw(Exception)
00774    {
00775       try 
00776       {
00777          strm.write(ptr,size);
00778          if(!strm.good()) 
00779          {
00780             Exception e("Stream error");
00781             GPSTK_THROW(e);
00782          }
00783       }
00784       catch(Exception& e) { GPSTK_RETHROW(e); }
00785       catch(exception& e) { Exception E("std except: "+string(e.what())); GPSTK_THROW(E); }
00786       catch(...) { Exception e("Unknown exception"); GPSTK_THROW(e); }
00787 
00788    }  // End of method 'PlanetEphemeris::writeBinary()'
00789 
00790 
00791    void PlanetEphemeris::readBinary(char *ptr, size_t size) 
00792       throw(Exception)
00793    {
00794       try 
00795       {
00796          istrm.read(ptr,size);
00797          if(istrm.eof() || !istrm.good()) 
00798          {
00799             Exception e("Stream error or premature EOF");
00800             GPSTK_THROW(e);
00801          }
00802       }
00803       catch(Exception& e) { GPSTK_RETHROW(e); }
00804       catch(exception& e) { Exception E("std except: "+string(e.what())); GPSTK_THROW(E); }
00805       catch(...) { Exception e("Unknown exception"); GPSTK_THROW(e); }
00806 
00807    }  // End of method 'PlanetEphemeris::readBinary()'
00808 
00809 
00810    void PlanetEphemeris::readBinaryHeader(std::string filename) 
00811       throw(Exception)
00812    {
00813       try 
00814       {
00815          int i,DENUM,recLength;
00816          char buffer[100];
00817          double AU,EMRAT;
00818          string word;
00819 
00820          // open the input binary file
00821          istrm.open(filename.c_str(), ios::in | ios::binary);
00822          if(!istrm) 
00823          {
00824             Exception e("Failed to open input binary file " + filename + ". Abort.");
00825             GPSTK_THROW(e);
00826          }
00827 
00828          // initialize
00829          EphemerisNumber = -1;
00830          constants.clear();
00831          store.clear();
00832          recLength = 0;
00833 
00834          // ----------------------------------------------------------------
00835          // read the first header record
00836          // 1. 3 labels each of length 84
00837          for(i=0; i<3; i++) 
00838          {
00839             readBinary(buffer,84); //istrm.read(buffer,84);
00840             recLength += 84;
00841             buffer[84] = '\0';
00842             label[i] = stripTrailing(stripLeading(buffer," ")," ");
00843          }
00844 
00845          // 2. 400 keys from the const array, each of length 6
00846          vector<string> consts_names;
00847          buffer[6] = '\0';
00848          for(i=0; i<400; i++) 
00849          {
00850             readBinary(buffer,6);
00851             recLength += 6;
00852             word = stripLeading(string(buffer));
00853             if(!word.empty()) 
00854             {
00855                consts_names.push_back(word);
00856             }
00857          }
00858          Nconst = consts_names.size();
00859 
00860          // 3. the three times
00861          readBinary((char *)&startJD,sizeof(double));
00862          readBinary((char *)&endJD,sizeof(double));
00863          readBinary((char *)&interval,sizeof(double));
00864          recLength += 3*sizeof(double);
00865 
00866          // 4. Ncoeff
00867          readBinary((char *)&Ncoeff,sizeof(int));
00868          recLength += sizeof(int);
00869 
00870          // 5. AU and EMRAT
00871          buffer[sizeof(double)] = '\0';
00872          readBinary((char *)&AU,sizeof(double));
00873          recLength += sizeof(double);
00874 
00875          readBinary((char *)&EMRAT,sizeof(double));
00876          recLength += sizeof(double);
00877 
00878          // 6. c_arrays for the first 12 planets
00879          for(i=0; i<12; i++) 
00880          {
00881             readBinary((char *)&c_offset[i],sizeof(int));
00882             readBinary((char *)&c_ncoeff[i],sizeof(int));
00883             readBinary((char *)&c_nsets[i],sizeof(int));
00884             recLength += 3*sizeof(int);
00885          }
00886 
00887          // 7. DENUM
00888          double denum;
00889          readBinary((char *)&denum,sizeof(double));
00890          recLength += sizeof(double);
00891 
00892          // 8. c_arrays for libration
00893          readBinary((char *)&c_offset[12],sizeof(int));
00894          readBinary((char *)&c_ncoeff[12],sizeof(int));
00895          readBinary((char *)&c_nsets[12],sizeof(int));
00896          recLength += 3*sizeof(int);
00897 
00898          // 9. pad - records are padded to be the same length as the data records b/c
00899          //          JPL does it (for Fortran reasons) - not necessary
00900          for(i=0; i < Ncoeff*sizeof(double)-recLength; i++)
00901             readBinary(buffer,1);
00902 
00903          // ----------------------------------------------------------------
00904          // the second header record: 400 values from the const array
00905          double d;
00906          for(i=0; i<400; i++) 
00907          {
00908             readBinary((char *)&d,sizeof(double));
00909             if(i < Nconst) 
00910             {
00911                constants[stripTrailing(consts_names[i])] = d;
00912             }
00913          }
00914          // pad
00915          for(i=0; i < (400-Nconst)*sizeof(double); i++)
00916             readBinary(buffer,1);
00917 
00918          // ----------------------------------------------------------------
00919          // test the header
00920          if(denum == constants["DENUM"]) 
00921          {
00922 
00923             // EphemerisNumber == -1 means the header has not been read
00924             // EphemerisNumber ==  0 means the fileposMap has not been read (binary)
00925             // EphemerisNumber == constants["DENUM"] means object has been initialized
00926             //                       (binary file), or header read (ASCII file)
00927             EphemerisNumber = 0;
00928 
00929             // clear the data arrays
00930             store.clear();
00931          }
00932          else 
00933          {
00934             GPSTK_WARNING_F2("","DENUM (%lf) does not equal the array value(%lf)",
00935                                 denum, constants["DENUM"]);
00936          }
00937       }
00938       catch(Exception& e) { GPSTK_RETHROW(e); }
00939       catch(exception& e) { Exception E("std except: "+string(e.what())); GPSTK_THROW(E); }
00940       catch(...) { Exception e("Unknown exception"); GPSTK_THROW(e); }
00941 
00942    }  // End of method 'PlanetEphemeris::readBinaryHeader(std::string filename) '
00943 
00944 
00945    int PlanetEphemeris::readBinaryData(bool save) 
00946       throw(Exception)
00947    {
00948       try 
00949       {
00950          // has the header been read?
00951          if(EphemerisNumber == -1) return -4;
00952 
00953          // read the data, optionally storing it all; fill the file position map
00954          int iret=-1,nrec=1;
00955          double prev=0.0;
00956          vector<double> data_vector;
00957          while(!istrm.eof() && istrm.good()) 
00958          {
00959             long filepos = istrm.tellg();
00960             iret = readBinaryRecord(data_vector);
00961             if(iret == -2) { iret = 0; break; }       // EOF
00962             if(iret) break;
00963 
00964             // if saving all in store, add it here
00965             if(save)
00966                store[data_vector[0]] = data_vector;
00967 
00968             // put the first record in coefficients array
00969             if(nrec == 1)
00970                coefficients = data_vector;
00971 
00972             // build the positions map
00973             fileposMap[data_vector[0]] = filepos;
00974 
00975             if(nrec > 1 && data_vector[0] != prev) 
00976             {
00977                ostringstream oss;
00978                oss << "ERROR: found gap in data at " << nrec << fixed << setprecision(6)
00979                   << " : prev end = " << prev << " != new beg = " << data_vector[0];
00980                Exception e(oss.str());
00981                GPSTK_THROW(e);
00982             }
00983 
00984             // remember the end time for next record
00985             prev = data_vector[1];
00986 
00987             // count records
00988             nrec++;
00989          }
00990 
00991          istrm.clear();
00992 
00993          return iret;
00994       }
00995       catch(Exception& e) { GPSTK_RETHROW(e); }
00996       catch(exception& e) { Exception E("std except: "+string(e.what())); GPSTK_THROW(E); }
00997       catch(...) { Exception e("Unknown exception"); GPSTK_THROW(e); }
00998 
00999    }  // End of method 'PlanetEphemeris::readBinaryData(bool save)'
01000 
01001 
01002    // return 0 ok, or
01003    // -3 stream is not open or not good
01004    // -4 EphemerisNumber is not defined
01005    // For -3,-4 : initializeWithBinaryFile() has not been called, or reading failed.
01006    int PlanetEphemeris::readBinaryRecord(vector<double>& data_vector) 
01007       throw(Exception)
01008    {
01009       try 
01010       {
01011          if(!istrm) return -3;
01012          if(istrm.eof() || !istrm.good()) return -3;
01013          if(EphemerisNumber <= -1) return -4;
01014 
01015          data_vector.clear();
01016 
01017          double d;
01018          for(int i=0; i<Ncoeff; i++) 
01019          {
01020             istrm.read((char *)&d,sizeof(double)); // don't use readBinary(), to catch EOF
01021             if(istrm.eof()) return -2;
01022             if(!istrm.good()) return -3;
01023             data_vector.push_back(d);
01024          }
01025 
01026          return 0;
01027       }
01028       catch(Exception& e) { GPSTK_RETHROW(e); }
01029       catch(exception& e) { Exception E("std except: "+string(e.what())); GPSTK_THROW(E); }
01030       catch(...) { Exception e("Unknown exception"); GPSTK_THROW(e); }
01031 
01032    }  // End of method 'PlanetEphemeris::readBinaryRecord()'
01033 
01034       // return 0 ok, or
01035       // -1 out of range : input time is before the first time in file
01036       // -2 out of range : input time is after the last time in file, or in a gap
01037       // -3 stream is not open or not good, or EOF was found prematurely
01038       // -4 EphemerisNumber is not defined
01039       // For -3,-4 : initializeWithBinaryFile() has not been called, or reading failed.
01040    int PlanetEphemeris::seekToJD(double JD) 
01041       throw(Exception)
01042    {
01043       try 
01044       {
01045          if(!istrm) return -3;
01046          if(istrm.eof() || !istrm.good()) return -3;
01047          if(EphemerisNumber != int(constants["DENUM"])) return -4;
01048 
01049          if(coefficients[0] <= JD && JD <= coefficients[1]) return 0;
01050 
01051          map<double,long>::const_iterator it; // key >= input
01052          it = fileposMap.lower_bound(JD); // it points to first element with JD <= time
01053 
01054          if(it == fileposMap.begin() && JD < it->first)
01055             return -1;                    // failure: JD is before the first record
01056 
01057          if(it == fileposMap.end()        // if beyond the found record, go to previous;
01058             || JD < it->first) it--;   // but beware the "lower_bound found the =" case
01059 
01060          istrm.seekg(it->second,ios_base::beg);         // get the record
01061          int iret = readBinaryRecord(coefficients);
01062          if(iret == -2) iret = -3;        // this means EOF during data read
01063          if(iret) return iret;            // reading failed
01064 
01065          if(JD > coefficients[1])
01066             return -2;                    // failure: JD is after the last record, or
01067          // JD is in a gap between records
01068          return 0;
01069       }
01070       catch(Exception& e) { GPSTK_RETHROW(e); }
01071       catch(exception& e) { Exception E("std except: "+string(e.what())); GPSTK_THROW(E); }
01072       catch(...) { Exception e("Unknown exception"); GPSTK_THROW(e); }
01073 
01074    }  // End of method 'PlanetEphemeris::seekToJD()'
01075 
01076  
01077    void PlanetEphemeris::computeState(double tt, 
01078                                       PlanetEphemeris::computeID which, 
01079                                       double PV[6])
01080       throw(Exception)
01081    {
01082       try {
01083          int i,j,i0,ncomp,offset;
01084 
01085          for(i=0; i<6; i++) PV[i]=0.0;
01086          if(which == NONE) return;
01087 
01088          double T,Tbeg,Tspan,Tspan0;
01089          Tbeg = coefficients[0];
01090          Tspan0 = Tspan = coefficients[1] - coefficients[0];
01091          i0 = c_offset[which]-1;                      // index of first coefficient in array
01092          ncomp = (which == NUTATIONS ? 2 : 3);        // number of components returned
01093 
01094          // if more than one set, find the right set
01095          if(c_nsets[which] > 1) 
01096          {
01097             Tspan /= double(c_nsets[which]);
01098             for(j=c_nsets[which]; j>0; j--) 
01099             {
01100                Tbeg = coefficients[0] + double(j-1)*Tspan;
01101                if(tt > Tbeg)                       // == with j==1 is the default
01102                {
01103                   i0 += (j-1)*ncomp*c_ncoeff[which];
01104                   break;
01105                }
01106             }
01107          }
01108 
01109          // normalized time
01110          T = 2.0*(tt-Tbeg)/Tspan - 1.0;
01111 
01112          // interpolate
01113          unsigned int N=c_ncoeff[which];
01114          vector<double> C(N,0.0);     // Chebyshev
01115          vector<double> U(N,0.0);     // derivative of Chebyshev
01116          for(i=0; i<ncomp; i++)      // loop over components
01117          {
01118 
01119             // seed the Chebyshev recursions
01120             C[0] = 1; C[1] = T; //C[2] = 2*T*T-1;
01121             U[0] = 0; U[1] = 1; //U[2] = 4*T;
01122 
01123             // generate the Chebyshevs
01124             for(j=2; j<N; j++) 
01125             {
01126                C[j] = 2*T*C[j-1] - C[j-2];
01127                U[j] = 2*T*U[j-1] + 2*C[j-1] - U[j-2];
01128             }
01129 
01130             // compute P and V
01131             // done above PV[i] = PV[i+3] = 0.0;
01132             for(j=N-1; j>-1; j--)                              // POS
01133                PV[i] += coefficients[i0+j+i*N] * C[j];
01134             for(j=N-1; j>0; j--) // j>0 b/c U[0]=0             // VEL
01135                PV[i+ncomp] += coefficients[i0+j+i*N] * U[j];
01136 
01137             // convert velocity to 'per day'
01138             PV[i+ncomp] *= 2*double(c_nsets[which])/Tspan0;
01139          }
01140       }
01141       catch(Exception& e) { GPSTK_RETHROW(e); }
01142       catch(exception& e) { Exception E("std except: "+string(e.what())); GPSTK_THROW(E); }
01143       catch(...) { Exception e("Unknown exception"); GPSTK_THROW(e); }
01144 
01145    }  // End of method 'PlanetEphemeris::computeState()'
01146    
01147 }   // End of namespace gpstk
01148 
01149 
01150 

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