00001 #pragma ident "$Id: RinexObsHeader.cpp 2458 2010-09-03 14:19:23Z btolman $"
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
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
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
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
00137
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 }
00182
00183
00184
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
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
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) {
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 = "";
00370
00371 vector<RinexObsType>::const_iterator itr = obsTypeList.begin();
00372
00373 while (itr != obsTypeList.end())
00374 {
00375
00376 if (obsWritten == 0)
00377 line = rightJustify(asString(obsTypeList.size()), 6);
00378
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 }
00519
00520
00521
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);
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
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
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)
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
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
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
00714
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 }
00755
00756
00757
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
00765 if (strm.headerRead == true)
00766 return;
00767
00768
00769
00770
00771
00772
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 }
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
00829 strm.header = *this;
00830 strm.headerRead = true;
00831
00832 }
00833
00834
00835
00836 RinexObsHeader::RinexObsType
00837 RinexObsHeader::convertObsType(const string& oneObs)
00838 throw(FFStreamError)
00839 {
00840 RinexObsType ot(RegisteredRinexObsTypes[0]);
00841 for(int i=0; i<RegisteredRinexObsTypes.size(); i++) {
00842 if(RegisteredRinexObsTypes[i].type == oneObs) {
00843 ot = RegisteredRinexObsTypes[i];
00844 break;
00845 }
00846
00847
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
00979
00980
00981 int RegisterExtendedRinexObsType(string t, string d, string u, unsigned int dep)
00982 {
00983 if(t.empty()) return -1;
00984
00985
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
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
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 }