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