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

Last change on this file since 8483 was 8483, checked in by stuerze, 11 months ago

SSR parameter clock rate, clock drift and URA are added within RTNET format

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 <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  checkEphemeris(eph, realTime);
123
124  const t_ephGPS*     ephGPS     = dynamic_cast<const t_ephGPS*>(eph);
125  const t_ephGlo*     ephGlo     = dynamic_cast<const t_ephGlo*>(eph);
126  const t_ephGal*     ephGal     = dynamic_cast<const t_ephGal*>(eph);
127  const t_ephSBAS*    ephSBAS    = dynamic_cast<const t_ephSBAS*>(eph);
128  const t_ephBDS*     ephBDS     = dynamic_cast<const t_ephBDS*>(eph);
129
130  t_eph* newEph = 0;
131
132  if      (ephGPS) {
133    newEph = new t_ephGPS(*ephGPS);
134  }
135  else if (ephGlo) {
136    newEph = new t_ephGlo(*ephGlo);
137  }
138  else if (ephGal) {
139    newEph = new t_ephGal(*ephGal);
140  }
141  else if (ephSBAS) {
142    newEph = new t_ephSBAS(*ephSBAS);
143  }
144  else if (ephBDS) {
145    newEph = new t_ephBDS(*ephBDS);
146  }
147  else {
148    return failure;
149  }
150
151  QString prn(newEph->prn().toInternalString().c_str());
152
153  const t_eph* ephOld = ephLast(prn);
154
155  if ((ephOld == 0 || newEph->isNewerThan(ephOld)) &&
156      (eph->checkState() != t_eph::bad &&
157       eph->checkState() != t_eph::outdated)) {
158    deque<t_eph*>& qq = _eph[prn];
159    qq.push_back(newEph);
160    if (qq.size() > _maxQueueSize) {
161      delete qq.front();
162      qq.pop_front();
163    }
164    ephBufferChanged();
165    return success;
166  }
167  else {
168    delete newEph;
169    return failure;
170  }
171}
172
173//
174////////////////////////////////////////////////////////////////////////////
175void bncEphUser::checkEphemeris(t_eph* eph, bool realTime) {
176
177  if (!eph || eph->checkState() == t_eph::ok || eph->checkState() == t_eph::bad) {
178    return;
179  }
180
181  // Check health status
182  // -------------------
183  if (eph->isUnhealthy()) {
184    eph->setCheckState(t_eph::unhealthy);
185  }
186
187  // Simple Check - check satellite radial distance
188  // ----------------------------------------------
189  ColumnVector xc(7);
190  ColumnVector vv(3);
191  if (eph->getCrd(eph->TOC(), xc, vv, false) != success) {
192    eph->setCheckState(t_eph::bad);
193    return;
194  }
195
196  double rr = xc.Rows(1,3).norm_Frobenius();
197
198  const double MINDIST = 2.e7;
199  const double MAXDIST = 6.e7;
200  if (rr < MINDIST || rr > MAXDIST || std::isnan(rr)) {
201    eph->setCheckState(t_eph::bad);
202    return;
203  }
204
205  // Check whether the epoch is too far away the current time
206  // --------------------------------------------------------
207  if (realTime) {
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 && timeDiff > 4 * 3600) { // update interval: 2h, data sets are valid for 4 hours
214      eph->setCheckState(t_eph::outdated);
215      return;
216    }
217    else if (eph->type() == t_eph::Galileo && timeDiff > 4 * 3600) { // update interval: 2h, data sets are valid for 4 hours
218      eph->setCheckState(t_eph::outdated);
219      return;
220    }
221    else if (eph->type() == t_eph::GLONASS && timeDiff > 1 * 3600) { // updated every 30 minutes
222      eph->setCheckState(t_eph::outdated);
223      return;
224    }
225    else if (eph->type() == t_eph::QZSS && timeDiff > 4 * 3600) { // orbit parameters are valid for 7200 seconds (at minimum)
226      eph->setCheckState(t_eph::outdated);
227      return;
228    }
229    else if (eph->type() == t_eph::SBAS && timeDiff > 600) { // maximum update interval: 300 sec
230      eph->setCheckState(t_eph::outdated);
231      return;
232    }
233    else if (eph->type() == t_eph::BDS && timeDiff > 6 * 3600) { // updates (GEO) up to 6 hours
234      eph->setCheckState(t_eph::outdated);
235      return;
236    }
237    else if (eph->type() == t_eph::IRNSS && timeDiff > 24 * 3600) { // update interval: up to 24 hours
238      eph->setCheckState(t_eph::outdated);
239      return;
240    }
241  }
242
243  // Check consistency with older ephemerides
244  // ----------------------------------------
245  const double MAXDIFF = 1000.0;
246  QString      prn     = QString(eph->prn().toInternalString().c_str());
247  t_eph*       ephL    = ephLast(prn);
248
249  if (ephL) {
250    ColumnVector xcL(4);
251    ColumnVector vvL(3);
252    ephL->getCrd(eph->TOC(), xcL, vvL, false);
253
254    double dt    = fabs(eph->TOC() - ephL->TOC());
255    double diff  = (xc.Rows(1,3) - xcL.Rows(1,3)).norm_Frobenius();
256    double diffC = fabs(xc(4) - xcL(4)) * t_CST::c;
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    else if  (eph->type() == t_eph::IRNSS  && dt > 24*3600) {
284      ephL->setCheckState(t_eph::outdated);
285      return;
286    }
287
288    if (diff < MAXDIFF && diffC < MAXDIFF) {
289      if (dt != 0.0) {
290        eph->setCheckState(t_eph::ok);
291        ephL->setCheckState(t_eph::ok);
292      }
293    }
294    else {
295      if (ephL->checkState() == t_eph::ok) {
296        eph->setCheckState(t_eph::bad);
297      }
298    }
299  }
300}
Note: See TracBrowser for help on using the repository browser.