BrouwerLyddanePropagatorBuilder.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.List;

  19. import org.hipparchus.util.FastMath;
  20. import org.orekit.attitudes.AttitudeProvider;
  21. import org.orekit.attitudes.InertialProvider;
  22. import org.orekit.estimation.leastsquares.AbstractBatchLSModel;
  23. import org.orekit.estimation.leastsquares.BatchLSModel;
  24. import org.orekit.estimation.leastsquares.ModelObserver;
  25. import org.orekit.estimation.measurements.ObservedMeasurement;
  26. import org.orekit.estimation.sequential.AbstractKalmanModel;
  27. import org.orekit.estimation.sequential.CovarianceMatrixProvider;
  28. import org.orekit.estimation.sequential.KalmanModel;
  29. import org.orekit.forces.gravity.potential.GravityFieldFactory;
  30. import org.orekit.forces.gravity.potential.TideSystem;
  31. import org.orekit.forces.gravity.potential.UnnormalizedSphericalHarmonicsProvider;
  32. import org.orekit.orbits.Orbit;
  33. import org.orekit.orbits.OrbitType;
  34. import org.orekit.orbits.PositionAngle;
  35. import org.orekit.propagation.analytical.BrouwerLyddanePropagator;
  36. import org.orekit.propagation.analytical.tle.TLE;
  37. import org.orekit.utils.ParameterDriver;
  38. import org.orekit.utils.ParameterDriversList;

  39. /** Builder for Brouwer-Lyddane propagator.
  40.  * <p>
  41.  * By default, Brouwer-Lyddane model considers only the perturbations due to zonal harmonics.
  42.  * However, for low Earth orbits, the magnitude of the perturbative acceleration due to
  43.  * atmospheric drag can be significant. Warren Phipps' 1992 thesis considered the atmospheric
  44.  * drag by time derivatives of the <i>mean</i> mean anomaly using the catch-all coefficient M2.
  45.  *
  46.  * Usually, M2 is adjusted during an orbit determination process and it represents the
  47.  * combination of all unmodeled secular along-track effects (i.e. not just the atmospheric drag).
  48.  * The behavior of M2 is closed to the {@link TLE#getBStar()} parameter for the TLE.
  49.  *
  50.  * If the value of M2 is equal to {@link BrouwerLyddanePropagator#M2 0.0}, the along-track
  51.  * secular effects are not considered in the dynamical model. Typical values for M2 are not known.
  52.  * It depends on the orbit type. However, the value of M2 must be very small (e.g. between 1.0e-14 and 1.0e-15).
  53.  * The unit of M2 is rad/s².
  54.  * <p>
  55.  * To estimate the M2 parameter, it is necessary to call the {@link #getPropagationParametersDrivers()} method
  56.  * as follow:
  57.  * <pre>
  58.  *  for (ParameterDriver driver : builder.getPropagationParametersDrivers().getDrivers()) {
  59.  *     if (BrouwerLyddanePropagator.M2_NAME.equals(driver.getName())) {
  60.  *        driver.setSelected(true);
  61.  *     }
  62.  *  }
  63.  * </pre>
  64.  * @author Melina Vanel
  65.  * @author Bryan Cazabonne
  66.  * @since 11.1
  67.  */
  68. public class BrouwerLyddanePropagatorBuilder extends AbstractPropagatorBuilder implements OrbitDeterminationPropagatorBuilder {

  69.     /** Parameters scaling factor.
  70.      * <p>
  71.      * We use a power of 2 to avoid numeric noise introduction
  72.      * in the multiplications/divisions sequences.
  73.      * </p>
  74.      */
  75.     private static final double SCALE = FastMath.scalb(1.0, -32);

  76.     /** Provider for un-normalized coefficients. */
  77.     private final UnnormalizedSphericalHarmonicsProvider provider;

  78.     /** Build a new instance.
  79.      * <p>
  80.      * The template orbit is used as a model to {@link
  81.      * #createInitialOrbit() create initial orbit}. It defines the
  82.      * inertial frame, the central attraction coefficient, the orbit type, and is also
  83.      * used together with the {@code positionScale} to convert from the {@link
  84.      * org.orekit.utils.ParameterDriver#setNormalizedValue(double) normalized} parameters used by the
  85.      * callers of this builder to the real orbital parameters.
  86.      * </p>
  87.      *
  88.      * @param templateOrbit reference orbit from which real orbits will be built
  89.      * (note that the mu from this orbit will be overridden with the mu from the
  90.      * {@code provider})
  91.      * @param provider for un-normalized zonal coefficients
  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 M2 value of empirical drag coefficient in rad/s².
  96.      *        If equal to {@link BrouwerLyddanePropagator#M2} drag is not computed
  97.      * @see #BrouwerLyddanePropagatorBuilder(Orbit,
  98.      * UnnormalizedSphericalHarmonicsProvider, PositionAngle, double, AttitudeProvider, double)
  99.      */
  100.     public BrouwerLyddanePropagatorBuilder(final Orbit templateOrbit,
  101.                                            final UnnormalizedSphericalHarmonicsProvider provider,
  102.                                            final PositionAngle positionAngle,
  103.                                            final double positionScale,
  104.                                            final double M2) {
  105.         this(templateOrbit, provider, positionAngle, positionScale, InertialProvider.of(templateOrbit.getFrame()), M2);
  106.     }

  107.     /** Build a new instance.
  108.      * <p>
  109.      * The template orbit is used as a model to {@link
  110.      * #createInitialOrbit() create initial orbit}. It defines the
  111.      * inertial frame, the central attraction coefficient, the orbit type, and is also
  112.      * used together with the {@code positionScale} to convert from the {@link
  113.      * org.orekit.utils.ParameterDriver#setNormalizedValue(double) normalized} parameters used by the
  114.      * callers of this builder to the real orbital parameters.
  115.      * </p>
  116.      *
  117.      * @param templateOrbit reference orbit from which real orbits will be built
  118.      * (note that the mu from this orbit will be overridden with the mu from the
  119.      * {@code provider})
  120.      * @param referenceRadius reference radius of the Earth for the potential model (m)
  121.      * @param mu central attraction coefficient (m³/s²)
  122.      * @param tideSystem tide system
  123.      * @param c20 un-normalized zonal coefficient (about -1.08e-3 for Earth)
  124.      * @param c30 un-normalized zonal coefficient (about +2.53e-6 for Earth)
  125.      * @param c40 un-normalized zonal coefficient (about +1.62e-6 for Earth)
  126.      * @param c50 un-normalized zonal coefficient (about +2.28e-7 for Earth)
  127.      * @param orbitType orbit type to use
  128.      * @param positionAngle position angle type to use
  129.      * @param positionScale scaling factor used for orbital parameters normalization
  130.      * (typically set to the expected standard deviation of the position)
  131.      * @param M2 value of empirical drag coefficient in rad/s².
  132.      *        If equal to {@link BrouwerLyddanePropagator#M2} drag is not computed
  133.      * @see #BrouwerLyddanePropagatorBuilder(Orbit,
  134.      * UnnormalizedSphericalHarmonicsProvider, PositionAngle, double, AttitudeProvider, double)
  135.      */
  136.     public BrouwerLyddanePropagatorBuilder(final Orbit templateOrbit,
  137.                                            final double referenceRadius,
  138.                                            final double mu,
  139.                                            final TideSystem tideSystem,
  140.                                            final double c20,
  141.                                            final double c30,
  142.                                            final double c40,
  143.                                            final double c50,
  144.                                            final OrbitType orbitType,
  145.                                            final PositionAngle positionAngle,
  146.                                            final double positionScale,
  147.                                            final double M2) {
  148.         this(templateOrbit,
  149.              GravityFieldFactory.getUnnormalizedProvider(referenceRadius, mu, tideSystem,
  150.                                                          new double[][] {
  151.                                                              {
  152.                                                                  0
  153.                                                              }, {
  154.                                                                  0
  155.                                                              }, {
  156.                                                                  c20
  157.                                                              }, {
  158.                                                                  c30
  159.                                                              }, {
  160.                                                                  c40
  161.                                                              }, {
  162.                                                                  c50
  163.                                                              }
  164.                                                          }, new double[][] {
  165.                                                              {
  166.                                                                  0
  167.                                                              }, {
  168.                                                                  0
  169.                                                              }, {
  170.                                                                  0
  171.                                                              }, {
  172.                                                                  0
  173.                                                              }, {
  174.                                                                  0
  175.                                                              }, {
  176.                                                                  0
  177.                                                              }
  178.                                                          }),
  179.              positionAngle, positionScale, M2);
  180.     }

  181.     /** Build a new instance.
  182.      * <p>
  183.      * The template orbit is used as a model to {@link
  184.      * #createInitialOrbit() create initial orbit}. It defines the
  185.      * inertial frame, the central attraction coefficient, the orbit type, and is also
  186.      * used together with the {@code positionScale} to convert from the {@link
  187.      * org.orekit.utils.ParameterDriver#setNormalizedValue(double) normalized} parameters used by the
  188.      * callers of this builder to the real orbital parameters.
  189.      * </p>
  190.      * @param templateOrbit reference orbit from which real orbits will be built
  191.      * (note that the mu from this orbit will be overridden with the mu from the
  192.      * {@code provider})
  193.      * @param provider for un-normalized zonal coefficients
  194.      * @param positionAngle position angle type to use
  195.      * @param positionScale scaling factor used for orbital parameters normalization
  196.      * (typically set to the expected standard deviation of the position)
  197.      * @param M2 value of empirical drag coefficient in rad/s².
  198.      *        If equal to {@link BrouwerLyddanePropagator#M2} drag is not computed
  199.      * @param attitudeProvider attitude law to use
  200.      */
  201.     public BrouwerLyddanePropagatorBuilder(final Orbit templateOrbit,
  202.                                            final UnnormalizedSphericalHarmonicsProvider provider,
  203.                                            final PositionAngle positionAngle,
  204.                                            final double positionScale,
  205.                                            final AttitudeProvider attitudeProvider,
  206.                                            final double M2) {
  207.         super(overrideMu(templateOrbit, provider, positionAngle), positionAngle, positionScale, true, attitudeProvider);
  208.         this.provider = provider;
  209.         // initialize M2 driver
  210.         final ParameterDriver M2Driver = new ParameterDriver(BrouwerLyddanePropagator.M2_NAME, M2, SCALE,
  211.                                                              Double.NEGATIVE_INFINITY,
  212.                                                              Double.POSITIVE_INFINITY);
  213.         addSupportedParameter(M2Driver);
  214.     }

  215.     /** Override central attraction coefficient.
  216.      * @param templateOrbit template orbit
  217.      * @param provider gravity field provider
  218.      * @param positionAngle position angle type to use
  219.      * @return orbit with overridden central attraction coefficient
  220.      */
  221.     private static Orbit overrideMu(final Orbit templateOrbit,
  222.                                     final UnnormalizedSphericalHarmonicsProvider provider,
  223.                                     final PositionAngle positionAngle) {
  224.         final double[] parameters    = new double[6];
  225.         final double[] parametersDot = templateOrbit.hasDerivatives() ? new double[6] : null;
  226.         templateOrbit.getType().mapOrbitToArray(templateOrbit, positionAngle, parameters, parametersDot);
  227.         return templateOrbit.getType().mapArrayToOrbit(parameters, parametersDot, positionAngle,
  228.                                                        templateOrbit.getDate(),
  229.                                                        provider.getMu(),
  230.                                                        templateOrbit.getFrame());
  231.     }

  232.     /** {@inheritDoc} */
  233.     public BrouwerLyddanePropagator buildPropagator(final double[] normalizedParameters) {
  234.         setParameters(normalizedParameters);

  235.         // Update M2 value and selection
  236.         double  newM2      = 0.0;
  237.         boolean isSelected = false;
  238.         for (final ParameterDriver driver : getPropagationParametersDrivers().getDrivers()) {
  239.             if (BrouwerLyddanePropagator.M2_NAME.equals(driver.getName())) {
  240.                 newM2      = driver.getValue();
  241.                 isSelected = driver.isSelected();
  242.             }
  243.         }

  244.         // Initialize propagator
  245.         final BrouwerLyddanePropagator propagator = new BrouwerLyddanePropagator(createInitialOrbit(), getAttitudeProvider(), provider, newM2);
  246.         propagator.getParametersDrivers().get(0).setSelected(isSelected);

  247.         // Return
  248.         return propagator;

  249.     }

  250.     /** {@inheritDoc} */
  251.     @Override
  252.     public AbstractBatchLSModel buildLSModel(final OrbitDeterminationPropagatorBuilder[] builders,
  253.                                              final List<ObservedMeasurement<?>> measurements,
  254.                                              final ParameterDriversList estimatedMeasurementsParameters,
  255.                                              final ModelObserver observer) {
  256.         return new BatchLSModel(builders, measurements, estimatedMeasurementsParameters, observer);
  257.     }

  258.     /** {@inheritDoc} */
  259.     @Override
  260.     public AbstractKalmanModel buildKalmanModel(final List<OrbitDeterminationPropagatorBuilder> propagatorBuilders,
  261.                                                 final List<CovarianceMatrixProvider> covarianceMatricesProviders,
  262.                                                 final ParameterDriversList estimatedMeasurementsParameters,
  263.                                                 final CovarianceMatrixProvider measurementProcessNoiseMatrix) {
  264.         return new KalmanModel(propagatorBuilders, covarianceMatricesProviders, estimatedMeasurementsParameters, measurementProcessNoiseMatrix);
  265.     }

  266. }