CircularLatitudeArgumentUtility.java

  1. /* Copyright 2022-2024 Romain Serra
  2.  * Licensed to CS GROUP (CS) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * CS licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *   http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package org.orekit.orbits;

  18. import org.hipparchus.util.FastMath;
  19. import org.hipparchus.util.SinCos;
  20. import org.orekit.errors.OrekitException;
  21. import org.orekit.errors.OrekitMessages;

  22. /**
  23.  * Utility methods for converting between different latitude arguments used by {@link org.orekit.orbits.CircularOrbit}.
  24.  * @author Romain Serra
  25.  * @see org.orekit.orbits.CircularOrbit
  26.  * @since 12.1
  27.  */
  28. public class CircularLatitudeArgumentUtility {

  29.     /** Tolerance for stopping criterion in iterative conversion from mean to eccentric angle. */
  30.     private static final double TOLERANCE_CONVERGENCE = 1.0e-12;

  31.     /** Maximum number of iterations in iterative conversion from mean to eccentric angle. */
  32.     private static final int MAXIMUM_ITERATION = 50;

  33.     /** Private constructor for utility class. */
  34.     private CircularLatitudeArgumentUtility() {
  35.         // nothing here (utils class)
  36.     }

  37.     /**
  38.      * Computes the true latitude argument from the eccentric latitude argument.
  39.      *
  40.      * @param ex     e cos(ω), first component of circular eccentricity vector
  41.      * @param ey     e sin(ω), second component of circular eccentricity vector
  42.      * @param alphaE = E + ω eccentric latitude argument (rad)
  43.      * @return the true latitude argument.
  44.      */
  45.     public static double eccentricToTrue(final double ex, final double ey, final double alphaE) {
  46.         final double epsilon   = eccentricAndTrueEpsilon(ex, ey);
  47.         final SinCos scAlphaE  = FastMath.sinCos(alphaE);
  48.         final double num       = ex * scAlphaE.sin() - ey * scAlphaE.cos();
  49.         final double den       = epsilon + 1 - ex * scAlphaE.cos() - ey * scAlphaE.sin();
  50.         return alphaE + eccentricAndTrueAtan(num, den);
  51.     }

  52.     /**
  53.      * Computes the eccentric latitude argument from the true latitude argument.
  54.      *
  55.      * @param ex     e cos(ω), first component of circular eccentricity vector
  56.      * @param ey     e sin(ω), second component of circular eccentricity vector
  57.      * @param alphaV = V + ω true latitude argument (rad)
  58.      * @return the eccentric latitude argument.
  59.      */
  60.     public static double trueToEccentric(final double ex, final double ey, final double alphaV) {
  61.         final double epsilon   = eccentricAndTrueEpsilon(ex, ey);
  62.         final SinCos scAlphaV  = FastMath.sinCos(alphaV);
  63.         final double num       = ey * scAlphaV.cos() - ex * scAlphaV.sin();
  64.         final double den       = epsilon + 1 + ex * scAlphaV.cos() + ey * scAlphaV.sin();
  65.         return alphaV + eccentricAndTrueAtan(num, den);
  66.     }

  67.     /**
  68.      * Computes an intermediate quantity for conversions between true and eccentric.
  69.      *
  70.      * @param ex e cos(ω), first component of circular eccentricity vector
  71.      * @param ey e sin(ω), second component of circular eccentricity vector
  72.      * @return intermediate variable referred to as epsilon.
  73.      */
  74.     private static double eccentricAndTrueEpsilon(final double ex, final double ey) {
  75.         return FastMath.sqrt(1 - ex * ex - ey * ey);
  76.     }

  77.     /**
  78.      * Computes another intermediate quantity for conversions between true and eccentric.
  79.      *
  80.      * @param num numerator for angular conversion
  81.      * @param den denominator for angular conversion
  82.      * @return arc-tangent of ratio of inputs times two.
  83.      */
  84.     private static double eccentricAndTrueAtan(final double num, final double den) {
  85.         return 2. * FastMath.atan(num / den);
  86.     }

  87.     /**
  88.      * Computes the eccentric latitude argument from the mean latitude argument.
  89.      *
  90.      * @param ex     e cos(ω), first component of circular eccentricity vector
  91.      * @param ey     e sin(ω), second component of circular eccentricity vector
  92.      * @param alphaM = M + ω  mean latitude argument (rad)
  93.      * @return the eccentric latitude argument.
  94.      */
  95.     public static double meanToEccentric(final double ex, final double ey, final double alphaM) {
  96.         // Generalization of Kepler equation to circular parameters
  97.         // with alphaE = PA + E and
  98.         //      alphaM = PA + M = alphaE - ex.sin(alphaE) + ey.cos(alphaE)
  99.         double alphaE         = alphaM;
  100.         double shift;
  101.         double alphaEMalphaM  = 0.0;
  102.         boolean hasConverged;
  103.         int    iter           = 0;
  104.         do {
  105.             final SinCos scAlphaE = FastMath.sinCos(alphaE);
  106.             final double f2 = ex * scAlphaE.sin() - ey * scAlphaE.cos();
  107.             final double f1 = 1.0 - ex * scAlphaE.cos() - ey * scAlphaE.sin();
  108.             final double f0 = alphaEMalphaM - f2;

  109.             final double f12 = 2.0 * f1;
  110.             shift = f0 * f12 / (f1 * f12 - f0 * f2);

  111.             alphaEMalphaM -= shift;
  112.             alphaE         = alphaM + alphaEMalphaM;

  113.             hasConverged = FastMath.abs(shift) <= TOLERANCE_CONVERGENCE;
  114.         } while (++iter < MAXIMUM_ITERATION && !hasConverged);

  115.         if (!hasConverged) {
  116.             throw new OrekitException(OrekitMessages.UNABLE_TO_COMPUTE_ECCENTRIC_LATITUDE_ARGUMENT, iter);
  117.         }
  118.         return alphaE;

  119.     }

  120.     /**
  121.      * Computes the mean latitude argument from the eccentric latitude argument.
  122.      *
  123.      * @param ex     e cos(ω), first component of circular eccentricity vector
  124.      * @param ey     e sin(ω), second component of circular eccentricity vector
  125.      * @param alphaE = E + ω  mean latitude argument (rad)
  126.      * @return the mean latitude argument.
  127.      */
  128.     public static double eccentricToMean(final double ex, final double ey, final double alphaE) {
  129.         final SinCos scAlphaE = FastMath.sinCos(alphaE);
  130.         return alphaE + (ey * scAlphaE.cos() - ex * scAlphaE.sin());
  131.     }

  132.     /**
  133.      * Computes the mean latitude argument from the eccentric latitude argument.
  134.      *
  135.      * @param ex     e cos(ω), first component of circular eccentricity vector
  136.      * @param ey     e sin(ω), second component of circular eccentricity vector
  137.      * @param alphaV = V + ω  true latitude argument (rad)
  138.      * @return the mean latitude argument.
  139.      */
  140.     public static double trueToMean(final double ex, final double ey, final double alphaV) {
  141.         final double alphaE = trueToEccentric(ex, ey, alphaV);
  142.         return eccentricToMean(ex, ey, alphaE);
  143.     }

  144.     /**
  145.      * Computes the true latitude argument from the eccentric latitude argument.
  146.      *
  147.      * @param ex     e cos(ω), first component of circular eccentricity vector
  148.      * @param ey     e sin(ω), second component of circular eccentricity vector
  149.      * @param alphaM = M + ω  mean latitude argument (rad)
  150.      * @return the true latitude argument.
  151.      */
  152.     public static double meanToTrue(final double ex, final double ey, final double alphaM) {
  153.         final double alphaE = meanToEccentric(ex, ey, alphaM);
  154.         return eccentricToTrue(ex, ey, alphaE);
  155.     }

  156. }