FieldCircularLatitudeArgumentUtility.java
- /* Copyright 2022-2025 Romain Serra
- * Licensed to CS GROUP (CS) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * CS licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- package org.orekit.orbits;
- import org.hipparchus.CalculusFieldElement;
- import org.hipparchus.util.FastMath;
- import org.hipparchus.util.FieldSinCos;
- import org.orekit.errors.OrekitException;
- import org.orekit.errors.OrekitInternalError;
- import org.orekit.errors.OrekitMessages;
- /**
- * Utility methods for converting between different latitude arguments used by {@link FieldCircularOrbit}.
- * @author Romain Serra
- * @see FieldCircularOrbit
- * @since 12.1
- */
- public class FieldCircularLatitudeArgumentUtility {
- /** Tolerance for stopping criterion in iterative conversion from mean to eccentric angle. */
- private static final double TOLERANCE_CONVERGENCE = 1.0e-11;
- /** Maximum number of iterations in iterative conversion from mean to eccentric angle. */
- private static final int MAXIMUM_ITERATION = 50;
- /** Private constructor for utility class. */
- private FieldCircularLatitudeArgumentUtility() {
- // nothing here (utils class)
- }
- /**
- * Computes the true latitude argument from the eccentric latitude argument.
- *
- * @param <T> Type of the field elements
- * @param ex e cos(ω), first component of circular eccentricity vector
- * @param ey e sin(ω), second component of circular eccentricity vector
- * @param alphaE = E + ω eccentric latitude argument (rad)
- * @return the true latitude argument.
- */
- public static <T extends CalculusFieldElement<T>> T eccentricToTrue(final T ex, final T ey, final T alphaE) {
- final T epsilon = eccentricAndTrueEpsilon(ex, ey);
- final FieldSinCos<T> scAlphaE = FastMath.sinCos(alphaE);
- final T cosAlphaE = scAlphaE.cos();
- final T sinAlphaE = scAlphaE.sin();
- final T num = ex.multiply(sinAlphaE).subtract(ey.multiply(cosAlphaE));
- final T den = epsilon.add(1).subtract(ex.multiply(cosAlphaE)).subtract(ey.multiply(sinAlphaE));
- return alphaE.add(eccentricAndTrueAtan(num, den));
- }
- /**
- * Computes the eccentric latitude argument from the true latitude argument.
- *
- * @param <T> Type of the field elements
- * @param ex e cos(ω), first component of circular eccentricity vector
- * @param ey e sin(ω), second component of circular eccentricity vector
- * @param alphaV = v + ω true latitude argument (rad)
- * @return the eccentric latitude argument.
- */
- public static <T extends CalculusFieldElement<T>> T trueToEccentric(final T ex, final T ey, final T alphaV) {
- final T epsilon = eccentricAndTrueEpsilon(ex, ey);
- final FieldSinCos<T> scAlphaV = FastMath.sinCos(alphaV);
- final T cosAlphaV = scAlphaV.cos();
- final T sinAlphaV = scAlphaV.sin();
- final T num = ey.multiply(cosAlphaV).subtract(ex.multiply(sinAlphaV));
- final T den = epsilon.add(1).add(ex.multiply(cosAlphaV).add(ey.multiply(sinAlphaV)));
- return alphaV.add(eccentricAndTrueAtan(num, den));
- }
- /**
- * Computes an intermediate quantity for conversions between true and eccentric.
- *
- * @param <T> Type of the field elements
- * @param ex e cos(ω), first component of circular eccentricity vector
- * @param ey e sin(ω), second component of circular eccentricity vector
- * @return intermediate variable referred to as epsilon.
- */
- private static <T extends CalculusFieldElement<T>> T eccentricAndTrueEpsilon(final T ex, final T ey) {
- return (ex.square().negate().subtract(ey.square()).add(1.)).sqrt();
- }
- /**
- * Computes another intermediate quantity for conversions between true and eccentric.
- *
- * @param <T> Type of the field elements
- * @param num numerator for angular conversion
- * @param den denominator for angular conversion
- * @return arc-tangent of ratio of inputs times two.
- */
- private static <T extends CalculusFieldElement<T>> T eccentricAndTrueAtan(final T num, final T den) {
- return (num.divide(den)).atan().multiply(2);
- }
- /**
- * Computes the eccentric latitude argument from the mean latitude argument.
- *
- * @param <T> Type of the field elements
- * @param ex e cos(ω), first component of circular eccentricity vector
- * @param ey e sin(ω), second component of circular eccentricity vector
- * @param alphaM = M + ω mean latitude argument (rad)
- * @return the eccentric latitude argument.
- */
- public static <T extends CalculusFieldElement<T>> T meanToEccentric(final T ex, final T ey, final T alphaM) {
- // Generalization of Kepler equation to circular parameters
- // with alphaE = PA + E and
- // alphaM = PA + M = alphaE - ex.sin(alphaE) + ey.cos(alphaE)
- T alphaE = alphaM;
- T shift;
- T alphaEMalphaM = alphaM.getField().getZero();
- boolean hasConverged;
- int iter = 0;
- do {
- final FieldSinCos<T> scAlphaE = FastMath.sinCos(alphaE);
- final T f2 = ex.multiply(scAlphaE.sin()).subtract(ey.multiply(scAlphaE.cos()));
- final T f1 = ex.negate().multiply(scAlphaE.cos()).subtract(ey.multiply(scAlphaE.sin())).add(1);
- final T f0 = alphaEMalphaM.subtract(f2);
- final T f12 = f1.multiply(2);
- shift = f0.multiply(f12).divide(f1.multiply(f12).subtract(f0.multiply(f2)));
- alphaEMalphaM = alphaEMalphaM.subtract(shift);
- alphaE = alphaM.add(alphaEMalphaM);
- hasConverged = FastMath.abs(shift.getReal()) <= TOLERANCE_CONVERGENCE;
- } while (++iter < MAXIMUM_ITERATION && !hasConverged);
- if (!hasConverged) {
- throw new OrekitException(OrekitMessages.UNABLE_TO_COMPUTE_ECCENTRIC_LATITUDE_ARGUMENT, iter);
- }
- return alphaE;
- }
- /**
- * Computes the mean latitude argument from the eccentric latitude argument.
- *
- * @param <T> Type of the field elements
- * @param ex e cos(ω), first component of circular eccentricity vector
- * @param ey e sin(ω), second component of circular eccentricity vector
- * @param alphaE = E + ω eccentric latitude argument (rad)
- * @return the mean latitude argument.
- */
- public static <T extends CalculusFieldElement<T>> T eccentricToMean(final T ex, final T ey, final T alphaE) {
- final FieldSinCos<T> scAlphaE = FastMath.sinCos(alphaE);
- return alphaE.subtract(ex.multiply(scAlphaE.sin()).subtract(ey.multiply(scAlphaE.cos())));
- }
- /**
- * Computes the mean latitude argument from the eccentric latitude argument.
- *
- * @param <T> Type of the field elements
- * @param ex e cos(ω), first component of circular eccentricity vector
- * @param ey e sin(ω), second component of circular eccentricity vector
- * @param alphaV = V + ω true latitude argument (rad)
- * @return the mean latitude argument.
- */
- public static <T extends CalculusFieldElement<T>> T trueToMean(final T ex, final T ey, final T alphaV) {
- final T alphaE = trueToEccentric(ex, ey, alphaV);
- return eccentricToMean(ex, ey, alphaE);
- }
- /**
- * Computes the true latitude argument from the eccentric latitude argument.
- *
- * @param <T> Type of the field elements
- * @param ex e cos(ω), first component of circular eccentricity vector
- * @param ey e sin(ω), second component of circular eccentricity vector
- * @param alphaM = M + ω mean latitude argument (rad)
- * @return the true latitude argument.
- */
- public static <T extends CalculusFieldElement<T>> T meanToTrue(final T ex, final T ey, final T alphaM) {
- final T alphaE = meanToEccentric(ex, ey, alphaM);
- return eccentricToTrue(ex, ey, alphaE);
- }
- /**
- * Convert argument of latitude.
- * @param oldType old position angle type
- * @param alpha old value for argument of latitude
- * @param ex ex
- * @param ey ey
- * @param newType new position angle type
- * @param <T> field type
- * @return convert argument of latitude
- * @since 12.2
- */
- public static <T extends CalculusFieldElement<T>> T convertAlpha(final PositionAngleType oldType, final T alpha,
- final T ex, final T ey,
- final PositionAngleType newType) {
- if (oldType == newType) {
- return alpha;
- } else {
- switch (newType) {
- case ECCENTRIC:
- if (oldType == PositionAngleType.MEAN) {
- return FieldCircularLatitudeArgumentUtility.meanToEccentric(ex, ey, alpha);
- } else {
- return FieldCircularLatitudeArgumentUtility.trueToEccentric(ex, ey, alpha);
- }
- case MEAN:
- if (oldType == PositionAngleType.TRUE) {
- return FieldCircularLatitudeArgumentUtility.trueToMean(ex, ey, alpha);
- } else {
- return FieldCircularLatitudeArgumentUtility.eccentricToMean(ex, ey, alpha);
- }
- case TRUE:
- if (oldType == PositionAngleType.MEAN) {
- return FieldCircularLatitudeArgumentUtility.meanToTrue(ex, ey, alpha);
- } else {
- return FieldCircularLatitudeArgumentUtility.eccentricToTrue(ex, ey, alpha);
- }
- default:
- throw new OrekitInternalError(null);
- }
- }
- }
- }