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

Last change on this file since 6817 was 6817, checked in by stuerze, 9 years ago

renaming of BDS's first frequency band from '1' in '2'

File size: 41.7 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#include "bncsettings.h"
48
49using namespace std;
50
51// Constructor
52////////////////////////////////////////////////////////////////////////////
53t_rnxObsHeader::t_rnxObsHeader() {
54 _usedSystems = "GREJCS";
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
78 while ( stream->status() == QTextStream::Ok && !stream->atEnd() ) {
79 QString line = stream->readLine(); ++ numLines;
80 if (line.isEmpty()) {
81 continue;
82 }
83 if (line.indexOf("END OF FILE") != -1) {
84 break;
85 }
86 QString value = line.mid(0,60).trimmed();
87 QString key = line.mid(60).trimmed();
88 if (key == "END OF HEADER") {
89 break;
90 }
91 else if (key == "RINEX VERSION / TYPE") {
92 QTextStream in(value.toAscii(), QIODevice::ReadOnly);
93 in >> _version;
94 }
95 else if (key == "MARKER NAME") {
96 _markerName = value;
97 }
98 else if (key == "MARKER NUMBER") {
99 _markerNumber = line.mid(0,20).trimmed();
100 }
101 else if (key == "ANT # / TYPE") {
102 _antennaNumber = line.mid( 0,20).trimmed();
103 _antennaName = line.mid(20,20).trimmed();
104 }
105 else if (key == "OBSERVER / AGENCY") {
106 _observer = line.mid( 0,20).trimmed();
107 _agency = line.mid(20,40).trimmed();
108 }
109 else if (key == "REC # / TYPE / VERS") {
110 _receiverNumber = line.mid( 0,20).trimmed();
111 _receiverType = line.mid(20,20).trimmed();
112 _receiverVersion = line.mid(40,20).trimmed();
113 }
114 else if (key == "INTERVAL") {
115 QTextStream in(value.toAscii(), QIODevice::ReadOnly);
116 in >> _interval;
117 }
118 else if (key == "COMMENT") {
119 _comments << line.mid(0,60).trimmed();
120 }
121 else if (key == "WAVELENGTH FACT L1/2") {
122 QTextStream in(value.toAscii(), QIODevice::ReadOnly);
123 int wlFactL1 = 0;
124 int wlFactL2 = 0;
125 int numSat = 0;
126 in >> wlFactL1 >> wlFactL2 >> numSat;
127 if (numSat == 0) {
128 for (unsigned iPrn = 1; iPrn <= t_prn::MAXPRN_GPS; iPrn++) {
129 _wlFactorsL1[iPrn] = wlFactL1;
130 _wlFactorsL2[iPrn] = wlFactL2;
131 }
132 }
133 else {
134 for (int ii = 0; ii < numSat; ii++) {
135 QString prn; in >> prn;
136 if (prn[0] == 'G') {
137 int iPrn;
138 readInt(prn, 1, 2, iPrn);
139 _wlFactorsL1[iPrn] = wlFactL1;
140 _wlFactorsL2[iPrn] = wlFactL2;
141 }
142 }
143 }
144 }
145 else if (key == "APPROX POSITION XYZ") {
146 QTextStream in(value.toAscii(), QIODevice::ReadOnly);
147 in >> _xyz[0] >> _xyz[1] >> _xyz[2];
148 }
149 else if (key == "ANTENNA: DELTA H/E/N") {
150 QTextStream in(value.toAscii(), QIODevice::ReadOnly);
151 in >> _antNEU[2] >> _antNEU[1] >> _antNEU[0];
152 }
153 else if (key == "ANTENNA: DELTA X/Y/Z") {
154 QTextStream in(value.toAscii(), QIODevice::ReadOnly);
155 in >> _antXYZ[0] >> _antXYZ[1] >> _antXYZ[2];
156 }
157 else if (key == "ANTENNA: B.SIGHT XYZ") {
158 QTextStream in(value.toAscii(), QIODevice::ReadOnly);
159 in >> _antBSG[0] >> _antBSG[1] >> _antBSG[2];
160 }
161 else if (key == "# / TYPES OF OBSERV") {
162 if (_version == 0.0) {
163 _version = t_rnxObsHeader::defaultRnxObsVersion2;
164 }
165 QTextStream* in = new QTextStream(value.toAscii(), QIODevice::ReadOnly);
166 int nTypes;
167 *in >> nTypes;
168 char sys0 = _usedSystems[0].toAscii();
169 _obsTypes[sys0].clear();
170 for (int ii = 0; ii < nTypes; ii++) {
171 if (ii > 0 && ii % 9 == 0) {
172 line = stream->readLine(); ++numLines;
173 delete in;
174 in = new QTextStream(line.left(60).toAscii(), QIODevice::ReadOnly);
175 }
176 QString hlp;
177 *in >> hlp;
178 _obsTypes[sys0].append(hlp);
179 }
180 for (int ii = 1; ii < _usedSystems.length(); ii++) {
181 char sysI = _usedSystems[ii].toAscii();
182 _obsTypes[sysI] = _obsTypes[sys0];
183 }
184 }
185 else if (key == "SYS / # / OBS TYPES") {
186 if (_version == 0.0) {
187 _version = t_rnxObsHeader::defaultRnxObsVersion3;
188 }
189 QTextStream* in = new QTextStream(value.toAscii(), QIODevice::ReadOnly);
190 char sys;
191 int nTypes;
192 *in >> sys >> nTypes;
193 _obsTypes[sys].clear();
194 for (int ii = 0; ii < nTypes; ii++) {
195 if (ii > 0 && ii % 13 == 0) {
196 line = stream->readLine(); ++numLines;
197 delete in;
198 in = new QTextStream(line.toAscii(), QIODevice::ReadOnly);
199 }
200 QString hlp;
201 *in >> hlp;
202 if (sys == 'C' && _version < 3.03) {
203 hlp.replace('1', '2');
204 }
205 _obsTypes[sys].push_back(hlp);
206 }
207 delete in;
208 }
209 else if (key == "TIME OF FIRST OBS") {
210 QTextStream in(value.toAscii(), QIODevice::ReadOnly);
211 int year, month, day, hour, min;
212 double sec;
213 in >> year >> month >> day >> hour >> min >> sec;
214 _startTime.set(year, month, day, hour, min, sec);
215 }
216 else if (key == "SYS / PHASE SHIFT"){
217 QTextStream* in = new QTextStream(value.toAscii(), QIODevice::ReadOnly);
218 char sys;
219 QString obstype;
220 double shift;
221 int satnum = 0;
222 QStringList satList;
223 QString sat;
224 *in >> sys >> obstype >> shift >> satnum;
225 if (obstype.size()) {
226 for (int ii = 0; ii < satnum; ii++) {
227 if (ii > 0 && ii % 10 == 0) {
228 line = stream->readLine(); ++numLines;
229 delete in;
230 in = new QTextStream(line.left(60).toAscii(), QIODevice::ReadOnly);
231 }
232 *in >> sat;
233 satList.append(sat);
234 }
235 _phaseShifts.insert(sys+obstype, QPair<double, QStringList>(shift, satList));
236 delete in;
237 }
238 }
239 else if (key == "GLONASS COD/PHS/BIS"){
240 QTextStream in(value.toAscii(), QIODevice::ReadOnly);
241 for (int ii = 0; ii < 4; ii++) {
242 QString type;
243 double value;
244 in >> type >> value;
245 if (type.size())
246 _gloPhaseBiases[type] = value;
247 }
248 }
249 else if (key == "GLONASS SLOT / FRQ #") {
250 QTextStream* in = new QTextStream(value.toAscii(), QIODevice::ReadOnly);
251 int nSlots = 0;
252 *in >> nSlots;
253 for (int ii = 0; ii < nSlots; ii++) {
254 if (ii > 0 && ii % 8 == 0) {
255 line = stream->readLine(); ++numLines;
256 delete in;
257 in = new QTextStream(line.left(60).toAscii(), QIODevice::ReadOnly);
258 }
259 QString sat;
260 int slot;
261 *in >> sat >> slot;
262 t_prn prn;
263 prn.set(sat.toStdString());
264 if(sat.size())
265 _gloSlots[prn] = slot;
266 }
267 delete in;
268 }
269 if (maxLines > 0 && numLines == maxLines) {
270 break;
271 }
272 }
273
274 // set default observation types if empty in input file
275 // ----------------------------------------------------
276 if (_obsTypes.empty()) {
277 setDefault(_markerName, _version);
278 }
279
280 // Systems used
281 // ------------
282 _usedSystems.clear();
283 QMapIterator<char, QStringList> it(_obsTypes);
284 while (it.hasNext()) {
285 it.next();
286 _usedSystems += QChar(it.key());
287 }
288
289 return success;
290}
291
292// Set Default Header
293////////////////////////////////////////////////////////////////////////////
294void t_rnxObsHeader::setDefault(const QString& markerName, int version) {
295
296 _markerName = markerName;
297
298 if (version <= 2) {
299 _version = t_rnxObsHeader::defaultRnxObsVersion2;
300 }
301 else {
302 _version = t_rnxObsHeader::defaultRnxObsVersion3;
303 }
304
305 _comments << "Default set of observation types used";
306
307 _obsTypes.clear();
308 if (_version < 3.0) {
309 _obsTypes['G'] << "C1" << "P1" << "L1" << "S1"
310 << "C2" << "P2" << "L2" << "S2";
311 _obsTypes['R'] = _obsTypes['G'];
312 _obsTypes['E'] = _obsTypes['G'];
313 _obsTypes['J'] = _obsTypes['G'];
314 _obsTypes['S'] = _obsTypes['G'];
315 _obsTypes['C'] = _obsTypes['G'];
316 }
317 else {
318 _obsTypes['G'] << "C1C" << "L1C" << "S1C"
319 << "C1W" << "L1W" << "S1W"
320 << "C2X" << "L2X" << "S2X"
321 << "C2W" << "L2W" << "S2W"
322 << "C5X" << "L5X" << "S5X";
323
324 _obsTypes['J'] = _obsTypes['G'];
325
326 _obsTypes['R'] << "C1C" << "L1C" << "S1C"
327 << "C2P" << "L2P" << "S2P";
328
329 _obsTypes['E'] << "C1X" << "L1X" << "SX1"
330 << "C5X" << "L5X" << "SX5"
331 << "C7X" << "L7X" << "SX7"
332 << "C8X" << "L8X" << "SX8";
333
334 _obsTypes['S'] << "C1C" << "L1C" << "S1C"
335 << "C5I" << "L5I" << "S5I"
336 << "C5Q" << "L5Q" << "S5Q";
337
338 _obsTypes['C'] << "C2I" << "L2I" << "S2I"
339 << "C6I" << "L6I" << "S6I"
340 << "C7I" << "L7I" << "S7I";
341 }
342}
343
344// Copy header
345////////////////////////////////////////////////////////////////////////////
346void t_rnxObsHeader::set(const t_rnxObsHeader& header, int version,
347 const QStringList* useObsTypes) {
348
349 if (version <= 2) {
350 _version = t_rnxObsHeader::defaultRnxObsVersion2;
351 }
352 else {
353 _version = t_rnxObsHeader::defaultRnxObsVersion3;
354 }
355 _interval = header._interval;
356 _antennaNumber = header._antennaNumber;
357 _antennaName = header._antennaName;
358 _markerName = header._markerName;
359 _markerNumber = header._markerNumber;
360 _antNEU = header._antNEU;
361 _antXYZ = header._antXYZ;
362 _antBSG = header._antBSG;
363 _xyz = header._xyz;
364 _observer = header._observer;
365 _agency = header._agency;
366 _receiverNumber = header._receiverNumber;
367 _receiverType = header._receiverType;
368 _receiverVersion = header._receiverVersion;
369 _startTime = header._startTime;
370 _comments = header._comments;
371 _usedSystems = header._usedSystems;
372 if (_version >= 3.0) {
373 _phaseShifts = header._phaseShifts;
374 _gloPhaseBiases = header._gloPhaseBiases;
375 _gloSlots = header._gloSlots;
376 }
377 for (unsigned iPrn = 1; iPrn <= t_prn::MAXPRN_GPS; iPrn++) {
378 _wlFactorsL1[iPrn] = header._wlFactorsL1[iPrn];
379 _wlFactorsL2[iPrn] = header._wlFactorsL2[iPrn];
380 }
381
382 // Set observation types
383 // ---------------------
384 _obsTypes.clear();
385 if (!useObsTypes || useObsTypes->size() == 0) {
386 if (int(_version) == int(header._version)) {
387 _obsTypes = header._obsTypes;
388 }
389 else {
390 if (_version >= 3.0) {
391 for (int iSys = 0; iSys < header.numSys(); iSys++) {
392 char sys = header.system(iSys);
393 for (int iType = 0; iType < header.nTypes(sys); iType++) {
394 QString type = header.obsType(sys, iType, _version);
395 if (!_obsTypes[sys].contains(type)) {
396 _obsTypes[sys].push_back(type);
397 }
398 }
399 }
400 }
401 else {
402 for (int iSys = 0; iSys < header.numSys(); iSys++) {
403 char sys = header.system(iSys);
404 for (int iType = 0; iType < header.nTypes(sys); iType++) {
405 QString type = header.obsType(sys, iType, _version);
406 for (int jSys = 0; jSys < _usedSystems.length(); jSys++) {
407 char thisSys = _usedSystems[jSys].toAscii();
408 if (!_obsTypes[thisSys].contains(type)) {
409 _obsTypes[thisSys].push_back(type);
410 }
411 }
412 }
413 }
414 }
415 }
416 }
417 else {
418 for (int iType = 0; iType < useObsTypes->size(); iType++) {
419 if (useObsTypes->at(iType).indexOf(":") != -1) {
420 QStringList hlp = useObsTypes->at(iType).split(":", QString::SkipEmptyParts);
421 if (hlp.size() == 2 && hlp[0].length() == 1) {
422 if (_version >= 3.0) {
423 char sys = hlp[0][0].toAscii();
424 QString type = t_rnxObsFile::type2to3(sys, hlp[1]);
425 if (!_obsTypes[sys].contains(type)) {
426 _obsTypes[sys].push_back(type);
427 }
428 }
429 else {
430 for (int iSys = 0; iSys < _usedSystems.length(); iSys++) {
431 char sys = _usedSystems[iSys].toAscii();
432 QString type = t_rnxObsFile::type3to2(sys, hlp[1]);
433 if (!_obsTypes[sys].contains(type)) {
434 _obsTypes[sys].push_back(type);
435 }
436 }
437 }
438 }
439 }
440 else {
441 for (int iSys = 0; iSys < _usedSystems.length(); iSys++) {
442 char sys = _usedSystems[iSys].toAscii();
443 QString type = _version >= 3.0 ? t_rnxObsFile::type2to3(sys, useObsTypes->at(iType)) :
444 t_rnxObsFile::type3to2(sys, useObsTypes->at(iType));
445 if (!_obsTypes[sys].contains(type)) {
446 _obsTypes[sys].push_back(type);
447 }
448 }
449 }
450 }
451 _usedSystems.clear();
452 QMapIterator<char, QStringList> it(_obsTypes);
453 while (it.hasNext()) {
454 it.next();
455 _usedSystems += QChar(it.key());
456 }
457 }
458}
459
460// Write Header
461////////////////////////////////////////////////////////////////////////////
462void t_rnxObsHeader::write(QTextStream* stream,
463 const QMap<QString, QString>* txtMap) const {
464
465 QStringList newComments;
466 QString runBy = BNC_CORE->userName();
467
468 if (txtMap) {
469 QMapIterator<QString, QString> it(*txtMap);
470 while (it.hasNext()) {
471 it.next();
472 if (it.key() == "RUN BY") {
473 runBy = it.value();
474 }
475 else if (it.key() == "COMMENT") {
476 newComments = it.value().split("\\n", QString::SkipEmptyParts);
477 }
478 }
479 }
480
481 *stream << QString("%1 Observation data Mixed")
482 .arg(_version, 9, 'f', 2)
483 .leftJustified(60)
484 << "RINEX VERSION / TYPE\n";
485
486 const QString fmtDate = (_version < 3.0) ? "dd-MMM-yy hh:mm"
487 : "yyyyMMdd hhmmss UTC";
488 *stream << QString("%1%2%3")
489 .arg(BNC_CORE->pgmName(), -20)
490 .arg(runBy.trimmed().left(20), -20)
491 .arg(QDateTime::currentDateTime().toUTC().toString(fmtDate), -20)
492 .leftJustified(60)
493 << "PGM / RUN BY / DATE\n";
494
495 QStringListIterator itCmnt(_comments + newComments);
496 while (itCmnt.hasNext()) {
497 *stream << itCmnt.next().trimmed().left(60).leftJustified(60) << "COMMENT\n";
498 }
499
500 *stream << QString("%1")
501 .arg(_markerName, -60)
502 .leftJustified(60)
503 << "MARKER NAME\n";
504
505 if (!_markerNumber.isEmpty()) {
506 *stream << QString("%1")
507 .arg(_markerNumber, -20)
508 .leftJustified(60)
509 << "MARKER NUMBER\n";
510 }
511
512 *stream << QString("%1%2")
513 .arg(_observer, -20)
514 .arg(_agency, -40)
515 .leftJustified(60)
516 << "OBSERVER / AGENCY\n";
517
518 *stream << QString("%1%2%3")
519 .arg(_receiverNumber, -20)
520 .arg(_receiverType, -20)
521 .arg(_receiverVersion, -20)
522 .leftJustified(60)
523 << "REC # / TYPE / VERS\n";
524
525 *stream << QString("%1%2")
526 .arg(_antennaNumber, -20)
527 .arg(_antennaName, -20)
528 .leftJustified(60)
529 << "ANT # / TYPE\n";
530
531 *stream << QString("%1%2%3")
532 .arg(_xyz(1), 14, 'f', 4)
533 .arg(_xyz(2), 14, 'f', 4)
534 .arg(_xyz(3), 14, 'f', 4)
535 .leftJustified(60)
536 << "APPROX POSITION XYZ\n";
537
538 *stream << QString("%1%2%3")
539 .arg(_antNEU(3), 14, 'f', 4)
540 .arg(_antNEU(2), 14, 'f', 4)
541 .arg(_antNEU(1), 14, 'f', 4)
542 .leftJustified(60)
543 << "ANTENNA: DELTA H/E/N\n";
544
545 if (_version < 3.0) {
546 int defaultWlFact1 = _wlFactorsL1[1];
547 int defaultWlFact2 = _wlFactorsL2[1]; // TODO check all prns
548 *stream << QString("%1%2")
549 .arg(defaultWlFact1, 6)
550 .arg(defaultWlFact2, 6)
551 .leftJustified(60)
552 << "WAVELENGTH FACT L1/2\n";
553 }
554
555 *stream << obsTypesStrings().join("");
556
557 if (_interval > 0) {
558 *stream << QString("%1")
559 .arg(_interval, 10, 'f', 3)
560 .leftJustified(60)
561 << "INTERVAL\n";
562 }
563
564 unsigned year, month, day, hour, min;
565 double sec;
566 _startTime.civil_date(year, month, day);
567 _startTime.civil_time(hour, min, sec);
568 *stream << QString("%1%2%3%4%5%6%7")
569 .arg(year, 6)
570 .arg(month, 6)
571 .arg(day, 6)
572 .arg(hour, 6)
573 .arg(min, 6)
574 .arg(sec, 13, 'f', 7)
575 .arg("GPS", 8)
576 .leftJustified(60)
577 << "TIME OF FIRST OBS\n";
578
579 if (_version >= 3.0) {
580 if (_phaseShifts.empty()) {
581 QMap<char, QStringList>::const_iterator it;
582 for (it = _obsTypes.begin(); it != _obsTypes.end(); ++it) {
583 char sys = it.key();
584 double shift = 0.0;
585 foreach (const QString &obstype, it.value()) {
586 if (obstype.left(1).contains('L')) {
587 *stream << QString("%1 %2 %3")
588 .arg(sys, 0)
589 .arg(obstype, 0)
590 .arg(shift, 9, 'f', 5)
591 .leftJustified(60)
592 << "SYS / PHASE SHIFT\n";
593 }
594 }
595 }
596 } else {
597 QMap<QString, QPair<double, QStringList> >::const_iterator it;
598 QString emptyFillStr;
599 for(it = _phaseShifts.begin(); it!= _phaseShifts.end(); ++it) {
600 QString sys = it.key().left(1);
601 QString obstype = it.key().mid(1);
602 double shift = it.value().first;
603 QStringList satList = it.value().second;
604 QString hlp = QString("%1 %2 %3 ")
605 .arg(sys.toStdString().c_str(), 0)
606 .arg(obstype, 4)
607 .arg(shift, 9, 'f', 5);
608 if (!satList.empty()) {
609 hlp += QString("%1 ").arg(satList.size(), 2);
610 }
611 else {
612 *stream << QString("%1")
613 .arg(hlp, 0)
614 .leftJustified(60)
615 << "SYS / PHASE SHIFT\n";
616 hlp = "";
617 }
618 int ii = 0;
619 QStringList::const_iterator it_s;
620 for (it_s = satList.begin(); it_s != satList.end(); ++it_s) {
621 (hlp.contains(obstype)) ?
622 emptyFillStr = "":
623 emptyFillStr = " ";
624 hlp += QString("%1 ").arg(*it_s);
625 ii++;
626 if (ii % 10 == 0) {
627 *stream << QString("%1%2")
628 .arg(emptyFillStr, 0)
629 .arg(hlp, 0)
630 .leftJustified(60)
631 << "SYS / PHASE SHIFT\n";
632 hlp = "";
633 }
634 }
635 if (hlp.size()) {
636 *stream << QString("%1%2")
637 .arg(emptyFillStr, 0)
638 .arg(hlp, 0)
639 .leftJustified(60)
640 << "SYS / PHASE SHIFT\n";
641 }
642 }
643 }
644 }
645
646 if (_version >= 3.0) {
647 QString hlp = "";
648 QMap<QString, double>::const_iterator it = _gloPhaseBiases.begin();
649 while (it != _gloPhaseBiases.end()){
650 hlp += QString("%1%2").arg(it.key(), 4).arg(it.value(), 9, 'f', 3);
651 it++;
652 }
653 *stream << QString("%1")
654 .arg(hlp, 0)
655 .leftJustified(60)
656 << "GLONASS COD/PHS/BIS\n";
657 }
658
659 if (_version >= 3.0) {
660 QString number = QString::number(_gloSlots.size());
661 QString hlp = "";
662 int ii = 0;
663 QMap<t_prn, int>::const_iterator it = _gloSlots.begin();
664 while (it != _gloSlots.end()) {
665 QString prn(it.key().toString().c_str());
666 hlp += QString("%1%2").arg(prn, 4).arg(it.value(), 3);
667 it++;
668 ii++;
669 if (ii % 8 == 0) {
670 *stream << QString("%1%2")
671 .arg(number, 3)
672 .arg(hlp, 0)
673 .leftJustified(60)
674 << "GLONASS SLOT / FRQ #\n";
675 ii = 0;
676 hlp = number = "";
677 }
678 }
679 if (hlp.size() || !_gloSlots.size()) {
680 *stream << QString("%1%2")
681 .arg(number, 3)
682 .arg(hlp, 0)
683 .leftJustified(60)
684 << "GLONASS SLOT / FRQ #\n";
685 }
686 }
687
688 *stream << QString()
689 .leftJustified(60)
690 << "END OF HEADER\n";
691}
692
693// Number of Different Systems
694////////////////////////////////////////////////////////////////////////////
695int t_rnxObsHeader::numSys() const {
696 return _obsTypes.size();
697}
698
699//
700////////////////////////////////////////////////////////////////////////////
701char t_rnxObsHeader::system(int iSys) const {
702 int iSysLocal = -1;
703 QMapIterator<char, QStringList> it(_obsTypes);
704 while (it.hasNext()) {
705 ++iSysLocal;
706 it.next();
707 if (iSysLocal == iSys) {
708 return it.key();
709 }
710 }
711 return ' ';
712}
713
714// Number of Observation Types (satellite-system specific)
715////////////////////////////////////////////////////////////////////////////
716int t_rnxObsHeader::nTypes(char sys) const {
717 if (_obsTypes.contains(sys)) {
718 return _obsTypes[sys].size();
719 }
720 else {
721 return 0;
722 }
723}
724
725// Observation Type (satellite-system specific)
726////////////////////////////////////////////////////////////////////////////
727QString t_rnxObsHeader::obsType(char sys, int index, double version) const {
728
729 if (version == 0.0) {
730 version = _version;
731 }
732 if (_obsTypes.contains(sys)) {
733 QString origType = _obsTypes[sys].at(index);
734 if (int(version) == int(_version)) {
735 return origType;
736 }
737 else if (int(version) == 2) {
738 return t_rnxObsFile::type3to2(sys, origType);
739 }
740 else if (int(version) == 3) {
741 return t_rnxObsFile::type2to3(sys, origType);
742 }
743 }
744 return "";
745}
746
747// Write Observation Types
748////////////////////////////////////////////////////////////////////////////
749QStringList t_rnxObsHeader::obsTypesStrings() const {
750
751 QStringList strList;
752 if (_version < 3.0) {
753 char sys0 = _usedSystems[0].toAscii();
754 QString hlp;
755 QTextStream(&hlp) << QString("%1").arg(_obsTypes[sys0].size(), 6);
756 for (int ii = 0; ii < _obsTypes[sys0].size(); ii++) {
757 QTextStream(&hlp) << QString("%1").arg(_obsTypes[sys0][ii], 6);
758 if ((ii+1) % 9 == 0 || ii == _obsTypes[sys0].size()-1) {
759 strList.append(hlp.leftJustified(60) + "# / TYPES OF OBSERV\n");
760 hlp = QString().leftJustified(6);
761 }
762 }
763 }
764 else {
765 for (int iSys = 0; iSys < numSys(); iSys++) {
766 char sys = system(iSys);
767 QString hlp;
768 QTextStream(&hlp) << QString("%1 %2").arg(sys).arg(nTypes(sys), 3);
769 for (int iType = 0; iType < nTypes(sys); iType++) {
770 QString type = obsType(sys, iType);
771 QTextStream(&hlp) << QString(" %1").arg(type, -3);
772 if ((iType+1) % 13 == 0 || iType == nTypes(sys)-1) {
773 strList.append(hlp.leftJustified(60) + "SYS / # / OBS TYPES\n");
774 hlp = QString().leftJustified(6);
775 }
776 }
777 }
778 }
779
780 return strList;
781}
782
783// Constructor
784////////////////////////////////////////////////////////////////////////////
785t_rnxObsFile::t_rnxObsFile(const QString& fileName, e_inpOut inpOut) {
786 _inpOut = inpOut;
787 _stream = 0;
788 _flgPowerFail = false;
789 if (_inpOut == input) {
790 openRead(fileName);
791 }
792 else {
793 openWrite(fileName);
794 }
795}
796
797// Open for input
798////////////////////////////////////////////////////////////////////////////
799void t_rnxObsFile::openRead(const QString& fileName) {
800
801 _fileName = fileName; expandEnvVar(_fileName);
802 _file = new QFile(_fileName);
803 _file->open(QIODevice::ReadOnly | QIODevice::Text);
804 _stream = new QTextStream();
805 _stream->setDevice(_file);
806
807 _header.read(_stream);
808
809 // Guess Observation Interval
810 // --------------------------
811 if (_header._interval == 0.0) {
812 bncTime ttPrev;
813 for (int iEpo = 0; iEpo < 10; iEpo++) {
814 const t_rnxEpo* rnxEpo = nextEpoch();
815 if (!rnxEpo) {
816 throw QString("t_rnxObsFile: not enough epochs");
817 }
818 if (iEpo > 0) {
819 double dt = rnxEpo->tt - ttPrev;
820 if (_header._interval == 0.0 || dt < _header._interval) {
821 _header._interval = dt;
822 }
823 }
824 ttPrev = rnxEpo->tt;
825 }
826 _stream->seek(0);
827 _header.read(_stream);
828 }
829
830 // Time of first observation
831 // -------------------------
832 if (!_header._startTime.valid()) {
833 const t_rnxEpo* rnxEpo = nextEpoch();
834 if (!rnxEpo) {
835 throw QString("t_rnxObsFile: not enough epochs");
836 }
837 _header._startTime = rnxEpo->tt;
838 _stream->seek(0);
839 _header.read(_stream);
840 }
841}
842
843// Open for output
844////////////////////////////////////////////////////////////////////////////
845void t_rnxObsFile::openWrite(const QString& fileName) {
846
847 _fileName = fileName; expandEnvVar(_fileName);
848 _file = new QFile(_fileName);
849 _file->open(QIODevice::WriteOnly | QIODevice::Text);
850 _stream = new QTextStream();
851 _stream->setDevice(_file);
852}
853
854// Destructor
855////////////////////////////////////////////////////////////////////////////
856t_rnxObsFile::~t_rnxObsFile() {
857 close();
858}
859
860// Close
861////////////////////////////////////////////////////////////////////////////
862void t_rnxObsFile::close() {
863 delete _stream; _stream = 0;
864 delete _file; _file = 0;
865}
866
867// Handle Special Epoch Flag
868////////////////////////////////////////////////////////////////////////////
869void t_rnxObsFile::handleEpochFlag(int flag, const QString& line,
870 bool& headerReRead) {
871
872 headerReRead = false;
873
874 // Power Failure
875 // -------------
876 if (flag == 1) {
877 _flgPowerFail = true;
878 }
879
880 // Start moving antenna
881 // --------------------
882 else if (flag == 2) {
883 // no action
884 }
885
886 // Re-Read Header
887 // --------------
888 else if (flag == 3 || flag == 4 || flag == 5) {
889 int numLines = 0;
890 if (version() < 3.0) {
891 readInt(line, 29, 3, numLines);
892 }
893 else {
894 readInt(line, 32, 3, numLines);
895 }
896 if (flag == 3 || flag == 4) {
897 _header.read(_stream, numLines);
898 headerReRead = true;
899 }
900 else {
901 for (int ii = 0; ii < numLines; ii++) {
902 _stream->readLine();
903 }
904 }
905 }
906
907 // Unhandled Flag
908 // --------------
909 else {
910 throw QString("t_rnxObsFile: unhandled flag\n" + line);
911 }
912}
913
914// Retrieve single Epoch
915////////////////////////////////////////////////////////////////////////////
916t_rnxObsFile::t_rnxEpo* t_rnxObsFile::nextEpoch() {
917 _currEpo.clear();
918 if (version() < 3.0) {
919 return nextEpochV2();
920 }
921 else {
922 return nextEpochV3();
923 }
924}
925
926// Retrieve single Epoch (RINEX Version 3)
927////////////////////////////////////////////////////////////////////////////
928t_rnxObsFile::t_rnxEpo* t_rnxObsFile::nextEpochV3() {
929
930 while ( _stream->status() == QTextStream::Ok && !_stream->atEnd() ) {
931
932 QString line = _stream->readLine();
933
934 if (line.isEmpty()) {
935 continue;
936 }
937
938 int flag = 0;
939 readInt(line, 31, 1, flag);
940 if (flag > 0) {
941 bool headerReRead = false;
942 handleEpochFlag(flag, line, headerReRead);
943 if (headerReRead) {
944 continue;
945 }
946 }
947
948 QTextStream in(line.mid(1).toAscii(), QIODevice::ReadOnly);
949
950 // Epoch Time
951 // ----------
952 int year, month, day, hour, min;
953 double sec;
954 in >> year >> month >> day >> hour >> min >> sec;
955 _currEpo.tt.set(year, month, day, hour, min, sec);
956
957 // Number of Satellites
958 // --------------------
959 int numSat;
960 readInt(line, 32, 3, numSat);
961
962 _currEpo.rnxSat.resize(numSat);
963
964 // Observations
965 // ------------
966 for (int iSat = 0; iSat < numSat; iSat++) {
967 line = _stream->readLine();
968 t_prn prn; prn.set(line.left(3).toAscii().data());
969 _currEpo.rnxSat[iSat].prn = prn;
970 char sys = prn.system();
971 for (int iType = 0; iType < _header.nTypes(sys); iType++) {
972 int pos = 3 + 16*iType;
973 double obsValue = 0.0;
974 int lli = 0;
975 int snr = 0;
976 readDbl(line, pos, 14, obsValue);
977 readInt(line, pos + 14, 1, lli);
978 readInt(line, pos + 15, 1, snr);
979 if (_flgPowerFail) {
980 lli |= 1;
981 }
982 QString type = obsType(sys, iType);
983 _currEpo.rnxSat[iSat].obs[type].value = obsValue;
984 _currEpo.rnxSat[iSat].obs[type].lli = lli;
985 _currEpo.rnxSat[iSat].obs[type].snr = snr;
986 }
987 }
988
989 _flgPowerFail = false;
990
991 return &_currEpo;
992 }
993
994 return 0;
995}
996
997// Retrieve single Epoch (RINEX Version 2)
998////////////////////////////////////////////////////////////////////////////
999t_rnxObsFile::t_rnxEpo* t_rnxObsFile::nextEpochV2() {
1000
1001 while ( _stream->status() == QTextStream::Ok && !_stream->atEnd() ) {
1002
1003 QString line = _stream->readLine();
1004
1005 if (line.isEmpty()) {
1006 continue;
1007 }
1008
1009 int flag = 0;
1010 readInt(line, 28, 1, flag);
1011 if (flag > 0) {
1012 bool headerReRead = false;
1013 handleEpochFlag(flag, line, headerReRead);
1014 if (headerReRead) {
1015 continue;
1016 }
1017 }
1018
1019 QTextStream in(line.toAscii(), QIODevice::ReadOnly);
1020
1021 // Epoch Time
1022 // ----------
1023 int year, month, day, hour, min;
1024 double sec;
1025 in >> year >> month >> day >> hour >> min >> sec;
1026 if (year < 80) {
1027 year += 2000;
1028 }
1029 else if (year < 100) {
1030 year += 1900;
1031 }
1032 _currEpo.tt.set(year, month, day, hour, min, sec);
1033
1034 // Number of Satellites
1035 // --------------------
1036 int numSat;
1037 readInt(line, 29, 3, numSat);
1038
1039 _currEpo.rnxSat.resize(numSat);
1040
1041 // Read Satellite Numbers
1042 // ----------------------
1043 int pos = 32;
1044 for (int iSat = 0; iSat < numSat; iSat++) {
1045 if (iSat > 0 && iSat % 12 == 0) {
1046 line = _stream->readLine();
1047 pos = 32;
1048 }
1049
1050 char sys = line.toAscii()[pos];
1051 if (sys == ' ') {
1052 sys = 'G';
1053 }
1054 int satNum; readInt(line, pos + 1, 2, satNum);
1055 _currEpo.rnxSat[iSat].prn.set(sys, satNum);
1056
1057 pos += 3;
1058 }
1059
1060 // Read Observation Records
1061 // ------------------------
1062 for (int iSat = 0; iSat < numSat; iSat++) {
1063 char sys = _currEpo.rnxSat[iSat].prn.system();
1064 line = _stream->readLine();
1065 pos = 0;
1066 for (int iType = 0; iType < _header.nTypes(sys); iType++) {
1067 if (iType > 0 && iType % 5 == 0) {
1068 line = _stream->readLine();
1069 pos = 0;
1070 }
1071 double obsValue = 0.0;
1072 int lli = 0;
1073 int snr = 0;
1074 readDbl(line, pos, 14, obsValue);
1075 readInt(line, pos + 14, 1, lli);
1076 readInt(line, pos + 15, 1, snr);
1077
1078 if (_flgPowerFail) {
1079 lli |= 1;
1080 }
1081
1082 QString type = obsType(sys, iType);
1083 _currEpo.rnxSat[iSat].obs[type].value = obsValue;
1084 _currEpo.rnxSat[iSat].obs[type].lli = lli;
1085 _currEpo.rnxSat[iSat].obs[type].snr = snr;
1086
1087 pos += 16;
1088 }
1089 }
1090
1091 _flgPowerFail = false;
1092
1093 return &_currEpo;
1094 }
1095
1096 return 0;
1097}
1098
1099// Write Data Epoch
1100////////////////////////////////////////////////////////////////////////////
1101void t_rnxObsFile::writeEpoch(const t_rnxEpo* epo) {
1102 if (epo == 0) {
1103 return;
1104 }
1105 t_rnxEpo epoLocal;
1106 epoLocal.tt = epo->tt;
1107 for (unsigned ii = 0; ii < epo->rnxSat.size(); ii++) {
1108 const t_rnxSat& rnxSat = epo->rnxSat[ii];
1109 if (_header._obsTypes[rnxSat.prn.system()].size() > 0) {
1110 epoLocal.rnxSat.push_back(rnxSat);
1111 }
1112 }
1113
1114 if (version() < 3.0) {
1115 return writeEpochV2(_stream, _header, &epoLocal);
1116 }
1117 else {
1118 return writeEpochV3(_stream, _header, &epoLocal);
1119 }
1120}
1121
1122// Write Data Epoch (RINEX Version 2)
1123////////////////////////////////////////////////////////////////////////////
1124void t_rnxObsFile::writeEpochV2(QTextStream* stream, const t_rnxObsHeader& header,
1125 const t_rnxEpo* epo) {
1126
1127 unsigned year, month, day, hour, min;
1128 double sec;
1129 epo->tt.civil_date(year, month, day);
1130 epo->tt.civil_time(hour, min, sec);
1131
1132 QString dateStr;
1133 QTextStream(&dateStr) << QString(" %1 %2 %3 %4 %5%6")
1134 .arg(int(fmod(year, 100)), 2, 10, QChar('0'))
1135 .arg(month, 2, 10, QChar('0'))
1136 .arg(day, 2, 10, QChar('0'))
1137 .arg(hour, 2, 10, QChar('0'))
1138 .arg(min, 2, 10, QChar('0'))
1139 .arg(sec, 11, 'f', 7);
1140
1141 int flag = 0;
1142 *stream << dateStr << QString("%1%2").arg(flag, 3).arg(epo->rnxSat.size(), 3);
1143 for (unsigned iSat = 0; iSat < epo->rnxSat.size(); iSat++) {
1144 const t_rnxSat& rnxSat = epo->rnxSat[iSat];
1145 if (iSat > 0 && iSat % 12 == 0) {
1146 *stream << endl << QString().leftJustified(32);
1147 }
1148 *stream << rnxSat.prn.toString().c_str();
1149 }
1150 *stream << endl;
1151 for (unsigned iSat = 0; iSat < epo->rnxSat.size(); iSat++) {
1152
1153 const t_rnxSat& rnxSat = epo->rnxSat[iSat];
1154 char sys = rnxSat.prn.system();
1155
1156 for (int iTypeV2 = 0; iTypeV2 < header.nTypes(sys); iTypeV2++) {
1157 if (iTypeV2 > 0 && iTypeV2 % 5 == 0) {
1158 *stream << endl;
1159 }
1160 QString typeV2 = header.obsType(sys, iTypeV2);
1161 bool found = false;
1162
1163 QString preferredAttrib = signalPriorities(sys);
1164 for (int iPref = 0; iPref < preferredAttrib.length(); iPref++) {
1165 QMapIterator<QString, t_rnxObs> itObs(rnxSat.obs);
1166 while (itObs.hasNext()) {
1167 itObs.next();
1168 const QString& type = itObs.key();
1169 const t_rnxObs& rnxObs = itObs.value();
1170 if ( preferredAttrib[iPref] == '?' ||
1171 (type.length() == 2 && preferredAttrib[iPref] == '_' ) ||
1172 (type.length() == 3 && preferredAttrib[iPref] == type[2]) ) {
1173 if (typeV2 == type3to2(sys, type)) {
1174 found = true;
1175 if (rnxObs.value == 0.0) {
1176 *stream << QString().leftJustified(16);
1177 }
1178 else {
1179 *stream << QString("%1").arg(rnxObs.value, 14, 'f', 3);
1180 if (rnxObs.lli != 0.0) {
1181 *stream << QString("%1").arg(rnxObs.lli,1);
1182 }
1183 else {
1184 *stream << ' ';
1185 }
1186 if (rnxObs.snr != 0.0) {
1187 *stream << QString("%1").arg(rnxObs.snr,1);
1188 }
1189 else {
1190 *stream << ' ';
1191 }
1192 }
1193 goto end_loop_iPref;
1194 }
1195 }
1196 }
1197 } end_loop_iPref:
1198 if (!found) {
1199 *stream << QString().leftJustified(16);
1200 }
1201 }
1202 *stream << endl;
1203 }
1204}
1205
1206// Write Data Epoch (RINEX Version 3)
1207////////////////////////////////////////////////////////////////////////////
1208void t_rnxObsFile::writeEpochV3(QTextStream* stream, const t_rnxObsHeader& header,
1209 const t_rnxEpo* epo) {
1210
1211 unsigned year, month, day, hour, min;
1212 double sec;
1213 epo->tt.civil_date(year, month, day);
1214 epo->tt.civil_time(hour, min, sec);
1215
1216 QString dateStr;
1217 QTextStream(&dateStr) << QString("> %1 %2 %3 %4 %5%6")
1218 .arg(year, 4)
1219 .arg(month, 2, 10, QChar('0'))
1220 .arg(day, 2, 10, QChar('0'))
1221 .arg(hour, 2, 10, QChar('0'))
1222 .arg(min, 2, 10, QChar('0'))
1223 .arg(sec, 11, 'f', 7);
1224
1225 int flag = 0;
1226 *stream << dateStr << QString("%1%2\n").arg(flag, 3).arg(epo->rnxSat.size(), 3);
1227
1228 for (unsigned iSat = 0; iSat < epo->rnxSat.size(); iSat++) {
1229 const t_rnxSat& rnxSat = epo->rnxSat[iSat];
1230 char sys = rnxSat.prn.system();
1231
1232 const t_rnxObs* hlp[header.nTypes(sys)];
1233 for (int iTypeV3 = 0; iTypeV3 < header.nTypes(sys); iTypeV3++) {
1234 hlp[iTypeV3] = 0;
1235 QString typeV3 = header.obsType(sys, iTypeV3);
1236 QMapIterator<QString, t_rnxObs> itObs(rnxSat.obs);
1237
1238 // Exact match
1239 // -----------
1240 while (itObs.hasNext()) {
1241 itObs.next();
1242 const QString& type = itObs.key();
1243 const t_rnxObs& rnxObs = itObs.value();
1244 if (typeV3 == type2to3(sys, type) && rnxObs.value != 0.0) {
1245 hlp[iTypeV3] = &itObs.value();
1246 }
1247 }
1248
1249 // Non-Exact match
1250 // ---------------
1251 itObs.toFront();
1252 while (itObs.hasNext()) {
1253 itObs.next();
1254 const QString& type = itObs.key();
1255 const t_rnxObs& rnxObs = itObs.value();
1256 if (hlp[iTypeV3] == 0 && typeV3 == type2to3(sys, type).left(2) && rnxObs.value != 0.0) {
1257 hlp[iTypeV3] = &itObs.value();
1258 }
1259 }
1260 }
1261
1262 *stream << rnxSat.prn.toString().c_str();
1263
1264 for (int iTypeV3 = 0; iTypeV3 < header.nTypes(sys); iTypeV3++) {
1265 const t_rnxObs* rnxObs = hlp[iTypeV3];
1266 if (rnxObs == 0) {
1267 *stream << QString().leftJustified(16);
1268 }
1269 else {
1270 *stream << QString("%1").arg(rnxObs->value, 14, 'f', 3);
1271 if (rnxObs->lli != 0.0) {
1272 *stream << QString("%1").arg(rnxObs->lli,1);
1273 }
1274 else {
1275 *stream << ' ';
1276 }
1277 if (rnxObs->snr != 0.0) {
1278 *stream << QString("%1").arg(rnxObs->snr,1);
1279 }
1280 else {
1281 *stream << ' ';
1282 }
1283 }
1284 }
1285 *stream << endl;
1286 }
1287}
1288
1289// Translate Observation Type v2 --> v3
1290////////////////////////////////////////////////////////////////////////////
1291QString t_rnxObsFile::type2to3(char sys, const QString& typeV2) {
1292 if (typeV2 == "P1") {
1293 return (sys == 'G') ? "C1W" : "C1P";
1294 }
1295 else if (typeV2 == "P2") {
1296 return (sys == 'G') ? "C2W" : "C2P";
1297 }
1298 return typeV2;
1299}
1300
1301// Translate Observation Type v3 --> v2
1302////////////////////////////////////////////////////////////////////////////
1303QString t_rnxObsFile::type3to2(char /* sys */, const QString& typeV3) {
1304 if (typeV3 == "C1P" || typeV3 == "C1W") {
1305 return "P1";
1306 }
1307 else if (typeV3 == "C2P" || typeV3 == "C2W") {
1308 return "P2";
1309 }
1310 return typeV3.left(2);
1311}
1312
1313// Set Observations from RINEX File
1314////////////////////////////////////////////////////////////////////////////
1315void t_rnxObsFile::setObsFromRnx(const t_rnxObsFile* rnxObsFile, const t_rnxObsFile::t_rnxEpo* epo,
1316 const t_rnxObsFile::t_rnxSat& rnxSat, t_satObs& obs) {
1317 obs._staID = rnxObsFile->markerName().toAscii().constData();
1318 obs._prn = rnxSat.prn;
1319 obs._time = epo->tt;
1320
1321 char sys = rnxSat.prn.system();
1322
1323 QChar addToL2;
1324 for (int iType = 0; iType < rnxObsFile->nTypes(sys); iType++) {
1325 QString type = rnxObsFile->obsType(sys, iType);
1326 QString typeV3 = rnxObsFile->obsType(sys, iType, 3.0); // may or may not differ from type
1327 if (rnxSat.obs.contains(type) && rnxSat.obs[type].value != 0.0) {
1328 if (type == "P2" && typeV3.length() > 2) {
1329 addToL2 = typeV3[2];
1330 break;
1331 }
1332 }
1333 }
1334
1335 for (int iType = 0; iType < rnxObsFile->nTypes(sys); iType++) {
1336 QString type = rnxObsFile->obsType(sys, iType);
1337 QString typeV3 = rnxObsFile->obsType(sys, iType, 3.0); // may or may not differ from type
1338 if (type == "L2") {
1339 typeV3 += addToL2;
1340 }
1341 if (rnxSat.obs.contains(type)) {
1342 const t_rnxObs& rnxObs = rnxSat.obs[type];
1343 if (rnxObs.value != 0.0) {
1344 string type2ch(typeV3.mid(1).toAscii().data());
1345
1346 t_frqObs* frqObs = 0;
1347 for (unsigned iFrq = 0; iFrq < obs._obs.size(); iFrq++) {
1348 if (obs._obs[iFrq]->_rnxType2ch == type2ch) {
1349 frqObs = obs._obs[iFrq];
1350 break;
1351 }
1352 }
1353 if (frqObs == 0) {
1354 frqObs = new t_frqObs;
1355 frqObs->_rnxType2ch = type2ch;
1356 obs._obs.push_back(frqObs);
1357 }
1358
1359 switch( typeV3.toAscii().data()[0] ) {
1360 case 'C':
1361 frqObs->_codeValid = true;
1362 frqObs->_code = rnxObs.value;
1363 break;
1364 case 'L':
1365 frqObs->_phaseValid = true;
1366 frqObs->_phase = rnxObs.value;
1367 frqObs->_slip = (rnxObs.lli & 1);
1368 break;
1369 case 'D':
1370 frqObs->_dopplerValid = true;
1371 frqObs->_doppler = rnxObs.value;
1372 break;
1373 case 'S':
1374 frqObs->_snrValid = true;
1375 frqObs->_snr = rnxObs.value;
1376 break;
1377 }
1378
1379 // Handle old-fashioned SNR values
1380 // -------------------------------
1381 if (rnxObs.snr != 0 && !frqObs->_snrValid) {
1382 frqObs->_snrValid = true;
1383 frqObs->_snr = rnxObs.snr * 6.0 + 2.5;
1384 }
1385 }
1386 }
1387 }
1388}
1389
1390// Tracking Mode Priorities
1391////////////////////////////////////////////////////////////////////////////
1392QString t_rnxObsFile::signalPriorities(char sys) {
1393
1394 bncSettings settings;
1395
1396 QStringList priorList;
1397 QString reqcAction = settings.value("reqcAction").toString();
1398
1399 // Priorities in Edit/Concatenate (post processing) mode
1400 // ---------------------------------------------------
1401 if (reqcAction == "Edit/Concatenate") {
1402 priorList = settings.value("reqcV2Priority").toString().split(" ", QString::SkipEmptyParts);
1403 }
1404
1405 // Priorities in real-time mode
1406 // ----------------------------
1407 else {
1408 priorList = settings.value("rnxV2Priority").toString().split(" ", QString::SkipEmptyParts);
1409 }
1410
1411 if (priorList.empty()) {
1412 priorList << "CWPX_?";
1413 }
1414
1415 QString result;
1416 for (int ii = 0; ii < priorList.size(); ii++) {
1417 if (priorList[ii].indexOf(":") != -1) {
1418 QStringList hlp = priorList[ii].split(":", QString::SkipEmptyParts);
1419 if (hlp.size() == 2 && hlp[0].length() == 1 && hlp[0][0] == sys) {
1420 result = hlp[1];
1421 break;
1422 }
1423 }
1424 else {
1425 result = priorList[ii];
1426 }
1427 }
1428
1429 return result;
1430}
Note: See TracBrowser for help on using the repository browser.