00001 #pragma ident "$Id: PRSolution.cpp 2503 2011-02-13 08:29:37Z yanweignss $"
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00030 #include "MathBase.hpp"
00031 #include "PRSolution.hpp"
00032 #include "GPSGeoid.hpp"
00033
00034
00035
00036
00043 class Combinations {
00044 public:
00046 Combinations(void)
00047 throw()
00048 {
00049 nc = n = k = 0;
00050 Index = NULL;
00051 }
00052
00055 Combinations(int N, int K)
00056 throw(gpstk::Exception)
00057 {
00058 try { init(N,K); }
00059 catch(gpstk::Exception& e) { GPSTK_RETHROW(e); }
00060 }
00061
00063 Combinations(const Combinations& right)
00064 throw()
00065 {
00066 *this = right;
00067 }
00068
00070 ~Combinations(void)
00071 {
00072 if(Index) delete[] Index;
00073 Index = NULL;
00074 }
00075
00077 Combinations& operator=(const Combinations& right)
00078 throw()
00079 {
00080 this->~Combinations();
00081 init(right.n,right.k);
00082 nc = right.nc;
00083 for(int j=0; j<k; j++) Index[j] = right.Index[j];
00084 return *this;
00085 }
00086
00089 int Next(void) throw();
00090
00093 int Selection(int j)
00094 throw()
00095 {
00096 if(j < 0 || j >= k) return -1;
00097 return Index[j];
00098 }
00099
00102 bool isSelected(int j)
00103 throw()
00104 {
00105 for(int i=0; i<k; i++)
00106 if(Index[i] == j) return true;
00107 return false;
00108 }
00109
00110 private:
00111
00114 void init(int N, int K)
00115 throw(gpstk::Exception);
00116
00118 int Increment(int j) throw();
00119
00120 int nc;
00121 int k,n;
00122 int* Index;
00123 };
00124
00125
00126 int Combinations::Next(void)
00127 throw()
00128 {
00129 if(k < 1) return -1;
00130 if(Increment(k-1) != -1) return ++nc;
00131 return -1;
00132 }
00133
00134 int Combinations::Increment(int j)
00135 throw()
00136 {
00137 if(Index[j] < n-k+j) {
00138 Index[j]++;
00139 for(int m=j+1; m<k; m++)
00140 Index[m]=Index[m-1]+1;
00141 return 0;
00142 }
00143
00144 if(j-1 < 0) return -1;
00145
00146 return Increment(j-1);
00147 }
00148
00149 void Combinations::init(int N, int K)
00150 throw(gpstk::Exception)
00151 {
00152 if(K > N || N < 0 || K < 0) {
00153 gpstk::Exception e("Combinations(n,k) must have k <= n, with n,k >= 0");
00154 GPSTK_THROW(e);
00155 }
00156
00157 if(K > 0) {
00158 Index = new int[K];
00159 if(!Index) {
00160 gpstk::Exception e("Could not allocate");
00161 GPSTK_THROW(e);
00162 }
00163 }
00164 else Index = NULL;
00165
00166 nc = 0;
00167 k = K;
00168 n = N;
00169 for(int j=0; j<k; j++)
00170 Index[j]=j;
00171 }
00172
00173
00174 using namespace std;
00175 using namespace gpstk;
00176
00177 namespace gpstk
00178 {
00179 int PRSolution::RAIMCompute(const DayTime& Tr,
00180 vector<SatID>& Satellite,
00181 const vector<double>& Pseudorange,
00182 const XvtStore<SatID>& Eph,
00183 TropModel *pTropModel)
00184 throw(Exception)
00185 {
00186 try {
00187 int iret,jret,i,j,N,Nreject,MinSV,stage;
00188 vector<bool> UseSat,UseSave;
00189 vector<int> GoodIndexes;
00190
00191 int BestNIter=0;
00192 double BestRMS=0.0,BestSL=0.0,BestConv=0.0;
00193 Vector<double> BestSol(3,0.0);
00194 vector<bool> BestUse;
00195 BestRMS = -1.0;
00196 Matrix<double> BestCovariance;
00197
00198
00199
00200 Valid = false;
00201
00202
00203
00204 if(Solution.size() != 4) { Solution.resize(4); Solution = 0.0; }
00205 APrioriSolution = Solution;
00206
00207
00208
00209
00210 i = PrepareAutonomousSolution(Tr, Satellite, Pseudorange, Eph, SVP,
00211 Debug?pDebugStream:0);
00212 if(Debug && pDebugStream) {
00213 *pDebugStream << "In RAIMCompute after PAS(): Satellites:";
00214 for(j=0; j<Satellite.size(); j++) {
00215 RinexSatID rs(::abs(Satellite[j].id), Satellite[j].system);
00216 *pDebugStream << " " << (Satellite[j].id < 0 ? "-":"") << rs;
00217 }
00218 *pDebugStream << endl;
00219 *pDebugStream << " SVP matrix("
00220 << SVP.rows() << "," << SVP.cols() << ")" << endl;
00221 *pDebugStream << fixed << setw(16) << setprecision(3) << SVP << endl;
00222 }
00223 if(i) return i;
00224
00225
00226
00227
00228
00229
00230
00231 for(N=0,i=0; i<Satellite.size(); i++) {
00232 if(Satellite[i].id > 0) {
00233 N++;
00234 UseSat.push_back(true);
00235 GoodIndexes.push_back(i);
00236 }
00237 else UseSat.push_back(false);
00238 }
00239 UseSave = UseSat;
00240
00241
00242
00243
00244
00245
00246
00247
00248 if(N < 4) return -3;
00249
00250
00251 MinSV = 5;
00252
00253 if(!ResidualCriterion || NSatsReject==0) MinSV=4;
00254
00255
00256
00257 Nreject = NSatsReject;
00258 if(Nreject == -1 || Nreject > N-MinSV)
00259 Nreject=N-MinSV;
00260
00261
00262
00263
00264
00265
00266 Vector<double> Slopes(Pseudorange.size());
00267
00268
00269 Vector<double> Residuals(Satellite.size(),0.0);
00270
00271
00272 stage = 0;
00273
00274 do {
00275
00276 Combinations Combo(N,stage);
00277
00278
00279 do {
00280
00281 UseSat = UseSave;
00282 for(i=0; i<GoodIndexes.size(); i++)
00283 if(Combo.isSelected(i)) UseSat[GoodIndexes[i]]=false;
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293 NIterations = MaxNIterations;
00294 Convergence = ConvergenceLimit;
00295 iret = AutonomousPRSolution(Tr, UseSat, SVP, pTropModel, Algebraic,
00296 NIterations, Convergence, Solution, Covariance, Residuals, Slopes,
00297 Debug?pDebugStream:0);
00298
00299
00300
00301 if(!ResidualCriterion) {
00302
00303 Vector<double> D=Solution-APrioriSolution;
00304 RMSResidual = RMS(D);
00305 }
00306 else {
00307
00308 RMSResidual = RMS(Residuals);
00309 }
00310
00311 MaxSlope = 0.0;
00312 if(iret == 0)
00313 for(i=0; i<UseSat.size(); i++)
00314 if(UseSat[i] && Slopes(i)>MaxSlope) MaxSlope=Slopes[i];
00315
00316
00317
00318 if(Debug && pDebugStream) {
00319 *pDebugStream << "RPS " << setw(2) << stage
00320 << " " << setw(4) << Tr.GPSfullweek()
00321 << " " << fixed << setw(10) << setprecision(3) << Tr.GPSsecond()
00322 << " " << setw(2) << N-stage << setprecision(6)
00323 << " " << setw(16) << Solution(0)
00324 << " " << setw(16) << Solution(1)
00325 << " " << setw(16) << Solution(2)
00326 << " " << setw(14) << Solution(3)
00327 << " " << setw(12) << RMSResidual
00328 << " " << fixed << setw(5) << setprecision(1) << MaxSlope
00329 << " " << NIterations
00330 << " " << scientific << setw(8) << setprecision(2)<< Convergence;
00331
00332 for(i=0; i<UseSat.size(); i++) {
00333 if(UseSat[i])
00334 *pDebugStream << " " << setw(3)<< Satellite[i].id;
00335 else
00336 *pDebugStream << " " << setw(3) << -::abs(Satellite[i].id);
00337 }
00338
00339 *pDebugStream << " (" << iret << ")" << endl;
00340 }
00341
00342
00343
00344 if(iret) {
00345 RMSResidual = 0.0;
00346 Solution = 0.0;
00347 }
00348 else {
00349
00350 if(BestRMS < 0.0 || RMSResidual < BestRMS) {
00351 BestRMS = RMSResidual;
00352 BestSol = Solution;
00353 BestUse = UseSat;
00354 BestSL = MaxSlope;
00355 BestConv = Convergence;
00356 BestNIter = NIterations;
00357 BestCovariance = Covariance;
00358 }
00359
00360 if((stage==0 || ReturnAtOnce) && RMSResidual < RMSLimit)
00361 break;
00362 }
00363
00364
00365 } while(Combo.Next() != -1);
00366
00367
00368 if(BestRMS > 0.0 && BestRMS < RMSLimit) {
00369 iret=0;
00370 break;
00371 }
00372
00373
00374 stage++;
00375 if(stage > Nreject) break;
00376
00377 } while(iret == 0 || iret == -1);
00378
00379
00380
00381 Convergence = BestConv;
00382 NIterations = BestNIter;
00383 RMSResidual = BestRMS;
00384 Solution = BestSol;
00385 MaxSlope = BestSL;
00386 Covariance = BestCovariance;
00387 for(Nsvs=0,i=0; i<BestUse.size(); i++) {
00388 if(!BestUse[i]) Satellite[i].id = -::abs(Satellite[i].id);
00389 else Nsvs++;
00390 }
00391
00392 if(iret==0 && BestSL > SlopeLimit) iret=1;
00393 if(iret==0 && BestSL > SlopeLimit/2.0 && Nsvs == 5) iret=1;
00394 if(iret>=0 && BestRMS >= RMSLimit) iret=2;
00395
00396 if(iret==0) Valid=true;
00397
00398 return iret;
00399 }
00400 catch(Exception& e) {
00401 GPSTK_RETHROW(e);
00402 }
00403 }
00404
00405
00406
00407
00408 int PRSolution::PrepareAutonomousSolution(const DayTime& Tr,
00409 vector<SatID>& Satellite,
00410 const vector<double>& Pseudorange,
00411 const XvtStore<SatID>& Eph,
00412 Matrix<double>& SVP,
00413 ostream *pDebugStream)
00414 throw()
00415 {
00416 if(pDebugStream) *pDebugStream << "PrepareAutomousSolution at time "
00417 << Tr.printf("%4F %13.6g") << endl;
00418
00419 int i,j,nsvs,N=Satellite.size();
00420 DayTime tx;
00421 Xvt PVT;
00422
00423 if(N <= 0) return 0;
00424 SVP = Matrix<double>(N,4,0.0);
00425 SVP = 0.0;
00426
00427 for(nsvs=0,i=0; i<N; i++) {
00428
00429 if(Satellite[i].id <= 0) continue;
00430
00431
00432 if(Satellite[i].system == SatID::systemGPS)
00433 ;
00434 else {
00435 Satellite[i].id = -::abs(Satellite[i].id);
00436 if(pDebugStream) *pDebugStream
00437 << "Warning: Ignoring satellite (system) " << Satellite[i];
00438 continue;
00439 }
00440
00441
00442 tx = Tr;
00443 tx -= Pseudorange[i]/C_GPS_M;
00444
00445 try {
00446 PVT = Eph.getXvt(Satellite[i], tx);
00447 }
00448 catch(InvalidRequest& e) {
00449 Satellite[i].id = -::abs(Satellite[i].id);
00450 if(pDebugStream) *pDebugStream
00451 << "Warning: PRSolution ignores satellite (ephemeris) "
00452 << Satellite[i] << endl;
00453 continue;
00454 }
00455
00456
00457 tx -= PVT.dtime;
00458 try {
00459 PVT = Eph.getXvt(Satellite[i], tx);
00460 }
00461 catch(InvalidRequest& e) {
00462 Satellite[i].id = -::abs(Satellite[i].id);
00463 continue;
00464 }
00465
00466
00467 for(j=0; j<3; j++) SVP(i,j) = PVT.x[j];
00468 SVP(i,3) = Pseudorange[i] + C_GPS_M * PVT.dtime;
00469 if(pDebugStream) *pDebugStream << "SVP: Sat " << RinexSatID(Satellite[i])
00470 << " PR " << fixed << setprecision(3) << Pseudorange[i]
00471 << " dtime " << C_GPS_M*PVT.dtime << endl;
00472 nsvs++;
00473 }
00474
00475 if(nsvs == 0) return -4;
00476 return 0;
00477
00478 }
00479
00480 int PRSolution::AlgebraicSolution(Matrix<double>& A,
00481 Vector<double>& Q,
00482 Vector<double>& X,
00483 Vector<double>& R)
00484 {
00485 try {
00486 int N=A.rows();
00487 Matrix<double> AT=transpose(A);
00488 Matrix<double> B=AT,C(4,4);
00489
00490 C = AT * A;
00491
00492 try {
00493
00494
00495
00496 C = inverseSVD(C);
00497 }
00498 catch(SingularMatrixException& sme) {
00499 return -2;
00500 }
00501
00502 B = C * AT;
00503
00504 Vector<double> One(N,1.0),V(4),U(4);
00505 double E,F,G,d,lam;
00506
00507 U = B * One;
00508 V = B * Q;
00509 E = Minkowski(U,U);
00510 F = Minkowski(U,V) - 1.0;
00511 G = Minkowski(V,V);
00512 d = F*F-E*G;
00513 if(d < 0.0) d=0.0;
00514 d = SQRT(d);
00515
00516
00517 lam = (-F+d)/E;
00518 X = lam*U + V;
00519 X(3) = -X(3);
00520
00521 R(0) = A(0,3)-X(3) - RSS(X(0)-A(0,0), X(1)-A(0,1), X(2)-A(0,2));
00522
00523
00524 lam = (-F-d)/E;
00525 X = lam*U + V;
00526 X(3) = -X(3);
00527
00528 R(1) = A(0,3)-X(3) - RSS(X(0)-A(0,0), X(1)-A(0,1), X(2)-A(0,2));
00529
00530
00531 if(ABS(R(1)) > ABS(R(0))) {
00532 lam = (-F+d)/E;
00533 X = lam*U + V;
00534 X(3) = -X(3);
00535 }
00536
00537
00538 for(int i=0; i<N; i++)
00539 R(i) = A(i,3)-X(3) - RSS(X(0)-A(i,0), X(1)-A(i,1), X(2)-A(i,2));
00540
00541 return 0;
00542
00543 }
00544 catch(Exception& e) {
00545 GPSTK_RETHROW(e);
00546 }
00547 }
00548
00549
00550
00551 int PRSolution::AutonomousPRSolution(const DayTime& T,
00552 const vector<bool>& Use,
00553 const Matrix<double> SVP,
00554 TropModel *pTropModel,
00555 const bool Algebraic,
00556 int& n_iterate,
00557 double& converge,
00558 Vector<double>& Sol,
00559 Matrix<double>& Cov,
00560 Vector<double>& Resid,
00561 Vector<double>& Slope,
00562 ostream *pDebugStream)
00563 throw(Exception)
00564 {
00565 if(!pTropModel) {
00566 Exception e("Undefined tropospheric model");
00567 GPSTK_THROW(e);
00568 }
00569
00570 try {
00571 int iret,i,j,n,nsvs;
00572 double rho,wt,svxyz[3];
00573 GPSGeoid geoid;
00574
00575
00576
00577
00578
00579 for(nsvs=0,i=0; i<Use.size(); i++) if(Use[i]) nsvs++;
00580 if(nsvs < 4) return -3;
00581
00582
00583 Vector<double> CRange(nsvs),dX(4);
00584 Matrix<double> P(nsvs,4),PT,G(4,nsvs),PG(nsvs,nsvs);
00585 Xvt SV,RX;
00586
00587 Sol.resize(4);
00588 Cov.resize(4,4);
00589 Resid.resize(nsvs);
00590 Slope.resize(Use.size());
00591
00592
00593 Vector<double> U(4),Q(nsvs);
00594 Matrix<double> A(P);
00595
00596 int niter_limit = (n_iterate<2 ? 2 : n_iterate);
00597 double conv_limit = converge;
00598
00599
00600 Sol = 0.0;
00601 n_iterate = 0;
00602 converge = 0.0;
00603
00604
00605
00606 bool applied_trop;
00607 do {
00608 applied_trop = true;
00609
00610
00611 RX.x = ECEF(Sol(0),Sol(1),Sol(2));
00612
00613
00614 for(n=0,i=0; i<Use.size(); i++) {
00615
00616 if(!Use[i]) continue;
00617
00618
00619 if(n_iterate == 0)
00620 rho = 0.070;
00621 else
00622 rho = RSS(SVP(i,0)-Sol(0), SVP(i,1)-Sol(1), SVP(i,2)-Sol(2))
00623 / geoid.c();
00624
00625
00626 wt = geoid.angVelocity()*rho;
00627 svxyz[0] = ::cos(wt)*SVP(i,0) + ::sin(wt)*SVP(i,1);
00628 svxyz[1] = -::sin(wt)*SVP(i,0) + ::cos(wt)*SVP(i,1);
00629 svxyz[2] = SVP(i,2);
00630
00631
00632 CRange(n) = SVP(i,3);
00633
00634
00635 if(n_iterate > 0) {
00636 SV.x = ECEF(svxyz[0],svxyz[1],svxyz[2]);
00637
00638 Position R(RX),S(SV);
00639 double tc=R.getHeight(), elev = R.elevation(SV);
00640 if(elev < 0.0 || fabs(tc) > 100000.0) {
00641 tc = 0.0;
00642 applied_trop = false;
00643 }
00644 else tc = pTropModel->correction(R,S,T);
00645
00646
00647 CRange(n) -= tc;
00648 }
00649
00650
00651 rho = RSS(svxyz[0]-Sol(0),svxyz[1]-Sol(1),svxyz[2]-Sol(2));
00652
00653
00654 P(n,0) = (Sol(0)-svxyz[0])/rho;
00655 P(n,1) = (Sol(1)-svxyz[1])/rho;
00656 P(n,2) = (Sol(2)-svxyz[2])/rho;
00657 P(n,3) = 1.0;
00658
00659
00660 Resid(n) = CRange(n) - rho - Sol(3);
00661
00662
00663
00664
00665
00666
00667 if(Algebraic) {
00668 U(0) = A(n,0) = svxyz[0];
00669 U(1) = A(n,1) = svxyz[1];
00670 U(2) = A(n,2) = svxyz[2];
00671 U(3) = A(n,3) = CRange(n);
00672 Q(n) = 0.5 * Minkowski(U,U);
00673 }
00674
00675 n++;
00676 }
00677
00678
00679
00680
00681
00682
00683
00684 PT = transpose(P);
00685 Cov = PT * P;
00686
00687
00688
00689
00690
00691 try { Cov = inverseSVD(Cov); }
00692
00693 catch(SingularMatrixException& sme) {
00694 return -2;
00695 }
00696
00697
00698
00699
00700
00701 G = Cov * PT;
00702 PG = P * G;
00703
00704
00705
00706
00707 n_iterate++;
00708
00709
00710 if(Algebraic) {
00711 iret = PRSolution::AlgebraicSolution(A,Q,Sol,Resid);
00712 if(iret) return iret;
00713 if(n_iterate > 1) {
00714 iret = 0;
00715 break;
00716 }
00717 }
00718
00719 else {
00720 dX = G * Resid;
00721 Sol += dX;
00722
00723 converge = norm(dX);
00724
00725 if(n_iterate > 1 && converge < conv_limit) {
00726 iret = 0;
00727 break;
00728 }
00729
00730 if(n_iterate >= niter_limit || converge > 1.e10) {
00731 iret = -1;
00732 break;
00733 }
00734 }
00735
00736
00737 } while(1);
00738
00739 if(!applied_trop && pDebugStream)
00740 *pDebugStream << "Warning - trop correction not applied at time "
00741 << T.printf("%4F %10.3g\n");
00742
00743
00744 Slope = 0.0;
00745 if(iret == 0) for(j=0,i=0; i<Use.size(); i++) {
00746 if(!Use[i]) continue;
00747 for(int k=0; k<4; k++) Slope(i) += G(k,j)*G(k,j);
00748 Slope(i) = SQRT(Slope(i)*double(n-4)/(1.0-PG(j,j)));
00749 j++;
00750 }
00751
00752 return iret;
00753
00754 }
00755 catch(Exception& e) {
00756 GPSTK_RETHROW(e);
00757 }
00758 }
00759
00760 }