Example #1
0
   void SolarRadiationPressure::doCompute(UTCTime utc, EarthBody& rb, Spacecraft& sc)
   {
      crossArea = sc.getDragArea();
      dryMass = sc.getDryMass();
      reflectCoeff = sc.getReflectCoeff();

      Vector<double> r_sun = ReferenceFrames::getJ2kPosition(utc.asTDB(),SolarSystem::Sun);
      Vector<double> r_moon = ReferenceFrames::getJ2kPosition(utc.asTDB(),SolarSystem::Moon);
      
      // from km to m
      r_sun = r_sun*1000.0;
      r_moon = r_moon*1000.0;

      // a
      a = accelSRP(sc.R(),r_sun)*getShadowFunction(sc.R(),r_sun,r_moon,SM_CONICAL);

      // da_dr   reference to Montenbruck P248
      // and it's in the same way as the gravitational attraction of the sun
      da_dr.resize(3,3,0.0);

      double au2 = ASConstant::AU * ASConstant::AU;
      double factor = -1.0*reflectCoeff * (crossArea/dryMass) * ASConstant::P_Sol*au2;

      Vector<double> d = sc.R() - r_sun;
      double dmag = norm(d);
      double dcubed = dmag * dmag *dmag;

      Vector<double> temp1 = d / dcubed;         //  detRJ/detRJ^3

      double muod3 = factor / dcubed;
      double jk = 3.0 * muod3/dmag/dmag; 

      double xx = d(0);
      double yy = d(1);
      double zz = d(2);

      da_dr(0,0) = jk * xx * xx - muod3;
      da_dr(0,1) = jk * xx * yy;
      da_dr(0,2) = jk * xx * zz;

      da_dr(1,0) = da_dr(0,1);
      da_dr(1,1) = jk * yy * yy - muod3;
      da_dr(1,2) = jk * yy * zz;

      da_dr(2,0) = da_dr(0,2);
      da_dr(2,1) = da_dr(1,2);
      da_dr(2,2) = jk * zz * zz - muod3;

      // da_dv
      da_dv.resize(3,3,0.0);

      // da_dp
      dadcr.resize(3,0.0);
      dadcr = a /reflectCoeff;

      da_dcr(0,0) = dadcr(0);
      da_dcr(1,0) = dadcr(1);
      da_dcr(2,0) = dadcr(2);

   }  // End of method 'SolarRadiationPressure::doCompute()'
Example #2
0
      /* Call the relevant methods to compute the acceleration.
      * @param t Time reference class
      * @param bRef Body reference class
      * @param sc Spacecraft parameters and state
      * @return the acceleration [m/s^s]
      */
   void MoonForce::doCompute(UTCTime utc, EarthBody& rb, Spacecraft& sc)
   {
      /* Oliver P69 and P248
       * a = GM*( (s-r)/norm(s-r)^3 - s/norm(s)^3 )
       *
       * da/dr = -GM*( I/norm(r-s)^3 - 3(r-s)transpose(r-s)/norm(r-s)^5)
       */

      Vector<double> r_moon = ReferenceFrames::getJ2kPosition(utc.asTDB(), SolarSystem::Moon);
      
      r_moon = r_moon * 1000.0;         // from km to m

      Vector<double> d = sc.R() - r_moon;
      double dmag = norm(d);
      double dcubed = dmag * dmag *dmag;

      Vector<double> temp1 = d / dcubed;         //  detRJ/detRJ^3

      double smag = norm(r_moon);
      double scubed = smag * smag * smag;

      Vector<double> temp2 = r_moon / scubed;   //  Rj/Rj^3

      Vector<double> sum = temp1 + temp2;
      a = sum * (-mu);                          // a

      // da_dr
      da_dr.resize(3,3,0.0);
      double muod3 = mu / dcubed;
      double jk = 3.0 * muod3/dmag/dmag; 

      double xx = d(0);
      double yy = d(1);
      double zz = d(2);

      da_dr(0,0) = jk * xx * xx - muod3;
      da_dr(0,1) = jk * xx * yy;
      da_dr(0,2) = jk * xx * zz;

      da_dr(1,0) = da_dr(0,1);
      da_dr(1,1) = jk * yy * yy - muod3;
      da_dr(1,2) = jk * yy * zz;

      da_dr(2,0) = da_dr(0,2);
      da_dr(2,1) = da_dr(1,2);
      da_dr(2,2) = jk * zz * zz - muod3;

      // da_dv
      da_dv.resize(3,3,0.0);


      //da_dp
      
   }  // End of method 'MoonForce::doCompute()'
