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

Last change on this file since 8216 was 8216, checked in by stuerze, 22 months ago

unhealthy satellites are reported within log file but are remainig in stream and file output

File size: 8.9 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 <iostream>
41
42#include "bncephuser.h"
43#include "bnccore.h"
44
45using namespace std;
46
47// Constructor
48////////////////////////////////////////////////////////////////////////////
49bncEphUser::bncEphUser(bool connectSlots) {
50  if (connectSlots) {
51    connect(BNC_CORE, SIGNAL(newGPSEph(t_ephGPS)),
52            this, SLOT(slotNewGPSEph(t_ephGPS)), Qt::DirectConnection);
53
54    connect(BNC_CORE, SIGNAL(newGlonassEph(t_ephGlo)),
55            this, SLOT(slotNewGlonassEph(t_ephGlo)), Qt::DirectConnection);
56
57    connect(BNC_CORE, SIGNAL(newGalileoEph(t_ephGal)),
58            this, SLOT(slotNewGalileoEph(t_ephGal)), Qt::DirectConnection);
59
60    connect(BNC_CORE, SIGNAL(newSBASEph(t_ephSBAS)),
61            this, SLOT(slotNewSBASEph(t_ephSBAS)), Qt::DirectConnection);
62
63    connect(BNC_CORE, SIGNAL(newBDSEph(t_ephBDS)),
64            this, SLOT(slotNewBDSEph(t_ephBDS)), Qt::DirectConnection);
65  }
66}
67
68// Destructor
69////////////////////////////////////////////////////////////////////////////
70bncEphUser::~bncEphUser() {
71  QMapIterator<QString, deque<t_eph*> > it(_eph);
72  while (it.hasNext()) {
73    it.next();
74    const deque<t_eph*>& qq = it.value();
75    for (unsigned ii = 0; ii < qq.size(); ii++) {
76      delete qq[ii];
77    }
78  }
79}
80
81// New GPS Ephemeris
82////////////////////////////////////////////////////////////////////////////
83void bncEphUser::slotNewGPSEph(t_ephGPS eph) {
84  putNewEph(&eph, false);
85}
86
87// New Glonass Ephemeris
88////////////////////////////////////////////////////////////////////////////
89void bncEphUser::slotNewGlonassEph(t_ephGlo eph) {
90  putNewEph(&eph, false);
91}
92
93// New Galileo Ephemeris
94////////////////////////////////////////////////////////////////////////////
95void bncEphUser::slotNewGalileoEph(t_ephGal eph) {
96  putNewEph(&eph, false);
97}
98
99// New SBAS Ephemeris
100////////////////////////////////////////////////////////////////////////////
101void bncEphUser::slotNewSBASEph(t_ephSBAS eph) {
102  putNewEph(&eph, false);
103}
104
105// New BDS Ephemeris
106////////////////////////////////////////////////////////////////////////////
107void bncEphUser::slotNewBDSEph(t_ephBDS eph) {
108  putNewEph(&eph, false);
109}
110
111//
112////////////////////////////////////////////////////////////////////////////
113t_irc bncEphUser::putNewEph(t_eph* eph, bool check) {
114
115  QMutexLocker locker(&_mutex);
116
117  if (eph == 0) {
118    return failure;
119  }
120
121  if (check) {
122    checkEphemeris(eph);
123  }
124
125  const t_ephGPS*     ephGPS     = dynamic_cast<const t_ephGPS*>(eph);
126  const t_ephGlo*     ephGlo     = dynamic_cast<const t_ephGlo*>(eph);
127  const t_ephGal*     ephGal     = dynamic_cast<const t_ephGal*>(eph);
128  const t_ephSBAS*    ephSBAS    = dynamic_cast<const t_ephSBAS*>(eph);
129  const t_ephBDS*     ephBDS     = dynamic_cast<const t_ephBDS*>(eph);
130
131  t_eph* newEph = 0;
132
133  if      (ephGPS) {
134    newEph = new t_ephGPS(*ephGPS);
135  }
136  else if (ephGlo) {
137    newEph = new t_ephGlo(*ephGlo);
138  }
139  else if (ephGal) {
140    newEph = new t_ephGal(*ephGal);
141  }
142  else if (ephSBAS) {
143    newEph = new t_ephSBAS(*ephSBAS);
144  }
145  else if (ephBDS) {
146    newEph = new t_ephBDS(*ephBDS);
147  }
148  else {
149    return failure;
150  }
151
152  QString prn(newEph->prn().toInternalString().c_str());
153
154  const t_eph* ephOld = ephLast(prn);
155
156  if (ephOld &&
157      (ephOld->checkState() == t_eph::bad ||
158       ephOld->checkState() == t_eph::outdated)) {
159    ephOld = 0;
160  }
161
162  if ((ephOld == 0 || newEph->isNewerThan(ephOld)) &&
163      (eph->checkState() != t_eph::bad &&
164       eph->checkState() != t_eph::outdated)) {
165    deque<t_eph*>& qq = _eph[prn];
166    qq.push_back(newEph);
167    if (qq.size() > _maxQueueSize) {
168      delete qq.front();
169      qq.pop_front();
170    }
171    ephBufferChanged();
172    return success;
173  }
174  else {
175    delete newEph;
176    return failure;
177  }
178}
179
180//
181////////////////////////////////////////////////////////////////////////////
182void bncEphUser::checkEphemeris(t_eph* eph) {
183
184  if (!eph || eph->checkState() == t_eph::ok || eph->checkState() == t_eph::bad) {
185    return;
186  }
187
188  // Check health status
189  // -------------------
190  if (eph->isUnhealthy()) {
191    eph->setCheckState(t_eph::unhealthy);
192  }
193
194  // Simple Check - check satellite radial distance
195  // ----------------------------------------------
196  ColumnVector xc(4);
197  ColumnVector vv(3);
198  if (eph->getCrd(eph->TOC(), xc, vv, false) != success) {
199    eph->setCheckState(t_eph::bad);
200    return;
201  }
202
203  double rr = xc.Rows(1,3).norm_Frobenius();
204
205  const double MINDIST = 2.e7;
206  const double MAXDIST = 6.e7;
207  if (rr < MINDIST || rr > MAXDIST || isnan(rr)) {
208    eph->setCheckState(t_eph::bad);
209    return;
210  }
211
212  // Check whether the epoch is too far away the current time
213  // --------------------------------------------------------
214  bncTime   toc = eph->TOC();
215  QDateTime now = currentDateAndTimeGPS();
216  bncTime currentTime(now.toString(Qt::ISODate).toStdString());
217  double timeDiff = fabs(toc - currentTime);
218
219  if      (eph->type() == t_eph::GPS     && timeDiff > 4*3600) { // update interval: 2h, data sets are valid for 4 hours
220    eph->setCheckState(t_eph::outdated);
221    return;
222  }
223  else if (eph->type() == t_eph::Galileo && timeDiff > 4*3600) { // update interval: 2h, data sets are valid for 4 hours
224    eph->setCheckState(t_eph::outdated);
225    return;
226  }
227  else if (eph->type() == t_eph::GLONASS && timeDiff > 1*3600) { // updated every 30 minutes
228    eph->setCheckState(t_eph::outdated);
229    return;
230  }
231  else if (eph->type() == t_eph::QZSS    && timeDiff > 4*3600) { // orbit parameters are valid for 7200 seconds (at minimum)
232    eph->setCheckState(t_eph::outdated);
233    return;
234  }
235  else if (eph->type() == t_eph::SBAS    && timeDiff > 600) { // maximum update interval: 300 sec
236    eph->setCheckState(t_eph::outdated);
237    return;
238  }
239  else if (eph->type() == t_eph::BDS     && timeDiff > 6*3600) { // updates (GEO) up to 6 hours
240    eph->setCheckState(t_eph::outdated);
241    return;
242  }
243  else if (eph->type() == t_eph::IRNSS   && timeDiff > 24*3600) { // update interval: up to 24 hours
244    eph->setCheckState(t_eph::outdated);
245    return;
246  }
247
248  // Check consistency with older ephemerides
249  // ----------------------------------------
250  const double MAXDIFF = 1000.0;
251  QString      prn     = QString(eph->prn().toInternalString().c_str());
252  t_eph*       ephL    = ephLast(prn);
253
254  if (ephL) {
255    ColumnVector xcL(4);
256    ColumnVector vvL(3);
257    ephL->getCrd(eph->TOC(), xcL, vvL, false);
258
259    double dt    = fabs(eph->TOC() - ephL->TOC());
260    double diff  = (xc.Rows(1,3) - xcL.Rows(1,3)).norm_Frobenius();
261    double diffC = fabs(xc(4) - xcL(4)) * t_CST::c;
262
263    // some lines to allow update of ephemeris data sets after outage
264    if      (eph->type() == t_eph::GPS     && dt > 4*3600) {
265      ephL->setCheckState(t_eph::outdated);
266      return;
267    }
268    else if (eph->type() == t_eph::Galileo && dt > 4*3600) {
269      ephL->setCheckState(t_eph::outdated);
270      return;
271    }
272    else if (eph->type() == t_eph::GLONASS && dt > 1*3600) {
273      ephL->setCheckState(t_eph::outdated);
274      return;
275    }
276    else if (eph->type() == t_eph::QZSS    && dt > 4*3600) {
277      ephL->setCheckState(t_eph::outdated);
278      return;
279    }
280    else if  (eph->type() == t_eph::SBAS   && dt > 600)    {
281      ephL->setCheckState(t_eph::outdated);
282      return;
283    }
284    else if  (eph->type() == t_eph::BDS    && dt > 6*3600) {
285      ephL->setCheckState(t_eph::outdated);
286      return;
287    }
288    else if  (eph->type() == t_eph::IRNSS  && dt > 24*3600) {
289      ephL->setCheckState(t_eph::outdated);
290      return;
291    }
292
293    if (diff < MAXDIFF && diffC < MAXDIFF) {
294      if (dt != 0.0) {
295        eph->setCheckState(t_eph::ok);
296        ephL->setCheckState(t_eph::ok);
297      }
298    }
299    else {
300      if (ephL->checkState() == t_eph::ok) {
301        eph->setCheckState(t_eph::bad);
302      }
303    }
304  }
305}
Note: See TracBrowser for help on using the repository browser.