source: ntrip/trunk/BNC/src/rinex/rnxobsfile.cpp@ 6127

Last change on this file since 6127 was 6127, checked in by mervart, 8 years ago
File size: 31.4 KB
Line 
1// Part of BNC, a utility for retrieving decoding and
2// converting GNSS data streams from NTRIP broadcasters.
3//
4// Copyright (C) 2007
5// German Federal Agency for Cartography and Geodesy (BKG)
6// http://www.bkg.bund.de
7// Czech Technical University Prague, Department of Geodesy
8// http://www.fsv.cvut.cz
9//
10// Email: euref-ip@bkg.bund.de
11//
12// This program is free software; you can redistribute it and/or
13// modify it under the terms of the GNU General Public License
14// as published by the Free Software Foundation, version 2.
15//
16// This program is distributed in the hope that it will be useful,
17// but WITHOUT ANY WARRANTY; without even the implied warranty of
18// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19// GNU General Public License for more details.
20//
21// You should have received a copy of the GNU General Public License
22// along with this program; if not, write to the Free Software
23// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24
25/* -------------------------------------------------------------------------
26 * BKG NTRIP Client
27 * -------------------------------------------------------------------------
28 *
29 * Class: t_rnxObsFile
30 *
31 * Purpose: Reads RINEX Observation File
32 *
33 * Author: L. Mervart
34 *
35 * Created: 24-Jan-2012
36 *
37 * Changes:
38 *
39 * -----------------------------------------------------------------------*/
40
41#include <iostream>
42#include <iomanip>
43#include <sstream>
44#include "rnxobsfile.h"
45#include "bncutils.h"
46#include "bnccore.h"
47
48using namespace std;
49
50const QString t_rnxObsHeader::defaultSystems = "GRES";
51
52// Constructor
53////////////////////////////////////////////////////////////////////////////
54t_rnxObsHeader::t_rnxObsHeader() {
55 _antNEU.ReSize(3); _antNEU = 0.0;
56 _antXYZ.ReSize(3); _antXYZ = 0.0;
57 _antBSG.ReSize(3); _antBSG = 0.0;
58 _xyz.ReSize(3); _xyz = 0.0;
59 _version = 0.0;
60 _interval = 0.0;
61 for (unsigned iPrn = 1; iPrn <= t_prn::MAXPRN_GPS; iPrn++) {
62 _wlFactorsL1[iPrn] = 1;
63 _wlFactorsL2[iPrn] = 1;
64 }
65}
66
67// Destructor
68////////////////////////////////////////////////////////////////////////////
69t_rnxObsHeader::~t_rnxObsHeader() {
70}
71
72// Read Header
73////////////////////////////////////////////////////////////////////////////
74t_irc t_rnxObsHeader::read(QTextStream* stream, int maxLines) {
75 _comments.clear();
76 int numLines = 0;
77 while ( stream->status() == QTextStream::Ok && !stream->atEnd() ) {
78 QString line = stream->readLine(); ++ numLines;
79 if (line.isEmpty()) {
80 continue;
81 }
82 if (line.indexOf("END OF FILE") != -1) {
83 break;
84 }
85 QString value = line.mid(0,60).trimmed();
86 QString key = line.mid(60).trimmed();
87 if (key == "END OF HEADER") {
88 break;
89 }
90 else if (key == "RINEX VERSION / TYPE") {
91 QTextStream in(value.toAscii(), QIODevice::ReadOnly);
92 in >> _version;
93 }
94 else if (key == "MARKER NAME") {
95 _markerName = value;
96 }
97 else if (key == "MARKER NUMBER") {
98 _markerNumber = line.mid(0,20).trimmed();
99 }
100 else if (key == "ANT # / TYPE") {
101 _antennaNumber = line.mid( 0,20).trimmed();
102 _antennaName = line.mid(20,20).trimmed();
103 }
104 else if (key == "OBSERVER / AGENCY") {
105 _observer = line.mid( 0,20).trimmed();
106 _agency = line.mid(20,40).trimmed();
107 }
108 else if (key == "REC # / TYPE / VERS") {
109 _receiverNumber = line.mid( 0,20).trimmed();
110 _receiverType = line.mid(20,20).trimmed();
111 _receiverVersion = line.mid(40,20).trimmed();
112 }
113 else if (key == "INTERVAL") {
114 QTextStream in(value.toAscii(), QIODevice::ReadOnly);
115 in >> _interval;
116 }
117 else if (key == "COMMENT") {
118 _comments << line.mid(0,60).trimmed();
119 }
120 else if (key == "WAVELENGTH FACT L1/2") {
121 QTextStream in(value.toAscii(), QIODevice::ReadOnly);
122 int wlFactL1 = 0;
123 int wlFactL2 = 0;
124 int numSat = 0;
125 in >> wlFactL1 >> wlFactL2 >> numSat;
126 if (numSat == 0) {
127 for (unsigned iPrn = 1; iPrn <= t_prn::MAXPRN_GPS; iPrn++) {
128 _wlFactorsL1[iPrn] = wlFactL1;
129 _wlFactorsL2[iPrn] = wlFactL2;
130 }
131 }
132 else {
133 for (int ii = 0; ii < numSat; ii++) {
134 QString prn; in >> prn;
135 if (prn[0] == 'G') {
136 int iPrn;
137 readInt(prn, 1, 2, iPrn);
138 _wlFactorsL1[iPrn] = wlFactL1;
139 _wlFactorsL2[iPrn] = wlFactL2;
140 }
141 }
142 }
143 }
144 else if (key == "APPROX POSITION XYZ") {
145 QTextStream in(value.toAscii(), QIODevice::ReadOnly);
146 in >> _xyz[0] >> _xyz[1] >> _xyz[2];
147 }
148 else if (key == "ANTENNA: DELTA H/E/N") {
149 QTextStream in(value.toAscii(), QIODevice::ReadOnly);
150 in >> _antNEU[2] >> _antNEU[1] >> _antNEU[0];
151 }
152 else if (key == "ANTENNA: DELTA X/Y/Z") {
153 QTextStream in(value.toAscii(), QIODevice::ReadOnly);
154 in >> _antXYZ[0] >> _antXYZ[1] >> _antXYZ[2];
155 }
156 else if (key == "ANTENNA: B.SIGHT XYZ") {
157 QTextStream in(value.toAscii(), QIODevice::ReadOnly);
158 in >> _antBSG[0] >> _antBSG[1] >> _antBSG[2];
159 }
160 else if (key == "# / TYPES OF OBSERV") {
161 QTextStream* in = new QTextStream(value.toAscii(), QIODevice::ReadOnly);
162 int nTypes;
163 *in >> nTypes;
164 char sys0 = defaultSystems[0].toAscii();
165 _obsTypes[sys0].clear();
166 for (int ii = 0; ii < nTypes; ii++) {
167 if (ii > 0 && ii % 9 == 0) {
168 line = stream->readLine(); ++numLines;
169 delete in;
170 in = new QTextStream(line.left(60).toAscii(), QIODevice::ReadOnly);
171 }
172 QString hlp;
173 *in >> hlp;
174 _obsTypes[sys0].append(hlp);
175 }
176 for (int ii = 1; ii < defaultSystems.length(); ii++) {
177 char sysI = defaultSystems[ii].toAscii();
178 _obsTypes[sysI] = _obsTypes[sys0];
179 }
180 }
181 else if (key == "SYS / # / OBS TYPES") {
182 QTextStream* in = new QTextStream(value.toAscii(), QIODevice::ReadOnly);
183 char sys;
184 int nTypes;
185 *in >> sys >> nTypes;
186 _obsTypes[sys].clear();
187 for (int ii = 0; ii < nTypes; ii++) {
188 if (ii > 0 && ii % 13 == 0) {
189 line = stream->readLine(); ++numLines;
190 delete in;
191 in = new QTextStream(line.toAscii(), QIODevice::ReadOnly);
192 }
193 QString hlp;
194 *in >> hlp;
195 _obsTypes[sys].push_back(hlp);
196 }
197 delete in;
198 }
199 else if (key == "TIME OF FIRST OBS") {
200 QTextStream in(value.toAscii(), QIODevice::ReadOnly);
201 int year, month, day, hour, min;
202 double sec;
203 in >> year >> month >> day >> hour >> min >> sec;
204 _startTime.set(year, month, day, hour, min, sec);
205 }
206 if (maxLines > 0 && numLines == maxLines) {
207 break;
208 }
209 }
210
211 return success;
212}
213
214// Write Header
215////////////////////////////////////////////////////////////////////////////
216void t_rnxObsHeader::write(QTextStream* stream,
217 const QMap<QString, QString>* txtMap) const {
218
219 QStringList newComments;
220 QString runBy = BNC_CORE->userName();
221
222 if (txtMap) {
223 QMapIterator<QString, QString> it(*txtMap);
224 while (it.hasNext()) {
225 it.next();
226 if (it.key() == "RUN BY") {
227 runBy = it.value();
228 }
229 else if (it.key() == "COMMENT") {
230 newComments = it.value().split("\\n", QString::SkipEmptyParts);
231 }
232 }
233 }
234
235 *stream << QString("%1 Observation data Mixed")
236 .arg(_version, 9, 'f', 2)
237 .leftJustified(60)
238 << "RINEX VERSION / TYPE\n";
239
240 const QString fmtDate = (_version < 3.0) ? "dd-MMM-yy hh:mm"
241 : "yyyyMMdd hhmmss UTC";
242 *stream << QString("%1%2%3")
243 .arg(BNC_CORE->pgmName(), -20)
244 .arg(runBy.trimmed().left(20), -20)
245 .arg(QDateTime::currentDateTime().toUTC().toString(fmtDate), -20)
246 .leftJustified(60)
247 << "PGM / RUN BY / DATE\n";
248
249 QStringListIterator itCmnt(_comments + newComments);
250 while (itCmnt.hasNext()) {
251 *stream << itCmnt.next().trimmed().left(60).leftJustified(60) << "COMMENT\n";
252 }
253
254 *stream << QString("%1")
255 .arg(_markerName, -60)
256 .leftJustified(60)
257 << "MARKER NAME\n";
258
259 if (!_markerNumber.isEmpty()) {
260 *stream << QString("%1")
261 .arg(_markerNumber, -20)
262 .leftJustified(60)
263 << "MARKER NUMBER\n";
264 }
265
266 *stream << QString("%1%2")
267 .arg(_observer, -20)
268 .arg(_agency, -40)
269 .leftJustified(60)
270 << "OBSERVER / AGENCY\n";
271
272 *stream << QString("%1%2%3")
273 .arg(_receiverNumber, -20)
274 .arg(_receiverType, -20)
275 .arg(_receiverVersion, -20)
276 .leftJustified(60)
277 << "REC # / TYPE / VERS\n";
278
279 *stream << QString("%1%2")
280 .arg(_antennaNumber, -20)
281 .arg(_antennaName, -20)
282 .leftJustified(60)
283 << "ANT # / TYPE\n";
284
285 *stream << QString("%1%2%3")
286 .arg(_xyz(1), 14, 'f', 4)
287 .arg(_xyz(2), 14, 'f', 4)
288 .arg(_xyz(3), 14, 'f', 4)
289 .leftJustified(60)
290 << "APPROX POSITION XYZ\n";
291
292 *stream << QString("%1%2%3")
293 .arg(_antNEU(3), 14, 'f', 4)
294 .arg(_antNEU(2), 14, 'f', 4)
295 .arg(_antNEU(1), 14, 'f', 4)
296 .leftJustified(60)
297 << "ANTENNA: DELTA H/E/N\n";
298
299 if (_version < 3.0) {
300 int defaultWlFact1 = _wlFactorsL1[1];
301 int defaultWlFact2 = _wlFactorsL2[1]; // TODO check all prns
302 *stream << QString("%1%2")
303 .arg(defaultWlFact1, 6)
304 .arg(defaultWlFact2, 6)
305 .leftJustified(60)
306 << "WAVELENGTH FACT L1/2\n";
307 }
308
309 *stream << obsTypesStrings().join("");
310
311 if (_interval > 0) {
312 *stream << QString("%1")
313 .arg(_interval, 10, 'f', 3)
314 .leftJustified(60)
315 << "INTERVAL\n";
316 }
317
318 unsigned year, month, day, hour, min;
319 double sec;
320 _startTime.civil_date(year, month, day);
321 _startTime.civil_time(hour, min, sec);
322 *stream << QString("%1%2%3%4%5%6%7")
323 .arg(year, 6)
324 .arg(month, 6)
325 .arg(day, 6)
326 .arg(hour, 6)
327 .arg(min, 6)
328 .arg(sec, 13, 'f', 7)
329 .arg("GPS", 8)
330 .leftJustified(60)
331 << "TIME OF FIRST OBS\n";
332
333 *stream << QString()
334 .leftJustified(60)
335 << "END OF HEADER\n";
336}
337
338// Number of Different Systems
339////////////////////////////////////////////////////////////////////////////
340int t_rnxObsHeader::numSys() const {
341 return _obsTypes.size();
342}
343
344// Number of Observation Types (satellite-system specific)
345////////////////////////////////////////////////////////////////////////////
346int t_rnxObsHeader::nTypes(char sys) const {
347 if (_obsTypes.contains(sys)) {
348 return _obsTypes[sys].size();
349 }
350 else {
351 return 0;
352 }
353}
354
355// Observation Type (satellite-system specific)
356////////////////////////////////////////////////////////////////////////////
357QString t_rnxObsHeader::obsType(char sys, int index, double version) const {
358
359 if (version == 0.0) {
360 version = _version;
361 }
362 if (_obsTypes.contains(sys)) {
363 QString origType = _obsTypes[sys].at(index);
364 if (int(version) == int(_version)) {
365 return origType;
366 }
367 else if (int(version) == 2) {
368 return t_rnxObsFile::type3to2(origType);
369 }
370 else if (int(version) == 3) {
371 return t_rnxObsFile::type2to3(sys, origType);
372 }
373 }
374 return "";
375}
376
377// Write Observation Types
378////////////////////////////////////////////////////////////////////////////
379QStringList t_rnxObsHeader::obsTypesStrings() const {
380
381 QStringList strList;
382
383 if (_version < 3.0) {
384 char sys0 = defaultSystems[0].toAscii();
385 QString hlp;
386 QTextStream(&hlp) << QString("%1").arg(_obsTypes[sys0].size(), 6);
387 for (int ii = 0; ii < _obsTypes[sys0].size(); ii++) {
388 QTextStream(&hlp) << QString("%1").arg(_obsTypes[sys0][ii], 6);
389 if ((ii+1) % 9 == 0 || ii == _obsTypes[sys0].size()-1) {
390 strList.append(hlp.leftJustified(60) + "# / TYPES OF OBSERV\n");
391 hlp = QString().leftJustified(6);
392 }
393 }
394 }
395 else {
396 QMapIterator<char, QVector<QString> > it(_obsTypes);
397 while (it.hasNext()) {
398 it.next();
399 char sys = it.key();
400 const QVector<QString>& types = it.value();
401 QString hlp;
402 QTextStream(&hlp) << QString("%1 %2").arg(sys).arg(types.size(), 3);
403 for (int ii = 0; ii < types.size(); ii++) {
404 QTextStream(&hlp) << QString(" %1").arg(types[ii], -3);
405 if ((ii+1) % 13 == 0 || ii == types.size()-1) {
406 strList.append(hlp.leftJustified(60) + "SYS / # / OBS TYPES\n");
407 hlp = QString().leftJustified(6);
408 }
409 }
410 }
411 }
412
413 return strList;
414}
415
416// Constructor
417////////////////////////////////////////////////////////////////////////////
418t_rnxObsFile::t_rnxObsFile(const QString& fileName, e_inpOut inpOut) {
419 _inpOut = inpOut;
420 _stream = 0;
421 _flgPowerFail = false;
422 if (_inpOut == input) {
423 openRead(fileName);
424 }
425 else {
426 openWrite(fileName);
427 }
428}
429
430// Open for input
431////////////////////////////////////////////////////////////////////////////
432void t_rnxObsFile::openRead(const QString& fileName) {
433
434 _fileName = fileName; expandEnvVar(_fileName);
435 _file = new QFile(_fileName);
436 _file->open(QIODevice::ReadOnly | QIODevice::Text);
437 _stream = new QTextStream();
438 _stream->setDevice(_file);
439
440 _header.read(_stream);
441
442 // Guess Observation Interval
443 // --------------------------
444 if (_header._interval == 0.0) {
445 bncTime ttPrev;
446 for (int iEpo = 0; iEpo < 10; iEpo++) {
447 const t_rnxEpo* rnxEpo = nextEpoch();
448 if (!rnxEpo) {
449 throw QString("t_rnxObsFile: not enough epochs");
450 }
451 if (iEpo > 0) {
452 double dt = rnxEpo->tt - ttPrev;
453 if (_header._interval == 0.0 || dt < _header._interval) {
454 _header._interval = dt;
455 }
456 }
457 ttPrev = rnxEpo->tt;
458 }
459 _stream->seek(0);
460 _header.read(_stream);
461 }
462
463 // Time of first observation
464 // -------------------------
465 if (!_header._startTime.valid()) {
466 const t_rnxEpo* rnxEpo = nextEpoch();
467 if (!rnxEpo) {
468 throw QString("t_rnxObsFile: not enough epochs");
469 }
470 _header._startTime = rnxEpo->tt;
471 _stream->seek(0);
472 _header.read(_stream);
473 }
474}
475
476// Open for output
477////////////////////////////////////////////////////////////////////////////
478void t_rnxObsFile::openWrite(const QString& fileName) {
479
480 _fileName = fileName; expandEnvVar(_fileName);
481 _file = new QFile(_fileName);
482 _file->open(QIODevice::WriteOnly | QIODevice::Text);
483 _stream = new QTextStream();
484 _stream->setDevice(_file);
485}
486
487// Destructor
488////////////////////////////////////////////////////////////////////////////
489t_rnxObsFile::~t_rnxObsFile() {
490 close();
491}
492
493// Close
494////////////////////////////////////////////////////////////////////////////
495void t_rnxObsFile::close() {
496 delete _stream; _stream = 0;
497 delete _file; _file = 0;
498}
499
500// Handle Special Epoch Flag
501////////////////////////////////////////////////////////////////////////////
502void t_rnxObsFile::handleEpochFlag(int flag, const QString& line,
503 bool& headerReRead) {
504
505 headerReRead = false;
506
507 // Power Failure
508 // -------------
509 if (flag == 1) {
510 _flgPowerFail = true;
511 }
512
513 // Start moving antenna
514 // --------------------
515 else if (flag == 2) {
516 // no action
517 }
518
519 // Re-Read Header
520 // --------------
521 else if (flag == 3 || flag == 4 || flag == 5) {
522 int numLines = 0;
523 if (version() < 3.0) {
524 readInt(line, 29, 3, numLines);
525 }
526 else {
527 readInt(line, 32, 3, numLines);
528 }
529 if (flag == 3 || flag == 4) {
530 _header.read(_stream, numLines);
531 headerReRead = true;
532 }
533 else {
534 for (int ii = 0; ii < numLines; ii++) {
535 _stream->readLine();
536 }
537 }
538 }
539
540 // Unhandled Flag
541 // --------------
542 else {
543 throw QString("t_rnxObsFile: unhandled flag\n" + line);
544 }
545}
546
547// Retrieve single Epoch
548////////////////////////////////////////////////////////////////////////////
549t_rnxObsFile::t_rnxEpo* t_rnxObsFile::nextEpoch() {
550 _currEpo.clear();
551 if (version() < 3.0) {
552 return nextEpochV2();
553 }
554 else {
555 return nextEpochV3();
556 }
557}
558
559// Retrieve single Epoch (RINEX Version 3)
560////////////////////////////////////////////////////////////////////////////
561t_rnxObsFile::t_rnxEpo* t_rnxObsFile::nextEpochV3() {
562
563 while ( _stream->status() == QTextStream::Ok && !_stream->atEnd() ) {
564
565 QString line = _stream->readLine();
566
567 if (line.isEmpty()) {
568 continue;
569 }
570
571 int flag = 0;
572 readInt(line, 31, 1, flag);
573 if (flag > 0) {
574 bool headerReRead = false;
575 handleEpochFlag(flag, line, headerReRead);
576 if (headerReRead) {
577 continue;
578 }
579 }
580
581 QTextStream in(line.mid(1).toAscii(), QIODevice::ReadOnly);
582
583 // Epoch Time
584 // ----------
585 int year, month, day, hour, min;
586 double sec;
587 in >> year >> month >> day >> hour >> min >> sec;
588 _currEpo.tt.set(year, month, day, hour, min, sec);
589
590 // Number of Satellites
591 // --------------------
592 int numSat;
593 readInt(line, 32, 3, numSat);
594
595 _currEpo.rnxSat.resize(numSat);
596 _currEpo.version = _header._version;
597
598 // Observations
599 // ------------
600 for (int iSat = 0; iSat < numSat; iSat++) {
601 line = _stream->readLine();
602 t_prn prn; prn.set(line.left(3).toAscii().data());
603 _currEpo.rnxSat[iSat].prn = prn;
604 char sys = prn.system();
605 for (int iType = 0; iType < _header.nTypes(sys); iType++) {
606 int pos = 3 + 16*iType;
607 double obsValue = 0.0;
608 int lli = 0;
609 int snr = 0;
610 readDbl(line, pos, 14, obsValue);
611 readInt(line, pos + 14, 1, lli);
612 readInt(line, pos + 15, 1, snr);
613 if (_flgPowerFail) {
614 lli |= 1;
615 }
616 QString type = obsType(sys, iType);
617 _currEpo.rnxSat[iSat].obs[type].value = obsValue;
618 _currEpo.rnxSat[iSat].obs[type].lli = lli;
619 _currEpo.rnxSat[iSat].obs[type].snr = snr;
620 }
621 }
622
623 _flgPowerFail = false;
624
625 return &_currEpo;
626 }
627
628 return 0;
629}
630
631// Retrieve single Epoch (RINEX Version 2)
632////////////////////////////////////////////////////////////////////////////
633t_rnxObsFile::t_rnxEpo* t_rnxObsFile::nextEpochV2() {
634
635 while ( _stream->status() == QTextStream::Ok && !_stream->atEnd() ) {
636
637 QString line = _stream->readLine();
638
639 if (line.isEmpty()) {
640 continue;
641 }
642
643 int flag = 0;
644 readInt(line, 28, 1, flag);
645 if (flag > 0) {
646 bool headerReRead = false;
647 handleEpochFlag(flag, line, headerReRead);
648 if (headerReRead) {
649 continue;
650 }
651 }
652
653 QTextStream in(line.toAscii(), QIODevice::ReadOnly);
654
655 // Epoch Time
656 // ----------
657 int year, month, day, hour, min;
658 double sec;
659 in >> year >> month >> day >> hour >> min >> sec;
660 if (year < 80) {
661 year += 2000;
662 }
663 else if (year < 100) {
664 year += 1900;
665 }
666 _currEpo.tt.set(year, month, day, hour, min, sec);
667
668 // Number of Satellites
669 // --------------------
670 int numSat;
671 readInt(line, 29, 3, numSat);
672
673 _currEpo.rnxSat.resize(numSat);
674 _currEpo.version = _header._version;
675
676 // Read Satellite Numbers
677 // ----------------------
678 int pos = 32;
679 for (int iSat = 0; iSat < numSat; iSat++) {
680 if (iSat > 0 && iSat % 12 == 0) {
681 line = _stream->readLine();
682 pos = 32;
683 }
684
685 char sys = line.toAscii()[pos];
686 int satNum; readInt(line, pos + 1, 2, satNum);
687 _currEpo.rnxSat[iSat].prn.set(sys, satNum);
688
689 pos += 3;
690 }
691
692 // Read Observation Records
693 // ------------------------
694 for (int iSat = 0; iSat < numSat; iSat++) {
695 char sys = _currEpo.rnxSat[iSat].prn.system();
696 line = _stream->readLine();
697 pos = 0;
698 for (int iType = 0; iType < _header.nTypes(sys); iType++) {
699 if (iType > 0 && iType % 5 == 0) {
700 line = _stream->readLine();
701 pos = 0;
702 }
703 double obsValue = 0.0;
704 int lli = 0;
705 int snr = 0;
706 readDbl(line, pos, 14, obsValue);
707 readInt(line, pos + 14, 1, lli);
708 readInt(line, pos + 15, 1, snr);
709
710 if (_flgPowerFail) {
711 lli |= 1;
712 }
713
714 QString type = obsType(sys, iType);
715 _currEpo.rnxSat[iSat].obs[type].value = obsValue;
716 _currEpo.rnxSat[iSat].obs[type].lli = lli;
717 _currEpo.rnxSat[iSat].obs[type].snr = snr;
718
719 pos += 16;
720 }
721 }
722
723 _flgPowerFail = false;
724
725 return &_currEpo;
726 }
727
728 return 0;
729}
730
731// Set Header Information
732////////////////////////////////////////////////////////////////////////////
733void t_rnxObsFile::setHeader(const t_rnxObsHeader& header, double version,
734 const QStringList& useObsTypes) {
735
736 if (version < 3.0) {
737 _header._version = t_rnxObsHeader::defaultRnxObsVersion2;
738 }
739 else {
740 _header._version = t_rnxObsHeader::defaultRnxObsVersion3;
741 }
742 _header._interval = header._interval;
743 _header._antennaNumber = header._antennaNumber;
744 _header._antennaName = header._antennaName;
745 _header._markerName = header._markerName;
746 _header._markerNumber = header._markerNumber;
747 _header._antNEU = header._antNEU;
748 _header._antXYZ = header._antXYZ;
749 _header._antBSG = header._antBSG;
750 _header._xyz = header._xyz;
751 _header._observer = header._observer;
752 _header._agency = header._agency;
753 _header._receiverNumber = header._receiverNumber;
754 _header._receiverType = header._receiverType;
755 _header._receiverVersion = header._receiverVersion;
756 _header._startTime = header._startTime;
757 for (unsigned iPrn = 1; iPrn <= t_prn::MAXPRN_GPS; iPrn++) {
758 _header._wlFactorsL1[iPrn] = header._wlFactorsL1[iPrn];
759 _header._wlFactorsL2[iPrn] = header._wlFactorsL2[iPrn];
760 }
761
762 // Set observation types
763 // ---------------------
764 _header._obsTypes.clear();
765 if (useObsTypes.size() == 0) {
766 _header._obsTypes = header._obsTypes;
767 }
768 else {
769 if (_header._version < 3.0) {
770 char sys0 = t_rnxObsHeader::defaultSystems[0].toAscii();
771 for (int ii = 0; ii < useObsTypes.size(); ii++) {
772 _header._obsTypes[sys0].push_back(useObsTypes[ii]);
773 }
774 for (int ii = 1; ii < t_rnxObsHeader::defaultSystems.length(); ii++) {
775 char sysI = t_rnxObsHeader::defaultSystems[ii].toAscii();
776 _header._obsTypes[sysI] = _header._obsTypes[sys0];
777 }
778 }
779 else {
780 for (int ii = 0; ii < useObsTypes.size(); ii++) {
781 if (useObsTypes[ii].indexOf(":") != -1) {
782 QStringList hlp = useObsTypes[ii].split(":", QString::SkipEmptyParts);
783 if (hlp.size() == 2 && hlp[0].length() == 1) {
784 char sys = hlp[0][0].toAscii();
785 QString type = hlp[1];
786 _header._obsTypes[sys].push_back(type);
787 }
788 }
789 else {
790 QString type = useObsTypes[ii];
791 for (int ii = 0; ii < t_rnxObsHeader::defaultSystems.length(); ii++) {
792 char sys = t_rnxObsHeader::defaultSystems[ii].toAscii();
793 _header._obsTypes[sys].push_back(type);
794 }
795 }
796 }
797 }
798 }
799}
800
801// Write Data Epoch
802////////////////////////////////////////////////////////////////////////////
803void t_rnxObsFile::writeEpoch(const t_rnxEpo* epo) {
804 if (version() < 3.0) {
805 return writeEpochV2(epo);
806 }
807 else {
808 return writeEpochV3(epo);
809 }
810}
811
812// Write Data Epoch (RINEX Version 2)
813////////////////////////////////////////////////////////////////////////////
814void t_rnxObsFile::writeEpochV2(const t_rnxEpo* epo) {
815
816 unsigned year, month, day, hour, min;
817 double sec;
818 epo->tt.civil_date(year, month, day);
819 epo->tt.civil_time(hour, min, sec);
820
821 QString dateStr;
822 QTextStream(&dateStr) << QString(" %1 %2 %3 %4 %5%6")
823 .arg(int(fmod(year, 100)), 2, 10, QChar('0'))
824 .arg(month, 2, 10, QChar('0'))
825 .arg(day, 2, 10, QChar('0'))
826 .arg(hour, 2, 10, QChar('0'))
827 .arg(min, 2, 10, QChar('0'))
828 .arg(sec, 11, 'f', 7);
829
830 int flag = 0;
831 *_stream << dateStr << QString("%1%2").arg(flag, 3).arg(epo->rnxSat.size(), 3);
832 for (unsigned iSat = 0; iSat < epo->rnxSat.size(); iSat++) {
833 const t_rnxSat& rnxSat = epo->rnxSat[iSat];
834 if (iSat > 0 && iSat % 12 == 0) {
835 *_stream << endl << QString().leftJustified(32);
836 }
837 *_stream << rnxSat.prn.toString().c_str();
838 }
839 *_stream << endl;
840 for (unsigned iSat = 0; iSat < epo->rnxSat.size(); iSat++) {
841
842 const t_rnxSat& rnxSat = epo->rnxSat[iSat];
843 char sys = rnxSat.prn.system();
844
845 for (int iType = 0; iType < nTypes(sys); iType++) {
846 if (iType > 0 && iType % 5 == 0) {
847 *_stream << endl;
848 }
849 QString type = obsType(sys, iType, epo->version);
850 if (!rnxSat.obs.contains(type)) {
851 *_stream << QString().leftJustified(16);
852 }
853 else {
854 const t_rnxObs& rnxObs = rnxSat.obs[type];
855 if (rnxObs.value == 0.0) {
856 *_stream << QString().leftJustified(16);
857 }
858 else {
859 *_stream << QString("%1").arg(rnxObs.value, 14, 'f', 3);
860 if (rnxObs.lli != 0.0) {
861 *_stream << QString("%1").arg(rnxObs.lli,1);
862 }
863 else {
864 *_stream << ' ';
865 }
866 if (rnxObs.snr != 0.0) {
867 *_stream << QString("%1").arg(rnxObs.snr,1);
868 }
869 else {
870 *_stream << ' ';
871 }
872 }
873 }
874 }
875 *_stream << endl;
876 }
877}
878
879// Write Data Epoch (RINEX Version 3)
880////////////////////////////////////////////////////////////////////////////
881void t_rnxObsFile::writeEpochV3(const t_rnxEpo* epo) {
882
883 unsigned year, month, day, hour, min;
884 double sec;
885 epo->tt.civil_date(year, month, day);
886 epo->tt.civil_time(hour, min, sec);
887
888 QString dateStr;
889 QTextStream(&dateStr) << QString("> %1 %2 %3 %4 %5%6")
890 .arg(year, 4)
891 .arg(month, 2, 10, QChar('0'))
892 .arg(day, 2, 10, QChar('0'))
893 .arg(hour, 2, 10, QChar('0'))
894 .arg(min, 2, 10, QChar('0'))
895 .arg(sec, 11, 'f', 7);
896
897 int flag = 0;
898 *_stream << dateStr << QString("%1%2\n").arg(flag, 3).arg(epo->rnxSat.size(), 3);
899
900 for (unsigned iSat = 0; iSat < epo->rnxSat.size(); iSat++) {
901 const t_rnxSat& rnxSat = epo->rnxSat[iSat];
902 char sys = rnxSat.prn.system();
903
904 *_stream << rnxSat.prn.toString().c_str();
905 for (int iType = 0; iType < nTypes(sys); iType++) {
906 QString type = obsType(sys, iType, epo->version);
907 if (!rnxSat.obs.contains(type)) {
908 *_stream << QString().leftJustified(16);
909 }
910 else {
911 const t_rnxObs& rnxObs = rnxSat.obs[type];
912 if (rnxObs.value == 0.0) {
913 *_stream << QString().leftJustified(16);
914 }
915 else {
916 *_stream << QString("%1").arg(rnxObs.value, 14, 'f', 3);
917 if (rnxObs.lli != 0.0) {
918 *_stream << QString("%1").arg(rnxObs.lli,1);
919 }
920 else {
921 *_stream << ' ';
922 }
923 if (rnxObs.snr != 0.0) {
924 *_stream << QString("%1").arg(rnxObs.snr,1);
925 }
926 else {
927 *_stream << ' ';
928 }
929 }
930 }
931 }
932 *_stream << endl;
933 }
934}
935
936// Translate Observation Type v2 --> v3
937////////////////////////////////////////////////////////////////////////////
938QString t_rnxObsFile::type2to3(char sys, const QString& typeV2) {
939
940 if (sys == 'G') {
941 if (typeV2 == "C1") return "C1C";
942 if (typeV2 == "C2") return "C2C";
943 if (typeV2 == "C5") return "C5C";
944 if (typeV2 == "P1") return "C1P";
945 if (typeV2 == "P2") return "C2P";
946 if (typeV2 == "L1") return "L1";
947 if (typeV2 == "L2") return "L2";
948 if (typeV2 == "L5") return "L5";
949 if (typeV2 == "D1") return "D1";
950 if (typeV2 == "D2") return "D2";
951 if (typeV2 == "D5") return "D5";
952 if (typeV2 == "S1") return "S1";
953 if (typeV2 == "S2") return "S2";
954 if (typeV2 == "S5") return "S5";
955 }
956
957 else if (sys == 'R') {
958 if (typeV2 == "C1") return "C1C";
959 if (typeV2 == "C2") return "C2C";
960 if (typeV2 == "P1") return "C1P";
961 if (typeV2 == "P2") return "C2P";
962 if (typeV2 == "L1") return "L1";
963 if (typeV2 == "L2") return "L2";
964 if (typeV2 == "D1") return "D1";
965 if (typeV2 == "D2") return "D2";
966 if (typeV2 == "S1") return "S1";
967 if (typeV2 == "S2") return "S2";
968 }
969
970 else if (sys == 'E') {
971 if (typeV2 == "C1") return "C1";
972 if (typeV2 == "C5") return "C5";
973 if (typeV2 == "C6") return "C6";
974 if (typeV2 == "C7") return "C7";
975 if (typeV2 == "C8") return "C8";
976 if (typeV2 == "L1") return "L1";
977 if (typeV2 == "L5") return "L5";
978 if (typeV2 == "L6") return "L6";
979 if (typeV2 == "L7") return "L7";
980 if (typeV2 == "L8") return "L8";
981 if (typeV2 == "D1") return "D1";
982 if (typeV2 == "D5") return "D5";
983 if (typeV2 == "D6") return "D6";
984 if (typeV2 == "D7") return "D7";
985 if (typeV2 == "D8") return "D8";
986 if (typeV2 == "S1") return "S1";
987 if (typeV2 == "S5") return "S5";
988 if (typeV2 == "S6") return "S6";
989 if (typeV2 == "S7") return "S7";
990 if (typeV2 == "S8") return "S8";
991 }
992
993 else if (sys == 'S') {
994 if (typeV2 == "C1") return "C1C";
995 if (typeV2 == "C5") return "C5C";
996 if (typeV2 == "L1") return "L1";
997 if (typeV2 == "L5") return "L5";
998 if (typeV2 == "D1") return "D1";
999 if (typeV2 == "D5") return "D5";
1000 if (typeV2 == "S1") return "S1";
1001 if (typeV2 == "S5") return "S5";
1002 }
1003
1004 return "";
1005}
1006
1007// Translate Observation Type v3 --> v2
1008////////////////////////////////////////////////////////////////////////////
1009QString t_rnxObsFile::type3to2(const QString& typeV3) {
1010 if (typeV3 == "C1P") {
1011 return "P1";
1012 }
1013 else if (typeV3 == "C2P") {
1014 return "P2";
1015 }
1016 else {
1017 return typeV3.left(2);
1018 }
1019
1020 return "";
1021}
1022
1023// Check for Changes in Header
1024////////////////////////////////////////////////////////////////////////////
1025void t_rnxObsFile::checkNewHeader(const t_rnxObsHeader& header) {
1026
1027 t_rnxObsHeader oldHeader(_header);
1028 setHeader(header, oldHeader._version, QStringList());
1029
1030 // Check Observation Types
1031 // -----------------------
1032 bool same = true;
1033 QMapIterator<char, QVector<QString> > it(_header._obsTypes);
1034 while (it.hasNext()) {
1035 it.next();
1036 char sys = it.key();
1037 const QVector<QString>& types = it.value();
1038 if (!oldHeader._obsTypes.contains(sys) || oldHeader._obsTypes[sys] != types) {
1039 same = false;
1040 break;
1041 }
1042 }
1043
1044 if (!same) {
1045 QStringList strLst = _header.obsTypesStrings();
1046 if (_header._version < 3.0) {
1047 *_stream << QString().leftJustified(26);
1048 }
1049 else {
1050 *_stream << '>' << QString().leftJustified(28);
1051 }
1052 *_stream << QString(" 4%1\n").arg(strLst.size(), 3)
1053 << strLst.join("");
1054 }
1055}
1056
1057// Set Observations from RINEX File
1058////////////////////////////////////////////////////////////////////////////
1059void t_rnxObsFile::setObsFromRnx(const t_rnxObsFile* rnxObsFile,
1060 const t_rnxObsFile::t_rnxEpo* epo,
1061 const t_rnxObsFile::t_rnxSat& rnxSat,
1062 t_obs& obs) {
1063
1064 strncpy(obs.StatID, rnxObsFile->markerName().toAscii().constData(),
1065 sizeof(obs.StatID));
1066
1067 obs.satSys = rnxSat.prn.system();
1068 obs.satNum = rnxSat.prn.number();
1069 obs.GPSWeek = epo->tt.gpsw();
1070 obs.GPSWeeks = epo->tt.gpssec();
1071
1072 for (int iType = 0; iType < rnxObsFile->nTypes(obs.satSys); iType++) {
1073 QString type = rnxObsFile->obsType(obs.satSys, iType);
1074 if (rnxSat.obs.contains(type)) {
1075 const t_rnxObs& rnxObs = rnxSat.obs[type];
1076 obs.setMeasdata(type, rnxObsFile->version(), rnxObs.value);
1077 if (type.indexOf("L1") == 0) {
1078 obs.snrL1 = rnxObs.snr;
1079 obs.slipL1 = (rnxObs.lli & 1);
1080 }
1081 else if (type.indexOf("L2") == 0) {
1082 obs.snrL2 = rnxObs.snr;
1083 obs.slipL2 = (rnxObs.lli & 1);
1084 }
1085 else if (type.indexOf("L5") == 0) {
1086 obs.snrL5 = rnxObs.snr;
1087 obs.slipL5 = (rnxObs.lli & 1);
1088 }
1089 }
1090 }
1091}
1092
Note: See TracBrowser for help on using the repository browser.