KeplerianPropagator.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 org.hipparchus.linear.RealMatrix;
  19. import org.orekit.attitudes.Attitude;
  20. import org.orekit.attitudes.AttitudeProvider;
  21. import org.orekit.attitudes.FrameAlignedProvider;
  22. import org.orekit.orbits.Orbit;
  23. import org.orekit.orbits.OrbitType;
  24. import org.orekit.orbits.PositionAngleType;
  25. import org.orekit.propagation.AbstractMatricesHarvester;
  26. import org.orekit.propagation.SpacecraftState;
  27. import org.orekit.time.AbsoluteDate;
  28. import org.orekit.utils.DoubleArrayDictionary;
  29. import org.orekit.utils.DataDictionary;
  30. import org.orekit.utils.TimeSpanMap;

  31. /** Simple Keplerian orbit propagator.
  32.  * @see Orbit
  33.  * @author Guylaine Prat
  34.  */
  35. public class KeplerianPropagator extends AbstractAnalyticalPropagator {

  36.     /** All states. */
  37.     private TimeSpanMap<SpacecraftState> states;

  38.     /** Build a propagator from orbit only.
  39.      * <p>The central attraction coefficient μ is set to the same value used
  40.      * for the initial orbit definition. Mass and attitude provider are set to
  41.      * unspecified non-null arbitrary values.</p>
  42.      *
  43.      * @param initialOrbit initial orbit
  44.      * @see #KeplerianPropagator(Orbit, AttitudeProvider)
  45.      */
  46.     public KeplerianPropagator(final Orbit initialOrbit) {
  47.         this(initialOrbit, FrameAlignedProvider.of(initialOrbit.getFrame()),
  48.              initialOrbit.getMu(), DEFAULT_MASS);
  49.     }

  50.     /** Build a propagator from orbit and central attraction coefficient μ.
  51.      * <p>Mass and attitude provider are set to unspecified non-null arbitrary values.</p>
  52.      *
  53.      * @param initialOrbit initial orbit
  54.      * @param mu central attraction coefficient (m³/s²)
  55.      * @see #KeplerianPropagator(Orbit, AttitudeProvider, double)
  56.      */
  57.     public KeplerianPropagator(final Orbit initialOrbit, final double mu) {
  58.         this(initialOrbit, FrameAlignedProvider.of(initialOrbit.getFrame()),
  59.              mu, DEFAULT_MASS);
  60.     }

  61.     /** Build a propagator from orbit and attitude provider.
  62.      * <p>The central attraction coefficient μ is set to the same value
  63.      * used for the initial orbit definition. Mass is set to an unspecified
  64.      * non-null arbitrary value.</p>
  65.      * @param initialOrbit initial orbit
  66.      * @param attitudeProv  attitude provider
  67.      */
  68.     public KeplerianPropagator(final Orbit initialOrbit,
  69.                                final AttitudeProvider attitudeProv) {
  70.         this(initialOrbit, attitudeProv, initialOrbit.getMu(), DEFAULT_MASS);
  71.     }

  72.     /** Build a propagator from orbit, attitude provider and central attraction
  73.      * coefficient μ.
  74.      * <p>Mass is set to an unspecified non-null arbitrary value.</p>
  75.      * @param initialOrbit initial orbit
  76.      * @param attitudeProv attitude provider
  77.      * @param mu central attraction coefficient (m³/s²)
  78.      */
  79.     public KeplerianPropagator(final Orbit initialOrbit,
  80.                                final AttitudeProvider attitudeProv,
  81.                                final double mu) {
  82.         this(initialOrbit, attitudeProv, mu, DEFAULT_MASS);
  83.     }

  84.     /** Build propagator from orbit, attitude provider, central attraction
  85.      * coefficient μ and mass.
  86.      * @param initialOrbit initial orbit
  87.      * @param attitudeProv attitude provider
  88.      * @param mu central attraction coefficient (m³/s²)
  89.      * @param mass spacecraft mass (kg)
  90.      */
  91.     public KeplerianPropagator(final Orbit initialOrbit, final AttitudeProvider attitudeProv,
  92.                                final double mu, final double mass) {

  93.         super(attitudeProv);

  94.         // ensure the orbit use the specified mu and has no non-Keplerian derivatives
  95.         final SpacecraftState initial = fixState(initialOrbit,
  96.                                                  getAttitudeProvider().getAttitude(initialOrbit,
  97.                                                                                    initialOrbit.getDate(),
  98.                                                                                    initialOrbit.getFrame()),
  99.                                                  mass, mu, null, null);
  100.         states = new TimeSpanMap<>(initial);
  101.         super.resetInitialState(initial);

  102.     }

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

  138.     /** {@inheritDoc} */
  139.     public void resetInitialState(final SpacecraftState state) {

  140.         // ensure the orbit use the specified mu and has no non-Keplerian derivatives
  141.         final SpacecraftState formerInitial = getInitialState();
  142.         final double mu = formerInitial == null ? state.getOrbit().getMu() : formerInitial.getOrbit().getMu();
  143.         final SpacecraftState fixedState = fixState(state.getOrbit(),
  144.                                                     state.getAttitude(),
  145.                                                     state.getMass(),
  146.                                                     mu,
  147.                                                     state.getAdditionalDataValues(),
  148.                                                     state.getAdditionalStatesDerivatives());

  149.         states = new TimeSpanMap<>(fixedState);
  150.         super.resetInitialState(fixedState);

  151.     }

  152.     /** {@inheritDoc} */
  153.     protected void resetIntermediateState(final SpacecraftState state, final boolean forward) {
  154.         if (forward) {
  155.             states.addValidAfter(state, state.getDate(), false);
  156.         } else {
  157.             states.addValidBefore(state, state.getDate(), false);
  158.         }
  159.         stateChanged(state);
  160.     }

  161.     /** {@inheritDoc} */
  162.     public Orbit propagateOrbit(final AbsoluteDate date) {

  163.         // propagate orbit
  164.         Orbit orbit = states.get(date).getOrbit();
  165.         do {
  166.             // we use a loop here to compensate for very small date shifts error
  167.             // that occur with long propagation time
  168.             orbit = orbit.shiftedBy(date.durationFrom(orbit.getDate()));
  169.         } while (!date.equals(orbit.getDate()));

  170.         return orbit;

  171.     }

  172.     /** {@inheritDoc}*/
  173.     protected double getMass(final AbsoluteDate date) {
  174.         return states.get(date).getMass();
  175.     }

  176.     /** {@inheritDoc} */
  177.     @Override
  178.     protected AbstractMatricesHarvester createHarvester(final String stmName, final RealMatrix initialStm,
  179.                                                         final DoubleArrayDictionary initialJacobianColumns) {
  180.         // Create the harvester
  181.         final KeplerianHarvester harvester = new KeplerianHarvester(this, stmName, initialStm, initialJacobianColumns);
  182.         // Update the list of additional state provider
  183.         addAdditionalDataProvider(harvester);
  184.         // Return the configured harvester
  185.         return harvester;
  186.     }

  187. }