RinexObsHeader.cpp

Go to the documentation of this file.
00001 #pragma ident "$Id: RinexObsHeader.cpp 2458 2010-09-03 14:19:23Z btolman $"
00002 
00003 //============================================================================
00004 //
00005 //  This file is part of GPSTk, the GPS Toolkit.
00006 //
00007 //  The GPSTk is free software; you can redistribute it and/or modify
00008 //  it under the terms of the GNU Lesser General Public License as published
00009 //  by the Free Software Foundation; either version 2.1 of the License, or
00010 //  any later version.
00011 //
00012 //  The GPSTk is distributed in the hope that it will be useful,
00013 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 //  GNU Lesser General Public License for more details.
00016 //
00017 //  You should have received a copy of the GNU Lesser General Public
00018 //  License along with GPSTk; if not, write to the Free Software Foundation,
00019 //  Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020 //  
00021 //  Copyright 2004, The University of Texas at Austin
00022 //
00023 //============================================================================
00024 
00025 //============================================================================
00026 //
00027 //This software developed by Applied Research Laboratories at the University of
00028 //Texas at Austin, under contract to an agency or agencies within the U.S. 
00029 //Department of Defense. The U.S. Government retains all rights to use,
00030 //duplicate, distribute, disclose, or release this software. 
00031 //
00032 //Pursuant to DoD Directive 523024 
00033 //
00034 // DISTRIBUTION STATEMENT A: This software has been approved for public 
00035 //                           release, distribution is unlimited.
00036 //
00037 //=============================================================================
00038 
00044 #include "StringUtils.hpp"
00045 #include "RinexObsHeader.hpp"
00046 #include "RinexObsStream.hpp"
00047 
00048 using namespace std;
00049 using namespace gpstk::StringUtils;
00050 
00051 namespace gpstk
00052 {
00053    const string RinexObsHeader::versionString =         "RINEX VERSION / TYPE";
00054    const string RinexObsHeader::runByString =           "PGM / RUN BY / DATE";
00055    const string RinexObsHeader::commentString =         "COMMENT";
00056    const string RinexObsHeader::markerNameString =      "MARKER NAME";
00057    const string RinexObsHeader::markerNumberString =    "MARKER NUMBER";
00058    const string RinexObsHeader::observerString =        "OBSERVER / AGENCY";
00059    const string RinexObsHeader::receiverString =        "REC # / TYPE / VERS";
00060    const string RinexObsHeader::antennaTypeString =     "ANT # / TYPE";
00061    const string RinexObsHeader::antennaPositionString = "APPROX POSITION XYZ";
00062    const string RinexObsHeader::antennaOffsetString =   "ANTENNA: DELTA H/E/N";
00063    const string RinexObsHeader::waveFactString =        "WAVELENGTH FACT L1/2";
00064    const string RinexObsHeader::numObsString =          "# / TYPES OF OBSERV";
00065    const string RinexObsHeader::intervalString =        "INTERVAL";
00066    const string RinexObsHeader::firstTimeString =       "TIME OF FIRST OBS";
00067    const string RinexObsHeader::lastTimeString =        "TIME OF LAST OBS";
00068    const string RinexObsHeader::receiverOffsetString =  "RCV CLOCK OFFS APPL";
00069    const string RinexObsHeader::leapSecondsString =     "LEAP SECONDS";
00070    const string RinexObsHeader::numSatsString =         "# OF SATELLITES";
00071    const string RinexObsHeader::prnObsString =          "PRN / # OF OBS";
00072    const string RinexObsHeader::endOfHeader =           "END OF HEADER";
00073 
00074    const unsigned int RinexObsHeader::RinexObsType::C1depend=0x01;
00075    const unsigned int RinexObsHeader::RinexObsType::L1depend=0x02;
00076    const unsigned int RinexObsHeader::RinexObsType::L2depend=0x04;
00077    const unsigned int RinexObsHeader::RinexObsType::P1depend=0x08;
00078    const unsigned int RinexObsHeader::RinexObsType::P2depend=0x10;
00079    const unsigned int RinexObsHeader::RinexObsType::EPdepend=0x20;
00080    const unsigned int RinexObsHeader::RinexObsType::PSdepend=0x40;
00081 
00082    const RinexObsHeader::RinexObsType RinexObsHeader::UN("UN", "Unknown or Invalid",   "unknown", 0);
00083    const RinexObsHeader::RinexObsType RinexObsHeader::L1("L1", "L1 Carrier Phase",     "L1 cycles",
00084       RinexObsHeader::RinexObsType::L1depend);
00085    const RinexObsHeader::RinexObsType RinexObsHeader::L2("L2", "L2 Carrier Phase",     "L2 cycles",
00086       RinexObsHeader::RinexObsType::L2depend);
00087    const RinexObsHeader::RinexObsType RinexObsHeader::C1("C1", "C/A-code pseudorange", "meters",
00088       RinexObsHeader::RinexObsType::C1depend);
00089    const RinexObsHeader::RinexObsType RinexObsHeader::C2("C2", "L2C-code pseudorange", "meters", 0);
00090    const RinexObsHeader::RinexObsType RinexObsHeader::P1("P1", "Pcode L1 pseudorange", "meters",
00091       RinexObsHeader::RinexObsType::P1depend);
00092    const RinexObsHeader::RinexObsType RinexObsHeader::P2("P2", "Pcode L2 pseudorange", "meters",
00093       RinexObsHeader::RinexObsType::P2depend);
00094    const RinexObsHeader::RinexObsType RinexObsHeader::D1("D1", "Doppler Frequency L1", "Hz", 0);
00095    const RinexObsHeader::RinexObsType RinexObsHeader::D2("D2", "Doppler Frequency L2", "Hz", 0);
00096    const RinexObsHeader::RinexObsType RinexObsHeader::S1("S1", "Signal-to-Noise L1",   "dB-Hz", 0);
00097    const RinexObsHeader::RinexObsType RinexObsHeader::S2("S2", "Signal-to-Noise L2",   "dB-Hz", 0);
00098    const RinexObsHeader::RinexObsType RinexObsHeader::T1("T1", "Transit 150 MHz",      "meters", 0);
00099    const RinexObsHeader::RinexObsType RinexObsHeader::T2("T2", "Transit 400 MHz",      "meters", 0);
00100    // v 2.11
00101    const RinexObsHeader::RinexObsType RinexObsHeader::C5("C5", "L5C-code pseudorange", "meters", 0);
00102    const RinexObsHeader::RinexObsType RinexObsHeader::L5("L5", "L5 Carrier Phase",     "L5 cycles", 0);
00103    const RinexObsHeader::RinexObsType RinexObsHeader::D5("D5", "Doppler Frequency L5", "Hz", 0);
00104    const RinexObsHeader::RinexObsType RinexObsHeader::S5("S5", "Signal-to-Noise L5",   "dB-Hz", 0);
00105    // Galileo only
00106    const RinexObsHeader::RinexObsType RinexObsHeader::C6("C6", "E6-code pseudorange",  "meters", 0);
00107    const RinexObsHeader::RinexObsType RinexObsHeader::L6("L6", "E6 Carrier Phase",     "L6 cycles", 0);
00108    const RinexObsHeader::RinexObsType RinexObsHeader::D6("D6", "Doppler Frequency E6", "Hz", 0);
00109    const RinexObsHeader::RinexObsType RinexObsHeader::S6("S6", "Signal-to-Noise E6",   "dB-Hz", 0);
00110 
00111    const RinexObsHeader::RinexObsType RinexObsHeader::C7("C7", "E5b-code pseudorange",  "meters", 0);
00112    const RinexObsHeader::RinexObsType RinexObsHeader::L7("L7", "E5b Carrier Phase",     "L7 cycles", 0);
00113    const RinexObsHeader::RinexObsType RinexObsHeader::D7("D7", "Doppler Frequency E5b", "Hz", 0);
00114    const RinexObsHeader::RinexObsType RinexObsHeader::S7("S7", "Signal-to-Noise E5b",   "dB-Hz", 0);
00115 
00116    const RinexObsHeader::RinexObsType RinexObsHeader::C8("C8", "E5a+b-code pseudorange", "meters", 0);
00117    const RinexObsHeader::RinexObsType RinexObsHeader::L8("L8", "E5a+b Carrier Phase",    "L8 cycles", 0);
00118    const RinexObsHeader::RinexObsType RinexObsHeader::D8("D8", "Doppler Frequency E5a+b","Hz", 0);
00119    const RinexObsHeader::RinexObsType RinexObsHeader::S8("S8", "Signal-to-Noise E5a+b",  "dB-Hz", 0);
00120 
00121    RinexObsHeader::RinexObsType sot[29] =
00122    { 
00123       RinexObsHeader::UN,
00124       RinexObsHeader::L1, RinexObsHeader::L2,
00125       RinexObsHeader::C1, RinexObsHeader::C2,
00126       RinexObsHeader::P1, RinexObsHeader::P2,
00127       RinexObsHeader::D1, RinexObsHeader::D2,
00128       RinexObsHeader::S1, RinexObsHeader::S2,
00129       RinexObsHeader::T1, RinexObsHeader::T2,
00130       RinexObsHeader::C5, RinexObsHeader::L5, RinexObsHeader::D5, RinexObsHeader::S5,
00131       RinexObsHeader::C6, RinexObsHeader::L6, RinexObsHeader::D6, RinexObsHeader::S6,
00132       RinexObsHeader::C7, RinexObsHeader::L7, RinexObsHeader::D7, RinexObsHeader::S7,
00133       RinexObsHeader::C8, RinexObsHeader::L8, RinexObsHeader::D8, RinexObsHeader::S8
00134    };
00135 
00136    // Warning: the size of the above sot array needs to be put
00137    // in this initializer.
00138    const std::vector<RinexObsHeader::RinexObsType> RinexObsHeader::StandardRinexObsTypes(sot,sot+29);
00139 
00140    std::vector<RinexObsHeader::RinexObsType> RinexObsHeader::RegisteredRinexObsTypes
00141       = RinexObsHeader::StandardRinexObsTypes;
00142 
00143    void RinexObsHeader::reallyPutRecord(FFStream& ffs) const 
00144       throw(std::exception, FFStreamError, StringException)
00145    {
00146       RinexObsStream& strm = dynamic_cast<RinexObsStream&>(ffs);
00147       
00148       strm.header = *this;
00149       
00150       unsigned long allValid;
00151       if (version == 2.0)        allValid = allValid20;
00152       else if (version == 2.1)   allValid = allValid21;
00153       else if (version == 2.11)  allValid = allValid211;
00154       else
00155       {
00156          FFStreamError err("Unknown RINEX version: " + asString(version,2));
00157          err.addText("Make sure to set the version correctly.");
00158          GPSTK_THROW(err);
00159       }
00160       
00161       if ((valid & allValid) != allValid)
00162       {
00163          FFStreamError err("Incomplete or invalid header.");
00164          err.addText("Make sure you set all header valid bits for all of the available data.");
00165          GPSTK_THROW(err);
00166       }
00167       
00168       try
00169       {
00170          WriteHeaderRecords(strm);
00171       }
00172       catch(FFStreamError& e)
00173       {
00174          GPSTK_RETHROW(e);
00175       }
00176       catch(StringException& e)
00177       {
00178          GPSTK_RETHROW(e);
00179       }
00180 
00181    }  // end RinexObsHeader::reallyPutRecord
00182       
00183 
00184       // this function computes the number of valid header records which WriteHeaderRecords will write
00185    int RinexObsHeader::NumberHeaderRecordsToBeWritten(void) const throw()
00186    {
00187       int n=0;
00188       if(valid & RinexObsHeader::versionValid) n++;
00189       if(valid & RinexObsHeader::runByValid) n++;
00190       if(valid & RinexObsHeader::markerNameValid) n++;
00191       if(valid & RinexObsHeader::observerValid) n++;
00192       if(valid & RinexObsHeader::receiverValid) n++;
00193       if(valid & RinexObsHeader::antennaTypeValid) n++;
00194       if(valid & RinexObsHeader::antennaPositionValid) n++;
00195       if(valid & RinexObsHeader::antennaOffsetValid) n++;
00196       if(valid & RinexObsHeader::waveFactValid) {
00197          n++;
00198          if(extraWaveFactList.size()) n += 1 + (extraWaveFactList.size()-1)/7;
00199       }
00200       if(valid & RinexObsHeader::obsTypeValid) n += 1 + (obsTypeList.size()-1)/9;
00201       if(valid & RinexObsHeader::intervalValid) n++;
00202       if(valid & RinexObsHeader::firstTimeValid) n++;
00203       if(valid & RinexObsHeader::lastTimeValid) n++;
00204       if(valid & RinexObsHeader::markerNumberValid) n++;
00205       if(valid & RinexObsHeader::receiverOffsetValid) n++;
00206       if(valid & RinexObsHeader::leapSecondsValid) n++;
00207       if(valid & RinexObsHeader::commentValid) n += commentList.size();
00208       if(valid & RinexObsHeader::numSatsValid) n++;
00209       if(valid & RinexObsHeader::prnObsValid)
00210          n += numObsForSat.size() * (1+numObsForSat.begin()->second.size()/9);
00211       if(valid & RinexObsHeader::endValid) n++;
00212       return n;
00213    }
00214 
00215       // this function writes all valid header records
00216    void RinexObsHeader::WriteHeaderRecords(FFStream& ffs) const
00217       throw(FFStreamError, StringException)
00218    {
00219       RinexObsStream& strm = dynamic_cast<RinexObsStream&>(ffs);
00220       string line;
00221       if (valid & versionValid)
00222       {
00223          line  = rightJustify(asString(version,2), 9);
00224          line += string(11, ' ');
00225          if ((fileType[0] != 'O') && (fileType[0] != 'o'))
00226          {
00227             FFStreamError err("This isn't a Rinex Observation file: " + 
00228                               fileType.substr(0,1));
00229             GPSTK_THROW(err);
00230          }
00231 
00232          if (system.system == RinexSatID::systemUnknown)
00233          {
00234             FFStreamError err("Invalid satellite system");
00235             GPSTK_THROW(err);
00236          }
00237 
00238          line += leftJustify(string("Observation"), 20);
00239          std::string str;
00240          if(system.system == SatID::systemMixed)
00241             str = "M (Mixed)";
00242          else {
00243             str = RinexSatID(system).systemChar();
00244             str = str + " (" + RinexSatID(system).systemString() + ")";
00245          }
00246          line += leftJustify(str, 20);
00247          line += versionString;
00248          strm << line << endl;
00249          strm.lineNumber++;
00250       }
00251       if (valid & runByValid)
00252       {
00253          line  = leftJustify(fileProgram,20);
00254          line += leftJustify(fileAgency,20);
00255          DayTime dt;
00256          dt.setLocalTime();
00257          string dat = dt.printf("%02m/%02d/%04Y %02H:%02M:%02S");
00258          line += leftJustify(dat, 20);
00259          line += runByString;
00260          strm << line << endl;
00261          strm.lineNumber++;
00262       }
00263       if (valid & markerNameValid)
00264       {
00265          line  = leftJustify(markerName, 60);
00266          line += markerNameString;
00267          strm << line << endl;
00268          strm.lineNumber++;
00269       }
00270       if (valid & observerValid)
00271       {
00272          line  = leftJustify(observer, 20);
00273          line += leftJustify(agency, 40);
00274          line += observerString;
00275          strm << line << endl;
00276          strm.lineNumber++;
00277       }
00278       if (valid & receiverValid)
00279       {
00280          line  = leftJustify(recNo, 20);
00281          line += leftJustify(recType, 20);
00282          line += leftJustify(recVers, 20);
00283          line += receiverString;
00284          strm << line << endl;
00285          strm.lineNumber++;
00286       }
00287       if (valid & antennaTypeValid)
00288       {
00289          line  = leftJustify(antNo, 20);
00290          line += leftJustify(antType, 20);
00291          line += string(20, ' ');
00292          line += antennaTypeString;
00293          strm << line << endl;
00294          strm.lineNumber++;
00295       }
00296       if (valid & antennaPositionValid)
00297       {
00298          line  = rightJustify(asString(antennaPosition[0], 4), 14);
00299          line += rightJustify(asString(antennaPosition[1], 4), 14);
00300          line += rightJustify(asString(antennaPosition[2], 4), 14);
00301          line += string(18, ' ');
00302          line += antennaPositionString;
00303          strm << line << endl;
00304          strm.lineNumber++;
00305       }
00306       if (valid & antennaOffsetValid)
00307       {
00308          line  = rightJustify(asString(antennaOffset[0], 4), 14);
00309          line += rightJustify(asString(antennaOffset[1], 4), 14);
00310          line += rightJustify(asString(antennaOffset[2], 4), 14);
00311          line += string(18, ' ');
00312          line += antennaOffsetString;
00313          strm << line << endl;
00314          strm.lineNumber++;
00315       }
00316       if (valid & waveFactValid)
00317       {
00318          line  = rightJustify(asString<short>(wavelengthFactor[0]),6);
00319          line += rightJustify(asString<short>(wavelengthFactor[1]),6);
00320          line += string(48, ' ');
00321          line += waveFactString;
00322          strm << line << endl;
00323          strm.lineNumber++;
00324          
00325             // handle continuation lines
00326          if (!extraWaveFactList.empty())
00327          {
00328             vector<ExtraWaveFact>::const_iterator itr = extraWaveFactList.begin();
00329             
00330             while (itr != extraWaveFactList.end())
00331             {
00332                const int maxSatsPerLine = 7;
00333                short satsWritten = 0, satsLeft = (*itr).satList.size(), satsThisLine;
00334                vector<SatID>::const_iterator vecItr = (*itr).satList.begin();
00335 
00336                while ((vecItr != (*itr).satList.end())) {
00337                   if(satsWritten == 0) {
00338                      line  = rightJustify(asString<short>((*itr).wavelengthFactor[0]),6);
00339                      line += rightJustify(asString<short>((*itr).wavelengthFactor[1]),6);
00340                      satsThisLine = (satsLeft > maxSatsPerLine ? maxSatsPerLine : satsLeft);
00341                      line += rightJustify(asString<short>(satsThisLine),6);
00342                   }
00343                   try {
00344                      line += string(3, ' ') + RinexSatID(*vecItr).toString();
00345                   }
00346                   catch (Exception& e) {
00347                      FFStreamError ffse(e);
00348                      GPSTK_THROW(ffse);
00349                   }
00350                   satsWritten++;
00351                   satsLeft--;
00352                   if(satsWritten==maxSatsPerLine || satsLeft==0) {      // output a complete line
00353                      line += string(60 - line.size(), ' ');
00354                      line += waveFactString;
00355                      strm << line << endl;
00356                      strm.lineNumber++;
00357                      satsWritten = 0;
00358                   }
00359                   vecItr++;
00360                }
00361                itr++;
00362             }
00363          }
00364       }
00365       if (valid & obsTypeValid)
00366       {
00367          const int maxObsPerLine = 9;
00368          int obsWritten = 0;
00369          line = ""; // make sure the line contents are reset.
00370          
00371          vector<RinexObsType>::const_iterator itr = obsTypeList.begin();
00372          
00373          while (itr != obsTypeList.end())
00374          {
00375                // the first line needs to have the # of obs
00376             if (obsWritten == 0)
00377                line  = rightJustify(asString(obsTypeList.size()), 6);
00378                // if you hit 9, write out the line and start a new one
00379             else if ((obsWritten % maxObsPerLine) == 0)
00380             {
00381                line += numObsString;
00382                strm << line << endl;
00383                strm.lineNumber++;
00384                line  = string(6, ' ');
00385             }
00386             line += rightJustify(convertObsType(*itr), 6);
00387             obsWritten++;
00388             itr++;
00389          }
00390          line += string(60 - line.size(), ' ');
00391          line += numObsString;
00392          strm << line << endl;
00393          strm.lineNumber++;
00394       }
00395       if (valid & intervalValid)
00396       {
00397          line  = rightJustify(asString(interval, 3), 10);
00398          line += string(50, ' ');
00399          line += intervalString;
00400          strm << line << endl;
00401          strm.lineNumber++;
00402       }
00403       if (valid & firstTimeValid)
00404       {
00405          line  = writeTime(firstObs);
00406          line += string(48-line.size(),' ');
00407          if(firstSystem.system == RinexSatID::systemGPS) line += "GPS";
00408          if(firstSystem.system == RinexSatID::systemGlonass) line += "GLO";
00409          if(firstSystem.system == RinexSatID::systemGalileo) line += "GAL";
00410          line += string(60 - line.size(), ' ');
00411          line += firstTimeString;
00412          strm << line << endl;
00413          strm.lineNumber++;
00414       }
00415       if (valid & lastTimeValid)
00416       {
00417          line  = writeTime(lastObs);
00418          line += string(48-line.size(),' ');
00419          if(lastSystem.system == RinexSatID::systemGPS) line += "GPS";
00420          if(lastSystem.system == RinexSatID::systemGlonass) line += "GLO";
00421          if(lastSystem.system == RinexSatID::systemGalileo) line += "GAL";
00422          line += string(60 - line.size(), ' ');
00423          line += lastTimeString;
00424          strm << line << endl;
00425          strm.lineNumber++;
00426       }
00427       if (valid & markerNumberValid)
00428       {
00429          line  = leftJustify(markerNumber, 20);
00430          line += string(40, ' ');
00431          line += markerNumberString;
00432          strm << line << endl;
00433          strm.lineNumber++;
00434       }
00435       if (valid & receiverOffsetValid)
00436       {
00437          line  = rightJustify(asString(receiverOffset),6);
00438          line += string(54, ' ');
00439          line += receiverOffsetString;
00440          strm << line << endl;
00441          strm.lineNumber++;
00442       }
00443       if (valid & leapSecondsValid)
00444       {
00445          line  = rightJustify(asString(leapSeconds),6);
00446          line += string(54, ' ');
00447          line += leapSecondsString;
00448          strm << line << endl;
00449          strm.lineNumber++;
00450       }
00451       if (valid & commentValid)
00452       {
00453          vector<string>::const_iterator itr = commentList.begin();
00454          while (itr != commentList.end())
00455          {
00456             line  = leftJustify((*itr), 60);
00457             line += commentString;
00458             strm << line << endl;
00459             strm.lineNumber++;
00460             itr++;
00461          }
00462       }
00463       if (valid & numSatsValid)
00464       {
00465          line  = rightJustify(asString(numSVs), 6);
00466          line += string(54, ' ');
00467          line += numSatsString;
00468          strm << line << endl;
00469          strm.lineNumber++;
00470       }
00471       if (valid & prnObsValid)
00472       {
00473          const int maxObsPerLine = 9;
00474          map<SatID, vector<int> >::const_iterator itr = numObsForSat.begin();
00475          while (itr != numObsForSat.end())
00476          {
00477             int numObsWritten = 0;
00478             
00479             vector<int>::const_iterator vecItr = (*itr).second.begin();
00480             while (vecItr != (*itr).second.end())
00481             {
00482                if (numObsWritten == 0)
00483                {
00484                   try {
00485                      RinexSatID prn((*itr).first);
00486                      line  = string(3, ' ') + prn.toString();
00487                   }
00488                   catch (Exception& e) {
00489                      FFStreamError ffse(e);
00490                      GPSTK_RETHROW(ffse); 
00491                   }
00492                }
00493                else if ((numObsWritten % maxObsPerLine)  == 0)
00494                {
00495                   line += prnObsString;
00496                   strm << line << endl;
00497                   strm.lineNumber++;
00498                   line  = string(6, ' ');
00499                }
00500                line += rightJustify(asString(*vecItr), 6);
00501                ++vecItr;
00502                ++numObsWritten;
00503             }
00504             line += string(60 - line.size(), ' ');
00505             line += prnObsString;
00506             strm << line << endl;
00507             strm.lineNumber++;
00508             itr++;
00509          }
00510       }
00511       if (valid & endValid)
00512       {
00513          line  = string(60, ' ');
00514          line += endOfHeader;
00515          strm << line << endl;
00516          strm.lineNumber++;               
00517       }   
00518    }   // end RinexObsHeader::WriteHeaderRecords()
00519 
00520 
00521       // this function parses a single header record
00522    void RinexObsHeader::ParseHeaderRecord(string& line)
00523       throw(FFStreamError)
00524    {
00525       string label(line, 60, 20);
00526          
00527       if (label == versionString)
00528       {
00529          version = asDouble(line.substr(0,20));
00530          fileType = strip(line.substr(20, 20));
00531          if ( (fileType[0] != 'O') &&
00532               (fileType[0] != 'o'))
00533          {
00534             FFStreamError e("This isn't a Rinex Obs file");
00535             GPSTK_THROW(e);
00536          }
00537          string system_str = strip(line.substr(40, 20));
00538          try {
00539             RinexSatID rsat;
00540             rsat.fromString(system_str);     // fromString includes Mixed!
00541             system.system = rsat.system;
00542          }
00543          catch (Exception& e)
00544          {
00545             FFStreamError ffse("Input satellite system is unsupported: " + system_str);
00546             GPSTK_THROW(ffse);
00547          }
00548          valid |= versionValid;
00549       }
00550       else if (label == runByString )
00551       {
00552          fileProgram =    strip(line.substr(0, 20));
00553          fileAgency =  strip(line.substr(20, 20));
00554          date =   strip(line.substr(40, 20));
00555          valid |= runByValid;
00556       }
00557       else if (label == commentString)
00558       {
00559          string s = strip(line.substr(0, 60));
00560          commentList.push_back(s);
00561          valid |= commentValid;
00562       }
00563       else if (label == markerNameString)
00564       {
00565          markerName = strip(line.substr(0,60));
00566          valid |= markerNameValid;
00567       }
00568       else if (label == markerNumberString)
00569       {
00570          markerNumber = strip(line.substr(0,20));
00571          valid |= markerNumberValid;
00572       }
00573       else if (label == observerString)
00574       {
00575          observer = strip(line.substr(0,20));
00576          agency = strip(line.substr(20,40));
00577          valid |= observerValid;
00578       }
00579       else if (label == receiverString)
00580       {
00581          recNo   = strip(line.substr(0, 20));
00582          recType = strip(line.substr(20,20));
00583          recVers = strip(line.substr(40,20));
00584          valid |= receiverValid;
00585       }
00586       else if (label ==antennaTypeString)
00587       {
00588          antNo =   strip(line.substr(0, 20));
00589          antType = strip(line.substr(20, 20));
00590          valid |= antennaTypeValid;
00591       }
00592       else if (label == antennaPositionString)
00593       {
00594          antennaPosition[0] = asDouble(line.substr(0,  14));
00595          antennaPosition[1] = asDouble(line.substr(14, 14));
00596          antennaPosition[2] = asDouble(line.substr(28, 14));
00597          valid |= antennaPositionValid;
00598       }
00599       else if (label == antennaOffsetString)
00600       {
00601          antennaOffset[0] = asDouble(line.substr(0,  14));
00602          antennaOffset[1] = asDouble(line.substr(14, 14));
00603          antennaOffset[2] = asDouble(line.substr(28, 14));
00604          valid |= antennaOffsetValid;
00605       }
00606       else if (label == waveFactString)
00607       {
00608             // first time reading this
00609          if (! (valid & waveFactValid))
00610          {
00611             wavelengthFactor[0] = asInt(line.substr(0,6));
00612             wavelengthFactor[1] = asInt(line.substr(6,6));
00613             valid |= waveFactValid;
00614          }
00615             // additional wave fact lines
00616          else
00617          {
00618             const int maxSatsPerLine = 7;
00619             int Nsats;
00620             ExtraWaveFact ewf;
00621             ewf.wavelengthFactor[0] = asInt(line.substr(0,6));
00622             ewf.wavelengthFactor[1] = asInt(line.substr(6,6));
00623             Nsats = asInt(line.substr(12,6));
00624                
00625             if (Nsats > maxSatsPerLine)   // > not >=
00626             {
00627                FFStreamError e("Invalid number of Sats for " + waveFactString);
00628                GPSTK_THROW(e);
00629             }
00630                
00631             for (int i = 0; i < Nsats; i++)
00632             {
00633                try {
00634                   RinexSatID prn(line.substr(21+i*6,3));
00635                   ewf.satList.push_back(prn); 
00636                }
00637                catch (Exception& e){
00638                   FFStreamError ffse(e);
00639                   GPSTK_RETHROW(ffse);
00640                }
00641             }
00642                
00643             extraWaveFactList.push_back(ewf);
00644          }
00645       }
00646       else if (label == numObsString)
00647       {
00648          const int maxObsPerLine = 9;
00649             // process the first line
00650          if (! (valid & obsTypeValid))
00651          {
00652             numObs = asInt(line.substr(0,6));
00653             
00654             for (int i = 0; (i < numObs) && (i < maxObsPerLine); i++)
00655             {
00656                int position = i * 6 + 6 + 4;
00657                RinexObsType rt = convertObsType(line.substr(position,2));
00658                obsTypeList.push_back(rt);
00659             }
00660             valid |= obsTypeValid;
00661          }
00662             // process continuation lines
00663          else
00664          {
00665             for (int i = obsTypeList.size();
00666                  (i < numObs) && ( (i % maxObsPerLine) < maxObsPerLine); i++)
00667             {
00668                int position = (i % maxObsPerLine) * 6 + 6 + 4;
00669                RinexObsType rt = convertObsType(line.substr(position,2));
00670                obsTypeList.push_back(rt);
00671             }
00672          }
00673       }
00674       else if (label == intervalString)
00675       {
00676          interval = asDouble(line.substr(0, 10));
00677          valid |= intervalValid;
00678       }
00679       else if (label == firstTimeString)
00680       {
00681          firstObs = parseTime(line);
00682          firstSystem.system = RinexSatID::systemGPS;
00683          if(line.substr(48,3)=="GLO") firstSystem.system=RinexSatID::systemGlonass;
00684          if(line.substr(48,3)=="GAL") firstSystem.system=RinexSatID::systemGalileo;
00685          valid |= firstTimeValid;
00686       }
00687       else if (label == lastTimeString)
00688       {
00689          lastObs = parseTime(line);
00690          lastSystem.system = RinexSatID::systemGPS;
00691          if(line.substr(48,3)=="GLO") lastSystem.system=RinexSatID::systemGlonass;
00692          if(line.substr(48,3)=="GAL") lastSystem.system=RinexSatID::systemGalileo;
00693          valid |= lastTimeValid;
00694       }
00695       else if (label == receiverOffsetString)
00696       {
00697          receiverOffset = asInt(line.substr(0,6));
00698          valid |= receiverOffsetValid;
00699       }
00700       else if (label == leapSecondsString)
00701       {
00702          leapSeconds = asInt(line.substr(0,6));
00703          valid |= leapSecondsValid;
00704       }
00705       else if (label == numSatsString)
00706       {
00707          numSVs = asInt(line.substr(0,6)) ;
00708          valid |= numSatsValid;
00709       }
00710       else if (label == prnObsString)
00711       {
00712          const int maxObsPerLine = 9;
00713             // continuation lines... you have to know what PRN
00714             // this is continuing for, hence lastPRN
00715          if ((lastPRN.id != -1) &&
00716              (numObsForSat[lastPRN].size() != obsTypeList.size()))
00717          {
00718             for(int i = numObsForSat[lastPRN].size(); 
00719                 (i < obsTypeList.size()) && 
00720                    ( (i % maxObsPerLine) < maxObsPerLine); i++)
00721             {
00722                numObsForSat[lastPRN].push_back(asInt(line.substr((i%maxObsPerLine)*6+6,6)));
00723             }
00724          }
00725          else
00726          {
00727             try { 
00728                lastPRN.fromString(line.substr(3,3));
00729             }
00730             catch (Exception& e) {
00731                FFStreamError ffse(e);
00732                GPSTK_RETHROW(ffse);
00733             }
00734             vector<int> numObsList;
00735             for(int i = 0; 
00736                    (i < obsTypeList.size()) && (i < maxObsPerLine); i++)
00737             {
00738                numObsList.push_back(asInt(line.substr(i*6+6,6)));
00739             }
00740 
00741             numObsForSat[lastPRN] = numObsList;
00742          }
00743          valid |= prnObsValid;
00744       }
00745       else if (label == endOfHeader)
00746       {
00747          valid |= endValid;
00748       }
00749       else
00750       {
00751          FFStreamError e("Unidentified label: " + label);
00752          GPSTK_THROW(e);
00753       }
00754    }   // end of RinexObsHeader::ParseHeaderRecord(string& line)
00755 
00756 
00757       // This function parses the entire header from the given stream
00758    void RinexObsHeader::reallyGetRecord(FFStream& ffs)
00759       throw(std::exception, FFStreamError, 
00760             gpstk::StringUtils::StringException)
00761    {
00762       RinexObsStream& strm = dynamic_cast<RinexObsStream&>(ffs);
00763       
00764          // if already read, just return
00765       if (strm.headerRead == true)
00766          return;
00767 
00768          // since we're reading a new header, we need to reinitialize
00769          // all our list structures.  all the other objects should be ok.
00770          // this also applies if we threw an exception the first time we read
00771          // the header and are now re-reading it. some of these could be full
00772          // and we need to empty them.
00773       commentList.clear();
00774       wavelengthFactor[0] = wavelengthFactor[1] = 1;
00775       extraWaveFactList.clear();
00776       obsTypeList.clear();
00777       numObsForSat.clear();
00778       valid = 0;
00779       numObs = 0;
00780       lastPRN.id = -1;
00781       
00782       string line;
00783       
00784       while (!(valid & endValid))
00785       {
00786          strm.formattedGetLine(line);
00787          StringUtils::stripTrailing(line);
00788 
00789          if (line.length()==0)
00790          {
00791             FFStreamError e("No data read");
00792             GPSTK_THROW(e);
00793          }
00794          else if (line.length()<60 || line.length()>80)
00795          {
00796             FFStreamError e("Invalid line length");
00797             GPSTK_THROW(e);
00798          }
00799 
00800          try
00801          {
00802             ParseHeaderRecord(line);
00803          }
00804          catch(FFStreamError& e)
00805          {
00806             GPSTK_RETHROW(e);
00807          }
00808          
00809       }   // end while(not end of header)
00810 
00811       unsigned long allValid;
00812       if      (version == 2.0)      allValid = allValid20;
00813       else if (version == 2.1)      allValid = allValid21;
00814       else if (version == 2.11)     allValid = allValid211;
00815       else
00816       {
00817          FFStreamError e("Unknown or unsupported RINEX version " + 
00818                          asString(version));
00819          GPSTK_THROW(e);
00820       }
00821             
00822       if ( (allValid & valid) != allValid)
00823       {
00824          FFStreamError e("Incomplete or invalid header");
00825          GPSTK_THROW(e);               
00826       }
00827             
00828          // If we get here, we should have reached the end of header line
00829       strm.header = *this;
00830       strm.headerRead = true;
00831             
00832    }  // end of reallyGetRecord()
00833 
00834 
00835 
00836    RinexObsHeader::RinexObsType 
00837    RinexObsHeader::convertObsType(const string& oneObs)
00838       throw(FFStreamError)
00839    {
00840       RinexObsType ot(RegisteredRinexObsTypes[0]);   // Unknown type
00841       for(int i=0; i<RegisteredRinexObsTypes.size(); i++) {
00842          if(RegisteredRinexObsTypes[i].type == oneObs) {
00843             ot = RegisteredRinexObsTypes[i];
00844             break;
00845          }
00846          //FFStreamError e("Bad obs type: " + oneObs);
00847          //GPSTK_THROW(e);
00848       }
00849       return ot;
00850    }
00851    string 
00852    RinexObsHeader::convertObsType(const RinexObsHeader::RinexObsType& oneObs)
00853       throw(FFStreamError)
00854    {
00855       return oneObs.type;
00856    }
00857 
00858 
00859    DayTime RinexObsHeader::parseTime(const string& line) const
00860    {
00861       int year, month, day, hour, min;
00862       double sec;
00863    
00864       year  = asInt(   line.substr(0,  6 ));
00865       month = asInt(   line.substr(6,  6 ));
00866       day   = asInt(   line.substr(12, 6 ));
00867       hour  = asInt(   line.substr(18, 6 ));
00868       min   = asInt(   line.substr(24, 6 ));
00869       sec   = asDouble(line.substr(30, 13));
00870       return DayTime(year, month, day, hour, min, sec);
00871    }
00872 
00873    string RinexObsHeader::writeTime(const DayTime& dt) const
00874    {
00875       string line;
00876       line  = rightJustify(asString<short>(dt.year()), 6);
00877       line += rightJustify(asString<short>(dt.month()), 6);
00878       line += rightJustify(asString<short>(dt.day()), 6);
00879       line += rightJustify(asString<short>(dt.hour()), 6);
00880       line += rightJustify(asString<short>(dt.minute()), 6);
00881       line += rightJustify(asString(dt.second(), 7), 13);
00882       return line;
00883    }
00884 
00885    void RinexObsHeader::dump(ostream& s) const
00886    {
00887       int i,j;
00888       s << "---------------------------------- REQUIRED ----------------------------------\n";
00889       string str;
00890       if(system.system == SatID::systemMixed)
00891          str = "M (Mixed)";
00892       else {
00893          str = RinexSatID(system).systemChar();
00894          str = str + " (" + RinexSatID(system).systemString() + ")";
00895       }
00896       s << "Rinex Version " << fixed << setw(5) << setprecision(2) << version
00897          << ",  File type " << fileType << ",  System " << str << ".\n";
00898       s << "Prgm: " << fileProgram << ",  Run: " << date << ",  By: " << fileAgency << endl;
00899       s << "Marker name: " << markerName << ".\n";
00900       s << "Obs'r : " << observer << ",  Agency: " << agency << endl;
00901       s << "Rec#: " << recNo << ",  Type: " << recType << ",  Vers: " << recVers << endl;
00902       s << "Antenna # : " << antNo << ",  Type : " << antType << endl;
00903       s << "Position (XYZ,m) : " << setprecision(4) << antennaPosition << ".\n";
00904       s << "Antenna offset (ENU,m) : " << setprecision(4) << antennaOffset << ".\n";
00905       s << "Wavelength factors (default) L1:" << wavelengthFactor[0]
00906          << ", L2: " << wavelengthFactor[1] << ".\n";
00907       for(i=0; i<extraWaveFactList.size(); i++) {
00908          s << "Wavelength factors (extra)   L1:"
00909             << extraWaveFactList[i].wavelengthFactor[0]
00910             << ", L2: " << extraWaveFactList[i].wavelengthFactor[1]
00911             << ", for Sats";
00912          for(j=0; j<extraWaveFactList[i].satList.size(); j++)
00913             s << " " << extraWaveFactList[i].satList[j];
00914          s << endl;
00915       }
00916       s << "Observation types (" << obsTypeList.size() << ") :\n";
00917       for(i=0; i<obsTypeList.size(); i++) 
00918          s << " Type #" << i << " = "
00919             << gpstk::RinexObsHeader::convertObsType(obsTypeList[i])
00920             << " " << obsTypeList[i].description
00921             << " (" << obsTypeList[i].units << ")." << endl;
00922       s << "Time of first obs " << firstObs.printf("%04Y/%02m/%02d %02H:%02M:%010.7f")
00923          << " " << (firstSystem.system==RinexSatID::systemGlonass ? "GLO" :
00924                    (firstSystem.system==RinexSatID::systemGalileo ? "GAL" : "GPS")) << endl;
00925       s << "(This header is ";
00926       if((valid & allValid211) == allValid211) s << "VALID 2.11";
00927       else if((valid & allValid21) == allValid21) s << "VALID 2.1";
00928       else if((valid & allValid20) == allValid20) s << "VALID 2.0";
00929       else s << "NOT VALID";
00930       s << " Rinex.)\n";
00931 
00932       if(!(valid & versionValid)) s << " Version is NOT valid\n";
00933       if(!(valid & runByValid)) s << " Run by is NOT valid\n";
00934       if(!(valid & markerNameValid)) s << " Marker Name is NOT valid\n";
00935       if(!(valid & observerValid)) s << " Observer is NOT valid\n";
00936       if(!(valid & receiverValid)) s << " Receiver is NOT valid\n";
00937       if(!(valid & antennaTypeValid)) s << " Antenna Type is NOT valid\n";
00938       if(!(valid & antennaPositionValid)) s << " Ant Position is NOT valid\n";
00939       if(!(valid & antennaOffsetValid)) s << " Antenna Offset is NOT valid\n";
00940       if(!(valid & waveFactValid)) s << " Wavelength factor is NOT valid\n";
00941       if(!(valid & obsTypeValid)) s << " Obs Type is NOT valid\n";
00942       if(!(valid & firstTimeValid)) s << " First time is NOT valid\n";
00943       if(!(valid & endValid)) s << " End is NOT valid\n";
00944 
00945       s << "---------------------------------- OPTIONAL ----------------------------------\n";
00946       if(valid & markerNumberValid) s << "Marker number : " << markerNumber << endl;
00947       if(valid & intervalValid) s << "Interval = "
00948          << fixed << setw(7) << setprecision(3) << interval << endl;
00949       if(valid & lastTimeValid) s << "Time of last obs "
00950          << lastObs.printf("%04Y/%02m/%02d %02H:%02M:%010.7f")
00951          << " " << (lastSystem.system==RinexSatID::systemGlonass ? "GLO":
00952                    (lastSystem.system==RinexSatID::systemGalileo ? "GAL" : "GPS")) << endl;
00953       if(valid & leapSecondsValid) s << "Leap seconds: " << leapSeconds << endl;
00954       if(valid & receiverOffsetValid) s << "Clock offset record is present and offsets "
00955          << (receiverOffset?"ARE":"are NOT") << " applied." << endl;
00956       if(valid & numSatsValid) s << "Number of Satellites with data : " << numSVs << endl;
00957       if(valid & prnObsValid) {
00958          s << "SAT  ";
00959          for(i=0; i<obsTypeList.size(); i++)
00960             s << setw(7) << convertObsType(obsTypeList[i]);
00961          s << endl;
00962          map<SatID, vector<int> >::const_iterator sat_itr = numObsForSat.begin();
00963          while (sat_itr != numObsForSat.end()) {
00964             vector<int> obsvec=sat_itr->second;
00965             s << " " << RinexSatID(sat_itr->first) << " ";
00966             for(i=0; i<obsvec.size(); i++) s << " " << setw(6) << obsvec[i];
00967             s << endl;
00968             sat_itr++;
00969          }
00970       }
00971       if(commentList.size() && !(valid & commentValid)) s << " Comment is NOT valid\n";
00972       s << "Comments (" << commentList.size() << ") :\n";
00973       for(i=0; i<commentList.size(); i++)
00974          s << commentList[i] << endl;
00975       s << "-------------------------------- END OF HEADER -------------------------------\n";
00976    }
00977 
00978    // return 1 if type already defined,
00979    //        0 if successful
00980    //       -1 if not successful - invalid input
00981    int RegisterExtendedRinexObsType(string t, string d, string u, unsigned int dep)
00982    {
00983       if(t.empty()) return -1;
00984       // throw if t="UN" ?
00985       // check that it is not duplicated
00986       for(int i=0; i<RinexObsHeader::RegisteredRinexObsTypes.size(); i++) {
00987          if(RinexObsHeader::RegisteredRinexObsTypes[i].type == t) { return 1; }
00988       }
00989       RinexObsHeader::RinexObsType ot;
00990       if(t.size()>2) t.resize(2,' '); ot.type = stripTrailing(t);
00991       if(d.size()>20) d.resize(20,' '); ot.description = stripTrailing(d);
00992       if(u.size()>10) u.resize(10,' '); ot.units = stripTrailing(u);
00993       ot.depend = dep;
00994       RinexObsHeader::RegisteredRinexObsTypes.push_back(ot);
00995       return 0;
00996    }
00997 
00998       // Pretty print a list of standard Rinex observation types
00999    void DisplayStandardRinexObsTypes(ostream& s)
01000    {
01001       s << "The list of standard Rinex obs types:\n";
01002       s << "  OT Description          Units\n";
01003       s << "  -- -------------------- ---------\n";
01004       for(int i=0; i<RinexObsHeader::StandardRinexObsTypes.size(); i++) {
01005          string line;
01006          line = string("  ")+RinexObsHeader::StandardRinexObsTypes[i].type;
01007          line += leftJustify(string(" ")+RinexObsHeader::StandardRinexObsTypes[i].description,21);
01008          line += leftJustify(string(" ")+RinexObsHeader::StandardRinexObsTypes[i].units,11);
01009          s << line << endl;
01010       }
01011    }
01012 
01013       // Pretty print a list of registered extended Rinex observation types
01014    void DisplayExtendedRinexObsTypes(ostream& s)
01015    {
01016       s << "The list of available extended Rinex obs types:\n";
01017       s << "  OT Description          Units     Required input (EP=ephemeris,PS=Rx Position)\n";
01018       s << "  -- -------------------- --------- ------------------\n";
01019       for(int i=RinexObsHeader::StandardRinexObsTypes.size();
01020                i<RinexObsHeader::RegisteredRinexObsTypes.size(); i++) {
01021          string line;
01022          line = string("  ")+RinexObsHeader::RegisteredRinexObsTypes[i].type;
01023          line += leftJustify(string(" ")+RinexObsHeader::RegisteredRinexObsTypes[i].description,21);
01024          line += leftJustify(string(" ")+RinexObsHeader::RegisteredRinexObsTypes[i].units,11);
01025          for(int j=1; j<=6; j++) {
01026             if(j==3 || j==4) continue;
01027             if(RinexObsHeader::RegisteredRinexObsTypes[i].depend &
01028                RinexObsHeader::StandardRinexObsTypes[j].depend)
01029                   line += string(" ")+RinexObsHeader::StandardRinexObsTypes[j].type;
01030             else line += string("   ");
01031          }
01032          if(RinexObsHeader::RegisteredRinexObsTypes[i].depend & RinexObsHeader::RinexObsType::EPdepend)
01033             line += string(" EP"); else line += string("   ");
01034          if(RinexObsHeader::RegisteredRinexObsTypes[i].depend & RinexObsHeader::RinexObsType::PSdepend)
01035             line += string(" PS"); else line += string("   ");
01036          s << line << endl;
01037       }
01038    }
01039 
01040 } // namespace gpstk

Generated on Wed Feb 8 03:31:02 2012 for GPS ToolKit Software Library by  doxygen 1.3.9.1