Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages | Examples

Keplerian.cpp

Go to the documentation of this file.
00001 //////////////////////////////////////////////////////////////////////////////////////////////////
00002 /*! \file Keplerian.cpp
00003  *  \brief Implementation of the Keplerian orbit state representation.
00004  *  \author $Author: jayhawk_hokie $
00005  *  \version $Revision: 1.5 $
00006  *  \date    $Date: 2007/08/31 16:52:10 $
00007  *//////////////////////////////////////////////////////////////////////////////////////////////////
00008 /* 
00009  *
00010  */
00011 //////////////////////////////////////////////////////////////////////////////////////////////////
00012 
00013 #include "Keplerian.h"
00014 namespace O_SESSAME {
00015 
00016 /*! \brief Default Deconstructor */
00017 Keplerian::~Keplerian()
00018 {
00019 }
00020 
00021 
00022 /*! \brief Return a pointer to a new instance of a Keplerian orbit state representation type.
00023  *
00024  *  This is used to request memory for a new instance of a Keplerian. It is necessary 
00025  *      when attempting to get a pointer from the abstract data type OrbitStateRepresentation 
00026  *      and the actual representation type isn't known.
00027  * @return a pointer to a new allocation of memory for the Keplerian object.
00028  */
00029 Keplerian* Keplerian::NewPointer()
00030 {
00031         return new Keplerian();
00032 }
00033 
00034 
00035 /*! \brief Return a pointer to a copy of the Keplerian orbit state representation instance.
00036  *
00037  *  This is used to request memory for a copy of this instance of Keplerian. It is necessary 
00038  *      when attempting to get a pointer from the abstract data type OrbitStateRepresentation 
00039  *      and the actual representation type isn't known.
00040  * @return a pointer to a copy of the Keplerian object.
00041  */
00042 Keplerian* Keplerian::Clone()
00043 {
00044         return new Keplerian(*this);
00045 }
00046 
00047 
00048 /*! \brief Create an initially empty Keplerian orbit state representation. */
00049 Keplerian::Keplerian() : m_OrbitalElements(NUM_KEPLERIAN_ELEMENTS), m_OrbitalParameters( NUM_KEPLERIAN_PARAMETERS )
00050 {
00051 }
00052 
00053 /*! \brief Create an initially empty Keplerian orbit state representation. */
00054 //Keplerian::Keplerian() : m_OrbitalElements(NUM_KEPLERIAN_ELEMENTS) 
00055 //{
00056 //}
00057 
00058 
00059 /*! Create a Keplerian orbit state representation from a vector of orbital elements.
00060  * @param _Elements 6-element vector of Keplerian orbital elements [a, e, i, \f$\Omega\f$, \f$\omega\f$, \f$\nu\f$]. (km, -, rad, rad, rad, rad)
00061  */
00062 Keplerian::Keplerian(const Vector& _Elements): m_OrbitalElements(NUM_KEPLERIAN_ELEMENTS), m_OrbitalParameters( NUM_KEPLERIAN_PARAMETERS )
00063 {
00064         SetKeplerianRepresentationTrueAnomaly( _Elements ); // Set as default
00065 }
00066 
00067 
00068 /*! \brief Create a copy of the Keplerian representation.
00069  *
00070  */
00071 Keplerian Keplerian::KeplerianCopy( )
00072 {
00073         return( *this );
00074 }
00075 
00076 
00077 /*! \brief Set the Keplerian representation by a vector representation of Orbital Elements.
00078  * 
00079  * @param _Elements 6-element vector of Keplerian orbital elements [a, e, i, \f$\Omega\f$, \f$\omega\f$, \f$\nu\f$]. (km, -, rad, rad, rad, rad)
00080  */
00081 void Keplerian::SetKeplerianRepresentationTrueAnomaly( const Vector& _OrbitalElements )
00082 {
00083 
00084         m_OrbitalElements = _OrbitalElements;
00085         /* Argument of Lattitude (rad) */
00086         m_OrbitalParameters( ARG_LATTITUDE ) = GetArgLattitude();
00087         /* Longitude of Perigee (rad) */
00088         m_OrbitalParameters( LONG_PERIGEE ) = GetLongPerigee();
00089         /* True Longitude (rad) */
00090         m_OrbitalParameters( TRUE_LONGITUDE ) = GetTrueLongitude();
00091         /* Eccentric Anomaly, E (rad) */
00092         m_OrbitalParameters( ECCENTRIC_ANOMALY ) = GetEccentricAnomalyFromTrueAnomaly();
00093         /* Mean Anomaly, M (-) */
00094         m_OrbitalParameters( MEAN_ANOMALY ) = GetMeanAnomalyFromEccentricAnomaly();
00095         
00096         return;
00097 }
00098 
00099 
00100 /*! \brief Set the Keplerian representation by a vector representation of Orbital Elements.
00101  * 
00102  * @param _Elements 6-element vector of Keplerian orbital elements [a, e, i, \f$\Omega\f$, \f$\omega\f$, E]. (km, -, rad, rad, rad, rad)
00103  */
00104 void Keplerian::SetKeplerianRepresentationEccentricAnomaly( const Vector& _OrbitalElements )
00105 {
00106 
00107         m_OrbitalElements( _(SEMIMAJOR_AXIS, ARG_PERIGEE) ) = _OrbitalElements( _( SEMIMAJOR_AXIS, ARG_PERIGEE ) ) ; // a, e, i, Omega, omega
00108         /* Eccentric Anomaly, E (rad) */
00109         m_OrbitalParameters( ECCENTRIC_ANOMALY ) = _OrbitalElements( VectorIndexBase + 5 );
00110         /* True Anomaly, \f$\nu\f$ (rad) */
00111         GetTrueAnomalyFromEccentricAnomaly( m_OrbitalParameters( ECCENTRIC_ANOMALY ) );
00112         
00113         /* Argument of Lattitude (rad) */
00114         m_OrbitalParameters( ARG_LATTITUDE ) = GetArgLattitude();
00115         /* Longitude of Perigee (rad) */
00116         m_OrbitalParameters( LONG_PERIGEE ) = GetLongPerigee();
00117         /* True Longitude (rad) */
00118         m_OrbitalParameters( TRUE_LONGITUDE ) = GetTrueLongitude();
00119         /* Mean Anomaly, M (-) */
00120         m_OrbitalParameters( MEAN_ANOMALY ) = GetMeanAnomalyFromEccentricAnomaly();
00121         
00122         return;
00123 }
00124 
00125 
00126 
00127 /*! \brief Set the Keplerian representation by a vector representation of Orbital Elements.
00128  * 
00129  * @param _Elements 6-element vector of Keplerian orbital elements [a, e, i, \f$\Omega\f$, \f$\omega\f$, M]. (km, -, rad, rad, rad, rad)
00130  */
00131 void Keplerian::SetKeplerianRepresentationMeanAnomaly( const Vector& _OrbitalElements )
00132 {
00133 
00134         m_OrbitalElements( _(SEMIMAJOR_AXIS, ARG_PERIGEE) ) = _OrbitalElements( _( SEMIMAJOR_AXIS, ARG_PERIGEE ) ) ; // a, e, i, Omega, omega
00135         
00136         /* Mean Anomaly, E (rad) */
00137         m_OrbitalParameters( MEAN_ANOMALY ) = _OrbitalElements( VectorIndexBase + 5 );
00138         
00139         /* Eccentric Anomaly (rad) */
00140         m_OrbitalParameters( ECCENTRIC_ANOMALY ) = GetEccentricAnomalyFromMeanAnomaly( m_OrbitalParameters( MEAN_ANOMALY ) );
00141 
00142         /* True Anomaly, \f$\nu\f$ (rad) */
00143         GetTrueAnomalyFromEccentricAnomaly( m_OrbitalParameters( ECCENTRIC_ANOMALY ) );
00144         
00145         /* Argument of Lattitude (rad) */
00146         m_OrbitalParameters( ARG_LATTITUDE ) = GetArgLattitude();
00147         /* Longitude of Perigee (rad) */
00148         m_OrbitalParameters( LONG_PERIGEE ) = GetLongPerigee();
00149         /* True Longitude (rad) */
00150         m_OrbitalParameters( TRUE_LONGITUDE ) = GetTrueLongitude();
00151         /* Mean Anomaly, M (-) */
00152         //m_OrbitalParameters( MEAN_ANOMALY ) = GetMeanAnomalyFromEccentricAnomaly();
00153         
00154         return;
00155 }
00156 
00157 
00158 /*! \brief Set the Keplerian representation by converting the position and velocity vectors in inertial coordinates (ECI)
00159  * to Keplerian Orbit Elements. Follows procedure outlined in Analytical Mechanics of Space Systems by 
00160  * Schaub and Junkins (page 409).
00161  * 
00162  * Required to match the OrbitStateRepresentation abstract class interface.
00163  * @param _position 3-element vector of position components in inertial coordinates. (km)
00164  * @param _velocity 3-element vector of vector components in inertial coordinates. (km/s)
00165  */
00166 void Keplerian::SetPositionVelocity(const Vector& _position, const Vector& _velocity)
00167 {
00168         double radiusScalar             = norm2( _position ); // scalar radius (km)
00169         double velocityScalar           = norm2( _velocity ); // scalar velocity (km/s)
00170         Vector angularMomentumVector    = crossP( _position, _velocity); // angular momentum vector (km^2/s)
00171         double angularMomentumScalar    = norm2( angularMomentumVector ); // angular momentum scalar (km^2/s)
00172         
00173         /* Determine Semimajor axis, a (km) from energy equation */
00174         m_OrbitalElements(SEMIMAJOR_AXIS) = 1 / ( 2/radiusScalar - pow( velocityScalar, 2 )/MU );
00175 
00176         /* Determine Eccentricity, e (-) from Eccentricity vector */
00177         Vector Eccentricity(3);
00178         Eccentricity                    = ( crossP( _velocity, angularMomentumVector ) - MU/radiusScalar * _position ) / MU ;
00179         m_OrbitalElements(ECCENTRICITY) = norm2( Eccentricity );
00180         
00181         /* Compute unit orientation vectors of the perifocal frame */
00182         Vector i_e = Eccentricity/( m_OrbitalElements(ECCENTRICITY) ); 
00183         Vector i_h = angularMomentumVector/angularMomentumScalar;
00184         Vector i_p = crossP( i_h, i_e );
00185 
00186         Vector i_r = _position/radiusScalar; // (-)
00187 
00188         Matrix PN(3,3);
00189         PN( _(1), _(1,3) ) = ~i_e;
00190         PN( _(2), _(1,3) ) = ~i_p;
00191         PN( _(3), _(1,3) ) = ~i_h;
00192 
00193         /* Longitude of the Ascending Node, Omega (rad) [range 0 to 2PI] */
00194         if( PN(3,2) == 0 ) // due to peculiar behavior of c++
00195                 m_OrbitalElements( LONG_ASC_NODE ) = atan2( PN(3,1), PN(3,2) );
00196         else
00197                 m_OrbitalElements( LONG_ASC_NODE ) = atan2( PN(3,1), -PN(3,2) );
00198         
00199         /* Inclination, i (rad) [range 0 to PI] */
00200         m_OrbitalElements( INCLINATION ) = acos( PN(3,3) );
00201 
00202         /* Argument of perigee, omega (rad) [range 0 to 2PI] */
00203         m_OrbitalElements( ARG_PERIGEE ) = atan2( PN(1,3), PN(2,3) );
00204 
00205 
00206         /* True Anomaly, f (rad) */
00207         m_OrbitalElements( TRUE_ANOMALY ) = atan2( ( ( crossP(i_e, i_r) ).dot(i_h) ), ( i_e.dot( i_r ) ) );
00208 
00209         /* Special Cases for Eccentricity */ 
00210         const double tolerance = 10e-8; 
00211         if( abs( m_OrbitalElements(ECCENTRICITY) ) < tolerance ) /* Circular Orbit */
00212         { 
00213                 m_OrbitalElements( ARG_PERIGEE )        = 0; /* undefined Argument of Periapsis */
00214                 if( m_OrbitalElements( INCLINATION ) < tolerance ) /* Circular Equatorial Orbit */
00215                 { 
00216                         m_OrbitalElements(LONG_ASC_NODE)        = 0; /* undefined Longitude of Ascending Node */
00217                         m_OrbitalElements(TRUE_ANOMALY)         = acos( _position( VectorIndexBase ) / radiusScalar ); /* Determine True Anomaly */
00218                         if( _position( VectorIndexBase+1 ) < 0 )
00219                                 m_OrbitalElements(TRUE_ANOMALY) = 2*PI - m_OrbitalElements(TRUE_ANOMALY); /* Select appropriate quadrant */
00220                 }
00221                 else /* Circular Inclined - define Argument of Latitude, u */
00222                 {
00223                         //m_OrbitalElements( TRUE_ANOMALY )     = m_OrbitalParameters( ARG_LATTITUDE );
00224                         
00225                         Vector K_Vector(3); 
00226                         K_Vector(VectorIndexBase+2) = 1;
00227                         Vector lineNodes                        = crossP( K_Vector, angularMomentumVector );
00228                         double magLineNodes                     = norm2( lineNodes ); 
00229                         m_OrbitalElements( TRUE_ANOMALY )       = acos( lineNodes.dot( _position )/( magLineNodes * radiusScalar) );
00230                         if( _position( VectorIndexBase+2 ) < 0 )
00231                                 m_OrbitalElements(TRUE_ANOMALY) = 2*PI - ( m_OrbitalElements( TRUE_ANOMALY ) ); 
00232                 }
00233         }
00234         /* Special Casses for Inclination */
00235         else if( m_OrbitalElements( INCLINATION ) < tolerance )
00236         { // Elliptical Equitorial - define True Longitude of Periapsis, ~omega~
00237                 m_OrbitalElements( LONG_ASC_NODE )              = 0; /* undefined Longitude of Ascending Node */
00238                 m_OrbitalElements( ARG_PERIGEE )                = acos( Eccentricity( VectorIndexBase ) / m_OrbitalElements(ECCENTRICITY) );
00239                 if (Eccentricity(VectorIndexBase+2) < 0)
00240                         m_OrbitalElements(ARG_PERIGEE)          = 2*PI - m_OrbitalElements(ARG_PERIGEE); 
00241         }
00242 
00243         /* Argument of Lattitude (rad) */
00244         m_OrbitalParameters( ARG_LATTITUDE ) = GetArgLattitude();
00245 
00246         /* Longitude of Perigee (rad) */
00247         m_OrbitalParameters( LONG_PERIGEE ) = GetLongPerigee();
00248 
00249         /* True Longitude (rad) */
00250         m_OrbitalParameters( TRUE_LONGITUDE ) = GetTrueLongitude();
00251 
00252         /* Eccentric Anomaly, E (rad) */
00253         m_OrbitalParameters( ECCENTRIC_ANOMALY ) = GetEccentricAnomalyFromTrueAnomaly();
00254 
00255         /* Mean Anomaly, M (-) */
00256         m_OrbitalParameters( MEAN_ANOMALY ) = GetMeanAnomalyFromEccentricAnomaly();
00257 
00258 
00259         return;
00260 }
00261 
00262 
00263 /*! \brief Determine the Argument of Lattitude, \f$\theta\f$ (rad).
00264  * \par Equation:
00265  * \f[\theta = \omega + f \f]
00266  */ 
00267 double Keplerian::GetArgLattitude()
00268 {
00269         m_OrbitalParameters( ARG_LATTITUDE ) = m_OrbitalElements( ARG_PERIGEE ) + m_OrbitalElements( TRUE_ANOMALY );
00270         return( m_OrbitalParameters( ARG_LATTITUDE ) );
00271 }
00272 
00273 /*! \brief Determine the Longitude of Perigee, \f$\Pi\f$ (rad).
00274  * \par Equation:
00275  * \f[\theta = \Omega + \omega\f]
00276  */ 
00277 double Keplerian::GetLongPerigee()
00278 {
00279         m_OrbitalParameters( LONG_PERIGEE ) = m_OrbitalElements( LONG_ASC_NODE ) + m_OrbitalElements( ARG_PERIGEE );
00280         return( m_OrbitalParameters( LONG_PERIGEE ) );
00281 }
00282 
00283 /*! \brief Determine the True Longitude, \f$\ell\f$ (rad).
00284  * \par Equation:
00285  * \f[\ell = \Omega + \omega + f \f]
00286  */ 
00287 double Keplerian::GetTrueLongitude()
00288 {
00289         m_OrbitalParameters( TRUE_LONGITUDE ) = m_OrbitalElements( LONG_ASC_NODE ) + m_OrbitalElements( ARG_PERIGEE ) + m_OrbitalElements( TRUE_ANOMALY );
00290         return( m_OrbitalParameters( TRUE_ANOMALY ) );
00291 }
00292 
00293 
00294 /*! \brief Determine the Eccentric Anomaly \f$E\f$ (rad) from the True Anomaly and Eccentricity.
00295  * \par Equation:
00296  * \f[E = 2 \arctan{ \sqrt{ \frac{ 1-e }{ 1+e } } \tan{ \frac{f}{2} } }\f]
00297  */ 
00298 double Keplerian::GetEccentricAnomalyFromTrueAnomaly()
00299 {
00300         /* Eccentric Anomaly, E (rad) */
00301         m_OrbitalParameters( ECCENTRIC_ANOMALY ) = 2 *  atan2( tan( m_OrbitalElements( TRUE_ANOMALY )/2 )
00302                 * sqrt( ( 1 - m_OrbitalElements( ECCENTRICITY ) ) ), sqrt( ( 1 + m_OrbitalElements( ECCENTRICITY ) ) ) );  
00303         return( m_OrbitalParameters( ECCENTRIC_ANOMALY ) );
00304 }
00305 
00306 /*! \brief Determine the Mean Anomaly \f$M\f$ (-) from the Eccentric Anomaly and Eccentricity.
00307  * \par Equation:
00308  * \f[M = E - e\sin{E}\f]
00309  */ 
00310 double Keplerian::GetMeanAnomalyFromEccentricAnomaly()
00311 {
00312         /* Mean Anomaly, M (-) */
00313         m_OrbitalParameters(MEAN_ANOMALY) = m_OrbitalParameters( ECCENTRIC_ANOMALY ) - m_OrbitalElements( ECCENTRICITY )
00314                 *sin( m_OrbitalParameters( ECCENTRIC_ANOMALY ) );
00315         return( m_OrbitalParameters( MEAN_ANOMALY ) ); 
00316 }
00317 
00318 /*! \brief Set the Keplerian representation by converting the position and velocity vector given in inertial coordinates.
00319  * 
00320  * required to match the OrbitStateRepresentation abstract class interface.
00321  * \todo implement Keplerian conversion functions
00322  * @param _Position 6-element vector of position and velocity components in inertial coordinates. (km, km/s)
00323  */
00324 void Keplerian::SetPositionVelocity(const Vector& _PositionVelocity)
00325 {
00326         Vector Pos(3); 
00327         Pos(_) = _PositionVelocity(_(VectorIndexBase, VectorIndexBase+2));
00328         Vector Vel(3); 
00329         Vel(_) = _PositionVelocity(_(VectorIndexBase+3, VectorIndexBase+5));
00330     
00331         SetPositionVelocity(Pos, Vel);
00332 }
00333 
00334 
00335 /*! \brief Set the Keplerian representation by converting the position and velocity vectors.
00336  * \todo implement Keplerian conversion functions
00337  * @param _Position 3-element vector of position components. (km)
00338  * @param _Velocity 3-element vector of vector components. (km/s)
00339  * @param _TargetOrbFrame Reference frame that the vector components are in.
00340  */
00341 void Keplerian::SetPositionVelocity(const Vector& _Position, const Vector& _Velocity, const OrbitFrame& _OrbFrame)
00342 {
00343         // Convert the position and velocity vectors to inertial frame components (ECI)
00344         Vector Position = _OrbFrame.GetRotation2IJK() * _Position;
00345         Vector Velocity = _OrbFrame.GetRotation2IJK() * _Velocity;
00346     
00347         // Call the inertial version of the SetPositionVelocity()
00348         SetPositionVelocity(Position, Velocity);
00349 }
00350 
00351     
00352  /*! \brief Set the Keplerian representation by converting the position and velocity vector.
00353   * \todo implement Keplerian conversion functions
00354   * @param _Position 6-element vector of position and velocity components. (km, km/s)
00355   * @param _TargetOrbFrame Reference frame that the vector components are in.
00356   */
00357 void Keplerian::SetPositionVelocity(const Vector& _PositionVelocity, const OrbitFrame& _OrbFrame)
00358 {
00359         Vector Pos(3); Pos(_) = _PositionVelocity(_(VectorIndexBase, VectorIndexBase+2));
00360         Vector Vel(3); Vel(_) = _PositionVelocity(_(VectorIndexBase+3, VectorIndexBase+5));
00361     
00362         SetPositionVelocity(Pos, Vel, _OrbFrame);
00363 }       
00364 
00365 
00366 /*! \brief Convert the Keplerian orbit representation to position and velocity vectors in the inertial frame.
00367   * 
00368   * Required to match the OrbitStateRepresentation abstract class interface.
00369   * @return 6-element vector of position and velocity vector components in the inertial reference frame (ECI). [km, km, km, km/s, km/s, km/s]^T
00370   */   
00371 Vector Keplerian::GetPositionVelocity() const
00372 {
00373 
00374         /* Rotation Matrix */
00375         Rotation _transformMatrix = R3( -GetLongAscNode() ) * R1( -GetInclination() ) * R3( -GetArgPerigee() );   
00376         
00377         Vector _positionVelocityPQW(6);
00378         _positionVelocityPQW = GetPositionVelocityPQW();
00379         
00380         Vector _positionVelocityECI(6);
00381         _positionVelocityECI( _(VectorIndexBase + 0, VectorIndexBase + 2) ) 
00382                 = _transformMatrix * _positionVelocityPQW( _(VectorIndexBase + 0, VectorIndexBase + 2) );
00383         _positionVelocityECI( _(VectorIndexBase + 3, VectorIndexBase + 5) ) 
00384                 = _transformMatrix * _positionVelocityPQW( _(VectorIndexBase + 3, VectorIndexBase + 5) );
00385  
00386         return _positionVelocityECI;
00387 }
00388 
00389 /*! \brief Convert the Keplerian orbit representation to position and velocity vectors in the  Perifocal frame (PQW).
00390   * 
00391   * This does not match the the OrbitStateRepresentation abstract class interface, but is used to obtain ECI position and velocity.
00392   * @return 6-element vector of position and velocity vector components in the inertial reference frame (PQW). [km, km, km, km/s, km/s, km/s]^T
00393   */   
00394 Vector Keplerian::GetPositionVelocityPQW() const
00395 {
00396         Vector _positionVelocity(6);
00397 
00398         _positionVelocity(VectorIndexBase + 0) = (GetSemiParameter() * cos(GetTrueAnomaly())) / (1 + GetEccentricity() * cos(GetTrueAnomaly()));
00399         _positionVelocity(VectorIndexBase + 1) = (GetSemiParameter() * sin(GetTrueAnomaly())) / (1 + GetEccentricity() * cos(GetTrueAnomaly()));
00400         //_positionVelocity(VectorIndexBase + 2) = 0;
00401         _positionVelocity(VectorIndexBase + 3) = -sqrt(MU/GetSemiParameter()) * sin(GetTrueAnomaly());
00402         _positionVelocity(VectorIndexBase + 4) = sqrt(MU/GetSemiParameter()) * (GetEccentricity() + cos(GetTrueAnomaly()));
00403         //_positionVelocity(VectorIndexBase + 5) = 0;
00404         
00405         return _positionVelocity;
00406 }
00407 
00408 /*! \brief Convert the Keplerian orbit representation to position and velocity vectors in the specified frame.
00409  * @param _TargetOrbFrame the desired reference frame to return the vector components in.
00410  * @return 6-element vector of position and velocity vector components in the specified reference frame. [km, km, km, km/s, km/s, km/s]^T
00411  */ 
00412 Vector Keplerian::GetPositionVelocity(const OrbitFrame& _TargetOrbFrame) const
00413 {
00414         Vector _positionVelocity = GetPositionVelocity();
00415 
00416         // Convert from the inertial frame to the specified target frame
00417         _positionVelocity(_(VectorIndexBase, VectorIndexBase+2)) = _TargetOrbFrame.GetRotationFromIJK() * _positionVelocity(_(VectorIndexBase, VectorIndexBase+2));
00418         _positionVelocity(_(VectorIndexBase+3, VectorIndexBase+5)) = _TargetOrbFrame.GetRotationFromIJK() * _positionVelocity(_(VectorIndexBase+3, VectorIndexBase+5));
00419         return _positionVelocity;
00420 }
00421 
00422 
00423 /*! \brief Return by reference the converted the Keplerian orbit representation to position and velocity vectors in the inertial frame.
00424  * 
00425  * required to match the OrbitStateRepresentation abstract class interface.
00426  * @param _Position a Vector through which to return the 3-element position vector in inertial corrdinates. (km)
00427  * @param _Velocity a Vector through which to return the 3-element velocity vector in inertial corrdinates. (km/s)
00428  * @param _TargetOrbFrame the desired reference frame to return the vector components in.
00429  */
00430 void Keplerian::GetPositionVelocity(Vector& _position, Vector& _velocity) const
00431 { 
00432         Vector _positionVelocity = GetPositionVelocity();
00433         _position = _positionVelocity( _(VectorIndexBase, VectorIndexBase+2) );
00434         _velocity = _positionVelocity( _(VectorIndexBase+3, VectorIndexBase+5) );
00435     
00436         return;
00437 }
00438 
00439 
00440 /*! \brief Return by reference the converted Keplerian orbit representation to position and velocity vectors in the specified frame.
00441  * @param _Position a Vector through which to return the 3-element position vector. (km)
00442  * @param _Velocity a Vector through which to return the 3-element velocity vector. (km/s)
00443  * @param _TargetOrbFrame the desired reference frame to return the vector components in.
00444  */
00445 void Keplerian::GetPositionVelocity(Vector& _Position, Vector& _Velocity, const OrbitFrame& _TargetOrbFrame) const
00446 { 
00447         // Call the inertial version of GetPositionVelocity()
00448         GetPositionVelocity(_Position, _Velocity);
00449     
00450         // Convert from the inertial frame to the specified target frame
00451         _Position = _TargetOrbFrame.GetRotationFromIJK() * _Position;
00452         _Velocity = _TargetOrbFrame.GetRotationFromIJK() * _Velocity;
00453         
00454         return;
00455 }
00456 
00457 
00458 /*! \brief Solves Kepler's Equation in order to compute eccentric anomaly (E) from mean anomaly (M) and eccentricity (e). 
00459  * Adapted from Appendix A, Orbits,
00460  * by Christopher D. Hall.  Class notes for AOE 4140.
00461  * Available at http://www.aoe.vt.edu/~chall/courses/aoe4140/ 
00462  * \todo Allow user to specify tolerance for numerical convergence. */
00463 double Keplerian::GetEccentricAnomalyFromMeanAnomaly(const double& _MeanAnomaly)
00464 {
00465         
00466         const double    tolerance = 1e-11;              // sets convergence level
00467         /*! \todo Allow user to specify tolerance for numerical convergence. */
00468         double          _EccentricAnomaly;              // returned value
00469         double          testEccAnomaly;                 // candidate EA, for convergence test
00470         double          eccentricity = m_OrbitalElements(ECCENTRICITY);
00471                                                                                 // from Keplerian private data member
00472 
00473         testEccAnomaly  = _MeanAnomaly;
00474         _EccentricAnomaly = testEccAnomaly - 
00475                 ( testEccAnomaly - eccentricity*sin(testEccAnomaly) - _MeanAnomaly ) /
00476                 ( 1 - eccentricity*cos(testEccAnomaly) );
00477         
00478         while ( fabs(_EccentricAnomaly-testEccAnomaly) > tolerance ) // iterate until _EA = testEA
00479         {
00480                 testEccAnomaly = _EccentricAnomaly;
00481                 _EccentricAnomaly = testEccAnomaly - 
00482                         ( testEccAnomaly - eccentricity*sin(testEccAnomaly) - _MeanAnomaly ) /
00483                         ( 1 - eccentricity*cos(testEccAnomaly) );
00484         }
00485 
00486         return _EccentricAnomaly;
00487 }
00488 
00489 
00490 /*! \brief Calculates true anomaly (\f$\nu\f$) from eccentric 
00491  * anomaly (E), semimajor axis (a), and eccentricity (e). 
00492  */
00493 /*! Adapted from Appendix A, Orbits,
00494  * by Christopher D. Hall.  Class notes for AOE 4140.
00495  * Available at http://www.aoe.vt.edu/~chall/courses/aoe4140/ 
00496  */
00497 void Keplerian::GetTrueAnomalyFromEccentricAnomaly(const double& _EccentricAnomaly)
00498 {
00499         
00500         double          cosTrueAnomaly;
00501         double          sinTrueAnomaly;
00502         double          semimajoraxis = m_OrbitalElements(SEMIMAJOR_AXIS);
00503         double          eccentricity = m_OrbitalElements(ECCENTRICITY);
00504         
00505         cosTrueAnomaly = ( eccentricity - cos(_EccentricAnomaly) ) / 
00506                 ( eccentricity*cos(_EccentricAnomaly) - 1 );
00507         sinTrueAnomaly = ( ( semimajoraxis*sqrt(1 - eccentricity*eccentricity) ) / 
00508                 ( semimajoraxis*(1 - eccentricity*cos(_EccentricAnomaly)) ) ) * 
00509                 sin(_EccentricAnomaly);
00510         
00511         m_OrbitalElements(TRUE_ANOMALY) = atan2( sinTrueAnomaly, cosTrueAnomaly );
00512         if ( m_OrbitalElements(TRUE_ANOMALY) < 0 );
00513         {
00514                 m_OrbitalElements(TRUE_ANOMALY) = m_OrbitalElements(TRUE_ANOMALY) + 2*PI;
00515         }
00516         
00517         return;
00518 }
00519 
00520 
00521 /*! \brief Parses a two line element set and updates orbital
00522  *      elements, returns a struct of additional information. 
00523  */
00524 /*! Adapted from Appendix A, Orbits,
00525  *      by Christopher D. Hall.  Class notes for AOE 4140.
00526  *      Available at http://www.aoe.vt.edu/~chall/courses/aoe4140/ 
00527  *
00528  *      Sample TLEs:
00529  *      COSMOS 2278 
00530  *      1 23087U 94023A 98011.59348139 .00000348 00000-0 21464-3 0 5260 
00531  *      2 23087 71.0176 58.4285 0007185 172.8790 187.2435 14.12274429191907
00532  *      
00533  *      NOAA 14 
00534  *      1 23455U 94089A 97320.90946019 .00000140 00000-0 10191-3 0 2621 
00535  *      2 23455 99.0090 272.6745 0008546 223.1686 136.8816 14.11711747148495
00536  *      
00537  *      
00538  *      TLE Definition
00539  *      AAAAAAAAAAAAAAAAAAAAAAAA
00540  *      1 NNNNNU NNNNNAAA NNNNN.NNNNNNNN +.NNNNNNNN +NNNNN-N +NNNNN-N N NNNNN
00541  *      2 NNNNN NNN.NNNN NNN.NNNN NNNNNNN NNN.NNNN NNN.NNNN NN.NNNNNNNNNNNNNN
00542  *      Line 0 is a twenty-four character name (to be consistent with the
00543  *      name length in the NORAD SATCAT).
00544  *      Lines 1 and 2 are the standard Two-Line Orbital Element Set Format
00545  *      identical to that used by NORAD and NASA. 
00546  */
00547 tleStruct Keplerian::ReadTwoLineElementSet(const string& _TwoLineElementSet)
00548 {
00549         
00550         int             finder = 0;             // the start of each substring
00551         int             endlfinder;             // the end of each substring
00552         int             finderLength;   // the length of each substring
00553         
00554         string  LineZero;               // of the tle...
00555         string  LineOne;
00556         string  LineTwo;
00557         
00558         stringstream    placeholder;    // an aptly named translator
00559         int                             exponent;               // for \ddot{meanmotion} and bstar
00560         
00561 // Parse the TLE into three lines by finding endline markers ('\n')...
00562         endlfinder = _TwoLineElementSet.find('\n',finder);  // found one!
00563         finderLength = endlfinder - finder;                                     // "how long is it?"
00564         LineZero = _TwoLineElementSet.substr(finder,finderLength);  // ok, get it.
00565         
00566         finder = endlfinder + 1;                                                        // go to the next character
00567         endlfinder = _TwoLineElementSet.find('\n',finder);      // and repeat x2!
00568         finderLength = endlfinder - finder;
00569         LineOne = _TwoLineElementSet.substr(finder,finderLength);
00570         
00571         finder = endlfinder + 1;
00572         endlfinder = _TwoLineElementSet.size();
00573         finderLength = endlfinder - finder;
00574         LineTwo = _TwoLineElementSet.substr(finder,finderLength);
00575         
00576         /*! \todo Error checking for syntactically correct TLEs, including endlines, carriage returns. */
00577 // Done parsing the TLE into lines.
00578         
00579         
00580 // Unpack Line Zero.
00581         // Line 0 Column Description
00582         // 01-24 Satellite SATCAT Name
00583         m_tleData.satName = LineZero.substr(0,24);
00584 // It's a short line!
00585                 
00586 // Unpack Line One.
00587         // Line 1 Column Description
00588         // 01 Line Number of Element Data, not saved.
00589         // 03-07 Satellite Number
00590         finder = 2;                                                                     // LineOne = [1 SatNum...
00591         endlfinder = LineOne.find(' ',finder);          // Look for the next space
00592         finderLength = endlfinder - finder;                     // Just for readability
00593         placeholder << LineOne.substr(finder,finderLength-1);   // Pull string into streamstring
00594         placeholder >> m_tleData.satNumber;                                             // Push streamstring into _____ (in this case, an int)
00595         // 08 Classification (U=Unclassified)
00596         placeholder.clear();                                            // Still part of the first substring
00597         placeholder << LineOne.substr(endlfinder-1,1);
00598         placeholder >> m_tleData.satClassification;
00599                                                                                                 // ah, whitespace.
00600         // 10-11 International Designator (Last two digits of launch year)
00601         finder = endlfinder + 1;
00602         endlfinder = LineOne.find(' ',finder);
00603         placeholder.clear();
00604         placeholder << LineOne.substr(finder,2);                // gotta be 2 (ints) long
00605         placeholder >> m_tleData.launchYear;
00606         /*! \todo Include full year info logic as per the tle standard, 
00607         wherein 57-99 --> 19__ and 00-56 --> 20__. */
00608         // 12-14 International Designator (Launch number of the year)
00609         placeholder.clear();
00610         placeholder << LineOne.substr(finder+2,3);              // assuming 3 ints, as per the standard
00611         placeholder >> m_tleData.launchNumber;
00612         // 15-17 International Designator (Piece of the launch)
00613         placeholder.clear();
00614         finderLength = endlfinder - finder;
00615         placeholder << LineOne.substr(finder+5,finderLength-5);         // should be 3 chars, but who knows?
00616         placeholder >> m_tleData.launchPiece;
00617         
00618         // 19-20 Epoch Year (Last two digits of year)
00619         finder = endlfinder + 1;
00620         endlfinder = LineOne.find(' ',finder);
00621         placeholder.clear();
00622         placeholder << LineOne.substr(finder,2);                // gotta be 2 ints long
00623         placeholder >> m_tleData.epochYear;
00624         // 21-32 Epoch (Day of the year and fractional portion of the day)
00625         placeholder.clear();
00626         finderLength = endlfinder - finder;
00627         placeholder << LineOne.substr(finder+2,finderLength-2);         // double until next whitespace.
00628         placeholder >> m_tleData.epochDay;
00629         
00630         // 34-43 First Time Derivative of the Mean Motion
00631         finder = endlfinder + 1;
00632         endlfinder = LineOne.find(' ',finder);
00633         finderLength = endlfinder - finder;
00634         placeholder.clear();
00635         placeholder << LineOne.substr(finder,finderLength);
00636         placeholder >> m_tleData.meanmotion1stDeriv;
00637         
00638         // 45-52 Second Time Derivative of Mean Motion (leading decimal point assumed)
00639         finder = endlfinder + 1;
00640         endlfinder = LineOne.find_first_of("-+",finder+1);      // +- starts the exponent 
00641         finderLength = endlfinder - finder;
00642         placeholder.clear();
00643         placeholder << LineOne.substr(finder,finderLength);
00644         placeholder >> m_tleData.meanmotion2ndDeriv;                    // so this is just the raw operand
00645         finder = endlfinder;
00646         endlfinder = LineOne.find(' ',finder);
00647         finderLength = endlfinder - finder;
00648         placeholder.clear();
00649         placeholder << LineOne.substr(finder,finderLength);
00650         placeholder >> exponent;                                                        // here's the exponent
00651         m_tleData.meanmotion2ndDeriv *= pow(10.0,exponent);     // this is op^exp
00652         if ( LineOne[finder] == '+' || LineOne[finder] == '-' )         // now include the leading decimal point
00653                 m_tleData.meanmotion2ndDeriv /= pow(10.0,finderLength-1);
00654         else
00655                 m_tleData.meanmotion2ndDeriv /= pow(10.0,finderLength);
00656         
00657         // 54-61 BSTAR drag term (leading decimal point assumed)
00658         finder = endlfinder + 1;
00659         endlfinder = LineOne.find_first_of("-+",finder+1);
00660         finderLength = endlfinder - finder;
00661         placeholder.clear();
00662         placeholder << LineOne.substr(finder,finderLength);
00663         placeholder >> m_tleData.bstarDrag;
00664         finder = endlfinder;
00665         endlfinder = LineOne.find(' ',finder);
00666         placeholder.clear();
00667         placeholder << LineOne.substr(finder,finderLength);
00668         placeholder >> exponent;
00669         m_tleData.bstarDrag *= pow(10.0,exponent);
00670         if ( LineOne[finder] == '+' || LineOne[finder] == '-' )
00671                 m_tleData.bstarDrag /= pow(10.0,finderLength-1);
00672         else
00673                 m_tleData.bstarDrag /= pow(10.0,finderLength);
00674         
00675         // 63 Ephemeris type
00676         finder = endlfinder + 1;
00677         endlfinder = LineOne.find(' ',finder);
00678         finderLength = endlfinder - finder;                     // = 1
00679         placeholder.clear();
00680         placeholder << LineOne.substr(finder,finderLength);
00681         placeholder >> m_tleData.ephemerisType;
00682 
00683         // 65-68 Element number
00684         finder = endlfinder + 1;
00685         endlfinder = LineOne.size()-1;                  // end of the line, minus 1 for checksum and 1 for \n
00686         finderLength = endlfinder - finder;
00687         placeholder.clear();
00688         placeholder << LineOne.substr(finder,finderLength);
00689         placeholder >> m_tleData.elementNumber;
00690         
00691         // 69 Checksum (Modulo 10)
00692         placeholder.clear();
00693         placeholder << LineOne.substr(endlfinder,1);    // end of the line, less \n
00694         placeholder >> m_tleData.checksumLine1;
00695 // Done with LineOne.
00696 
00697 // Onto LineTwo!
00698         // Line 2 Column Description
00699         // 01 Line Number of Element Data, not saved
00700         // 03-07 Satellite Number, not saved here (saved in Line 1)
00701         // 09-16 Inclination [Degrees], in m_OrbitalElements [radians]
00702         endlfinder = LineTwo.find(' ',2);       // start looking for ' ' inside the satellite number
00703         finder = endlfinder + 1;
00704         endlfinder = LineTwo.find(' ',finder);
00705         finderLength = endlfinder - finder;
00706         placeholder.clear();
00707         placeholder << LineTwo.substr(finder,finderLength);
00708         placeholder >> m_OrbitalElements(INCLINATION);  // Keplerian private data member
00709         m_OrbitalElements(INCLINATION) *= PI/180.0;             // consistent units are good squishy.
00710         
00711         // 18-25 Right Ascension of the Ascending Node [Degrees], in m_OrbitalElements [radians]
00712         finder = endlfinder + 1;
00713         endlfinder = LineTwo.find(' ',finder);
00714         finderLength = endlfinder - finder;
00715         placeholder.clear();
00716         placeholder << LineTwo.substr(finder,finderLength);
00717         placeholder >> m_OrbitalElements(LONG_ASC_NODE);
00718         m_OrbitalElements(LONG_ASC_NODE) *= PI/180.0;
00719         /*! \todo verify that RAAN = longitude of the ascending node. */
00720         
00721         // 27-33 Eccentricity (leading decimal point assumed), in m_OrbitalElements
00722         finder = endlfinder + 1;
00723         endlfinder = LineTwo.find(' ',finder);
00724         finderLength = endlfinder - finder;
00725         placeholder.clear();
00726         placeholder << "0." << LineTwo.substr(finder,finderLength);
00727         placeholder >> m_OrbitalElements(ECCENTRICITY);
00728         m_OrbitalElements(ECCENTRICITY) *= PI/180.0;
00729         
00730         // 35-42 Argument of Perigee [Degrees], in m_OrbitalElements [radians]
00731         finder = endlfinder + 1;
00732         endlfinder = LineTwo.find(' ',finder);
00733         finderLength = endlfinder - finder;
00734         placeholder.clear();
00735         placeholder << LineTwo.substr(finder,finderLength);
00736         placeholder >> m_OrbitalElements(ARG_PERIGEE);
00737         m_OrbitalElements(ARG_PERIGEE) *= PI/180.0;
00738 
00739         // 44-51 Mean Anomaly [Degrees], in m_OrbitalElements [radians]
00740         finder = endlfinder + 1;
00741         endlfinder = LineTwo.find(' ',finder);
00742         finderLength = endlfinder - finder;
00743         placeholder.clear();
00744         placeholder << LineTwo.substr(finder,finderLength);
00745         placeholder >> m_tleData.meanAnomaly;
00746         m_tleData.meanAnomaly *= PI/180.0;
00747         m_tleData.eccentricAnomaly = GetEccentricAnomalyFromMeanAnomaly(m_tleData.meanAnomaly);
00748         
00749         // 53-63 Mean Motion [Revs per day]
00750         finder = endlfinder + 1;
00751         endlfinder = LineTwo.size()-1;                  // last substring
00752         placeholder.clear();
00753         placeholder << LineTwo.substr(finder,11);
00754         placeholder >> m_tleData.meanMotion;
00755         // Buy one mean motion, get a semi-major axis at no extra charge!
00756         m_OrbitalElements(SEMIMAJOR_AXIS) = pow( (MU/pow(m_tleData.meanMotion,2)), (1.0/3.0) );
00757         // And now we can get true anomaly.
00758         GetTrueAnomalyFromEccentricAnomaly(m_tleData.eccentricAnomaly);
00759         
00760         // 64-68 Revolution number at epoch [Revs]
00761         placeholder.clear();
00762         placeholder << LineTwo.substr(finder+11,5);
00763         placeholder >> m_tleData.revolutionNumber;
00764         
00765         // 69 Checksum (Modulo 10)
00766         placeholder.clear();
00767         placeholder << LineTwo.substr(endlfinder,1);
00768         placeholder >> m_tleData.checksumLine2;
00769         
00770         return m_tleData;
00771 }
00772 
00773 
00774 // end jls 030512
00775 
00776 
00777 
00778 
00779 
00780 
00781 
00782 
00783 
00784 
00785 
00786 
00787 /* ********* DEPRECATED FUNCTIONS ********* */
00788 
00789 
00790 
00791 /*! \brief Set the vector of the representation's state vector.
00792  * \warning Deprecated - Do Not Use - will be moved internally
00793  */
00794 void Keplerian::SetState(const Vector& _Elements)
00795 {
00796 
00797         SetKeplerianRepresentationTrueAnomaly( _Elements ); // Set as default
00798         
00799         return;
00800 }
00801 
00802 
00803 /*! \brief Return a vector of the representation's state vector.
00804  * \warning Deprecated - Do Not Use - will be moved internally
00805  */
00806 Vector Keplerian::GetState() const
00807 {
00808     return m_OrbitalElements;
00809 }
00810 
00811 
00812 /*! \brief Return a vector by reference of the representation's state vector.
00813  * \warning Deprecated - Do Not Use - will be moved internally
00814  */
00815 void Keplerian::GetState(Vector& _Elements) const
00816 {
00817     _Elements = m_OrbitalElements;
00818     return;
00819 }
00820 
00821 
00822 
00823 
00824 } // close namespace O_SESSAME
00825 
00826 // Do not change the comments below - they will be added automatically by CVS
00827 /*****************************************************************************
00828 *       $Log: Keplerian.cpp,v $
00829 *       Revision 1.5  2007/08/31 16:52:10  jayhawk_hokie
00830 *       Added functions.
00831 *       
00832 *       Revision 1.4  2006/08/25 15:49:28  jayhawk_hokie
00833 *       Added set Keplerian representation for True Anomaly, Eccentric Anomaly, and Mean Anomaly.
00834 *       
00835 *       Revision 1.3  2006/08/23 21:45:11  jayhawk_hokie
00836 *       Updated ECI to Keplerian and Keplerian to ECI. Also tested functions for special eliptical orbits.
00837 *       
00838 *       Revision 1.2  2005/06/29 20:25:29  jayhawk_hokie
00839 *       Fixed COE equations due to being incomplete.
00840 *       
00841 *       Revision 1.1.1.1  2005/04/26 17:41:00  cakinli
00842 *       Adding OpenSESSAME to DSACSS distrib to capture fixed version.
00843 *       
00844 *       Revision 1.10  2003/05/23 19:28:32  simpliciter
00845 *       Moved comments from header file, basic housekeeping.
00846 *       
00847 *       Revision 1.9  2003/05/20 20:49:05  simpliciter
00848 *       Added new functions for parsing TLEs:
00849 *        - GetEccentricAnomalyFromMeanAnomaly,
00850 *        - GetTrueAnomalyFromEccentricAnomaly,
00851 *        - ReadTwoLineElementSet.
00852 *       
00853 *       Revision 1.8  2003/05/15 21:00:44  nilspace
00854 *       Added SetPositionVelocity(Vector) function implementation.
00855 *       
00856 *       Revision 1.7  2003/05/05 20:46:37  nilspace
00857 *       Added inertial Get/SetPositionVelocity to conform to new OrbitStateRepresentation abstract class.
00858 *       
00859 *       Revision 1.6  2003/04/29 18:48:30  nilspace
00860 *       Added NewPointer and Clone functions to help in getting the correct memory allocation.
00861 *       
00862 *       Revision 1.5  2003/04/24 21:14:23  nilspace
00863 *       const'd all Get() functions.
00864 *       
00865 *       Revision 1.4  2003/04/24 20:10:46  nilspace
00866 *       const'd all Get() functions.
00867 *       
00868 *       Revision 1.3  2003/04/23 18:52:28  nilspace
00869 *       Updated to call correct OrbitFrame::GetRotation calls.
00870 *       Added temporary PI and MU values.
00871 *       Added K_Vector Values.
00872 *       
00873 *       Revision 1.2  2003/04/22 18:06:07  nilspace
00874 *       Added math for Matthew Berry.
00875 *       
00876 *       Revision 1.1  2003/04/08 22:47:35  nilspace
00877 *       Initial Submission.
00878 *       
00879 ******************************************************************************/

Generated on Wed Sep 5 12:54:21 2007 for DSACSS Operational Code by  doxygen 1.3.9.1