source: ntrip/branches/BNC_2.12/src/bncephuser.cpp @ 8706

Last change on this file since 8706 was 8706, checked in by stuerze, 14 months ago

minor changes to try to prevent crashes in case of GLONASS upload

File size: 9.1 KB
Line 
1// converting GNSS data streams from NTRIP broadcasters.
2//
3// Copyright (C) 2007
4// German Federal Agency for Cartography and Geodesy (BKG)
5// http://www.bkg.bund.de
6// Czech Technical University Prague, Department of Geodesy
7// http://www.fsv.cvut.cz
8//
9// Email: euref-ip@bkg.bund.de
10//
11// This program is free software; you can redistribute it and/or
12// modify it under the terms of the GNU General Public License
13// as published by the Free Software Foundation, version 2.
14//
15// This program is distributed in the hope that it will be useful,
16// but WITHOUT ANY WARRANTY; without even the implied warranty of
17// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18// GNU General Public License for more details.
19//
20// You should have received a copy of the GNU General Public License
21// along with this program; if not, write to the Free Software
22// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23
24/* -------------------------------------------------------------------------
25 * BKG NTRIP Client
26 * -------------------------------------------------------------------------
27 *
28 * Class:      bncEphUser
29 *
30 * Purpose:    Base for Classes that use Ephemerides
31 *
32 * Author:     L. Mervart
33 *
34 * Created:    27-Jan-2011
35 *
36 * Changes:
37 *
38 * -----------------------------------------------------------------------*/
39
40#include <cmath>
41#include <iostream>
42
43#include "bncephuser.h"
44#include "bnccore.h"
45
46using namespace std;
47
48// Constructor
49////////////////////////////////////////////////////////////////////////////
50bncEphUser::bncEphUser(bool connectSlots) {
51  if (connectSlots) {
52    connect(BNC_CORE, SIGNAL(newGPSEph(t_ephGPS)),
53            this, SLOT(slotNewGPSEph(t_ephGPS)), Qt::DirectConnection);
54
55    connect(BNC_CORE, SIGNAL(newGlonassEph(t_ephGlo)),
56            this, SLOT(slotNewGlonassEph(t_ephGlo)), Qt::DirectConnection);
57
58    connect(BNC_CORE, SIGNAL(newGalileoEph(t_ephGal)),
59            this, SLOT(slotNewGalileoEph(t_ephGal)), Qt::DirectConnection);
60
61    connect(BNC_CORE, SIGNAL(newSBASEph(t_ephSBAS)),
62            this, SLOT(slotNewSBASEph(t_ephSBAS)), Qt::DirectConnection);
63
64    connect(BNC_CORE, SIGNAL(newBDSEph(t_ephBDS)),
65            this, SLOT(slotNewBDSEph(t_ephBDS)), Qt::DirectConnection);
66  }
67}
68
69// Destructor
70////////////////////////////////////////////////////////////////////////////
71bncEphUser::~bncEphUser() {
72  QMapIterator<QString, deque<t_eph*> > it(_eph);
73  while (it.hasNext()) {
74    it.next();
75    const deque<t_eph*>& qq = it.value();
76    for (unsigned ii = 0; ii < qq.size(); ii++) {
77      delete qq[ii];
78    }
79  }
80}
81
82// New GPS Ephemeris
83////////////////////////////////////////////////////////////////////////////
84void bncEphUser::slotNewGPSEph(t_ephGPS eph) {
85  putNewEph(&eph, true);
86}
87
88// New Glonass Ephemeris
89////////////////////////////////////////////////////////////////////////////
90void bncEphUser::slotNewGlonassEph(t_ephGlo eph) {
91  putNewEph(&eph, true);
92}
93
94// New Galileo Ephemeris
95////////////////////////////////////////////////////////////////////////////
96void bncEphUser::slotNewGalileoEph(t_ephGal eph) {
97  putNewEph(&eph, true);
98}
99
100// New SBAS Ephemeris
101////////////////////////////////////////////////////////////////////////////
102void bncEphUser::slotNewSBASEph(t_ephSBAS eph) {
103  putNewEph(&eph, true);
104}
105
106// New BDS Ephemeris
107////////////////////////////////////////////////////////////////////////////
108void bncEphUser::slotNewBDSEph(t_ephBDS eph) {
109  putNewEph(&eph, true);
110}
111
112//
113////////////////////////////////////////////////////////////////////////////
114t_irc bncEphUser::putNewEph(t_eph* eph, bool realTime) {
115
116  QMutexLocker locker(&_mutex);
117
118  if (eph == 0) {
119    return failure;
120  }
121
122  const t_ephGPS*     ephGPS     = dynamic_cast<const t_ephGPS*>(eph);
123  const t_ephGlo*     ephGlo     = dynamic_cast<const t_ephGlo*>(eph);
124  const t_ephGal*     ephGal     = dynamic_cast<const t_ephGal*>(eph);
125  const t_ephSBAS*    ephSBAS    = dynamic_cast<const t_ephSBAS*>(eph);
126  const t_ephBDS*     ephBDS     = dynamic_cast<const t_ephBDS*>(eph);
127
128  t_eph* newEph = 0;
129
130  if      (ephGPS) {
131    newEph = new t_ephGPS(*ephGPS);
132  }
133  else if (ephGlo) {
134    newEph = new t_ephGlo(*ephGlo);
135  }
136  else if (ephGal) {
137    newEph = new t_ephGal(*ephGal);
138  }
139  else if (ephSBAS) {
140    newEph = new t_ephSBAS(*ephSBAS);
141  }
142  else if (ephBDS) {
143    newEph = new t_ephBDS(*ephBDS);
144  }
145  else {
146    return failure;
147  }
148
149  QString prn(newEph->prn().toInternalString().c_str());
150
151  const t_eph* ephOld = ephLast(prn);
152
153  if (ephOld &&
154      (ephOld->checkState() == t_eph::bad ||
155       ephOld->checkState() == t_eph::outdated)) {
156    ephOld = 0;
157  }
158
159  if (ephOld == 0 || newEph->isNewerThan(ephOld)) {
160    checkEphemeris(eph, realTime);
161  }
162  else {
163    delete newEph;
164    return failure;
165  }
166
167  if (eph->checkState() != t_eph::bad &&
168       eph->checkState() != t_eph::outdated) {
169    deque<t_eph*>& qq = _eph[prn];
170    qq.push_back(newEph);
171    if (qq.size() > _maxQueueSize) {
172      delete qq.front();
173      qq.pop_front();
174    }
175    ephBufferChanged();
176    return success;
177  }
178  else {
179    delete newEph;
180    return failure;
181  }
182}
183
184//
185////////////////////////////////////////////////////////////////////////////
186void bncEphUser::checkEphemeris(t_eph* eph, bool realTime) {
187
188  if (!eph || eph->checkState() == t_eph::ok || eph->checkState() == t_eph::bad) {
189    return;
190  }
191
192  // Check health status
193  // -------------------
194  if (eph->isUnhealthy()) {
195    eph->setCheckState(t_eph::unhealthy);
196    return;
197  }
198
199  // Simple Check - check satellite radial distance
200  // ----------------------------------------------
201  ColumnVector xc(6);
202  ColumnVector vv(3);
203  if (eph->getCrd(eph->TOC(), xc, vv, false) != success) {
204    eph->setCheckState(t_eph::bad);
205    return;
206  }
207
208  double rr = xc.Rows(1,3).norm_Frobenius();
209
210  const double MINDIST = 2.e7;
211  const double MAXDIST = 6.e7;
212  if (rr < MINDIST || rr > MAXDIST || std::isnan(rr)) {
213    eph->setCheckState(t_eph::bad);
214    return;
215  }
216
217  // Check whether the epoch is too far away the current time
218  // --------------------------------------------------------
219  if (realTime) {
220    bncTime   toc = eph->TOC();
221    QDateTime now = currentDateAndTimeGPS();
222    bncTime currentTime(now.toString(Qt::ISODate).toStdString());
223    double timeDiff = fabs(toc - currentTime);
224
225    if      (eph->type() == t_eph::GPS     && timeDiff > 4*3600) { // update interval: 2h, data sets are valid for 4 hours
226      eph->setCheckState(t_eph::outdated);
227      return;
228    }
229    else if (eph->type() == t_eph::Galileo && timeDiff > 4*3600) { // update interval: 2h, data sets are valid for 4 hours
230      eph->setCheckState(t_eph::outdated);
231      return;
232    }
233    else if (eph->type() == t_eph::GLONASS && timeDiff > 2*3600) { // updated every 30 minutes
234      eph->setCheckState(t_eph::outdated);
235      return;
236    }
237    else if (eph->type() == t_eph::QZSS    && timeDiff > 4*3600) { // orbit parameters are valid for 7200 seconds (at minimum)
238      eph->setCheckState(t_eph::outdated);
239      return;
240    }
241    else if (eph->type() == t_eph::SBAS    && timeDiff > 600) { // maximum update interval: 300 sec
242      eph->setCheckState(t_eph::outdated);
243      return;
244    }
245    else if (eph->type() == t_eph::BDS     && timeDiff > 6*3600) { // updates (GEO) up to 6 hours
246      eph->setCheckState(t_eph::outdated);
247      return;
248    }
249    else if (eph->type() == t_eph::IRNSS   && timeDiff > 24*3600) { // update interval: up to 24 hours
250      eph->setCheckState(t_eph::outdated);
251      return;
252    }
253  }
254
255  // Check consistency with older ephemerides
256  // ----------------------------------------
257  const double MAXDIFF = 1000.0;
258  QString      prn     = QString(eph->prn().toInternalString().c_str());
259  t_eph*       ephL    = ephLast(prn);
260
261  if (ephL) {
262    ColumnVector xcL(6);
263    ColumnVector vvL(3);
264    ephL->getCrd(eph->TOC(), xcL, vvL, false);
265
266    double dt    = fabs(eph->TOC() - ephL->TOC());
267    double diff  = (xc.Rows(1,3) - xcL.Rows(1,3)).norm_Frobenius();
268    double diffC = fabs(xc(4) - xcL(4)) * t_CST::c;
269
270    // some lines to allow update of ephemeris data sets after outage
271    if      (eph->type() == t_eph::GPS     && dt > 4*3600) {
272      ephL->setCheckState(t_eph::outdated);
273      return;
274    }
275    else if (eph->type() == t_eph::Galileo && dt > 4*3600) {
276      ephL->setCheckState(t_eph::outdated);
277      return;
278    }
279    else if (eph->type() == t_eph::GLONASS && dt > 2*3600) {
280      ephL->setCheckState(t_eph::outdated);
281      return;
282    }
283    else if (eph->type() == t_eph::QZSS    && dt > 4*3600) {
284      ephL->setCheckState(t_eph::outdated);
285      return;
286    }
287    else if  (eph->type() == t_eph::SBAS   && dt > 600)    {
288      ephL->setCheckState(t_eph::outdated);
289      return;
290    }
291    else if  (eph->type() == t_eph::BDS    && dt > 6*3600) {
292      ephL->setCheckState(t_eph::outdated);
293      return;
294    }
295    else if  (eph->type() == t_eph::IRNSS  && dt > 24*3600) {
296      ephL->setCheckState(t_eph::outdated);
297      return;
298    }
299
300    if (diff < MAXDIFF && diffC < MAXDIFF) {
301      if (dt != 0.0) {
302        eph->setCheckState(t_eph::ok);
303        ephL->setCheckState(t_eph::ok);
304      }
305    }
306    else {
307      if (ephL->checkState() == t_eph::ok) {
308        eph->setCheckState(t_eph::bad);
309      }
310    }
311  }
312}
Note: See TracBrowser for help on using the repository browser.