KeplerOrbit.cpp

Go to the documentation of this file.
00001 #pragma ident "$Id: KeplerOrbit.cpp 2457 2010-08-18 14:20:12Z coandrei $"
00002 
00009 //============================================================================
00010 //
00011 //  This file is part of GPSTk, the GPS Toolkit.
00012 //
00013 //  The GPSTk is free software; you can redistribute it and/or modify
00014 //  it under the terms of the GNU Lesser General Public License as published
00015 //  by the Free Software Foundation; either version 2.1 of the License, or
00016 //  any later version.
00017 //
00018 //  The GPSTk is distributed in the hope that it will be useful,
00019 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00020 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00021 //  GNU Lesser General Public License for more details.
00022 //
00023 //  You should have received a copy of the GNU Lesser General Public
00024 //  License along with GPSTk; if not, write to the Free Software Foundation,
00025 //  Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00026 //
00027 //  Wei Yan - Chinese Academy of Sciences . 2009, 2010
00028 //
00029 //============================================================================
00030 
00031 #include "KeplerOrbit.hpp"
00032 #include <limits>
00033 #include <cmath>
00034 #include "ASConstant.hpp"
00035 #include "ReferenceFrames.hpp"
00036 
00037 namespace gpstk
00038 {
00039    using namespace std;
00040 
00041    const double KeplerOrbit::eps_mach = numeric_limits<double>::epsilon();
00042 
00043       /* Computes the eccentric anomaly for elliptic orbits
00044        * @param M    Mean anomaly in [rad]
00045        * @param e    Eccentricity of the orbit [0,1]
00046        * @return     Eccentric anomaly in [rad]
00047        */
00048    double KeplerOrbit::EccentricAnomaly(double M, double e)
00049    {
00050       const int maxit = 15;
00051       const double eps = 100.0*eps_mach;
00052 
00053       // Variables
00054       int    i=0;
00055       double E, f;
00056 
00057       // Starting value
00058 
00059       M = Modulo(M, 2.0*ASConstant::PI);   
00060       if (e<0.8) E=M; else E= ASConstant::PI;
00061 
00062       // Iteration
00063       do 
00064       {
00065          f = E - e*std::sin(E) - M;
00066          E = E - f / ( 1.0 - e*std::cos(E) );
00067          ++i;
00068          if (i == maxit) 
00069          {
00070             cerr << " convergence problems in EccAnom" << endl;
00071             break;
00072          }
00073       }
00074       while (fabs(f) > eps);
00075 
00076       return E;
00077 
00078    }  // End of 'KeplerOrbit::EccAnom()'
00079 
00080 
00081       /* Computes the true anomaly for elliptic orbits
00082        * @param M    Mean anomaly in [rad]
00083        * @param e    Eccentricity of the orbit [0,1]
00084        * @return     True anomaly in [rad]
00085        */
00086    double KeplerOrbit::TrueAnomaly (double M, double e)
00087    {
00088       double E = EccentricAnomaly(M, e);
00089 
00090       double scta = std::sqrt(1.0-e*e)*std::sin(E)/(1.0-e*std::cos(E));
00091       double ccta = (std::cos(E)-e)/(1.0-e*std::cos(E));
00092 
00093       return atan2(scta, ccta);
00094    }
00095    
00096 
00102    double KeplerOrbit::MeanAnomaly (double cta, double e)
00103    {
00104       double sinE = (std::sqrt(1.0-e*e)*std::sin(cta))/(1.0+e*std::cos(cta));
00105       double cosE = (e+std::cos(cta))/(1.0+e*std::cos(cta));
00106       double E = atan2(sinE,cosE);
00107 
00108       return (E- e * std::sin(E));
00109    }
00110 
00111       /*Computes the sector-triangle ratio from two position vectors and 
00112        * the intermediate time 
00113        * @param r_a     Position at time t_a
00114        * @param r_a     Position at time t_b
00115        * @param tau     Normalized time (sqrt(GM)*(t_a-t_b))
00116        * @return        Sector-triangle ratio
00117         */
00118    double KeplerOrbit::FindEta (const Vector<double>& r_a, 
00119                                 const Vector<double>& r_b, 
00120                                 double tau)
00121    {
00122       // Constants
00123 
00124       const int maxit = 30;
00125       const double delta = 100.0*eps_mach;  
00126 
00127       // Variables
00128 
00129       double kappa, m, l, s_a, s_b, eta_min, eta1, eta2, F1, F2, d_eta;
00130 
00131 
00132       // Auxiliary quantities
00133 
00134       s_a = norm(r_a);  
00135       s_b = norm(r_b);  
00136 
00137       kappa = std::sqrt ( 2.0*(s_a*s_b+dot(r_a,r_b)) );
00138 
00139       m = tau*tau / std::pow(kappa,3);   
00140       l = (s_a+s_b) / (2.0*kappa) - 0.5;
00141 
00142       eta_min = std::sqrt(m/(l+1.0));
00143 
00144       // Start with Hansen's approximation
00145 
00146       eta2 = ( 12.0 + 10.0*std::sqrt(1.0+(44.0/9.0)*m /(l+5.0/6.0)) ) / 22.0;
00147       eta1 = eta2 + 0.1;   
00148 
00149       // Secant method
00150 
00151       F1 = F(eta1, m, l);   
00152       F2 = F(eta2, m, l);  
00153 
00154       int i = 0;
00155 
00156       while (std::fabs(F2-F1) > delta)
00157       {
00158          d_eta = -F2*(eta2-eta1)/(F2-F1);  
00159          eta1 = eta2; F1 = F2; 
00160          while (eta2+d_eta<=eta_min)  d_eta *= 0.5;
00161          eta2 += d_eta;  
00162          F2 = F(eta2,m,l); ++i;
00163 
00164          if ( i == maxit ) 
00165          {
00166             cerr << "WARNING: Convergence problems in FindEta" << endl;
00167             break;
00168          }
00169       }
00170 
00171       return eta2;
00172    }
00173 
00174       /*Computes the satellite state vector from osculating Keplerian 
00175        * elements for elliptic orbits.
00176        * @GM       Gravitational coefficient
00177        * @Kep      Keplerian elements(a e i OMG omg M)
00178        * @dt       Time since epoch
00179        * @return   State vector(position and velocity)
00180        *
00181        * @warning  The semimajor axis a=Kep(0), dt and GM must be given in 
00182        *           consistent units 
00183        */
00184    Vector<double> KeplerOrbit::State( double GM, const Vector<double>& Kep, double dt )
00185    {
00186       
00187       // Keplerian elements at epoch
00188       const double a     = Kep(0);  
00189       const double e     = Kep(1);  
00190       const double i     = Kep(2);  
00191       const double Omega = Kep(3);
00192       const double omega = Kep(4); 
00193       const double M0    = Kep(5);
00194       
00195       // Mean anomaly
00196       double M = M0 + std::sqrt(GM/(a*a*a)) * dt;
00197 
00198       // Eccentric anomaly
00199 
00200       double E  = EccentricAnomaly(M,e);   
00201 
00202       double cosE = std::cos(E); 
00203       double sinE = std::sin(E);
00204 
00205       // Perifocal coordinates
00206 
00207       double fac = std::sqrt( (1.0-e)*(1.0+e) );  
00208 
00209       double R = a*(1.0-e*cosE);       // Distance
00210       double V = std::sqrt(GM*a)/R;    // Velocity
00211 
00212       Vector<double>  r(3,0.0),v(3,0.0);
00213       r(0) = a * (cosE - e); 
00214       r(1) = a * fac * sinE;  
00215       r(2) = 0.0;
00216 
00217       v(0) = -V * sinE;    
00218       v(1) = +V * fac * cosE;
00219       v(2) = 0.0;
00220 
00221       // Transformation to reference system (Gaussian vectors)
00222       Matrix<double> PQW(3,3,0.0);
00223       PQW = ReferenceFrames::Rz(-Omega) 
00224           * ReferenceFrames::Rx(-i) 
00225           * ReferenceFrames::Rz(-omega);
00226 
00227       r = PQW * r;
00228       v = PQW * v;
00229 
00230       return Stack(r,v);
00231 
00232    }  // End of method 'KeplerOrbit::State()'
00233 
00234 
00235    Vector<double> KeplerOrbit::Stack(Vector<double> r,Vector<double> v)
00236    {
00237       const int n = r.size() + v.size();
00238       Vector<double> rv(n,0.0);
00239 
00240       for(int i=0;i<n;i++)
00241       {
00242          if(i<r.size())
00243          {
00244             rv(i) = r(i);
00245          }
00246          else
00247          {
00248             rv(i) = v(i-r.size());
00249          }
00250       }
00251 
00252       return rv;
00253    }
00254 
00255    
00256       /*Computes the partial derivatives of the satellite state vector with 
00257        * respect to the orbital elements for elliptic, Keplerian orbits
00258        *
00259        * @param GM   Gravitational coefficient
00260        * @param Kep  Keplerian elements (a,e,i,Omega,omega,M) 
00261        * @param dt   Time since epoch
00262        * @return     Partials derivatives of the state vector (x,y,z,vx,vy,vz) 
00263        *             at time dt with respect to the epoch orbital elements
00264        * warning The semimajor axis a=Kep(0), dt and GM must be given in consistent units, 
00265        * The function cannot be used with circular or non-inclined orbit.
00266        */
00267    Matrix<double> KeplerOrbit::StatePartials ( double GM, const Vector<double>& Kep, double dt )
00268    {
00269 
00270       // Variables
00271       
00272       
00273       Vector<double>  dPdi(3),dPdO(3),dPdo(3),dQdi(3),dQdO(3),dQdo(3); 
00274       Vector<double>  dYda(6),dYde(6),dYdi(6),dYdO(6),dYdo(6),dYdM(6);
00275       Matrix<double>  dYdA(6,6);
00276 
00277       // Keplerian elements at epoch
00278 
00279       const double a     = Kep(0);  
00280       const double e     = Kep(1);  
00281       const double i     = Kep(2);  
00282       const double Omega = Kep(3);
00283       const double omega = Kep(4); 
00284       const double M0    = Kep(5);
00285 
00286       // Mean and eccentric anomaly
00287 
00288       double n = std::sqrt (GM/(a*a*a));
00289       double M = M0 +n*dt;
00290       double E = EccentricAnomaly(M,e);   
00291 
00292       // Perifocal coordinates
00293 
00294       double cosE = std::cos(E); 
00295       double sinE = std::sin(E);
00296       double fac  = std::sqrt((1.0-e)*(1.0+e));  
00297 
00298       double r = a*(1.0-e*cosE);  // Distance
00299       double v = std::sqrt(GM*a)/r;    // Velocity
00300 
00301       double x  = +a*(cosE-e); 
00302       double y  = +a*fac*sinE;
00303       double vx = -v*sinE;     
00304       double vy = +v*fac*cosE; 
00305 
00306       // Transformation to reference system (Gaussian vectors) and partials
00307       Matrix<double>  PQW(3,3,0.0);
00308       PQW = ReferenceFrames::Rz(-Omega) 
00309           * ReferenceFrames::Rx(-i) 
00310           * ReferenceFrames::Rz(-omega);
00311 
00312       //P = PQW.Col(0);  Q = PQW.Col(1);  W = PQW.Col(2);
00313       Vector<double>  P(3),Q(3),W(3),e_z(3),N(3);
00314       P(0) = PQW(0,0);
00315       P(1) = PQW(1,0);
00316       P(2) = PQW(2,0);
00317 
00318       Q(0) = PQW(0,1);
00319       Q(1) = PQW(1,1);
00320       Q(2) = PQW(2,1);
00321       
00322       W(0) = PQW(0,2);
00323       W(1) = PQW(1,2);
00324       W(2) = PQW(2,2);
00325       
00326       //e_z = Vector(0,0,1);  
00327       e_z(0) = 0.0;
00328       e_z(1) = 0.0;
00329       e_z(2) = 1.0;
00330       
00331       
00332       N = cross(e_z,W); N = N/norm(N);
00333       
00334       dPdi = cross(N,P);  dPdO = cross(e_z,P); dPdo =  Q;
00335       dQdi = cross(N,Q);  dQdO = cross(e_z,Q); dQdo = -1.0*P;
00336       
00337       // Partials w.r.t. semimajor axis, eccentricity and mean anomaly at time dt      
00338       dYda = Stack ( (x/a)*P + (y/a)*Q,
00339          (-vx/(2*a))*P + (-vy/(2*a))*Q );
00340 
00341 
00342       dYde = Stack ( (-a-std::pow(y/fac,2)/r)*P + (x*y/(r*fac*fac))*Q , 
00343          (vx*(2*a*x+e*std::pow(y/fac,2))/(r*r))*P
00344          + ((n/fac)*std::pow(a/r,2)*(x*x/r-std::pow(y/fac,2)/a))*Q );
00345 
00346 
00347       dYdM = Stack ( (vx*P+vy*Q)/n, (-n*std::pow(a/r,3))*(x*P+y*Q) );
00348 
00349 
00350       // Partials w.r.t. inlcination, node and argument of pericenter
00351       dYdi = Stack ( x*dPdi+y*dQdi, vx*dPdi+vy*dQdi ); 
00352       dYdO = Stack ( x*dPdO+y*dQdO, vx*dPdO+vy*dQdO ); 
00353       dYdo = Stack ( x*dPdo+y*dQdo, vx*dPdo+vy*dQdo ); 
00354 
00355       // Derivative of mean anomaly at time dt w.r.t. the semimajor axis at epoch
00356 
00357       double dMda = -1.5*(n/a)*dt;  
00358 
00359       // Combined partial derivative matrix of state with respect to epoch elements
00360 
00361       for (int k=0; k<6; k++) 
00362       {
00363          dYdA(k,0) = dYda(k) + dYdM(k)*dMda;  
00364          dYdA(k,1) = dYde(k); 
00365          dYdA(k,2) = dYdi(k); 
00366          dYdA(k,3) = dYdO(k);
00367          dYdA(k,4) = dYdo(k);
00368          dYdA(k,5) = dYdM(k);
00369       }
00370 
00371       return dYdA;
00372 
00373    }  // End of method 'KeplerOrbit::StatePartials()'
00374 
00375 
00376       /* Computes the osculating Keplerian elements from the satellite 
00377        * state vector for elliptic orbits.
00378        * @param GM       Gravitational coefficient
00379        * @param y        State vector(position and velocity)
00380        * @param return   Keplerian elements(a e i OGM omg M)
00381        * @param warning  The state vector and GM must be given in consistent units
00382        */
00383    Vector<double> KeplerOrbit::Elements( double GM, const Vector<double>& y )
00384    {
00385       // position and velocity
00386       Vector<double>  r(3),v(3);
00387       r(0) = y(0);
00388       r(1) = y(1);
00389       r(2) = y(2);
00390       v(0) = y(3);
00391       v(1) = y(4);
00392       v(2) = y(5);
00393 
00394       Vector<double> h = cross(r,v);                           // Areal velocity
00395       double H = norm(h);
00396 
00397       double Omega = atan2( h(0), -h(1) );                     // Long. ascend. node 
00398       Omega = Modulo(Omega,2.0*ASConstant::PI);
00399 
00400       double i     = std::atan2( std::sqrt(h(0)*h(0)+h(1)*h(1)), h(2) ); // Inclination        
00401       
00402       double u  = std::atan2( r(2)*H, -r(0)*h(1)+r(1)*h(0) );    // Arg. of latitude   
00403       double R  = norm(r);                                       // Distance           
00404 
00405       double a = 1.0 / (2.0/R-dot(v,v)/GM);                     // Semi-major axis    
00406 
00407       double eCosE = 1.0-R/a;                                   // e*cos(E)           
00408       double eSinE = dot(r,v)/std::sqrt(GM*a);                  // e*sin(E)           
00409 
00410       double e2 = eCosE*eCosE +eSinE*eSinE;
00411       double e  = std::sqrt(e2);                                     // Eccentricity 
00412       double E  = std::atan2(eSinE,eCosE);                           // Eccentric anomaly  
00413 
00414       double M  = Modulo(E-eSinE,2.0*ASConstant::PI);                // Mean anomaly
00415 
00416       double nu = std::atan2(std::sqrt(1.0-e2)*eSinE, eCosE-e2);     // True anomaly
00417 
00418       double omega = Modulo(u-nu,2.0*ASConstant::PI);                // Arg. of perihelion 
00419 
00420       // Keplerian elements vector
00421 
00422       Vector<double> Kep(6,0.0);
00423       Kep(0) = a;
00424       Kep(1) = e;
00425       Kep(2) = i;
00426       Kep(3) = Omega;
00427       Kep(4) = omega;
00428       Kep(5) = M;
00429 
00430       return Kep; 
00431 
00432    }  // End of method 'KeplerOrbit::Elements()'
00433 
00434    
00435       /*Computes orbital elements from two given position vectors and 
00436        *associated times 
00437        * @param GM        Gravitational coefficient
00438        * @param Mjda     Time ta (Modified Julian Date)
00439        * @param Mjdb     Time tb (Modified Julian Date)
00440        * @param ra       Position vector at time t_a
00441        * @param rb       Position vector at time t_b
00442        * @return>   Keplerian elements (a,e,i,Omega,omega,M) at ta
00443        *
00444        * @warning   The function cannot be used with state vectors describing a 
00445        *            circular or non-inclined orbit.
00446        */
00447    Vector<double> KeplerOrbit::Elements( double GM, double Mjda, double Mjdb, 
00448       const Vector<double>& ra, const Vector<double>& rb )
00449    {
00450 
00451       // Variables
00452       double  a, e, i, Omega, omega, M;
00453 
00454       // Calculate vector r_0 (fraction of r_b perpendicular to r_a) 
00455       // and the magnitudes of r_a,r_b and r_0
00456 
00457       double s_a = norm(ra);  
00458       Vector<double> e_a = ra/s_a;
00459 
00460       double s_b = norm(rb); 
00461       double fac = dot(rb,e_a); 
00462       Vector<double> r_0 = rb-fac*e_a;
00463 
00464       double s_0 = norm(r_0);  
00465       Vector<double> e_0 = r_0/s_0;
00466 
00467       // Inclination and ascending node 
00468 
00469       Vector<double> W = cross(e_a,e_0);
00470       Omega = std::atan2( W(0), -W(1) );                     // Long. ascend. node 
00471       Omega = Modulo(Omega,2.0*ASConstant::PI);
00472       i     = std::atan2( std::sqrt(W(0)*W(0)+W(1)*W(1)), W(2) ); // Inclination        
00473       
00474       double u(0.0);
00475       if (i==0.0) 
00476          u = std::atan2( ra(1), ra(0) );
00477       else 
00478          u = std::atan2( +e_a(2) , -e_a(0)*W(1)+e_a(1)*W(0) );
00479 
00480       // Semilatus rectum
00481 
00482       double tau = std::sqrt(GM) * 86400.0*fabs(Mjdb-Mjda);   
00483       double eta = FindEta( ra, rb, tau );
00484       double p   = std::pow( s_a*s_0*eta/tau, 2 );   
00485 
00486       // Eccentricity, true anomaly and argument of perihelion
00487 
00488       double cos_dnu = fac / s_b;    
00489       double sin_dnu = s_0 / s_b;
00490 
00491       double ecos_nu = p / s_a - 1.0;  
00492       double esin_nu = ( ecos_nu * cos_dnu - (p/s_b-1.0) ) / sin_dnu;
00493 
00494       e  = std::sqrt( ecos_nu*ecos_nu + esin_nu*esin_nu );
00495       double nu = std::atan2(esin_nu,ecos_nu);
00496 
00497       omega = Modulo(u-nu,2.0*ASConstant::PI);
00498 
00499       // Perihelion distance, semimajor axis and mean motion
00500 
00501       a = p/(1.0-e*e);
00502       double n = std::sqrt( GM / std::fabs(a*a*a) );
00503 
00504       // Mean anomaly and time of perihelion passage
00505 
00506       if (e<1.0) {
00507          double E = std::atan2( std::sqrt((1.0-e)*(1.0+e)) * esin_nu,  ecos_nu + e*e );
00508          M = Modulo( E - e*std::sin(E), 2.0*ASConstant::PI );
00509       }
00510       else 
00511       {
00512          double sinhH = std::sqrt((e-1.0)*(e+1.0)) * esin_nu / ( e + e * ecos_nu );
00513          M = e * sinhH - std::log ( sinhH + std::sqrt(1.0+sinhH*sinhH) );
00514       }
00515 
00516       // Keplerian elements vector
00517 
00518       gpstk::Vector<double> Kep(6,0.0);
00519       Kep(0) = a;
00520       Kep(1) = e;
00521       Kep(2) = i;
00522       Kep(3) = Omega;
00523       Kep(4) = omega;
00524       Kep(5) = M;
00525 
00526       return Kep;
00527 
00528    }  // End of method 'KeplerOrbit::Elements()'
00529 
00530 
00543    void KeplerOrbit::TwoBody( double GM, const Vector<double>& Y0, double dt, 
00544       Vector<double>& Y, Matrix<double>& dYdY0 )
00545    {
00546       double  a,e,i,n, sqe2,naa;
00547       double  P_aM, P_eM, P_eo, P_io, P_iO;
00548       gpstk::Vector<double>  A0(6);
00549       gpstk::Matrix<double>  dY0dA0(6,6), dYdA0(6,6), dA0dY0(6,6);
00550 
00551       // Orbital elements at epoch
00552       A0 = Elements(GM,Y0);
00553 
00554       a = A0(0);  e = A0(1);  i = A0(2);
00555 
00556       n = std::sqrt(GM/(a*a*a));
00557 
00558       // Propagated state 
00559 
00560       Y = State(GM,A0,dt);
00561 
00562       // State vector partials w.r.t epoch elements
00563 
00564       dY0dA0 = StatePartials(GM,A0,0.0);
00565       dYdA0  = StatePartials(GM,A0,dt);
00566       
00567       // Poisson brackets
00568 
00569       sqe2 = std::sqrt((1.0-e)*(1.0+e));
00570       naa  = n*a*a;
00571 
00572       P_aM = -2.0/(n*a);                   // P(a,M)     = -P(M,a)
00573       P_eM = -(1.0-e)*(1.0+e)/(naa*e);     // P(e,M)     = -P(M,e)
00574       P_eo = +sqe2/(naa*e);                // P(e,omega) = -P(omega,e)
00575       P_io = -1.0/(naa*sqe2*std::tan(i));       // P(i,omega) = -P(omega,i)
00576       P_iO = +1.0/(naa*sqe2*std::sin(i));       // P(i,Omega) = -P(Omega,i)
00577 
00578       // Partials of epoch elements w.r.t. epoch state
00579 
00580       for(int k=0;k<3;k++) 
00581       {
00582 
00583          dA0dY0(0,k)   = + P_aM*dY0dA0(k+3,5);
00584          dA0dY0(0,k+3) = - P_aM*dY0dA0(k  ,5);
00585 
00586          dA0dY0(1,k)   = + P_eo*dY0dA0(k+3,4) + P_eM*dY0dA0(k+3,5);
00587          dA0dY0(1,k+3) = - P_eo*dY0dA0(k  ,4) - P_eM*dY0dA0(k  ,5);
00588 
00589          dA0dY0(2,k)   = + P_iO*dY0dA0(k+3,3) + P_io*dY0dA0(k+3,4);
00590          dA0dY0(2,k+3) = - P_iO*dY0dA0(k  ,3) - P_io*dY0dA0(k  ,4);
00591 
00592          dA0dY0(3,k)   = - P_iO*dY0dA0(k+3,2);
00593          dA0dY0(3,k+3) = + P_iO*dY0dA0(k  ,2);
00594 
00595          dA0dY0(4,k)   = - P_eo*dY0dA0(k+3,1) - P_io*dY0dA0(k+3,2);
00596          dA0dY0(4,k+3) = + P_eo*dY0dA0(k  ,1) + P_io*dY0dA0(k  ,2);
00597 
00598          dA0dY0(5,k)   = - P_aM*dY0dA0(k+3,0) - P_eM*dY0dA0(k+3,1);
00599          dA0dY0(5,k+3) = + P_aM*dY0dA0(k  ,0) + P_eM*dY0dA0(k  ,1);
00600 
00601       };
00602 
00603       // State transition matrix
00604       dYdY0 = dYdA0 * dA0dY0;
00605 
00606    }  // End of method 'KeplerOrbit::TwoBody()'
00607 
00608       
00609       // F : local function for use by FindEta()
00610       // F = 1 - eta +(m/eta**2)*W(m/eta**2-l)
00611       //
00612    double KeplerOrbit::F (double eta, double m, double l)
00613    {
00614 
00615       const double eps = 100.0 * eps_mach;
00616 
00617       double  w,W,a,n,g;
00618 
00619       w = m/(eta*eta)-l; 
00620 
00621       if (std::fabs(w)<0.1) 
00622       { 
00623          W = a = 4.0/3.0; n = 0.0;
00624          do 
00625          {
00626             n += 1.0;  a *= w*(n+2.0)/(n+1.5);  W += a; 
00627          }
00628          while (std::fabs(a) >= eps);
00629       }
00630       else 
00631       {
00632          if (w > 0.0) 
00633          {
00634             g = 2.0 * std::asin(std::sqrt(w));  
00635             W = (2.0*g - std::sin(2.0*g)) / std::pow(std::sin(g), 3);
00636          }
00637          else 
00638          {
00639             g = 2.0*std::log(std::sqrt(-w)+std::sqrt(1.0-w));  // =2.0*arsinh(sqrt(-w))
00640             W = (std::sinh(2.0*g) - 2.0*g) / std::pow(std::sinh(g), 3);
00641          }
00642       }
00643 
00644       return ( 1.0 - eta + (w+l)*W );
00645 
00646    }   // End of function F
00647 
00648    double KeplerOrbit::getPeriod(double GM, const Vector<double>& Kep)
00649    {
00650       const double n = std::sqrt(GM / std::pow(Kep(0),3));
00651       return 2.0 * ASConstant::PI / n;
00652    }
00653    
00654    double KeplerOrbit::getApogee(double GM, const Vector<double>& Kep)
00655    {
00656       // p =  a*(1-e*e)
00657       double p = Kep(0) * (1.0 - Kep(1) * Kep(1));
00658       return p / (1 - Kep(1));
00659    }
00660 
00661    double KeplerOrbit::getPerigee(double GM, const Vector<double>& Kep)
00662    {
00663       // p =  a*(1-e*e)
00664       double p = Kep(0) * (1.0 - Kep(1) * Kep(1));
00665 
00666       return p / (1 + Kep(1));
00667    }
00668 
00669 
00670 
00671    void KeplerOrbit::test()
00672    {
00673       const double GM_Earth    = 398600.4415e+9;    // [m^3/s^2]; JGM3
00674       
00675       const double Deg = 180.0 / ASConstant::PI;
00676       
00677       double rv[6]={-6345.000e3, -3723.000e3,  -580.000e3, +2.169000e3, -9.266000e3, -1.079000e3 };
00678 
00679       Vector<double> Y0_ref(6);
00680       Y0_ref = rv;
00681 
00682       Vector<double> Kep = Elements ( GM_Earth, Y0_ref );
00683       double ceta = KeplerOrbit::TrueAnomaly(Kep(5),Kep(1));
00684       double ecc = KeplerOrbit::EccentricAnomaly(Kep(5),Kep(1));
00685 
00686       cout<<fixed<<setprecision(6);
00687       cout << "Orbital elements:" << endl << endl
00688          << setprecision(3)
00689          << "  Semimajor axis   " << setw(10) << Kep(0)/1000.0 << " km" << endl
00690          << setprecision(7)
00691          << "  Eccentricity     " << setw(10) << Kep(1)<< endl
00692          << setprecision(3)
00693          << "  Inclination      " << setw(10) << Kep(2)*Deg << " deg"<< endl
00694          << "  RA ascend. node  " << setw(10) << Kep(3)*Deg << " deg"<< endl
00695          << "  Arg. of perigee  " << setw(10) << Kep(4)*Deg << " deg"<< endl
00696          << "  Mean anomaly     " << setw(10) << Kep(5)*Deg << " deg"<< endl
00697          << "  True anomaly     " << setw(10) << ceta*Deg << " deg"<< endl
00698          << "  Eccentric anomaly" << setw(10) << ecc*Deg << " deg"<< endl
00699          << endl;
00700       
00701 
00702       Vector<double> Y_ref = State(GM_Earth,Kep,0);
00703       Vector<double> Y(6);
00704       Matrix<double> phi(6,6);
00705 
00706       KeplerOrbit::TwoBody ( GM_Earth,Y0_ref,0, Y,phi); // State vector
00707       
00708       cout<<fixed<<setw(12)<<setprecision(8);
00709       for(int i=0;i<6;i++)
00710       {
00711          cout<<Y(i)<<endl;
00712       }
00713 
00714       for(int i=0;i<6;i++)
00715       {
00716          for(int j=0;j<6;j++)
00717          {
00718             cout<<phi(i,j)<< " ";
00719          }
00720          cout<<endl;
00721       }
00722 
00723       Vector<double> Y2(6),diff(6);
00724       Y2 = phi*Y0_ref;
00725 
00726       diff = Y2-Y;
00727       for(int i=0;i<6;i++)
00728       {
00729          cout<<diff(i)<<endl;
00730       }
00731       
00732   
00733    }    // End of method 'KeplerOrbit::test()'
00734 
00735 
00736 }       // End of namespace 'gpstk'
00737 
00738 
00739 
00740 
00741 

Generated on Tue May 22 03:30:59 2012 for GPS ToolKit Software Library by  doxygen 1.3.9.1