예제 #1
0
 /**
  * Simple constructor.
  *
  * <p>The {@code applyBefore} parameter is mainly used when the differential effect is associated
  * with a maneuver. In this case, the parameter must be set to {@code false}.
  *
  * @param orbit0 original orbit at reference date
  * @param orbit1 shifted orbit at reference date
  * @param applyBefore if true, effect is applied both before and after reference date, if false it
  *     is only applied after reference date
  * @param gravityField gravity field to use
  * @exception OrekitException if gravity field does not contain J2 coefficient
  */
 public J2DifferentialEffect(
     final Orbit orbit0,
     final Orbit orbit1,
     final boolean applyBefore,
     final UnnormalizedSphericalHarmonicsProvider gravityField)
     throws OrekitException {
   this(
       orbit0,
       orbit1,
       applyBefore,
       gravityField.getAe(),
       gravityField.getMu(),
       -gravityField.onDate(orbit0.getDate()).getUnnormalizedCnm(2, 0));
 }
예제 #2
0
 /**
  * Simple constructor.
  *
  * <p>The {@code applyBefore} parameter is mainly used when the differential effect is associated
  * with a maneuver. In this case, the parameter must be set to {@code false}.
  *
  * @param original original state at reference date
  * @param directEffect direct effect changing the orbit
  * @param applyBefore if true, effect is applied both before and after reference date, if false it
  *     is only applied after reference date
  * @param gravityField gravity field to use
  * @exception OrekitException if gravity field does not contain J2 coefficient
  */
 public J2DifferentialEffect(
     final SpacecraftState original,
     final AdapterPropagator.DifferentialEffect directEffect,
     final boolean applyBefore,
     final UnnormalizedSphericalHarmonicsProvider gravityField)
     throws OrekitException {
   this(
       original,
       directEffect,
       applyBefore,
       gravityField.getAe(),
       gravityField.getMu(),
       -gravityField.onDate(original.getDate()).getUnnormalizedCnm(2, 0));
 }
예제 #3
0
  /**
   * Single constructor.
   *
   * @param centralBodyFrame rotating body frame
   * @param centralBodyRotationRate central body rotation rate (rad/s)
   * @param provider provider for spherical harmonics
   * @param mDailiesOnly if true only M-dailies tesseral harmonics are taken into account for short
   *     periodics
   */
  TesseralContribution(
      final Frame centralBodyFrame,
      final double centralBodyRotationRate,
      final UnnormalizedSphericalHarmonicsProvider provider,
      final boolean mDailiesOnly) {

    // Central body rotating frame
    this.bodyFrame = centralBodyFrame;

    // Save the rotation rate
    this.centralBodyRotationRate = centralBodyRotationRate;

    // Central body rotation period in seconds
    this.bodyPeriod = MathUtils.TWO_PI / centralBodyRotationRate;

    // Provider for spherical harmonics
    this.provider = provider;
    this.maxDegree = provider.getMaxDegree();
    this.maxOrder = provider.getMaxOrder();

    // set the maximum degree order for short periodics
    this.maxDegreeTesseralSP = FastMath.min(maxDegree, MAX_DEGREE_TESSERAL_SP);
    this.maxDegreeMdailyTesseralSP = FastMath.min(maxDegree, MAX_DEGREE_MDAILY_TESSERAL_SP);
    this.maxOrderTesseralSP = FastMath.min(maxOrder, MAX_ORDER_TESSERAL_SP);
    this.maxOrderMdailyTesseralSP = FastMath.min(maxOrder, MAX_ORDER_MDAILY_TESSERAL_SP);

    // set the maximum value for eccentricity power
    this.maxEccPowTesseralSP = MAX_ECCPOWER_SP;
    this.maxEccPowMdailyTesseralSP = FastMath.min(maxDegreeMdailyTesseralSP - 2, MAX_ECCPOWER_SP);
    this.jMax = FastMath.min(MAXJ, maxDegreeTesseralSP + maxEccPowTesseralSP);

    // m-daylies only
    this.mDailiesOnly = mDailiesOnly;

    // Initialize default values
    this.resOrders = new ArrayList<Integer>();
    this.nonResOrders = new TreeMap<Integer, List<Integer>>();
    this.maxEccPow = 0;
    this.maxHansen = 0;

    // Factorials computation
    final int maxFact = 2 * maxDegree + 1;
    this.fact = new double[maxFact];
    fact[0] = 1;
    for (int i = 1; i < maxFact; i++) {
      fact[i] = i * fact[i - 1];
    }
  }
