source: ntrip/trunk/BNC/bncpppclient.cpp@ 2228

Last change on this file since 2228 was 2228, checked in by mervart, 14 years ago

* empty log message *

File size: 10.6 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: bncPPPclient
30 *
31 * Purpose: Precise Point Positioning
32 *
33 * Author: L. Mervart
34 *
35 * Created: 21-Nov-2009
36 *
37 * Changes:
38 *
39 * -----------------------------------------------------------------------*/
40
41#include "bncpppclient.h"
42#include "bncapp.h"
43#include "bncutils.h"
44#include "bncconst.h"
45#include "bncmodel.h"
46#include "bncsettings.h"
47
48extern "C" {
49#include "clock_orbit_rtcm.h"
50}
51
52using namespace std;
53
54// Constructor
55////////////////////////////////////////////////////////////////////////////
56bncPPPclient::bncPPPclient(QByteArray staID) {
57
58 bncSettings settings;
59
60 if ( Qt::CheckState(settings.value("pppGLONASS").toInt()) == Qt::Checked) {
61 _useGlonass = true;
62 }
63 else {
64 _useGlonass = false;
65 }
66
67 connect(((bncApp*)qApp), SIGNAL(newEphGPS(gpsephemeris)),
68 this, SLOT(slotNewEphGPS(gpsephemeris)));
69 connect(((bncApp*)qApp), SIGNAL(newEphGlonass(glonassephemeris)),
70 this, SLOT(slotNewEphGlonass(glonassephemeris)));
71 connect(((bncApp*)qApp), SIGNAL(newCorrections(QList<QString>)),
72 this, SLOT(slotNewCorrections(QList<QString>)));
73
74 _staID = staID;
75 _epoData = 0;
76 _model = new bncModel(staID);
77 connect(_model, SIGNAL(newNMEAstr(QByteArray)),
78 this, SIGNAL(newNMEAstr(QByteArray)));
79}
80
81// Destructor
82////////////////////////////////////////////////////////////////////////////
83bncPPPclient::~bncPPPclient() {
84 delete _model;
85 delete _epoData;
86 QMapIterator<QString, t_eph*> it(_eph);
87 while (it.hasNext()) {
88 it.next();
89 delete it.value();
90 }
91 QMapIterator<QString, t_corr*> ic(_corr);
92 while (ic.hasNext()) {
93 ic.next();
94 delete ic.value();
95 }
96}
97
98//
99////////////////////////////////////////////////////////////////////////////
100void bncPPPclient::putNewObs(p_obs pp) {
101 QMutexLocker locker(&_mutex);
102
103 t_obsInternal* obs = &(pp->_o);
104
105 if (obs->satSys != 'G' && !_useGlonass) {
106 return;
107 }
108
109 t_satData* satData = new t_satData();
110
111 // Set Code Observations
112 // ---------------------
113 if (obs->P1) {
114 satData->P1 = obs->P1;
115 satData->codeTypeF1 = t_satData::P_CODE;
116 }
117 else if (obs->C1) {
118 satData->P1 = obs->C1;
119 satData->codeTypeF1 = t_satData::C_CODE;
120 }
121 else {
122 delete satData;
123 return;
124 }
125
126 if (obs->P2) {
127 satData->P2 = obs->P2;
128 satData->codeTypeF2 = t_satData::P_CODE;
129 }
130 else if (obs->C2) {
131 satData->P2 = obs->C2;
132 satData->codeTypeF2 = t_satData::C_CODE;
133 }
134 else {
135 delete satData;
136 return;
137 }
138
139 double f1 = t_CST::freq1;
140 double f2 = t_CST::freq2;
141
142 // Ionosphere-Free Combination
143 // ---------------------------
144 double c1 = f1 * f1 / (f1 * f1 - f2 * f2);
145 double c2 = - f2 * f2 / (f1 * f1 - f2 * f2);
146
147 satData->P3 = c1 * satData->P1 + c2 * satData->P2;
148
149 // Set Phase Observations
150 // ----------------------
151 if (obs->L1 && obs->L2) {
152 satData->L1 = obs->L1 * t_CST::c / f1;
153 satData->L2 = obs->L2 * t_CST::c / f2;
154 }
155 else {
156 delete satData;
157 return;
158 }
159 satData->L3 = c1 * satData->L1 + c2 * satData->L2;
160
161 // Add new Satellite to the epoch
162 // ------------------------------
163 bncTime tt(obs->GPSWeek, obs->GPSWeeks);
164
165 if (!_epoData) {
166 _epoData = new t_epoData();
167 _epoData->tt = tt;
168 }
169 else if (tt != _epoData->tt) {
170 processEpoch();
171 delete _epoData;
172 _epoData = new t_epoData();
173 _epoData->tt = tt;
174 }
175
176 QString prn =
177 QString("%1%2").arg(obs->satSys).arg(obs->satNum, 2, 10, QChar('0'));
178
179 _epoData->satData[prn] = satData;
180}
181
182//
183////////////////////////////////////////////////////////////////////////////
184void bncPPPclient::slotNewEphGPS(gpsephemeris gpseph) {
185 QMutexLocker locker(&_mutex);
186
187 QString prn = QString("G%1").arg(gpseph.satellite, 2, 10, QChar('0'));
188
189 if (_eph.contains(prn)) {
190 t_ephGPS* ee = static_cast<t_ephGPS*>(_eph.value(prn));
191 if ( (ee->GPSweek() < gpseph.GPSweek) ||
192 (ee->GPSweek() == gpseph.GPSweek &&
193 ee->TOC() < gpseph.TOC) ) {
194 ee->set(&gpseph);
195 }
196 }
197 else {
198 t_ephGPS* ee = new t_ephGPS();
199 ee->set(&gpseph);
200 _eph[prn] = ee;
201 }
202}
203
204//
205////////////////////////////////////////////////////////////////////////////
206void bncPPPclient::slotNewEphGlonass(glonassephemeris gloeph) {
207 QMutexLocker locker(&_mutex);
208
209 QString prn = QString("R%1").arg(gloeph.almanac_number, 2, 10, QChar('0'));
210
211 if (_eph.contains(prn)) {
212 t_ephGlo* ee = static_cast<t_ephGlo*>(_eph.value(prn));
213 if ( (ee->GPSweek() < gloeph.GPSWeek) ||
214 (ee->GPSweek() == gloeph.GPSWeek &&
215 ee->GPSweeks() < gloeph.GPSTOW) ) {
216 ee->set(&gloeph);
217 }
218 }
219 else {
220 t_ephGlo* ee = new t_ephGlo();
221 ee->set(&gloeph);
222 _eph[prn] = ee;
223 }
224}
225
226//
227////////////////////////////////////////////////////////////////////////////
228void bncPPPclient::slotNewCorrections(QList<QString> corrList) {
229 QMutexLocker locker(&_mutex);
230
231 if (corrList.size() == 0) {
232 return;
233 }
234
235 // Remove All Corrections
236 // ----------------------
237 QMapIterator<QString, t_corr*> ic(_corr);
238 while (ic.hasNext()) {
239 ic.next();
240 delete ic.value();
241 }
242 _corr.clear();
243
244 QListIterator<QString> it(corrList);
245 while (it.hasNext()) {
246 QTextStream in(it.next().toAscii());
247 int messageType;
248 int updateInterval;
249 int GPSweek;
250 double GPSweeks;
251 QString prn;
252 in >> messageType >> updateInterval >> GPSweek >> GPSweeks >> prn;
253 if ( messageType == COTYPE_GPSCOMBINED ||
254 messageType == COTYPE_GLONASSCOMBINED ||
255 messageType == COTYPE_GPSORBIT ||
256 messageType == COTYPE_GPSCLOCK ||
257 messageType == COTYPE_GLONASSORBIT ||
258 messageType == COTYPE_GLONASSCLOCK ) {
259
260 t_corr* cc = 0;
261 if (_corr.contains(prn)) {
262 cc = _corr.value(prn);
263 }
264 else {
265 cc = new t_corr();
266 _corr[prn] = cc;
267 }
268
269 cc->tt.set(GPSweek, GPSweeks);
270
271 if ( messageType == COTYPE_GPSCOMBINED ||
272 messageType == COTYPE_GLONASSCOMBINED ) {
273 cc->rao.ReSize(3);
274 in >> cc->iod >> cc->dClk >> cc->rao[0] >> cc->rao[1] >> cc->rao[2];
275 cc->dClk /= t_CST::c;
276 cc->raoSet = true;
277 cc->dClkSet = true;
278 }
279 else if ( messageType == COTYPE_GPSORBIT ||
280 messageType == COTYPE_GLONASSORBIT ) {
281 cc->rao.ReSize(3);
282 in >> cc->iod >> cc->rao[0] >> cc->rao[1] >> cc->rao[2];
283 cc->raoSet = true;
284 }
285 else if ( messageType == COTYPE_GPSCLOCK ||
286 messageType == COTYPE_GLONASSCLOCK ) {
287 int dummyIOD;
288 in >> dummyIOD >> cc->dClk;
289 cc->dClk /= t_CST::c;
290 cc->dClkSet = true;
291 }
292 }
293 }
294
295 QMutableMapIterator<QString, t_corr*> im(_corr);
296 while (im.hasNext()) {
297 im.next();
298 t_corr* cc = im.value();
299 if (!cc->ready()) {
300 delete cc;
301 im.remove();
302 }
303 }
304}
305
306// Satellite Position
307////////////////////////////////////////////////////////////////////////////
308t_irc bncPPPclient::getSatPos(const bncTime& tt, const QString& prn,
309 ColumnVector& xc, ColumnVector& vv, bool& corr) {
310
311 const bool CORR_REQUIRED = true;
312 const double MAXAGE = 120.0;
313
314 corr = false;
315
316 if (_eph.contains(prn)) {
317 t_eph* ee = _eph.value(prn);
318 ee->position(tt.gpsw(), tt.gpssec(), xc.data(), vv.data());
319
320 if (CORR_REQUIRED) {
321 if (_corr.contains(prn)) {
322 t_corr* cc = _corr.value(prn);
323 if (ee->IOD() == cc->iod && (tt - cc->tt) < MAXAGE) {
324 corr = true;
325 applyCorr(cc, xc, vv);
326 return success;
327 }
328 }
329 return failure;
330 }
331
332 return success;
333 }
334
335 return failure;
336}
337
338//
339////////////////////////////////////////////////////////////////////////////
340void bncPPPclient::applyCorr(const t_corr* cc, ColumnVector& xc,
341 ColumnVector& vv) {
342 ColumnVector dx(3);
343 RSW_to_XYZ(xc.Rows(1,3), vv, cc->rao, dx);
344
345 xc[0] -= dx[0];
346 xc[1] -= dx[1];
347 xc[2] -= dx[2];
348 xc[3] -= cc->dClk;
349
350 // Relativistic Correction
351 // -----------------------
352 xc[3] -= 2.0 * DotProduct(xc.Rows(1,3),vv) / t_CST::c / t_CST::c ;
353}
354
355// Correct Time of Transmission
356////////////////////////////////////////////////////////////////////////////
357t_irc bncPPPclient::cmpToT(const QString& prn, t_satData* satData) {
358
359 double prange = satData->P3;
360 if (prange == 0.0) {
361 return failure;
362 }
363
364 double clkSat = 0.0;
365 for (int ii = 1; ii <= 10; ii++) {
366
367 bncTime ToT = _epoData->tt - prange / t_CST::c - clkSat;
368
369 ColumnVector xc(4);
370 ColumnVector vv(3);
371 bool corr = false;
372 if (getSatPos(ToT, prn, xc, vv, corr) != success) {
373 return failure;
374 }
375
376 double clkSatOld = clkSat;
377 clkSat = xc(4);
378
379 if ( fabs(clkSat-clkSatOld) * t_CST::c < 1.e-4 ) {
380 satData->xx = xc.Rows(1,3);
381 satData->vv = vv;
382 satData->clk = clkSat * t_CST::c;
383 satData->clkCorr = corr;
384 return success;
385 }
386 }
387
388 return failure;
389}
390
391//
392////////////////////////////////////////////////////////////////////////////
393void bncPPPclient::processEpoch() {
394
395 // Data Pre-Processing
396 // -------------------
397 QMutableMapIterator<QString, t_satData*> im(_epoData->satData);
398 while (im.hasNext()) {
399 im.next();
400 QString prn = im.key();
401 t_satData* satData = im.value();
402
403 if (cmpToT(prn, satData) != success) {
404 delete satData;
405 im.remove();
406 continue;
407 }
408 }
409
410 // Filter Solution
411 // ---------------
412 if (_model->update(_epoData) == success) {
413 emit newPosition(_model->time(), _model->x(), _model->y(), _model->z());
414 }
415}
416
Note: See TracBrowser for help on using the repository browser.