source: ntrip/trunk/BNC/combination/bnccomb.cpp@ 3448

Last change on this file since 3448 was 3448, checked in by mervart, 15 years ago
File size: 18.6 KB
RevLine 
[2898]1/* -------------------------------------------------------------------------
2 * BKG NTRIP Client
3 * -------------------------------------------------------------------------
4 *
5 * Class: bncComb
6 *
7 * Purpose: Combinations of Orbit/Clock Corrections
8 *
9 * Author: L. Mervart
10 *
11 * Created: 22-Jan-2011
12 *
13 * Changes:
14 *
15 * -----------------------------------------------------------------------*/
16
[2933]17#include <newmatio.h>
[2921]18#include <iomanip>
[3214]19#include <sstream>
[2898]20
21#include "bnccomb.h"
22#include "bncapp.h"
[3201]23#include "upload/bncrtnetdecoder.h"
[2910]24#include "bncsettings.h"
[2933]25#include "bncmodel.h"
[2988]26#include "bncutils.h"
[3027]27#include "bncpppclient.h"
[3181]28#include "bncsp3.h"
[3052]29#include "bncantex.h"
[3055]30#include "bnctides.h"
[2898]31
[3438]32const int moduloTime = 10;
[2898]33
[3438]34const double sig0_offAC = 1000.0;
[3445]35const double sig0_offACSat = 100.0;
[3438]36const double sigP_offACSat = 0.0;
[3448]37const double sig0_clkSat = 100.0;
38const double sigP_clkSat = 100.0;
[3438]39
[3134]40const int MAXPRN_GPS = 32;
41
[3438]42using namespace std;
43
[2898]44// Constructor
45////////////////////////////////////////////////////////////////////////////
[3429]46cmbParam::cmbParam(parType type_, int index_,
47 const QString& ac_, const QString& prn_) {
[3032]48
[3433]49 type = type_;
50 index = index_;
51 AC = ac_;
52 prn = prn_;
53 xx = 0.0;
[3429]54
55 if (type == offAC) {
[3439]56 epoSpec = true;
57 sig0 = sig0_offAC;
58 sigP = sig0;
[3429]59 }
60 else if (type == offACSat) {
[3439]61 epoSpec = false;
62 sig0 = sig0_offACSat;
63 sigP = sigP_offACSat;
[3429]64 }
65 else if (type == clkSat) {
[3439]66 epoSpec = false;
67 sig0 = sig0_clkSat;
68 sigP = sigP_clkSat;
[3429]69 }
[2933]70}
71
72// Destructor
73////////////////////////////////////////////////////////////////////////////
74cmbParam::~cmbParam() {
75}
76
77// Partial
78////////////////////////////////////////////////////////////////////////////
[3429]79double cmbParam::partial(const QString& AC_, const QString& prn_) {
[2933]80
[3429]81 if (type == offAC) {
[3032]82 if (AC == AC_) {
[2934]83 return 1.0;
84 }
85 }
[3429]86 else if (type == offACSat) {
87 if (AC == AC_ && prn == prn_) {
[2933]88 return 1.0;
89 }
90 }
[3429]91 else if (type == clkSat) {
92 if (prn == prn_) {
[2933]93 return 1.0;
94 }
95 }
96
97 return 0.0;
98}
99
[2990]100//
101////////////////////////////////////////////////////////////////////////////
102QString cmbParam::toString() const {
[2933]103
[2990]104 QString outStr;
105
[3429]106 if (type == offAC) {
[2992]107 outStr = "AC offset " + AC;
[2990]108 }
[3429]109 else if (type == offACSat) {
[2992]110 outStr = "Sat Offset " + AC + " " + prn;
[2990]111 }
[3429]112 else if (type == clkSat) {
[2992]113 outStr = "Clk Corr " + prn;
[2990]114 }
[2933]115
[2990]116 return outStr;
117}
118
[2933]119// Constructor
120////////////////////////////////////////////////////////////////////////////
[2898]121bncComb::bncComb() {
[2910]122
123 bncSettings settings;
124
125 QStringList combineStreams = settings.value("combineStreams").toStringList();
[2918]126
[3143]127 if (combineStreams.size() >= 1 && !combineStreams[0].isEmpty()) {
[2910]128 QListIterator<QString> it(combineStreams);
129 while (it.hasNext()) {
130 QStringList hlp = it.next().split(" ");
[2918]131 cmbAC* newAC = new cmbAC();
132 newAC->mountPoint = hlp[0];
133 newAC->name = hlp[1];
134 newAC->weight = hlp[2].toDouble();
[3429]135 _ACs.append(newAC);
[2910]136 }
137 }
[2927]138
[3211]139 _rtnetDecoder = 0;
[3201]140
[2990]141 connect(this, SIGNAL(newMessage(QByteArray,bool)),
142 ((bncApp*)qApp), SLOT(slotMessage(const QByteArray,bool)));
[2933]143
[3032]144
145 // Initialize Parameters (model: Clk_Corr = AC_Offset + Sat_Offset + Clk)
146 // ----------------------------------------------------------------------
[2933]147 int nextPar = 0;
[3429]148 QListIterator<cmbAC*> it(_ACs);
[2991]149 while (it.hasNext()) {
[3429]150 cmbAC* AC = it.next();
151 _params.push_back(new cmbParam(cmbParam::offAC, ++nextPar, AC->name, ""));
[3134]152 for (int iGps = 1; iGps <= MAXPRN_GPS; iGps++) {
153 QString prn = QString("G%1").arg(iGps, 2, 10, QChar('0'));
[3429]154 _params.push_back(new cmbParam(cmbParam::offACSat, ++nextPar,
155 AC->name, prn));
[2991]156 }
157 }
[3134]158 for (int iGps = 1; iGps <= MAXPRN_GPS; iGps++) {
[2933]159 QString prn = QString("G%1").arg(iGps, 2, 10, QChar('0'));
[3429]160 _params.push_back(new cmbParam(cmbParam::clkSat, ++nextPar, "", prn));
[2933]161 }
162
[3032]163 // Initialize Variance-Covariance Matrix
164 // -------------------------------------
165 _QQ.ReSize(_params.size());
[2933]166 _QQ = 0.0;
167 for (int iPar = 1; iPar <= _params.size(); iPar++) {
168 cmbParam* pp = _params[iPar-1];
[3439]169 _QQ(iPar,iPar) = pp->sig0 * pp->sig0;
[2933]170 }
[3035]171
[3052]172 // ANTEX File
173 // ----------
174 _antex = 0;
175 QString antexFileName = settings.value("pppAntex").toString();
176 if (!antexFileName.isEmpty()) {
177 _antex = new bncAntex();
178 if (_antex->readFile(antexFileName) != success) {
179 emit newMessage("wrong ANTEX file", true);
180 delete _antex;
181 _antex = 0;
182 }
183 }
[3138]184
[3448]185 // Not yet regularized
186 // -------------------
187 _firstReg = false;
188
[3329]189 // Maximal Residuum
190 // ----------------
191 _MAXRES = settings.value("cmbMaxres").toDouble();
192 if (_MAXRES <= 0.0) {
193 _MAXRES = 999.0;
194 }
[2898]195}
196
197// Destructor
198////////////////////////////////////////////////////////////////////////////
199bncComb::~bncComb() {
[3429]200 QListIterator<cmbAC*> icAC(_ACs);
201 while (icAC.hasNext()) {
202 delete icAC.next();
[2918]203 }
[3201]204 delete _rtnetDecoder;
[3052]205 delete _antex;
[3296]206 for (int iPar = 1; iPar <= _params.size(); iPar++) {
207 delete _params[iPar-1];
208 }
[3434]209 QVectorIterator<cmbCorr*> itCorr(corrs());
[3429]210 while (itCorr.hasNext()) {
211 delete itCorr.next();
212 }
[2898]213}
214
[2928]215// Read and store one correction line
[2898]216////////////////////////////////////////////////////////////////////////////
217void bncComb::processCorrLine(const QString& staID, const QString& line) {
[2906]218 QMutexLocker locker(&_mutex);
[2913]219
[3431]220 // Find the AC Name
221 // ----------------
222 QString acName;
223 QListIterator<cmbAC*> icAC(_ACs);
224 while (icAC.hasNext()) {
225 cmbAC* AC = icAC.next();
226 if (AC->mountPoint == staID) {
227 acName = AC->name;
228 break;
229 }
230 }
231 if (acName.isEmpty()) {
232 return;
233 }
234
[2918]235 // Read the Correction
236 // -------------------
[3429]237 cmbCorr* newCorr = new cmbCorr();
[3431]238 newCorr->acName = acName;
[2913]239 if (!newCorr->readLine(line) == success) {
240 delete newCorr;
241 return;
242 }
243
[3274]244 // Check Modulo Time
245 // -----------------
246 if (int(newCorr->tt.gpssec()) % moduloTime != 0.0) {
247 delete newCorr;
248 return;
249 }
250
[3299]251 // Delete old corrections
252 // ----------------------
[3437]253 if (_resTime.valid() && newCorr->tt <= _resTime) {
[2924]254 delete newCorr;
255 return;
256 }
257
[3029]258 // Check the Ephemeris
259 //--------------------
[2986]260 if (_eph.find(newCorr->prn) == _eph.end()) {
261 delete newCorr;
262 return;
263 }
264 else {
265 t_eph* lastEph = _eph[newCorr->prn]->last;
266 t_eph* prevEph = _eph[newCorr->prn]->prev;
[3029]267 if (lastEph && lastEph->IOD() == newCorr->iod) {
268 newCorr->eph = lastEph;
[2986]269 }
[3029]270 else if (prevEph && prevEph->IOD() == newCorr->iod) {
271 newCorr->eph = prevEph;
[3429]272 switchToLastEph(lastEph, newCorr);
[3029]273 }
274 else {
[2986]275 delete newCorr;
276 return;
277 }
278 }
279
[3435]280 // Process previous Epoch(s)
281 // -------------------------
282 QListIterator<bncTime> itTime(_buffer.keys());
283 while (itTime.hasNext()) {
284 bncTime epoTime = itTime.next();
[3438]285 if (epoTime < newCorr->tt - moduloTime) {
[3435]286 _resTime = epoTime;
287 processEpoch();
288 }
[2927]289 }
290
[3429]291 // Merge or add the correction
292 // ---------------------------
[3435]293 QVector<cmbCorr*>& corrs = _buffer[newCorr->tt].corrs;
[3429]294 cmbCorr* existingCorr = 0;
[3435]295 QVectorIterator<cmbCorr*> itCorr(corrs);
[3429]296 while (itCorr.hasNext()) {
297 cmbCorr* hlp = itCorr.next();
298 if (hlp->prn == newCorr->prn && hlp->acName == newCorr->prn) {
299 existingCorr = hlp;
[2918]300 break;
301 }
302 }
[3429]303 if (existingCorr) {
[3298]304 delete newCorr;
[3429]305 existingCorr->readLine(line); // merge (multiple messages)
[2918]306 }
[2919]307 else {
[3435]308 corrs.append(newCorr);
[2919]309 }
[2898]310}
311
[2986]312// Change the correction so that it refers to last received ephemeris
313////////////////////////////////////////////////////////////////////////////
[3029]314void bncComb::switchToLastEph(const t_eph* lastEph, t_corr* corr) {
[3028]315
[3429]316 if (corr->eph == lastEph) {
317 return;
318 }
319
[2987]320 ColumnVector oldXC(4);
321 ColumnVector oldVV(3);
[3029]322 corr->eph->position(corr->tt.gpsw(), corr->tt.gpssec(),
323 oldXC.data(), oldVV.data());
[2988]324
[2987]325 ColumnVector newXC(4);
326 ColumnVector newVV(3);
[3029]327 lastEph->position(corr->tt.gpsw(), corr->tt.gpssec(),
[2987]328 newXC.data(), newVV.data());
[2988]329
330 ColumnVector dX = newXC.Rows(1,3) - oldXC.Rows(1,3);
[2989]331 ColumnVector dV = newVV - oldVV;
332 double dC = newXC(4) - oldXC(4);
333
[2988]334 ColumnVector dRAO(3);
335 XYZ_to_RSW(newXC.Rows(1,3), newVV, dX, dRAO);
[2989]336
337 ColumnVector dDotRAO(3);
338 XYZ_to_RSW(newXC.Rows(1,3), newVV, dV, dDotRAO);
339
[3448]340 QString msg = "switch " + corr->prn
[3029]341 + QString(" %1 -> %2 %3").arg(corr->iod,3)
[3013]342 .arg(lastEph->IOD(),3).arg(dC*t_CST::c, 8, 'f', 4);
343
[3029]344 emit newMessage(msg.toAscii(), false);
[3028]345
[3029]346 corr->iod = lastEph->IOD();
347 corr->eph = lastEph;
[3031]348 corr->rao += dRAO;
349 corr->dotRao += dDotRAO;
[3029]350 corr->dClk -= dC;
[2986]351}
352
[3429]353// Process Epoch
[2928]354////////////////////////////////////////////////////////////////////////////
[3429]355void bncComb::processEpoch() {
[2918]356
[3429]357 int nPar = _params.size();
[3448]358 int nObs = corrs().size();
[3429]359
[3448]360 if (nObs == 0) {
361 return;
362 }
363
[2990]364 _log.clear();
365
366 QTextStream out(&_log, QIODevice::WriteOnly);
367
[3371]368 out << endl << "Combination:" << endl
[3275]369 << "------------------------------" << endl;
[2990]370
[3433]371 // Observation Statistics
372 // ----------------------
373 QListIterator<cmbAC*> icAC(_ACs);
374 while (icAC.hasNext()) {
375 cmbAC* AC = icAC.next();
376 AC->numObs = 0;
[3434]377 QVectorIterator<cmbCorr*> itCorr(corrs());
[3433]378 while (itCorr.hasNext()) {
379 cmbCorr* corr = itCorr.next();
380 if (corr->acName == AC->name) {
381 AC->numObs += 1;
382 }
383 }
384 out << AC->name.toAscii().data() << ": " << AC->numObs << endl;
385 }
386
[3429]387 // Prediction Step
388 // ---------------
[2933]389 ColumnVector x0(nPar);
390 for (int iPar = 1; iPar <= _params.size(); iPar++) {
[3448]391 cmbParam* pp = _params[iPar-1];
[3439]392 if (pp->epoSpec) {
393 pp->xx = 0.0;
394 _QQ.Row(iPar) = 0.0;
395 _QQ.Column(iPar) = 0.0;
396 _QQ(iPar,iPar) = pp->sig0 * pp->sig0;
397 }
398 else {
399 _QQ(iPar,iPar) += pp->sigP * pp->sigP;
400 }
[2933]401 x0(iPar) = pp->xx;
402 }
403
[3448]404 // Create First Design Matrix and Vector of Measurements
405 // -----------------------------------------------------
406 const double Pl = 1.0 / (0.05 * 0.05);
[3441]407
[3448]408 const int nCon = (_firstReg == false) ? 1 + MAXPRN_GPS : 1;
409 Matrix AA(nObs+nCon, nPar); AA = 0.0;
410 ColumnVector ll(nObs+nCon); ll = 0.0;
411 DiagonalMatrix PP(nObs+nCon); PP = Pl;
412
413 int iObs = 0;
414
[3429]415 QMap<QString, t_corr*> resCorr;
[3135]416
[3448]417 QVectorIterator<cmbCorr*> itCorr(corrs());
418 while (itCorr.hasNext()) {
419 cmbCorr* corr = itCorr.next();
420 QString prn = corr->prn;
421 switchToLastEph(_eph[prn]->last, corr);
422 ++iObs;
[3429]423
[3448]424 if (resCorr.find(prn) == resCorr.end()) {
425 resCorr[prn] = new t_corr(*corr);
[3441]426 }
[2933]427
[3448]428 for (int iPar = 1; iPar <= _params.size(); iPar++) {
429 cmbParam* pp = _params[iPar-1];
430 AA(iObs, iPar) = pp->partial(corr->acName, prn);
431 }
432
433 ll(iObs) = corr->dClk * t_CST::c - DotProduct(AA.Row(iObs), x0);
434 }
435
436 // Regularization
437 // --------------
438 const double Ph = 1.e6;
439 int iCond = 1;
440 PP(nObs+iCond) = Ph;
441 for (int iPar = 1; iPar <= _params.size(); iPar++) {
442 cmbParam* pp = _params[iPar-1];
443 if (pp->type == cmbParam::clkSat &&
444 AA.Column(iPar).maximum_absolute_value() > 0.0) {
445 AA(nObs+iCond, iPar) = 1.0;
446 }
447 }
448
449 if (!_firstReg) {
450 _firstReg = true;
451 for (int iGps = 1; iGps <= MAXPRN_GPS; iGps++) {
452 ++iCond;
453 QString prn = QString("G%1").arg(iGps, 2, 10, QChar('0'));
454 PP(nObs+1+iGps) = Ph;
455 for (int iPar = 1; iPar <= _params.size(); iPar++) {
456 cmbParam* pp = _params[iPar-1];
457 if (pp->type == cmbParam::offACSat && pp->prn == prn) {
458 AA(nObs+iCond, iPar) = 1.0;
459 }
460 }
461 }
462 }
463
464 ColumnVector dx;
465 SymmetricMatrix QQ_sav = _QQ;
466
467 // Update and outlier detection loop
468 // ---------------------------------
469 for (int ii = 1; ii < 10; ii++) {
[3429]470 bncModel::kalman(AA, ll, PP, _QQ, dx);
471 ColumnVector vv = ll - AA * dx;
[3080]472
[3429]473 int maxResIndex;
474 double maxRes = vv.maximum_absolute_value1(maxResIndex);
475 out.setRealNumberNotation(QTextStream::FixedNotation);
476 out.setRealNumberPrecision(3);
477 out << _resTime.datestr().c_str() << " " << _resTime.timestr().c_str()
[3432]478 << " Maximum Residuum " << maxRes << ' '
[3434]479 << corrs()[maxResIndex-1]->acName << ' ' << corrs()[maxResIndex-1]->prn;
[3080]480
[3432]481 if (maxRes > _MAXRES) {
482 for (int iPar = 1; iPar <= _params.size(); iPar++) {
483 cmbParam* pp = _params[iPar-1];
484 if (pp->type == cmbParam::offACSat &&
[3434]485 pp->AC == corrs()[maxResIndex-1]->acName &&
486 pp->prn == corrs()[maxResIndex-1]->prn) {
[3432]487 QQ_sav.Row(iPar) = 0.0;
488 QQ_sav.Column(iPar) = 0.0;
[3439]489 QQ_sav(iPar,iPar) = pp->sig0 * pp->sig0;
[3432]490 }
491 }
492
493 out << " Outlier" << endl;
494 _QQ = QQ_sav;
[3448]495 AA.Row(maxResIndex) = 0.0;
496 ll.Row(maxResIndex) = 0.0;
[3432]497 }
498 else {
499 out << " OK" << endl;
500 break;
501 }
502 }
503
504 // Update Parameter Values
505 // -----------------------
[3429]506 for (int iPar = 1; iPar <= _params.size(); iPar++) {
507 cmbParam* pp = _params[iPar-1];
508 pp->xx += dx(iPar);
509 if (pp->type == cmbParam::clkSat) {
510 if (resCorr.find(pp->prn) != resCorr.end()) {
511 resCorr[pp->prn]->dClk = pp->xx / t_CST::c;
[3080]512 }
513 }
[3429]514 out << _resTime.datestr().c_str() << " "
515 << _resTime.timestr().c_str() << " ";
516 out.setRealNumberNotation(QTextStream::FixedNotation);
517 out.setFieldWidth(8);
518 out.setRealNumberPrecision(4);
519 out << pp->toString() << " "
520 << pp->xx << " +- " << sqrt(_QQ(pp->index,pp->index)) << endl;
521 out.setFieldWidth(0);
[2918]522 }
[2919]523
[3432]524 // Print Results
525 // -------------
[3429]526 printResults(out, resCorr);
527 dumpResults(resCorr);
[2928]528
[2990]529 emit newMessage(_log, false);
[3296]530
[3432]531 // Delete Data
532 // -----------
[3434]533 _buffer.remove(_resTime);
[2918]534}
[3011]535
[3201]536// Print results
[3011]537////////////////////////////////////////////////////////////////////////////
[3429]538void bncComb::printResults(QTextStream& out,
[3011]539 const QMap<QString, t_corr*>& resCorr) {
540
541 QMapIterator<QString, t_corr*> it(resCorr);
542 while (it.hasNext()) {
543 it.next();
544 t_corr* corr = it.value();
[3029]545 const t_eph* eph = corr->eph;
[3015]546 if (eph) {
547 double xx, yy, zz, cc;
[3429]548 eph->position(_resTime.gpsw(), _resTime.gpssec(), xx, yy, zz, cc);
[3015]549
[3429]550 out << _resTime.datestr().c_str() << " "
551 << _resTime.timestr().c_str() << " ";
[3015]552 out.setFieldWidth(3);
553 out << "Full Clock " << corr->prn << " " << corr->iod << " ";
554 out.setFieldWidth(14);
555 out << (cc + corr->dClk) * t_CST::c << endl;
[3370]556 out.setFieldWidth(0);
[3015]557 }
558 else {
559 out << "bncComb::printResuls bug" << endl;
560 }
[3011]561 }
562}
[3202]563
564// Send results to RTNet Decoder and directly to PPP Client
565////////////////////////////////////////////////////////////////////////////
[3429]566void bncComb::dumpResults(const QMap<QString, t_corr*>& resCorr) {
[3202]567
[3214]568 ostringstream out; out.setf(std::ios::fixed);
[3216]569 QStringList corrLines;
[3214]570
571 unsigned year, month, day, hour, minute;
572 double sec;
[3429]573 _resTime.civil_date(year, month, day);
574 _resTime.civil_time(hour, minute, sec);
[3214]575
576 out << "* "
577 << setw(4) << year << " "
578 << setw(2) << month << " "
579 << setw(2) << day << " "
580 << setw(2) << hour << " "
581 << setw(2) << minute << " "
582 << setw(12) << setprecision(8) << sec << " "
583 << endl;
584
[3202]585 QMapIterator<QString, t_corr*> it(resCorr);
586 while (it.hasNext()) {
587 it.next();
588 t_corr* corr = it.value();
589
[3214]590 double dT = 60.0;
[3202]591
[3214]592 for (int iTime = 1; iTime <= 2; iTime++) {
593
[3429]594 bncTime time12 = (iTime == 1) ? _resTime : _resTime + dT;
[3214]595
596 ColumnVector xc(4);
597 ColumnVector vv(3);
598 corr->eph->position(time12.gpsw(), time12.gpssec(),
599 xc.data(), vv.data());
600 bncPPPclient::applyCorr(time12, corr, xc, vv);
601
602 // Relativistic Correction
603 // -----------------------
604 double relCorr = - 2.0 * DotProduct(xc.Rows(1,3),vv) / t_CST::c / t_CST::c;
605 xc(4) -= relCorr;
606
607 // Code Biases
608 // -----------
609 double dcbP1C1 = 0.0;
610 double dcbP1P2 = 0.0;
611
612 // Correction Phase Center --> CoM
613 // -------------------------------
614 ColumnVector dx(3); dx = 0.0;
615 if (_antex) {
616 double Mjd = time12.mjd() + time12.daysec()/86400.0;
617 if (_antex->satCoMcorrection(corr->prn, Mjd, xc.Rows(1,3), dx) == success) {
618 xc(1) -= dx(1);
619 xc(2) -= dx(2);
620 xc(3) -= dx(3);
621 }
622 else {
623 cout << "antenna not found" << endl;
624 }
625 }
626
627 if (iTime == 1) {
628 out << 'P' << corr->prn.toAscii().data()
629 << setw(14) << setprecision(6) << xc(1) / 1000.0
630 << setw(14) << setprecision(6) << xc(2) / 1000.0
631 << setw(14) << setprecision(6) << xc(3) / 1000.0
632 << setw(14) << setprecision(6) << xc(4) * 1e6
633 << setw(14) << setprecision(6) << relCorr * 1e6
634 << setw(8) << setprecision(3) << dx(1)
635 << setw(8) << setprecision(3) << dx(2)
636 << setw(8) << setprecision(3) << dx(3)
637 << setw(8) << setprecision(3) << dcbP1C1
638 << setw(8) << setprecision(3) << dcbP1P2
639 << setw(6) << setprecision(1) << dT;
[3216]640
[3218]641 QString line;
[3217]642 int messageType = COTYPE_GPSCOMBINED;
[3218]643 int updateInt = 0;
644 line.sprintf("%d %d %d %.1f %s"
645 " %3d"
646 " %8.3f %8.3f %8.3f %8.3f"
647 " %10.5f %10.5f %10.5f %10.5f"
[3262]648 " %10.5f %10.5f %10.5f %10.5f INTERNAL",
[3218]649 messageType, updateInt, time12.gpsw(), time12.gpssec(),
650 corr->prn.toAscii().data(),
651 corr->iod,
[3219]652 corr->dClk * t_CST::c,
[3218]653 corr->rao[0],
654 corr->rao[1],
655 corr->rao[2],
[3219]656 corr->dotDClk * t_CST::c,
[3218]657 corr->dotRao[0],
658 corr->dotRao[1],
659 corr->dotRao[2],
[3262]660 corr->dotDotDClk * t_CST::c,
661 corr->dotDotRao[0],
662 corr->dotDotRao[1],
663 corr->dotDotRao[2]);
[3220]664 corrLines << line;
[3214]665 }
666 else {
667 out << setw(14) << setprecision(6) << xc(1) / 1000.0
668 << setw(14) << setprecision(6) << xc(2) / 1000.0
669 << setw(14) << setprecision(6) << xc(3) / 1000.0 << endl;
670 }
671 }
672
673 delete corr;
674 }
[3228]675 out << "EOE" << endl; // End Of Epoch flag
[3214]676
[3215]677 if (!_rtnetDecoder) {
678 _rtnetDecoder = new bncRtnetDecoder();
679 }
[3221]680
[3215]681 vector<string> errmsg;
[3221]682 _rtnetDecoder->Decode((char*) out.str().data(), out.str().size(), errmsg);
[3215]683
[3216]684 // Optionally send new Corrections to PPP
685 // --------------------------------------
686 bncApp* app = (bncApp*) qApp;
687 if (app->_bncPPPclient) {
688 app->_bncPPPclient->slotNewCorrections(corrLines);
689 }
[3202]690}
Note: See TracBrowser for help on using the repository browser.