AbstractParametricAcceleration.java

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

  18. import java.util.stream.Stream;

  19. import org.hipparchus.Field;
  20. import org.hipparchus.RealFieldElement;
  21. import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
  22. import org.hipparchus.geometry.euclidean.threed.Vector3D;
  23. import org.orekit.attitudes.Attitude;
  24. import org.orekit.attitudes.AttitudeProvider;
  25. import org.orekit.attitudes.FieldAttitude;
  26. import org.orekit.propagation.FieldSpacecraftState;
  27. import org.orekit.propagation.SpacecraftState;
  28. import org.orekit.propagation.events.EventDetector;
  29. import org.orekit.propagation.events.FieldEventDetector;

  30. /** This class implements a parametric acceleration.
  31.  * <p>Parametric accelerations are intended to model lesser-known
  32.  * forces, estimating a few defining parameters from a parametric
  33.  * function using orbit determination. Typical parametric functions
  34.  * are polynomial (often limited to a constant term) and harmonic
  35.  * (often with either orbital period or half orbital period).</p>
  36.  * <p>An important operational example is the infamous GPS Y-bias,
  37.  * which is thought to be related to a radiator thermal radiation.
  38.  * Other examples could be to model leaks that produce roughly constant
  39.  * trust in some spacecraft-related direction.</p>
  40.  * <p>The acceleration direction is considered constant in either:
  41.  * </p>
  42.  * <ul>
  43.  *   <li>inertial frame</li>
  44.  *   <li>spacecraft frame</li>
  45.  *   <li>a dedicated attitude frame overriding spacecraft attitude
  46.  *   (this could for example be used to model solar arrays orientation
  47.  *   if the force is related to solar arrays)</li>
  48.  * </ul>
  49.  * <p>
  50.  * If the direction of the acceleration is unknown, then three instances
  51.  * of this class should be used, one along the X axis, one along the Y
  52.  * axis and one along the Z axis and their parameters estimated as usual.
  53.  * </p>
  54.  * @since 9.0
  55.  * @author Luc Maisonobe
  56.  */
  57. public abstract class AbstractParametricAcceleration extends AbstractForceModel {

  58.     /** Direction of the acceleration in defining frame. */
  59.     private final Vector3D direction;

  60.     /** Flag for inertial acceleration direction. */
  61.     private final boolean isInertial;

  62.     /** The attitude to override, if set. */
  63.     private final AttitudeProvider attitudeOverride;

  64.     /** Simple constructor.
  65.      * @param direction acceleration direction in overridden spacecraft frame
  66.      * @param isInertial if true, direction is defined in the same inertial
  67.      * frame used for propagation (i.e. {@link SpacecraftState#getFrame()}),
  68.      * otherwise direction is defined in spacecraft frame (i.e. using the
  69.      * propagation {@link
  70.      * org.orekit.propagation.Propagator#setAttitudeProvider(AttitudeProvider)
  71.      * attitude law})
  72.      * @param attitudeOverride provider for attitude used to compute acceleration
  73.      * direction
  74.      */
  75.     protected AbstractParametricAcceleration(final Vector3D direction,  final boolean isInertial,
  76.                                              final AttitudeProvider attitudeOverride) {
  77.         this.direction        = direction;
  78.         this.isInertial       = isInertial;
  79.         this.attitudeOverride = attitudeOverride;
  80.     }

  81.     /** Check if direction is inertial.
  82.      * @return true if direction is inertial
  83.      */
  84.     protected boolean isInertial() {
  85.         return isInertial;
  86.     }

  87.     /** Compute the signed amplitude of the acceleration.
  88.      * <p>
  89.      * The acceleration is the direction multiplied by the signed amplitude. So if
  90.      * signed amplitude is negative, the acceleratin is towards the opposite of the
  91.      * direction specified at construction.
  92.      * </p>
  93.      * @param state current state information: date, kinematics, attitude
  94.      * @param parameters values of the force model parameters
  95.      * @return norm of the acceleration
  96.      */
  97.     protected abstract double signedAmplitude(SpacecraftState state, double[] parameters);

  98.     /** Compute the signed amplitude of the acceleration.
  99.      * <p>
  100.      * The acceleration is the direction multiplied by the signed amplitude. So if
  101.      * signed amplitude is negative, the acceleratin is towards the opposite of the
  102.      * direction specified at construction.
  103.      * </p>
  104.      * @param state current state information: date, kinematics, attitude
  105.      * @param parameters values of the force model parameters
  106.      * @param <T> type of the elements
  107.      * @return norm of the acceleration
  108.      */
  109.     protected abstract <T extends RealFieldElement<T>> T signedAmplitude(FieldSpacecraftState<T> state, T[] parameters);

  110.     /** {@inheritDoc} */
  111.     @Override
  112.     public Vector3D acceleration(final SpacecraftState state, final double[] parameters) {

  113.         final Vector3D inertialDirection;
  114.         if (isInertial) {
  115.             // the acceleration direction is already defined in the inertial frame
  116.             inertialDirection = direction;
  117.         } else {
  118.             final Attitude attitude;
  119.             if (attitudeOverride == null) {
  120.                 // the acceleration direction is defined in spacecraft frame as set by the propagator
  121.                 attitude = state.getAttitude();
  122.             } else {
  123.                 // the acceleration direction is defined in a dedicated frame
  124.                 attitude = attitudeOverride.getAttitude(state.getOrbit(), state.getDate(), state.getFrame());
  125.             }
  126.             inertialDirection = attitude.getRotation().applyInverseTo(direction);
  127.         }

  128.         return new Vector3D(signedAmplitude(state, parameters), inertialDirection);

  129.     }

  130.     /** {@inheritDoc} */
  131.     @Override
  132.     public <T extends RealFieldElement<T>> FieldVector3D<T> acceleration(final FieldSpacecraftState<T> state,
  133.                                                                          final T[] parameters) {

  134.         final FieldVector3D<T> inertialDirection;
  135.         if (isInertial) {
  136.             // the acceleration direction is already defined in the inertial frame
  137.             inertialDirection = new FieldVector3D<>(state.getDate().getField(), direction);
  138.         } else {
  139.             final FieldAttitude<T> attitude;
  140.             if (attitudeOverride == null) {
  141.                 // the acceleration direction is defined in spacecraft frame as set by the propagator
  142.                 attitude = state.getAttitude();
  143.             } else {
  144.                 // the acceleration direction is defined in a dedicated frame
  145.                 attitude = attitudeOverride.getAttitude(state.getOrbit(), state.getDate(), state.getFrame());
  146.             }
  147.             inertialDirection = attitude.getRotation().applyInverseTo(direction);
  148.         }

  149.         return new FieldVector3D<>(signedAmplitude(state, parameters), inertialDirection);

  150.     }

  151.     /** {@inheritDoc} */
  152.     @Override
  153.     public Stream<EventDetector> getEventsDetectors() {
  154.         return Stream.empty();
  155.     }

  156.     /** {@inheritDoc} */
  157.     @Override
  158.     public <T extends RealFieldElement<T>> Stream<FieldEventDetector<T>> getFieldEventsDetectors(final Field<T> field) {
  159.         return Stream.empty();
  160.     }

  161. }