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

  18. import java.io.Serializable;
  19. import java.util.Map;

  20. import org.hipparchus.RealFieldElement;
  21. import org.hipparchus.analysis.differentiation.DSFactory;
  22. import org.hipparchus.analysis.differentiation.DerivativeStructure;
  23. import org.hipparchus.analysis.differentiation.Gradient;
  24. import org.hipparchus.geometry.euclidean.threed.FieldRotation;
  25. import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
  26. import org.hipparchus.geometry.euclidean.threed.Rotation;
  27. import org.hipparchus.geometry.euclidean.threed.RotationConvention;
  28. import org.hipparchus.geometry.euclidean.threed.Vector3D;
  29. import org.hipparchus.util.FastMath;
  30. import org.orekit.errors.OrekitException;
  31. import org.orekit.errors.OrekitInternalError;
  32. import org.orekit.errors.OrekitMessages;
  33. import org.orekit.frames.FieldTransform;
  34. import org.orekit.frames.Transform;
  35. import org.orekit.frames.TransformProvider;
  36. import org.orekit.time.AbsoluteDate;
  37. import org.orekit.time.FieldAbsoluteDate;
  38. import org.orekit.time.UT1Scale;
  39. import org.orekit.utils.IERSConventions;
  40. import org.orekit.utils.ParameterDriver;

  41. /** Class modeling an Earth frame whose Earth Orientation Parameters can be estimated.
  42.  * <p>
  43.  * This class adds parameters for an additional polar motion
  44.  * and an additional prime meridian orientation on top of an underlying regular Earth
  45.  * frame like {@link org.orekit.frames.FramesFactory#getITRF(IERSConventions, boolean) ITRF}.
  46.  * The polar motion and prime meridian orientation are applied <em>after</em> regular Earth
  47.  * orientation parameters, so the value of the estimated parameters will be correction to EOP,
  48.  * they will not be the complete EOP values by themselves. Basically, this means that for
  49.  * Earth, the following transforms are applied in order, between inertial frame and this frame:
  50.  * </p>
  51.  * <ol>
  52.  *   <li>precession/nutation, as theoretical model plus celestial pole EOP parameters</li>
  53.  *   <li>body rotation, as theoretical model plus prime meridian EOP parameters</li>
  54.  *   <li>polar motion, which is only from EOP parameters (no theoretical models)</li>
  55.  *   <li>additional body rotation, controlled by {@link #getPrimeMeridianOffsetDriver()} and {@link #getPrimeMeridianDriftDriver()}</li>
  56.  *   <li>additional polar motion, controlled by {@link #getPolarOffsetXDriver()}, {@link #getPolarDriftXDriver()},
  57.  *   {@link #getPolarOffsetYDriver()} and {@link #getPolarDriftYDriver()}</li>
  58.  * </ol>
  59.  * @author Luc Maisonobe
  60.  * @since 9.1
  61.  */
  62. public class EstimatedEarthFrameProvider implements TransformProvider {

  63.     /** Earth Angular Velocity, in rad/s, from TIRF model. */
  64.     public static final double EARTH_ANGULAR_VELOCITY = 7.292115146706979e-5;

  65.     /** Serializable UID. */
  66.     private static final long serialVersionUID = 20170922L;

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

  74.     /** Underlying raw UT1. */
  75.     private final UT1Scale baseUT1;

  76.     /** Estimated UT1. */
  77.     private final transient UT1Scale estimatedUT1;

  78.     /** Driver for prime meridian offset. */
  79.     private final transient ParameterDriver primeMeridianOffsetDriver;

  80.     /** Driver for prime meridian drift. */
  81.     private final transient ParameterDriver primeMeridianDriftDriver;

  82.     /** Driver for pole offset along X. */
  83.     private final transient ParameterDriver polarOffsetXDriver;

  84.     /** Driver for pole drift along X. */
  85.     private final transient ParameterDriver polarDriftXDriver;

  86.     /** Driver for pole offset along Y. */
  87.     private final transient ParameterDriver polarOffsetYDriver;

  88.     /** Driver for pole drift along Y. */
  89.     private final transient ParameterDriver polarDriftYDriver;

  90.     /** Build an estimated Earth frame.
  91.      * <p>
  92.      * The initial values for the pole and prime meridian parametric linear models
  93.      * ({@link #getPrimeMeridianOffsetDriver()}, {@link #getPrimeMeridianDriftDriver()},
  94.      * {@link #getPolarOffsetXDriver()}, {@link #getPolarDriftXDriver()},
  95.      * {@link #getPolarOffsetXDriver()}, {@link #getPolarDriftXDriver()}) are set to 0.
  96.      * </p>
  97.      * @param baseUT1 underlying base UT1
  98.      * @since 9.1
  99.      */
  100.     public EstimatedEarthFrameProvider(final UT1Scale baseUT1) {

  101.         this.primeMeridianOffsetDriver = new ParameterDriver("prime-meridian-offset",
  102.                                                              0.0, ANGULAR_SCALE,
  103.                                                             -FastMath.PI, FastMath.PI);

  104.         this.primeMeridianDriftDriver = new ParameterDriver("prime-meridian-drift",
  105.                                                             0.0, ANGULAR_SCALE,
  106.                                                             Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY);

  107.         this.polarOffsetXDriver = new ParameterDriver("polar-offset-X",
  108.                                                       0.0, ANGULAR_SCALE,
  109.                                                       -FastMath.PI, FastMath.PI);

  110.         this.polarDriftXDriver = new ParameterDriver("polar-drift-X",
  111.                                                      0.0, ANGULAR_SCALE,
  112.                                                      Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY);

  113.         this.polarOffsetYDriver = new ParameterDriver("polar-offset-Y",
  114.                                                       0.0, ANGULAR_SCALE,
  115.                                                       -FastMath.PI, FastMath.PI);

  116.         this.polarDriftYDriver = new ParameterDriver("polar-drift-Y",
  117.                                                      0.0, ANGULAR_SCALE,
  118.                                                      Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY);

  119.         this.baseUT1      = baseUT1;
  120.         this.estimatedUT1 = new EstimatedUT1Scale();

  121.     }

  122.     /** Get a driver allowing to add a prime meridian rotation.
  123.      * <p>
  124.      * The parameter is an angle in radians. In order to convert this
  125.      * value to a DUT1 in seconds, the value must be divided by
  126.      * {@link #EARTH_ANGULAR_VELOCITY} (nominal Angular Velocity of Earth).
  127.      * </p>
  128.      * @return driver for prime meridian rotation
  129.      */
  130.     public ParameterDriver getPrimeMeridianOffsetDriver() {
  131.         return primeMeridianOffsetDriver;
  132.     }

  133.     /** Get a driver allowing to add a prime meridian rotation rate.
  134.      * <p>
  135.      * The parameter is an angle rate in radians per second. In order to convert this
  136.      * value to a LOD in seconds, the value must be multiplied by -86400 and divided by
  137.      * {@link #EARTH_ANGULAR_VELOCITY} (nominal Angular Velocity of Earth).
  138.      * </p>
  139.      * @return driver for prime meridian rotation rate
  140.      */
  141.     public ParameterDriver getPrimeMeridianDriftDriver() {
  142.         return primeMeridianDriftDriver;
  143.     }

  144.     /** Get a driver allowing to add a polar offset along X.
  145.      * <p>
  146.      * The parameter is an angle in radians
  147.      * </p>
  148.      * @return driver for polar offset along X
  149.      */
  150.     public ParameterDriver getPolarOffsetXDriver() {
  151.         return polarOffsetXDriver;
  152.     }

  153.     /** Get a driver allowing to add a polar drift along X.
  154.      * <p>
  155.      * The parameter is an angle rate in radians per second
  156.      * </p>
  157.      * @return driver for polar drift along X
  158.      */
  159.     public ParameterDriver getPolarDriftXDriver() {
  160.         return polarDriftXDriver;
  161.     }

  162.     /** Get a driver allowing to add a polar offset along Y.
  163.      * <p>
  164.      * The parameter is an angle in radians
  165.      * </p>
  166.      * @return driver for polar offset along Y
  167.      */
  168.     public ParameterDriver getPolarOffsetYDriver() {
  169.         return polarOffsetYDriver;
  170.     }

  171.     /** Get a driver allowing to add a polar drift along Y.
  172.      * <p>
  173.      * The parameter is an angle rate in radians per second
  174.      * </p>
  175.      * @return driver for polar drift along Y
  176.      */
  177.     public ParameterDriver getPolarDriftYDriver() {
  178.         return polarDriftYDriver;
  179.     }

  180.     /** Get the estimated UT1 time scale.
  181.      * @return estimated UT1 time scale
  182.      */
  183.     public UT1Scale getEstimatedUT1() {
  184.         return estimatedUT1;
  185.     }

  186.     /** {@inheritDoc} */
  187.     @Override
  188.     public Transform getTransform(final AbsoluteDate date) {

  189.         // take parametric prime meridian shift into account
  190.         final double theta    = linearModel(date, primeMeridianOffsetDriver, primeMeridianDriftDriver);
  191.         final double thetaDot = primeMeridianDriftDriver.getValue();
  192.         final Transform meridianShift =
  193.                         new Transform(date,
  194.                                       new Rotation(Vector3D.PLUS_K, theta, RotationConvention.FRAME_TRANSFORM),
  195.                                       new Vector3D(0, 0, thetaDot));

  196.         // take parametric pole shift into account
  197.         final double xpNeg     = -linearModel(date, polarOffsetXDriver, polarDriftXDriver);
  198.         final double ypNeg     = -linearModel(date, polarOffsetYDriver, polarDriftYDriver);
  199.         final double xpNegDot  = -polarDriftXDriver.getValue();
  200.         final double ypNegDot  = -polarDriftYDriver.getValue();
  201.         final Transform poleShift =
  202.                         new Transform(date,
  203.                                       new Transform(date,
  204.                                                     new Rotation(Vector3D.PLUS_J, xpNeg, RotationConvention.FRAME_TRANSFORM),
  205.                                                     new Vector3D(0.0, xpNegDot, 0.0)),
  206.                                       new Transform(date,
  207.                                                     new Rotation(Vector3D.PLUS_I, ypNeg, RotationConvention.FRAME_TRANSFORM),
  208.                                                     new Vector3D(ypNegDot, 0.0, 0.0)));

  209.         return new Transform(date, meridianShift, poleShift);

  210.     }

  211.     /** {@inheritDoc} */
  212.     @Override
  213.     public <T extends RealFieldElement<T>> FieldTransform<T> getTransform(final FieldAbsoluteDate<T> date) {

  214.         final T zero = date.getField().getZero();

  215.         // prime meridian shift parameters
  216.         final T theta    = linearModel(date, primeMeridianOffsetDriver, primeMeridianDriftDriver);
  217.         final T thetaDot = zero.add(primeMeridianDriftDriver.getValue());

  218.         // pole shift parameters
  219.         final T xpNeg    = linearModel(date, polarOffsetXDriver, polarDriftXDriver).negate();
  220.         final T ypNeg    = linearModel(date, polarOffsetYDriver, polarDriftYDriver).negate();
  221.         final T xpNegDot = zero.subtract(polarDriftXDriver.getValue());
  222.         final T ypNegDot = zero.subtract(polarDriftYDriver.getValue());

  223.         return getTransform(date, theta, thetaDot, xpNeg, xpNegDot, ypNeg, ypNegDot);

  224.     }

  225.     /** Get the transform with derivatives.
  226.      * @param date date of the transform
  227.      * @param factory factory for the derivatives
  228.      * @param indices indices of the estimated parameters in derivatives computations
  229.      * @return computed transform with derivatives
  230.      * @deprecated as of 10.2, replaced by {@link #getTransform(FieldAbsoluteDate, int, Map)}
  231.      */
  232.     @Deprecated
  233.     public FieldTransform<DerivativeStructure> getTransform(final FieldAbsoluteDate<DerivativeStructure> date,
  234.                                                             final DSFactory factory,
  235.                                                             final Map<String, Integer> indices) {

  236.         // prime meridian shift parameters
  237.         final DerivativeStructure theta    = linearModel(factory, date,
  238.                                                          primeMeridianOffsetDriver, primeMeridianDriftDriver,
  239.                                                          indices);
  240.         final DerivativeStructure thetaDot = primeMeridianDriftDriver.getValue(factory, indices);

  241.         // pole shift parameters
  242.         final DerivativeStructure xpNeg    = linearModel(factory, date,
  243.                                                          polarOffsetXDriver, polarDriftXDriver, indices).negate();
  244.         final DerivativeStructure ypNeg    = linearModel(factory, date,
  245.                                                          polarOffsetYDriver, polarDriftYDriver, indices).negate();
  246.         final DerivativeStructure xpNegDot = polarDriftXDriver.getValue(factory, indices).negate();
  247.         final DerivativeStructure ypNegDot = polarDriftYDriver.getValue(factory, indices).negate();

  248.         return getTransform(date, theta, thetaDot, xpNeg, xpNegDot, ypNeg, ypNegDot);

  249.     }

  250.     /** Get the transform with derivatives.
  251.      * @param date date of the transform
  252.      * @param freeParameters total number of free parameters in the gradient
  253.      * @param indices indices of the estimated parameters in derivatives computations
  254.      * @return computed transform with derivatives
  255.      * @since 10.2
  256.      */
  257.     public FieldTransform<Gradient> getTransform(final FieldAbsoluteDate<Gradient> date,
  258.                                                  final int freeParameters,
  259.                                                  final Map<String, Integer> indices) {

  260.         // prime meridian shift parameters
  261.         final Gradient theta    = linearModel(freeParameters, date,
  262.                                               primeMeridianOffsetDriver, primeMeridianDriftDriver,
  263.                                               indices);
  264.         final Gradient thetaDot = primeMeridianDriftDriver.getValue(freeParameters, indices);

  265.         // pole shift parameters
  266.         final Gradient xpNeg    = linearModel(freeParameters, date,
  267.                                                          polarOffsetXDriver, polarDriftXDriver, indices).negate();
  268.         final Gradient ypNeg    = linearModel(freeParameters, date,
  269.                                                          polarOffsetYDriver, polarDriftYDriver, indices).negate();
  270.         final Gradient xpNegDot = polarDriftXDriver.getValue(freeParameters, indices).negate();
  271.         final Gradient ypNegDot = polarDriftYDriver.getValue(freeParameters, indices).negate();

  272.         return getTransform(date, theta, thetaDot, xpNeg, xpNegDot, ypNeg, ypNegDot);

  273.     }

  274.     /** Get the transform with derivatives.
  275.      * @param date date of the transform
  276.      * @param theta angle of the prime meridian
  277.      * @param thetaDot angular rate of the prime meridian
  278.      * @param xpNeg opposite of the angle of the pole motion along X
  279.      * @param xpNegDot opposite of the angular rate of the pole motion along X
  280.      * @param ypNeg opposite of the angle of the pole motion along Y
  281.      * @param ypNegDot opposite of the angular rate of the pole motion along Y
  282.      * @param <T> type of the field elements
  283.      * @return computed transform with derivatives
  284.      */
  285.     private <T extends RealFieldElement<T>> FieldTransform<T> getTransform(final FieldAbsoluteDate<T> date,
  286.                                                                            final T theta, final T thetaDot,
  287.                                                                            final T xpNeg, final T xpNegDot,
  288.                                                                            final T ypNeg, final T ypNegDot) {

  289.         final T                zero  = date.getField().getZero();
  290.         final FieldVector3D<T> plusI = FieldVector3D.getPlusI(date.getField());
  291.         final FieldVector3D<T> plusJ = FieldVector3D.getPlusJ(date.getField());
  292.         final FieldVector3D<T> plusK = FieldVector3D.getPlusK(date.getField());

  293.         // take parametric prime meridian shift into account
  294.         final FieldTransform<T> meridianShift =
  295.                         new FieldTransform<>(date,
  296.                                              new FieldRotation<>(plusK, theta, RotationConvention.FRAME_TRANSFORM),
  297.                                              new FieldVector3D<>(zero, zero, thetaDot));

  298.         // take parametric pole shift into account
  299.         final FieldTransform<T> poleShift =
  300.                         new FieldTransform<>(date,
  301.                                       new FieldTransform<>(date,
  302.                                                            new FieldRotation<>(plusJ, xpNeg, RotationConvention.FRAME_TRANSFORM),
  303.                                                            new FieldVector3D<>(zero, xpNegDot, zero)),
  304.                                       new FieldTransform<>(date,
  305.                                                            new FieldRotation<>(plusI, ypNeg, RotationConvention.FRAME_TRANSFORM),
  306.                                                            new FieldVector3D<>(ypNegDot, zero, zero)));

  307.         return new FieldTransform<>(date, meridianShift, poleShift);

  308.     }

  309.     /** Evaluate a parametric linear model.
  310.      * @param date current date
  311.      * @param offsetDriver driver for the offset parameter
  312.      * @param driftDriver driver for the drift parameter
  313.      * @return current value of the linear model
  314.      */
  315.     private double linearModel(final AbsoluteDate date,
  316.                                final ParameterDriver offsetDriver, final ParameterDriver driftDriver) {
  317.         if (offsetDriver.getReferenceDate() == null) {
  318.             throw new OrekitException(OrekitMessages.NO_REFERENCE_DATE_FOR_PARAMETER,
  319.                                       offsetDriver.getName());
  320.         }
  321.         final double dt     = date.durationFrom(offsetDriver.getReferenceDate());
  322.         final double offset = offsetDriver.getValue();
  323.         final double drift  = driftDriver.getValue();
  324.         return dt * drift + offset;
  325.     }

  326.     /** Evaluate a parametric linear model.
  327.      * @param date current date
  328.      * @param offsetDriver driver for the offset parameter
  329.      * @param driftDriver driver for the drift parameter
  330.      * @return current value of the linear model
  331.      * @param <T> type of the filed elements
  332.      */
  333.     private <T extends RealFieldElement<T>> T linearModel(final FieldAbsoluteDate<T> date,
  334.                                                           final ParameterDriver offsetDriver,
  335.                                                           final ParameterDriver driftDriver) {
  336.         if (offsetDriver.getReferenceDate() == null) {
  337.             throw new OrekitException(OrekitMessages.NO_REFERENCE_DATE_FOR_PARAMETER,
  338.                                       offsetDriver.getName());
  339.         }
  340.         final T dt          = date.durationFrom(offsetDriver.getReferenceDate());
  341.         final double offset = offsetDriver.getValue();
  342.         final double drift  = driftDriver.getValue();
  343.         return dt.multiply(drift).add(offset);
  344.     }

  345.     /** Evaluate a parametric linear model.
  346.      * @param factory factory for the derivatives
  347.      * @param date current date
  348.      * @param offsetDriver driver for the offset parameter
  349.      * @param driftDriver driver for the drift parameter
  350.      * @param indices indices of the estimated parameters in derivatives computations
  351.      * @return current value of the linear model
  352.      * @deprecated as of 10.2, replaced by {@link #linearModel(int, FieldAbsoluteDate, ParameterDriver, ParameterDriver, Map)}
  353.      */
  354.     @Deprecated
  355.     private DerivativeStructure linearModel(final DSFactory factory, final FieldAbsoluteDate<DerivativeStructure> date,
  356.                                             final ParameterDriver offsetDriver, final ParameterDriver driftDriver,
  357.                                             final Map<String, Integer> indices) {
  358.         if (offsetDriver.getReferenceDate() == null) {
  359.             throw new OrekitException(OrekitMessages.NO_REFERENCE_DATE_FOR_PARAMETER,
  360.                                       offsetDriver.getName());
  361.         }
  362.         final DerivativeStructure dt     = date.durationFrom(offsetDriver.getReferenceDate());
  363.         final DerivativeStructure offset = offsetDriver.getValue(factory, indices);
  364.         final DerivativeStructure drift  = driftDriver.getValue(factory, indices);
  365.         return dt.multiply(drift).add(offset);
  366.     }

  367.     /** Evaluate a parametric linear model.
  368.      * @param freeParameters total number of free parameters in the gradient
  369.      * @param date current date
  370.      * @param offsetDriver driver for the offset parameter
  371.      * @param driftDriver driver for the drift parameter
  372.      * @param indices indices of the estimated parameters in derivatives computations
  373.      * @return current value of the linear model
  374.      * @since 10.2
  375.      */
  376.     private Gradient linearModel(final int freeParameters, final FieldAbsoluteDate<Gradient> date,
  377.                                  final ParameterDriver offsetDriver, final ParameterDriver driftDriver,
  378.                                  final Map<String, Integer> indices) {
  379.         if (offsetDriver.getReferenceDate() == null) {
  380.             throw new OrekitException(OrekitMessages.NO_REFERENCE_DATE_FOR_PARAMETER,
  381.                                       offsetDriver.getName());
  382.         }
  383.         final Gradient dt     = date.durationFrom(offsetDriver.getReferenceDate());
  384.         final Gradient offset = offsetDriver.getValue(freeParameters, indices);
  385.         final Gradient drift  = driftDriver.getValue(freeParameters, indices);
  386.         return dt.multiply(drift).add(offset);
  387.     }

  388.     /** Replace the instance with a data transfer object for serialization.
  389.      * <p>
  390.      * This intermediate class serializes the files supported names, the ephemeris type
  391.      * and the body name.
  392.      * </p>
  393.      * @return data transfer object that will be serialized
  394.      */
  395.     private Object writeReplace() {
  396.         return new DataTransferObject(baseUT1,
  397.                                       primeMeridianOffsetDriver.getValue(),
  398.                                       primeMeridianDriftDriver.getValue(),
  399.                                       polarOffsetXDriver.getValue(),
  400.                                       polarDriftXDriver.getValue(),
  401.                                       polarOffsetYDriver.getValue(),
  402.                                       polarDriftYDriver.getValue());
  403.     }

  404.     /** Local time scale for estimated UT1. */
  405.     private class EstimatedUT1Scale extends UT1Scale {

  406.         /** Serializable UID. */
  407.         private static final long serialVersionUID = 20170922L;

  408.         /** Simple constructor.
  409.          */
  410.         EstimatedUT1Scale() {
  411.             super(baseUT1.getEOPHistory(), baseUT1.getUTCScale());
  412.         }

  413.         /** {@inheritDoc} */
  414.         @Override
  415.         public <T extends RealFieldElement<T>> T offsetFromTAI(final FieldAbsoluteDate<T> date) {
  416.             final T dut1 = linearModel(date, primeMeridianOffsetDriver, primeMeridianDriftDriver).divide(EARTH_ANGULAR_VELOCITY);
  417.             return baseUT1.offsetFromTAI(date).add(dut1);
  418.         }

  419.         /** {@inheritDoc} */
  420.         @Override
  421.         public double offsetFromTAI(final AbsoluteDate date) {
  422.             final double dut1 = linearModel(date, primeMeridianOffsetDriver, primeMeridianDriftDriver) / EARTH_ANGULAR_VELOCITY;
  423.             return baseUT1.offsetFromTAI(date) + dut1;
  424.         }

  425.         /** {@inheritDoc} */
  426.         @Override
  427.         public String getName() {
  428.             return baseUT1.getName() + "/estimated";
  429.         }

  430.     }

  431.     /** Internal class used only for serialization. */
  432.     private static class DataTransferObject implements Serializable {

  433.         /** Serializable UID. */
  434.         private static final long serialVersionUID = 20171124L;

  435.         /** Underlying raw UT1. */
  436.         private final UT1Scale baseUT1;

  437.         /** Current prime meridian offset. */
  438.         private final double primeMeridianOffset;

  439.         /** Current prime meridian drift. */
  440.         private final double primeMeridianDrift;

  441.         /** Current pole offset along X. */
  442.         private final double polarOffsetX;

  443.         /** Current pole drift along X. */
  444.         private final double polarDriftX;

  445.         /** Current pole offset along Y. */
  446.         private final double polarOffsetY;

  447.         /** Current pole drift along Y. */
  448.         private final double polarDriftY;

  449.         /** Simple constructor.
  450.          * @param baseUT1 underlying raw UT1
  451.          * @param primeMeridianOffset current prime meridian offset
  452.          * @param primeMeridianDrift current prime meridian drift
  453.          * @param polarOffsetX current pole offset along X
  454.          * @param polarDriftX current pole drift along X
  455.          * @param polarOffsetY current pole offset along Y
  456.          * @param polarDriftY current pole drift along Y
  457.          */
  458.         DataTransferObject(final  UT1Scale baseUT1,
  459.                            final double primeMeridianOffset, final double primeMeridianDrift,
  460.                            final double polarOffsetX,        final double polarDriftX,
  461.                            final double polarOffsetY,        final double polarDriftY) {
  462.             this.baseUT1             = baseUT1;
  463.             this.primeMeridianOffset = primeMeridianOffset;
  464.             this.primeMeridianDrift  = primeMeridianDrift;
  465.             this.polarOffsetX        = polarOffsetX;
  466.             this.polarDriftX         = polarDriftX;
  467.             this.polarOffsetY        = polarOffsetY;
  468.             this.polarDriftY         = polarDriftY;
  469.         }

  470.         /** Replace the deserialized data transfer object with a {@link EstimatedEarthFrameProvider}.
  471.          * @return replacement {@link EstimatedEarthFrameProvider}
  472.          */
  473.         private Object readResolve() {
  474.             try {
  475.                 final EstimatedEarthFrameProvider provider = new EstimatedEarthFrameProvider(baseUT1);
  476.                 provider.getPrimeMeridianOffsetDriver().setValue(primeMeridianOffset);
  477.                 provider.getPrimeMeridianDriftDriver().setValue(primeMeridianDrift);
  478.                 provider.getPolarOffsetXDriver().setValue(polarOffsetX);
  479.                 provider.getPolarDriftXDriver().setValue(polarDriftX);
  480.                 provider.getPolarOffsetYDriver().setValue(polarOffsetY);
  481.                 provider.getPolarDriftYDriver().setValue(polarDriftY);
  482.                 return provider;
  483.             } catch (OrekitException oe) {
  484.                 // this should never happen as values already come from previous drivers
  485.                 throw new OrekitInternalError(oe);
  486.             }
  487.         }

  488.     }

  489. }