source: ntrip/trunk/BNC/RTCM/RTCM2Decoder.cpp@ 2689

Last change on this file since 2689 was 2689, checked in by mervart, 14 years ago
File size: 11.0 KB
RevLine 
[297]1// Part of BNC, a utility for retrieving decoding and
[464]2// converting GNSS data streams from NTRIP broadcasters.
[242]3//
[464]4// Copyright (C) 2007
[297]5// German Federal Agency for Cartography and Geodesy (BKG)
6// http://www.bkg.bund.de
[464]7// Czech Technical University Prague, Department of Geodesy
[297]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.
[242]24
[464]25/* -------------------------------------------------------------------------
26 * BKG NTRIP Client
27 * -------------------------------------------------------------------------
28 *
29 * Class: RTCM2Decoder
30 *
31 * Purpose: RTCM2 Decoder
32 *
33 * Author: L. Mervart
34 *
35 * Created: 24-Aug-2006
36 *
37 * Changes:
38 *
39 * -----------------------------------------------------------------------*/
40
[1044]41#include <math.h>
42#include <sstream>
43#include <iomanip>
[1218]44#include <set>
[1044]45
[242]46#include "../bncutils.h"
[1044]47#include "rtcm_utils.h"
[242]48#include "GPSDecoder.h"
[243]49#include "RTCM2Decoder.h"
[242]50
51using namespace std;
[1044]52using namespace rtcm2;
[242]53
54//
55// Constructor
56//
57
[1044]58RTCM2Decoder::RTCM2Decoder(const std::string& ID) {
59 _ID = ID;
[242]60}
61
62//
63// Destructor
64//
65
66RTCM2Decoder::~RTCM2Decoder() {
[1218]67 for (t_listMap::iterator ii = _ephList.begin(); ii != _ephList.end(); ii++) {
[1044]68 delete ii->second;
69 }
[242]70}
71
[1044]72
[242]73//
[1044]74t_irc RTCM2Decoder::getStaCrd(double& xx, double& yy, double& zz) {
75 if ( !_msg03.validMsg ) {
76 return failure;
77 }
78
79 xx = _msg03.x + (_msg22.validMsg ? _msg22.dL1[0] : 0.0);
80 yy = _msg03.y + (_msg22.validMsg ? _msg22.dL1[1] : 0.0);
81 zz = _msg03.z + (_msg22.validMsg ? _msg22.dL1[2] : 0.0);
[242]82
[1044]83 return success;
84}
85
[1167]86//
87t_irc RTCM2Decoder::getStaCrd(double& xx, double& yy, double& zz,
88 double& dx1, double& dy1, double& dz1,
89 double& dx2, double& dy2, double& dz2) {
90 xx = _msg03.x;
91 yy = _msg03.y;
92 zz = _msg03.z;
[1044]93
[1167]94 dx1 = (_msg22.validMsg ? _msg22.dL1[0] : 0.0);
95 dy1 = (_msg22.validMsg ? _msg22.dL1[1] : 0.0);
96 dz1 = (_msg22.validMsg ? _msg22.dL1[2] : 0.0);
97
98 dx2 = (_msg22.validMsg ? _msg22.dL2[0] : 0.0);
99 dy2 = (_msg22.validMsg ? _msg22.dL2[1] : 0.0);
100 dz2 = (_msg22.validMsg ? _msg22.dL2[2] : 0.0);
101
102 return success;
103}
104
105
[1044]106//
[1218]107t_irc RTCM2Decoder::Decode(char* buffer, int bufLen, vector<string>& errmsg) {
[242]108
[1218]109 errmsg.clear();
110
[242]111 _buffer.append(buffer, bufLen);
112 int refWeek;
113 double refSecs;
114 currentGPSWeeks(refWeek, refSecs);
[702]115 bool decoded = false;
[242]116
117 while(true) {
118 _PP.getPacket(_buffer);
119 if (!_PP.valid()) {
[702]120 if (decoded) {
121 return success;
122 } else {
123 return failure;
124 }
[242]125 }
[1268]126
127 // Store message number
128 _typeList.push_back(_PP.ID());
[242]129
130 if ( _PP.ID()==18 || _PP.ID()==19 ) {
131
132 _ObsBlock.extract(_PP);
133
134 if (_ObsBlock.valid()) {
[702]135 decoded = true;
[242]136
137 int epochWeek;
138 double epochSecs;
139 _ObsBlock.resolveEpoch(refWeek, refSecs, epochWeek, epochSecs);
140
141 for (int iSat=0; iSat < _ObsBlock.nSat; iSat++) {
[622]142 p_obs obs = new t_obs();
[627]143 _obsList.push_back(obs);
[341]144 if (_ObsBlock.PRN[iSat] > 100) {
[1044]145 obs->_o.satNum = _ObsBlock.PRN[iSat] % 100;
146 obs->_o.satSys = 'R';
147 }
148 else {
149 obs->_o.satNum = _ObsBlock.PRN[iSat];
150 obs->_o.satSys = 'G';
151 }
152 obs->_o.GPSWeek = epochWeek;
153 obs->_o.GPSWeeks = epochSecs;
154 obs->_o.C1 = _ObsBlock.rng_C1[iSat];
155 obs->_o.P1 = _ObsBlock.rng_P1[iSat];
156 obs->_o.P2 = _ObsBlock.rng_P2[iSat];
157 obs->_o.L1 = _ObsBlock.resolvedPhase_L1(iSat);
158 obs->_o.L2 = _ObsBlock.resolvedPhase_L2(iSat);
159 obs->_o.slip_cnt_L1 = _ObsBlock.slip_L1[iSat];
160 obs->_o.slip_cnt_L2 = _ObsBlock.slip_L2[iSat];
[242]161 }
162 _ObsBlock.clear();
163 }
164 }
[1044]165
166 else if ( _PP.ID() == 20 || _PP.ID() == 21 ) {
167 _msg2021.extract(_PP);
168
169 if (_msg2021.valid()) {
[1045]170 decoded = true;
[1218]171 translateCorr2Obs(errmsg);
[1044]172 }
173 }
174
175 else if ( _PP.ID() == 3 ) {
176 _msg03.extract(_PP);
177 }
178
179 else if ( _PP.ID() == 22 ) {
180 _msg22.extract(_PP);
181 }
[1268]182
[1269]183 else if ( _PP.ID() == 23 ) {
184 _msg23.extract(_PP);
185 }
[1268]186
[1269]187 else if ( _PP.ID() == 24 ) {
188 _msg24.extract(_PP);
189 }
[1268]190
[1269]191 // Output for RTCM scan
192 if ( _PP.ID() == 3 ) {
193 if ( _msg03.validMsg ) {
194 _antList.push_back(t_antInfo());
195
196 this->getStaCrd(_antList.back().xx, _antList.back().yy, _antList.back().zz);
197
198 _antList.back().type = t_antInfo::APC;
199 _antList.back().message = _PP.ID();
200 }
[1268]201 }
[1269]202 else if ( _PP.ID() == 23 ) {
203 if ( _msg23.validMsg ) {
204 _antType.push_back(_msg23.antType.c_str());
205 }
206 }
207 else if ( _PP.ID() == 24 ) {
208 if ( _msg24.validMsg ) {
209 _antList.push_back(t_antInfo());
210
211 _antList.back().xx = _msg24.x;
212 _antList.back().yy = _msg24.y;
213 _antList.back().zz = _msg24.z;
214
215 _antList.back().type = t_antInfo::ARP;
216 _antList.back().message = _PP.ID();
217 }
218 }
[242]219 }
[649]220 return success;
[242]221}
222
[1044]223
224
[1218]225bool RTCM2Decoder::storeEph(const gpsephemeris& gpseph, string& storedPRN, vector<int>& IODs) {
[1044]226 t_ephGPS eph; eph.set(&gpseph);
227
[1218]228 return storeEph(eph, storedPRN, IODs);
[1044]229}
230
231
[1218]232bool RTCM2Decoder::storeEph(const t_ephGPS& gpseph, string& storedPRN, vector<int>& IODs) {
[1044]233 t_ephGPS* eph = new t_ephGPS(gpseph);
234
235 string prn = eph->prn();
236
[1218]237 t_listMap::iterator ip = _ephList.find(prn);
238 if (ip == _ephList.end() ) {
239 ip = _ephList.insert(pair<string, t_ephList*>(prn, new t_ephList)).first;
[1044]240 }
[1218]241 t_ephList* ephList = ip->second;
[1044]242
[1218]243 bool stored = ephList->store(eph);
[1044]244
[1218]245 if ( stored ) {
246 storedPRN = eph->prn();
247 ephList->getIODs(IODs);
248 return true;
[1044]249 }
250
251 delete eph;
[1218]252
253 return false;
[1044]254}
255
256
[1218]257void RTCM2Decoder::translateCorr2Obs(vector<string>& errmsg) {
[1044]258
259 if ( !_msg03.validMsg || !_msg2021.valid() ) {
260 return;
261 }
262
263 double stax = _msg03.x + (_msg22.validMsg ? _msg22.dL1[0] : 0.0);
264 double stay = _msg03.y + (_msg22.validMsg ? _msg22.dL1[1] : 0.0);
265 double staz = _msg03.z + (_msg22.validMsg ? _msg22.dL1[2] : 0.0);
266
267 int refWeek;
268 double refSecs;
269 currentGPSWeeks(refWeek, refSecs);
270
271 // Resolve receiver time of measurement (see RTCM 2.3, page 4-42, Message 18, Note 1)
272 // ----------------------------------------------------------------------------------
273 double hoursec_est = _msg2021.hoursec(); // estimated time of measurement
274 double hoursec_rcv = rint(hoursec_est * 1e2) / 1e2; // receiver clock reading at hoursec_est
275 double rcv_clk_bias = (hoursec_est - hoursec_rcv) * c_light;
276
277 int GPSWeek;
278 double GPSWeeks;
279 resolveEpoch(hoursec_est, refWeek, refSecs,
280 GPSWeek, GPSWeeks);
281
282 int GPSWeek_rcv;
283 double GPSWeeks_rcv;
284 resolveEpoch(hoursec_rcv, refWeek, refSecs,
285 GPSWeek_rcv, GPSWeeks_rcv);
286
287 // Loop over all satellites
288 // ------------------------
289 for (RTCM2_2021::data_iterator icorr = _msg2021.data.begin();
290 icorr != _msg2021.data.end(); icorr++) {
291 const RTCM2_2021::HiResCorr* corr = icorr->second;
292
[1218]293 // beg test
294 if ( corr->PRN >= 200 ) {
295 continue;
296 }
297 // end test
298
299
[1044]300 ostringstream oPRN; oPRN.fill('0');
301
302 oPRN << (corr->PRN < 200 ? 'G' : 'R')
303 << setw(2) << (corr->PRN < 200 ? corr->PRN : corr->PRN - 200);
304
305 string PRN(oPRN.str());
306
[1218]307 t_listMap::const_iterator ieph = _ephList.find(PRN);
[1044]308
309 double L1 = 0;
310 double L2 = 0;
311 double P1 = 0;
312 double P2 = 0;
313 string obsT = "";
314
315 // new observation
316 p_obs new_obs = 0;
317
[1218]318 // missing IOD
319 vector<string> missingIOD;
320 vector<string> hasIOD;
[1044]321 for (unsigned ii = 0; ii < 4; ii++) {
322 int IODcorr = 0;
323 double corrVal = 0;
324 const t_eph* eph = 0;
325 double* obsVal = 0;
326
327 switch (ii) {
328 case 0: // --- L1 ---
329 IODcorr = corr->IODp1;
330 corrVal = corr->phase1 * LAMBDA_1;
331 obsVal = &L1;
332 obsT = "L1";
333 break;
334 case 1: // --- L2 ---
335 IODcorr = corr->IODp2;
336 corrVal = corr->phase2 * LAMBDA_2;
337 obsVal = &L2;
338 obsT = "L2";
339 break;
340 case 2: // --- P1 ---
341 IODcorr = corr->IODr1;
342 corrVal = corr->range1;
343 obsVal = &P1;
344 obsT = "P1";
345 break;
346 case 3: // --- P2 ---
347 IODcorr = corr->IODr2;
348 corrVal = corr->range2;
349 obsVal = &P2;
350 obsT = "P2";
351 break;
352 default:
353 continue;
354 }
355
[1299]356 // Select corresponding ephemerides
357 if ( ieph != _ephList.end() ) {
358 eph = ieph->second->getEph(IODcorr);
359 }
[1218]360
361 if ( eph ) {
362 ostringstream msg;
363 msg << obsT << ':' << setw(3) << eph->IOD();
364 hasIOD.push_back(msg.str());
365
366
[1044]367 int GPSWeek_tot;
368 double GPSWeeks_tot;
369 double rho, xSat, ySat, zSat, clkSat;
370 cmpRho(eph, stax, stay, staz,
371 GPSWeek, GPSWeeks,
372 rho, GPSWeek_tot, GPSWeeks_tot,
373 xSat, ySat, zSat, clkSat);
374
375 *obsVal = rho - corrVal + rcv_clk_bias - clkSat;
376
377 if ( *obsVal == 0 ) *obsVal = ZEROVALUE;
378
379 // Allocate new memory
380 // -------------------
381 if ( !new_obs ) {
382 new_obs = new t_obs();
383
384 new_obs->_o.StatID[0] = '\x0';
385 new_obs->_o.satSys = (corr->PRN < 200 ? 'G' : 'R');
386 new_obs->_o.satNum = (corr->PRN < 200 ? corr->PRN : corr->PRN - 200);
387
388 new_obs->_o.GPSWeek = GPSWeek_rcv;
389 new_obs->_o.GPSWeeks = GPSWeeks_rcv;
390 }
391
392 // Store estimated measurements
393 // ----------------------------
394 switch (ii) {
395 case 0: // --- L1 ---
396 new_obs->_o.L1 = *obsVal / LAMBDA_1;
397 new_obs->_o.slip_cnt_L1 = corr->lock1;
398 break;
399 case 1: // --- L2 ---
400 new_obs->_o.L2 = *obsVal / LAMBDA_2;
401 new_obs->_o.slip_cnt_L2 = corr->lock2;
402 break;
403 case 2: // --- C1 / P1 ---
404 if ( corr->Pind1 )
405 new_obs->_o.P1 = *obsVal;
406 else
407 new_obs->_o.C1 = *obsVal;
408 break;
409 case 3: // --- C2 / P2 ---
410 if ( corr->Pind2 )
411 new_obs->_o.P2 = *obsVal;
412 else
413 new_obs->_o.C2 = *obsVal;
414 break;
415 default:
416 continue;
417 }
418 }
[1218]419 else if ( IODcorr != 0 ) {
420 ostringstream msg;
421 msg << obsT << ':' << setw(3) << IODcorr;
422 missingIOD.push_back(msg.str());
423 }
[1044]424 } // loop over frequencies
[1218]425
426 // Error report
427 if ( missingIOD.size() ) {
428 ostringstream missingIODstr;
429
430 copy(missingIOD.begin(), missingIOD.end(), ostream_iterator<string>(missingIODstr, " "));
431
432 errmsg.push_back("missing eph for " + PRN + " , IODs " + missingIODstr.str());
433 }
434
435 // Store new observation
[1044]436 if ( new_obs ) {
437 _obsList.push_back( new_obs );
[1218]438
[1299]439 ////ostringstream hasIODstr;
440 ////copy(hasIOD.begin(), hasIOD.end(), ostream_iterator<string>(hasIODstr, " "));
441 ////errmsg.push_back("decoded PRN " + PRN + " : " + hasIODstr.str());
[1044]442 }
443 }
444}
Note: See TracBrowser for help on using the repository browser.