TimeStampedPVCoordinates.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.utils;

  18. import org.hipparchus.analysis.differentiation.Derivative;
  19. import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
  20. import org.hipparchus.geometry.euclidean.threed.Vector3D;
  21. import org.orekit.annotation.DefaultDataContext;
  22. import org.orekit.data.DataContext;
  23. import org.orekit.frames.Frame;
  24. import org.orekit.frames.StaticTransform;
  25. import org.orekit.frames.Transform;
  26. import org.orekit.time.AbsoluteDate;
  27. import org.orekit.time.TimeOffset;
  28. import org.orekit.time.TimeScale;
  29. import org.orekit.time.TimeStamped;

  30. /** {@link TimeStamped time-stamped} version of {@link PVCoordinates}.
  31.  * <p>Instances of this class are guaranteed to be immutable.</p>
  32.  * @author Luc Maisonobe
  33.  * @since 7.0
  34.  */
  35. public class TimeStampedPVCoordinates extends PVCoordinates implements TimeStamped {

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

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

  49.     /**
  50.      * Build from position and velocity. Acceleration is set to zero.
  51.      *
  52.      * @param date coordinates date
  53.      * @param position the position vector (m)
  54.      * @param velocity the velocity vector (m/s)
  55.      */
  56.     public TimeStampedPVCoordinates(final AbsoluteDate date,
  57.                                     final Vector3D position,
  58.                                     final Vector3D velocity) {
  59.         this(date, position, velocity, Vector3D.ZERO);
  60.     }

  61.     /**
  62.      * Build from position velocity acceleration coordinates.
  63.      *
  64.      * @param date coordinates date
  65.      * @param pv position velocity, and acceleration coordinates, in meters and seconds.
  66.      */
  67.     public TimeStampedPVCoordinates(final AbsoluteDate date, final PVCoordinates pv) {
  68.         this(date, pv.getPosition(), pv.getVelocity(), pv.getAcceleration());
  69.     }

  70.     /** Multiplicative constructor
  71.      * <p>Build a TimeStampedPVCoordinates from another one and a scale factor.</p>
  72.      * <p>The TimeStampedPVCoordinates built will be a * pv</p>
  73.      * @param date date of the built coordinates
  74.      * @param a scale factor
  75.      * @param pv base (unscaled) PVCoordinates
  76.      */
  77.     public TimeStampedPVCoordinates(final AbsoluteDate date,
  78.                                     final double a, final PVCoordinates pv) {
  79.         super(new Vector3D(a, pv.getPosition()),
  80.               new Vector3D(a, pv.getVelocity()),
  81.               new Vector3D(a, pv.getAcceleration()));
  82.         this.date = date;
  83.     }

  84.     /** Subtractive constructor
  85.      * <p>Build a relative TimeStampedPVCoordinates from a start and an end position.</p>
  86.      * <p>The TimeStampedPVCoordinates built will be end - start.</p>
  87.      * @param date date of the built coordinates
  88.      * @param start Starting PVCoordinates
  89.      * @param end ending PVCoordinates
  90.      */
  91.     public TimeStampedPVCoordinates(final AbsoluteDate date,
  92.                                     final PVCoordinates start, final PVCoordinates end) {
  93.         super(end.getPosition().subtract(start.getPosition()),
  94.               end.getVelocity().subtract(start.getVelocity()),
  95.               end.getAcceleration().subtract(start.getAcceleration()));
  96.         this.date = date;
  97.     }

  98.     /** Linear constructor
  99.      * <p>Build a TimeStampedPVCoordinates from two other ones and corresponding scale factors.</p>
  100.      * <p>The TimeStampedPVCoordinates built will be a1 * u1 + a2 * u2</p>
  101.      * @param date date of the built coordinates
  102.      * @param a1 first scale factor
  103.      * @param pv1 first base (unscaled) PVCoordinates
  104.      * @param a2 second scale factor
  105.      * @param pv2 second base (unscaled) PVCoordinates
  106.      */
  107.     public TimeStampedPVCoordinates(final AbsoluteDate date,
  108.                                     final double a1, final PVCoordinates pv1,
  109.                                     final double a2, final PVCoordinates pv2) {
  110.         super(new Vector3D(a1, pv1.getPosition(),     a2, pv2.getPosition()),
  111.               new Vector3D(a1, pv1.getVelocity(),     a2, pv2.getVelocity()),
  112.               new Vector3D(a1, pv1.getAcceleration(), a2, pv2.getAcceleration()));
  113.         this.date = date;
  114.     }

  115.     /** Linear constructor
  116.      * <p>Build a TimeStampedPVCoordinates from three other ones and corresponding scale factors.</p>
  117.      * <p>The TimeStampedPVCoordinates built will be a1 * u1 + a2 * u2 + a3 * u3</p>
  118.      * @param date date of the built coordinates
  119.      * @param a1 first scale factor
  120.      * @param pv1 first base (unscaled) PVCoordinates
  121.      * @param a2 second scale factor
  122.      * @param pv2 second base (unscaled) PVCoordinates
  123.      * @param a3 third scale factor
  124.      * @param pv3 third base (unscaled) PVCoordinates
  125.      */
  126.     public TimeStampedPVCoordinates(final AbsoluteDate date,
  127.                                     final double a1, final PVCoordinates pv1,
  128.                                     final double a2, final PVCoordinates pv2,
  129.                                     final double a3, final PVCoordinates pv3) {
  130.         super(new Vector3D(a1, pv1.getPosition(),     a2, pv2.getPosition(),     a3, pv3.getPosition()),
  131.               new Vector3D(a1, pv1.getVelocity(),     a2, pv2.getVelocity(),     a3, pv3.getVelocity()),
  132.               new Vector3D(a1, pv1.getAcceleration(), a2, pv2.getAcceleration(), a3, pv3.getAcceleration()));
  133.         this.date = date;
  134.     }

  135.     /** Linear constructor
  136.      * <p>Build a TimeStampedPVCoordinates from four other ones and corresponding scale factors.</p>
  137.      * <p>The TimeStampedPVCoordinates built will be a1 * u1 + a2 * u2 + a3 * u3 + a4 * u4</p>
  138.      * @param date date of the built coordinates
  139.      * @param a1 first scale factor
  140.      * @param pv1 first base (unscaled) PVCoordinates
  141.      * @param a2 second scale factor
  142.      * @param pv2 second base (unscaled) PVCoordinates
  143.      * @param a3 third scale factor
  144.      * @param pv3 third base (unscaled) PVCoordinates
  145.      * @param a4 fourth scale factor
  146.      * @param pv4 fourth base (unscaled) PVCoordinates
  147.      */
  148.     public TimeStampedPVCoordinates(final AbsoluteDate date,
  149.                                     final double a1, final PVCoordinates pv1,
  150.                                     final double a2, final PVCoordinates pv2,
  151.                                     final double a3, final PVCoordinates pv3,
  152.                                     final double a4, final PVCoordinates pv4) {
  153.         super(new Vector3D(a1, pv1.getPosition(),     a2, pv2.getPosition(),     a3, pv3.getPosition(),     a4, pv4.getPosition()),
  154.               new Vector3D(a1, pv1.getVelocity(),     a2, pv2.getVelocity(),     a3, pv3.getVelocity(),     a4, pv4.getVelocity()),
  155.               new Vector3D(a1, pv1.getAcceleration(), a2, pv2.getAcceleration(), a3, pv3.getAcceleration(), a4, pv4.getAcceleration()));
  156.         this.date = date;
  157.     }

  158.     /** Builds a TimeStampedPVCoordinates triplet from  a {@link FieldVector3D}&lt;{@link Derivative}&gt;.
  159.      * <p>
  160.      * The vector components must have time as their only derivation parameter and
  161.      * have consistent derivation orders.
  162.      * </p>
  163.      * @param date date of the built coordinates
  164.      * @param p vector with time-derivatives embedded within the coordinates
  165.      * @param <U> type of the derivative
  166.      */
  167.     public <U extends Derivative<U>> TimeStampedPVCoordinates(final AbsoluteDate date, final FieldVector3D<U> p) {
  168.         super(p);
  169.         this.date = date;
  170.     }

  171.     /** {@inheritDoc} */
  172.     public AbsoluteDate getDate() {
  173.         return date;
  174.     }

  175.     /** Get a time-shifted state.
  176.      * <p>
  177.      * The state can be slightly shifted to close dates. This shift is based on
  178.      * a simple Taylor expansion. It is <em>not</em> intended as a replacement for
  179.      * proper orbit propagation (it is not even Keplerian!) but should be sufficient
  180.      * for either small time shifts or coarse accuracy.
  181.      * </p>
  182.      * @param dt time shift in seconds
  183.      * @return a new state, shifted with respect to the instance (which is immutable)
  184.      */
  185.     public TimeStampedPVCoordinates shiftedBy(final double dt) {
  186.         final PVCoordinates spv = super.shiftedBy(dt);
  187.         return new TimeStampedPVCoordinates(date.shiftedBy(dt),
  188.                                             spv.getPosition(), spv.getVelocity(), spv.getAcceleration());
  189.     }

  190.     /** Get a time-shifted state.
  191.      * <p>
  192.      * The state can be slightly shifted to close dates. This shift is based on
  193.      * a simple Taylor expansion. It is <em>not</em> intended as a replacement for
  194.      * proper orbit propagation (it is not even Keplerian!) but should be sufficient
  195.      * for either small time shifts or coarse accuracy.
  196.      * </p>
  197.      * @param dt time shift
  198.      * @return a new state, shifted with respect to the instance (which is immutable)
  199.      * @since 13.0
  200.      */
  201.     public TimeStampedPVCoordinates shiftedBy(final TimeOffset dt) {
  202.         final PVCoordinates spv = super.shiftedBy(dt);
  203.         return new TimeStampedPVCoordinates(date.shiftedBy(dt),
  204.                                             spv.getPosition(), spv.getVelocity(), spv.getAcceleration());
  205.     }

  206.     /** Create a local provider using simply Taylor expansion through {@link #shiftedBy(double)}.
  207.      * <p>
  208.      * The time evolution is based on a simple Taylor expansion. It is <em>not</em> intended as a
  209.      * replacement for proper orbit propagation (it is not even Keplerian!) but should be sufficient
  210.      * for either small time shifts or coarse accuracy.
  211.      * </p>
  212.      * @param instanceFrame frame in which the instance is defined
  213.      * @return provider based on Taylor expansion, for small time shifts around instance date
  214.      */
  215.     public PVCoordinatesProvider toTaylorProvider(final Frame instanceFrame) {
  216.         return new PVCoordinatesProvider() {
  217.             /** {@inheritDoc} */
  218.             public Vector3D getPosition(final AbsoluteDate d,  final Frame f) {
  219.                 final TimeStampedPVCoordinates shifted   = shiftedBy(d.durationFrom(getDate()));
  220.                 final StaticTransform          transform = instanceFrame.getStaticTransformTo(f, d);
  221.                 return transform.transformPosition(shifted.getPosition());
  222.             }
  223.             /** {@inheritDoc} */
  224.             public TimeStampedPVCoordinates getPVCoordinates(final AbsoluteDate d,  final Frame f) {
  225.                 final TimeStampedPVCoordinates shifted   = shiftedBy(d.durationFrom(date));
  226.                 final Transform                transform = instanceFrame.getTransformTo(f, d);
  227.                 return transform.transformPVCoordinates(shifted);
  228.             }
  229.         };
  230.     }

  231.     /** Return a string representation of this date, position, velocity, and acceleration.
  232.      *
  233.      * <p>This method uses the {@link DataContext#getDefault() default data context}.
  234.      *
  235.      * @return string representation of this.
  236.      */
  237.     @Override
  238.     @DefaultDataContext
  239.     public String toString() {
  240.         return toString(DataContext.getDefault().getTimeScales().getUTC());
  241.     }

  242.     /**
  243.      * Return a string representation of this date, position, velocity, and acceleration.
  244.      *
  245.      * @param utc time scale used to print the date.
  246.      * @return string representation of this.
  247.      */
  248.     public String toString(final TimeScale utc) {
  249.         final String comma = ", ";
  250.         return new StringBuilder().append('{').
  251.                                   append(date.toString(utc)).append(", P(").
  252.                                   append(getPosition().getX()).append(comma).
  253.                                   append(getPosition().getY()).append(comma).
  254.                                   append(getPosition().getZ()).append("), V(").
  255.                                   append(getVelocity().getX()).append(comma).
  256.                                   append(getVelocity().getY()).append(comma).
  257.                                   append(getVelocity().getZ()).append("), A(").
  258.                                   append(getAcceleration().getX()).append(comma).
  259.                                   append(getAcceleration().getY()).append(comma).
  260.                                   append(getAcceleration().getZ()).append(")}").toString();
  261.     }

  262. }