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