AbstractMeasurement.java

  1. /* Copyright 2002-2025 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.frames.Frame;
  27. import org.orekit.propagation.SpacecraftState;
  28. import org.orekit.time.AbsoluteDate;
  29. import org.orekit.time.FieldAbsoluteDate;
  30. import org.orekit.utils.Constants;
  31. import org.orekit.utils.FieldPVCoordinatesProvider;
  32. import org.orekit.utils.PVCoordinatesProvider;
  33. import org.orekit.utils.ParameterDriver;
  34. import org.orekit.utils.FieldShiftingPVCoordinatesProvider;
  35. import org.orekit.utils.ShiftingPVCoordinatesProvider;
  36. import org.orekit.utils.TimeStampedFieldPVCoordinates;
  37. import org.orekit.utils.TimeStampedPVCoordinates;

  38. /** Abstract class handling measurements boilerplate.
  39.  * @param <T> the type of the measurement
  40.  * @author Luc Maisonobe
  41.  * @since 8.0
  42.  */
  43. public abstract class AbstractMeasurement<T extends ObservedMeasurement<T>> implements ObservedMeasurement<T> {

  44.     /** List of the supported parameters. */
  45.     private final List<ParameterDriver> supportedParameters;

  46.     /** Satellites related to this measurement.
  47.      * @since 9.3
  48.      */
  49.     private final List<ObservableSatellite> satellites;

  50.     /** Date of the measurement. */
  51.     private final AbsoluteDate date;

  52.     /** Observed value. */
  53.     private double[] observed;

  54.     /** Theoretical standard deviation. */
  55.     private final double[] sigma;

  56.     /** Base weight. */
  57.     private final double[] baseWeight;

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

  60.     /** Enabling status. */
  61.     private boolean enabled;

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

  76.         this.supportedParameters = new ArrayList<>();

  77.         this.date       = date;
  78.         this.observed   = new double[] {
  79.             observed
  80.         };
  81.         this.sigma      = new double[] {
  82.             sigma
  83.         };
  84.         this.baseWeight = new double[] {
  85.             baseWeight
  86.         };

  87.         this.satellites = satellites;

  88.         this.modifiers = new ArrayList<>();
  89.         setEnabled(true);

  90.     }

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

  106.         this.date       = date;
  107.         this.observed   = observed.clone();
  108.         this.sigma      = sigma.clone();
  109.         this.baseWeight = baseWeight.clone();

  110.         this.satellites = satellites;

  111.         this.modifiers = new ArrayList<>();
  112.         setEnabled(true);

  113.     }

  114.     /** {@inheritDoc} */
  115.     @Override
  116.     public void setObservedValue(final double[] newObserved) {
  117.         this.observed = newObserved.clone();
  118.     }

  119.     /** Add a parameter driver.
  120.      * @param driver parameter driver to add
  121.      * @since 9.3
  122.      */
  123.     protected void addParameterDriver(final ParameterDriver driver) {
  124.         supportedParameters.add(driver);
  125.     }

  126.     /** {@inheritDoc} */
  127.     @Override
  128.     public List<ParameterDriver> getParametersDrivers() {
  129.         return Collections.unmodifiableList(supportedParameters);
  130.     }

  131.     /** {@inheritDoc} */
  132.     @Override
  133.     public void setEnabled(final boolean enabled) {
  134.         this.enabled = enabled;
  135.     }

  136.     /** {@inheritDoc} */
  137.     @Override
  138.     public boolean isEnabled() {
  139.         return enabled;
  140.     }

  141.     /** {@inheritDoc} */
  142.     @Override
  143.     public int getDimension() {
  144.         return observed.length;
  145.     }

  146.     /** {@inheritDoc} */
  147.     @Override
  148.     public double[] getTheoreticalStandardDeviation() {
  149.         return sigma.clone();
  150.     }

  151.     /** {@inheritDoc} */
  152.     @Override
  153.     public double[] getBaseWeight() {
  154.         return baseWeight.clone();
  155.     }

  156.     /** {@inheritDoc} */
  157.     @Override
  158.     public List<ObservableSatellite> getSatellites() {
  159.         return satellites;
  160.     }

  161.     /** Estimate the theoretical value without derivatives.
  162.      * The default implementation uses the computation with derivatives and ought to be overwritten for performance.
  163.      * <p>
  164.      * The theoretical value does not have <em>any</em> modifiers applied.
  165.      * </p>
  166.      * @param iteration iteration number
  167.      * @param evaluation evaluation number
  168.      * @param states orbital states at measurement date
  169.      * @return theoretical value
  170.      * @see #estimate(int, int, SpacecraftState[])
  171.      * @since 12.0
  172.      */
  173.     protected EstimatedMeasurementBase<T> theoreticalEvaluationWithoutDerivatives(final int iteration,
  174.                                                                                   final int evaluation,
  175.                                                                                   final SpacecraftState[] states) {
  176.         final EstimatedMeasurement<T> estimatedMeasurement = theoreticalEvaluation(iteration, evaluation, states);
  177.         final EstimatedMeasurementBase<T> estimatedMeasurementBase = new EstimatedMeasurementBase<>(estimatedMeasurement.getObservedMeasurement(),
  178.                 iteration, evaluation, states, estimatedMeasurement.getParticipants());
  179.         estimatedMeasurementBase.setEstimatedValue(estimatedMeasurement.getEstimatedValue());
  180.         estimatedMeasurementBase.setStatus(estimatedMeasurement.getStatus());
  181.         return estimatedMeasurementBase;
  182.     }

  183.     /** Estimate the theoretical value.
  184.      * <p>
  185.      * The theoretical value does not have <em>any</em> modifiers applied.
  186.      * </p>
  187.      * @param iteration iteration number
  188.      * @param evaluation evaluation number
  189.      * @param states orbital states at measurement date
  190.      * @return theoretical value
  191.      * @see #estimate(int, int, SpacecraftState[])
  192.      */
  193.     protected abstract EstimatedMeasurement<T> theoreticalEvaluation(int iteration, int evaluation, SpacecraftState[] states);

  194.     /** {@inheritDoc} */
  195.     @Override
  196.     public EstimatedMeasurementBase<T> estimateWithoutDerivatives(final int iteration, final int evaluation, final SpacecraftState[] states) {

  197.         // compute the theoretical value
  198.         final EstimatedMeasurementBase<T> estimation = theoreticalEvaluationWithoutDerivatives(iteration, evaluation, states);

  199.         // apply the modifiers
  200.         for (final EstimationModifier<T> modifier : modifiers) {
  201.             modifier.modifyWithoutDerivatives(estimation);
  202.         }

  203.         return estimation;

  204.     }

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

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

  210.         // apply the modifiers
  211.         for (final EstimationModifier<T> modifier : modifiers) {
  212.             modifier.modify(estimation);
  213.         }

  214.         return estimation;

  215.     }

  216.     /** {@inheritDoc} */
  217.     @Override
  218.     public AbsoluteDate getDate() {
  219.         return date;
  220.     }

  221.     /** {@inheritDoc} */
  222.     @Override
  223.     public double[] getObservedValue() {
  224.         return observed.clone();
  225.     }

  226.     /** {@inheritDoc} */
  227.     @Override
  228.     public void addModifier(final EstimationModifier<T> modifier) {

  229.         // combine the measurement parameters and the modifier parameters
  230.         supportedParameters.addAll(modifier.getParametersDrivers());

  231.         modifiers.add(modifier);

  232.     }

  233.     /** {@inheritDoc} */
  234.     @Override
  235.     public List<EstimationModifier<T>> getModifiers() {
  236.         return Collections.unmodifiableList(modifiers);
  237.     }

  238.     /** Compute propagation delay on a link leg (typically downlink or uplink).
  239.      * @param adjustableEmitterPV position/velocity of emitter that may be adjusted
  240.      * @param receiverPosition fixed position of receiver at {@code signalArrivalDate}
  241.      * @param frame inertial frame in which both {@code adjustableEmitterPV} and
  242.      * {@code receiverPosition} are defined
  243.      * @param signalArrivalDate date at which the signal arrives to receiver
  244.      * @return <em>positive</em> delay between signal emission and signal reception dates
  245.      * @since 13.0
  246.      */
  247.     public static double signalTimeOfFlightAdjustableEmitter(final TimeStampedPVCoordinates adjustableEmitterPV,
  248.                                                              final Vector3D receiverPosition,
  249.                                                              final AbsoluteDate signalArrivalDate,
  250.                                                              final Frame frame) {
  251.         return signalTimeOfFlightAdjustableEmitter(new ShiftingPVCoordinatesProvider(adjustableEmitterPV, frame),
  252.                                                    adjustableEmitterPV.getDate(),
  253.                                                    receiverPosition, signalArrivalDate,
  254.                                                    frame);
  255.     }

  256.     /** Compute propagation delay on a link leg (typically downlink or uplink).
  257.      * @param adjustableEmitter position/velocity provider of emitter
  258.      * @param approxEmissionDate approximate emission date
  259.      * @param receiverPosition fixed position of receiver at {@code signalArrivalDate}
  260.      * @param signalArrivalDate date at which the signal arrives to receiver
  261.      * @param frame inertial frame in which receiver is defined
  262.      * @return <em>positive</em> delay between signal emission and signal reception dates
  263.      * @since 13.0
  264.      */
  265.     public static double signalTimeOfFlightAdjustableEmitter(final PVCoordinatesProvider adjustableEmitter,
  266.                                                              final AbsoluteDate approxEmissionDate,
  267.                                                              final Vector3D receiverPosition,
  268.                                                              final AbsoluteDate signalArrivalDate,
  269.                                                              final Frame frame) {

  270.         // initialize emission date search loop assuming the state is already correct
  271.         // this will be true for all but the first orbit determination iteration,
  272.         // and even for the first iteration the loop will converge very fast
  273.         final double offset = signalArrivalDate.durationFrom(approxEmissionDate);
  274.         double delay = offset;

  275.         // search signal transit date, computing the signal travel in inertial frame
  276.         final double cReciprocal = 1.0 / Constants.SPEED_OF_LIGHT;
  277.         double delta;
  278.         int count = 0;
  279.         do {
  280.             final double previous = delay;
  281.             final Vector3D pos    = adjustableEmitter.getPosition(approxEmissionDate.shiftedBy(offset - delay), frame);
  282.             delay                 = receiverPosition.distance(pos) * cReciprocal;
  283.             delta                 = FastMath.abs(delay - previous);
  284.         } while (count++ < 10 && delta >= 2 * FastMath.ulp(delay));

  285.         return delay;

  286.     }

  287.     /** Compute propagation delay on a link leg (typically downlink or uplink).
  288.      * @param emitterPosition fixed position of emitter
  289.      * @param emissionDate emission date
  290.      * @param adjustableReceiverPV position/velocity of receiver that may be adjusted
  291.      * @param approxReceptionDate approximate reception date
  292.      * @param frame inertial frame in which both {@code emitterPosition} and
  293.      * {@code adjustableReceiverPV} are defined
  294.      * @return <em>positive</em> delay between signal emission and signal reception dates
  295.      * @since 13.0
  296.      */
  297.     public static double signalTimeOfFlightAdjustableReceiver(final Vector3D emitterPosition,
  298.                                                               final AbsoluteDate emissionDate,
  299.                                                               final TimeStampedPVCoordinates adjustableReceiverPV,
  300.                                                               final AbsoluteDate approxReceptionDate,
  301.                                                               final Frame frame) {
  302.         return signalTimeOfFlightAdjustableReceiver(emitterPosition, emissionDate,
  303.                                                     new ShiftingPVCoordinatesProvider(adjustableReceiverPV, frame),
  304.                                                     approxReceptionDate, frame);
  305.     }

  306.     /** Compute propagation delay on a link leg (typically downlink or uplink).
  307.      * @param emitterPosition fixed position of emitter
  308.      * @param emissionDate emission date
  309.      * @param adjustableReceiver provider for adjusting receiver position
  310.      * @param approxReceptionDate approximate reception date
  311.      * @param frame inertial frame in which emitter is defined
  312.      * @return <em>positive</em> delay between signal emission and signal reception dates
  313.      * @since 13.0
  314.      */
  315.     public static double signalTimeOfFlightAdjustableReceiver(final Vector3D emitterPosition,
  316.                                                               final AbsoluteDate emissionDate,
  317.                                                               final PVCoordinatesProvider adjustableReceiver,
  318.                                                               final AbsoluteDate approxReceptionDate,
  319.                                                               final Frame frame) {

  320.         // initialize reception date search loop assuming the state is already correct
  321.         final double offset = approxReceptionDate.durationFrom(emissionDate);
  322.         double delay = offset;

  323.         // search signal transit date, computing the signal travel in inertial frame
  324.         final double cReciprocal = 1.0 / Constants.SPEED_OF_LIGHT;
  325.         double delta;
  326.         int count = 0;
  327.         do {
  328.             final double previous   = delay;
  329.             final Vector3D arrivalP = adjustableReceiver.getPosition(approxReceptionDate.shiftedBy(delay - offset), frame);
  330.             delay                   = arrivalP.distance(emitterPosition) * cReciprocal;
  331.             delta                   = FastMath.abs(delay - previous);
  332.             count++;
  333.         } while (count < 10 && delta >= 2 * FastMath.ulp(delay));

  334.         return delay;

  335.     }

  336.     /** Compute propagation delay on a link leg (typically downlink or uplink).
  337.      * @param adjustableEmitterPV position/velocity of emitter that may be adjusted
  338.      * @param receiverPosition fixed position of receiver at {@code signalArrivalDate},
  339.      * in the same frame as {@code adjustableEmitterPV}
  340.      * @param signalArrivalDate date at which the signal arrives to receiver
  341.      * @return <em>positive</em> delay between signal emission and signal reception dates
  342.      * @param frame inertial frame in which both {@code adjustableEmitterPV} and
  343.      * {@code receiverPosition} are defined
  344.      * @param <T> the type of the components
  345.      * @since 13.0
  346.      */
  347.     public static <T extends CalculusFieldElement<T>> T signalTimeOfFlightAdjustableEmitter(final TimeStampedFieldPVCoordinates<T> adjustableEmitterPV,
  348.                                                                                             final FieldVector3D<T> receiverPosition,
  349.                                                                                             final FieldAbsoluteDate<T> signalArrivalDate,
  350.                                                                                             final Frame frame) {
  351.         return signalTimeOfFlightAdjustableEmitter(new FieldShiftingPVCoordinatesProvider<>(adjustableEmitterPV,
  352.                                                                                             frame),
  353.                                                    adjustableEmitterPV.getDate(),
  354.                                                    receiverPosition, signalArrivalDate,
  355.                                                    frame);
  356.     }

  357.     /** Compute propagation delay on a link leg (typically downlink or uplink).
  358.      * @param adjustableEmitter position/velocity provider of emitter
  359.      * @param approxEmissionDate approximate emission date
  360.      * @param receiverPosition fixed position of receiver at {@code signalArrivalDate},
  361.      * in the same frame as {@code adjustableEmitterPV}
  362.      * @param signalArrivalDate date at which the signal arrives to receiver
  363.      * @param frame inertial frame in which receiver is defined
  364.      * @return <em>positive</em> delay between signal emission and signal reception dates
  365.      * @param <T> the type of the components
  366.      * @since 13.0
  367.      */
  368.     public static <T extends CalculusFieldElement<T>> T signalTimeOfFlightAdjustableEmitter(final FieldPVCoordinatesProvider<T> adjustableEmitter,
  369.                                                                                             final FieldAbsoluteDate<T> approxEmissionDate,
  370.                                                                                             final FieldVector3D<T> receiverPosition,
  371.                                                                                             final FieldAbsoluteDate<T> signalArrivalDate,
  372.                                                                                             final Frame frame) {

  373.         // Initialize emission date search loop assuming the emitter PV is almost correct
  374.         // this will be true for all but the first orbit determination iteration,
  375.         // and even for the first iteration the loop will converge extremely fast
  376.         final T offset = signalArrivalDate.durationFrom(approxEmissionDate);
  377.         T delay = offset;

  378.         // search signal transit date, computing the signal travel in the frame shared by emitter and receiver
  379.         final double cReciprocal = 1.0 / Constants.SPEED_OF_LIGHT;
  380.         double delta;
  381.         int count = 0;
  382.         do {
  383.             final double previous           = delay.getReal();
  384.             final FieldVector3D<T> transitP = adjustableEmitter.getPosition(approxEmissionDate.shiftedBy(offset.subtract(delay)),
  385.                                                                             frame);
  386.             delay                           = receiverPosition.distance(transitP).multiply(cReciprocal);
  387.             delta                           = FastMath.abs(delay.getReal() - previous);
  388.         } while (count++ < 10 && delta >= 2 * FastMath.ulp(delay.getReal()));

  389.         return delay;

  390.     }

  391.     /** Compute propagation delay on a link leg (typically downlink or uplink).
  392.      * @param emitterPosition fixed position of emitter
  393.      * @param emissionDate emission date
  394.      * @param adjustableReceiverPV position/velocity of emitter that may be adjusted
  395.      * @param approxReceptionDate approximate reception date
  396.      * @param frame inertial frame in which both {@code emitterPosition} and
  397.      * {@code adjustableReceiverPV} are defined
  398.      * @param <T> the type of the components
  399.      * @return <em>positive</em> delay between signal emission and signal reception dates
  400.      * @since 13.0
  401.      */
  402.     public static <T extends CalculusFieldElement<T>> T signalTimeOfFlightAdjustableReceiver(final FieldVector3D<T> emitterPosition,
  403.                                                                                              final FieldAbsoluteDate<T> emissionDate,
  404.                                                                                              final TimeStampedFieldPVCoordinates<T> adjustableReceiverPV,
  405.                                                                                              final FieldAbsoluteDate<T> approxReceptionDate,
  406.                                                                                              final Frame frame) {
  407.         return signalTimeOfFlightAdjustableReceiver(emitterPosition, emissionDate,
  408.                                                     new FieldShiftingPVCoordinatesProvider<>(adjustableReceiverPV, frame),
  409.                                                     approxReceptionDate, frame);
  410.     }

  411.     /** Compute propagation delay on a link leg (typically downlink or uplink).
  412.      * @param emitterPosition fixed position of emitter
  413.      * @param emissionDate emission date
  414.      * @param adjustableReceiver provider for adjusting receiver position
  415.      * @param approxReceptionDate approximate reception date
  416.      * @param frame inertial frame in which emitter is defined
  417.      * @param <T> the type of the components
  418.      * @return <em>positive</em> delay between signal emission and signal reception dates
  419.      * @since 13.0
  420.      */
  421.     public static <T extends CalculusFieldElement<T>> T signalTimeOfFlightAdjustableReceiver(final FieldVector3D<T> emitterPosition,
  422.                                                                                              final FieldAbsoluteDate<T> emissionDate,
  423.                                                                                              final FieldPVCoordinatesProvider<T> adjustableReceiver,
  424.                                                                                              final FieldAbsoluteDate<T> approxReceptionDate,
  425.                                                                                              final Frame frame) {

  426.         // initialize reception date search loop assuming the state is already correct
  427.         final T offset = approxReceptionDate.durationFrom(emissionDate);
  428.         T delay = offset;

  429.         // search signal transit date, computing the signal travel in the frame shared by emitter and receiver
  430.         final double cReciprocal = 1.0 / Constants.SPEED_OF_LIGHT;
  431.         double delta;
  432.         int count = 0;
  433.         do {
  434.             final double previous           = delay.getReal();
  435.             final FieldVector3D<T> arrivalP = adjustableReceiver.getPosition(approxReceptionDate.shiftedBy(delay.subtract(offset)),
  436.                                                                             frame);
  437.             delay                           = arrivalP.distance(emitterPosition).multiply(cReciprocal);
  438.             delta                           = FastMath.abs(delay.getReal() - previous);
  439.         } while (count++ < 10 && delta >= 2 * FastMath.ulp(delay.getReal()));

  440.         return delay;

  441.     }

  442.     /** Get Cartesian coordinates as derivatives.
  443.      * <p>
  444.      * The position will correspond to variables {@code firstDerivative},
  445.      * {@code firstDerivative + 1} and {@code firstDerivative + 2}.
  446.      * The velocity will correspond to variables {@code firstDerivative + 3},
  447.      * {@code firstDerivative + 4} and {@code firstDerivative + 5}.
  448.      * The acceleration will correspond to constants.
  449.      * </p>
  450.      * @param state state of the satellite considered
  451.      * @param firstDerivative index of the first derivative
  452.      * @param freeParameters total number of free parameters in the gradient
  453.      * @return Cartesian coordinates as derivatives
  454.      * @since 10.2
  455.      */
  456.     public static TimeStampedFieldPVCoordinates<Gradient> getCoordinates(final SpacecraftState state,
  457.                                                                          final int firstDerivative,
  458.                                                                          final int freeParameters) {

  459.         // Position of the satellite expressed as a gradient
  460.         // The components of the position are the 3 first derivative parameters
  461.         final Vector3D p = state.getPosition();
  462.         final FieldVector3D<Gradient> pDS =
  463.                         new FieldVector3D<>(Gradient.variable(freeParameters, firstDerivative,     p.getX()),
  464.                                             Gradient.variable(freeParameters, firstDerivative + 1, p.getY()),
  465.                                             Gradient.variable(freeParameters, firstDerivative + 2, p.getZ()));

  466.         // Velocity of the satellite expressed as a gradient
  467.         // The components of the velocity are the 3 second derivative parameters
  468.         final Vector3D v = state.getPVCoordinates().getVelocity();
  469.         final FieldVector3D<Gradient> vDS =
  470.                         new FieldVector3D<>(Gradient.variable(freeParameters, firstDerivative + 3, v.getX()),
  471.                                             Gradient.variable(freeParameters, firstDerivative + 4, v.getY()),
  472.                                             Gradient.variable(freeParameters, firstDerivative + 5, v.getZ()));

  473.         // Acceleration of the satellite
  474.         // The components of the acceleration are not derivative parameters
  475.         final Vector3D a = state.getPVCoordinates().getAcceleration();
  476.         final FieldVector3D<Gradient> aDS =
  477.                         new FieldVector3D<>(Gradient.constant(freeParameters, a.getX()),
  478.                                             Gradient.constant(freeParameters, a.getY()),
  479.                                             Gradient.constant(freeParameters, a.getZ()));

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

  481.     }

  482. }