00001 #pragma ident "$Id: PRSolution.cpp 3140 2012-06-18 15:03:02Z susancummins $"
00002
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include "MathBase.hpp"
00032 #include "PRSolution.hpp"
00033 #include "GPSEllipsoid.hpp"
00034 #include "Combinations.hpp"
00035 #include "TimeString.hpp"
00036 #include "stl_helpers.hpp"
00037 #include "logstream.hpp"
00038
00039 using namespace std;
00040 using namespace gpstk;
00041
00042 namespace gpstk
00043 {
00044 const string PRSolution::calfmt = string("%04Y/%02m/%02d %02H:%02M:%02S");
00045 const string PRSolution::gpsfmt = string("%4F %10.3g");
00046 const string PRSolution::timfmt = gpsfmt + string(" ") + calfmt;
00047
00048 ostream& operator<<(ostream& os, const WtdAveStats& was)
00049 { was.dump(os,was.getMessage()); return os;}
00050
00051
00052
00053
00054 int PRSolution::PreparePRSolution(const CommonTime& Tr,
00055 vector<SatID>& Sats,
00056 vector<SatID::SatelliteSystem>& Syss,
00057 const vector<double>& Pseudorange,
00058 const XvtStore<SatID> *pEph,
00059 Matrix<double>& SVP) const
00060 throw()
00061 {
00062 int i,j,noeph(0),N,NSVS;
00063 CommonTime tx;
00064 Xvt PVT;
00065
00066
00067 if(Syss.size() == 0) {
00068 for(i=0; i<Sats.size(); i++) {
00069 SatID::SatelliteSystem sys=Sats[i].system;
00070 if(vectorindex(Syss, sys) == -1)
00071 Syss.push_back(sys);
00072 }
00073 }
00074
00075
00076 for(N=0,i=0; i<Sats.size(); i++) {
00077 if(Sats[i].id <= 0) continue;
00078 if(vectorindex(Syss, Sats[i].system) == -1) {
00079 LOG(DEBUG) << " PRSolution ignores satellite (system) "
00080 << RinexSatID(Sats[i]) << " at time " << printTime(Tr,timfmt);
00081 Sats[i].id = -Sats[i].id;
00082 continue;
00083 }
00084 ++N;
00085 }
00086
00087 SVP = Matrix<double>(Sats.size(),4,0.0);
00088 if(N <= 0) return 0;
00089 NSVS = 0;
00090
00091
00092 for(i=0; i<Sats.size(); i++) {
00093
00094
00095 if(Sats[i].id <= 0) {
00096 LOG(DEBUG) << " PRSolution ignores marked satellite "
00097 << RinexSatID(Sats[i]) << " at time " << printTime(Tr,timfmt);
00098 continue;
00099 }
00100
00101
00102 tx = Tr;
00103 tx -= Pseudorange[i]/C_MPS;
00104 try {
00105 PVT = pEph->getXvt(Sats[i], tx);
00106 }
00107 catch(InvalidRequest& e) {
00108 LOG(DEBUG) << "Warning - PRSolution ignores satellite (no ephemeris) "
00109 << RinexSatID(Sats[i]) << " at time " << printTime(tx,timfmt)
00110 << " [" << e.getText() << "]";
00111 Sats[i].id = -::abs(Sats[i].id);
00112 ++noeph;
00113 continue;
00114 }
00115
00116
00117 tx -= PVT.clkbias + PVT.relcorr;
00118 try {
00119 PVT = pEph->getXvt(Sats[i], tx);
00120 }
00121 catch(InvalidRequest& e) {
00122 LOG(DEBUG) << "Warning - PRSolution ignores satellite (no ephemeris 2) "
00123 << RinexSatID(Sats[i]) << " at time " << printTime(tx,timfmt)
00124 << " [" << e.getText() << "]";
00125 Sats[i].id = -::abs(Sats[i].id);
00126 ++noeph;
00127 continue;
00128 }
00129
00130
00131 for(j=0; j<3; j++) SVP(i,j) = PVT.x[j];
00132 SVP(i,3) = Pseudorange[i] + C_MPS * (PVT.clkbias + PVT.relcorr);
00133
00134 LOG(DEBUG) << "SVP: Sat " << RinexSatID(Sats[i])
00135 << " PR " << fixed << setprecision(3) << Pseudorange[i]
00136 << " clkbias " << C_MPS*PVT.clkbias
00137 << " relcorr " << C_MPS*PVT.relcorr;
00138
00139
00140 NSVS++;
00141 }
00142
00143 if(noeph == N) return -4;
00144
00145 return NSVS;
00146
00147 }
00148
00149
00150
00151
00152
00153 int PRSolution::SimplePRSolution(const CommonTime& T,
00154 const vector<SatID>& Sats,
00155 const Matrix<double>& SVP,
00156 const Matrix<double>& invMC,
00157 TropModel *pTropModel,
00158 const int& niterLimit,
00159 const double& convLimit,
00160 const vector<SatID::SatelliteSystem>& Syss,
00161 const Vector<double>& APSol,
00162 Vector<double>& Resids,
00163 Vector<double>& Slopes)
00164 throw(Exception)
00165 {
00166 if(!pTropModel) {
00167 Exception e("Undefined tropospheric model");
00168 GPSTK_THROW(e);
00169 }
00170 if(Sats.size() != SVP.rows() ||
00171 (invMC.rows() > 0 && invMC.rows() != Sats.size())) {
00172 LOG(ERROR) << "Sats has length " << Sats.size();
00173 LOG(ERROR) << "SVP has dimension " << SVP.rows() << "x" << SVP.cols();
00174 LOG(ERROR) << "invMC has dimension " << invMC.rows() << "x" << invMC.cols();
00175 Exception e("Invalid dimensions");
00176 GPSTK_THROW(e);
00177 }
00178 if(Syss.size() == 0) {
00179 Exception e("Allowed satellite systems input (Syss) is empty!");
00180 GPSTK_THROW(e);
00181 }
00182
00183 int iret(0),i,j,k,n;
00184 double rho,wt,svxyz[3];
00185 GPSEllipsoid ellip;
00186
00187 Valid = false;
00188
00189 try {
00190
00191
00192 vector<SatID::SatelliteSystem> mySyss;
00193 {
00194
00195 vector<SatID::SatelliteSystem> tempSyss;
00196 for(Nsvs=0,i=0; i<Sats.size(); i++) {
00197 if(Sats[i].id <= 0)
00198 continue;
00199
00200 SatID::SatelliteSystem sys(Sats[i].system);
00201 if(vectorindex(Syss, sys) == -1)
00202 continue;
00203
00204 Nsvs++;
00205 if(vectorindex(tempSyss, sys) == -1)
00206 tempSyss.push_back(sys);
00207 }
00208
00209
00210 for(i=0; i<Syss.size(); i++)
00211 if(vectorindex(tempSyss, Syss[i]) != -1)
00212 mySyss.push_back(Syss[i]);
00213 }
00214
00215
00216 const int dim(3 + mySyss.size());
00217
00218
00219 if(Nsvs < dim) return -3;
00220
00221
00222
00223 Matrix<double> iMC;
00224 if(invMC.rows() > 0) {
00225 LOG(DEBUG) << "Build inverse MCov";
00226 iMC = Matrix<double>(Nsvs,Nsvs,0.0);
00227 for(n=0,i=0; i<Sats.size(); i++) {
00228 if(Sats[i].id <= 0) continue;
00229 for(k=0,j=0; j<Sats.size(); j++) {
00230 if(Sats[j].id <= 0) continue;
00231 iMC(n,k) = invMC(i,j);
00232 ++k;
00233 }
00234 ++n;
00235 }
00236 LOG(DEBUG) << "inv MCov matrix is\n" << fixed << setprecision(4) << iMC;
00237 }
00238
00239
00240
00241 Vector<double> CRange(Nsvs),dX(dim);
00242 Matrix<double> P(Nsvs,dim,0.0),PT,G(dim,Nsvs),PG(Nsvs,Nsvs),Rotation;
00243 Triple dirCos;
00244 Xvt SV,RX;
00245
00246 Solution.resize(dim);
00247 Covariance.resize(dim,dim);
00248 Resids.resize(Nsvs);
00249 Slopes.resize(Nsvs);
00250 LOG(DEBUG) << " Solution dimension is " << dim << " and Nsvs is " << Nsvs;
00251
00252
00253
00254 int n_iterate(0), niter_limit(niterLimit < 2 ? 2 : niterLimit);
00255 double converge(0.0);
00256
00257
00258 if(APSol.size() == 0) Solution = Vector<double>(dim,0.0);
00259 else {
00260
00261 Solution = APSol;
00262
00263 LOG(DEBUG) << " apriori solution (" << Solution.size() << ") is [ "
00264 << fixed << setprecision(3) << Solution << " ]";
00265 }
00266
00267
00268
00269 do {
00270 TropFlag = false;
00271
00272
00273 RX.x = Triple(Solution(0),Solution(1),Solution(2));
00274
00275
00276 for(n=0,i=0; i<Sats.size(); i++) {
00277
00278 if(Sats[i].id <= 0) continue;
00279
00280
00281
00282 if(n_iterate == 0)
00283 rho = 0.070;
00284 else
00285 rho = RSS(SVP(i,0)-Solution(0),
00286 SVP(i,1)-Solution(1), SVP(i,2)-Solution(2))/ellip.c();
00287
00288
00289 wt = ellip.angVelocity()*rho;
00290 svxyz[0] = ::cos(wt)*SVP(i,0) + ::sin(wt)*SVP(i,1);
00291 svxyz[1] = -::sin(wt)*SVP(i,0) + ::cos(wt)*SVP(i,1);
00292 svxyz[2] = SVP(i,2);
00293
00294
00295 rho = RSS(svxyz[0]-Solution(0),
00296 svxyz[1]-Solution(1),
00297 svxyz[2]-Solution(2));
00298
00299
00300 dirCos[0] = (Solution(0)-svxyz[0])/rho;
00301 dirCos[1] = (Solution(1)-svxyz[1])/rho;
00302 dirCos[2] = (Solution(2)-svxyz[2])/rho;
00303
00304
00305
00306 CRange(n) = SVP(i,3) - rho;
00307
00308
00309 if(n_iterate > 0) {
00310 SV.x = Triple(svxyz[0],svxyz[1],svxyz[2]);
00311 Position R,S;
00312 R.setECEF(RX.x[0],RX.x[1],RX.x[2]);
00313 S.setECEF(SV.x[0],SV.x[1],SV.x[2]);
00314
00315
00316 double tc(R.getHeight());
00317
00318 if(R.elevation(S) < 0.0 || tc > 100000.0 || tc < -1000.0) {
00319 tc = 0.0;
00320 TropFlag = true;
00321 }
00322 else
00323 tc = pTropModel->correction(R,S,T);
00324
00325 CRange(n) -= tc;
00326 LOG(DEBUG) << "Trop " << i << " " << Sats[i] << " "
00327 << fixed << setprecision(3) << tc;
00328
00329 }
00330
00331
00332 j = 3 + vectorindex(mySyss, Sats[i].system);
00333
00334
00335 const double clk(Solution(j));
00336 LOG(DEBUG) << "Clock is (" << j << ") " << clk;
00337
00338
00339 Resids(n) = CRange(n) - clk;
00340
00341
00342
00343 P(n,0) = dirCos[0];
00344 P(n,1) = dirCos[1];
00345 P(n,2) = dirCos[2];
00346 P(n,j) = 1.0;
00347
00348
00349
00350 n++;
00351
00352 }
00353
00354 if(n != Nsvs) {
00355 Exception e("Counting error after satellite loop");
00356 GPSTK_THROW(e);
00357 }
00358
00359 LOG(DEBUG) << "Partials (" << P.rows() << "x" << P.cols() << ")\n"
00360 << fixed << setprecision(4) << P;
00361 LOG(DEBUG) << "Resids (" << Resids.size() << ") "
00362 << fixed << setprecision(3) << Resids;
00363
00364
00365
00366 PT = transpose(P);
00367
00368
00369 if(invMC.rows() > 0) Covariance = PT * iMC * P;
00370 else Covariance = PT * P;
00371 LOG(DEBUG) << "Computed inverse cov";
00372
00373
00374 try {
00375 Covariance = inverseSVD(Covariance);
00376 }
00377 catch(SingularMatrixException& sme) { return -2; }
00378
00379
00380 if(invMC.rows() > 0) G = Covariance * PT * iMC;
00381 else G = Covariance * PT;
00382
00383
00384 PG = P * G;
00385 LOG(DEBUG) << "Computed PG";
00386
00387 n_iterate++;
00388
00389
00390
00391 dX = G * Resids;
00392 LOG(DEBUG) << "Computed dX(" << dX.size() << ")";
00393 Solution += dX;
00394
00395
00396
00397 converge = norm(dX);
00398 if(n_iterate > 1 && converge < convLimit) {
00399 iret = 0;
00400 break;
00401 }
00402 if(n_iterate >= niterLimit || converge > 1.e10) {
00403 iret = -1;
00404 break;
00405 }
00406
00407 } while(1);
00408 LOG(DEBUG) << "Out of iteration loop";
00409
00410 if(TropFlag) LOG(DEBUG) << "Trop correction not applied at time "
00411 << printTime(T,timfmt);
00412
00413
00414 MaxSlope = 0.0;
00415 Slopes = 0.0;
00416 if(iret == 0) for(j=0,i=0; i<Sats.size(); i++) {
00417 if(Sats[i].id <= 0) continue;
00418
00419 for(int k=0; k<dim; k++) Slopes(j) += G(k,j)*G(k,j);
00420 Slopes(j) = SQRT(Slopes(j)*double(n-dim)/(1.0-PG(j,j)));
00421
00422 if(Slopes(j) > MaxSlope) MaxSlope = Slopes(j);
00423
00424 j++;
00425 }
00426
00427
00428 if(APSol.size() != 0)
00429 PreFitResidual = P*(Solution-APSol) - Resids;
00430
00431
00432 RMSResidual = RMS(Resids);
00433
00434
00435 MaxSlope = 0.0;
00436 for(i=0; i<Slopes.size(); i++)
00437 if(Slopes(i) > MaxSlope)
00438 MaxSlope = Slopes[i];
00439
00440
00441 currTime = T;
00442 SatelliteIDs = Sats;
00443 SystemIDs = mySyss;
00444 invMeasCov = iMC;
00445 Partials = P;
00446 NIterations = n_iterate;
00447 Convergence = converge;
00448 Valid = true;
00449
00450 return iret;
00451
00452 } catch(Exception& e) { GPSTK_RETHROW(e); }
00453
00454 }
00455
00456
00457
00458
00459 int PRSolution::RAIMCompute(const CommonTime& Tr,
00460 vector<SatID>& Sats,
00461 vector<SatID::SatelliteSystem>& Syss,
00462 const vector<double>& Pseudorange,
00463 const Matrix<double>& invMC,
00464 const XvtStore<SatID> *pEph,
00465 TropModel *pTropModel)
00466 throw(Exception)
00467 {
00468 try {
00469 int iret,i,j,N;
00470 vector<int> GoodIndexes;
00471
00472
00473 bool BestTropFlag(false);
00474 int BestNIter(0),BestIret(-5);
00475 double BestRMS(-1.0),BestSL(0.0),BestConv(0.0);
00476 Vector<double> BestSol(3,0.0),BestPFR;
00477 vector<SatID> BestSats,SaveSats;
00478 Matrix<double> SVP,BestCov,BestInvMCov,BestPartials;
00479 vector<SatID::SatelliteSystem> BestSyss;
00480
00481
00482 Valid = false;
00483 currTime = Tr;
00484 TropFlag = SlopeFlag = RMSFlag = false;
00485
00486
00487
00488
00489
00490
00491 N = PreparePRSolution(Tr, Sats, Syss, Pseudorange, pEph, SVP);
00492
00493 if(LOGlevel >= ConfigureLOG::Level("DEBUG")) {
00494 ostringstream oss;
00495 oss << "RAIMCompute: after PrepareAS(): Satellites:";
00496 for(i=0; i<Sats.size(); i++) {
00497 RinexSatID rs(::abs(Sats[i].id), Sats[i].system);
00498 oss << " " << (Sats[i].id < 0 ? "-" : "") << rs;
00499 }
00500 oss << endl;
00501
00502 oss << " SVP matrix("
00503 << SVP.rows() << "," << SVP.cols() << ")" << endl;
00504 oss << fixed << setw(16) << setprecision(5) << SVP;
00505
00506 LOG(DEBUG) << oss.str();
00507 }
00508
00509
00510 if(N <= 0) return -4;
00511
00512
00513
00514
00515
00516
00517
00518 SaveSats = Sats;
00519 for(i=0; i<Sats.size(); i++)
00520 if(Sats[i].id > 0)
00521 GoodIndexes.push_back(i);
00522
00523
00524 if(LOGlevel >= ConfigureLOG::Level("DEBUG")) {
00525 ostringstream oss;
00526 oss << " Good satellites (" << N << ") are:";
00527 for(i=0; i<GoodIndexes.size(); i++)
00528 oss << " " << RinexSatID(Sats[GoodIndexes[i]]);
00529 LOG(DEBUG) << oss.str();
00530 }
00531
00532
00533
00534
00535
00536
00537 Vector<double> Slopes;
00538
00539 Vector<double> Resids;
00540
00541
00542 int stage(0);
00543
00544 do {
00545
00546 Combinations Combo(N,stage);
00547
00548
00549 do {
00550
00551 Sats = SaveSats;
00552 for(i=0; i<GoodIndexes.size(); i++)
00553 if(Combo.isSelected(i))
00554 Sats[GoodIndexes[i]].id = -::abs(Sats[GoodIndexes[i]].id);
00555
00556 if(LOGlevel >= ConfigureLOG::Level("DEBUG")) {
00557 ostringstream oss;
00558 oss << " RAIM: Try the combo ";
00559 for(i=0; i<Sats.size(); i++) {
00560 RinexSatID rs(::abs(Sats[i].id), Sats[i].system);
00561 oss << " " << (Sats[i].id < 0 ? "-" : " ") << rs;
00562 }
00563 LOG(DEBUG) << oss.str();
00564 }
00565
00566
00567 Vector<double> APSol(4,0.0);
00568 if(hasMemory) APSol = memory.APSolution;
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579 iret = SimplePRSolution(Tr, Sats, SVP, invMC, pTropModel,
00580 MaxNIterations, ConvergenceLimit, Syss, APSol, Resids, Slopes);
00581
00582 LOG(DEBUG) << " RAIM: SimplePRS returns " << iret;
00583 if(iret <= 0 && iret > BestIret) BestIret = iret;
00584
00585
00586
00587 if(iret < 0) {
00588 if(iret == -1) {
00589 LOG(DEBUG) << " SPS: Failed to converge - go on";
00590 continue;
00591 }
00592 else if(iret == -2) {
00593 LOG(DEBUG) << " SPS: singular - go on";
00594 continue;
00595 }
00596 else if(iret == -3) {
00597 LOG(DEBUG) <<" SPS: not enough satellites: quit";
00598 break;
00599 }
00600 else if(iret == -4) {
00601 LOG(DEBUG) <<" SPS: no ephemeris: quit";
00602 break;
00603 }
00604 }
00605
00606
00607
00608 LOG(DEBUG) << outputString(string("RPS"),iret);
00609
00610
00611
00612
00613
00614
00615
00616
00617 if(BestRMS < 0.0 || RMSResidual < BestRMS) {
00618 BestRMS = RMSResidual;
00619 BestSol = Solution;
00620 BestSats = SatelliteIDs;
00621 BestSyss = SystemIDs;
00622 BestSL = MaxSlope;
00623 BestConv = Convergence;
00624 BestNIter = NIterations;
00625 BestCov = Covariance;
00626 BestInvMCov = invMeasCov;
00627 BestPartials = Partials;
00628 BestPFR = PreFitResidual;
00629 BestTropFlag = TropFlag;
00630 BestIret = iret;
00631 }
00632
00633 if(stage==0 && RMSResidual < RMSLimit)
00634 break;
00635
00636 } while(Combo.Next() != -1);
00637
00638
00639 if(BestRMS > 0.0 && BestRMS < RMSLimit) {
00640 LOG(DEBUG) << " RAIM: Success in the RAIM loop";
00641 iret = 0;
00642 break;
00643 }
00644
00645
00646 stage++;
00647
00648
00649 if(NSatsReject > -1 && stage > NSatsReject) {
00650 LOG(DEBUG) << " RAIM: break before stage " << stage
00651 << " due to NSatsReject " << NSatsReject;
00652 break;
00653 }
00654
00655
00656 if(iret == -3 || iret == -4) {
00657 LOG(DEBUG) << " RAIM: break before stage " << stage
00658 << "; " << (iret==-3 ? "too few sats" : "no ephemeris");
00659 break;
00660 }
00661
00662 LOG(DEBUG) << " RAIM: go to stage " << stage;
00663
00664 } while(1);
00665
00666
00667
00668 if(iret >= 0) {
00669 Sats = SatelliteIDs = BestSats;
00670 SystemIDs = BestSyss;
00671 Solution = BestSol;
00672 Covariance = BestCov;
00673 invMeasCov = BestInvMCov;
00674 Partials = BestPartials;
00675 PreFitResidual = BestPFR;
00676 Convergence = BestConv;
00677 NIterations = BestNIter;
00678 RMSResidual = BestRMS;
00679 MaxSlope = BestSL;
00680 TropFlag = BestTropFlag;
00681 iret = BestIret;
00682
00683
00684 if(Syss.size() != BestSyss.size()) {
00685 N = 3+Syss.size();
00686 Solution = Vector<double>(N,0.0);
00687 Covariance = Matrix<double>(N,N,0.0);
00688 Partials = Matrix<double>(BestPartials.rows(),N,0.0);
00689
00690
00691 vector<int> indexes;
00692 for(j=0,i=0; i<Syss.size(); i++)
00693 indexes.push_back(Syss[i] == BestSyss[j] ? j++ : -1);
00694
00695
00696 for(i=0; i<3; i++) {
00697 Solution(i) = BestSol(i);
00698 for(j=0; j<Partials.rows(); j++) Partials(i,j) = BestPartials(i,j);
00699 for(j=0; j<3; j++) Covariance(i,j) = BestCov(i,j);
00700 for(j=0; j<indexes.size(); j++) {
00701 Covariance(i,3+j)=(indexes[j]==-1 ? 0.:BestCov(i,3+indexes[j]));
00702 Covariance(3+j,i)=(indexes[j]==-1 ? 0.:BestCov(3+indexes[j],i));
00703 }
00704 }
00705
00706
00707 for(j=0; j<indexes.size(); j++) {
00708 int n(indexes[j]);
00709 bool ok(n != -1);
00710 Solution(3+j) = (ok ? BestSol(3+n) : 0.0);
00711 for(i=0; i<Partials.rows(); i++)
00712 Partials(i,3+j) = (ok ? BestPartials(i,3+n) : 0.0);
00713 for(i=0; i<indexes.size(); i++) {
00714 Covariance(3+i,3+j) = (ok ? BestCov(3+i,3+n) : 0.0);
00715 Covariance(3+j,3+i) = (ok ? BestCov(3+n,3+i) : 0.0);
00716 }
00717 }
00718 }
00719
00720
00721 for(Nsvs=0,i=0; i<SatelliteIDs.size(); i++)
00722 if(SatelliteIDs[i].id > 0)
00723 Nsvs++;
00724 }
00725
00726 if(iret==0) {
00727 if(BestSL > SlopeLimit) { iret = 1; SlopeFlag = true; }
00728 if(BestSL > SlopeLimit/2.0 && Nsvs == 5) { iret = 1; SlopeFlag = true; }
00729 if(BestRMS >= RMSLimit) { iret = 1; RMSFlag = true; }
00730 if(TropFlag) iret = 1;
00731 Valid = true;
00732
00733
00734 DOPCompute();
00735
00736
00737 if(hasMemory)
00738 memory.add(Solution, Covariance, PreFitResidual, Partials, invMeasCov);
00739 }
00740
00741 LOG(DEBUG) << " RAIM exit with ret value " << iret
00742 << " and Valid " << (Valid ? "T":"F");
00743
00744 return iret;
00745 }
00746 catch(Exception& e) {
00747 GPSTK_RETHROW(e);
00748 }
00749 }
00750
00751
00752
00753 int PRSolution::DOPCompute(void) throw(Exception)
00754 {
00755 try {
00756 Matrix<double> PTP(transpose(Partials)*Partials);
00757 Matrix<double> Cov(inverseLUD(PTP));
00758
00759 PDOP = SQRT(Cov(0,0)+Cov(1,1)+Cov(2,2));
00760
00761 TDOP = 0.0;
00762 for(int i=3; i<Cov.rows(); i++) TDOP += Cov(i,i);
00763 TDOP = SQRT(TDOP);
00764
00765 GDOP = RSS(PDOP,TDOP);
00766
00767 return 0;
00768 }
00769 catch(Exception& e) { GPSTK_RETHROW(e); }
00770 }
00771
00772
00773
00774 string PRSolution::outputValidString(int iret) throw()
00775 {
00776 ostringstream oss;
00777 if(iret != -99) {
00778 oss << " (" << iret << " " << errorCodeString(iret);
00779 if(iret==1) {
00780 oss << " due to";
00781 if(RMSFlag) oss << " large RMS residual";
00782 if(SlopeFlag) oss << " large slope";
00783 if(TropFlag) oss << " missed trop. corr.";
00784 }
00785 oss << ") " << (Valid ? "" : "N") << "V";
00786 }
00787 return oss.str();
00788 }
00789
00790 string PRSolution::outputNAVString(string tag, int iret, const Vector<double>& Vec)
00791 throw()
00792 {
00793 ostringstream oss;
00794
00795
00796 oss << tag << " NAV " << printTime(currTime,gpsfmt)
00797 << fixed << setprecision(6)
00798 << " " << setw(16) << (&Vec==&PRSNullVector ? Solution(0) : Vec(0))
00799 << " " << setw(16) << (&Vec==&PRSNullVector ? Solution(1) : Vec(1))
00800 << " " << setw(16) << (&Vec==&PRSNullVector ? Solution(2) : Vec(2))
00801 << fixed << setprecision(3);
00802 for(int i=0; i<SystemIDs.size(); i++) {
00803 RinexSatID sat(1,SystemIDs[i]);
00804 oss << " " << sat.systemString3() << " " << setw(11) << Solution(3+i);
00805 }
00806 oss << outputValidString(iret);
00807
00808 return oss.str();
00809 }
00810
00811 string PRSolution::outputPOSString(string tag, int iret, const Vector<double>& Vec)
00812 throw()
00813 {
00814 ostringstream oss;
00815
00816
00817 oss << tag << " POS " << printTime(currTime,gpsfmt)
00818 << fixed << setprecision(6)
00819 << " " << setw(16) << (&Vec==&PRSNullVector ? Solution(0) : Vec(0))
00820 << " " << setw(16) << (&Vec==&PRSNullVector ? Solution(1) : Vec(1))
00821 << " " << setw(16) << (&Vec==&PRSNullVector ? Solution(2) : Vec(2))
00822 << outputValidString(iret);
00823
00824 return oss.str();
00825 }
00826
00827 string PRSolution::outputCLKString(string tag, int iret) throw()
00828 {
00829 ostringstream oss;
00830
00831
00832 oss << tag << " CLK " << printTime(currTime,gpsfmt)
00833 << fixed << setprecision(3);
00834 for(int i=0; i<SystemIDs.size(); i++) {
00835 RinexSatID sat(1,SystemIDs[i]);
00836 oss << " " << sat.systemString3() << " " << setw(11) << Solution(3+i);
00837 }
00838 oss << outputValidString(iret);
00839
00840 return oss.str();
00841 }
00842
00843
00844 string PRSolution::outputRMSString(string tag, int iret) throw()
00845 {
00846 ostringstream oss;
00847
00848
00849 oss << tag << " RMS " << printTime(currTime,gpsfmt)
00850 << " " << setw(2) << SatelliteIDs.size()-Nsvs
00851 << " " << setw(2) << Nsvs
00852 << fixed << setprecision(3)
00853 << " " << setw(8) << RMSResidual
00854 << setprecision(2)
00855 << " " << setw(7) << TDOP
00856 << " " << setw(7) << PDOP
00857 << " " << setw(7) << GDOP
00858 << setprecision(1)
00859 << " " << setw(5) << MaxSlope
00860 << " " << setw(2) << NIterations
00861 << scientific << setprecision(2)
00862 << " " << setw(8) << Convergence;
00863 for(int i=0; i<SatelliteIDs.size(); i++) {
00864 RinexSatID rs(::abs(SatelliteIDs[i].id), SatelliteIDs[i].system);
00865 oss << " " << (SatelliteIDs[i].id < 0 ? "-" : " ") << rs;
00866 }
00867 oss << outputValidString(iret);
00868
00869 return oss.str();
00870 }
00871
00872 string PRSolution::outputString(string tag, int iret, const Vector<double>& Vec)
00873 throw()
00874 {
00875 ostringstream oss;
00876 oss << outputNAVString(tag,iret,Vec) << endl;
00877 oss << outputRMSString(tag,iret);
00878
00879 return oss.str();
00880 }
00881
00882 string PRSolution::errorCodeString(int iret) throw()
00883 {
00884 string str("unknown");
00885 if(iret == 1) str = string("ok but perhaps degraded");
00886 else if(iret== 0) str = string("ok");
00887 else if(iret==-1) str = string("failed to converge");
00888 else if(iret==-2) str = string("singular solution");
00889 else if(iret==-3) str = string("not enough satellites");
00890 else if(iret==-4) str = string("not any ephemeris");
00891 return str;
00892 }
00893
00894 string PRSolution::configString(string tag) throw()
00895 {
00896 ostringstream oss;
00897 oss << tag << " " << printTime(currTime,timfmt)
00898 << (Valid ? "":" not") << " valid,"
00899 << (Mixed ? "":" not") << " mixed"
00900 << "\n iterations " << MaxNIterations
00901 << "\n convergence " << scientific << setprecision(2) << ConvergenceLimit
00902 << "\n RMS residual limit " << fixed << RMSLimit
00903 << "\n RAIM slope limit " << fixed << SlopeLimit << " meters"
00904 << "\n Maximum number of satellites to reject is " << NSatsReject
00905 << "\n Memory information IS " << (hasMemory ? "":"NOT ") << "stored"
00906 ;
00907
00908
00909
00910
00911
00912
00913
00914 return oss.str();
00915 }
00916
00917 const Vector<double> PRSolution::PRSNullVector;
00918
00919 }
00920