00001
00002 #pragma ident "$Id: RinexNavHeader.cpp 766 2007-09-20 18:32:38Z snelsen $"
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
00039
00040
00041
00042
00043
00044
00045
00046
00052 #include "StringUtils.hpp"
00053 #include "DayTime.hpp"
00054 #include "RinexNavHeader.hpp"
00055 #include "RinexNavStream.hpp"
00056
00057 #include <iostream>
00058
00059 using namespace gpstk::StringUtils;
00060 using namespace std;
00061
00062 namespace gpstk
00063 {
00064 const string RinexNavHeader::endOfHeader = "END OF HEADER";
00065 const string RinexNavHeader::leapSecondsString = "LEAP SECONDS";
00066 const string RinexNavHeader::deltaUTCString = "DELTA-UTC: A0,A1,T,W";
00067 const string RinexNavHeader::ionBetaString = "ION BETA";
00068 const string RinexNavHeader::ionAlphaString = "ION ALPHA";
00069 const string RinexNavHeader::commentString = "COMMENT";
00070 const string RinexNavHeader::runByString = "PGM / RUN BY / DATE";
00071 const string RinexNavHeader::versionString = "RINEX VERSION / TYPE";
00072
00073 void RinexNavHeader::reallyPutRecord(FFStream& ffs) const
00074 throw(std::exception, FFStreamError, StringException)
00075 {
00076 RinexNavStream& strm = dynamic_cast<RinexNavStream&>(ffs);
00077
00078 strm.header = (*this);
00079
00080 unsigned long allValid;
00081 if (version == 2.0) allValid = allValid20;
00082 else if (version == 2.1) allValid = allValid21;
00083 else if (version == 2.11) allValid = allValid211;
00084 else
00085 {
00086 FFStreamError err("Unknown RINEX version: " + asString(version,3));
00087 err.addText("Make sure to set the version correctly.");
00088 GPSTK_THROW(err);
00089 }
00090
00091 if ((valid & allValid) != allValid)
00092 {
00093 FFStreamError err("Incomplete or invalid header.");
00094 err.addText("Make sure you set all header valid bits for all of the available data.");
00095 GPSTK_THROW(err);
00096 }
00097
00098 string line;
00099
00100 if (valid & versionValid)
00101 {
00102 line = rightJustify(asString(version,3), 10);
00103 line += string(10, ' ');
00104 line += string("NAVIGATION");
00105 line += string(30, ' ');
00106 line += versionString;
00107 strm << line << endl;
00108 strm.lineNumber++;
00109 }
00110 if (valid & runByValid)
00111 {
00112 line = leftJustify(fileProgram,20);
00113 line += leftJustify(fileAgency,20);
00114 DayTime dt;
00115 dt.setLocalTime();
00116 string dat = dt.printf("%02m/%02d/%04Y %02H:%02M:%02S");
00117 line += leftJustify(dat, 20);
00118 line += runByString;
00119 strm << line << endl;
00120 strm.lineNumber++;
00121 }
00122 if (valid & commentValid)
00123 {
00124 vector<string>::const_iterator itr = commentList.begin();
00125 while (itr != commentList.end())
00126 {
00127 line = leftJustify((*itr), 60);
00128 line += commentString;
00129 strm << line << endl;
00130 strm.lineNumber++;
00131 itr++;
00132 }
00133 }
00134 if (valid & ionAlphaValid)
00135 {
00136 line = string(2, ' ');
00137 for (int i = 0; i < 4; i++)
00138 {
00139 line += rightJustify(doub2for(ionAlpha[i], 12, 2),12);
00140 }
00141 line += string(10, ' ');
00142 line += ionAlphaString;
00143 strm << line << endl;
00144 strm.lineNumber++;
00145 }
00146 if (valid & ionBetaValid)
00147 {
00148 line = string(2, ' ');
00149 for (int i = 0; i < 4; i++)
00150 {
00151 line += rightJustify(doub2for(ionBeta[i], 12, 2),12);
00152 }
00153 line += string(10, ' ');
00154 line += ionBetaString;
00155 strm << line << endl;
00156 strm.lineNumber++;
00157 }
00158 if (valid & deltaUTCValid)
00159 {
00160 line = string(3, ' ');
00161
00162 line += doub2for(A0, 19, 2);
00163 line += doub2for(A1, 19, 2);
00164 line += rightJustify(asString(UTCRefTime),9);
00165 line += rightJustify(asString(UTCRefWeek),9);
00166 line += string(1, ' ');
00167 line += deltaUTCString;
00168 strm << line << endl;
00169 strm.lineNumber++;
00170 }
00171 if (valid & leapSecondsValid)
00172 {
00173 line = rightJustify(asString(leapSeconds), 6);
00174 line += string(54, ' ');
00175 line += leapSecondsString;
00176 strm << line << endl;
00177 strm.lineNumber++;
00178 }
00179 if (valid & endValid)
00180 {
00181 line = string(60,' ');
00182 line += endOfHeader;
00183 strm << line << endl;
00184 strm.lineNumber++;
00185 }
00186
00187 }
00188
00189 void RinexNavHeader::reallyGetRecord(FFStream& ffs)
00190 throw(std::exception, FFStreamError, StringException)
00191 {
00192 RinexNavStream& strm = dynamic_cast<RinexNavStream&>(ffs);
00193
00194
00195 if (strm.headerRead == true)
00196 return;
00197
00198 valid = 0;
00199
00200
00201 commentList.clear();
00202
00203 while (! (valid & endValid))
00204 {
00205 string line;
00206 strm.formattedGetLine(line);
00207 StringUtils::stripTrailing(line);
00208
00209 if (line.length()==0) continue;
00210 else if (line.length()<60 || line.length()>80)
00211 {
00212 FFStreamError e("Invalid line length");
00213 GPSTK_THROW(e);
00214 }
00215
00216 string thisLabel(line, 60, 20);
00217
00218 if (thisLabel == versionString)
00219 {
00220 version = asDouble(line.substr(0,20));
00221 fileType = strip(line.substr(20,20));
00222 if ( (fileType[0] != 'N') &&
00223 (fileType[0] != 'n'))
00224 {
00225 FFStreamError e("This isn't a Rinex Nav file");
00226 GPSTK_THROW(e);
00227 }
00228 valid |= versionValid;
00229 }
00230 else if (thisLabel == runByString)
00231 {
00232 fileProgram = strip(line.substr(0,20));
00233 fileAgency = strip(line.substr(20,20));
00234 date = strip(line.substr(40,20));
00235 valid |= runByValid;
00236 }
00237 else if (thisLabel == commentString)
00238 {
00239 commentList.push_back(strip(line.substr(0,60)));
00240 valid |= commentValid;
00241 }
00242 else if (thisLabel == ionAlphaString)
00243 {
00244 for(int i = 0; i < 4; i++)
00245 ionAlpha[i] = gpstk::StringUtils::for2doub(line.substr(2 + 12 * i,12));
00246 valid |= ionAlphaValid;
00247 }
00248 else if (thisLabel == ionBetaString)
00249 {
00250 for(int i = 0; i < 4; i++)
00251 ionBeta[i] = gpstk::StringUtils::for2doub(line.substr(2 + 12 * i,12));
00252 valid |= ionBetaValid;
00253 }
00254 else if (thisLabel == deltaUTCString)
00255 {
00256 A0 = gpstk::StringUtils::for2doub(line.substr(3,19));
00257 A1 = gpstk::StringUtils::for2doub(line.substr(22,19));
00258 UTCRefTime = asInt(line.substr(41,9));
00259 UTCRefWeek = asInt(line.substr(50,9));
00260 valid |= deltaUTCValid;
00261 }
00262 else if (thisLabel == leapSecondsString)
00263 {
00264 leapSeconds = asInt(line.substr(0,6));
00265 valid |= leapSecondsValid;
00266 }
00267 else if (thisLabel == endOfHeader)
00268 {
00269 valid |= endValid;
00270 }
00271 else
00272 {
00273 throw(FFStreamError("Unknown header label at line " +
00274 asString<size_t>(strm.lineNumber)));
00275 }
00276 }
00277
00278 unsigned long allValid;
00279 if (version == 2.0) allValid = allValid20;
00280 else if (version == 2.1) allValid = allValid21;
00281 else if (version == 2.11) allValid = allValid211;
00282 else
00283 {
00284 FFStreamError e("Unknown or unsupported RINEX version " +
00285 asString(version));
00286 GPSTK_THROW(e);
00287 }
00288
00289 if ( (allValid & valid) != allValid)
00290 {
00291 FFStreamError e("Incomplete or invalid header");
00292 GPSTK_THROW(e);
00293 }
00294
00295
00296 strm.header = *this;
00297 strm.headerRead = true;
00298 }
00299
00300 void RinexNavHeader::dump(ostream& s) const
00301 {
00302 int i;
00303 s << "---------------------------------- REQUIRED ----------------------------------\n";
00304 s << "Rinex Version " << fixed << setw(5) << setprecision(2) << version
00305 << ", File type " << fileType << ".\n";
00306 s << "Prgm: " << fileProgram << ", Run: " << date << ", By: " << fileAgency << endl;
00307
00308 s << "(This header is ";
00309 if((valid & allValid211) == allValid211) s << "VALID 2.11";
00310 else if((valid & allValid21) == allValid21) s << "VALID 2.1";
00311 else if((valid & allValid20) == allValid20) s << "VALID 2.0";
00312 else s << "NOT VALID";
00313 s << " Rinex.)\n";
00314
00315 if(!(valid & versionValid)) s << " Version is NOT valid\n";
00316 if(!(valid & runByValid)) s << " Run by is NOT valid\n";
00317 if(!(valid & endValid)) s << " End is NOT valid\n";
00318
00319 s << "---------------------------------- OPTIONAL ----------------------------------\n";
00320 if(valid & ionAlphaValid) { s << "Ion alpha:";
00321 for(i=0; i<4; i++) s << " " << scientific << setprecision(4) << ionAlpha[i];
00322 s << endl; }
00323 else s << " Ion alpha is NOT valid\n";
00324 if(valid & ionBetaValid) { s << "Ion beta:";
00325 for(i=0; i<4; i++) s << " " << scientific << setprecision(4) << ionBeta[i];
00326 s << endl; }
00327 else s << " Ion beta is NOT valid\n";
00328 if(valid & deltaUTCValid) s << "Delta UTC: A0="
00329 << scientific << setprecision(12) << A0 << ", A1="
00330 << scientific << setprecision(12) << A1 << ", UTC ref = ("
00331 << UTCRefWeek << "," << UTCRefTime << ")\n";
00332 else s << " Delta UTC is NOT valid\n";
00333 if(valid & leapSecondsValid) s << "Leap seconds: " << leapSeconds << endl;
00334 else s << " Leap seconds is NOT valid\n";
00335 if(commentList.size() > 0) {
00336 s << "Comments (" << commentList.size() << ") :\n";
00337 for(int i=0; i<commentList.size(); i++)
00338 s << commentList[i] << endl;
00339 }
00340 s << "-------------------------------- END OF HEADER -------------------------------\n";
00341 }
00342
00343 }