FieldKeplerianPropagator.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.analytical;


  18. import java.util.Collections;
  19. import java.util.List;

  20. import org.hipparchus.CalculusFieldElement;
  21. import org.hipparchus.util.MathArrays;
  22. import org.orekit.attitudes.AttitudeProvider;
  23. import org.orekit.attitudes.FieldAttitude;
  24. import org.orekit.attitudes.FrameAlignedProvider;
  25. import org.orekit.orbits.FieldOrbit;
  26. import org.orekit.orbits.Orbit;
  27. import org.orekit.orbits.OrbitType;
  28. import org.orekit.orbits.PositionAngleType;
  29. import org.orekit.propagation.FieldSpacecraftState;
  30. import org.orekit.time.FieldAbsoluteDate;
  31. import org.orekit.utils.FieldArrayDictionary;
  32. import org.orekit.utils.FieldDataDictionary;
  33. import org.orekit.utils.FieldTimeSpanMap;
  34. import org.orekit.utils.ParameterDriver;

  35. /** Simple Keplerian orbit propagator.
  36.  * @see FieldOrbit
  37.  * @author Guylaine Prat
  38.  * @param <T> type of the field elements
  39.  */
  40. public class FieldKeplerianPropagator<T extends CalculusFieldElement<T>> extends FieldAbstractAnalyticalPropagator<T> {


  41.     /** All states. */
  42.     private transient FieldTimeSpanMap<FieldSpacecraftState<T>, T> states;

  43.     /** Build a propagator from orbit only.
  44.      * <p>The central attraction coefficient μ is set to the same value used
  45.      * for the initial orbit definition. Mass and attitude provider are set to
  46.      * unspecified non-null arbitrary values.</p>
  47.      *
  48.      * @param initialFieldOrbit initial orbit
  49.      * @see #FieldKeplerianPropagator(FieldOrbit, AttitudeProvider)
  50.      */
  51.     public FieldKeplerianPropagator(final FieldOrbit<T> initialFieldOrbit) {
  52.         this(initialFieldOrbit, FrameAlignedProvider.of(initialFieldOrbit.getFrame()),
  53.              initialFieldOrbit.getMu(), initialFieldOrbit.getA().getField().getZero().newInstance(DEFAULT_MASS));
  54.     }

  55.     /** Build a propagator from orbit and central attraction coefficient μ.
  56.      * <p>Mass and attitude provider are set to unspecified non-null arbitrary values.</p>
  57.      *
  58.      * @param initialFieldOrbit initial orbit
  59.      * @param mu central attraction coefficient (m³/s²)
  60.      * @see #FieldKeplerianPropagator(FieldOrbit, AttitudeProvider, CalculusFieldElement)
  61.      */
  62.     public FieldKeplerianPropagator(final FieldOrbit<T> initialFieldOrbit, final T mu) {
  63.         this(initialFieldOrbit, FrameAlignedProvider.of(initialFieldOrbit.getFrame()),
  64.              mu, initialFieldOrbit.getA().getField().getZero().newInstance(DEFAULT_MASS));
  65.     }

  66.     /** Build a propagator from orbit and attitude provider.
  67.      * <p>The central attraction coefficient μ is set to the same value
  68.      * used for the initial orbit definition. Mass is set to an unspecified
  69.      * non-null arbitrary value.</p>
  70.      * @param initialFieldOrbit initial orbit
  71.      * @param attitudeProv  attitude provider
  72.      */
  73.     public FieldKeplerianPropagator(final FieldOrbit<T> initialFieldOrbit,
  74.                                     final AttitudeProvider attitudeProv) {
  75.         this(initialFieldOrbit, attitudeProv, initialFieldOrbit.getMu(),
  76.                 initialFieldOrbit.getA().getField().getZero().newInstance(DEFAULT_MASS));
  77.     }

  78.     /** Build a propagator from orbit, attitude provider and central attraction
  79.      * coefficient μ.
  80.      * <p>Mass is set to an unspecified non-null arbitrary value.</p>
  81.      * @param initialFieldOrbit initial orbit
  82.      * @param attitudeProv attitude provider
  83.      * @param mu central attraction coefficient (m³/s²)
  84.      */
  85.     public FieldKeplerianPropagator(final FieldOrbit<T> initialFieldOrbit,
  86.                                     final AttitudeProvider attitudeProv,
  87.                                     final T mu) {
  88.         this(initialFieldOrbit, attitudeProv, mu, initialFieldOrbit.getA().getField().getZero().newInstance(DEFAULT_MASS));
  89.     }

  90.     /** Build propagator from orbit, attitude provider, central attraction
  91.      * coefficient μ and mass.
  92.      * @param initialOrbit initial orbit
  93.      * @param attitudeProv attitude provider
  94.      * @param mu central attraction coefficient (m³/s²)
  95.      * @param mass spacecraft mass (kg)
  96.      */
  97.     public FieldKeplerianPropagator(final FieldOrbit<T> initialOrbit, final AttitudeProvider attitudeProv,
  98.                                     final T mu, final T mass) {

  99.         super(initialOrbit.getA().getField(), attitudeProv);

  100.         // ensure the orbit use the specified mu and has no non-Keplerian derivatives
  101.         final FieldSpacecraftState<T> initial = fixState(initialOrbit,
  102.                                                          getAttitudeProvider().getAttitude(initialOrbit,
  103.                                                                                            initialOrbit.getDate(),
  104.                                                                                            initialOrbit.getFrame()),
  105.                                                          mass, mu, null, null);
  106.         states = new FieldTimeSpanMap<>(initial, initialOrbit.getA().getField());
  107.         super.resetInitialState(initial);
  108.     }

  109.     /** Fix state to use a specified mu and remove derivatives.
  110.      * <p>
  111.      * This ensures the propagation model (which is based on calling
  112.      * {@link Orbit#shiftedBy(double)}) is Keplerian only and uses a specified mu.
  113.      * </p>
  114.      * @param orbit orbit to fix
  115.      * @param attitude current attitude
  116.      * @param mass current mass
  117.      * @param mu gravity coefficient to use
  118.      * @param additionalStates additional states (may be null)
  119.      * @param additionalStatesderivatives additional states derivatives (may be null)
  120.      * @return fixed orbit
  121.      */
  122.     private FieldSpacecraftState<T> fixState(final FieldOrbit<T> orbit, final FieldAttitude<T> attitude, final T mass, final T mu,
  123.                                              final FieldDataDictionary<T> additionalStates,
  124.                                              final FieldArrayDictionary<T> additionalStatesderivatives) {
  125.         final OrbitType type = orbit.getType();
  126.         final T[] stateVector = MathArrays.buildArray(mass.getField(), 6);
  127.         final PositionAngleType positionAngleType = PositionAngleType.MEAN;
  128.         type.mapOrbitToArray(orbit, positionAngleType, stateVector, null);
  129.         final FieldOrbit<T> fixedOrbit = type.mapArrayToOrbit(stateVector, null, positionAngleType,
  130.                                                               orbit.getDate(), mu, orbit.getFrame());
  131.         FieldSpacecraftState<T> fixedState = new FieldSpacecraftState<>(fixedOrbit, attitude).withMass(mass);
  132.         if (additionalStates != null) {
  133.             for (final FieldDataDictionary<T>.Entry entry : additionalStates.getData()) {
  134.                 fixedState = fixedState.addAdditionalData(entry.getKey(), entry.getValue());
  135.             }
  136.         }
  137.         if (additionalStatesderivatives != null) {
  138.             for (final FieldArrayDictionary<T>.Entry entry : additionalStatesderivatives.getData()) {
  139.                 fixedState = fixedState.addAdditionalStateDerivative(entry.getKey(), entry.getValue());
  140.             }
  141.         }
  142.         return fixedState;
  143.     }

  144.     /** {@inheritDoc} */
  145.     @Override
  146.     public void resetInitialState(final FieldSpacecraftState<T> state) {

  147.         // ensure the orbit use the specified mu and has no non-Keplerian derivatives
  148.         final FieldSpacecraftState<T> formerInitial = getInitialState();
  149.         final T mu = formerInitial == null ? state.getOrbit().getMu() : formerInitial.getOrbit().getMu();
  150.         final FieldSpacecraftState<T> fixedState = fixState(state.getOrbit(),
  151.                                                             state.getAttitude(),
  152.                                                             state.getMass(),
  153.                                                             mu,
  154.                                                             state.getAdditionalDataValues(),
  155.                                                             state.getAdditionalStatesDerivatives());

  156.         states = new FieldTimeSpanMap<>(fixedState, state.getDate().getField());
  157.         super.resetInitialState(fixedState);

  158.     }

  159.     /** {@inheritDoc} */
  160.     @Override
  161.     protected void resetIntermediateState(final FieldSpacecraftState<T> state, final boolean forward) {
  162.         if (forward) {
  163.             states.addValidAfter(state, state.getDate());
  164.         } else {
  165.             states.addValidBefore(state, state.getDate());
  166.         }
  167.         stateChanged(state);
  168.     }

  169.     /** {@inheritDoc} */
  170.     @Override
  171.     public FieldOrbit<T> propagateOrbit(final FieldAbsoluteDate<T> date,
  172.                                         final T[] parameters) {
  173.         // propagate orbit
  174.         FieldOrbit<T> orbit = states.get(date).getOrbit();
  175.         do {
  176.             // we use a loop here to compensate for very small date shifts error
  177.             // that occur with long propagation time
  178.             orbit = orbit.shiftedBy(date.durationFrom(orbit.getDate()));
  179.         } while (!date.equals(orbit.getDate()));
  180.         return orbit;
  181.     }

  182.     /** {@inheritDoc}*/
  183.     @Override
  184.     protected T getMass(final FieldAbsoluteDate<T> date) {
  185.         return states.get(date).getMass();
  186.     }

  187.     /** {@inheritDoc} */
  188.     @Override
  189.     public List<ParameterDriver> getParametersDrivers() {
  190.         // Keplerian propagation model does not have parameter drivers.
  191.         return Collections.emptyList();
  192.     }

  193. }