TimeStampedFieldPVCoordinates.java

  1. /* Copyright 2002-2016 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.utils;

  18. import java.util.Collection;

  19. import org.apache.commons.math3.RealFieldElement;
  20. import org.apache.commons.math3.analysis.interpolation.FieldHermiteInterpolator;
  21. import org.apache.commons.math3.geometry.euclidean.threed.FieldVector3D;
  22. import org.orekit.errors.OrekitInternalError;
  23. import org.orekit.time.AbsoluteDate;
  24. import org.orekit.time.TimeStamped;

  25. /** {@link TimeStamped time-stamped} version of {@link FieldPVCoordinates}.
  26.  * <p>Instances of this class are guaranteed to be immutable.</p>
  27.  * @param <T> the type of the field elements
  28.  * @author Luc Maisonobe
  29.  * @since 7.0
  30.  */
  31. public class TimeStampedFieldPVCoordinates<T extends RealFieldElement<T>>
  32.     extends FieldPVCoordinates<T> implements TimeStamped {

  33.     /** Serializable UID. */
  34.     private static final long serialVersionUID = 20140611L;

  35.     /** The date. */
  36.     private final AbsoluteDate date;

  37.     /** Builds a PVCoordinates pair.
  38.      * @param date coordinates date
  39.      * @param position the position vector (m)
  40.      * @param velocity the velocity vector (m/s)
  41.      * @param acceleration the acceleration vector (m/s²)
  42.      */
  43.     public TimeStampedFieldPVCoordinates(final AbsoluteDate date,
  44.                                          final FieldVector3D<T> position,
  45.                                          final FieldVector3D<T> velocity,
  46.                                          final FieldVector3D<T> acceleration) {
  47.         super(position, velocity, acceleration);
  48.         this.date = date;
  49.     }

  50.     /** Multiplicative constructor
  51.      * <p>Build a PVCoordinates from another one and a scale factor.</p>
  52.      * <p>The PVCoordinates built will be a * pv</p>
  53.      * @param date date of the built coordinates
  54.      * @param a scale factor
  55.      * @param pv base (unscaled) PVCoordinates
  56.      */
  57.     public TimeStampedFieldPVCoordinates(final AbsoluteDate date,
  58.                                          final double a, final FieldPVCoordinates<T> pv) {
  59.         super(new FieldVector3D<T>(a, pv.getPosition()),
  60.               new FieldVector3D<T>(a, pv.getVelocity()),
  61.               new FieldVector3D<T>(a, pv.getAcceleration()));
  62.         this.date = date;
  63.     }

  64.     /** Multiplicative constructor
  65.      * <p>Build a PVCoordinates from another one and a scale factor.</p>
  66.      * <p>The PVCoordinates built will be a * pv</p>
  67.      * @param date date of the built coordinates
  68.      * @param a scale factor
  69.      * @param pv base (unscaled) PVCoordinates
  70.      */
  71.     public TimeStampedFieldPVCoordinates(final AbsoluteDate date,
  72.                                          final T a, final FieldPVCoordinates<T> pv) {
  73.         super(new FieldVector3D<T>(a, pv.getPosition()),
  74.               new FieldVector3D<T>(a, pv.getVelocity()),
  75.               new FieldVector3D<T>(a, pv.getAcceleration()));
  76.         this.date = date;
  77.     }

  78.     /** Multiplicative constructor
  79.      * <p>Build a PVCoordinates from another one and a scale factor.</p>
  80.      * <p>The PVCoordinates built will be a * pv</p>
  81.      * @param date date of the built coordinates
  82.      * @param a scale factor
  83.      * @param pv base (unscaled) PVCoordinates
  84.      */
  85.     public TimeStampedFieldPVCoordinates(final AbsoluteDate date,
  86.                                          final T a, final PVCoordinates pv) {
  87.         super(new FieldVector3D<T>(a, pv.getPosition()),
  88.               new FieldVector3D<T>(a, pv.getVelocity()),
  89.               new FieldVector3D<T>(a, pv.getAcceleration()));
  90.         this.date = date;
  91.     }

  92.     /** Subtractive constructor
  93.      * <p>Build a relative PVCoordinates from a start and an end position.</p>
  94.      * <p>The PVCoordinates built will be end - start.</p>
  95.      * @param date date of the built coordinates
  96.      * @param start Starting PVCoordinates
  97.      * @param end ending PVCoordinates
  98.      */
  99.     public TimeStampedFieldPVCoordinates(final AbsoluteDate date,
  100.                                          final FieldPVCoordinates<T> start, final FieldPVCoordinates<T> end) {
  101.         super(end.getPosition().subtract(start.getPosition()),
  102.               end.getVelocity().subtract(start.getVelocity()),
  103.               end.getAcceleration().subtract(start.getAcceleration()));
  104.         this.date = date;
  105.     }

  106.     /** Linear constructor
  107.      * <p>Build a PVCoordinates from two other ones and corresponding scale factors.</p>
  108.      * <p>The PVCoordinates built will be a1 * u1 + a2 * u2</p>
  109.      * @param date date of the built coordinates
  110.      * @param a1 first scale factor
  111.      * @param pv1 first base (unscaled) PVCoordinates
  112.      * @param a2 second scale factor
  113.      * @param pv2 second base (unscaled) PVCoordinates
  114.      */
  115.     public TimeStampedFieldPVCoordinates(final AbsoluteDate date,
  116.                                          final double a1, final FieldPVCoordinates<T> pv1,
  117.                                          final double a2, final FieldPVCoordinates<T> pv2) {
  118.         super(new FieldVector3D<T>(a1, pv1.getPosition(),     a2, pv2.getPosition()),
  119.               new FieldVector3D<T>(a1, pv1.getVelocity(),     a2, pv2.getVelocity()),
  120.               new FieldVector3D<T>(a1, pv1.getAcceleration(), a2, pv2.getAcceleration()));
  121.         this.date = date;
  122.     }

  123.     /** Linear constructor
  124.      * <p>Build a PVCoordinates from two other ones and corresponding scale factors.</p>
  125.      * <p>The PVCoordinates built will be a1 * u1 + a2 * u2</p>
  126.      * @param date date of the built coordinates
  127.      * @param a1 first scale factor
  128.      * @param pv1 first base (unscaled) PVCoordinates
  129.      * @param a2 second scale factor
  130.      * @param pv2 second base (unscaled) PVCoordinates
  131.      */
  132.     public TimeStampedFieldPVCoordinates(final AbsoluteDate date,
  133.                                          final T a1, final FieldPVCoordinates<T> pv1,
  134.                                          final T a2, final FieldPVCoordinates<T> pv2) {
  135.         super(new FieldVector3D<T>(a1, pv1.getPosition(),     a2, pv2.getPosition()),
  136.               new FieldVector3D<T>(a1, pv1.getVelocity(),     a2, pv2.getVelocity()),
  137.               new FieldVector3D<T>(a1, pv1.getAcceleration(), a2, pv2.getAcceleration()));
  138.         this.date = date;
  139.     }

  140.     /** Linear constructor
  141.      * <p>Build a PVCoordinates from two other ones and corresponding scale factors.</p>
  142.      * <p>The PVCoordinates built will be a1 * u1 + a2 * u2</p>
  143.      * @param date date of the built coordinates
  144.      * @param a1 first scale factor
  145.      * @param pv1 first base (unscaled) PVCoordinates
  146.      * @param a2 second scale factor
  147.      * @param pv2 second base (unscaled) PVCoordinates
  148.      */
  149.     public TimeStampedFieldPVCoordinates(final AbsoluteDate date,
  150.                                          final T a1, final PVCoordinates pv1,
  151.                                          final T a2, final PVCoordinates pv2) {
  152.         super(new FieldVector3D<T>(a1, pv1.getPosition(),     a2, pv2.getPosition()),
  153.               new FieldVector3D<T>(a1, pv1.getVelocity(),     a2, pv2.getVelocity()),
  154.               new FieldVector3D<T>(a1, pv1.getAcceleration(), a2, pv2.getAcceleration()));
  155.         this.date = date;
  156.     }

  157.     /** Linear constructor
  158.      * <p>Build a PVCoordinates from three other ones and corresponding scale factors.</p>
  159.      * <p>The PVCoordinates built will be a1 * u1 + a2 * u2 + a3 * u3</p>
  160.      * @param date date of the built coordinates
  161.      * @param a1 first scale factor
  162.      * @param pv1 first base (unscaled) PVCoordinates
  163.      * @param a2 second scale factor
  164.      * @param pv2 second base (unscaled) PVCoordinates
  165.      * @param a3 third scale factor
  166.      * @param pv3 third base (unscaled) PVCoordinates
  167.      */
  168.     public TimeStampedFieldPVCoordinates(final AbsoluteDate date,
  169.                                          final double a1, final FieldPVCoordinates<T> pv1,
  170.                                          final double a2, final FieldPVCoordinates<T> pv2,
  171.                                          final double a3, final FieldPVCoordinates<T> pv3) {
  172.         super(new FieldVector3D<T>(a1, pv1.getPosition(),     a2, pv2.getPosition(),     a3, pv3.getPosition()),
  173.               new FieldVector3D<T>(a1, pv1.getVelocity(),     a2, pv2.getVelocity(),     a3, pv3.getVelocity()),
  174.               new FieldVector3D<T>(a1, pv1.getAcceleration(), a2, pv2.getAcceleration(), a3, pv3.getAcceleration()));
  175.         this.date = date;
  176.     }

  177.     /** Linear constructor
  178.      * <p>Build a PVCoordinates from three other ones and corresponding scale factors.</p>
  179.      * <p>The PVCoordinates built will be a1 * u1 + a2 * u2 + a3 * u3</p>
  180.      * @param date date of the built coordinates
  181.      * @param a1 first scale factor
  182.      * @param pv1 first base (unscaled) PVCoordinates
  183.      * @param a2 second scale factor
  184.      * @param pv2 second base (unscaled) PVCoordinates
  185.      * @param a3 third scale factor
  186.      * @param pv3 third base (unscaled) PVCoordinates
  187.      */
  188.     public TimeStampedFieldPVCoordinates(final AbsoluteDate date,
  189.                                          final T a1, final FieldPVCoordinates<T> pv1,
  190.                                          final T a2, final FieldPVCoordinates<T> pv2,
  191.                                          final T a3, final FieldPVCoordinates<T> pv3) {
  192.         super(new FieldVector3D<T>(a1, pv1.getPosition(),     a2, pv2.getPosition(),     a3, pv3.getPosition()),
  193.               new FieldVector3D<T>(a1, pv1.getVelocity(),     a2, pv2.getVelocity(),     a3, pv3.getVelocity()),
  194.               new FieldVector3D<T>(a1, pv1.getAcceleration(), a2, pv2.getAcceleration(), a3, pv3.getAcceleration()));
  195.         this.date = date;
  196.     }

  197.     /** Linear constructor
  198.      * <p>Build a PVCoordinates from three other ones and corresponding scale factors.</p>
  199.      * <p>The PVCoordinates built will be a1 * u1 + a2 * u2 + a3 * u3</p>
  200.      * @param date date of the built coordinates
  201.      * @param a1 first scale factor
  202.      * @param pv1 first base (unscaled) PVCoordinates
  203.      * @param a2 second scale factor
  204.      * @param pv2 second base (unscaled) PVCoordinates
  205.      * @param a3 third scale factor
  206.      * @param pv3 third base (unscaled) PVCoordinates
  207.      */
  208.     public TimeStampedFieldPVCoordinates(final AbsoluteDate date,
  209.                                          final T a1, final PVCoordinates pv1,
  210.                                          final T a2, final PVCoordinates pv2,
  211.                                          final T a3, final PVCoordinates pv3) {
  212.         super(new FieldVector3D<T>(a1, pv1.getPosition(),     a2, pv2.getPosition(),     a3, pv3.getPosition()),
  213.               new FieldVector3D<T>(a1, pv1.getVelocity(),     a2, pv2.getVelocity(),     a3, pv3.getVelocity()),
  214.               new FieldVector3D<T>(a1, pv1.getAcceleration(), a2, pv2.getAcceleration(), a3, pv3.getAcceleration()));
  215.         this.date = date;
  216.     }

  217.     /** Linear constructor
  218.      * <p>Build a PVCoordinates from four other ones and corresponding scale factors.</p>
  219.      * <p>The PVCoordinates built will be a1 * u1 + a2 * u2 + a3 * u3 + a4 * u4</p>
  220.      * @param date date of the built coordinates
  221.      * @param a1 first scale factor
  222.      * @param pv1 first base (unscaled) PVCoordinates
  223.      * @param a2 second scale factor
  224.      * @param pv2 second base (unscaled) PVCoordinates
  225.      * @param a3 third scale factor
  226.      * @param pv3 third base (unscaled) PVCoordinates
  227.      * @param a4 fourth scale factor
  228.      * @param pv4 fourth base (unscaled) PVCoordinates
  229.      */
  230.     public TimeStampedFieldPVCoordinates(final AbsoluteDate date,
  231.                                          final double a1, final FieldPVCoordinates<T> pv1,
  232.                                          final double a2, final FieldPVCoordinates<T> pv2,
  233.                                          final double a3, final FieldPVCoordinates<T> pv3,
  234.                                          final double a4, final FieldPVCoordinates<T> pv4) {
  235.         super(new FieldVector3D<T>(a1, pv1.getPosition(),     a2, pv2.getPosition(),
  236.                                    a3, pv3.getPosition(),     a4, pv4.getPosition()),
  237.               new FieldVector3D<T>(a1, pv1.getVelocity(),     a2, pv2.getVelocity(),
  238.                                    a3, pv3.getVelocity(),     a4, pv4.getVelocity()),
  239.               new FieldVector3D<T>(a1, pv1.getAcceleration(), a2, pv2.getAcceleration(),
  240.                                    a3, pv3.getAcceleration(), a4, pv4.getAcceleration()));
  241.         this.date = date;
  242.     }

  243.     /** Linear constructor
  244.      * <p>Build a PVCoordinates from four other ones and corresponding scale factors.</p>
  245.      * <p>The PVCoordinates built will be a1 * u1 + a2 * u2 + a3 * u3 + a4 * u4</p>
  246.      * @param date date of the built coordinates
  247.      * @param a1 first scale factor
  248.      * @param pv1 first base (unscaled) PVCoordinates
  249.      * @param a2 second scale factor
  250.      * @param pv2 second base (unscaled) PVCoordinates
  251.      * @param a3 third scale factor
  252.      * @param pv3 third base (unscaled) PVCoordinates
  253.      * @param a4 fourth scale factor
  254.      * @param pv4 fourth base (unscaled) PVCoordinates
  255.      */
  256.     public TimeStampedFieldPVCoordinates(final AbsoluteDate date,
  257.                                          final T a1, final FieldPVCoordinates<T> pv1,
  258.                                          final T a2, final FieldPVCoordinates<T> pv2,
  259.                                          final T a3, final FieldPVCoordinates<T> pv3,
  260.                                          final T a4, final FieldPVCoordinates<T> pv4) {
  261.         super(new FieldVector3D<T>(a1, pv1.getPosition(),     a2, pv2.getPosition(),
  262.                                    a3, pv3.getPosition(),     a4, pv4.getPosition()),
  263.               new FieldVector3D<T>(a1, pv1.getVelocity(),     a2, pv2.getVelocity(),
  264.                                    a3, pv3.getVelocity(),     a4, pv4.getVelocity()),
  265.               new FieldVector3D<T>(a1, pv1.getAcceleration(), a2, pv2.getAcceleration(),
  266.                                    a3, pv3.getAcceleration(), a4, pv4.getAcceleration()));
  267.         this.date = date;
  268.     }

  269.     /** Linear constructor
  270.      * <p>Build a PVCoordinates from four other ones and corresponding scale factors.</p>
  271.      * <p>The PVCoordinates built will be a1 * u1 + a2 * u2 + a3 * u3 + a4 * u4</p>
  272.      * @param date date of the built coordinates
  273.      * @param a1 first scale factor
  274.      * @param pv1 first base (unscaled) PVCoordinates
  275.      * @param a2 second scale factor
  276.      * @param pv2 second base (unscaled) PVCoordinates
  277.      * @param a3 third scale factor
  278.      * @param pv3 third base (unscaled) PVCoordinates
  279.      * @param a4 fourth scale factor
  280.      * @param pv4 fourth base (unscaled) PVCoordinates
  281.      */
  282.     public TimeStampedFieldPVCoordinates(final AbsoluteDate date,
  283.                                          final T a1, final PVCoordinates pv1,
  284.                                          final T a2, final PVCoordinates pv2,
  285.                                          final T a3, final PVCoordinates pv3,
  286.                                          final T a4, final PVCoordinates pv4) {
  287.         super(new FieldVector3D<T>(a1, pv1.getPosition(),     a2, pv2.getPosition(),
  288.                                    a3, pv3.getPosition(),     a4, pv4.getPosition()),
  289.               new FieldVector3D<T>(a1, pv1.getVelocity(),     a2, pv2.getVelocity(),
  290.                                    a3, pv3.getVelocity(),     a4, pv4.getVelocity()),
  291.               new FieldVector3D<T>(a1, pv1.getAcceleration(), a2, pv2.getAcceleration(),
  292.                                    a3, pv3.getAcceleration(), a4, pv4.getAcceleration()));
  293.         this.date = date;
  294.     }

  295.     /** {@inheritDoc} */
  296.     public AbsoluteDate getDate() {
  297.         return date;
  298.     }

  299.     /** Get a time-shifted state.
  300.      * <p>
  301.      * The state can be slightly shifted to close dates. This shift is based on
  302.      * a simple linear model. It is <em>not</em> intended as a replacement for
  303.      * proper orbit propagation (it is not even Keplerian!) but should be sufficient
  304.      * for either small time shifts or coarse accuracy.
  305.      * </p>
  306.      * @param dt time shift in seconds
  307.      * @return a new state, shifted with respect to the instance (which is immutable)
  308.      */
  309.     public TimeStampedFieldPVCoordinates<T> shiftedBy(final double dt) {
  310.         final FieldPVCoordinates<T> spv = super.shiftedBy(dt);
  311.         return new TimeStampedFieldPVCoordinates<T>(date.shiftedBy(dt),
  312.                                                     spv.getPosition(), spv.getVelocity(), spv.getAcceleration());
  313.     }

  314.     /** Interpolate position-velocity.
  315.      * <p>
  316.      * The interpolated instance is created by polynomial Hermite interpolation
  317.      * ensuring velocity remains the exact derivative of position.
  318.      * </p>
  319.      * <p>
  320.      * Note that even if first time derivatives (velocities)
  321.      * from sample can be ignored, the interpolated instance always includes
  322.      * interpolated derivatives. This feature can be used explicitly to
  323.      * compute these derivatives when it would be too complex to compute them
  324.      * from an analytical formula: just compute a few sample points from the
  325.      * explicit formula and set the derivatives to zero in these sample points,
  326.      * then use interpolation to add derivatives consistent with the positions.
  327.      * </p>
  328.      * @param date interpolation date
  329.      * @param filter filter for derivatives from the sample to use in interpolation
  330.      * @param sample sample points on which interpolation should be done
  331.      * @param <T> the type of the field elements
  332.      * @return a new position-velocity, interpolated at specified date
  333.      */
  334.     @SuppressWarnings("unchecked")
  335.     public static <T extends RealFieldElement<T>>
  336.         TimeStampedFieldPVCoordinates<T> interpolate(final AbsoluteDate date,
  337.                                                      final CartesianDerivativesFilter filter,
  338.                                                      final Collection<TimeStampedFieldPVCoordinates<T>> sample) {

  339.         // get field properties
  340.         final T prototype = sample.iterator().next().getPosition().getX();
  341.         final T zero      = prototype.getField().getZero();

  342.         // set up an interpolator taking derivatives into account
  343.         final FieldHermiteInterpolator<T> interpolator = new FieldHermiteInterpolator<T>();

  344.         // add sample points
  345.         switch (filter) {
  346.             case USE_P :
  347.                 // populate sample with position data, ignoring velocity
  348.                 for (final TimeStampedFieldPVCoordinates<T> datedPV : sample) {
  349.                     final FieldVector3D<T> position = datedPV.getPosition();
  350.                     interpolator.addSamplePoint(zero.add(datedPV.getDate().durationFrom(date)),
  351.                                                 position.toArray());
  352.                 }
  353.                 break;
  354.             case USE_PV :
  355.                 // populate sample with position and velocity data
  356.                 for (final TimeStampedFieldPVCoordinates<T> datedPV : sample) {
  357.                     final FieldVector3D<T> position = datedPV.getPosition();
  358.                     final FieldVector3D<T> velocity = datedPV.getVelocity();
  359.                     interpolator.addSamplePoint(zero.add(datedPV.getDate().durationFrom(date)),
  360.                                                 position.toArray(), velocity.toArray());
  361.                 }
  362.                 break;
  363.             case USE_PVA :
  364.                 // populate sample with position, velocity and acceleration data
  365.                 for (final TimeStampedFieldPVCoordinates<T> datedPV : sample) {
  366.                     final FieldVector3D<T> position     = datedPV.getPosition();
  367.                     final FieldVector3D<T> velocity     = datedPV.getVelocity();
  368.                     final FieldVector3D<T> acceleration = datedPV.getAcceleration();
  369.                     interpolator.addSamplePoint(zero.add(datedPV.getDate().durationFrom(date)),
  370.                                                 position.toArray(), velocity.toArray(), acceleration.toArray());
  371.                 }
  372.                 break;
  373.             default :
  374.                 // this should never happen
  375.                 throw new OrekitInternalError(null);
  376.         }

  377.         // interpolate
  378.         final T[][] p = interpolator.derivatives(zero, 2);

  379.         // build a new interpolated instance
  380.         return new TimeStampedFieldPVCoordinates<T>(date,
  381.                                                     new FieldVector3D<T>(p[0]),
  382.                                                     new FieldVector3D<T>(p[1]),
  383.                                                     new FieldVector3D<T>(p[2]));

  384.     }

  385.     /** Return a string representation of this position/velocity pair.
  386.      * @return string representation of this position/velocity pair
  387.      */
  388.     public String toString() {
  389.         final String comma = ", ";
  390.         return new StringBuffer().append('{').append(date).append(", P(").
  391.                                   append(getPosition().getX().getReal()).append(comma).
  392.                                   append(getPosition().getY().getReal()).append(comma).
  393.                                   append(getPosition().getZ().getReal()).append("), V(").
  394.                                   append(getVelocity().getX().getReal()).append(comma).
  395.                                   append(getVelocity().getY().getReal()).append(comma).
  396.                                   append(getVelocity().getZ().getReal()).append("), A(").
  397.                                   append(getAcceleration().getX().getReal()).append(comma).
  398.                                   append(getAcceleration().getY().getReal()).append(comma).
  399.                                   append(getAcceleration().getZ().getReal()).append(")}").toString();
  400.     }

  401. }