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

Last change on this file since 6221 was 6221, checked in by mervart, 10 years ago
File size: 29.6 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//
345////////////////////////////////////////////////////////////////////////////
346char t_rnxObsHeader::system(int iSys) const {
347 int iSysLocal = -1;
348 QMapIterator<char, QVector<QString> > it(_obsTypes);
349 while (it.hasNext()) {
350 ++iSysLocal;
351 it.next();
352 if (iSysLocal == iSys) {
353 return it.key();
354 }
355 }
356 return ' ';
357}
358
359// Number of Observation Types (satellite-system specific)
360////////////////////////////////////////////////////////////////////////////
361int t_rnxObsHeader::nTypes(char sys) const {
362 if (_obsTypes.contains(sys)) {
363 return _obsTypes[sys].size();
364 }
365 else {
366 return 0;
367 }
368}
369
370// Observation Type (satellite-system specific)
371////////////////////////////////////////////////////////////////////////////
372QString t_rnxObsHeader::obsType(char sys, int index, double version) const {
373
374 if (version == 0.0) {
375 version = _version;
376 }
377 if (_obsTypes.contains(sys)) {
378 QString origType = _obsTypes[sys].at(index);
379 if (int(version) == int(_version)) {
380 return origType;
381 }
382 else if (int(version) == 2) {
383 return t_rnxObsFile::type3to2(sys, origType);
384 }
385 else if (int(version) == 3) {
386 return t_rnxObsFile::type2to3(sys, origType);
387 }
388 }
389 return "";
390}
391
392// Write Observation Types
393////////////////////////////////////////////////////////////////////////////
394QStringList t_rnxObsHeader::obsTypesStrings() const {
395
396 QStringList strList;
397
398 if (_version < 3.0) {
399 char sys0 = defaultSystems[0].toAscii();
400 QString hlp;
401 QTextStream(&hlp) << QString("%1").arg(_obsTypes[sys0].size(), 6);
402 for (int ii = 0; ii < _obsTypes[sys0].size(); ii++) {
403 QTextStream(&hlp) << QString("%1").arg(_obsTypes[sys0][ii], 6);
404 if ((ii+1) % 9 == 0 || ii == _obsTypes[sys0].size()-1) {
405 strList.append(hlp.leftJustified(60) + "# / TYPES OF OBSERV\n");
406 hlp = QString().leftJustified(6);
407 }
408 }
409 }
410 else {
411 for (int iSys = 0; iSys < numSys(); iSys++) {
412 char sys = system(iSys);
413 QString hlp;
414 QTextStream(&hlp) << QString("%1 %2").arg(sys).arg(nTypes(sys), 3);
415 for (int iType = 0; iType < nTypes(sys); iType++) {
416 QString type = obsType(sys, iType);
417 QTextStream(&hlp) << QString(" %1").arg(type, -3);
418 if ((iType+1) % 13 == 0 || iType == nTypes(sys)-1) {
419 strList.append(hlp.leftJustified(60) + "SYS / # / OBS TYPES\n");
420 hlp = QString().leftJustified(6);
421 }
422 }
423 }
424 }
425
426 return strList;
427}
428
429// Constructor
430////////////////////////////////////////////////////////////////////////////
431t_rnxObsFile::t_rnxObsFile(const QString& fileName, e_inpOut inpOut) {
432 _inpOut = inpOut;
433 _stream = 0;
434 _flgPowerFail = false;
435 if (_inpOut == input) {
436 openRead(fileName);
437 }
438 else {
439 openWrite(fileName);
440 }
441}
442
443// Open for input
444////////////////////////////////////////////////////////////////////////////
445void t_rnxObsFile::openRead(const QString& fileName) {
446
447 _fileName = fileName; expandEnvVar(_fileName);
448 _file = new QFile(_fileName);
449 _file->open(QIODevice::ReadOnly | QIODevice::Text);
450 _stream = new QTextStream();
451 _stream->setDevice(_file);
452
453 _header.read(_stream);
454
455 // Guess Observation Interval
456 // --------------------------
457 if (_header._interval == 0.0) {
458 bncTime ttPrev;
459 for (int iEpo = 0; iEpo < 10; iEpo++) {
460 const t_rnxEpo* rnxEpo = nextEpoch();
461 if (!rnxEpo) {
462 throw QString("t_rnxObsFile: not enough epochs");
463 }
464 if (iEpo > 0) {
465 double dt = rnxEpo->tt - ttPrev;
466 if (_header._interval == 0.0 || dt < _header._interval) {
467 _header._interval = dt;
468 }
469 }
470 ttPrev = rnxEpo->tt;
471 }
472 _stream->seek(0);
473 _header.read(_stream);
474 }
475
476 // Time of first observation
477 // -------------------------
478 if (!_header._startTime.valid()) {
479 const t_rnxEpo* rnxEpo = nextEpoch();
480 if (!rnxEpo) {
481 throw QString("t_rnxObsFile: not enough epochs");
482 }
483 _header._startTime = rnxEpo->tt;
484 _stream->seek(0);
485 _header.read(_stream);
486 }
487}
488
489// Open for output
490////////////////////////////////////////////////////////////////////////////
491void t_rnxObsFile::openWrite(const QString& fileName) {
492
493 _fileName = fileName; expandEnvVar(_fileName);
494 _file = new QFile(_fileName);
495 _file->open(QIODevice::WriteOnly | QIODevice::Text);
496 _stream = new QTextStream();
497 _stream->setDevice(_file);
498}
499
500// Destructor
501////////////////////////////////////////////////////////////////////////////
502t_rnxObsFile::~t_rnxObsFile() {
503 close();
504}
505
506// Close
507////////////////////////////////////////////////////////////////////////////
508void t_rnxObsFile::close() {
509 delete _stream; _stream = 0;
510 delete _file; _file = 0;
511}
512
513// Handle Special Epoch Flag
514////////////////////////////////////////////////////////////////////////////
515void t_rnxObsFile::handleEpochFlag(int flag, const QString& line,
516 bool& headerReRead) {
517
518 headerReRead = false;
519
520 // Power Failure
521 // -------------
522 if (flag == 1) {
523 _flgPowerFail = true;
524 }
525
526 // Start moving antenna
527 // --------------------
528 else if (flag == 2) {
529 // no action
530 }
531
532 // Re-Read Header
533 // --------------
534 else if (flag == 3 || flag == 4 || flag == 5) {
535 int numLines = 0;
536 if (version() < 3.0) {
537 readInt(line, 29, 3, numLines);
538 }
539 else {
540 readInt(line, 32, 3, numLines);
541 }
542 if (flag == 3 || flag == 4) {
543 _header.read(_stream, numLines);
544 headerReRead = true;
545 }
546 else {
547 for (int ii = 0; ii < numLines; ii++) {
548 _stream->readLine();
549 }
550 }
551 }
552
553 // Unhandled Flag
554 // --------------
555 else {
556 throw QString("t_rnxObsFile: unhandled flag\n" + line);
557 }
558}
559
560// Retrieve single Epoch
561////////////////////////////////////////////////////////////////////////////
562t_rnxObsFile::t_rnxEpo* t_rnxObsFile::nextEpoch() {
563 _currEpo.clear();
564 if (version() < 3.0) {
565 return nextEpochV2();
566 }
567 else {
568 return nextEpochV3();
569 }
570}
571
572// Retrieve single Epoch (RINEX Version 3)
573////////////////////////////////////////////////////////////////////////////
574t_rnxObsFile::t_rnxEpo* t_rnxObsFile::nextEpochV3() {
575
576 while ( _stream->status() == QTextStream::Ok && !_stream->atEnd() ) {
577
578 QString line = _stream->readLine();
579
580 if (line.isEmpty()) {
581 continue;
582 }
583
584 int flag = 0;
585 readInt(line, 31, 1, flag);
586 if (flag > 0) {
587 bool headerReRead = false;
588 handleEpochFlag(flag, line, headerReRead);
589 if (headerReRead) {
590 continue;
591 }
592 }
593
594 QTextStream in(line.mid(1).toAscii(), QIODevice::ReadOnly);
595
596 // Epoch Time
597 // ----------
598 int year, month, day, hour, min;
599 double sec;
600 in >> year >> month >> day >> hour >> min >> sec;
601 _currEpo.tt.set(year, month, day, hour, min, sec);
602
603 // Number of Satellites
604 // --------------------
605 int numSat;
606 readInt(line, 32, 3, numSat);
607
608 _currEpo.rnxSat.resize(numSat);
609
610 // Observations
611 // ------------
612 for (int iSat = 0; iSat < numSat; iSat++) {
613 line = _stream->readLine();
614 t_prn prn; prn.set(line.left(3).toAscii().data());
615 _currEpo.rnxSat[iSat].prn = prn;
616 char sys = prn.system();
617 for (int iType = 0; iType < _header.nTypes(sys); iType++) {
618 int pos = 3 + 16*iType;
619 double obsValue = 0.0;
620 int lli = 0;
621 int snr = 0;
622 readDbl(line, pos, 14, obsValue);
623 readInt(line, pos + 14, 1, lli);
624 readInt(line, pos + 15, 1, snr);
625 if (_flgPowerFail) {
626 lli |= 1;
627 }
628 QString type = obsType(sys, iType);
629 _currEpo.rnxSat[iSat].obs[type].value = obsValue;
630 _currEpo.rnxSat[iSat].obs[type].lli = lli;
631 _currEpo.rnxSat[iSat].obs[type].snr = snr;
632 }
633 }
634
635 _flgPowerFail = false;
636
637 return &_currEpo;
638 }
639
640 return 0;
641}
642
643// Retrieve single Epoch (RINEX Version 2)
644////////////////////////////////////////////////////////////////////////////
645t_rnxObsFile::t_rnxEpo* t_rnxObsFile::nextEpochV2() {
646
647 while ( _stream->status() == QTextStream::Ok && !_stream->atEnd() ) {
648
649 QString line = _stream->readLine();
650
651 if (line.isEmpty()) {
652 continue;
653 }
654
655 int flag = 0;
656 readInt(line, 28, 1, flag);
657 if (flag > 0) {
658 bool headerReRead = false;
659 handleEpochFlag(flag, line, headerReRead);
660 if (headerReRead) {
661 continue;
662 }
663 }
664
665 QTextStream in(line.toAscii(), QIODevice::ReadOnly);
666
667 // Epoch Time
668 // ----------
669 int year, month, day, hour, min;
670 double sec;
671 in >> year >> month >> day >> hour >> min >> sec;
672 if (year < 80) {
673 year += 2000;
674 }
675 else if (year < 100) {
676 year += 1900;
677 }
678 _currEpo.tt.set(year, month, day, hour, min, sec);
679
680 // Number of Satellites
681 // --------------------
682 int numSat;
683 readInt(line, 29, 3, numSat);
684
685 _currEpo.rnxSat.resize(numSat);
686
687 // Read Satellite Numbers
688 // ----------------------
689 int pos = 32;
690 for (int iSat = 0; iSat < numSat; iSat++) {
691 if (iSat > 0 && iSat % 12 == 0) {
692 line = _stream->readLine();
693 pos = 32;
694 }
695
696 char sys = line.toAscii()[pos];
697 int satNum; readInt(line, pos + 1, 2, satNum);
698 _currEpo.rnxSat[iSat].prn.set(sys, satNum);
699
700 pos += 3;
701 }
702
703 // Read Observation Records
704 // ------------------------
705 for (int iSat = 0; iSat < numSat; iSat++) {
706 char sys = _currEpo.rnxSat[iSat].prn.system();
707 line = _stream->readLine();
708 pos = 0;
709 for (int iType = 0; iType < _header.nTypes(sys); iType++) {
710 if (iType > 0 && iType % 5 == 0) {
711 line = _stream->readLine();
712 pos = 0;
713 }
714 double obsValue = 0.0;
715 int lli = 0;
716 int snr = 0;
717 readDbl(line, pos, 14, obsValue);
718 readInt(line, pos + 14, 1, lli);
719 readInt(line, pos + 15, 1, snr);
720
721 if (_flgPowerFail) {
722 lli |= 1;
723 }
724
725 QString type = obsType(sys, iType);
726 _currEpo.rnxSat[iSat].obs[type].value = obsValue;
727 _currEpo.rnxSat[iSat].obs[type].lli = lli;
728 _currEpo.rnxSat[iSat].obs[type].snr = snr;
729
730 pos += 16;
731 }
732 }
733
734 _flgPowerFail = false;
735
736 return &_currEpo;
737 }
738
739 return 0;
740}
741
742// Set Header Information
743////////////////////////////////////////////////////////////////////////////
744void t_rnxObsFile::setHeader(const t_rnxObsHeader& header, double version,
745 const QStringList& useObsTypes) {
746
747 if (version < 3.0) {
748 _header._version = t_rnxObsHeader::defaultRnxObsVersion2;
749 }
750 else {
751 _header._version = t_rnxObsHeader::defaultRnxObsVersion3;
752 }
753 _header._interval = header._interval;
754 _header._antennaNumber = header._antennaNumber;
755 _header._antennaName = header._antennaName;
756 _header._markerName = header._markerName;
757 _header._markerNumber = header._markerNumber;
758 _header._antNEU = header._antNEU;
759 _header._antXYZ = header._antXYZ;
760 _header._antBSG = header._antBSG;
761 _header._xyz = header._xyz;
762 _header._observer = header._observer;
763 _header._agency = header._agency;
764 _header._receiverNumber = header._receiverNumber;
765 _header._receiverType = header._receiverType;
766 _header._receiverVersion = header._receiverVersion;
767 _header._startTime = header._startTime;
768 for (unsigned iPrn = 1; iPrn <= t_prn::MAXPRN_GPS; iPrn++) {
769 _header._wlFactorsL1[iPrn] = header._wlFactorsL1[iPrn];
770 _header._wlFactorsL2[iPrn] = header._wlFactorsL2[iPrn];
771 }
772
773 // Set observation types
774 // ---------------------
775 _header._obsTypes.clear();
776 if (useObsTypes.size() == 0) {
777 if (int(_header._version) == int(header._version)) {
778 _header._obsTypes = header._obsTypes;
779 }
780 else {
781 for (int iSys = 0; iSys < header.numSys(); iSys++) {
782 char sys = header.system(iSys);
783 for (int iType = 0; iType < header.nTypes(sys); iType++) {
784 _header._obsTypes[sys].push_back(header.obsType(sys, iType, _header._version));
785 }
786 }
787 }
788 }
789 else {
790 for (int iType = 0; iType < useObsTypes.size(); iType++) {
791 if (useObsTypes[iType].indexOf(":") != -1) {
792 QStringList hlp = useObsTypes[iType].split(":", QString::SkipEmptyParts);
793 if (hlp.size() == 2 && hlp[0].length() == 1) {
794 char sys = hlp[0][0].toAscii();
795 QString type = hlp[1];
796 _header._obsTypes[sys].push_back(type);
797 }
798 }
799 else {
800 for (int iSys = 0; iSys < t_rnxObsHeader::defaultSystems.length(); iSys++) {
801 char sys = t_rnxObsHeader::defaultSystems[iSys].toAscii();
802 _header._obsTypes[sys].push_back(useObsTypes[iType]);
803 }
804 }
805 }
806 }
807}
808
809// Write Data Epoch
810////////////////////////////////////////////////////////////////////////////
811void t_rnxObsFile::writeEpoch(const t_rnxEpo* epo) {
812 if (version() < 3.0) {
813 return writeEpochV2(epo);
814 }
815 else {
816 return writeEpochV3(epo);
817 }
818}
819
820// Write Data Epoch (RINEX Version 2)
821////////////////////////////////////////////////////////////////////////////
822void t_rnxObsFile::writeEpochV2(const t_rnxEpo* epo) {
823
824 unsigned year, month, day, hour, min;
825 double sec;
826 epo->tt.civil_date(year, month, day);
827 epo->tt.civil_time(hour, min, sec);
828
829 QString dateStr;
830 QTextStream(&dateStr) << QString(" %1 %2 %3 %4 %5%6")
831 .arg(int(fmod(year, 100)), 2, 10, QChar('0'))
832 .arg(month, 2, 10, QChar('0'))
833 .arg(day, 2, 10, QChar('0'))
834 .arg(hour, 2, 10, QChar('0'))
835 .arg(min, 2, 10, QChar('0'))
836 .arg(sec, 11, 'f', 7);
837
838 int flag = 0;
839 *_stream << dateStr << QString("%1%2").arg(flag, 3).arg(epo->rnxSat.size(), 3);
840 for (unsigned iSat = 0; iSat < epo->rnxSat.size(); iSat++) {
841 const t_rnxSat& rnxSat = epo->rnxSat[iSat];
842 if (iSat > 0 && iSat % 12 == 0) {
843 *_stream << endl << QString().leftJustified(32);
844 }
845 *_stream << rnxSat.prn.toString().c_str();
846 }
847 *_stream << endl;
848 for (unsigned iSat = 0; iSat < epo->rnxSat.size(); iSat++) {
849
850 const t_rnxSat& rnxSat = epo->rnxSat[iSat];
851 char sys = rnxSat.prn.system();
852
853 for (int iTypeV2 = 0; iTypeV2 < nTypes(sys); iTypeV2++) {
854 if (iTypeV2 > 0 && iTypeV2 % 5 == 0) {
855 *_stream << endl;
856 }
857 QString typeV2 = obsType(sys, iTypeV2);
858 bool found = false;
859 QMapIterator<QString, t_rnxObs> itObs(rnxSat.obs);
860 while (itObs.hasNext()) {
861 itObs.next();
862 const QString& type = itObs.key();
863 const t_rnxObs& rnxObs = itObs.value();
864 if (typeV2 == type3to2(sys, type)) {
865 found = true;
866 if (rnxObs.value == 0.0) {
867 *_stream << QString().leftJustified(16);
868 }
869 else {
870 *_stream << QString("%1").arg(rnxObs.value, 14, 'f', 3);
871 if (rnxObs.lli != 0.0) {
872 *_stream << QString("%1").arg(rnxObs.lli,1);
873 }
874 else {
875 *_stream << ' ';
876 }
877 if (rnxObs.snr != 0.0) {
878 *_stream << QString("%1").arg(rnxObs.snr,1);
879 }
880 else {
881 *_stream << ' ';
882 }
883 }
884 break;
885 }
886 }
887 if (!found) {
888 *_stream << QString().leftJustified(16);
889 }
890 }
891 *_stream << endl;
892 }
893}
894
895// Write Data Epoch (RINEX Version 3)
896////////////////////////////////////////////////////////////////////////////
897void t_rnxObsFile::writeEpochV3(const t_rnxEpo* epo) {
898
899 unsigned year, month, day, hour, min;
900 double sec;
901 epo->tt.civil_date(year, month, day);
902 epo->tt.civil_time(hour, min, sec);
903
904 QString dateStr;
905 QTextStream(&dateStr) << QString("> %1 %2 %3 %4 %5%6")
906 .arg(year, 4)
907 .arg(month, 2, 10, QChar('0'))
908 .arg(day, 2, 10, QChar('0'))
909 .arg(hour, 2, 10, QChar('0'))
910 .arg(min, 2, 10, QChar('0'))
911 .arg(sec, 11, 'f', 7);
912
913 int flag = 0;
914 *_stream << dateStr << QString("%1%2\n").arg(flag, 3).arg(epo->rnxSat.size(), 3);
915
916 for (unsigned iSat = 0; iSat < epo->rnxSat.size(); iSat++) {
917 const t_rnxSat& rnxSat = epo->rnxSat[iSat];
918 char sys = rnxSat.prn.system();
919
920 *_stream << rnxSat.prn.toString().c_str();
921
922 for (int iTypeV3 = 0; iTypeV3 < nTypes(sys); iTypeV3++) {
923 QString typeV3 = obsType(sys, iTypeV3);
924 bool found = false;
925 QMapIterator<QString, t_rnxObs> itObs(rnxSat.obs);
926 while (itObs.hasNext()) {
927 itObs.next();
928 const QString& type = itObs.key();
929 const t_rnxObs& rnxObs = itObs.value();
930 if (typeV3 == type2to3(sys, type)) {
931 found = true;
932 if (rnxObs.value == 0.0) {
933 *_stream << QString().leftJustified(16);
934 }
935 else {
936 *_stream << QString("%1").arg(rnxObs.value, 14, 'f', 3);
937 if (rnxObs.lli != 0.0) {
938 *_stream << QString("%1").arg(rnxObs.lli,1);
939 }
940 else {
941 *_stream << ' ';
942 }
943 if (rnxObs.snr != 0.0) {
944 *_stream << QString("%1").arg(rnxObs.snr,1);
945 }
946 else {
947 *_stream << ' ';
948 }
949 }
950 }
951 }
952 if (!found) {
953 *_stream << QString().leftJustified(16);
954 }
955 }
956 *_stream << endl;
957 }
958}
959
960// Translate Observation Type v2 --> v3
961////////////////////////////////////////////////////////////////////////////
962QString t_rnxObsFile::type2to3(char sys, const QString& typeV2) {
963 if (typeV2 == "P1") {
964 return (sys == 'G') ? "C1W" : "C1P";
965 }
966 else if (typeV2 == "P2") {
967 return (sys == 'G') ? "C2W" : "C2P";
968 }
969 return typeV2;
970}
971
972// Translate Observation Type v3 --> v2
973////////////////////////////////////////////////////////////////////////////
974QString t_rnxObsFile::type3to2(char /* sys */, const QString& typeV3) {
975 if (typeV3 == "C1P" || typeV3 == "C1W") {
976 return "P1";
977 }
978 else if (typeV3 == "C2P" || typeV3 == "C2W") {
979 return "P2";
980 }
981 return typeV3.left(2);
982}
983
984// Set Observations from RINEX File
985////////////////////////////////////////////////////////////////////////////
986void t_rnxObsFile::setObsFromRnx(const t_rnxObsFile* rnxObsFile, const t_rnxObsFile::t_rnxEpo* epo,
987 const t_rnxObsFile::t_rnxSat& rnxSat, t_satObs& obs) {
988
989 obs._staID = rnxObsFile->markerName().toAscii().constData();
990 obs._prn = rnxSat.prn;
991 obs._time = epo->tt;
992
993 char sys = rnxSat.prn.system();
994
995 for (int iType = 0; iType < rnxObsFile->nTypes(sys); iType++) {
996 QString type = rnxObsFile->obsType(sys, iType);
997 if (rnxSat.obs.contains(type)) {
998 const t_rnxObs& rnxObs = rnxSat.obs[type];
999 if (rnxObs.value != 0.0) {
1000 string type2ch(type.mid(1).toAscii().data());
1001
1002 t_frqObs* frqObs = 0;
1003 for (unsigned iFrq = 0; iFrq < obs._obs.size(); iFrq++) {
1004 if (obs._obs[iFrq]->_rnxType2ch == type2ch) {
1005 frqObs = obs._obs[iFrq];
1006 break;
1007 }
1008 }
1009 if (frqObs == 0) {
1010 frqObs = new t_frqObs;
1011 frqObs->_rnxType2ch = type2ch;
1012 obs._obs.push_back(frqObs);
1013 }
1014
1015 switch( type.toAscii().data()[0] ) {
1016 case 'C':
1017 frqObs->_codeValid = true;
1018 frqObs->_code = rnxObs.value;
1019 break;
1020 case 'L':
1021 frqObs->_phaseValid = true;
1022 frqObs->_phase = rnxObs.value;
1023 frqObs->_slip = (rnxObs.lli & 1);
1024 break;
1025 case 'D':
1026 frqObs->_dopplerValid = true;
1027 frqObs->_doppler = rnxObs.value;
1028 break;
1029 case 'S':
1030 frqObs->_snrValid = true;
1031 frqObs->_snr = rnxObs.value;
1032 break;
1033 }
1034 }
1035 }
1036 }
1037}
1038
Note: See TracBrowser for help on using the repository browser.