PRSolution.cpp

Go to the documentation of this file.
00001 #pragma ident "$Id: PRSolution.cpp 2503 2011-02-13 08:29:37Z yanweignss $"
00002 
00003 //============================================================================
00004 //
00005 //  This file is part of GPSTk, the GPS Toolkit.
00006 //
00007 //  The GPSTk is free software; you can redistribute it and/or modify
00008 //  it under the terms of the GNU Lesser General Public License as published
00009 //  by the Free Software Foundation; either version 2.1 of the License, or
00010 //  any later version.
00011 //
00012 //  The GPSTk is distributed in the hope that it will be useful,
00013 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 //  GNU Lesser General Public License for more details.
00016 //
00017 //  You should have received a copy of the GNU Lesser General Public
00018 //  License along with GPSTk; if not, write to the Free Software Foundation,
00019 //  Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020 //  
00021 //  Copyright 2004, The University of Texas at Austin
00022 //
00023 //============================================================================
00024 
00030 #include "MathBase.hpp"
00031 #include "PRSolution.hpp"
00032 #include "GPSGeoid.hpp"
00033 
00034 // -----------------------------------------------------------------------------------
00035 // Combinations.hpp
00036 // Find all the combinations of n things taken k at a time.
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) {        // can this index be incremented?
00138       Index[j]++;
00139       for(int m=j+1; m<k; m++)
00140          Index[m]=Index[m-1]+1;
00141       return 0;
00142    }
00143       // is this the last index?
00144    if(j-1 < 0) return -1;
00145       // increment the next lower index
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          // Use these to save the 'best' solution within the loop.
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;      // this marks the 'Best' set as unused.
00196          Matrix<double> BestCovariance;
00197 
00198          // ----------------------------------------------------------------
00199          // initialize
00200          Valid = false;
00201 
00202          // Save the input solution
00203          // (for use in rejection when ResidualCriterion is false).
00204          if(Solution.size() != 4) { Solution.resize(4); Solution = 0.0; }
00205          APrioriSolution = Solution;
00206 
00207          // ----------------------------------------------------------------
00208          // fill the SVP matrix, and use it for every solution
00209          // NB this routine can set Satellite[.]=negative when no ephemeris
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;  // return is 0(ok) or -4(no ephemeris)
00224 
00225          // count how many good satellites we have
00226          // Initialize UseSat based on Satellite, and build GoodIndexes.
00227          // UseSat is used to mark good sats (true) and those to ignore (false).
00228          // UseSave saves the original so it can be reused for each solution.
00229          // Let GoodIndexes be all the indexes of Satellites that are good:
00230          // UseSat[GoodIndexes[.]] == true by definition
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          //if(Debug) {
00241          //   *pDebugStream << "GoodIndexes (" << N << ") are";
00242          //   for(i=0; i<GoodIndexes.size(); i++)
00243          //      *pDebugStream << " " << Satellite[GoodIndexes[i]];
00244          //   *pDebugStream << endl;
00245          //}
00246 
00247          // don't even try if there are not 4 good satellites
00248          if(N < 4) return -3;
00249 
00250          // minimum number of sats needed for algorithm
00251          MinSV = 5;   // this would be RAIM
00252           // ( not really RAIM || not RAIM at all - just one solution)
00253          if(!ResidualCriterion || NSatsReject==0) MinSV=4;
00254 
00255          // how many satellites can RAIM reject, if we have to?
00256          // default is -1, meaning as many as possible
00257          Nreject = NSatsReject;
00258          if(Nreject == -1 || Nreject > N-MinSV)
00259             Nreject=N-MinSV;
00260 
00261          // ----------------------------------------------------------------
00262          // now compute the solution, first with all the data. If this fails,
00263          // reject 1 satellite at a time and try again, then 2, etc.
00264 
00265          // Slopes for each satellite are computed (cf. the RAIM algorithm)
00266          Vector<double> Slopes(Pseudorange.size());
00267 
00268          // Residuals stores the post-fit data residuals.
00269          Vector<double> Residuals(Satellite.size(),0.0);
00270 
00271          // stage is the number of satellites to reject.
00272          stage = 0;
00273 
00274          do {
00275             // compute all the combinations of N satellites taken stage at a time
00276             Combinations Combo(N,stage);
00277 
00278             // compute a solution for each combination of marked satellites
00279             do {
00280                // Mark the satellites for this combination
00281                UseSat = UseSave;
00282                for(i=0; i<GoodIndexes.size(); i++)
00283                   if(Combo.isSelected(i)) UseSat[GoodIndexes[i]]=false;
00284 
00285                // ----------------------------------------------------------------
00286                // Compute a solution given the data; ignore ranges for marked
00287                // satellites. Fill Vector 'Slopes' with slopes for each unmarked
00288                // satellite.
00289                // Return 0  ok
00290                //       -1  failed to converge
00291                //       -2  singular problem
00292                //       -3  not enough good data
00293                NIterations = MaxNIterations;             // pass limits in
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                // Compute RMS residual...
00301                if(!ResidualCriterion) {
00302                   // when 'distance from a priori' is the criterion.
00303                   Vector<double> D=Solution-APrioriSolution;
00304                   RMSResidual = RMS(D);
00305                }
00306                else {
00307                   // and in the usual case
00308                   RMSResidual = RMS(Residuals);
00309                }
00310                // ... and find the maximum slope
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                // print solution with diagnostic information
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                      // print the SatID for good sats
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                      // also print the return value
00339                   *pDebugStream << " (" << iret << ")" << endl;
00340                }// end debug print
00341 
00342                // ----------------------------------------------------------------
00343                // deal with the results of AutonomousPRSolution()
00344                if(iret) {     // failure for this combination
00345                   RMSResidual = 0.0;
00346                   Solution = 0.0;
00347                }
00348                else {         // success
00349                      // save 'best' solution for later
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                      // quit immediately?
00360                   if((stage==0 || ReturnAtOnce) && RMSResidual < RMSLimit)
00361                      break;
00362                }
00363 
00364                // get the next combinations and repeat
00365             } while(Combo.Next() != -1);
00366 
00367             // end of the stage
00368             if(BestRMS > 0.0 && BestRMS < RMSLimit) { // success
00369                iret=0;
00370                break;
00371             }
00372 
00373             // go to next stage
00374             stage++;
00375             if(stage > Nreject) break;
00376 
00377          } while(iret == 0 || iret == -1);        // end loop over stages
00378 
00379          // ----------------------------------------------------------------
00380          // copy out the best solution and return
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    }  // end PRSolution::RAIMCompute()
00404 
00405    // -------------------------------------------------------------------------
00406    // Prepare for the autonomous solution by computing direction cosines,
00407    // corrected pseudoranges and satellite system.
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;                // transmit time
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                // skip marked satellites
00429             if(Satellite[i].id <= 0) continue;
00430 
00431             // test the system
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                // first estimate of transmit time
00442             tx = Tr;
00443             tx -= Pseudorange[i]/C_GPS_M;
00444                // get ephemeris range, etc
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                // update transmit time and get ephemeris range again
00457             tx -= PVT.dtime;     // clk+rel
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                // SVP = {SV position at transmit time}, raw range + clk + rel
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    } // end PrepareAutonomousPRSolution
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          // invert
00492          try {
00493             //double big,small;
00494             //condNum(C,big,small);
00495             //if(small < 1.e-15 || big/small > 1.e15) return -2;
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; // avoid imaginary solutions: what does this really mean?
00514          d = SQRT(d);
00515 
00516             // first solution ...
00517          lam = (-F+d)/E;
00518          X = lam*U + V;
00519          X(3) = -X(3);
00520             // ... and its residual
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             // second solution ...
00524          lam = (-F-d)/E;
00525          X = lam*U + V;
00526          X(3) = -X(3);
00527             // ... and its residual
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             // pick the right solution
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             // compute the residuals
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    }  // end PRSolution::AlgebraicSolution
00548 
00549    // -------------------------------------------------------------------------
00550    // Compute a straightforward solution using all the unmarked data.
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          //if(pDebugStream) *pDebugStream << "Enter APRS " << n_iterate << " "
00576          //   << scientific << setprecision(3) << converge << endl;
00577 
00578             // find the number of good satellites
00579          for(nsvs=0,i=0; i<Use.size(); i++) if(Use[i]) nsvs++;
00580          if(nsvs < 4) return -3;
00581 
00582             // define for computation
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             // define for algebraic solution
00593          Vector<double> U(4),Q(nsvs);
00594          Matrix<double> A(P);
00595             // and for linearized least squares
00596          int niter_limit = (n_iterate<2 ? 2 : n_iterate);
00597          double conv_limit = converge;
00598 
00599             // prepare for iteration loop
00600          Sol = 0.0;                                // initial guess: center of earth
00601          n_iterate = 0;
00602          converge = 0.0;
00603 
00604          // iteration loop
00605          // do at least twice so that trop model gets evaluated
00606          bool applied_trop;
00607          do {
00608             applied_trop = true;
00609 
00610                // current estimate of position solution
00611             RX.x = ECEF(Sol(0),Sol(1),Sol(2));
00612 
00613                // loop over satellites, computing partials matrix
00614             for(n=0,i=0; i<Use.size(); i++) {
00615                   // ignore marked satellites
00616                if(!Use[i]) continue;
00617 
00618                   // time of flight (sec)
00619                if(n_iterate == 0)
00620                   rho = 0.070;             // initial guess: 70ms
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                   // correct for earth rotation
00626                wt = geoid.angVelocity()*rho;             // radians
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                   // corrected pseudorange (m)
00632                CRange(n) = SVP(i,3);
00633 
00634                   // correct for troposphere (but not on the first iteration)
00635                if(n_iterate > 0) {
00636                   SV.x = ECEF(svxyz[0],svxyz[1],svxyz[2]);
00637                   // must test RX for reasonableness to avoid corrupting TropModel
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                   //if(pDebugStream) *pDebugStream << "Trop " << i << " "
00646                   //   << fixed << setprecision(3) << tc << endl;
00647                   CRange(n) -= tc;
00648                }
00649 
00650                   // geometric range
00651                rho = RSS(svxyz[0]-Sol(0),svxyz[1]-Sol(1),svxyz[2]-Sol(2));
00652 
00653                   // partials matrix
00654                P(n,0) = (Sol(0)-svxyz[0])/rho;           // x direction cosine
00655                P(n,1) = (Sol(1)-svxyz[1])/rho;           // y direction cosine
00656                P(n,2) = (Sol(2)-svxyz[2])/rho;           // z direction cosine
00657                P(n,3) = 1.0;
00658 
00659                   // data vector: corrected range residual
00660                Resid(n) = CRange(n) - rho - Sol(3);
00661 
00662                   // TD: allow weight matrix = measurement covariance inverse
00663                // P *= MCov;
00664                // Resid *= MCov;
00665 
00666                   // compute intermediate quantities for algebraic solution
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++;        // n is number of good satellites - used for Slope
00676             }  // end loop over satellites
00677 
00678             //if(pDebugStream) *pDebugStream << "Partials\n"
00679                //<< fixed << setprecision(4) << P << endl;
00680             //if(pDebugStream) *pDebugStream << "Resid "
00681                //<< fixed << setprecision(3) << Resid << endl;
00682 
00683                // compute information matrix = inverse covariance matrix
00684             PT = transpose(P);
00685             Cov = PT * P;
00686 
00687                // invert using SVD
00688             //double big,small;
00689             //condNum(PT*P,big,small);
00690             //if(small < 1.e-15 || big/small > 1.e15) return -2;
00691             try { Cov = inverseSVD(Cov); }
00692             //try { Cov = inverseLUD(Cov); }
00693             catch(SingularMatrixException& sme) {
00694                return -2;
00695             }
00696 
00697             //if(pDebugStream) *pDebugStream << "Covariance\n"
00698                //<< fixed << setprecision(8) << Cov << endl;
00699 
00700                // generalized inverse
00701             G = Cov * PT;
00702             PG = P * G;                         // used for Slope
00703 
00704             //if(pDebugStream) *pDebugStream << "Generalized inverse\n"
00705                //<< fixed << setprecision(8) << G << endl;
00706 
00707             n_iterate++;                        // increment number iterations
00708 
00709                // ----------------- algebraic solution -----------------------
00710             if(Algebraic) {
00711                iret = PRSolution::AlgebraicSolution(A,Q,Sol,Resid);
00712                if(iret) return iret;                     // (singular)
00713                if(n_iterate > 1) {                       // need 2, for trop
00714                   iret = 0;
00715                   break;
00716                }
00717             }
00718                // ----------------- linearized least squares solution --------
00719             else {
00720                dX = G * Resid;
00721                Sol += dX;
00722                   // test for convergence
00723                converge = norm(dX);
00724                   // success: quit
00725                if(n_iterate > 1 && converge < conv_limit) {
00726                   iret = 0;
00727                   break;
00728                }
00729                   // failure: quit
00730                if(n_iterate >= niter_limit || converge > 1.e10) {
00731                   iret = -1;
00732                   break;
00733                }
00734             }
00735                
00736 
00737          } while(1);    // end iteration loop
00738 
00739          if(!applied_trop && pDebugStream)
00740             *pDebugStream << "Warning - trop correction not applied at time "
00741                << T.printf("%4F %10.3g\n");
00742 
00743             // compute slopes
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    } // end PRSolution::AutonomousPRSolution
00759 
00760 } // namespace gpstk

Generated on Wed Feb 8 03:31:01 2012 for GPS ToolKit Software Library by  doxygen 1.3.9.1