DSSTTheory.java

  1. /* Copyright 2002-2025 CS GROUP
  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.propagation.conversion.osc2mean;

  18. import java.util.ArrayList;
  19. import java.util.Collection;
  20. import java.util.List;

  21. import org.hipparchus.CalculusFieldElement;
  22. import org.hipparchus.Field;
  23. import org.hipparchus.util.MathArrays;
  24. import org.orekit.attitudes.Attitude;
  25. import org.orekit.attitudes.AttitudeProvider;
  26. import org.orekit.attitudes.FieldAttitude;
  27. import org.orekit.attitudes.FrameAlignedProvider;
  28. import org.orekit.orbits.FieldOrbit;
  29. import org.orekit.orbits.Orbit;
  30. import org.orekit.orbits.OrbitType;
  31. import org.orekit.orbits.PositionAngleType;
  32. import org.orekit.propagation.FieldSpacecraftState;
  33. import org.orekit.propagation.PropagationType;
  34. import org.orekit.propagation.Propagator;
  35. import org.orekit.propagation.SpacecraftState;
  36. import org.orekit.propagation.semianalytical.dsst.forces.DSSTForceModel;
  37. import org.orekit.propagation.semianalytical.dsst.forces.FieldShortPeriodTerms;
  38. import org.orekit.propagation.semianalytical.dsst.forces.ShortPeriodTerms;
  39. import org.orekit.propagation.semianalytical.dsst.utilities.AuxiliaryElements;
  40. import org.orekit.propagation.semianalytical.dsst.utilities.FieldAuxiliaryElements;
  41. import org.orekit.time.FieldAbsoluteDate;
  42. import org.orekit.utils.Constants;

  43. /**
  44.  * DSST theory for osculating to mean orbit conversion.
  45.  *
  46.  * @author Pascal Parraud
  47.  * @since 13.0
  48.  */
  49. public class DSSTTheory implements MeanTheory {

  50.     /** Theory used for converting from osculating to mean orbit. */
  51.     public static final String THEORY = "DSST";

  52.     /** Force models used to compute short periodic terms. */
  53.     private final Collection<DSSTForceModel> forceModels;

  54.     /** Spacecraft mass (kg). */
  55.     private final double mass;

  56.     /** Attitude provider. */
  57.     private AttitudeProvider attitudeProvider;

  58.     /**
  59.      * Constructor with default values.
  60.      * @param forceModels the force models
  61.      */
  62.     public DSSTTheory(final Collection<DSSTForceModel> forceModels) {
  63.         this(forceModels, null, Propagator.DEFAULT_MASS);
  64.     }

  65.     /**
  66.      * Full constructor.
  67.      * @param forceModels the force models
  68.      * @param attitudeProvider the attitude law
  69.      * @param mass the mass (kg)
  70.      */
  71.     public DSSTTheory(final Collection<DSSTForceModel> forceModels,
  72.                       final AttitudeProvider attitudeProvider,
  73.                       final double mass) {
  74.         this.forceModels = forceModels;
  75.         this.attitudeProvider = attitudeProvider;
  76.         this.mass = mass;
  77.     }

  78.     /** {@inheritDoc} */
  79.     @Override
  80.     public String getTheoryName() {
  81.         return THEORY;
  82.     }

  83.     /** {@inheritDoc} */
  84.     @Override
  85.     public double getReferenceRadius() {
  86.         return Constants.IERS2010_EARTH_EQUATORIAL_RADIUS;
  87.     };

  88.     /** {@inheritDoc} */
  89.     @Override
  90.     public Orbit preprocessing(final Orbit osculating) {
  91.         // If not defined
  92.         if (attitudeProvider == null) {
  93.             // Creates a default attitude provider
  94.             attitudeProvider = FrameAlignedProvider.of(osculating.getFrame());
  95.         }
  96.         // ensure all Gaussian force models can rely on attitude
  97.         for (final DSSTForceModel force : forceModels) {
  98.             force.registerAttitudeProvider(attitudeProvider);
  99.         }
  100.         // Returns an equinoctial orbit
  101.         return OrbitType.EQUINOCTIAL.convertType(osculating);
  102.     }

  103.     /** {@inheritDoc} */
  104.     @Override
  105.     public Orbit meanToOsculating(final Orbit mean) {

  106.         // Create the spacecraft state
  107.         final Attitude attitude = attitudeProvider.getAttitude(mean, mean.getDate(), mean.getFrame());
  108.         final SpacecraftState meanState = new SpacecraftState(mean, attitude).withMass(mass);

  109.         // Create the auxiliary object
  110.         final AuxiliaryElements aux = new AuxiliaryElements(mean, +1);

  111.         // Set the force models
  112.         final List<ShortPeriodTerms> shortPeriodTerms = new ArrayList<>();
  113.         for (final DSSTForceModel force : forceModels) {
  114.             shortPeriodTerms.addAll(force.initializeShortPeriodTerms(aux, PropagationType.OSCULATING,
  115.                                                                      force.getParameters(mean.getDate())));
  116.             force.updateShortPeriodTerms(force.getParametersAllValues(), meanState);
  117.         }

  118.         // recompute the osculating parameters from the current mean parameters
  119.         return computeOsculatingOrbit(mean, shortPeriodTerms);
  120.     }

  121.     /** Compute osculating orbit from mean orbit.
  122.      * <p>
  123.      * Compute and add the short periodic variation to the mean orbit.
  124.      * </p>
  125.      * @param meanOrbit initial mean orbit
  126.      * @param shortPeriodTerms short period terms
  127.      * @return osculating orbit
  128.      */
  129.     private Orbit computeOsculatingOrbit(final Orbit meanOrbit,
  130.                                          final List<ShortPeriodTerms> shortPeriodTerms) {

  131.         final double[] mean = new double[6];
  132.         final double[] meanDot = new double[6];
  133.         OrbitType.EQUINOCTIAL.mapOrbitToArray(meanOrbit, PositionAngleType.MEAN, mean, meanDot);
  134.         final double[] y = mean.clone();
  135.         for (final ShortPeriodTerms spt : shortPeriodTerms) {
  136.             final double[] shortPeriodic = spt.value(meanOrbit);
  137.             for (int i = 0; i < shortPeriodic.length; i++) {
  138.                 y[i] += shortPeriodic[i];
  139.             }
  140.         }
  141.         return OrbitType.EQUINOCTIAL.mapArrayToOrbit(y, meanDot, PositionAngleType.MEAN,
  142.                                                      meanOrbit.getDate(), meanOrbit.getMu(),
  143.                                                      meanOrbit.getFrame());
  144.     }

  145.     /** {@inheritDoc} */
  146.     @Override
  147.     public <T extends CalculusFieldElement<T>> FieldOrbit<T> preprocessing(final FieldOrbit<T> osculating) {
  148.         // If not defined
  149.         if (attitudeProvider == null) {
  150.             // Creates a default attitude provider
  151.             attitudeProvider = FrameAlignedProvider.of(osculating.getFrame());
  152.         }
  153.         // ensure all Gaussian force models can rely on attitude
  154.         for (final DSSTForceModel force : forceModels) {
  155.             force.registerAttitudeProvider(attitudeProvider);
  156.         }
  157.         // Returns an equinoctial orbit
  158.         return OrbitType.EQUINOCTIAL.convertType(osculating);
  159.     }

  160.     /** {@inheritDoc} */
  161.     @Override
  162.     @SuppressWarnings("unchecked")
  163.     public <T extends CalculusFieldElement<T>> FieldOrbit<T> meanToOsculating(final FieldOrbit<T> mean) {

  164.         final FieldAbsoluteDate<T> date = mean.getDate();
  165.         final Field<T> field = date.getField();

  166.         // Create the spacecraft state
  167.         final T fieldMass = field.getZero().newInstance(mass);
  168.         final FieldAttitude<T> attitude = attitudeProvider.getAttitude(mean, mean.getDate(), mean.getFrame());
  169.         final FieldSpacecraftState<T> meanState = new FieldSpacecraftState<>(mean, attitude).withMass(fieldMass);

  170.         //Create the auxiliary object
  171.         final FieldAuxiliaryElements<T> aux = new FieldAuxiliaryElements<>(mean, +1);

  172.         // Set the force models
  173.         final List<FieldShortPeriodTerms<T>> shortPeriodTerms = new ArrayList<>();
  174.         for (final DSSTForceModel force : forceModels) {
  175.             shortPeriodTerms.addAll(force.initializeShortPeriodTerms(aux, PropagationType.OSCULATING,
  176.                                                                      force.getParameters(field, date)));
  177.             force.updateShortPeriodTerms(force.getParametersAllValues(field), meanState);
  178.         }

  179.         // recompute the osculating parameters from the current mean parameters
  180.         return computeOsculatingOrbit(mean, shortPeriodTerms);
  181.     }

  182.     /** Compute osculating orbit from mean orbit.
  183.      * <p>
  184.      * Compute and add the short periodic variation to the mean {@link SpacecraftState}.
  185.      * </p>
  186.      * @param meanOrbit initial mean orbit
  187.      * @param shortPeriodTerms short period terms
  188.      * @param <T> type of the elements
  189.      * @return osculating orbit
  190.      */
  191.     private <T extends CalculusFieldElement<T>> FieldOrbit<T> computeOsculatingOrbit(final FieldOrbit<T> meanOrbit,
  192.                                                                                      final List<FieldShortPeriodTerms<T>> shortPeriodTerms) {

  193.         final T[] mean = MathArrays.buildArray(meanOrbit.getDate().getField(), 6);
  194.         final T[] meanDot = MathArrays.buildArray(meanOrbit.getDate().getField(), 6);
  195.         OrbitType.EQUINOCTIAL.mapOrbitToArray(meanOrbit, PositionAngleType.MEAN, mean, meanDot);
  196.         final T[] y = mean.clone();
  197.         for (final FieldShortPeriodTerms<T> spt : shortPeriodTerms) {
  198.             final T[] shortPeriodic = spt.value(meanOrbit);
  199.             for (int i = 0; i < shortPeriodic.length; i++) {
  200.                 y[i] = y[i].add(shortPeriodic[i]);
  201.             }
  202.         }
  203.         return OrbitType.EQUINOCTIAL.mapArrayToOrbit(y, meanDot,
  204.                                                      PositionAngleType.MEAN,
  205.                                                      meanOrbit.getDate(),
  206.                                                      meanOrbit.getMu(),
  207.                                                      meanOrbit.getFrame());
  208.     }
  209. }