AbstractPropagatorBuilder.java

  1. /* Copyright 2002-2022 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;

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

  20. import org.hipparchus.exception.LocalizedCoreFormats;
  21. import org.hipparchus.util.FastMath;
  22. import org.orekit.attitudes.AttitudeProvider;
  23. import org.orekit.attitudes.InertialProvider;
  24. import org.orekit.errors.OrekitIllegalArgumentException;
  25. import org.orekit.forces.gravity.NewtonianAttraction;
  26. import org.orekit.frames.Frame;
  27. import org.orekit.orbits.Orbit;
  28. import org.orekit.orbits.OrbitType;
  29. import org.orekit.orbits.PositionAngle;
  30. import org.orekit.propagation.integration.AdditionalDerivativesProvider;
  31. import org.orekit.time.AbsoluteDate;
  32. import org.orekit.utils.ParameterDriver;
  33. import org.orekit.utils.ParameterDriversList;
  34. import org.orekit.utils.ParameterDriversList.DelegatingDriver;
  35. import org.orekit.utils.ParameterObserver;

  36. /** Base class for propagator builders.
  37.  * @author Pascal Parraud
  38.  * @since 7.1
  39.  */
  40. public abstract class AbstractPropagatorBuilder implements PropagatorBuilder {

  41.     /** Central attraction scaling factor.
  42.      * <p>
  43.      * We use a power of 2 to avoid numeric noise introduction
  44.      * in the multiplications/divisions sequences.
  45.      * </p>
  46.      */
  47.     private static final double MU_SCALE = FastMath.scalb(1.0, 32);

  48.     /** Date of the initial orbit. */
  49.     private AbsoluteDate initialOrbitDate;

  50.     /** Frame in which the orbit is propagated. */
  51.     private final Frame frame;

  52.     /** Central attraction coefficient (m³/s²). */
  53.     private double mu;

  54.     /** Drivers for orbital parameters. */
  55.     private final ParameterDriversList orbitalDrivers;

  56.     /** List of the supported parameters. */
  57.     private ParameterDriversList propagationDrivers;

  58.     /** Orbit type to use. */
  59.     private final OrbitType orbitType;

  60.     /** Position angle type to use. */
  61.     private final PositionAngle positionAngle;

  62.     /** Position scale to use for the orbital drivers. */
  63.     private final double positionScale;

  64.     /** Attitude provider for the propagator. */
  65.     private AttitudeProvider attitudeProvider;

  66.     /** Additional equations. */
  67.     @Deprecated
  68.     private List<org.orekit.propagation.integration.AdditionalEquations> additionalEquations;

  69.     /** Additional derivatives providers.
  70.      * @since 11.1
  71.      */
  72.     private List<AdditionalDerivativesProvider> additionalDerivativesProviders;

  73.     /** Build a new instance.
  74.      * <p>
  75.      * The template orbit is used as a model to {@link
  76.      * #createInitialOrbit() create initial orbit}. It defines the
  77.      * inertial frame, the central attraction coefficient, the orbit type, and is also
  78.      * used together with the {@code positionScale} to convert from the {@link
  79.      * ParameterDriver#setNormalizedValue(double) normalized} parameters used by the
  80.      * callers of this builder to the real orbital parameters. The initial attitude
  81.      * provider is aligned with the inertial frame.
  82.      * </p>
  83.      * <p>
  84.      * By default, all the {@link #getOrbitalParametersDrivers() orbital parameters drivers}
  85.      * are selected, which means that if the builder is used for orbit determination or
  86.      * propagator conversion, all orbital parameters will be estimated. If only a subset
  87.      * of the orbital parameters must be estimated, caller must retrieve the orbital
  88.      * parameters by calling {@link #getOrbitalParametersDrivers()} and then call
  89.      * {@link ParameterDriver#setSelected(boolean) setSelected(false)}.
  90.      * </p>
  91.      * @param templateOrbit reference orbit from which real orbits will be built
  92.      * @param positionAngle position angle type to use
  93.      * @param positionScale scaling factor used for orbital parameters normalization
  94.      * (typically set to the expected standard deviation of the position)
  95.      * @param addDriverForCentralAttraction if true, a {@link ParameterDriver} should
  96.      * be set up for central attraction coefficient
  97.      * @since 8.0
  98.      * @see #AbstractPropagatorBuilder(Orbit, PositionAngle, double, boolean,
  99.      * AttitudeProvider)
  100.      */
  101.     protected AbstractPropagatorBuilder(final Orbit templateOrbit, final PositionAngle positionAngle,
  102.                                         final double positionScale, final boolean addDriverForCentralAttraction) {
  103.         this(templateOrbit, positionAngle, positionScale, addDriverForCentralAttraction,
  104.              new InertialProvider(templateOrbit.getFrame()));
  105.     }

  106.     /** Build a new instance.
  107.      * <p>
  108.      * The template orbit is used as a model to {@link
  109.      * #createInitialOrbit() create initial orbit}. It defines the
  110.      * inertial frame, the central attraction coefficient, the orbit type, and is also
  111.      * used together with the {@code positionScale} to convert from the {@link
  112.      * ParameterDriver#setNormalizedValue(double) normalized} parameters used by the
  113.      * callers of this builder to the real orbital parameters.
  114.      * </p>
  115.      * <p>
  116.      * By default, all the {@link #getOrbitalParametersDrivers() orbital parameters drivers}
  117.      * are selected, which means that if the builder is used for orbit determination or
  118.      * propagator conversion, all orbital parameters will be estimated. If only a subset
  119.      * of the orbital parameters must be estimated, caller must retrieve the orbital
  120.      * parameters by calling {@link #getOrbitalParametersDrivers()} and then call
  121.      * {@link ParameterDriver#setSelected(boolean) setSelected(false)}.
  122.      * </p>
  123.      * @param templateOrbit reference orbit from which real orbits will be built
  124.      * @param positionAngle position angle type to use
  125.      * @param positionScale scaling factor used for orbital parameters normalization
  126.      * (typically set to the expected standard deviation of the position)
  127.      * @param addDriverForCentralAttraction if true, a {@link ParameterDriver} should
  128.      * be set up for central attraction coefficient
  129.      * @param attitudeProvider for the propagator.
  130.      * @since 10.1
  131.      * @see #AbstractPropagatorBuilder(Orbit, PositionAngle, double, boolean)
  132.      */
  133.     protected AbstractPropagatorBuilder(final Orbit templateOrbit,
  134.                                         final PositionAngle positionAngle,
  135.                                         final double positionScale,
  136.                                         final boolean addDriverForCentralAttraction,
  137.                                         final AttitudeProvider attitudeProvider) {

  138.         this.initialOrbitDate    = templateOrbit.getDate();
  139.         this.frame               = templateOrbit.getFrame();
  140.         this.mu                  = templateOrbit.getMu();
  141.         this.propagationDrivers  = new ParameterDriversList();
  142.         this.orbitType           = templateOrbit.getType();
  143.         this.positionAngle       = positionAngle;
  144.         this.positionScale       = positionScale;
  145.         this.orbitalDrivers      = orbitType.getDrivers(positionScale, templateOrbit, positionAngle);
  146.         this.attitudeProvider = attitudeProvider;
  147.         for (final DelegatingDriver driver : orbitalDrivers.getDrivers()) {
  148.             driver.setSelected(true);
  149.         }

  150.         this.additionalEquations             = new ArrayList<>();
  151.         this.additionalDerivativesProviders  = new ArrayList<>();

  152.         if (addDriverForCentralAttraction) {
  153.             final ParameterDriver muDriver = new ParameterDriver(NewtonianAttraction.CENTRAL_ATTRACTION_COEFFICIENT,
  154.                                                                  mu, MU_SCALE, 0, Double.POSITIVE_INFINITY);
  155.             muDriver.addObserver(new ParameterObserver() {
  156.                 /** {@inheridDoc} */
  157.                 @Override
  158.                 public void valueChanged(final double previousValue, final ParameterDriver driver) {
  159.                     AbstractPropagatorBuilder.this.mu = driver.getValue();
  160.                 }
  161.             });
  162.             propagationDrivers.add(muDriver);
  163.         }

  164.     }

  165.     /** {@inheritDoc} */
  166.     public OrbitType getOrbitType() {
  167.         return orbitType;
  168.     }

  169.     /** {@inheritDoc} */
  170.     public PositionAngle getPositionAngle() {
  171.         return positionAngle;
  172.     }

  173.     /** {@inheritDoc} */
  174.     public AbsoluteDate getInitialOrbitDate() {
  175.         return initialOrbitDate;
  176.     }

  177.     /** {@inheritDoc} */
  178.     public Frame getFrame() {
  179.         return frame;
  180.     }

  181.     /** {@inheritDoc} */
  182.     public ParameterDriversList getOrbitalParametersDrivers() {
  183.         return orbitalDrivers;
  184.     }

  185.     /** {@inheritDoc} */
  186.     public ParameterDriversList getPropagationParametersDrivers() {
  187.         return propagationDrivers;
  188.     }

  189.     /**
  190.      * Get the attitude provider.
  191.      *
  192.      * @return the attitude provider
  193.      * @since 10.1
  194.      */
  195.     public AttitudeProvider getAttitudeProvider() {
  196.         return attitudeProvider;
  197.     }

  198.     /**
  199.      * Set the attitude provider.
  200.      *
  201.      * @param attitudeProvider attitude provider
  202.      * @since 10.1
  203.      */
  204.     public void setAttitudeProvider(final AttitudeProvider attitudeProvider) {
  205.         this.attitudeProvider = attitudeProvider;
  206.     }

  207.     /** Get the position scale.
  208.      * @return the position scale used to scale the orbital drivers
  209.      */
  210.     public double getPositionScale() {
  211.         return positionScale;
  212.     }

  213.     /** Get the central attraction coefficient (µ - m³/s²) value.
  214.      * @return the central attraction coefficient (µ - m³/s²) value
  215.      * @since 9.2
  216.      */
  217.     public double getMu() {
  218.         return mu;
  219.     }

  220.     /** Get the number of selected parameters.
  221.      * @return number of selected parameters
  222.      */
  223.     private int getNbSelected() {

  224.         int count = 0;

  225.         // count orbital parameters
  226.         for (final ParameterDriver driver : orbitalDrivers.getDrivers()) {
  227.             if (driver.isSelected()) {
  228.                 ++count;
  229.             }
  230.         }

  231.         // count propagation parameters
  232.         for (final ParameterDriver driver : propagationDrivers.getDrivers()) {
  233.             if (driver.isSelected()) {
  234.                 ++count;
  235.             }
  236.         }

  237.         return count;

  238.     }

  239.     /** {@inheritDoc} */
  240.     public double[] getSelectedNormalizedParameters() {

  241.         // allocate array
  242.         final double[] selected = new double[getNbSelected()];

  243.         // fill data
  244.         int index = 0;
  245.         for (final ParameterDriver driver : orbitalDrivers.getDrivers()) {
  246.             if (driver.isSelected()) {
  247.                 selected[index++] = driver.getNormalizedValue();
  248.             }
  249.         }
  250.         for (final ParameterDriver driver : propagationDrivers.getDrivers()) {
  251.             if (driver.isSelected()) {
  252.                 selected[index++] = driver.getNormalizedValue();
  253.             }
  254.         }

  255.         return selected;

  256.     }

  257.     /** Build an initial orbit using the current selected parameters.
  258.      * <p>
  259.      * This method is a stripped down version of {@link #buildPropagator(double[])}
  260.      * that only builds the initial orbit and not the full propagator.
  261.      * </p>
  262.      * @return an initial orbit
  263.      * @since 8.0
  264.      */
  265.     protected Orbit createInitialOrbit() {
  266.         final double[] unNormalized = new double[orbitalDrivers.getNbParams()];
  267.         for (int i = 0; i < unNormalized.length; ++i) {
  268.             unNormalized[i] = orbitalDrivers.getDrivers().get(i).getValue();
  269.         }
  270.         return getOrbitType().mapArrayToOrbit(unNormalized, null, positionAngle, initialOrbitDate, mu, frame);
  271.     }

  272.     /** Set the selected parameters.
  273.      * @param normalizedParameters normalized values for the selected parameters
  274.      */
  275.     protected void setParameters(final double[] normalizedParameters) {


  276.         if (normalizedParameters.length != getNbSelected()) {
  277.             throw new OrekitIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH,
  278.                                                      normalizedParameters.length,
  279.                                                      getNbSelected());
  280.         }

  281.         int index = 0;

  282.         // manage orbital parameters
  283.         for (final ParameterDriver driver : orbitalDrivers.getDrivers()) {
  284.             if (driver.isSelected()) {
  285.                 driver.setNormalizedValue(normalizedParameters[index++]);
  286.             }
  287.         }

  288.         // manage propagation parameters
  289.         for (final ParameterDriver driver : propagationDrivers.getDrivers()) {
  290.             if (driver.isSelected()) {
  291.                 driver.setNormalizedValue(normalizedParameters[index++]);
  292.             }
  293.         }

  294.     }

  295.     /** Add a supported parameter.
  296.      * @param driver driver for the parameter
  297.      */
  298.     protected void addSupportedParameter(final ParameterDriver driver) {
  299.         propagationDrivers.add(driver);
  300.         propagationDrivers.sort();
  301.     }

  302.     /** Reset the orbit in the propagator builder.
  303.      * @param newOrbit New orbit to set in the propagator builder
  304.      */
  305.     public void resetOrbit(final Orbit newOrbit) {

  306.         // Map the new orbit in an array of double
  307.         final double[] orbitArray = new double[6];
  308.         orbitType.mapOrbitToArray(newOrbit, getPositionAngle(), orbitArray, null);

  309.         // Update all the orbital drivers, selected or unselected
  310.         // Reset values and reference values
  311.         final List<DelegatingDriver> orbitalDriversList = getOrbitalParametersDrivers().getDrivers();
  312.         int i = 0;
  313.         for (DelegatingDriver driver : orbitalDriversList) {
  314.             driver.setReferenceValue(orbitArray[i]);
  315.             driver.setValue(orbitArray[i++]);
  316.         }

  317.         // Change the initial orbit date in the builder
  318.         this.initialOrbitDate = newOrbit.getDate();
  319.     }

  320.     /** Add a set of user-specified equations to be integrated along with the orbit propagation (author Shiva Iyer).
  321.      * @param additional additional equations
  322.      * @since 10.1
  323.      * @deprecated as of 11.1, replaced by {@link #addAdditionalDerivativesProvider(AdditionalDerivativesProvider)}
  324.      */
  325.     @Deprecated
  326.     public void addAdditionalEquations(final org.orekit.propagation.integration.AdditionalEquations additional) {
  327.         additionalEquations.add(additional);
  328.     }

  329.     /** Get the list of additional equations.
  330.      * @return the list of additional equations
  331.      * @since 10.1
  332.      * @deprecated as of 11.1, replaced by {@link #addAdditionalDerivativesProvider(AdditionalDerivativesProvider)}
  333.      */
  334.     @Deprecated
  335.     protected List<org.orekit.propagation.integration.AdditionalEquations> getAdditionalEquations() {
  336.         return additionalEquations;
  337.     }

  338.     /** Add a set of user-specified equations to be integrated along with the orbit propagation (author Shiva Iyer).
  339.      * @param provider provider for additional derivatives
  340.      * @since 11.1
  341.      */
  342.     public void addAdditionalDerivativesProvider(final AdditionalDerivativesProvider provider) {
  343.         additionalDerivativesProviders.add(provider);
  344.     }

  345.     /** Get the list of additional equations.
  346.      * @return the list of additional equations
  347.      * @since 11.1
  348.      */
  349.     protected List<AdditionalDerivativesProvider> getAdditionalDerivativesProviders() {
  350.         return additionalDerivativesProviders;
  351.     }

  352.     /** Deselects orbital and propagation drivers. */
  353.     public void deselectDynamicParameters() {
  354.         for (ParameterDriver driver : getPropagationParametersDrivers().getDrivers()) {
  355.             driver.setSelected(false);
  356.         }
  357.         for (ParameterDriver driver : getOrbitalParametersDrivers().getDrivers()) {
  358.             driver.setSelected(false);
  359.         }
  360.     }

  361. }