source: ntrip/trunk/BNC/src/upload/bncrtnetuploadcaster.cpp@ 6325

Last change on this file since 6325 was 6139, checked in by mervart, 10 years ago
File size: 24.3 KB
RevLine 
[3222]1/* -------------------------------------------------------------------------
2 * BKG NTRIP Server
3 * -------------------------------------------------------------------------
4 *
[3224]5 * Class: bncRtnetUploadCaster
[3222]6 *
7 * Purpose: Connection to NTRIP Caster
8 *
9 * Author: L. Mervart
10 *
11 * Created: 29-Mar-2011
12 *
[5662]13 * Changes:
[3222]14 *
15 * -----------------------------------------------------------------------*/
16
17#include <math.h>
[5662]18#include "bncrtnetuploadcaster.h"
[3222]19#include "bncsettings.h"
[3224]20#include "bncephuser.h"
[3222]21#include "bncclockrinex.h"
22#include "bncsp3.h"
23
[6139]24extern "C" {
25# include "rtcm3torinex.h"
26}
27
[3222]28using namespace std;
29
30// Constructor
31////////////////////////////////////////////////////////////////////////////
[3224]32bncRtnetUploadCaster::bncRtnetUploadCaster(const QString& mountpoint,
[3222]33 const QString& outHost, int outPort,
[5662]34 const QString& password,
35 const QString& crdTrafo, bool CoM,
[3222]36 const QString& sp3FileName,
37 const QString& rnxFileName,
[4111]38 int PID, int SID, int IOD, int iRow) :
[3273]39 bncUploadCaster(mountpoint, outHost, outPort, password, iRow, 0) {
[3224]40
[5130]41 if (!outHost.isEmpty()) {
42 _casterID += outHost;
43 }
44 if (!crdTrafo.isEmpty()) {
45 _casterID += " " + crdTrafo;
46 }
47 if (!sp3FileName.isEmpty()) {
48 _casterID += " " + sp3FileName;
49 }
50 if (!rnxFileName.isEmpty()) {
51 _casterID += " " + rnxFileName;
52 }
53
[3222]54 _crdTrafo = crdTrafo;
55 _CoM = CoM;
[4111]56 _PID = PID;
57 _SID = SID;
58 _IOD = IOD;
[3222]59
[3224]60 // Member that receives the ephemeris
61 // ----------------------------------
62 _ephUser = new bncEphUser();
[3222]63
[3272]64 bncSettings settings;
65 QString intr = settings.value("uploadIntr").toString();
[4174]66
67 _samplRtcmEphCorr = settings.value("uploadSamplRtcmEphCorr").toDouble();
[4542]68 int samplClkRnx = settings.value("uploadSamplClkRnx").toInt();
69 int samplSp3 = settings.value("uploadSamplSp3").toInt() * 60;
[4174]70
71 if (_samplRtcmEphCorr == 0.0) {
[3753]72 _usedEph = 0;
73 }
74 else {
75 _usedEph = new QMap<QString, t_eph*>;
76 }
[3272]77
[3222]78 // RINEX writer
79 // ------------
80 if (!rnxFileName.isEmpty()) {
[4174]81 _rnx = new bncClockRinex(rnxFileName, intr, samplClkRnx);
[3222]82 }
83 else {
84 _rnx = 0;
85 }
86
87 // SP3 writer
88 // ----------
89 if (!sp3FileName.isEmpty()) {
[4174]90 _sp3 = new bncSP3(sp3FileName, intr, samplSp3);
[3222]91 }
92 else {
93 _sp3 = 0;
94 }
95
96 // Set Transformation Parameters
97 // -----------------------------
98 if (_crdTrafo == "ETRF2000") {
[3890]99 _dx = 0.0521;
100 _dy = 0.0493;
101 _dz = -0.0585;
102 _dxr = 0.0001;
[3222]103 _dyr = 0.0001;
104 _dzr = -0.0018;
105 _ox = 0.000891;
106 _oy = 0.005390;
107 _oz = -0.008712;
108 _oxr = 0.000081;
109 _oyr = 0.000490;
110 _ozr = -0.000792;
[3890]111 _sc = 1.34;
[3222]112 _scr = 0.08;
113 _t0 = 2000.0;
114 }
115 else if (_crdTrafo == "NAD83") {
[5345]116 _dx = 0.99343;
117 _dy = -1.90331;
118 _dz = -0.52655;
119 _dxr = 0.00079;
120 _dyr = -0.00060;
121 _dzr = -0.00134;
122 _ox = -0.02591467;
123 _oy = -0.00942645;
124 _oz = -0.01159935;
125 _oxr = -0.00006667;
126 _oyr = 0.00075744;
127 _ozr = 0.00005133;
128 _sc = 1.71504;
[5348]129 _scr = -0.10201;
[5345]130 _t0 = 1997.0;
[3222]131 }
132 else if (_crdTrafo == "GDA94") {
[4963]133 _dx = -0.08468;
134 _dy = -0.01942;
135 _dz = 0.03201;
136 _dxr = 0.00142;
137 _dyr = 0.00134;
138 _dzr = 0.00090;
139 _ox = 0.0004254;
140 _oy = -0.0022578;
141 _oz = -0.0024015;
142 _oxr = -0.0015461;
143 _oyr = -0.0011820;
144 _ozr = -0.0011551;
145 _sc = 9.710;
146 _scr = 0.109;
[3222]147 _t0 = 1994.0;
148 }
149 else if (_crdTrafo == "SIRGAS2000") {
[4956]150 _dx = 0.0020;
151 _dy = 0.0041;
152 _dz = 0.0039;
[3222]153 _dxr = 0.0000;
154 _dyr = 0.0000;
155 _dzr = 0.0000;
[4956]156 _ox = 0.000170;
157 _oy = -0.000030;
158 _oz = 0.000070;
[3222]159 _oxr = 0.000000;
160 _oyr = 0.000000;
161 _ozr = 0.000000;
[5662]162 _sc = -1.000;
[3222]163 _scr = 0.000;
164 _t0 = 0000.0;
165 }
166 else if (_crdTrafo == "SIRGAS95") {
167 _dx = 0.0077;
168 _dy = 0.0058;
169 _dz = -0.0138;
170 _dxr = 0.0000;
171 _dyr = 0.0000;
172 _dzr = 0.0000;
173 _ox = 0.000000;
174 _oy = 0.000000;
175 _oz = -0.000030;
176 _oxr = 0.000000;
177 _oyr = 0.000000;
178 _ozr = 0.000000;
179 _sc = 1.570;
180 _scr = 0.000;
181 _t0 = 0000.0;
182 }
[5347]183 else if (_crdTrafo == "DREF91") {
[5340]184 _dx = -0.0118;
185 _dy = 0.1432;
186 _dz = -0.1117;
187 _dxr = 0.0001;
188 _dyr = 0.0001;
189 _dzr = -0.0018;
190 _ox = 0.003291;
191 _oy = 0.006190;
192 _oz = -0.011012;
193 _oxr = 0.000081;
194 _oyr = 0.000490;
195 _ozr = -0.000792;
196 _sc = 12.24;
197 _scr = 0.08;
198 _t0 = 2000.0;
199 }
[3222]200 else if (_crdTrafo == "Custom") {
201 _dx = settings.value("trafo_dx").toDouble();
202 _dy = settings.value("trafo_dy").toDouble();
203 _dz = settings.value("trafo_dz").toDouble();
204 _dxr = settings.value("trafo_dxr").toDouble();
205 _dyr = settings.value("trafo_dyr").toDouble();
206 _dzr = settings.value("trafo_dzr").toDouble();
207 _ox = settings.value("trafo_ox").toDouble();
208 _oy = settings.value("trafo_oy").toDouble();
209 _oz = settings.value("trafo_oz").toDouble();
210 _oxr = settings.value("trafo_oxr").toDouble();
211 _oyr = settings.value("trafo_oyr").toDouble();
212 _ozr = settings.value("trafo_ozr").toDouble();
213 _sc = settings.value("trafo_sc").toDouble();
214 _scr = settings.value("trafo_scr").toDouble();
215 _t0 = settings.value("trafo_t0").toDouble();
216 }
217}
218
219// Destructor
220////////////////////////////////////////////////////////////////////////////
[3224]221bncRtnetUploadCaster::~bncRtnetUploadCaster() {
[3222]222 if (isRunning()) {
223 wait();
224 }
225 delete _rnx;
226 delete _sp3;
227 delete _ephUser;
[3753]228 delete _usedEph;
[3222]229}
230
[5662]231//
[3222]232////////////////////////////////////////////////////////////////////////////
[3224]233void bncRtnetUploadCaster::decodeRtnetStream(char* buffer, int bufLen) {
[5662]234
[3222]235 QMutexLocker locker(&_mutex);
236
[3230]237 // Append to internal buffer
238 // -------------------------
[3222]239 _rtnetStreamBuffer.append(QByteArray(buffer, bufLen));
[3230]240
241 // Select buffer part that contains last epoch
242 // -------------------------------------------
243 QStringList lines;
244 int iEpoBeg = _rtnetStreamBuffer.lastIndexOf('*'); // begin of last epoch
245 if (iEpoBeg == -1) {
[3226]246 _rtnetStreamBuffer.clear();
247 return;
[3222]248 }
[3230]249 _rtnetStreamBuffer = _rtnetStreamBuffer.mid(iEpoBeg);
250
251 int iEpoEnd = _rtnetStreamBuffer.lastIndexOf("EOE"); // end of last epoch
252 if (iEpoEnd == -1) {
253 return;
254 }
[3226]255 else {
[3230]256 lines = _rtnetStreamBuffer.left(iEpoEnd).split('\n', QString::SkipEmptyParts);
257 _rtnetStreamBuffer = _rtnetStreamBuffer.mid(iEpoEnd+3);
[3226]258 }
[3222]259
[3226]260 if (lines.size() < 2) {
[3222]261 return;
262 }
263
[3226]264 // Keep the last unfinished line in buffer
265 // ---------------------------------------
266 int iLastEOL = _rtnetStreamBuffer.lastIndexOf('\n');
267 if (iLastEOL != -1) {
268 _rtnetStreamBuffer = _rtnetStreamBuffer.mid(iLastEOL+1);
269 }
270
271 // Read first line (with epoch time)
272 // ---------------------------------
273 QTextStream in(lines[0].toAscii());
274 QString hlp;
275 int year, month, day, hour, min;
276 double sec;
277 in >> hlp >> year >> month >> day >> hour >> min >> sec;
278 bncTime epoTime; epoTime.set( year, month, day, hour, min, sec);
279
[5662]280 emit(newMessage("bncRtnetUploadCaster: decode " +
[5131]281 QByteArray(epoTime.datestr().c_str()) + " " +
[5662]282 QByteArray(epoTime.timestr().c_str()) + " " +
[5132]283 _casterID.toAscii(), false));
[4808]284
[3222]285 struct ClockOrbit co;
286 memset(&co, 0, sizeof(co));
[5672]287 co.EpochTime[CLOCKORBIT_SATGPS] = static_cast<int>(epoTime.gpssec());
288 double gt = epoTime.gpssec() + 3 * 3600 - gnumleap(year, month, day);
289 co.EpochTime[CLOCKORBIT_SATGLONASS] = static_cast<int>(fmod(gt, 86400.0));
290
[5666]291 co.Supplied[COBOFS_CLOCK] = 1;
292 co.Supplied[COBOFS_ORBIT] = 1;
[3222]293 co.SatRefDatum = DATUM_ITRF;
[4111]294 co.SSRIOD = _IOD;
295 co.SSRProviderID = _PID; // 256 .. BKG, 257 ... EUREF
296 co.SSRSolutionID = _SID;
[5662]297
[5666]298 struct CodeBias bias;
[3222]299 memset(&bias, 0, sizeof(bias));
[5666]300 bias.EpochTime[CLOCKORBIT_SATGPS] = co.EpochTime[CLOCKORBIT_SATGPS];
301 bias.EpochTime[CLOCKORBIT_SATGLONASS] = co.EpochTime[CLOCKORBIT_SATGLONASS];
[5662]302
[4753]303 // Default Update Interval
304 // -----------------------
[4754]305 int clkUpdInd = 2; // 5 sec
306 int ephUpdInd = clkUpdInd; // default
307 if (_samplRtcmEphCorr == 10.0) {
308 ephUpdInd = 3;
309 }
310 else if (_samplRtcmEphCorr == 15.0) {
311 ephUpdInd = 4;
312 }
313 else if (_samplRtcmEphCorr == 30.0) {
314 ephUpdInd = 5;
315 }
316 else if (_samplRtcmEphCorr == 60.0) {
317 ephUpdInd = 6;
318 }
319 else if (_samplRtcmEphCorr == 120.0) {
320 ephUpdInd = 7;
321 }
322 else if (_samplRtcmEphCorr == 240.0) {
323 ephUpdInd = 8;
324 }
325 else if (_samplRtcmEphCorr == 300.0) {
326 ephUpdInd = 9;
327 }
328 else if (_samplRtcmEphCorr == 600.0) {
329 ephUpdInd = 10;
330 }
331 else if (_samplRtcmEphCorr == 900.0) {
332 ephUpdInd = 11;
333 }
[4753]334
[4754]335 co.UpdateInterval = clkUpdInd;
336 bias.UpdateInterval = clkUpdInd;
[4753]337
[3226]338 for (int ii = 1; ii < lines.size(); ii++) {
[5662]339
[3222]340 QString prn;
[4991]341 ColumnVector rtnAPC;
342 ColumnVector rtnVel;
343 ColumnVector rtnCoM;
344 double rtnClk;
[5662]345
[3222]346 QTextStream in(lines[ii].toAscii());
347
348 in >> prn;
349
[3753]350 t_eph* eph = 0;
[3222]351 const bncEphUser::t_ephPair* ephPair = _ephUser->ephPair(prn);
352 if (ephPair) {
353
[3754]354 eph = ephPair->last;
355
[4098]356 // Use previous ephemeris if the last one is too recent
357 // ----------------------------------------------------
358 const int MINAGE = 60; // seconds
359 if (ephPair->prev && eph->receptDateTime().isValid() &&
360 eph->receptDateTime().secsTo(currentDateAndTimeGPS()) < MINAGE) {
361 eph = ephPair->prev;
362 }
[3754]363
[3753]364 // Make sure the clock messages refer to same IOD as orbit messages
365 // ----------------------------------------------------------------
366 if (_usedEph) {
[4174]367 if (fmod(epoTime.gpssec(), _samplRtcmEphCorr) == 0.0) {
[3753]368 (*_usedEph)[prn] = eph;
369 }
370 else {
371 eph = 0;
372 if (_usedEph->contains(prn)) {
373 t_eph* usedEph = _usedEph->value(prn);
374 if (usedEph == ephPair->last) {
375 eph = ephPair->last;
376 }
377 else if (usedEph == ephPair->prev) {
378 eph = ephPair->prev;
379 }
380 }
381 }
382 }
383 }
384
385 if (eph) {
386
[5503]387 QMap<QString, double> codeBiases;
388
[4991]389 while (true) {
390 QString key;
391 int numVal = 0;
392 in >> key >> numVal;
393 if (in.status() != QTextStream::Ok) {
394 break;
395 }
396 if (key == "APC") {
397 rtnAPC.ReSize(3);
398 in >> rtnAPC[0] >> rtnAPC[1] >> rtnAPC[2];
399 }
400 else if (key == "Clk") {
401 in >> rtnClk;
402 }
403 else if (key == "Vel") {
404 rtnVel.ReSize(3);
405 in >> rtnVel[0] >> rtnVel[1] >> rtnVel[2];
406 }
407 else if (key == "CoM") {
408 rtnCoM.ReSize(3);
409 in >> rtnCoM[0] >> rtnCoM[1] >> rtnCoM[2];
410 }
[5503]411 else if (key == "CodeBias") {
412 for (int ii = 0; ii < numVal; ii++) {
413 QString type;
414 double value;
415 in >> type >> value;
416 codeBiases[type] = value;
417 }
418 }
[4991]419 else {
420 for (int ii = 0; ii < numVal; ii++) {
421 double dummy;
422 in >> dummy;
423 }
424 }
[5662]425 }
[3222]426 struct ClockOrbit::SatData* sd = 0;
427 if (prn[0] == 'G') {
[5666]428 sd = co.Sat + co.NumberOfSat[CLOCKORBIT_SATGPS];
429 ++co.NumberOfSat[CLOCKORBIT_SATGPS];
[3222]430 }
431 else if (prn[0] == 'R') {
[5666]432 sd = co.Sat + CLOCKORBIT_NUMGPS + co.NumberOfSat[CLOCKORBIT_SATGLONASS];
433 ++co.NumberOfSat[CLOCKORBIT_SATGLONASS];
[3222]434 }
435 if (sd) {
436 QString outLine;
[5662]437 processSatellite(eph, epoTime.gpsw(), epoTime.gpssec(), prn,
[4991]438 rtnAPC, rtnClk, rtnVel, rtnCoM, sd, outLine);
[3222]439 }
[5662]440
[5666]441 struct CodeBias::BiasSat* biasSat = 0;
[3222]442 if (prn[0] == 'G') {
[5666]443 biasSat = bias.Sat + bias.NumberOfSat[CLOCKORBIT_SATGPS];
444 ++bias.NumberOfSat[CLOCKORBIT_SATGPS];
[3222]445 }
446 else if (prn[0] == 'R') {
[5666]447 biasSat = bias.Sat + CLOCKORBIT_NUMGPS + bias.NumberOfSat[CLOCKORBIT_SATGLONASS];
448 ++bias.NumberOfSat[CLOCKORBIT_SATGLONASS];
[3222]449 }
[5662]450
[5503]451 // Code Biases
452 // -----------
[3222]453 if (biasSat) {
454 biasSat->ID = prn.mid(1).toInt();
[5503]455 biasSat->NumberOfCodeBiases = 0;
[3222]456 if (prn[0] == 'G') {
[5503]457 QMapIterator<QString, double> it(codeBiases);
458 while (it.hasNext()) {
459 it.next();
[5504]460 if (it.key() == "1C") {
[5503]461 int ii = biasSat->NumberOfCodeBiases; if (ii >= CLOCKORBIT_NUMBIAS) break;
462 biasSat->NumberOfCodeBiases += 1;
463 biasSat->Biases[ii].Type = CODETYPEGPS_L1_CA;
464 biasSat->Biases[ii].Bias = it.value();
465 }
[5504]466 else if (it.key() == "1C") {
[5503]467 int ii = biasSat->NumberOfCodeBiases; if (ii >= CLOCKORBIT_NUMBIAS) break;
468 biasSat->NumberOfCodeBiases += 1;
469 biasSat->Biases[ii].Type = CODETYPEGPS_L1_CA;
470 biasSat->Biases[ii].Bias = it.value();
471 }
[5504]472 else if (it.key() == "1P") {
[5503]473 int ii = biasSat->NumberOfCodeBiases; if (ii >= CLOCKORBIT_NUMBIAS) break;
474 biasSat->NumberOfCodeBiases += 1;
475 biasSat->Biases[ii].Type = CODETYPEGPS_L1_P;
476 biasSat->Biases[ii].Bias = it.value();
477 }
[5504]478 else if (it.key() == "1W") {
[5503]479 int ii = biasSat->NumberOfCodeBiases; if (ii >= CLOCKORBIT_NUMBIAS) break;
480 biasSat->NumberOfCodeBiases += 1;
481 biasSat->Biases[ii].Type = CODETYPEGPS_L1_Z;
482 biasSat->Biases[ii].Bias = it.value();
483 }
[5504]484 else if (it.key() == "2C") {
[5503]485 int ii = biasSat->NumberOfCodeBiases; if (ii >= CLOCKORBIT_NUMBIAS) break;
486 biasSat->NumberOfCodeBiases += 1;
487 biasSat->Biases[ii].Type = CODETYPEGPS_L2_CA;
488 biasSat->Biases[ii].Bias = it.value();
489 }
[5504]490 else if (it.key() == "2D") {
[5503]491 int ii = biasSat->NumberOfCodeBiases; if (ii >= CLOCKORBIT_NUMBIAS) break;
492 biasSat->NumberOfCodeBiases += 1;
493 biasSat->Biases[ii].Type = CODETYPEGPS_SEMI_CODELESS;
494 biasSat->Biases[ii].Bias = it.value();
495 }
[5504]496 else if (it.key() == "2S") {
[5503]497 int ii = biasSat->NumberOfCodeBiases; if (ii >= CLOCKORBIT_NUMBIAS) break;
498 biasSat->NumberOfCodeBiases += 1;
499 biasSat->Biases[ii].Type = CODETYPEGPS_L2_CM;
500 biasSat->Biases[ii].Bias = it.value();
501 }
[5504]502 else if (it.key() == "2L") {
[5503]503 int ii = biasSat->NumberOfCodeBiases; if (ii >= CLOCKORBIT_NUMBIAS) break;
504 biasSat->NumberOfCodeBiases += 1;
505 biasSat->Biases[ii].Type = CODETYPEGPS_L2_CL;
506 biasSat->Biases[ii].Bias = it.value();
507 }
[5504]508 else if (it.key() == "2X") {
[5503]509 int ii = biasSat->NumberOfCodeBiases; if (ii >= CLOCKORBIT_NUMBIAS) break;
510 biasSat->NumberOfCodeBiases += 1;
511 biasSat->Biases[ii].Type = CODETYPEGPS_L2_CML;
512 biasSat->Biases[ii].Bias = it.value();
513 }
[5504]514 else if (it.key() == "2P") {
[5503]515 int ii = biasSat->NumberOfCodeBiases; if (ii >= CLOCKORBIT_NUMBIAS) break;
516 biasSat->NumberOfCodeBiases += 1;
517 biasSat->Biases[ii].Type = CODETYPEGPS_L2_P;
518 biasSat->Biases[ii].Bias = it.value();
519 }
[5510]520 else if (it.key() == "2W") {
[5503]521 int ii = biasSat->NumberOfCodeBiases; if (ii >= CLOCKORBIT_NUMBIAS) break;
522 biasSat->NumberOfCodeBiases += 1;
523 biasSat->Biases[ii].Type = CODETYPEGPS_L2_Z;
524 biasSat->Biases[ii].Bias = it.value();
525 }
[5504]526 else if (it.key() == "5I") {
[5503]527 int ii = biasSat->NumberOfCodeBiases; if (ii >= CLOCKORBIT_NUMBIAS) break;
528 biasSat->NumberOfCodeBiases += 1;
529 biasSat->Biases[ii].Type = CODETYPEGPS_L5_I;
530 biasSat->Biases[ii].Bias = it.value();
531 }
[5504]532 else if (it.key() == "5Q") {
[5503]533 int ii = biasSat->NumberOfCodeBiases; if (ii >= CLOCKORBIT_NUMBIAS) break;
534 biasSat->NumberOfCodeBiases += 1;
535 biasSat->Biases[ii].Type = CODETYPEGPS_L5_Q;
536 biasSat->Biases[ii].Bias = it.value();
537 }
538 }
[3222]539 }
540 else if (prn[0] == 'R') {
[5503]541 QMapIterator<QString, double> it(codeBiases);
542 while (it.hasNext()) {
543 it.next();
[5504]544 if (it.key() == "1C") {
[5503]545 int ii = biasSat->NumberOfCodeBiases; if (ii >= CLOCKORBIT_NUMBIAS) break;
546 biasSat->NumberOfCodeBiases += 1;
547 biasSat->Biases[ii].Type = CODETYPEGLONASS_L1_CA;
548 biasSat->Biases[ii].Bias = it.value();
549 }
[5504]550 else if (it.key() == "1P") {
[5503]551 int ii = biasSat->NumberOfCodeBiases; if (ii >= CLOCKORBIT_NUMBIAS) break;
552 biasSat->NumberOfCodeBiases += 1;
553 biasSat->Biases[ii].Type = CODETYPEGLONASS_L1_P;
554 biasSat->Biases[ii].Bias = it.value();
555 }
[5504]556 else if (it.key() == "2C") {
[5503]557 int ii = biasSat->NumberOfCodeBiases; if (ii >= CLOCKORBIT_NUMBIAS) break;
558 biasSat->NumberOfCodeBiases += 1;
559 biasSat->Biases[ii].Type = CODETYPEGLONASS_L2_CA;
560 biasSat->Biases[ii].Bias = it.value();
561 }
[5504]562 else if (it.key() == "2P") {
[5503]563 int ii = biasSat->NumberOfCodeBiases; if (ii >= CLOCKORBIT_NUMBIAS) break;
564 biasSat->NumberOfCodeBiases += 1;
565 biasSat->Biases[ii].Type = CODETYPEGLONASS_L2_P;
566 biasSat->Biases[ii].Bias = it.value();
567 }
568 }
[3222]569 }
570 }
571 }
572 }
[3227]573
[5662]574 QByteArray hlpBufferCo;
[3493]575
576 // Orbit and Clock Corrections together
577 // ------------------------------------
[4174]578 if (_samplRtcmEphCorr == 0.0) {
[5666]579 if (co.NumberOfSat[CLOCKORBIT_SATGPS] > 0 || co.NumberOfSat[CLOCKORBIT_SATGLONASS] > 0) {
[3493]580 char obuffer[CLOCKORBIT_BUFFERSIZE];
581 int len = MakeClockOrbit(&co, COTYPE_AUTO, 0, obuffer, sizeof(obuffer));
582 if (len > 0) {
583 hlpBufferCo = QByteArray(obuffer, len);
584 }
[3222]585 }
586 }
[3493]587
588 // Orbit and Clock Corrections separately
589 // --------------------------------------
590 else {
[5666]591 if (co.NumberOfSat[CLOCKORBIT_SATGPS] > 0) {
[3493]592 char obuffer[CLOCKORBIT_BUFFERSIZE];
[4174]593 if (fmod(epoTime.gpssec(), _samplRtcmEphCorr) == 0.0) {
[4754]594 co.UpdateInterval = ephUpdInd;
[3591]595 int len1 = MakeClockOrbit(&co, COTYPE_GPSORBIT, 1, obuffer, sizeof(obuffer));
[4754]596 co.UpdateInterval = clkUpdInd;
[3493]597 if (len1 > 0) {
598 hlpBufferCo += QByteArray(obuffer, len1);
599 }
600 }
[5666]601 int mmsg = (co.NumberOfSat[CLOCKORBIT_SATGLONASS] > 0) ? 1 : 0;
[3591]602 int len2 = MakeClockOrbit(&co, COTYPE_GPSCLOCK, mmsg, obuffer, sizeof(obuffer));
[3493]603 if (len2 > 0) {
604 hlpBufferCo += QByteArray(obuffer, len2);
605 }
606 }
[5666]607 if (co.NumberOfSat[CLOCKORBIT_SATGLONASS] > 0) {
[3493]608 char obuffer[CLOCKORBIT_BUFFERSIZE];
[4174]609 if (fmod(epoTime.gpssec(), _samplRtcmEphCorr) == 0.0) {
[4754]610 co.UpdateInterval = ephUpdInd;
[3591]611 int len1 = MakeClockOrbit(&co, COTYPE_GLONASSORBIT, 1, obuffer, sizeof(obuffer));
[4754]612 co.UpdateInterval = clkUpdInd;
[3493]613 if (len1 > 0) {
614 hlpBufferCo += QByteArray(obuffer, len1);
615 }
616 }
617 int len2 = MakeClockOrbit(&co, COTYPE_GLONASSCLOCK, 0, obuffer, sizeof(obuffer));
618 if (len2 > 0) {
619 hlpBufferCo += QByteArray(obuffer, len2);
620 }
621 }
622 }
[5662]623
[3493]624 // Biases
625 // ------
[5662]626 QByteArray hlpBufferBias;
[5666]627 if (bias.NumberOfSat[CLOCKORBIT_SATGPS] > 0 || bias.NumberOfSat[CLOCKORBIT_SATGLONASS] > 0) {
[3222]628 char obuffer[CLOCKORBIT_BUFFERSIZE];
[5666]629 int len = MakeCodeBias(&bias, BTYPE_AUTO, 0, obuffer, sizeof(obuffer));
[3222]630 if (len > 0) {
[3227]631 hlpBufferBias = QByteArray(obuffer, len);
[3222]632 }
633 }
[3227]634
[4808]635 _outBuffer += hlpBufferCo + hlpBufferBias;
[3222]636}
637
[5662]638//
[3222]639////////////////////////////////////////////////////////////////////////////
[5662]640void bncRtnetUploadCaster::processSatellite(t_eph* eph, int GPSweek,
[4991]641 double GPSweeks, const QString& prn,
642 const ColumnVector& rtnAPC,
643 double rtnClk,
644 const ColumnVector& rtnVel,
645 const ColumnVector& rtnCoM,
646 struct ClockOrbit::SatData* sd,
647 QString& outLine) {
[3222]648
[4930]649 // Broadcast Position and Velocity
650 // -------------------------------
651 ColumnVector xB(4);
652 ColumnVector vB(3);
[6109]653 eph->getCrd(bncTime(GPSweek, GPSweeks), xB, vB, false);
[5662]654
[4991]655 // Precise Position
656 // ----------------
657 ColumnVector xP = _CoM ? rtnCoM : rtnAPC;
[3222]658
[5662]659 double dc = 0.0;
[4930]660 if (_crdTrafo != "IGS08") {
661 crdTrafo(GPSweek, xP, dc);
662 }
[5662]663
[4930]664 // Difference in xyz
665 // -----------------
666 ColumnVector dx = xB.Rows(1,3) - xP;
[4991]667 ColumnVector dv = vB - rtnVel;
[5662]668
[4930]669 // Difference in RSW
670 // -----------------
[3222]671 ColumnVector rsw(3);
[4930]672 XYZ_to_RSW(xB.Rows(1,3), vB, dx, rsw);
[3222]673
[4930]674 ColumnVector dotRsw(3);
675 XYZ_to_RSW(xB.Rows(1,3), vB, dv, dotRsw);
[3222]676
[4930]677 // Clock Correction
678 // ----------------
[4991]679 double dClk = rtnClk - (xB(4) - dc) * t_CST::c;
[3222]680
681 if (sd) {
[4930]682 sd->ID = prn.mid(1).toInt();
683 sd->IOD = eph->IOD();
684 sd->Clock.DeltaA0 = dClk;
[5655]685 sd->Clock.DeltaA1 = 0.0; // TODO
686 sd->Clock.DeltaA2 = 0.0; // TODO
[4930]687 sd->Orbit.DeltaRadial = rsw(1);
688 sd->Orbit.DeltaAlongTrack = rsw(2);
689 sd->Orbit.DeltaCrossTrack = rsw(3);
690 sd->Orbit.DotDeltaRadial = dotRsw(1);
691 sd->Orbit.DotDeltaAlongTrack = dotRsw(2);
692 sd->Orbit.DotDeltaCrossTrack = dotRsw(3);
[3222]693 }
694
[5662]695 outLine.sprintf("%d %.1f %s %3d %10.3f %8.3f %8.3f %8.3f\n",
[5776]696 GPSweek, GPSweeks, eph->prn().toString().c_str(),
[3222]697 eph->IOD(), dClk, rsw(1), rsw(2), rsw(3));
698
[4991]699 double relativity = -2.0 * DotProduct(xP, rtnVel) / t_CST::c;
700 double sp3Clk = (rtnClk - relativity) / t_CST::c; // in seconds
701
[3222]702 if (_rnx) {
[4991]703 _rnx->write(GPSweek, GPSweeks, prn, sp3Clk);
[3222]704 }
705 if (_sp3) {
[4991]706 _sp3->write(GPSweek, GPSweeks, prn, rtnCoM, sp3Clk);
[3222]707 }
708}
709
710// Transform Coordinates
711////////////////////////////////////////////////////////////////////////////
[5662]712void bncRtnetUploadCaster::crdTrafo(int GPSWeek, ColumnVector& xyz,
[4803]713 double& dc) {
[3222]714
715 // Current epoch minus 2000.0 in years
716 // ------------------------------------
717 double dt = (GPSWeek - (1042.0+6.0/7.0)) / 365.2422 * 7.0 + 2000.0 - _t0;
718
719 ColumnVector dx(3);
720
721 dx(1) = _dx + dt * _dxr;
722 dx(2) = _dy + dt * _dyr;
723 dx(3) = _dz + dt * _dzr;
724
725 static const double arcSec = 180.0 * 3600.0 / M_PI;
726
727 double ox = (_ox + dt * _oxr) / arcSec;
728 double oy = (_oy + dt * _oyr) / arcSec;
729 double oz = (_oz + dt * _ozr) / arcSec;
730
731 double sc = 1.0 + _sc * 1e-9 + dt * _scr * 1e-9;
732
[4912]733 // Specify approximate center of area
734 // ----------------------------------
735 ColumnVector meanSta(3);
736
737 if (_crdTrafo == "ETRF2000") {
[4973]738 meanSta(1) = 3661090.0;
739 meanSta(2) = 845230.0;
740 meanSta(3) = 5136850.0;
[4908]741 }
[4912]742 else if (_crdTrafo == "NAD83") {
[4973]743 meanSta(1) = -1092950.0;
744 meanSta(2) = -4383600.0;
745 meanSta(3) = 4487420.0;
[4912]746 }
747 else if (_crdTrafo == "GDA94") {
[4973]748 meanSta(1) = -4052050.0;
749 meanSta(2) = 4212840.0;
750 meanSta(3) = -2545110.0;
[4912]751 }
752 else if (_crdTrafo == "SIRGAS2000") {
[4973]753 meanSta(1) = 3740860.0;
754 meanSta(2) = -4964290.0;
755 meanSta(3) = -1425420.0;
[4912]756 }
757 else if (_crdTrafo == "SIRGAS95") {
[4973]758 meanSta(1) = 3135390.0;
759 meanSta(2) = -5017670.0;
760 meanSta(3) = -2374440.0;
[4912]761 }
[5343]762 else if (_crdTrafo == "DREF91") {
763 meanSta(1) = 3959579.0;
764 meanSta(2) = 721719.0;
765 meanSta(3) = 4931539.0;
766 }
[4912]767 else if (_crdTrafo == "Custom") {
768 meanSta(1) = 0.0; // TODO
769 meanSta(2) = 0.0; // TODO
770 meanSta(3) = 0.0; // TODO
771 }
[4908]772
[4912]773 // Clock correction proportional to topocentric distance to satellites
774 // -------------------------------------------------------------------
775 double rho = (xyz - meanSta).norm_Frobenius();
[4913]776 dc = rho * (sc - 1.0) / sc / t_CST::c;
[4908]777
[3222]778 Matrix rMat(3,3);
779 rMat(1,1) = 1.0;
780 rMat(1,2) = -oz;
781 rMat(1,3) = oy;
782 rMat(2,1) = oz;
783 rMat(2,2) = 1.0;
784 rMat(2,3) = -ox;
785 rMat(3,1) = -oy;
786 rMat(3,2) = ox;
787 rMat(3,3) = 1.0;
788
789 xyz = sc * rMat * xyz + dx;
790}
791
Note: See TracBrowser for help on using the repository browser.