source: ntrip/trunk/BNC/src/bncephuser.cpp @ 7847

Last change on this file since 7847 was 7847, checked in by stuerze, 3 years ago

QZSS ephemeris time of validity is extended because it is encoded together with GPS ephemerides and the validity for QZSS orbit parameters is 7200 second at minimum

File size: 8.3 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  // Simple Check - check satellite radial distance
189  // ----------------------------------------------
190  ColumnVector xc(4);
191  ColumnVector vv(3);
192  if (eph->getCrd(eph->TOC(), xc, vv, false) != success) {
193    eph->setCheckState(t_eph::bad);
194    return;
195  }
196
197  double rr = xc.Rows(1,3).norm_Frobenius();
198
199  const double MINDIST = 2.e7;
200  const double MAXDIST = 6.e7;
201  if (rr < MINDIST || rr > MAXDIST) {
202    eph->setCheckState(t_eph::bad);
203    return;
204  }
205
206  // Check whether the epoch is too far away the current time
207  // --------------------------------------------------------
208  bncTime   toc = eph->TOC();
209  QDateTime now = currentDateAndTimeGPS();
210  bncTime currentTime(now.toString(Qt::ISODate).toStdString());
211  double timeDiff = fabs(toc - currentTime);
212
213  if      (eph->type() == t_eph::GPS  || t_eph::Galileo) {
214    if (timeDiff > 4*3600) { // update interval: 2h, data sets are valid for 4 hours
215      eph->setCheckState(t_eph::outdated);
216      return;
217    }
218  }
219  else if (eph->type() == t_eph::GLONASS) {
220    if (timeDiff > 1*3600) { // updated every 30 minutes
221      eph->setCheckState(t_eph::outdated);
222      return;
223    }
224  }
225  else if (eph->type() == t_eph::QZSS) {
226    if (timeDiff > 4*3600) { // orbit parameters are valid for 7200 seconds (at minimum)
227      eph->setCheckState(t_eph::outdated);
228      return;
229    }
230  }
231  else if (eph->type() == t_eph::SBAS) {
232    if (timeDiff > 600) { // maximum update interval: 300 sec
233      eph->setCheckState(t_eph::outdated);
234      return;
235    }
236  }
237  else if (eph->type() == t_eph::BDS) {
238    if (timeDiff > 6*3600) { // updates 1 (GEO) up to 6 hours
239      eph->setCheckState(t_eph::outdated);
240      return;
241    }
242  }
243
244
245  // Check consistency with older ephemerides
246  // ----------------------------------------
247  const double MAXDIFF = 1000.0;
248  QString      prn     = QString(eph->prn().toInternalString().c_str());
249  t_eph*       ephL    = ephLast(prn);
250  if (ephL) {
251    ColumnVector xcL(4);
252    ColumnVector vvL(3);
253    ephL->getCrd(eph->TOC(), xcL, vvL, false);
254
255    double dt   = eph->TOC() - ephL->TOC();
256    double diff = (xc.Rows(1,3) - xcL.Rows(1,3)).norm_Frobenius();
257
258    // some lines to allow update of ephemeris data sets after outage
259    if      (eph->type() == t_eph::GPS     && dt > 4*3600) {
260      ephL->setCheckState(t_eph::outdated);
261      return;
262    }
263    else if (eph->type() == t_eph::Galileo && dt > 4*3600) {
264      ephL->setCheckState(t_eph::outdated);
265      return;
266    }
267    else if (eph->type() == t_eph::GLONASS && dt > 1*3600) {
268      ephL->setCheckState(t_eph::outdated);
269      return;
270    }
271    else if (eph->type() == t_eph::QZSS    && dt > 4*3600) {
272      ephL->setCheckState(t_eph::outdated);
273      return;
274    }
275    else if  (eph->type() == t_eph::SBAS   && dt > 600)    {
276      ephL->setCheckState(t_eph::outdated);
277      return;
278    }
279    else if  (eph->type() == t_eph::BDS    && dt > 6*3600) {
280      ephL->setCheckState(t_eph::outdated);
281      return;
282    }
283
284    if (diff < MAXDIFF) {
285      if (dt != 0.0) {
286        eph->setCheckState(t_eph::ok);
287        ephL->setCheckState(t_eph::ok);
288      }
289    }
290    else {
291      if (ephL->checkState() == t_eph::ok) {
292        eph->setCheckState(t_eph::bad);
293      }
294    }
295  }
296}
Note: See TracBrowser for help on using the repository browser.