source: ntrip/trunk/BNC/src/RTCM3/RTCM3Decoder.cpp@ 6543

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

re-activate blocktype as message type indicator because 'rr' contains sometimes error codes as well

File size: 13.9 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: RTCM3Decoder
30 *
31 * Purpose: RTCM3 Decoder
32 *
33 * Author: L. Mervart
34 *
35 * Created: 24-Aug-2006
36 *
37 * Changes:
38 *
39 * -----------------------------------------------------------------------*/
40
41#include <iostream>
42#include <iomanip>
43#include <sstream>
44#include <math.h>
45#include <string.h>
46
47#include "RTCM3Decoder.h"
48#include "../RTCM/rtcm_utils.h"
49#include "bncconst.h"
50#include "bnccore.h"
51#include "bncutils.h"
52#include "bncsettings.h"
53
54using namespace std;
55
56#ifndef isinf
57# define isinf(x) 0
58#endif
59
60// Error Handling
61////////////////////////////////////////////////////////////////////////////
62void RTCM3Error(const char*, ...) {
63}
64
65// Constructor
66////////////////////////////////////////////////////////////////////////////
67RTCM3Decoder::RTCM3Decoder(const QString& staID, bncRawFile* rawFile) :
68 GPSDecoder() {
69
70 _staID = staID;
71 _rawFile = rawFile;
72
73 bncSettings settings;
74 _checkMountPoint = settings.value("miscMount").toString();
75
76 connect(this, SIGNAL(newGPSEph(t_ephGPS)), BNC_CORE, SLOT(slotNewGPSEph(t_ephGPS)));
77 connect(this, SIGNAL(newGlonassEph(t_ephGlo)), BNC_CORE, SLOT(slotNewGlonassEph(t_ephGlo)));
78 connect(this, SIGNAL(newGalileoEph(t_ephGal)), BNC_CORE, SLOT(slotNewGalileoEph(t_ephGal)));
79 connect(this, SIGNAL(newSBASEph(t_ephSBAS)), BNC_CORE, SLOT(slotNewSBASEph(t_ephSBAS)));
80
81 // Mode can be either observations or corrections
82 // ----------------------------------------------
83 _mode = unknown;
84
85 // Antenna position (used for decoding of message 1003)
86 // ----------------------------------------------------
87 _antXYZ[0] = _antXYZ[1] = _antXYZ[2] = 0;
88
89}
90
91// Destructor
92////////////////////////////////////////////////////////////////////////////
93RTCM3Decoder::~RTCM3Decoder() {
94 QMapIterator<QByteArray, RTCM3coDecoder*> it(_coDecoders);
95 while (it.hasNext()) {
96 it.next();
97 delete it.value();
98 }
99}
100
101//
102////////////////////////////////////////////////////////////////////////////
103t_irc RTCM3Decoder::Decode(char* buffer, int bufLen, vector<string>& errmsg) {
104
105 errmsg.clear();
106
107 bool decoded = false;
108
109 // If read from file, mode is always uknown
110 // ----------------------------------------
111 if (_rawFile) {
112 _mode = unknown;
113 _staID = _rawFile->staID();
114 }
115
116 // Try to decode Clock and Orbit Corrections
117 // -----------------------------------------
118 if (_mode == unknown || _mode == corrections) {
119
120 // Find the corresponding coDecoder
121 // --------------------------------
122 if (!_coDecoders.contains(_staID.toAscii())) {
123 _coDecoders[_staID.toAscii()] = new RTCM3coDecoder(_staID);
124 }
125 RTCM3coDecoder* coDecoder = _coDecoders[_staID.toAscii()];
126
127 if ( coDecoder->Decode(buffer, bufLen, errmsg) == success ) {
128 decoded = true;
129 if (!_rawFile && _mode == unknown) {
130 _mode = corrections;
131 }
132 }
133 }
134
135 // Find the corresponding parser, initialize a new parser if necessary
136 // -------------------------------------------------------------------
137 bool newParser = !_parsers.contains(_staID.toAscii());
138 RTCM3ParserData& parser = _parsers[_staID.toAscii()];
139 if (newParser) {
140 memset(&parser, 0, sizeof(parser));
141 parser.rinex3 = 0;
142 double secGPS;
143 currentGPSWeeks(parser.GPSWeek, secGPS);
144 parser.GPSTOW = int(secGPS);
145 }
146
147 // Remaining part decodes the Observations
148 // ---------------------------------------
149 if (_mode == unknown || _mode == observations ||
150 _checkMountPoint == _staID || _checkMountPoint == "ALL") {
151
152 for (int iByte = 0; iByte < bufLen; iByte++) {
153
154 parser.Message[parser.MessageSize++] = buffer[iByte];
155
156 if (parser.MessageSize >= parser.NeedBytes) {
157
158 while (int rr = RTCM3Parser(&parser)) {
159
160 // RTCMv3 message types
161 // --------------------
162 _typeList.push_back(parser.blocktype);
163
164 // RTCMv3 antenna descriptor
165 // -------------------------
166 if (rr == 1007 || rr == 1008 || rr == 1033) {
167 _antType.push_back(parser.antenna);
168 }
169
170 // RTCMv3 antenna XYZ
171 // ------------------
172 else if (rr == 1005) {
173 _antList.push_back(t_antInfo());
174 _antList.back().type = t_antInfo::ARP;
175 _antList.back().xx = parser.antX * 1e-4;
176 _antList.back().yy = parser.antY * 1e-4;
177 _antList.back().zz = parser.antZ * 1e-4;
178 _antList.back().message = rr;
179
180 // Remember station position for 1003 message decoding
181 _antXYZ[0] = parser.antX * 1e-4;
182 _antXYZ[1] = parser.antY * 1e-4;
183 _antXYZ[2] = parser.antZ * 1e-4;
184 }
185
186 // RTCMv3 antenna XYZ-H
187 // --------------------
188 else if(rr == 1006) {
189 _antList.push_back(t_antInfo());
190 _antList.back().type = t_antInfo::ARP;
191 _antList.back().xx = parser.antX * 1e-4;
192 _antList.back().yy = parser.antY * 1e-4;
193 _antList.back().zz = parser.antZ * 1e-4;
194 _antList.back().height = parser.antH * 1e-4;
195 _antList.back().height_f = true;
196 _antList.back().message = rr;
197
198 // Remember station position for 1003 message decoding
199 _antXYZ[0] = parser.antX * 1e-4;
200 _antXYZ[1] = parser.antY * 1e-4;
201 _antXYZ[2] = parser.antZ * 1e-4;
202 }
203
204 // GNSS Observations
205 // -----------------
206 else if (rr == 1 || rr == 2) {
207 decoded = true;
208
209 if (!parser.init) {
210 HandleHeader(&parser);
211 parser.init = 1;
212 }
213
214 if (rr == 2) {
215 emit(newMessage( (_staID +
216 ": No valid RINEX! All values are modulo 299792.458!").toAscii(),
217 true));
218 }
219
220 gnssdata& gnssData = parser.Data;
221
222 for (int iSat = 0; iSat < gnssData.numsats; iSat++) {
223
224 t_satObs obs;
225 int satID = gnssData.satellites[iSat];
226
227 // GPS
228 // ---
229 if (satID >= PRN_GPS_START && satID <= PRN_GPS_END) {
230 obs._prn.set('G', satID);
231 }
232
233 // Glonass
234 // -------
235 else if (satID >= PRN_GLONASS_START && satID <= PRN_GLONASS_END) {
236 obs._prn.set('R', satID - PRN_GLONASS_START + 1);
237 }
238
239 // Galileo
240 // -------
241 else if (satID >= PRN_GALILEO_START && satID <= PRN_GALILEO_END) {
242 obs._prn.set('E', satID - PRN_GALILEO_START + 1);
243 }
244
245 // SBAS
246 // ----
247 else if (satID >= PRN_SBAS_START && satID <= PRN_SBAS_END) {
248 obs._prn.set('S', satID - PRN_SBAS_START + 20);
249 }
250
251 // Giove A and B
252 // -------------
253 else if (satID >= PRN_GIOVE_START && satID <= PRN_GIOVE_END) {
254 obs._prn.set('E', satID - PRN_GIOVE_START + PRN_GIOVE_OFFSET);
255 }
256
257 // QZSS
258 // -------------
259 else if (satID >= PRN_QZSS_START && satID <= PRN_QZSS_END) {
260 obs._prn.set('J', satID - PRN_QZSS_START + 1);
261 }
262
263 // COMPASS
264 // -------------
265 else if (satID >= PRN_COMPASS_START && satID <= PRN_COMPASS_END) {
266 obs._prn.set('C', satID - PRN_COMPASS_START + 1);
267 }
268
269 // Unknown System
270 // --------------
271 else {
272 continue;
273 }
274
275 obs._time.set(gnssData.week, gnssData.timeofweek / 1000.0);
276
277 QString prn(obs._prn.toString().c_str());
278
279 int obs_slip_cnt_L1 = 0;
280 int obs_slip_cnt_L2 = 0;
281 int obs_slip_cnt_L5 = 0;
282
283 // Handle loss-of-lock flags
284 // -------------------------
285 const int maxSlipCnt = 100;
286 if (!_slip_cnt_L1.contains(prn)) {
287 _slip_cnt_L1[prn] = 0;
288 _slip_cnt_L2[prn] = 0;
289 _slip_cnt_L5[prn] = 0;
290 }
291 if (GNSSDF2_LOCKLOSSL1 & gnssData.dataflags2[iSat]) {
292 if (_slip_cnt_L1[prn] < maxSlipCnt) {
293 ++_slip_cnt_L1[prn];
294 }
295 else {
296 _slip_cnt_L1[prn] = 1;
297 }
298 obs_slip_cnt_L1 = _slip_cnt_L1[prn];
299 }
300 if (GNSSDF2_LOCKLOSSL2 & gnssData.dataflags2[iSat]) {
301 if (_slip_cnt_L2[prn] < maxSlipCnt) {
302 ++_slip_cnt_L2[prn];
303 }
304 else {
305 _slip_cnt_L2[prn] = 1;
306 }
307 obs_slip_cnt_L2 = _slip_cnt_L2[prn];
308 }
309 if (GNSSDF2_LOCKLOSSL5 & gnssData.dataflags2[iSat]) {
310 if (_slip_cnt_L5[prn] < maxSlipCnt) {
311 ++_slip_cnt_L5[prn];
312 }
313 else {
314 _slip_cnt_L5[prn] = 1;
315 }
316 obs_slip_cnt_L5 = _slip_cnt_L5[prn];
317 }
318
319 // Loop over all data types
320 // ------------------------
321 for (int iEntry = 0; iEntry < GNSSENTRY_NUMBER; ++iEntry) {
322 if (gnssData.codetype[iSat][iEntry] == 0) {
323 continue;
324 }
325 string rnxType(gnssData.codetype[iSat][iEntry]);
326
327 t_frqObs* frqObs = 0;
328 for (unsigned iFrq = 0; iFrq < obs._obs.size(); iFrq++) {
329 if (obs._obs[iFrq]->_rnxType2ch == rnxType) {
330 frqObs = obs._obs[iFrq];
331 break;
332 }
333 }
334 if (frqObs == 0) {
335 frqObs = new t_frqObs;
336 frqObs->_rnxType2ch = rnxType;
337 obs._obs.push_back(frqObs);
338 }
339
340 switch(iEntry & 3) {
341 case GNSSENTRY_CODE:
342 frqObs->_codeValid = true;
343 frqObs->_code = gnssData.measdata[iSat][iEntry];
344 break;
345 case GNSSENTRY_PHASE:
346 frqObs->_phaseValid = true;
347 frqObs->_phase = gnssData.measdata[iSat][iEntry];
348 if (rnxType[0] == '1') {
349 frqObs->_slipCounter = obs_slip_cnt_L1;
350 }
351 else if (rnxType[0] == '2') {
352 frqObs->_slipCounter = obs_slip_cnt_L2;
353 }
354 else if (rnxType[0] == '5') {
355 frqObs->_slipCounter = obs_slip_cnt_L5;
356 }
357 break;
358 case GNSSENTRY_DOPPLER:
359 frqObs->_dopplerValid = true;
360 frqObs->_doppler = gnssData.measdata[iSat][iEntry];
361 break;
362 case GNSSENTRY_SNR:
363 frqObs->_snrValid = true;
364 frqObs->_snr = gnssData.measdata[iSat][iEntry];
365 break;
366 }
367 }
368 _obsList.push_back(obs);
369 }
370 }
371
372 // GPS Ephemeris
373 // -------------
374 else if (rr == 1019) {
375 decoded = true;
376 t_ephGPS eph; eph.set(&parser.ephemerisGPS);
377 emit newGPSEph(eph);
378 }
379
380 // GLONASS Ephemeris
381 // -----------------
382 else if (rr == 1020 && parser.ephemerisGLONASS.almanac_number >= 1 &&
383 parser.ephemerisGLONASS.almanac_number <= PRN_GLONASS_NUM) {
384 decoded = true;
385 t_ephGlo eph; eph.set(&parser.ephemerisGLONASS);
386 emit newGlonassEph(eph);
387 }
388
389 // Galileo Ephemeris
390 // -----------------
391 else if (rr == 1045 || rr == 1046) {
392 decoded = true;
393 t_ephGal eph; eph.set(&parser.ephemerisGALILEO);
394 emit newGalileoEph(eph);
395 }
396
397 // QZSS Ephemeris
398 // --------------
399 else if (rr == 1044) {
400 decoded = true;
401 t_ephGPS eph; eph.set(&parser.ephemerisGPS);
402 emit newGPSEph(eph);
403 }
404
405 // SBAS Ephemeris
406 // --------------
407 else if (rr == 1043) {
408 decoded = true;
409 t_ephSBAS eph; eph.set(&parser.ephemerisSBAS);
410 emit newSBASEph(eph);
411 }
412 }
413 }
414 }
415 if (!_rawFile && _mode == unknown && decoded) {
416 _mode = observations;
417 }
418 }
419
420 if (decoded) {
421 return success;
422 }
423 else {
424 return failure;
425 }
426}
427
428// Time of Corrections
429//////////////////////////////////////////////////////////////////////////////
430int RTCM3Decoder::corrGPSEpochTime() const {
431 if (_mode == corrections && _coDecoders.size() > 0) {
432 return _coDecoders.begin().value()->corrGPSEpochTime();
433 }
434 else {
435 return -1;
436 }
437}
Note: See TracBrowser for help on using the repository browser.