예제 #4
0
  /**
   * Compute the n-SUM for potential derivatives components.
   *
   * @param date current date
   * @param j resonant index <i>j</i>
   * @param m resonant order <i>m</i>
   * @param s d'Alembert characteristic <i>s</i>
   * @param maxN maximum possible value for <i>n</i> index
   * @param roaPow powers of R/a up to degree <i>n</i>
   * @param ghMSJ G<sup>j</sup><sub>m,s</sub> and H<sup>j</sup><sub>m,s</sub> polynomials
   * @param gammaMNS &Gamma;<sup>m</sup><sub>n,s</sub>(γ) function
   * @return Components of U<sub>n</sub> derivatives for fixed j, m, s
   * @throws OrekitException if some error occurred
   */
  private double[][] computeNSum(
      final AbsoluteDate date,
      final int j,
      final int m,
      final int s,
      final int maxN,
      final double[] roaPow,
      final GHmsjPolynomials ghMSJ,
      final GammaMnsFunction gammaMNS)
      throws OrekitException {

    // spherical harmonics
    final UnnormalizedSphericalHarmonics harmonics = provider.onDate(date);

    // Potential derivatives components
    double dUdaCos = 0.;
    double dUdaSin = 0.;
    double dUdhCos = 0.;
    double dUdhSin = 0.;
    double dUdkCos = 0.;
    double dUdkSin = 0.;
    double dUdlCos = 0.;
    double dUdlSin = 0.;
    double dUdAlCos = 0.;
    double dUdAlSin = 0.;
    double dUdBeCos = 0.;
    double dUdBeSin = 0.;
    double dUdGaCos = 0.;
    double dUdGaSin = 0.;

    // I^m
    final int Im = I > 0 ? 1 : (m % 2 == 0 ? 1 : -1);

    // jacobi v, w, indices from 2.7.1-(15)
    final int v = FastMath.abs(m - s);
    final int w = FastMath.abs(m + s);

    // Initialise lower degree nmin = (Max(2, m, |s|)) for summation over n
    final int nmin = FastMath.max(FastMath.max(2, m), FastMath.abs(s));

    // Get the corresponding Hansen object
    final int sIndex = maxDegree + (j < 0 ? -s : s);
    final int jIndex = FastMath.abs(j);
    final HansenTesseralLinear hans = this.hansenObjects[sIndex][jIndex];

    // n-SUM from nmin to N
    for (int n = nmin; n <= maxN; n++) {
      // If (n - s) is odd, the contribution is null because of Vmns
      if ((n - s) % 2 == 0) {

        // Vmns coefficient
        final double fns = fact[n + FastMath.abs(s)];
        final double vMNS = CoefficientsFactory.getVmns(m, n, s, fns, fact[n - m]);

        // Inclination function Gamma and derivative
        final double gaMNS = gammaMNS.getValue(m, n, s);
        final double dGaMNS = gammaMNS.getDerivative(m, n, s);

        // Hansen kernel value and derivative
        final double kJNS = hans.getValue(-n - 1, chi);
        final double dkJNS = hans.getDerivative(-n - 1, chi);

        // Gjms, Hjms polynomials and derivatives
        final double gMSJ = ghMSJ.getGmsj(m, s, j);
        final double hMSJ = ghMSJ.getHmsj(m, s, j);
        final double dGdh = ghMSJ.getdGmsdh(m, s, j);
        final double dGdk = ghMSJ.getdGmsdk(m, s, j);
        final double dGdA = ghMSJ.getdGmsdAlpha(m, s, j);
        final double dGdB = ghMSJ.getdGmsdBeta(m, s, j);
        final double dHdh = ghMSJ.getdHmsdh(m, s, j);
        final double dHdk = ghMSJ.getdHmsdk(m, s, j);
        final double dHdA = ghMSJ.getdHmsdAlpha(m, s, j);
        final double dHdB = ghMSJ.getdHmsdBeta(m, s, j);

        // Jacobi l-index from 2.7.1-(15)
        final int l = FastMath.min(n - m, n - FastMath.abs(s));
        // Jacobi polynomial and derivative
        final DerivativeStructure jacobi =
            JacobiPolynomials.getValue(l, v, w, new DerivativeStructure(1, 1, 0, gamma));

        // Geopotential coefficients
        final double cnm = harmonics.getUnnormalizedCnm(n, m);
        final double snm = harmonics.getUnnormalizedSnm(n, m);

        // Common factors from expansion of equations 3.3-4
        final double cf_0 = roaPow[n] * Im * vMNS;
        final double cf_1 = cf_0 * gaMNS * jacobi.getValue();
        final double cf_2 = cf_1 * kJNS;
        final double gcPhs = gMSJ * cnm + hMSJ * snm;
        final double gsMhc = gMSJ * snm - hMSJ * cnm;
        final double dKgcPhsx2 = 2. * dkJNS * gcPhs;
        final double dKgsMhcx2 = 2. * dkJNS * gsMhc;
        final double dUdaCoef = (n + 1) * cf_2;
        final double dUdlCoef = j * cf_2;
        final double dUdGaCoef =
            cf_0 * kJNS * (jacobi.getValue() * dGaMNS + gaMNS * jacobi.getPartialDerivative(1));

        // dU / da components
        dUdaCos += dUdaCoef * gcPhs;
        dUdaSin += dUdaCoef * gsMhc;

        // dU / dh components
        dUdhCos += cf_1 * (kJNS * (cnm * dGdh + snm * dHdh) + h * dKgcPhsx2);
        dUdhSin += cf_1 * (kJNS * (snm * dGdh - cnm * dHdh) + h * dKgsMhcx2);

        // dU / dk components
        dUdkCos += cf_1 * (kJNS * (cnm * dGdk + snm * dHdk) + k * dKgcPhsx2);
        dUdkSin += cf_1 * (kJNS * (snm * dGdk - cnm * dHdk) + k * dKgsMhcx2);

        // dU / dLambda components
        dUdlCos += dUdlCoef * gsMhc;
        dUdlSin += -dUdlCoef * gcPhs;

        // dU / alpha components
        dUdAlCos += cf_2 * (dGdA * cnm + dHdA * snm);
        dUdAlSin += cf_2 * (dGdA * snm - dHdA * cnm);

        // dU / dBeta components
        dUdBeCos += cf_2 * (dGdB * cnm + dHdB * snm);
        dUdBeSin += cf_2 * (dGdB * snm - dHdB * cnm);

        // dU / dGamma components
        dUdGaCos += dUdGaCoef * gcPhs;
        dUdGaSin += dUdGaCoef * gsMhc;
      }
    }

    return new double[][] {
      {dUdaCos, dUdaSin},
      {dUdhCos, dUdhSin},
      {dUdkCos, dUdkSin},
      {dUdlCos, dUdlSin},
      {dUdAlCos, dUdAlSin},
      {dUdBeCos, dUdBeSin},
      {dUdGaCos, dUdGaSin}
    };
  }