Example #3
0
      /* Ocean pole tide to normalized earth potential coefficients
       *
       * @param mjdUtc UTC in MJD
       * @param dC     Correction to normalized coefficients dC
       * @param dS     Correction to normalized coefficients dS
       *    C20 C21 C22 C30 C31 C32 C33 C40 C41 C42 C43 C44
       */
   void EarthOceanTide::getOceanTide(double mjdUtc, double dC[], double dS[] )
   {
      try
      {
         loadTideFile(fileName,maxN,minX);
      }
      catch (...)
      {
         // faild to get the ocean tide model
         // return zeros
         const int n = (maxN-1)*(maxN+4)/2; 
         for(int i=0;i<n;i++)
         {
            dC[i] = 0.0;
            dS[i] = 0.0;
         }

         return;
      }
      
      UTCTime utc;
      utc=mjdUtc;

      //   CC PURPOSE    :  COMPUTE DOODSON'S FUNDAMENTAL ARGUMENTS (BETA)
      //  CC               AND FUNDAMENTAL ARGUMENTS FOR NUTATION (FNUT)
      double BETA[6]={0.0};
      double FNUT[5] ={0.0};
      ReferenceFrames::doodsonArguments(utc.asUT1(), utc.asTT(), BETA,FNUT);

      for(int i=0;i<tideData.NTACT;i++)
      {
         int N= tideData.NM[i][0];
         int M= tideData.NM[i][1];

         if(tideData.NM[i][0]>maxN) continue;

         double delta = M ? 0 : 1;

         double FNM = 4.0*ASConstant::PI*G*RHOW/GE* std::sqrt(FAC[N+M]/FAC[N-M]/(2.0*N+1.0)/(2.0-delta))
            *(1.0+tideData.KNMP[N-1])/(2.0*N+1)/100.0;

         double ARG =0;
         for(int j=0;j<6;j++)
         {
            ARG +=tideData.NDOD[i][j]*BETA[j];
         }

         double CARG = std::cos(ARG);
         double SARG = std::sin(ARG);

         int index=N*(N+1)/2-3+M;

         dC[index]=dC[index]
         +FNM*(
            (tideData.CSPM[i][0]+tideData.CSPM[i][2])*CARG
            +(tideData.CSPM[i][1]+tideData.CSPM[i][3])*SARG);

         dS[index]=dS[index]
         +FNM*(
            (tideData.CSPM[i][1]-tideData.CSPM[i][3])*CARG
            -(tideData.CSPM[i][0]-tideData.CSPM[i][2])*SARG);
      }
      
   }	// End of method 'EarthOceanTide::getOceanTide()'
