AbstractMeasurement.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.estimation.measurements;

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

  21. import org.hipparchus.CalculusFieldElement;
  22. import org.hipparchus.analysis.differentiation.Gradient;
  23. import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
  24. import org.hipparchus.geometry.euclidean.threed.Vector3D;
  25. import org.hipparchus.util.FastMath;
  26. import org.orekit.propagation.SpacecraftState;
  27. import org.orekit.time.AbsoluteDate;
  28. import org.orekit.time.FieldAbsoluteDate;
  29. import org.orekit.utils.Constants;
  30. import org.orekit.utils.ParameterDriver;
  31. import org.orekit.utils.TimeStampedFieldPVCoordinates;
  32. import org.orekit.utils.TimeStampedPVCoordinates;

  33. /** Abstract class handling measurements boilerplate.
  34.  * @param <T> the type of the measurement
  35.  * @author Luc Maisonobe
  36.  * @since 8.0
  37.  */
  38. public abstract class AbstractMeasurement<T extends ObservedMeasurement<T>>
  39.     implements ObservedMeasurement<T> {

  40.     /** List of the supported parameters. */
  41.     private final List<ParameterDriver> supportedParameters;

  42.     /** Satellites related to this measurement.
  43.      * @since 9.3
  44.      */
  45.     private final List<ObservableSatellite> satellites;

  46.     /** Date of the measurement. */
  47.     private final AbsoluteDate date;

  48.     /** Observed value. */
  49.     private final double[] observed;

  50.     /** Theoretical standard deviation. */
  51.     private final double[] sigma;

  52.     /** Base weight. */
  53.     private final double[] baseWeight;

  54.     /** Modifiers that apply to the measurement.*/
  55.     private final List<EstimationModifier<T>> modifiers;

  56.     /** Enabling status. */
  57.     private boolean enabled;

  58.     /** Simple constructor for mono-dimensional measurements.
  59.      * <p>
  60.      * At construction, a measurement is enabled.
  61.      * </p>
  62.      * @param date date of the measurement
  63.      * @param observed observed value
  64.      * @param sigma theoretical standard deviation
  65.      * @param baseWeight base weight
  66.      * @param satellites satellites related to this measurement
  67.      * @since 9.3
  68.      */
  69.     protected AbstractMeasurement(final AbsoluteDate date, final double observed,
  70.                                   final double sigma, final double baseWeight,
  71.                                   final List<ObservableSatellite> satellites) {

  72.         this.supportedParameters = new ArrayList<ParameterDriver>();

  73.         this.date       = date;
  74.         this.observed   = new double[] {
  75.             observed
  76.         };
  77.         this.sigma      = new double[] {
  78.             sigma
  79.         };
  80.         this.baseWeight = new double[] {
  81.             baseWeight
  82.         };

  83.         this.satellites = satellites;

  84.         this.modifiers = new ArrayList<EstimationModifier<T>>();
  85.         setEnabled(true);

  86.     }

  87.     /** Simple constructor, for multi-dimensional measurements.
  88.      * <p>
  89.      * At construction, a measurement is enabled.
  90.      * </p>
  91.      * @param date date of the measurement
  92.      * @param observed observed value
  93.      * @param sigma theoretical standard deviation
  94.      * @param baseWeight base weight
  95.      * @param satellites satellites related to this measurement
  96.      * @since 9.3
  97.      */
  98.     protected AbstractMeasurement(final AbsoluteDate date, final double[] observed,
  99.                                   final double[] sigma, final double[] baseWeight,
  100.                                   final List<ObservableSatellite> satellites) {
  101.         this.supportedParameters = new ArrayList<ParameterDriver>();

  102.         this.date       = date;
  103.         this.observed   = observed.clone();
  104.         this.sigma      = sigma.clone();
  105.         this.baseWeight = baseWeight.clone();

  106.         this.satellites = satellites;

  107.         this.modifiers = new ArrayList<EstimationModifier<T>>();
  108.         setEnabled(true);

  109.     }

  110.     /** Add a parameter driver.
  111.      * @param driver parameter driver to add
  112.      * @since 9.3
  113.      */
  114.     protected void addParameterDriver(final ParameterDriver driver) {
  115.         supportedParameters.add(driver);
  116.     }

  117.     /** {@inheritDoc} */
  118.     @Override
  119.     public List<ParameterDriver> getParametersDrivers() {
  120.         return Collections.unmodifiableList(supportedParameters);
  121.     }

  122.     /** {@inheritDoc} */
  123.     @Override
  124.     public void setEnabled(final boolean enabled) {
  125.         this.enabled = enabled;
  126.     }

  127.     /** {@inheritDoc} */
  128.     @Override
  129.     public boolean isEnabled() {
  130.         return enabled;
  131.     }

  132.     /** {@inheritDoc} */
  133.     @Override
  134.     public int getDimension() {
  135.         return observed.length;
  136.     }

  137.     /** {@inheritDoc} */
  138.     @Override
  139.     public double[] getTheoreticalStandardDeviation() {
  140.         return sigma.clone();
  141.     }

  142.     /** {@inheritDoc} */
  143.     @Override
  144.     public double[] getBaseWeight() {
  145.         return baseWeight.clone();
  146.     }

  147.     /** {@inheritDoc} */
  148.     @Override
  149.     public List<ObservableSatellite> getSatellites() {
  150.         return satellites;
  151.     }

  152.     /** Estimate the theoretical value.
  153.      * <p>
  154.      * The theoretical value does not have <em>any</em> modifiers applied.
  155.      * </p>
  156.      * @param iteration iteration number
  157.      * @param evaluation evaluation number
  158.      * @param states orbital states at measurement date
  159.      * @return theoretical value
  160.      * @see #estimate(int, int, SpacecraftState[])
  161.      */
  162.     protected abstract EstimatedMeasurement<T> theoreticalEvaluation(int iteration, int evaluation, SpacecraftState[] states);

  163.     /** {@inheritDoc} */
  164.     @Override
  165.     public EstimatedMeasurement<T> estimate(final int iteration, final int evaluation, final SpacecraftState[] states) {

  166.         // compute the theoretical value
  167.         final EstimatedMeasurement<T> estimation = theoreticalEvaluation(iteration, evaluation, states);

  168.         // apply the modifiers
  169.         for (final EstimationModifier<T> modifier : modifiers) {
  170.             modifier.modify(estimation);
  171.         }

  172.         return estimation;

  173.     }

  174.     /** {@inheritDoc} */
  175.     @Override
  176.     public AbsoluteDate getDate() {
  177.         return date;
  178.     }

  179.     /** {@inheritDoc} */
  180.     @Override
  181.     public double[] getObservedValue() {
  182.         return observed.clone();
  183.     }

  184.     /** {@inheritDoc} */
  185.     @Override
  186.     public void addModifier(final EstimationModifier<T> modifier) {

  187.         // combine the measurement parameters and the modifier parameters
  188.         supportedParameters.addAll(modifier.getParametersDrivers());

  189.         modifiers.add(modifier);

  190.     }

  191.     /** {@inheritDoc} */
  192.     @Override
  193.     public List<EstimationModifier<T>> getModifiers() {
  194.         return Collections.unmodifiableList(modifiers);
  195.     }

  196.     /** Compute propagation delay on a link leg (typically downlink or uplink).
  197.      * @param adjustableEmitterPV position/velocity of emitter that may be adjusted
  198.      * @param receiverPosition fixed position of receiver at {@code signalArrivalDate},
  199.      * in the same frame as {@code adjustableEmitterPV}
  200.      * @param signalArrivalDate date at which the signal arrives to receiver
  201.      * @return <em>positive</em> delay between signal emission and signal reception dates
  202.      */
  203.     public static double signalTimeOfFlight(final TimeStampedPVCoordinates adjustableEmitterPV,
  204.                                             final Vector3D receiverPosition,
  205.                                             final AbsoluteDate signalArrivalDate) {

  206.         // initialize emission date search loop assuming the state is already correct
  207.         // this will be true for all but the first orbit determination iteration,
  208.         // and even for the first iteration the loop will converge very fast
  209.         final double offset = signalArrivalDate.durationFrom(adjustableEmitterPV.getDate());
  210.         double delay = offset;

  211.         // search signal transit date, computing the signal travel in inertial frame
  212.         final double cReciprocal = 1.0 / Constants.SPEED_OF_LIGHT;
  213.         double delta;
  214.         int count = 0;
  215.         do {
  216.             final double previous   = delay;
  217.             final Vector3D transitP = adjustableEmitterPV.shiftedBy(offset - delay).getPosition();
  218.             delay                   = receiverPosition.distance(transitP) * cReciprocal;
  219.             delta                   = FastMath.abs(delay - previous);
  220.         } while (count++ < 10 && delta >= 2 * FastMath.ulp(delay));

  221.         return delay;

  222.     }

  223.     /** Compute propagation delay on a link leg (typically downlink or uplink).
  224.      * @param adjustableEmitterPV position/velocity of emitter that may be adjusted
  225.      * @param receiverPosition fixed position of receiver at {@code signalArrivalDate},
  226.      * in the same frame as {@code adjustableEmitterPV}
  227.      * @param signalArrivalDate date at which the signal arrives to receiver
  228.      * @return <em>positive</em> delay between signal emission and signal reception dates
  229.      * @param <T> the type of the components
  230.      */
  231.     public static <T extends CalculusFieldElement<T>> T signalTimeOfFlight(final TimeStampedFieldPVCoordinates<T> adjustableEmitterPV,
  232.                                                                        final FieldVector3D<T> receiverPosition,
  233.                                                                        final FieldAbsoluteDate<T> signalArrivalDate) {

  234.         // Initialize emission date search loop assuming the emitter PV is almost correct
  235.         // this will be true for all but the first orbit determination iteration,
  236.         // and even for the first iteration the loop will converge extremely fast
  237.         final T offset = signalArrivalDate.durationFrom(adjustableEmitterPV.getDate());
  238.         T delay = offset;

  239.         // search signal transit date, computing the signal travel in the frame shared by emitter and receiver
  240.         final double cReciprocal = 1.0 / Constants.SPEED_OF_LIGHT;
  241.         double delta;
  242.         int count = 0;
  243.         do {
  244.             final double previous           = delay.getReal();
  245.             final FieldVector3D<T> transitP = adjustableEmitterPV.shiftedBy(delay.negate().add(offset)).getPosition();
  246.             delay                           = receiverPosition.distance(transitP).multiply(cReciprocal);
  247.             delta                           = FastMath.abs(delay.getReal() - previous);
  248.         } while (count++ < 10 && delta >= 2 * FastMath.ulp(delay.getReal()));

  249.         return delay;

  250.     }

  251.     /** Get Cartesian coordinates as derivatives.
  252.      * <p>
  253.      * The position will correspond to variables {@code firstDerivative},
  254.      * {@code firstDerivative + 1} and {@code firstDerivative + 2}.
  255.      * The velocity will correspond to variables {@code firstDerivative + 3},
  256.      * {@code firstDerivative + 4} and {@code firstDerivative + 5}.
  257.      * The acceleration will correspond to constants.
  258.      * </p>
  259.      * @param state state of the satellite considered
  260.      * @param firstDerivative index of the first derivative
  261.      * @param freeParameters total number of free parameters in the gradient
  262.      * @return Cartesian coordinates as derivatives
  263.      * @since 10.2
  264.      */
  265.     public static TimeStampedFieldPVCoordinates<Gradient> getCoordinates(final SpacecraftState state,
  266.                                                                          final int firstDerivative,
  267.                                                                          final int freeParameters) {

  268.         // Position of the satellite expressed as a gradient
  269.         // The components of the position are the 3 first derivative parameters
  270.         final Vector3D p = state.getPVCoordinates().getPosition();
  271.         final FieldVector3D<Gradient> pDS =
  272.                         new FieldVector3D<>(Gradient.variable(freeParameters, firstDerivative + 0, p.getX()),
  273.                                             Gradient.variable(freeParameters, firstDerivative + 1, p.getY()),
  274.                                             Gradient.variable(freeParameters, firstDerivative + 2, p.getZ()));

  275.         // Velocity of the satellite expressed as a gradient
  276.         // The components of the velocity are the 3 second derivative parameters
  277.         final Vector3D v = state.getPVCoordinates().getVelocity();
  278.         final FieldVector3D<Gradient> vDS =
  279.                         new FieldVector3D<>(Gradient.variable(freeParameters, firstDerivative + 3, v.getX()),
  280.                                             Gradient.variable(freeParameters, firstDerivative + 4, v.getY()),
  281.                                             Gradient.variable(freeParameters, firstDerivative + 5, v.getZ()));

  282.         // Acceleration of the satellite
  283.         // The components of the acceleration are not derivative parameters
  284.         final Vector3D a = state.getPVCoordinates().getAcceleration();
  285.         final FieldVector3D<Gradient> aDS =
  286.                         new FieldVector3D<>(Gradient.constant(freeParameters, a.getX()),
  287.                                             Gradient.constant(freeParameters, a.getY()),
  288.                                             Gradient.constant(freeParameters, a.getZ()));

  289.         return new TimeStampedFieldPVCoordinates<>(state.getDate(), pDS, vDS, aDS);

  290.     }

  291. }