AbstractIndirectShooting.java

  1. /* Copyright 2022-2025 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.control.indirect.shooting;

  18. import org.hipparchus.CalculusFieldElement;
  19. import org.hipparchus.Field;
  20. import org.hipparchus.ode.ODEIntegrator;
  21. import org.hipparchus.ode.nonstiff.FieldExplicitRungeKuttaIntegrator;
  22. import org.orekit.control.indirect.shooting.propagation.ShootingPropagationSettings;
  23. import org.orekit.forces.ForceModel;
  24. import org.orekit.forces.gravity.NewtonianAttraction;
  25. import org.orekit.orbits.FieldOrbit;
  26. import org.orekit.orbits.Orbit;
  27. import org.orekit.propagation.FieldSpacecraftState;
  28. import org.orekit.propagation.SpacecraftState;
  29. import org.orekit.propagation.conversion.FieldExplicitRungeKuttaIntegratorBuilder;
  30. import org.orekit.propagation.conversion.ODEIntegratorBuilder;
  31. import org.orekit.propagation.integration.AdditionalDerivativesProvider;
  32. import org.orekit.propagation.numerical.NumericalPropagator;

  33. /**
  34.  * Abstract class for indirect shooting methods with numerical propagation.
  35.  *
  36.  * @author Romain Serra
  37.  * @since 12.2
  38.  */
  39. public abstract class AbstractIndirectShooting {

  40.     /** Default value for convergence tolerance on mass adjoint variable. */
  41.     public static final double DEFAULT_TOLERANCE_MASS_ADJOINT = 1e-10;

  42.     /** Propagation settings. */
  43.     private final ShootingPropagationSettings propagationSettings;

  44.     /**
  45.      * Constructor.
  46.      * @param propagationSettings propagation settings
  47.      */
  48.     protected AbstractIndirectShooting(final ShootingPropagationSettings propagationSettings) {
  49.         this.propagationSettings = propagationSettings;
  50.     }

  51.     /**
  52.      * Getter for the propagation settings.
  53.      * @return propagation settings
  54.      */
  55.     public ShootingPropagationSettings getPropagationSettings() {
  56.         return propagationSettings;
  57.     }

  58.     /**
  59.      * Solve for the boundary conditions, given an initial mass and an initial guess for the adjoint variables.
  60.      * @param initialMass initial mass
  61.      * @param initialGuess initial guess
  62.      * @return boundary problem solution
  63.      */
  64.     public abstract ShootingBoundaryOutput solve(double initialMass, double[] initialGuess);

  65.     /**
  66.      * Create numerical propagator.
  67.      * @param initialState initial state
  68.      * @return numerical propagator
  69.      */
  70.     protected NumericalPropagator buildPropagator(final SpacecraftState initialState) {
  71.         final ODEIntegrator integrator = buildIntegrator(initialState);
  72.         final NumericalPropagator propagator =
  73.               new NumericalPropagator(integrator, propagationSettings.getAttitudeProvider());
  74.         propagator.setIgnoreCentralAttraction(true);
  75.         propagator.setInitialState(initialState);
  76.         propagator.setIgnoreCentralAttraction(false);
  77.         propagator.removeForceModels();
  78.         if (initialState.isOrbitDefined()) {
  79.             propagator.setOrbitType(initialState.getOrbit().getType());
  80.         } else {
  81.             if (propagationSettings.getForceModels().stream().noneMatch(NewtonianAttraction.class::isInstance)) {
  82.                 propagator.setIgnoreCentralAttraction(true);
  83.             }
  84.             propagator.setOrbitType(null);
  85.         }
  86.         for (final ForceModel forceModel: propagationSettings.getForceModels()) {
  87.             propagator.addForceModel(forceModel);
  88.         }
  89.         final AdditionalDerivativesProvider derivativesProvider = propagationSettings.getAdjointDynamicsProvider()
  90.                 .buildAdditionalDerivativesProvider();
  91.         propagator.addAdditionalDerivativesProvider(derivativesProvider);
  92.         return propagator;
  93.     }

  94.     /**
  95.      * Create integrator.
  96.      * @param initialState initial state
  97.      * @return integrator
  98.      */
  99.     private ODEIntegrator buildIntegrator(final SpacecraftState initialState) {
  100.         final ODEIntegratorBuilder integratorBuilder = propagationSettings.getIntegrationSettings().getIntegratorBuilder();
  101.         if (initialState.isOrbitDefined()) {
  102.             final Orbit orbit = initialState.getOrbit();
  103.             return integratorBuilder.buildIntegrator(orbit, orbit.getType(), NumericalPropagator.DEFAULT_POSITION_ANGLE_TYPE);
  104.         } else {
  105.             return integratorBuilder.buildIntegrator(initialState.getAbsPVA());
  106.         }
  107.     }

  108.     /**
  109.      * Create Field integrator.
  110.      * @param initialState initial state
  111.      * @param <T> field type
  112.      * @return integrator.
  113.      */
  114.     protected <T extends CalculusFieldElement<T>> FieldExplicitRungeKuttaIntegrator<T> buildFieldIntegrator(final FieldSpacecraftState<T> initialState) {
  115.         final Field<T> field = initialState.getMass().getField();
  116.         final FieldExplicitRungeKuttaIntegratorBuilder<T> integratorBuilder = propagationSettings.getIntegrationSettings()
  117.             .getFieldIntegratorBuilder(field);
  118.         if (initialState.isOrbitDefined()) {
  119.             final FieldOrbit<T> orbit = initialState.getOrbit();
  120.             return integratorBuilder.buildIntegrator(field, orbit.toOrbit(), orbit.getType(),
  121.                     NumericalPropagator.DEFAULT_POSITION_ANGLE_TYPE);
  122.         } else {
  123.             return integratorBuilder.buildIntegrator(initialState.getAbsPVA());
  124.         }
  125.     }

  126. }