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

Last change on this file since 9249 was 9249, checked in by stuerze, 20 months ago

another check is added, to prevent the usage of not updated nav data sets during ssr upload

File size: 9.7 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 double rr = xc.Rows(1,3).norm_Frobenius();
208
209 const double MINDIST = 2.e7;
210 const double MAXDIST = 6.e7;
211 if (rr < MINDIST || rr > MAXDIST || std::isnan(rr)) {
212 eph->setCheckState(t_eph::bad);
213 return;
214 }
215
216 // Check whether the epoch is too far away the current time
217 // --------------------------------------------------------
218 if (realTime) {
219 bncTime toc = eph->TOC();
220 QDateTime now = currentDateAndTimeGPS();
221 bncTime currentTime(now.toString(Qt::ISODate).toStdString());
222 double dt = currentTime - toc;
223
224 // update interval: 2h, data sets are valid for 4 hours
225 if (eph->type() == t_eph::GPS && (dt > 4*3600.0 || dt < -2*3600.0)) {
226 eph->setCheckState(t_eph::outdated);
227 return;
228 }
229 // update interval: 3h, data sets are valid for 4 hours
230 else if (eph->type() == t_eph::Galileo && (dt > 4*3600.0 || dt < 0.0)) {
231 eph->setCheckState(t_eph::outdated);
232 return;
233 }
234 // updated every 30 minutes
235 else if (eph->type() == t_eph::GLONASS && (dt > 1*3600.0 || dt < -1800.0)) {
236 eph->setCheckState(t_eph::outdated);
237 return;
238 }
239 // orbit parameters are valid for 7200 seconds (minimum)
240 else if (eph->type() == t_eph::QZSS && (dt > 2*3600.0 || dt < -1*3600.0)) {
241 eph->setCheckState(t_eph::outdated);
242 return;
243 }
244 // maximum update interval: 300 sec
245 else if (eph->type() == t_eph::SBAS && (dt > 600 || dt < -300.0)) {
246 eph->setCheckState(t_eph::outdated);
247 return;
248 }
249 // updates 1h (GEO) up to 6 hours non-GEO
250 else if (eph->type() == t_eph::BDS && (dt > 6*3600 || dt < 0.0)) {
251 eph->setCheckState(t_eph::outdated);
252 return;
253 }
254 // update interval: up to 24 hours
255 else if (eph->type() == t_eph::IRNSS && fabs(dt > 24*3600.0)) {
256 eph->setCheckState(t_eph::outdated);
257 return;
258 }
259 }
260
261 // Check consistency with older ephemeris
262 // --------------------------------------
263 const double MAXDIFF = 1000.0;
264 const double MINDIFF = 1.0;
265 QString prn = QString(eph->prn().toInternalString().c_str());
266 t_eph* ephL = ephLast(prn);
267
268 if (ephL) {
269 ColumnVector xcL(6);
270 ColumnVector vvL(3);
271 ephL->getCrd(eph->TOC(), xcL, vvL, false);
272 double dt = eph->TOC() - ephL->TOC();
273 if (dt < 0.0) {
274 dt += 604800.0;
275 }
276 double diff = (xc.Rows(1,3) - xcL.Rows(1,3)).norm_Frobenius();
277 double diffC = fabs(xc(4) - xcL(4)) * t_CST::c;
278
279 // some lines to allow update of ephemeris data sets after an outage
280 // update interval: 2h,
281 if (eph->type() == t_eph::GPS && dt > 2*3600.0) {
282 ephL->setCheckState(t_eph::outdated);
283 return;
284 }
285 // update interval: 3h,
286 else if (eph->type() == t_eph::Galileo && dt > 3*3600.0) {
287 ephL->setCheckState(t_eph::outdated);
288 return;
289 }
290 // updated every 30 minutes
291 else if (eph->type() == t_eph::GLONASS && dt > 1800.0) {
292 ephL->setCheckState(t_eph::outdated);
293 return;
294 }
295 // updated every ?
296 else if (eph->type() == t_eph::QZSS && dt > 2*3600.0) {
297 ephL->setCheckState(t_eph::outdated);
298 return;
299 }
300 // maximum update interval: 300 sec
301 else if (eph->type() == t_eph::SBAS && dt > 300.0) {
302 ephL->setCheckState(t_eph::outdated);
303 return;
304 }
305 // updates 1h (GEO) up to 6 hours non-GEO
306 else if (eph->type() == t_eph::BDS && dt > 6*3600.0) {
307 ephL->setCheckState(t_eph::outdated);
308 return;
309 }
310 // update interval: up to 24 hours
311 else if (eph->type() == t_eph::IRNSS && dt > 24*3600.0) {
312 ephL->setCheckState(t_eph::outdated);
313 return;
314 }
315
316 if (diff < MAXDIFF && diffC < MAXDIFF) {
317 if (dt != 0.0) {
318 if (diff < MINDIFF && diffC < MINDIFF &&
319 ephL->checkState() == t_eph::ok) {
320 // to prevent the same data sets with different TOC values
321 eph->setCheckState(t_eph::bad);
322 }
323 else {
324 eph->setCheckState(t_eph::ok);
325 ephL->setCheckState(t_eph::ok);
326 }
327 }
328 }
329 else {
330 if (ephL->checkState() == t_eph::ok) {
331 eph->setCheckState(t_eph::bad);
332 }
333 }
334 }
335}
Note: See TracBrowser for help on using the repository browser.