Example #4
0
      /* Abstract class requires the subclass to compute the atmospheric density.
       * @param utc epoch in UTC
       * @param rb  EarthRef object.
       * @param r   Position vector.
       * @param v   Velocity vector
       * @return Atmospheric density in kg/m^3
       */
   double HarrisPriesterDrag::computeDensity( UTCTime utc, 
                                              EarthBody& rb, 
                                              Vector<double> r, 
                                              Vector<double> v)
   {
      double density = 0.0;
      
      // Get the J2000 to TOD transformation
      Matrix<double> N = ReferenceFrames::J2kToTODMatrix(utc);

      // Debuging
      /*
      double nn[3][3]={ {0.9999994803, -0.0009350126, -0.0004063480},
      {0.0009349995, 0.9999995624, -0.0000322758},
      {0.0004063780, 0.0000318958, 0.9999999169}};
      
      N = &nn[0][0];

      
      cout<<fixed<<setprecision(6);
      //cout<<workingDens<<endl;
      */

      // Transform r from J2000 to TOD
      Vector<double> r_tod = N * r;

      //* Satellite true altitude
      Position pos(r_tod(0), r_tod(1), r_tod(2), Position::Cartesian);
      double alt = pos.getAltitude()/1000.0;      // km
      
      if ( alt >= upper_limit || alt <= lower_limit ) 
      { 
         //return 0.0;

         string msg = "HarrisPriesterDrag is good for 100.0 km t0 2000.0 km"
            + string("the altitude you try is ")
            + StringUtils::asString(alt) + " km!";
         
         Exception e(msg);
         
         //GPSTK_THROW(e);
      }

      Vector<double> r_Sun = ReferenceFrames::getJ2kPosition( utc.asTDB(),
                                                              SolarSystem::Sun);

      // get coefficients for this F107
      //updateF107(std::pow(149597870.0/norm(r_Sun),2)*dailyF107);
      updateF107(averageF107);

      // Debuging
      /*
      alt = 360.01323431364915;
      cout<<r_Sun<<endl;
      double rr[3] = {4.87202078904524E7,	1.318213179104784E8,	5.71498291483194E7};
      r_Sun = &rr[0];
      */

      double ra_Sun  = std::atan2( r_Sun(1), r_Sun(0));
      double dec_Sun = std::atan2( r_Sun(2), 
                                   std::sqrt( 
                                     std::pow(r_Sun(0),2) + std::pow(r_Sun(1),2)
                                     ) );

        //* Unit vector u towards the apex of the diurnal bulge
        //* in inertial geocentric coordinates
      double c_dec = std::cos(dec_Sun);
      

      Vector<double> u(3,0.0);      // Apex of diurnal bulge
      u(0) = c_dec * std::cos(ra_Sun + ra_lag);
      u(1) = c_dec * std::sin(ra_Sun + ra_lag);
      u(2) = std::sin(dec_Sun);

      //* Cosine of half angle between satellite position vector and
      //* apex of diurnal bulge
      double c_psi2 = (0.5 + 0.5 * dot(r,u)/norm(r));
      
      int ih = 0;

      // index search
      for(int i = 0; i < 59-1; i++)
      {
         if(alt >= workingDens[i][0] && alt < workingDens[i+1][0])
         {
            ih = i;
            break;
         }
      }
      
      // exponential density interpolation
      double h_min = (workingDens[ih][0] - workingDens[ih+1][0]) 
                   / std::log(workingDens[ih+1][1] / workingDens[ih][1]);

      double h_max = (workingDens[ih][0] - workingDens[ih+1][0]) 
                   / std::log(workingDens[ih+1][2] 
                   / workingDens[ih][2]);
      
      double d_min = workingDens[ih][1]*std::exp((workingDens[ih][0]-alt)/h_min);
      double d_max = workingDens[ih][2]*std::exp((workingDens[ih][0]-alt)/h_max);
      
      // Density computation
      //Use 2 for low inclination orbits and 6 for polar orbits
      // Reference Montenbruck P90
      double n_prm = 2.0;
      Vector<double> h = cross(r,v);
      double inc = std::acos(h(2) / norm(h));
      n_prm = 2.0 + inc * 8.0 / ASConstant::PI;


      density = d_min + (d_max - d_min) * std::pow(c_psi2,n_prm / 2.0);

      return density * 1.0e-9;   //[kg/m^3]

   }  // End of method 'HarrisPriesterDrag::computeDensity()'