예제 #5
0
  /** {@inheritDoc} */
  @Override
  public double[] getShortPeriodicVariations(final AbsoluteDate date, final double[] meanElements)
      throws OrekitException {

    // Initialise the short periodic variations
    final double[] shortPeriodicVariation = new double[] {0., 0., 0., 0., 0., 0.};

    // Compute only if there is at least one non-resonant tesseral or
    // only the m-daily tesseral should be taken into account
    if (!nonResOrders.isEmpty() || mDailiesOnly) {

      // Build an Orbit object from the mean elements
      final Orbit meanOrbit =
          OrbitType.EQUINOCTIAL.mapArrayToOrbit(
              meanElements, PositionAngle.MEAN, date, provider.getMu(), this.frame);

      // Build an auxiliary object
      final AuxiliaryElements aux = new AuxiliaryElements(meanOrbit, I);

      // Central body rotation angle from equation 2.7.1-(3)(4).
      final Transform t = bodyFrame.getTransformTo(aux.getFrame(), aux.getDate());
      final Vector3D xB = t.transformVector(Vector3D.PLUS_I);
      final Vector3D yB = t.transformVector(Vector3D.PLUS_J);
      final double currentTheta =
          FastMath.atan2(
              -f.dotProduct(yB) + I * g.dotProduct(xB), f.dotProduct(xB) + I * g.dotProduct(yB));

      // Add the m-daily contribution
      for (int m = 1; m <= maxOrderMdailyTesseralSP; m++) {
        // Phase angle
        final double jlMmt = -m * currentTheta;
        final double sinPhi = FastMath.sin(jlMmt);
        final double cosPhi = FastMath.cos(jlMmt);

        // compute contribution for each element
        for (int i = 0; i < 6; i++) {
          shortPeriodicVariation[i] +=
              tesseralSPCoefs.getCijm(i, 0, m, date) * cosPhi
                  + tesseralSPCoefs.getSijm(i, 0, m, date) * sinPhi;
        }
      }

      // loop through all non-resonant (j,m) pairs
      for (final Map.Entry<Integer, List<Integer>> entry : nonResOrders.entrySet()) {
        final int m = entry.getKey();
        final List<Integer> listJ = entry.getValue();

        for (int j : listJ) {
          // Phase angle
          final double jlMmt = j * meanElements[5] - m * currentTheta;
          final double sinPhi = FastMath.sin(jlMmt);
          final double cosPhi = FastMath.cos(jlMmt);

          // compute contribution for each element
          for (int i = 0; i < 6; i++) {
            shortPeriodicVariation[i] +=
                tesseralSPCoefs.getCijm(i, j, m, date) * cosPhi
                    + tesseralSPCoefs.getSijm(i, j, m, date) * sinPhi;
          }
        }
      }
    }

    return shortPeriodicVariation;
  }
