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

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