DSSTPropagatorBuilder.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.Collections;
  20. import java.util.List;

  21. import org.orekit.attitudes.Attitude;
  22. import org.orekit.attitudes.AttitudeProvider;
  23. import org.orekit.attitudes.InertialProvider;
  24. import org.orekit.estimation.leastsquares.DSSTBatchLSModel;
  25. import org.orekit.estimation.leastsquares.ModelObserver;
  26. import org.orekit.estimation.measurements.ObservedMeasurement;
  27. import org.orekit.estimation.sequential.AbstractKalmanModel;
  28. import org.orekit.estimation.sequential.CovarianceMatrixProvider;
  29. import org.orekit.orbits.EquinoctialOrbit;
  30. import org.orekit.orbits.Orbit;
  31. import org.orekit.orbits.OrbitType;
  32. import org.orekit.orbits.PositionAngle;
  33. import org.orekit.propagation.PropagationType;
  34. import org.orekit.propagation.Propagator;
  35. import org.orekit.propagation.SpacecraftState;
  36. import org.orekit.propagation.integration.AdditionalDerivativesProvider;
  37. import org.orekit.propagation.semianalytical.dsst.DSSTPropagator;
  38. import org.orekit.propagation.semianalytical.dsst.forces.DSSTForceModel;
  39. import org.orekit.propagation.semianalytical.dsst.forces.DSSTNewtonianAttraction;
  40. import org.orekit.utils.ParameterDriver;
  41. import org.orekit.utils.ParameterDriversList;

  42. /** Builder for DSST propagator.
  43.  * @author Bryan Cazabonne
  44.  * @since 10.0
  45.  */
  46. public class DSSTPropagatorBuilder extends AbstractPropagatorBuilder implements OrbitDeterminationPropagatorBuilder {

  47.     /** First order integrator builder for propagation. */
  48.     private final ODEIntegratorBuilder builder;

  49.     /** Force models used during the extrapolation of the orbit. */
  50.     private final List<DSSTForceModel> forceModels;

  51.     /** Current mass for initial state (kg). */
  52.     private double mass;

  53.     /** Type of the orbit used for the propagation.*/
  54.     private PropagationType propagationType;

  55.     /** Type of the elements used to define the orbital state.*/
  56.     private PropagationType stateType;

  57.     /** Build a new instance.
  58.      * <p>
  59.      * The reference orbit is used as a model to {@link
  60.      * #createInitialOrbit() create initial orbit}. It defines the
  61.      * inertial frame, the central attraction coefficient, and is also used together
  62.      * with the {@code positionScale} to convert from the {@link
  63.      * ParameterDriver#setNormalizedValue(double) normalized} parameters used by the
  64.      * callers of this builder to the real orbital parameters.
  65.      * </p>
  66.      *
  67.      * @param referenceOrbit reference orbit from which real orbits will be built
  68.      * @param builder first order integrator builder
  69.      * @param positionScale scaling factor used for orbital parameters normalization
  70.      * (typically set to the expected standard deviation of the position)
  71.      * @param propagationType type of the orbit used for the propagation (mean or osculating)
  72.      * @param stateType type of the elements used to define the orbital state (mean or osculating)
  73.      * @see #DSSTPropagatorBuilder(Orbit, ODEIntegratorBuilder, double, PropagationType,
  74.      * PropagationType, AttitudeProvider)
  75.      */
  76.     public DSSTPropagatorBuilder(final Orbit referenceOrbit,
  77.                                  final ODEIntegratorBuilder builder,
  78.                                  final double positionScale,
  79.                                  final PropagationType propagationType,
  80.                                  final PropagationType stateType) {
  81.         this(referenceOrbit, builder, positionScale, propagationType, stateType,
  82.                 InertialProvider.of(referenceOrbit.getFrame()));
  83.     }

  84.     /** Build a new instance.
  85.      * <p>
  86.      * The reference orbit is used as a model to {@link
  87.      * #createInitialOrbit() create initial orbit}. It defines the
  88.      * inertial frame, the central attraction coefficient, and is also used together
  89.      * with the {@code positionScale} to convert from the {@link
  90.      * ParameterDriver#setNormalizedValue(double) normalized} parameters used by the
  91.      * callers of this builder to the real orbital parameters.
  92.      * </p>
  93.      * @param referenceOrbit reference orbit from which real orbits will be built
  94.      * @param builder first order integrator builder
  95.      * @param positionScale scaling factor used for orbital parameters normalization
  96.      * (typically set to the expected standard deviation of the position)
  97.      * @param propagationType type of the orbit used for the propagation (mean or osculating)
  98.      * @param stateType type of the elements used to define the orbital state (mean or osculating)
  99.      * @param attitudeProvider attitude law.
  100.      * @since 10.1
  101.      */
  102.     public DSSTPropagatorBuilder(final Orbit referenceOrbit,
  103.                                  final ODEIntegratorBuilder builder,
  104.                                  final double positionScale,
  105.                                  final PropagationType propagationType,
  106.                                  final PropagationType stateType,
  107.                                  final AttitudeProvider attitudeProvider) {
  108.         super(referenceOrbit, PositionAngle.MEAN, positionScale, true, attitudeProvider);
  109.         this.builder           = builder;
  110.         this.forceModels       = new ArrayList<DSSTForceModel>();
  111.         this.mass              = Propagator.DEFAULT_MASS;
  112.         this.propagationType   = propagationType;
  113.         this.stateType         = stateType;
  114.     }

  115.     /** Get the type of the orbit used for the propagation (mean or osculating).
  116.      * @return the type of the orbit used for the propagation
  117.      */
  118.     public PropagationType getPropagationType() {
  119.         return propagationType;
  120.     }

  121.     /** Get the type of the elements used to define the orbital state (mean or osculating).
  122.      * @return the type of the elements used to define the orbital state
  123.      */
  124.     public PropagationType getStateType() {
  125.         return stateType;
  126.     }

  127.     /** Create a copy of a DSSTPropagatorBuilder object.
  128.      * @return Copied version of the DSSTPropagatorBuilder
  129.      */
  130.     public DSSTPropagatorBuilder copy() {
  131.         final DSSTPropagatorBuilder copyBuilder =
  132.                         new DSSTPropagatorBuilder((EquinoctialOrbit) OrbitType.EQUINOCTIAL.convertType(createInitialOrbit()),
  133.                                                   builder,
  134.                                                   getPositionScale(),
  135.                                                   propagationType,
  136.                                                   stateType,
  137.                                                   getAttitudeProvider());
  138.         copyBuilder.setMass(mass);
  139.         for (DSSTForceModel model : forceModels) {
  140.             copyBuilder.addForceModel(model);
  141.         }
  142.         return copyBuilder;
  143.     }

  144.     /** Get the integrator builder.
  145.      * @return the integrator builder
  146.      */
  147.     public ODEIntegratorBuilder getIntegratorBuilder()
  148.     {
  149.         return builder;
  150.     }

  151.     /** Get the list of all force models.
  152.      * @return the list of all force models
  153.      */
  154.     public List<DSSTForceModel> getAllForceModels()
  155.     {
  156.         return Collections.unmodifiableList(forceModels);
  157.     }

  158.     /** Get the mass.
  159.      * @return the mass
  160.      */
  161.     public double getMass()
  162.     {
  163.         return mass;
  164.     }

  165.     /** Set the initial mass.
  166.      * @param mass the mass (kg)
  167.      */
  168.     public void setMass(final double mass) {
  169.         this.mass = mass;
  170.     }

  171.     /** Add a force model to the global perturbation model.
  172.      * <p>If this method is not called at all, the integrated orbit will follow
  173.      * a Keplerian evolution only.</p>
  174.      * @param model perturbing {@link DSSTForceModel} to add
  175.      */
  176.     public void addForceModel(final DSSTForceModel model) {
  177.         if (model instanceof DSSTNewtonianAttraction) {
  178.             // we want to add the central attraction force model
  179.             if (hasNewtonianAttraction()) {
  180.                 // there is already a central attraction model, replace it
  181.                 forceModels.set(forceModels.size() - 1, model);
  182.             } else {
  183.                 // there are no central attraction model yet, add it at the end of the list
  184.                 forceModels.add(model);
  185.             }
  186.         } else {
  187.             // we want to add a perturbing force model
  188.             if (hasNewtonianAttraction()) {
  189.                 // insert the new force model before Newtonian attraction,
  190.                 // which should always be the last one in the list
  191.                 forceModels.add(forceModels.size() - 1, model);
  192.             } else {
  193.                 // we only have perturbing force models up to now, just append at the end of the list
  194.                 forceModels.add(model);
  195.             }
  196.         }

  197.         for (final ParameterDriver driver : model.getParametersDrivers()) {
  198.             addSupportedParameter(driver);
  199.         }
  200.     }

  201.     /** Reset the orbit in the propagator builder.
  202.      * @param newOrbit newOrbit New orbit to set in the propagator builder
  203.      * @param orbitType orbit type (MEAN or OSCULATING)
  204.      */
  205.     public void resetOrbit(final Orbit newOrbit, final PropagationType orbitType) {
  206.         this.stateType = orbitType;
  207.         super.resetOrbit(newOrbit);
  208.     }

  209.     /** {@inheritDoc} */
  210.     @SuppressWarnings("deprecation")
  211.     public DSSTPropagator buildPropagator(final double[] normalizedParameters) {

  212.         setParameters(normalizedParameters);
  213.         final EquinoctialOrbit orbit    = (EquinoctialOrbit) OrbitType.EQUINOCTIAL.convertType(createInitialOrbit());
  214.         final Attitude         attitude = getAttitudeProvider().getAttitude(orbit, orbit.getDate(), getFrame());
  215.         final SpacecraftState  state    = new SpacecraftState(orbit, attitude, mass);

  216.         final DSSTPropagator propagator = new DSSTPropagator(
  217.                 builder.buildIntegrator(orbit, OrbitType.EQUINOCTIAL),
  218.                 propagationType,
  219.                 getAttitudeProvider());

  220.         // Configure force models
  221.         if (!hasNewtonianAttraction()) {
  222.             // There are no central attraction model yet, add it at the end of the list
  223.             addForceModel(new DSSTNewtonianAttraction(orbit.getMu()));
  224.         }
  225.         for (DSSTForceModel model : forceModels) {
  226.             propagator.addForceModel(model);
  227.         }

  228.         propagator.setInitialState(state, stateType);

  229.         // Add additional derivatives providers to the propagator
  230.         for (AdditionalDerivativesProvider provider: getAdditionalDerivativesProviders()) {
  231.             propagator.addAdditionalDerivativesProvider(provider);
  232.         }

  233.         // FIXME: remove in 12.0 when AdditionalEquations is removed
  234.         for (org.orekit.propagation.integration.AdditionalEquations equations : getAdditionalEquations()) {
  235.             propagator.addAdditionalDerivativesProvider(new org.orekit.propagation.integration.AdditionalEquationsAdapter(equations, propagator::getInitialState));
  236.         }

  237.         return propagator;

  238.     }

  239.     /** {@inheritDoc} */
  240.     @Override
  241.     public DSSTBatchLSModel buildLSModel(final OrbitDeterminationPropagatorBuilder[] builders,
  242.                                 final List<ObservedMeasurement<?>> measurements,
  243.                                 final ParameterDriversList estimatedMeasurementsParameters,
  244.                                 final ModelObserver observer) {
  245.         return new DSSTBatchLSModel(builders,
  246.                                     measurements,
  247.                                     estimatedMeasurementsParameters,
  248.                                     observer,
  249.                                     propagationType, stateType);
  250.     }

  251.     /** {@inheritDoc} */
  252.     @Override
  253.     @SuppressWarnings("deprecation")
  254.     public AbstractKalmanModel buildKalmanModel(final List<OrbitDeterminationPropagatorBuilder> propagatorBuilders,
  255.                                                 final List<CovarianceMatrixProvider> covarianceMatricesProviders,
  256.                                                 final ParameterDriversList estimatedMeasurementsParameters,
  257.                                                 final CovarianceMatrixProvider measurementProcessNoiseMatrix) {
  258.         // FIXME: remove in 12.0 when DSSTKalmanModel is removed
  259.         return new org.orekit.estimation.sequential.DSSTKalmanModel(propagatorBuilders,
  260.                                                                     covarianceMatricesProviders,
  261.                                                                     estimatedMeasurementsParameters,
  262.                                                                     measurementProcessNoiseMatrix,
  263.                                                                     propagationType, stateType);
  264.     }

  265.     /** Check if Newtonian attraction force model is available.
  266.      * <p>
  267.      * Newtonian attraction is always the last force model in the list.
  268.      * </p>
  269.      * @return true if Newtonian attraction force model is available
  270.      */
  271.     private boolean hasNewtonianAttraction() {
  272.         final int last = forceModels.size() - 1;
  273.         return last >= 0 && forceModels.get(last) instanceof DSSTNewtonianAttraction;
  274.     }

  275. }