Changeset 3202 in ntrip
- Timestamp:
- Mar 30, 2011, 4:15:54 PM (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/BNC/combination/bnccomb.cpp
r3201 r3202 299 299 else { 300 300 newEpoch->corr[newCorr->prn] = newCorr; 301 } 302 } 303 304 // Change the correction so that it refers to last received ephemeris 305 //////////////////////////////////////////////////////////////////////////// 306 void 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 //////////////////////////////////////////////////////////////////////////// 343 void 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 //////////////////////////////////////////////////////////////////////////// 518 void 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 } 301 539 } 302 540 } … … 363 601 } 364 602 } 365 366 // Change the correction so that it refers to last received ephemeris367 ////////////////////////////////////////////////////////////////////////////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->prn391 + 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 Epochs404 ////////////////////////////////////////////////////////////////////////////405 void bncComb::processEpochs(const QList<cmbEpoch*>& epochs) {406 407 _log.clear();408 409 QTextStream out(&_log, QIODevice::WriteOnly);410 411 out << "Combination:" << endl412 << "------------------------------" << endl;413 414 // Predict Parameters Values, Add White Noise415 // ------------------------------------------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 Observations440 // ------------------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 ephemeris450 // ------------------------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 // Regularization502 // --------------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 option530 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 results579 ////////////////////////////////////////////////////////////////////////////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.