HarmonicParametricAcceleration.java

  1. /* Copyright 2002-2018 CS Systèmes d'Information
  2.  * Licensed to CS Systèmes d'Information (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.forces;

  18. import org.hipparchus.RealFieldElement;
  19. import org.hipparchus.geometry.euclidean.threed.Vector3D;
  20. import org.hipparchus.util.FastMath;
  21. import org.hipparchus.util.MathUtils;
  22. import org.orekit.attitudes.AttitudeProvider;
  23. import org.orekit.errors.OrekitException;
  24. import org.orekit.errors.OrekitInternalError;
  25. import org.orekit.propagation.FieldSpacecraftState;
  26. import org.orekit.propagation.SpacecraftState;
  27. import org.orekit.time.AbsoluteDate;
  28. import org.orekit.utils.ParameterDriver;

  29. /** This class implements a {@link AbstractParametricAcceleration parametric acceleration}
  30.  * with harmonic signed amplitude.
  31.  * @since 9.0
  32.  * @author Luc Maisonobe
  33.  */
  34. public class HarmonicParametricAcceleration extends AbstractParametricAcceleration {

  35.     /** Amplitude scaling factor.
  36.      * <p>
  37.      * 2⁻²⁰ is the order of magnitude of third body perturbing acceleration.
  38.      * </p>
  39.      * <p>
  40.      * We use a power of 2 to avoid numeric noise introduction
  41.      * in the multiplications/divisions sequences.
  42.      * </p>
  43.      */
  44.     private static final double AMPLITUDE_SCALE = FastMath.scalb(1.0, -20);

  45.     /** Phase scaling factor.
  46.      * <p>
  47.      * 2⁻²³ is the order of magnitude of an angle corresponding to one meter along
  48.      * track for a Low Earth Orbiting satellite.
  49.      * </p>
  50.      * <p>
  51.      * We use a power of 2 to avoid numeric noise introduction
  52.      * in the multiplications/divisions sequences.
  53.      * </p>
  54.      */
  55.     private static final double PHASE_SCALE = FastMath.scalb(1.0, -23);

  56.     /** Drivers for the parameters. */
  57.     private final ParameterDriver[] drivers;

  58.     /** Reference date for computing phase. */
  59.     private AbsoluteDate referenceDate;

  60.     /** Angular frequency ω = 2kπ/T. */
  61.     private final double omega;

  62.     /** Simple constructor.
  63.      * <p>
  64.      * The signed amplitude of the acceleration is γ sin[2kπ(t-t₀)/T + φ], where
  65.      * γ is parameter {@code 0} and represents the full amplitude, t is current
  66.      * date, t₀ is reference date, {@code T} is fundamental period, {@code k} is
  67.      * harmonic multiplier, and φ is parameter {@code 1} and represents phase at t₀.
  68.      * The value t-t₀ is in seconds.
  69.      * </p>
  70.      * <p>
  71.      * The fundamental period {@code T} is often set to the Keplerian period of the
  72.      * orbit and the harmonic multiplier {@code k} is often set to 1 or 2. The model
  73.      * has two parameters, one for the full amplitude and one for the phase at reference
  74.      * date.
  75.      * </p>
  76.      * <p>
  77.      * The two parameters for this model are the full amplitude (parameter 0) and the
  78.      * phase at reference date (parameter 1). Their reference values (used also as the
  79.      * initial values) are both set to 0. User can change them before starting the
  80.      * propagation (or orbit determination) by calling {@link #getParametersDrivers()}
  81.      * and {@link ParameterDriver#setValue(double)}.
  82.      * </p>
  83.      * @param direction acceleration direction in defining frame
  84.      * @param isInertial if true, direction is defined in the same inertial
  85.      * frame used for propagation (i.e. {@link SpacecraftState#getFrame()}),
  86.      * otherwise direction is defined in spacecraft frame (i.e. using the
  87.      * propagation {@link
  88.      * org.orekit.propagation.Propagator#setAttitudeProvider(AttitudeProvider)
  89.      * attitude law})
  90.      * @param prefix prefix to use for parameter drivers
  91.      * @param referenceDate reference date for computing phase, if null
  92.      * the reference date will be automatically set at propagation start
  93.      * @param fundamentalPeriod fundamental period (typically set to initial orbit
  94.      * {@link org.orekit.orbits.Orbit#getKeplerianPeriod() Keplerian period})
  95.      * @param harmonicMultiplier multiplier to compute harmonic period from
  96.      * fundamental period)
  97.      */
  98.     public HarmonicParametricAcceleration(final Vector3D direction, final boolean isInertial,
  99.                                           final String prefix, final AbsoluteDate referenceDate,
  100.                                           final double fundamentalPeriod, final int harmonicMultiplier) {
  101.         this(direction, isInertial, null, prefix, referenceDate,
  102.              fundamentalPeriod, harmonicMultiplier);
  103.     }

  104.     /** Simple constructor.
  105.      * <p>
  106.      * The signed amplitude of the acceleration is γ sin[2kπ(t-t₀)/T + φ], where
  107.      * γ is parameter {@code 0} and represents the full amplitude, t is current
  108.      * date, t₀ is reference date, {@code T} is fundamental period, {@code k} is
  109.      * harmonic multiplier, and φ is parameter {@code 1} and represents phase at t₀.
  110.      * The value t-t₀ is in seconds.
  111.      * </p>
  112.      * <p>
  113.      * The fundamental period {@code T} is often set to the Keplerian period of the
  114.      * orbit and the harmonic multiplier {@code k} is often set to 1 or 2. The model
  115.      * has two parameters, one for the full amplitude and one for the phase at reference
  116.      * date.
  117.      * </p>
  118.      * <p>
  119.      * The two parameters for this model are the full amplitude (parameter 0) and the
  120.      * phase at reference date (parameter 1). Their reference values (used also as the
  121.      * initial values) are both set to 0. User can change them before starting the
  122.      * propagation (or orbit determination) by calling {@link #getParametersDrivers()}
  123.      * and {@link ParameterDriver#setValue(double)}.
  124.      * </p>
  125.      * @param direction acceleration direction in overridden spacecraft frame
  126.      * @param attitudeOverride provider for attitude used to compute acceleration
  127.      * direction
  128.      * @param prefix prefix to use for parameter drivers
  129.      * @param referenceDate reference date for computing phase, if null
  130.      * the reference date will be automatically set at propagation start
  131.      * @param fundamentalPeriod fundamental period (typically set to initial orbit
  132.      * {@link org.orekit.orbits.Orbit#getKeplerianPeriod() Keplerian period})
  133.      * @param harmonicMultiplier multiplier to compute harmonic period from
  134.      * fundamental period)
  135.      */
  136.     public HarmonicParametricAcceleration(final Vector3D direction, final AttitudeProvider attitudeOverride,
  137.                                           final String prefix, final AbsoluteDate referenceDate,
  138.                                           final double fundamentalPeriod, final int harmonicMultiplier) {
  139.         this(direction, false, attitudeOverride, prefix, referenceDate,
  140.              fundamentalPeriod, harmonicMultiplier);
  141.     }

  142.     /** Simple constructor.
  143.      * @param direction acceleration direction in overridden spacecraft frame
  144.      * @param isInertial if true, direction is defined in the same inertial
  145.      * frame used for propagation (i.e. {@link SpacecraftState#getFrame()}),
  146.      * otherwise direction is defined in spacecraft frame (i.e. using the
  147.      * propagation {@link
  148.      * org.orekit.propagation.Propagator#setAttitudeProvider(AttitudeProvider)
  149.      * attitude law})
  150.      * @param attitudeOverride provider for attitude used to compute acceleration
  151.      * direction
  152.      * @param prefix prefix to use for parameter drivers
  153.      * @param referenceDate reference date for computing polynomials, if null
  154.      * the reference date will be automatically set at propagation start
  155.      * @param fundamentalPeriod fundamental period (typically set to initial orbit
  156.      * {@link org.orekit.orbits.Orbit#getKeplerianPeriod() Keplerian period})
  157.      * @param harmonicMultiplier multiplier to compute harmonic period from
  158.      * fundamental period)
  159.      */
  160.     private HarmonicParametricAcceleration(final Vector3D direction, final boolean isInertial,
  161.                                            final AttitudeProvider attitudeOverride,
  162.                                            final String prefix, final AbsoluteDate referenceDate,
  163.                                            final double fundamentalPeriod, final int harmonicMultiplier) {
  164.         super(direction, isInertial, attitudeOverride);
  165.         this.referenceDate = referenceDate;
  166.         this.omega         = harmonicMultiplier * MathUtils.TWO_PI / fundamentalPeriod;
  167.         try {
  168.             drivers = new ParameterDriver[] {
  169.                 new ParameterDriver(prefix + " γ",
  170.                                     0.0, AMPLITUDE_SCALE, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY),
  171.                 new ParameterDriver(prefix + " φ",
  172.                                     0.0, PHASE_SCALE, -MathUtils.TWO_PI, MathUtils.TWO_PI),
  173.             };
  174.         } catch (OrekitException oe) {
  175.             // this should never happen as scales are hard-coded
  176.             throw new OrekitInternalError(oe);
  177.         }
  178.     }

  179.     /** {@inheritDoc} */
  180.     @Override
  181.     public boolean dependsOnPositionOnly() {
  182.         return isInertial();
  183.     }

  184.     /** {@inheritDoc} */
  185.     @Override
  186.     public void init(final SpacecraftState initialState, final AbsoluteDate target)
  187.         throws OrekitException {
  188.         if (referenceDate == null) {
  189.             referenceDate = initialState.getDate();
  190.         }
  191.     }

  192.     /** {@inheritDoc}.
  193.      * The signed amplitude of the acceleration is γ sin[2kπ(t-t₀)/T + φ], where
  194.      * γ is parameter {@code 0} and represents the full amplitude, t is current
  195.      * date, t₀ is reference date, {@code T} is fundamental period, {@code k} is
  196.      * harmonic multiplier, and φ is parameter {@code 1} and represents phase at t₀.
  197.      * The value t-t₀ is in seconds.
  198.      */
  199.     @Override
  200.     protected double signedAmplitude(final SpacecraftState state, final double[] parameters) {
  201.         final double dt = state.getDate().durationFrom(referenceDate);
  202.         return parameters[0] * FastMath.sin(dt * omega + parameters[1]);
  203.     }

  204.     /** {@inheritDoc}
  205.      * The signed amplitude of the acceleration is γ sin[2kπ(t-t₀)/T + φ], where
  206.      * γ is parameter {@code 0} and represents the full amplitude, t is current
  207.      * date, t₀ is reference date, {@code T} is fundamental period, {@code k} is
  208.      * harmonic multiplier, and φ is parameter {@code 1} and represents phase at t₀.
  209.      * The value t-t₀ is in seconds.
  210.      */
  211.     @Override
  212.     protected <T extends RealFieldElement<T>> T signedAmplitude(final FieldSpacecraftState<T> state, final T[] parameters) {
  213.         final T dt = state.getDate().durationFrom(referenceDate);
  214.         return parameters[0].multiply(dt.multiply(omega).add(parameters[1]).sin());
  215.     }

  216.     /** {@inheritDoc} */
  217.     @Override
  218.     public ParameterDriver[] getParametersDrivers() {
  219.         return drivers.clone();
  220.     }

  221. }