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

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

BDS frequency band changes in RINEX 3.03 added

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