source: ntrip/trunk/BNS/bns.cpp@ 1068

Last change on this file since 1068 was 1068, checked in by mervart, 16 years ago

* empty log message *

File size: 12.1 KB
Line 
1/* -------------------------------------------------------------------------
2 * BKG NTRIP Server
3 * -------------------------------------------------------------------------
4 *
5 * Class: bns
6 *
7 * Purpose: This class implements the main application behaviour
8 *
9 * Author: L. Mervart
10 *
11 * Created: 29-Mar-2008
12 *
13 * Changes:
14 *
15 * -----------------------------------------------------------------------*/
16
17#include <math.h>
18#include <iostream>
19#include <newmatio.h>
20
21#include "bns.h"
22#include "bnsutils.h"
23#include "bnsrinex.h"
24#include "bnssp3.h"
25
26using namespace std;
27
28// Constructor
29////////////////////////////////////////////////////////////////////////////
30t_bns::t_bns(QObject* parent) : QThread(parent) {
31
32 this->setTerminationEnabled(true);
33
34 connect(this, SIGNAL(moveSocket(QThread*)),
35 this, SLOT(slotMoveSocket(QThread*)));
36
37 QSettings settings;
38
39 // Set Proxy (application-wide)
40 // ----------------------------
41 QString proxyHost = settings.value("proxyHost").toString();
42 int proxyPort = settings.value("proxyPort").toInt();
43
44 QNetworkProxy proxy;
45 if (proxyHost.isEmpty()) {
46 proxy.setType(QNetworkProxy::NoProxy);
47 }
48 else {
49 proxy.setType(QNetworkProxy::Socks5Proxy);
50 proxy.setHostName(proxyHost);
51 proxy.setPort(proxyPort);
52 }
53 QNetworkProxy::setApplicationProxy(proxy);
54
55 // Thread that handles broadcast ephemeris
56 // ---------------------------------------
57 _bnseph = new t_bnseph(parent);
58
59 connect(_bnseph, SIGNAL(newEph(t_eph*, int)),
60 this, SLOT(slotNewEph(t_eph*, int)));
61 connect(_bnseph, SIGNAL(newMessage(QByteArray)),
62 this, SLOT(slotMessage(const QByteArray)));
63 connect(_bnseph, SIGNAL(error(QByteArray)),
64 this, SLOT(slotError(const QByteArray)));
65
66 // Server listening for rtnet results
67 // ----------------------------------
68 _clkSocket = 0;
69 _clkServer = new QTcpServer;
70 _clkServer->listen(QHostAddress::Any, settings.value("clkPort").toInt());
71 connect(_clkServer, SIGNAL(newConnection()),this, SLOT(slotNewConnection()));
72
73 // Socket and file for outputting the results
74 // -------------------------------------------
75 for (int ic = 1; ic <= 2; ic++) {
76
77 QString mountpoint = settings.value("mountpoint_%1").toString().arg(ic);
78 if (!mountpoint.isEmpty()) {
79 QString outFileName = settings.value("outFile_%1").toString().arg(ic);
80 QString refSys = settings.value("refSys_%1").toString().arg(ic);
81
82 _caster.push_back(new t_bnscaster(mountpoint, outFileName, refSys));
83 connect(_caster.back(), SIGNAL(error(const QByteArray)),
84 this, SLOT(slotError(const QByteArray)));
85 connect(_caster.back(), SIGNAL(newMessage(const QByteArray)),
86 this, SLOT(slotMessage(const QByteArray)));
87 }
88 }
89
90 // Log File
91 // --------
92 QIODevice::OpenMode oMode;
93 if (Qt::CheckState(settings.value("fileAppend").toInt()) == Qt::Checked) {
94 oMode = QIODevice::WriteOnly | QIODevice::Unbuffered | QIODevice::Append;
95 }
96 else {
97 oMode = QIODevice::WriteOnly | QIODevice::Unbuffered;
98 }
99
100 QString logFileName = settings.value("logFile").toString();
101 if (logFileName.isEmpty()) {
102 _logFile = 0;
103 _logStream = 0;
104 }
105 else {
106 _logFile = new QFile(logFileName);
107 if (_logFile->open(oMode)) {
108 _logStream = new QTextStream(_logFile);
109 }
110 else {
111 _logStream = 0;
112 }
113 }
114
115 // RINEX writer
116 // ------------
117 if ( settings.value("rnxPath").toString().isEmpty() ) {
118 _rnx = 0;
119 }
120 else {
121 QString prep = "BNS";
122 QString ext = ".clk";
123 QString path = settings.value("rnxPath").toString();
124 QString intr = settings.value("rnxIntr").toString();
125 int sampl = settings.value("rnxSampl").toInt();
126 _rnx = new bnsRinex(prep, ext, path, intr, sampl);
127 }
128
129 // SP3 writer
130 // ----------
131 if ( settings.value("sp3Path").toString().isEmpty() ) {
132 _sp3 = 0;
133 }
134 else {
135 QString prep = "BNS";
136 QString ext = ".sp3";
137 QString path = settings.value("sp3Path").toString();
138 QString intr = settings.value("sp3Intr").toString();
139 int sampl = settings.value("sp3Sampl").toInt();
140 _sp3 = new bnsSP3(prep, ext, path, intr, sampl);
141 }
142}
143
144// Destructor
145////////////////////////////////////////////////////////////////////////////
146t_bns::~t_bns() {
147 deleteBnsEph();
148 delete _clkServer;
149 delete _clkSocket;
150 for (int ic = 0; ic < _caster.size(); ic++) {
151 delete _caster.at(ic);
152 }
153 delete _logStream;
154 delete _logFile;
155 QMapIterator<QString, t_ephPair*> it(_ephList);
156 while (it.hasNext()) {
157 it.next();
158 delete it.value();
159 }
160 delete _rnx;
161 delete _sp3;
162}
163
164// Delete bns thread
165////////////////////////////////////////////////////////////////////////////
166void t_bns::deleteBnsEph() {
167 if (_bnseph) {
168 _bnseph->terminate();
169 _bnseph->wait(100);
170 delete _bnseph;
171 _bnseph = 0;
172 }
173}
174
175// Write a Program Message
176////////////////////////////////////////////////////////////////////////////
177void t_bns::slotMessage(const QByteArray msg) {
178 if (_logStream) {
179 *_logStream << msg << endl;
180 _logStream->flush();
181 }
182 emit(newMessage(msg));
183}
184
185// Write a Program Message
186////////////////////////////////////////////////////////////////////////////
187void t_bns::slotError(const QByteArray msg) {
188 if (_logStream) {
189 *_logStream << msg << endl;
190 _logStream->flush();
191 }
192 deleteBnsEph();
193 emit(error(msg));
194}
195
196// New Connection
197////////////////////////////////////////////////////////////////////////////
198void t_bns::slotNewConnection() {
199 slotMessage("t_bns::slotNewConnection");
200 delete _clkSocket;
201 _clkSocket = _clkServer->nextPendingConnection();
202}
203
204//
205////////////////////////////////////////////////////////////////////////////
206void t_bns::slotNewEph(t_eph* ep, int nBytes) {
207
208 QMutexLocker locker(&_mutex);
209
210 emit(newEphBytes(nBytes));
211
212 t_ephPair* pair;
213 if ( !_ephList.contains(ep->prn()) ) {
214 pair = new t_ephPair();
215 _ephList.insert(ep->prn(), pair);
216 }
217 else {
218 pair = _ephList[ep->prn()];
219 }
220
221 if (pair->eph == 0) {
222 pair->eph = ep;
223 }
224 else {
225 if (ep->isNewerThan(pair->eph)) {
226 delete pair->oldEph;
227 pair->oldEph = pair->eph;
228 pair->eph = ep;
229 }
230 else {
231 delete ep;
232 }
233 }
234}
235
236// Start
237////////////////////////////////////////////////////////////////////////////
238void t_bns::run() {
239
240 slotMessage("============ Start BNS ============");
241
242 // Start Thread that retrieves broadcast Ephemeris
243 // -----------------------------------------------
244 _bnseph->start();
245
246 // Endless loop
247 // ------------
248 while (true) {
249
250 if (_clkSocket && _clkSocket->thread() != currentThread()) {
251 emit(moveSocket(currentThread()));
252 }
253
254 if (_clkSocket && _clkSocket->state() == QAbstractSocket::ConnectedState) {
255 if ( _clkSocket->canReadLine()) {
256 readEpoch();
257 }
258 else {
259 _clkSocket->waitForReadyRead(10);
260 }
261 }
262 else {
263 msleep(10);
264 }
265 }
266}
267
268//
269////////////////////////////////////////////////////////////////////////////
270void t_bns::readEpoch() {
271
272 QByteArray line = _clkSocket->readLine();
273
274 emit(newClkBytes(line.length()));
275
276 if (line.indexOf('*') == -1) {
277 return;
278 }
279
280 QTextStream in(line);
281
282 QString hlp;
283 int GPSweek, numSat;
284 double GPSweeks;
285
286 in >> hlp >> GPSweek >> GPSweeks >> numSat;
287
288 if (numSat > 0) {
289
290 QStringList prns;
291
292 for (int ic = 0; ic < _caster.size(); ic++) {
293 _caster.at(ic)->open();
294
295 for (int oldEph = 0; oldEph <= 0; oldEph++) { // TODO: handle old ephemeris
296
297 struct ClockOrbit co;
298 memset(&co, 0, sizeof(co));
299 co.GPSEpochTime = (int)GPSweeks;
300 co.GLONASSEpochTime = (int)fmod(GPSweeks, 86400.0);
301 co.ClockDataSupplied = 1;
302 co.OrbitDataSupplied = 1;
303 co.SatRefPoint = POINT_CENTER;
304 co.SatRefDatum = DATUM_ITRF;
305
306 for (int ii = 1; ii <= numSat; ii++) {
307
308 QString prn;
309 ColumnVector xx(5);
310 t_eph* ep = 0;
311
312 if (oldEph == 0) {
313 line = _clkSocket->readLine();
314 QTextStream in(line);
315 in >> prn;
316 prns << prn;
317 if ( _ephList.contains(prn) ) {
318 in >> xx(1) >> xx(2) >> xx(3) >> xx(4) >> xx(5); xx(4) *= 1e-6;
319
320 //// beg test (zero clock correction for Gerhard Wuebbena)
321 //// xx(4) -= xx(5) / 299792458.0;
322 //// end test
323
324 t_ephPair* pair = _ephList[prn];
325 pair->xx = xx;
326 ep = pair->eph;
327 }
328 }
329 else {
330 prn = prns[ii-1];
331 if ( _ephList.contains(prn) ) {
332 t_ephPair* pair = _ephList[prn];
333 prn = pair->eph->prn();
334 xx = pair->xx;
335 ep = pair->oldEph;
336 }
337 }
338
339 if (ep != 0) {
340 struct ClockOrbit::SatData* sd = 0;
341 if (prn[0] == 'G') {
342 sd = co.Sat + co.NumberOfGPSSat;
343 ++co.NumberOfGPSSat;
344 }
345 else if (prn[0] == 'R') {
346 sd = co.Sat + CLOCKORBIT_NUMGPS + co.NumberOfGLONASSSat;
347 ++co.NumberOfGLONASSSat;
348 }
349 if (sd) {
350 QString outLine;
351 processSatellite(oldEph, _caster.at(ic)->crdTrafo(), ep, GPSweek,
352 GPSweeks, prn, xx, sd, outLine);
353 _caster.at(ic)->printAscii(line);
354 }
355 }
356 }
357
358 if ( _caster.at(ic)->used() &&
359 (co.NumberOfGPSSat > 0 || co.NumberOfGLONASSSat > 0) ) {
360 char obuffer[CLOCKORBIT_BUFFERSIZE];
361 int len = MakeClockOrbit(&co, COTYPE_AUTO, 0, obuffer, sizeof(obuffer));
362 if (len > 0) {
363 emit(newOutBytes(len));
364 _caster.at(ic)->write(obuffer, len);
365 }
366 }
367 }
368 }
369 }
370}
371
372//
373////////////////////////////////////////////////////////////////////////////
374void t_bns::processSatellite(int oldEph, bool trafo, t_eph* ep, int GPSweek,
375 double GPSweeks, const QString& prn,
376 const ColumnVector& xx,
377 struct ClockOrbit::SatData* sd,
378 QString& outLine) {
379
380 ColumnVector xB(4);
381 ColumnVector vv(3);
382
383 ep->position(GPSweek, GPSweeks, xB, vv);
384
385 ColumnVector xyz = xx.Rows(1,3);
386 if (trafo) {
387 crdTrafo(GPSweek, xyz);
388 }
389
390 ColumnVector dx = xyz - xB.Rows(1,3);
391
392 double dClk = (xx(4) - xB(4)) * 299792458.0;
393 ColumnVector rsw(3);
394
395 XYZ_to_RSW(xB.Rows(1,3), vv, dx, rsw);
396
397 if (sd) {
398 sd->ID = prn.mid(1).toInt();
399 sd->IOD = ep->IOD();
400 sd->Clock.DeltaA0 = dClk;
401 sd->Orbit.DeltaRadial = rsw(1);
402 sd->Orbit.DeltaAlongTrack = rsw(2);
403 sd->Orbit.DeltaCrossTrack = rsw(3);
404 }
405
406 char oldCh = (oldEph ? '!' : ' ');
407 outLine.sprintf("%c %d %.1f %s %3d %10.3f %8.3f %8.3f %8.3f\n",
408 oldCh, GPSweek, GPSweeks, ep->prn().toAscii().data(),
409 ep->IOD(), dClk, rsw(1), rsw(2), rsw(3));
410
411 if (!oldEph) {
412 if (_rnx) {
413 _rnx->write(GPSweek, GPSweeks, prn, xx);
414 }
415 if (_sp3) {
416 _sp3->write(GPSweek, GPSweeks, prn, xx);
417 }
418 }
419}
420
421//
422////////////////////////////////////////////////////////////////////////////
423void t_bns::slotMoveSocket(QThread* tt) {
424 _clkSocket->setParent(0);
425 _clkSocket->moveToThread(tt);
426 slotMessage("bns::slotMoveSocket");
427}
428
429// Transform Coordinates IGS -> ETRF
430////////////////////////////////////////////////////////////////////////////
431void t_bns::crdTrafo(int GPSWeek, ColumnVector& xyz) {
432
433 ColumnVector dx(3);
434 dx(1) = 0.054;
435 dx(2) = 0.051;
436 dx(3) = -0.048;
437 const static double arcSec = 180.0 * 3600.0 / M_PI;
438 const static double ox = 0.000081 / arcSec;
439 const static double oy = 0.000490 / arcSec;
440 const static double oz = -0.000792 / arcSec;
441
442 Matrix rMat(3,3); rMat = 0.0;
443 rMat(1,2) = -oz;
444 rMat(1,3) = oy;
445 rMat(2,1) = oz;
446 rMat(2,3) = -ox;
447 rMat(3,1) = -oy;
448 rMat(3,2) = ox;
449
450 // Current epoch minus 1989.0 in years
451 // ------------------------------------
452 double dt = (GPSWeek - 469.0) / 365.2422 * 7.0;
453
454 xyz += dx + dt * rMat * xyz;
455}
Note: See TracBrowser for help on using the repository browser.