예제 #6
0
  /** {@inheritDoc} */
  @Override
  public void initializeStep(final AuxiliaryElements aux) throws OrekitException {

    // Equinoctial elements
    a = aux.getSma();
    k = aux.getK();
    h = aux.getH();
    q = aux.getQ();
    p = aux.getP();
    lm = aux.getLM();

    // Eccentricity
    ecc = aux.getEcc();
    e2 = ecc * ecc;

    // Retrograde factor
    I = aux.getRetrogradeFactor();

    // Equinoctial frame vectors
    f = aux.getVectorF();
    g = aux.getVectorG();

    // Central body rotation angle from equation 2.7.1-(3)(4).
    final Transform t = bodyFrame.getTransformTo(aux.getFrame(), aux.getDate());
    final Vector3D xB = t.transformVector(Vector3D.PLUS_I);
    final Vector3D yB = t.transformVector(Vector3D.PLUS_J);
    theta =
        FastMath.atan2(
            -f.dotProduct(yB) + I * g.dotProduct(xB), f.dotProduct(xB) + I * g.dotProduct(yB));

    // Direction cosines
    alpha = aux.getAlpha();
    beta = aux.getBeta();
    gamma = aux.getGamma();

    // Equinoctial coefficients
    // A = sqrt(μ * a)
    final double A = aux.getA();
    // B = sqrt(1 - h² - k²)
    final double B = aux.getB();
    // C = 1 + p² + q²
    final double C = aux.getC();
    // Common factors from equinoctial coefficients
    // 2 * a / A
    ax2oA = 2. * a / A;
    // B / A
    BoA = B / A;
    // 1 / AB
    ooAB = 1. / (A * B);
    // C / 2AB
    Co2AB = C * ooAB / 2.;
    // B / (A * (1 + B))
    BoABpo = BoA / (1. + B);
    // &mu / a
    moa = provider.getMu() / a;
    // R / a
    roa = provider.getAe() / a;

    // &Chi; = 1 / B
    chi = 1. / B;
    chi2 = chi * chi;

    // mean motion n
    meanMotion = aux.getMeanMotion();
  }