PRSolution.cpp

Go to the documentation of this file.
00001 #pragma ident "$Id: PRSolution.cpp 1180 2008-04-04 13:51:59Z btolman $"
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 "EphemerisRange.hpp"
00033 #include "GPSGeoid.hpp"
00034 
00035 // -----------------------------------------------------------------------------------
00036 // Combinations.hpp
00037 // Find all the combinations of n things taken k at a time.
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) {        // can this index be incremented?
00142       Index[j]++;
00143       for(int m=j+1; m<k; m++)
00144          Index[m]=Index[m-1]+1;
00145       return 0;
00146    }
00147       // is this the last index?
00148    if(j-1 < 0) return -1;
00149       // increment the next lower index
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          // Use these to save the 'best' solution within the loop.
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;      // this marks the 'Best' set as unused.
00200 
00201          // ----------------------------------------------------------------
00202          // initialize
00203          Valid = false;
00204 
00205          // Save the input solution
00206          // (for use in rejection when ResidualCriterion is false).
00207          if(Solution.size() != 4) { Solution.resize(4); Solution = 0.0; }
00208          APrioriSolution = Solution;
00209 
00210          // ----------------------------------------------------------------
00211          // fill the SVP matrix, and use it for every solution
00212          // NB this routine can set Satellite[.]=negative when no ephemeris
00213          i = PrepareAutonomousSolution(Tr, Satellite, Pseudorange, Eph, SVP,
00214                pDebugStream);
00215          //if(Debug) {
00216          //   *pDebugStream << "In RAIMCompute after PAS(): Satellites:";
00217          //   for(j=0; j<Satellite.size(); j++)
00218          //      *pDebugStream << " " << RinexSatID(Satellite[j]);
00219          //   *pDebugStream << endl;
00220          //   *pDebugStream << " SVP matrix("
00221          //      << SVP.rows() << "," << SVP.cols() << ")" << endl;
00222          //   *pDebugStream << fixed << setw(16) << setprecision(3) << SVP << endl;
00223          //}
00224          if(i) return i;  // return is 0(ok) or -4(no ephemeris)
00225 
00226          // count how many good satellites we have
00227          // Initialize UseSat based on Satellite, and build GoodIndexes.
00228          // UseSat is used to mark good sats (true) and those to ignore (false).
00229          // UseSave saves the original so it can be reused for each solution.
00230          // Let GoodIndexes be all the indexes of Satellites that are good:
00231          // UseSat[GoodIndexes[.]] == true by definition
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          //if(Debug) {
00242          //   *pDebugStream << "GoodIndexes (" << N << ") are";
00243          //   for(i=0; i<GoodIndexes.size(); i++)
00244          //      *pDebugStream << " " << Satellite[GoodIndexes[i]];
00245          //   *pDebugStream << endl;
00246          //}
00247 
00248          // don't even try if there are not 4 good satellites
00249          if(N < 4) return -3;
00250 
00251          // minimum number of sats needed for algorithm
00252          MinSV = 5;   // this would be RAIM
00253           // ( not really RAIM || not RAIM at all - just one solution)
00254          if(!ResidualCriterion || NSatsReject==0) MinSV=4;
00255 
00256          // how many satellites can RAIM reject, if we have to?
00257          // default is -1, meaning as many as possible
00258          Nreject = NSatsReject;
00259          if(Nreject == -1 || Nreject > N-MinSV)
00260             Nreject=N-MinSV;
00261 
00262          // ----------------------------------------------------------------
00263          // now compute the solution, first with all the data. If this fails,
00264          // reject 1 satellite at a time and try again, then 2, etc.
00265 
00266          // Slopes for each satellite are computed (cf. the RAIM algorithm)
00267          Vector<double> Slopes(Pseudorange.size());
00268 
00269          // Residuals stores the post-fit data residuals.
00270          Vector<double> Residuals(Satellite.size(),0.0);
00271 
00272          // stage is the number of satellites to reject.
00273          stage = 0;
00274 
00275          do {
00276             // compute all the combinations of N satellites taken stage at a time
00277             Combinations Combo(N,stage);
00278 
00279             // compute a solution for each combination of marked satellites
00280             do {
00281                // Mark the satellites for this combination
00282                UseSat = UseSave;
00283                for(i=0; i<GoodIndexes.size(); i++)
00284                   if(Combo.isSelected(i)) UseSat[i]=false;
00285 
00286                // ----------------------------------------------------------------
00287                // Compute a solution given the data; ignore ranges for marked
00288                // satellites. Fill Vector 'Slopes' with slopes for each unmarked
00289                // satellite.
00290                // Return 0  ok
00291                //       -1  failed to converge
00292                //       -2  singular problem
00293                //       -3  not enough good data
00294                NIterations = MaxNIterations;             // pass limits in
00295                Convergence = ConvergenceLimit;
00296                iret = AutonomousPRSolution(Tr, UseSat, SVP, pTropModel, Algebraic,
00297                   NIterations, Convergence, Solution, Covariance, Residuals, Slopes,
00298                   pDebugStream);
00299 
00300                // ----------------------------------------------------------------
00301                // Compute RMS residual...
00302                if(!ResidualCriterion) {
00303                   // when 'distance from a priori' is the criterion.
00304                   Vector<double> D=Solution-APrioriSolution;
00305                   RMSResidual = RMS(D);
00306                }
00307                else {
00308                   // and in the usual case
00309                   RMSResidual = RMS(Residuals);
00310                }
00311                // ... and find the maximum slope
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                // print solution with diagnostic information
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                      // print the SatID for good sats
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                      // also print the return value
00340                   *pDebugStream << " (" << iret << ")" << endl;
00341                }// end debug print
00342 
00343                // ----------------------------------------------------------------
00344                // deal with the results of AutonomousPRSolution()
00345                if(iret) {     // failure for this combination
00346                   RMSResidual = 0.0;
00347                   Solution = 0.0;
00348                }
00349                else {         // success
00350                      // save 'best' solution for later
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                      // 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);        // 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          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    }  // end PRSolution::RAIMCompute()
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;                // transmit time
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                // skip marked satellites
00422             if(Satellite[i].id <= 0) continue;
00423 
00424                // first estimate of transmit time
00425             tx = Tr;
00426             tx -= Pseudorange[i]/C_GPS_M;
00427                // get ephemeris range, etc
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                // update transmit time and get ephemeris range again
00437             tx -= PVT.dtime;     // clk+rel
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                // SVP = {SV position at transmit time}, raw range + clk + rel
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    } // end PrepareAutonomousPRSolution
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          // invert
00469          try {
00470             //double big,small;
00471             //condNum(C,big,small);
00472             //if(small < 1.e-15 || big/small > 1.e15) return -2;
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; // avoid imaginary solutions: what does this really mean?
00491          d = SQRT(d);
00492 
00493             // first solution ...
00494          lam = (-F+d)/E;
00495          X = lam*U + V;
00496          X(3) = -X(3);
00497             // ... and its residual
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             // second solution ...
00501          lam = (-F-d)/E;
00502          X = lam*U + V;
00503          X(3) = -X(3);
00504             // ... and its residual
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             // pick the right solution
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             // compute the residuals
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    }  // end PRSolution::AlgebraicSolution
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;               // WGS84?
00550 
00551          //if(pDebugStream) *pDebugStream << "Enter APRS " << n_iterate << " "
00552          //   << scientific << setprecision(3) << converge << endl;
00553 
00554             // find the number of good satellites
00555          for(N=0,i=0; i<Use.size(); i++) if(Use[i]) N++;
00556          if(N < 4) return -3;
00557 
00558             // define for computation
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             // define for algebraic solution
00569          Vector<double> U(4),Q(N);
00570          Matrix<double> A(P);
00571             // and for linearized least squares
00572          int niter_limit = (n_iterate<2 ? 2 : n_iterate);
00573          double conv_limit = converge;
00574 
00575             // prepare for iteration loop
00576          Sol = 0.0;                                // initial guess: center of earth
00577          n_iterate = 0;
00578          converge = 0.0;
00579 
00580             // iteration loop
00581             // do at least twice (even for algebraic solution) so that
00582             // trop model gets evaluated
00583          do {
00584                // current estimate of position solution
00585             RX.x = ECEF(Sol(0),Sol(1),Sol(2));
00586 
00587                // loop over satellites, computing partials matrix
00588             for(n=0,i=0; i<Use.size(); i++) {
00589                   // ignore marked satellites
00590                if(!Use[i]) continue;
00591 
00592                   // time of flight (sec)
00593                if(n_iterate == 0)
00594                   rho = 0.070;             // initial guess: 70ms
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                   // correct for earth rotation
00600                wt = geoid.angVelocity()*rho;             // radians
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                   // corrected pseudorange (m)
00606                CRange(n) = SVP(i,3);
00607 
00608                   // correct for troposphere (but not on the first iteration)
00609                if(n_iterate > 0) {
00610                   SV.x = ECEF(svxyz[0],svxyz[1],svxyz[2]);
00611                   // must test RX for reasonableness to avoid corrupting TropModel
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                   // geometric range
00620                rho = RSS(svxyz[0]-Sol(0),svxyz[1]-Sol(1),svxyz[2]-Sol(2));
00621 
00622                   // partials matrix
00623                P(n,0) = (Sol(0)-svxyz[0])/rho;           // x direction cosine
00624                P(n,1) = (Sol(1)-svxyz[1])/rho;           // y direction cosine
00625                P(n,2) = (Sol(2)-svxyz[2])/rho;           // z direction cosine
00626                P(n,3) = 1.0;
00627 
00628                   // data vector: corrected range residual
00629                Resid(n) = CRange(n) - rho - Sol(3);
00630 
00631                   // TD: allow weight matrix = measurement covariance
00632                // P *= MCov;
00633                // Resid *= MCov;
00634 
00635                   // compute intermediate quantities for algebraic solution
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++;        // n is number of good satellites - used for Slope
00645             }  // end loop over satellites
00646 
00647                // compute information matrix = inverse covariance matrix
00648             PT = transpose(P);
00649             Cov = PT * P;
00650 
00651                // invert using SVD
00652             //double big,small;
00653             //condNum(PT*P,big,small);
00654             //if(small < 1.e-15 || big/small > 1.e15) return -2;
00655             try { Cov = inverseSVD(Cov); }
00656             //try { Cov = inverseLUD(Cov); }
00657             catch(SingularMatrixException& sme) {
00658                return -2;
00659             }
00660 
00661                // generalized inverse
00662             G = Cov * PT;
00663             PG = P * G;                         // used for Slope
00664 
00665             n_iterate++;                        // increment number iterations
00666 
00667                // ----------------- algebraic solution -----------------------
00668             if(Algebraic) {
00669                iret = PRSolution::AlgebraicSolution(A,Q,Sol,Resid);
00670                if(iret) return iret;                     // (singular)
00671                if(n_iterate > 1) {                       // need 2, for trop
00672                   iret = 0;
00673                   break;
00674                }
00675             }
00676                // ----------------- linearized least squares solution --------
00677             else {
00678                dX = G * Resid;
00679                Sol += dX;
00680                   // test for convergence
00681                converge = norm(dX);
00682                   // success: quit
00683                if(n_iterate > 1 && converge < conv_limit) {
00684                   iret = 0;
00685                   break;
00686                }
00687                   // failure: quit
00688                if(n_iterate >= niter_limit || converge > 1.e10) {
00689                   iret = -1;
00690                   break;
00691                }
00692             }
00693                
00694 
00695          } while(1);    // end iteration loop
00696 
00697             // compute slopes
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    } // end PRSolution::AutonomousPRSolution
00713 
00714 } // namespace gpstk

Generated on Tue Jan 6 03:31:23 2009 for GPS ToolKit Software Library by  doxygen 1.3.9.1