Changeset 3202 in ntrip


Ignore:
Timestamp:
Mar 30, 2011, 4:15:54 PM (13 years ago)
Author:
mervart
Message:
 
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/BNC/combination/bnccomb.cpp

    r3201 r3202  
    299299  else {
    300300    newEpoch->corr[newCorr->prn] = newCorr;
     301  }
     302}
     303
     304// Change the correction so that it refers to last received ephemeris
     305////////////////////////////////////////////////////////////////////////////
     306void bncComb::switchToLastEph(const t_eph* lastEph, t_corr* corr) {
     307
     308  ColumnVector oldXC(4);
     309  ColumnVector oldVV(3);
     310  corr->eph->position(corr->tt.gpsw(), corr->tt.gpssec(),
     311                      oldXC.data(), oldVV.data());
     312
     313  ColumnVector newXC(4);
     314  ColumnVector newVV(3);
     315  lastEph->position(corr->tt.gpsw(), corr->tt.gpssec(),
     316                    newXC.data(), newVV.data());
     317
     318  ColumnVector dX = newXC.Rows(1,3) - oldXC.Rows(1,3);
     319  ColumnVector dV = newVV           - oldVV;
     320  double       dC = newXC(4)        - oldXC(4);
     321
     322  ColumnVector dRAO(3);
     323  XYZ_to_RSW(newXC.Rows(1,3), newVV, dX, dRAO);
     324
     325  ColumnVector dDotRAO(3);
     326  XYZ_to_RSW(newXC.Rows(1,3), newVV, dV, dDotRAO);
     327
     328  QString msg = "switch " + corr->prn
     329    + QString(" %1 -> %2 %3").arg(corr->iod,3)
     330    .arg(lastEph->IOD(),3).arg(dC*t_CST::c, 8, 'f', 4);
     331
     332  emit newMessage(msg.toAscii(), false);
     333
     334  corr->iod     = lastEph->IOD();
     335  corr->eph     = lastEph;
     336  corr->rao    += dRAO;
     337  corr->dotRao += dDotRAO;
     338  corr->dClk   -= dC;
     339}
     340
     341// Process Epochs
     342////////////////////////////////////////////////////////////////////////////
     343void bncComb::processEpochs(const QList<cmbEpoch*>& epochs) {
     344
     345  _log.clear();
     346
     347  QTextStream out(&_log, QIODevice::WriteOnly);
     348
     349  out <<                   "Combination:" << endl
     350      << "------------------------------" << endl;
     351
     352  // Predict Parameters Values, Add White Noise
     353  // ------------------------------------------
     354  for (int iPar = 1; iPar <= _params.size(); iPar++) {
     355    cmbParam* pp = _params[iPar-1];
     356    if (pp->sig_P != 0.0) {
     357      pp->xx = 0.0;
     358      for (int jj = 1; jj <= _params.size(); jj++) {
     359        _QQ(iPar, jj) = 0.0;
     360      }
     361      _QQ(iPar,iPar) = pp->sig_P * pp->sig_P;
     362    }
     363  }
     364
     365  bncTime                resTime = epochs.first()->time;
     366  QMap<QString, t_corr*> resCorr;
     367
     368  int nPar = _params.size();
     369  int nObs = 0; 
     370
     371  ColumnVector x0(nPar);
     372  for (int iPar = 1; iPar <= _params.size(); iPar++) {
     373    cmbParam* pp = _params[iPar-1];
     374    x0(iPar) = pp->xx;
     375  }
     376
     377  // Count Observations
     378  // ------------------
     379  QListIterator<cmbEpoch*> itEpo(epochs);
     380  while (itEpo.hasNext()) {
     381    cmbEpoch* epo = itEpo.next();
     382    QMutableMapIterator<QString, t_corr*> itCorr(epo->corr);
     383    while (itCorr.hasNext()) {
     384      itCorr.next();
     385      t_corr* corr = itCorr.value();
     386
     387      // Switch to last ephemeris
     388      // ------------------------
     389      t_eph* lastEph = _eph[corr->prn]->last;
     390      if (lastEph == corr->eph) {     
     391        ++nObs;
     392      }
     393      else {
     394        if (corr->eph == _eph[corr->prn]->prev) {
     395          switchToLastEph(lastEph, corr);
     396          ++nObs;
     397        }
     398        else {
     399          itCorr.remove();
     400        }
     401      }
     402    }
     403  }
     404
     405  if (nObs > 0) {
     406    const double Pl = 1.0 / (0.05 * 0.05);
     407
     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    QListIterator<cmbEpoch*> itEpo(epochs);
     415    while (itEpo.hasNext()) {
     416      cmbEpoch* epo = itEpo.next();
     417      QMapIterator<QString, t_corr*> itCorr(epo->corr);
     418   
     419      while (itCorr.hasNext()) {
     420        itCorr.next();
     421        ++iObs;
     422        t_corr* corr = itCorr.value();
     423
     424        if (epo->acName == _masterAC) {
     425          resCorr[corr->prn] = new t_corr(*corr);
     426        }
     427
     428        for (int iPar = 1; iPar <= _params.size(); iPar++) {
     429          cmbParam* pp = _params[iPar-1];
     430          AA(iObs, iPar) = pp->partial(epo->acName, corr);
     431        }
     432
     433        ll(iObs) = corr->dClk * t_CST::c - DotProduct(AA.Row(iObs), x0);
     434      }
     435
     436      delete epo;
     437    }
     438
     439    // Regularization
     440    // --------------
     441    const double Ph = 1.e6;
     442    int iCond = 1;
     443    PP(nObs+iCond) = Ph;
     444    for (int iPar = 1; iPar <= _params.size(); iPar++) {
     445      cmbParam* pp = _params[iPar-1];
     446      if (pp->type == cmbParam::clk &&
     447          AA.Column(iPar).maximum_absolute_value() > 0.0) {
     448        AA(nObs+iCond, iPar) = 1.0;
     449      }
     450    }
     451
     452    if (!_firstReg) {
     453      _firstReg = true;
     454      for (int iGps = 1; iGps <= MAXPRN_GPS; iGps++) {
     455        ++iCond;
     456        QString prn = QString("G%1").arg(iGps, 2, 10, QChar('0'));
     457        PP(nObs+1+iGps) = Ph;
     458        for (int iPar = 1; iPar <= _params.size(); iPar++) {
     459          cmbParam* pp = _params[iPar-1];
     460          if (pp->type == cmbParam::Sat_offset && pp->prn == prn) {
     461            AA(nObs+iCond, iPar) = 1.0;
     462          }
     463        }
     464      }
     465    }
     466
     467    const double MAXRES = 999.10;  // TODO: make it an option
     468
     469    ColumnVector dx;
     470    SymmetricMatrix QQ_sav = _QQ;
     471
     472    for (int ii = 1; ii < 10; ii++) {
     473      bncModel::kalman(AA, ll, PP, _QQ, dx);
     474      ColumnVector vv = ll - AA * dx;
     475
     476      int    maxResIndex;
     477      double maxRes = vv.maximum_absolute_value1(maxResIndex);   
     478      out.setRealNumberNotation(QTextStream::FixedNotation);
     479      out.setRealNumberPrecision(3); 
     480      out << "Maximum Residuum " << maxRes << " (index " << maxResIndex << ")\n";
     481
     482      if (maxRes > MAXRES) {
     483        out << "Outlier Detected" << endl;
     484        _QQ = QQ_sav;
     485        AA.Row(maxResIndex) = 0.0;
     486        ll.Row(maxResIndex) = 0.0;
     487      }
     488      else {
     489        break;
     490      }
     491    }
     492
     493    for (int iPar = 1; iPar <= _params.size(); iPar++) {
     494      cmbParam* pp = _params[iPar-1];
     495      pp->xx += dx(iPar);
     496      if (pp->type == cmbParam::clk) {
     497        if (resCorr.find(pp->prn) != resCorr.end()) {
     498          resCorr[pp->prn]->dClk = pp->xx / t_CST::c;
     499        }
     500      }
     501      out << currentDateAndTimeGPS().toString("yy-MM-dd hh:mm:ss ").toAscii().data();
     502      out.setRealNumberNotation(QTextStream::FixedNotation);
     503      out.setFieldWidth(8);
     504      out.setRealNumberPrecision(4);
     505      out << pp->toString() << " "
     506          << pp->xx << " +- " << sqrt(_QQ(pp->index,pp->index)) << endl;
     507    }
     508  }
     509
     510  printResults(out, resTime, resCorr);
     511  dumpResults(resTime, resCorr);
     512
     513  emit newMessage(_log, false);
     514}
     515
     516// Print results
     517////////////////////////////////////////////////////////////////////////////
     518void bncComb::printResults(QTextStream& out, const bncTime& resTime,
     519                           const QMap<QString, t_corr*>& resCorr) {
     520
     521  QMapIterator<QString, t_corr*> it(resCorr);
     522  while (it.hasNext()) {
     523    it.next();
     524    t_corr* corr = it.value();
     525    const t_eph* eph = corr->eph;
     526    if (eph) {
     527      double xx, yy, zz, cc;
     528      eph->position(resTime.gpsw(), resTime.gpssec(), xx, yy, zz, cc);
     529
     530      out << currentDateAndTimeGPS().toString("yy-MM-dd hh:mm:ss ").toAscii().data();
     531      out.setFieldWidth(3);
     532      out << "Full Clock " << corr->prn << " " << corr->iod << " ";
     533      out.setFieldWidth(14);
     534      out << (cc + corr->dClk) * t_CST::c << endl;
     535    }
     536    else {
     537      out << "bncComb::printResuls bug" << endl;
     538    }
    301539  }
    302540}
     
    363601  }
    364602}
    365 
    366 // Change the correction so that it refers to last received ephemeris
    367 ////////////////////////////////////////////////////////////////////////////
    368 void bncComb::switchToLastEph(const t_eph* lastEph, t_corr* corr) {
    369 
    370   ColumnVector oldXC(4);
    371   ColumnVector oldVV(3);
    372   corr->eph->position(corr->tt.gpsw(), corr->tt.gpssec(),
    373                       oldXC.data(), oldVV.data());
    374 
    375   ColumnVector newXC(4);
    376   ColumnVector newVV(3);
    377   lastEph->position(corr->tt.gpsw(), corr->tt.gpssec(),
    378                     newXC.data(), newVV.data());
    379 
    380   ColumnVector dX = newXC.Rows(1,3) - oldXC.Rows(1,3);
    381   ColumnVector dV = newVV           - oldVV;
    382   double       dC = newXC(4)        - oldXC(4);
    383 
    384   ColumnVector dRAO(3);
    385   XYZ_to_RSW(newXC.Rows(1,3), newVV, dX, dRAO);
    386 
    387   ColumnVector dDotRAO(3);
    388   XYZ_to_RSW(newXC.Rows(1,3), newVV, dV, dDotRAO);
    389 
    390   QString msg = "switch " + corr->prn
    391     + QString(" %1 -> %2 %3").arg(corr->iod,3)
    392     .arg(lastEph->IOD(),3).arg(dC*t_CST::c, 8, 'f', 4);
    393 
    394   emit newMessage(msg.toAscii(), false);
    395 
    396   corr->iod     = lastEph->IOD();
    397   corr->eph     = lastEph;
    398   corr->rao    += dRAO;
    399   corr->dotRao += dDotRAO;
    400   corr->dClk   -= dC;
    401 }
    402 
    403 // Process Epochs
    404 ////////////////////////////////////////////////////////////////////////////
    405 void bncComb::processEpochs(const QList<cmbEpoch*>& epochs) {
    406 
    407   _log.clear();
    408 
    409   QTextStream out(&_log, QIODevice::WriteOnly);
    410 
    411   out <<                   "Combination:" << endl
    412       << "------------------------------" << endl;
    413 
    414   // Predict Parameters Values, Add White Noise
    415   // ------------------------------------------
    416   for (int iPar = 1; iPar <= _params.size(); iPar++) {
    417     cmbParam* pp = _params[iPar-1];
    418     if (pp->sig_P != 0.0) {
    419       pp->xx = 0.0;
    420       for (int jj = 1; jj <= _params.size(); jj++) {
    421         _QQ(iPar, jj) = 0.0;
    422       }
    423       _QQ(iPar,iPar) = pp->sig_P * pp->sig_P;
    424     }
    425   }
    426 
    427   bncTime                resTime = epochs.first()->time;
    428   QMap<QString, t_corr*> resCorr;
    429 
    430   int nPar = _params.size();
    431   int nObs = 0; 
    432 
    433   ColumnVector x0(nPar);
    434   for (int iPar = 1; iPar <= _params.size(); iPar++) {
    435     cmbParam* pp = _params[iPar-1];
    436     x0(iPar) = pp->xx;
    437   }
    438 
    439   // Count Observations
    440   // ------------------
    441   QListIterator<cmbEpoch*> itEpo(epochs);
    442   while (itEpo.hasNext()) {
    443     cmbEpoch* epo = itEpo.next();
    444     QMutableMapIterator<QString, t_corr*> itCorr(epo->corr);
    445     while (itCorr.hasNext()) {
    446       itCorr.next();
    447       t_corr* corr = itCorr.value();
    448 
    449       // Switch to last ephemeris
    450       // ------------------------
    451       t_eph* lastEph = _eph[corr->prn]->last;
    452       if (lastEph == corr->eph) {     
    453         ++nObs;
    454       }
    455       else {
    456         if (corr->eph == _eph[corr->prn]->prev) {
    457           switchToLastEph(lastEph, corr);
    458           ++nObs;
    459         }
    460         else {
    461           itCorr.remove();
    462         }
    463       }
    464     }
    465   }
    466 
    467   if (nObs > 0) {
    468     const double Pl = 1.0 / (0.05 * 0.05);
    469 
    470     const int nCon = (_firstReg == false) ? 1 + MAXPRN_GPS : 1;
    471     Matrix         AA(nObs+nCon, nPar);  AA = 0.0;
    472     ColumnVector   ll(nObs+nCon);        ll = 0.0;
    473     DiagonalMatrix PP(nObs+nCon);        PP = Pl;
    474 
    475     int iObs = 0;
    476     QListIterator<cmbEpoch*> itEpo(epochs);
    477     while (itEpo.hasNext()) {
    478       cmbEpoch* epo = itEpo.next();
    479       QMapIterator<QString, t_corr*> itCorr(epo->corr);
    480    
    481       while (itCorr.hasNext()) {
    482         itCorr.next();
    483         ++iObs;
    484         t_corr* corr = itCorr.value();
    485 
    486         if (epo->acName == _masterAC) {
    487           resCorr[corr->prn] = new t_corr(*corr);
    488         }
    489 
    490         for (int iPar = 1; iPar <= _params.size(); iPar++) {
    491           cmbParam* pp = _params[iPar-1];
    492           AA(iObs, iPar) = pp->partial(epo->acName, corr);
    493         }
    494 
    495         ll(iObs) = corr->dClk * t_CST::c - DotProduct(AA.Row(iObs), x0);
    496       }
    497 
    498       delete epo;
    499     }
    500 
    501     // Regularization
    502     // --------------
    503     const double Ph = 1.e6;
    504     int iCond = 1;
    505     PP(nObs+iCond) = Ph;
    506     for (int iPar = 1; iPar <= _params.size(); iPar++) {
    507       cmbParam* pp = _params[iPar-1];
    508       if (pp->type == cmbParam::clk &&
    509           AA.Column(iPar).maximum_absolute_value() > 0.0) {
    510         AA(nObs+iCond, iPar) = 1.0;
    511       }
    512     }
    513 
    514     if (!_firstReg) {
    515       _firstReg = true;
    516       for (int iGps = 1; iGps <= MAXPRN_GPS; iGps++) {
    517         ++iCond;
    518         QString prn = QString("G%1").arg(iGps, 2, 10, QChar('0'));
    519         PP(nObs+1+iGps) = Ph;
    520         for (int iPar = 1; iPar <= _params.size(); iPar++) {
    521           cmbParam* pp = _params[iPar-1];
    522           if (pp->type == cmbParam::Sat_offset && pp->prn == prn) {
    523             AA(nObs+iCond, iPar) = 1.0;
    524           }
    525         }
    526       }
    527     }
    528 
    529     const double MAXRES = 999.10;  // TODO: make it an option
    530 
    531     ColumnVector dx;
    532     SymmetricMatrix QQ_sav = _QQ;
    533 
    534     for (int ii = 1; ii < 10; ii++) {
    535       bncModel::kalman(AA, ll, PP, _QQ, dx);
    536       ColumnVector vv = ll - AA * dx;
    537 
    538       int    maxResIndex;
    539       double maxRes = vv.maximum_absolute_value1(maxResIndex);   
    540       out.setRealNumberNotation(QTextStream::FixedNotation);
    541       out.setRealNumberPrecision(3); 
    542       out << "Maximum Residuum " << maxRes << " (index " << maxResIndex << ")\n";
    543 
    544       if (maxRes > MAXRES) {
    545         out << "Outlier Detected" << endl;
    546         _QQ = QQ_sav;
    547         AA.Row(maxResIndex) = 0.0;
    548         ll.Row(maxResIndex) = 0.0;
    549       }
    550       else {
    551         break;
    552       }
    553     }
    554 
    555     for (int iPar = 1; iPar <= _params.size(); iPar++) {
    556       cmbParam* pp = _params[iPar-1];
    557       pp->xx += dx(iPar);
    558       if (pp->type == cmbParam::clk) {
    559         if (resCorr.find(pp->prn) != resCorr.end()) {
    560           resCorr[pp->prn]->dClk = pp->xx / t_CST::c;
    561         }
    562       }
    563       out << currentDateAndTimeGPS().toString("yy-MM-dd hh:mm:ss ").toAscii().data();
    564       out.setRealNumberNotation(QTextStream::FixedNotation);
    565       out.setFieldWidth(8);
    566       out.setRealNumberPrecision(4);
    567       out << pp->toString() << " "
    568           << pp->xx << " +- " << sqrt(_QQ(pp->index,pp->index)) << endl;
    569     }
    570   }
    571 
    572   printResults(out, resTime, resCorr);
    573   dumpResults(resTime, resCorr);
    574 
    575   emit newMessage(_log, false);
    576 }
    577 
    578 // Print results
    579 ////////////////////////////////////////////////////////////////////////////
    580 void bncComb::printResults(QTextStream& out, const bncTime& resTime,
    581                            const QMap<QString, t_corr*>& resCorr) {
    582 
    583   QMapIterator<QString, t_corr*> it(resCorr);
    584   while (it.hasNext()) {
    585     it.next();
    586     t_corr* corr = it.value();
    587     const t_eph* eph = corr->eph;
    588     if (eph) {
    589       double xx, yy, zz, cc;
    590       eph->position(resTime.gpsw(), resTime.gpssec(), xx, yy, zz, cc);
    591 
    592       out << currentDateAndTimeGPS().toString("yy-MM-dd hh:mm:ss ").toAscii().data();
    593       out.setFieldWidth(3);
    594       out << "Full Clock " << corr->prn << " " << corr->iod << " ";
    595       out.setFieldWidth(14);
    596       out << (cc + corr->dClk) * t_CST::c << endl;
    597     }
    598     else {
    599       out << "bncComb::printResuls bug" << endl;
    600     }
    601   }
    602 }
Note: See TracChangeset for help on using the changeset viewer.