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

Last change on this file since 10565 was 10330, checked in by stuerze, 10 months ago

another test is added in PPP and combination mode to check if stored ephemerides were outdated and/or not updated in between

File size: 8.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) || eph->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 newEph->setCheckState(eph->checkState());
171 qq.push_back(newEph);
172 if (qq.size() > _maxQueueSize) {
173 delete qq.front();
174 qq.pop_front();
175 }
176 ephBufferChanged();
177 return success;
178 }
179 else {
180 delete newEph;
181 return failure;
182 }
183}
184
185//
186////////////////////////////////////////////////////////////////////////////
187void bncEphUser::checkEphemeris(t_eph* eph, bool realTime) {
188
189 if (!eph) {
190 return;
191 }
192
193 // Check whether the epoch is too far away the current time
194 // --------------------------------------------------------
195 if (realTime) {
196 QDateTime now = currentDateAndTimeGPS();
197 bncTime currentTime(now.toString(Qt::ISODate).toStdString());
198 if (outDatedBcep(eph, currentTime)) {
199 eph->setCheckState(t_eph::outdated);
200 return;
201 }
202 }
203
204 // Check health status
205 // -------------------
206 if (eph->isUnhealthy()) {
207 eph->setCheckState(t_eph::unhealthy);
208 return;
209 }
210
211 // Simple Check - check satellite radial distance
212 // ----------------------------------------------
213 ColumnVector xc(6);
214 ColumnVector vv(3);
215 if (eph->getCrd(eph->TOC(), xc, vv, false) != success) {
216 eph->setCheckState(t_eph::bad);
217 return;
218 }
219 double rr = xc.Rows(1,3).NormFrobenius();
220
221 const double MINDIST = 2.e7;
222 const double MAXDIST = 6.e7;
223 if (rr < MINDIST || rr > MAXDIST || std::isnan(rr)) {
224 eph->setCheckState(t_eph::bad);
225 return;
226 }
227
228 // Check consistency with older ephemeris
229 // --------------------------------------
230 const double MAXDIFF_INIT = 10.0;
231 const double MINDIFF = 0.005;
232 QString prn = QString(eph->prn().toInternalString().c_str());
233 t_eph* ephL = ephLast(prn);
234
235 // maxdiff adapted to individual systems
236 char sys = eph->prn().system();
237 double MAXDIFF = MAXDIFF_INIT;
238 if (sys == 'C' ||
239 sys == 'S' ) {
240 MAXDIFF *= 10.0;
241 }
242
243 if (ephL && ephL->checkState() != t_eph::bad) {
244 ColumnVector xcL(6);
245 ColumnVector vvL(3);
246 if (ephL->getCrd(eph->TOC(), xcL, vvL, false) != success) {
247 ephL->setCheckState(t_eph::bad);
248 return;
249 }
250
251 double diff = (xc.Rows(1,3) - xcL.Rows(1,3)).NormFrobenius();
252 double diffC = fabs(xc(4) - xcL(4)) * t_CST::c;
253
254 if (diff < MAXDIFF &&
255 diffC < MAXDIFF) {
256 if (diff < MINDIFF &&
257 diffC < MINDIFF &&
258 ephL->checkState() == t_eph::ok) {
259 // to prevent the same data sets with different TOC values
260 eph->setCheckState(t_eph::bad);
261 }
262 else {
263 eph->setCheckState(t_eph::ok);
264 ephL->setCheckState(t_eph::ok);
265 }
266 }
267 else {
268 if (ephL->checkState() == t_eph::ok) {
269 eph->setCheckState(t_eph::bad);
270 }
271 }
272
273 // some lines to allow update of ephemeris data sets after an outage
274 // -----------------------------------------------------------------
275 double dt = eph->TOC() - ephL->TOC();
276
277 // update interval: 2h
278 if (eph->type() == t_eph::GPS && dt > 7200.0) {
279 ephL->setCheckState(t_eph::outdated);
280 return;
281 }
282 // update interval: 3h
283 else if (eph->type() == t_eph::Galileo && dt > 10800.0) {
284 ephL->setCheckState(t_eph::outdated);
285 return;
286 }
287 // updated every 30 minutes + 5 min
288 else if (eph->type() == t_eph::GLONASS && dt > 2100.0) {
289 ephL->setCheckState(t_eph::outdated);
290 return;
291 }
292 // updated every ?
293 else if (eph->type() == t_eph::QZSS && dt > 3600.0) {
294 ephL->setCheckState(t_eph::outdated);
295 return;
296 }
297 // maximum update interval: 300 sec
298 else if (eph->type() == t_eph::SBAS && dt > 600.0) {
299 ephL->setCheckState(t_eph::outdated);
300 return;
301 }
302 // updates 1h + 5 min
303 else if (eph->type() == t_eph::BDS && dt > 3900.0) {
304 ephL->setCheckState(t_eph::outdated);
305 return;
306 }
307 // update interval: up to 24 hours
308 else if (eph->type() == t_eph::IRNSS && dt > 86400.0) {
309 ephL->setCheckState(t_eph::outdated);
310 return;
311 }
312 }
313}
314
Note: See TracBrowser for help on using the repository browser.