AbsolutePVCoordinates.java

  1. /* Copyright 2002-2023 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 java.io.Serializable;

  19. import org.hipparchus.analysis.differentiation.Derivative;
  20. import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
  21. import org.hipparchus.geometry.euclidean.threed.Vector3D;
  22. import org.hipparchus.util.FastMath;
  23. import org.orekit.annotation.DefaultDataContext;
  24. import org.orekit.data.DataContext;
  25. import org.orekit.errors.OrekitException;
  26. import org.orekit.errors.OrekitIllegalArgumentException;
  27. import org.orekit.errors.OrekitMessages;
  28. import org.orekit.frames.Frame;
  29. import org.orekit.frames.StaticTransform;
  30. import org.orekit.frames.Transform;
  31. import org.orekit.time.AbsoluteDate;
  32. import org.orekit.time.TimeStamped;

  33. /** Position - Velocity - Acceleration linked to a date and a frame.
  34.  */
  35. public class AbsolutePVCoordinates extends TimeStampedPVCoordinates
  36.     implements TimeStamped, Serializable, PVCoordinatesProvider {

  37.     /** Serializable UID. */
  38.     private static final long serialVersionUID = 20150824L;

  39.     /** Frame in which are defined the coordinates. */
  40.     private final Frame frame;

  41.     /** Build from position, velocity, acceleration.
  42.      * @param frame the frame in which the coordinates are defined
  43.      * @param date coordinates date
  44.      * @param position the position vector (m)
  45.      * @param velocity the velocity vector (m/s)
  46.      * @param acceleration the acceleration vector (m/sÂý)
  47.      */
  48.     public AbsolutePVCoordinates(final Frame frame, final AbsoluteDate date,
  49.                                  final Vector3D position, final Vector3D velocity, final Vector3D acceleration) {
  50.         super(date, position, velocity, acceleration);
  51.         this.frame = frame;
  52.     }

  53.     /** Build from position and velocity. Acceleration is set to zero.
  54.      * @param frame the frame in which the coordinates are defined
  55.      * @param date coordinates date
  56.      * @param position the position vector (m)
  57.      * @param velocity the velocity vector (m/s)
  58.      */
  59.     public AbsolutePVCoordinates(final Frame frame, final AbsoluteDate date,
  60.                                  final Vector3D position,
  61.                                  final Vector3D velocity) {
  62.         this(frame, date, position, velocity, Vector3D.ZERO);
  63.     }

  64.     /** Build from frame, date and PVA coordinates.
  65.      * @param frame the frame in which the coordinates are defined
  66.      * @param date date of the coordinates
  67.      * @param pva TimeStampedPVCoordinates
  68.      */
  69.     public AbsolutePVCoordinates(final Frame frame, final AbsoluteDate date, final PVCoordinates pva) {
  70.         super(date, pva);
  71.         this.frame = frame;
  72.     }

  73.     /** Build from frame and TimeStampedPVCoordinates.
  74.      * @param frame the frame in which the coordinates are defined
  75.      * @param pva TimeStampedPVCoordinates
  76.      */
  77.     public AbsolutePVCoordinates(final Frame frame, final TimeStampedPVCoordinates pva) {
  78.         super(pva.getDate(), pva);
  79.         this.frame = frame;
  80.     }

  81.     /** Multiplicative constructor
  82.      * <p>Build a AbsolutePVCoordinates from another one and a scale factor.</p>
  83.      * <p>The TimeStampedPVCoordinates built will be a * AbsPva</p>
  84.      * @param date date of the built coordinates
  85.      * @param a scale factor
  86.      * @param AbsPva base (unscaled) AbsolutePVCoordinates
  87.      */
  88.     public AbsolutePVCoordinates(final AbsoluteDate date,
  89.                                  final double a, final AbsolutePVCoordinates AbsPva) {
  90.         super(date, a, AbsPva);
  91.         this.frame = AbsPva.frame;
  92.     }

  93.     /** Subtractive constructor
  94.      * <p>Build a relative AbsolutePVCoordinates from a start and an end position.</p>
  95.      * <p>The AbsolutePVCoordinates built will be end - start.</p>
  96.      * <p>In case start and end use two different pseudo-inertial frames,
  97.      * the new AbsolutePVCoordinates arbitrarily be defined in the start frame. </p>
  98.      * @param date date of the built coordinates
  99.      * @param start Starting AbsolutePVCoordinates
  100.      * @param end ending AbsolutePVCoordinates
  101.      */
  102.     public AbsolutePVCoordinates(final AbsoluteDate date,
  103.                                  final AbsolutePVCoordinates start, final AbsolutePVCoordinates end) {
  104.         super(date, start, end);
  105.         ensureIdenticalFrames(start, end);
  106.         this.frame = start.frame;
  107.     }

  108.     /** Linear constructor
  109.      * <p>Build a AbsolutePVCoordinates from two other ones and corresponding scale factors.</p>
  110.      * <p>The AbsolutePVCoordinates built will be a1 * u1 + a2 * u2</p>
  111.      * <p>In case the AbsolutePVCoordinates use different pseudo-inertial frames,
  112.      * the new AbsolutePVCoordinates arbitrarily be defined in the first frame. </p>
  113.      * @param date date of the built coordinates
  114.      * @param a1 first scale factor
  115.      * @param absPv1 first base (unscaled) AbsolutePVCoordinates
  116.      * @param a2 second scale factor
  117.      * @param absPv2 second base (unscaled) AbsolutePVCoordinates
  118.      */
  119.     public AbsolutePVCoordinates(final AbsoluteDate date,
  120.                                  final double a1, final AbsolutePVCoordinates absPv1,
  121.                                  final double a2, final AbsolutePVCoordinates absPv2) {
  122.         super(date, a1, absPv1.getPVCoordinates(), a2, absPv2.getPVCoordinates());
  123.         ensureIdenticalFrames(absPv1, absPv2);
  124.         this.frame = absPv1.getFrame();
  125.     }

  126.     /** Linear constructor
  127.      * <p>Build a AbsolutePVCoordinates from three other ones and corresponding scale factors.</p>
  128.      * <p>The AbsolutePVCoordinates built will be a1 * u1 + a2 * u2 + a3 * u3</p>
  129.      * <p>In case the AbsolutePVCoordinates use different pseudo-inertial frames,
  130.      * the new AbsolutePVCoordinates arbitrarily be defined in the first frame. </p>
  131.      * @param date date of the built coordinates
  132.      * @param a1 first scale factor
  133.      * @param absPv1 first base (unscaled) AbsolutePVCoordinates
  134.      * @param a2 second scale factor
  135.      * @param absPv2 second base (unscaled) AbsolutePVCoordinates
  136.      * @param a3 third scale factor
  137.      * @param absPv3 third base (unscaled) AbsolutePVCoordinates
  138.      */
  139.     public AbsolutePVCoordinates(final AbsoluteDate date,
  140.                                  final double a1, final AbsolutePVCoordinates absPv1,
  141.                                  final double a2, final AbsolutePVCoordinates absPv2,
  142.                                  final double a3, final AbsolutePVCoordinates absPv3) {
  143.         super(date, a1, absPv1.getPVCoordinates(), a2, absPv2.getPVCoordinates(),
  144.                 a3, absPv3.getPVCoordinates());
  145.         ensureIdenticalFrames(absPv1, absPv2);
  146.         ensureIdenticalFrames(absPv1, absPv3);
  147.         this.frame = absPv1.getFrame();
  148.     }

  149.     /** Linear constructor
  150.      * <p>Build a AbsolutePVCoordinates from four other ones and corresponding scale factors.</p>
  151.      * <p>The AbsolutePVCoordinates built will be a1 * u1 + a2 * u2 + a3 * u3 + a4 * u4</p>
  152.      * <p>In case the AbsolutePVCoordinates use different pseudo-inertial frames,
  153.      * the new AbsolutePVCoordinates arbitrarily be defined in the first frame. </p>
  154.      * @param date date of the built coordinates
  155.      * @param a1 first scale factor
  156.      * @param absPv1 first base (unscaled) AbsolutePVCoordinates
  157.      * @param a2 second scale factor
  158.      * @param absPv2 second base (unscaled) AbsolutePVCoordinates
  159.      * @param a3 third scale factor
  160.      * @param absPv3 third base (unscaled) AbsolutePVCoordinates
  161.      * @param a4 fourth scale factor
  162.      * @param absPv4 fourth base (unscaled) AbsolutePVCoordinates
  163.      */
  164.     public AbsolutePVCoordinates(final AbsoluteDate date,
  165.                                  final double a1, final AbsolutePVCoordinates absPv1,
  166.                                  final double a2, final AbsolutePVCoordinates absPv2,
  167.                                  final double a3, final AbsolutePVCoordinates absPv3,
  168.                                  final double a4, final AbsolutePVCoordinates absPv4) {
  169.         super(date, a1, absPv1.getPVCoordinates(), a2, absPv2.getPVCoordinates(),
  170.                 a3, absPv3.getPVCoordinates(), a4, absPv4.getPVCoordinates());
  171.         ensureIdenticalFrames(absPv1, absPv2);
  172.         ensureIdenticalFrames(absPv1, absPv3);
  173.         ensureIdenticalFrames(absPv1, absPv4);
  174.         this.frame = absPv1.getFrame();
  175.     }

  176.     /** Builds a AbsolutePVCoordinates triplet from  a {@link FieldVector3D}&lt;{@link Derivative}&gt;.
  177.      * <p>
  178.      * The vector components must have time as their only derivation parameter and
  179.      * have consistent derivation orders.
  180.      * </p>
  181.      * @param frame the frame in which the parameters are defined
  182.      * @param date date of the built coordinates
  183.      * @param p vector with time-derivatives embedded within the coordinates
  184.      * @param <U> type of the derivative
  185.      */
  186.     public <U extends Derivative<U>> AbsolutePVCoordinates(final Frame frame, final AbsoluteDate date,
  187.                                                            final FieldVector3D<U> p) {
  188.         super(date, p);
  189.         this.frame = frame;
  190.     }

  191.     /** Ensure that the frames from two AbsolutePVCoordinates are identical.
  192.      * @param absPv1 first AbsolutePVCoordinates
  193.      * @param absPv2 first AbsolutePVCoordinates
  194.      * @throws OrekitIllegalArgumentException if frames are different
  195.      */
  196.     private static void ensureIdenticalFrames(final AbsolutePVCoordinates absPv1, final AbsolutePVCoordinates absPv2)
  197.         throws OrekitIllegalArgumentException {
  198.         if (!absPv1.frame.equals(absPv2.frame)) {
  199.             throw new OrekitIllegalArgumentException(OrekitMessages.INCOMPATIBLE_FRAMES,
  200.                                                      absPv1.frame.getName(), absPv2.frame.getName());
  201.         }
  202.     }

  203.     /** Get a time-shifted state.
  204.      * <p>
  205.      * The state can be slightly shifted to close dates. This shift is based on
  206.      * a simple Taylor expansion. It is <em>not</em> intended as a replacement for
  207.      * proper orbit propagation (it is not even Keplerian!) but should be sufficient
  208.      * for either small time shifts or coarse accuracy.
  209.      * </p>
  210.      * @param dt time shift in seconds
  211.      * @return a new state, shifted with respect to the instance (which is immutable)
  212.      */
  213.     public AbsolutePVCoordinates shiftedBy(final double dt) {
  214.         final TimeStampedPVCoordinates spv = super.shiftedBy(dt);
  215.         return new AbsolutePVCoordinates(frame, spv);
  216.     }

  217.     /** Create a local provider using simply Taylor expansion through {@link #shiftedBy(double)}.
  218.      * <p>
  219.      * The time evolution is based on a simple Taylor expansion. It is <em>not</em> intended as a
  220.      * replacement for proper orbit propagation (it is not even Keplerian!) but should be sufficient
  221.      * for either small time shifts or coarse accuracy.
  222.      * </p>
  223.      * @return provider based on Taylor expansion, for small time shifts around instance date
  224.      */
  225.     public PVCoordinatesProvider toTaylorProvider() {
  226.         return new PVCoordinatesProvider() {
  227.             /** {@inheritDoc} */
  228.             public Vector3D getPosition(final AbsoluteDate d,  final Frame f) {
  229.                 final TimeStampedPVCoordinates shifted   = shiftedBy(d.durationFrom(getDate()));
  230.                 final StaticTransform          transform = frame.getStaticTransformTo(f, d);
  231.                 return transform.transformPosition(shifted.getPosition());
  232.             }
  233.             /** {@inheritDoc} */
  234.             public TimeStampedPVCoordinates getPVCoordinates(final AbsoluteDate d,  final Frame f) {
  235.                 final TimeStampedPVCoordinates shifted   = shiftedBy(d.durationFrom(getDate()));
  236.                 final Transform                transform = frame.getTransformTo(f, d);
  237.                 return transform.transformPVCoordinates(shifted);
  238.             }
  239.         };
  240.     }

  241.     /** Get the frame in which the coordinates are defined.
  242.      * @return frame in which the coordinates are defined
  243.      */
  244.     public Frame getFrame() {
  245.         return frame;
  246.     }

  247.     /** Get the TimeStampedPVCoordinates.
  248.      * @return TimeStampedPVCoordinates
  249.      */
  250.     public TimeStampedPVCoordinates getPVCoordinates() {
  251.         return this;
  252.     }

  253.     /** Get the position in a specified frame.
  254.      * @param outputFrame frame in which the position coordinates shall be computed
  255.      * @return position
  256.      * @see #getPVCoordinates(Frame)
  257.      * @since 12.0
  258.      */
  259.     public Vector3D getPosition(final Frame outputFrame) {
  260.         // If output frame requested is the same as definition frame,
  261.         // Position vector is returned directly
  262.         if (outputFrame == frame) {
  263.             return getPosition();
  264.         }

  265.         // Else, position vector is transformed to output frame
  266.         final StaticTransform t = frame.getStaticTransformTo(outputFrame, getDate());
  267.         return t.transformPosition(getPosition());
  268.     }

  269.     /** Get the TimeStampedPVCoordinates in a specified frame.
  270.      * @param outputFrame frame in which the position/velocity coordinates shall be computed
  271.      * @return TimeStampedPVCoordinates
  272.      * @exception OrekitException if transformation between frames cannot be computed
  273.      * @see #getPVCoordinates()
  274.      */
  275.     public TimeStampedPVCoordinates getPVCoordinates(final Frame outputFrame) {
  276.         // If output frame requested is the same as definition frame,
  277.         // PV coordinates are returned directly
  278.         if (outputFrame == frame) {
  279.             return getPVCoordinates();
  280.         }

  281.         // Else, PV coordinates are transformed to output frame
  282.         final Transform t = frame.getTransformTo(outputFrame, getDate());
  283.         return t.transformPVCoordinates(getPVCoordinates());
  284.     }

  285.     @Override
  286.     public TimeStampedPVCoordinates getPVCoordinates(final AbsoluteDate otherDate, final Frame outputFrame) {
  287.         return shiftedBy(otherDate.durationFrom(getDate())).getPVCoordinates(outputFrame);
  288.     }

  289.     /** Replace the instance with a data transfer object for serialization.
  290.      * @return data transfer object that will be serialized
  291.      */
  292.     @DefaultDataContext
  293.     private Object writeReplace() {
  294.         return new DTO(this);
  295.     }

  296.     /** Internal class used only for serialization. */
  297.     @DefaultDataContext
  298.     private static class DTO implements Serializable {

  299.         /** Serializable UID. */
  300.         private static final long serialVersionUID = 20150916L;

  301.         /** Double values. */
  302.         private double[] d;

  303.         /** Frame in which acoordinates are defined. */
  304.         private final Frame frame;

  305.         /** Simple constructor.
  306.          * @param absPva instance to serialize
  307.          */
  308.         private DTO(final AbsolutePVCoordinates absPva) {

  309.             // decompose date
  310.             final AbsoluteDate j2000Epoch =
  311.                     DataContext.getDefault().getTimeScales().getJ2000Epoch();
  312.             final double epoch  = FastMath.floor(absPva.getDate().durationFrom(j2000Epoch));
  313.             final double offset = absPva.getDate().durationFrom(j2000Epoch.shiftedBy(epoch));

  314.             this.d = new double[] {
  315.                 epoch, offset,
  316.                 absPva.getPosition().getX(),     absPva.getPosition().getY(),     absPva.getPosition().getZ(),
  317.                 absPva.getVelocity().getX(),     absPva.getVelocity().getY(),     absPva.getVelocity().getZ(),
  318.                 absPva.getAcceleration().getX(), absPva.getAcceleration().getY(), absPva.getAcceleration().getZ()
  319.             };
  320.             this.frame = absPva.frame;

  321.         }

  322.         /** Replace the deserialized data transfer object with a {@link AbsolutePVCoordinates}.
  323.          * @return replacement {@link AbsolutePVCoordinates}
  324.          */
  325.         private Object readResolve() {
  326.             final AbsoluteDate j2000Epoch =
  327.                     DataContext.getDefault().getTimeScales().getJ2000Epoch();
  328.             return new AbsolutePVCoordinates(frame,
  329.                                              j2000Epoch.shiftedBy(d[0]).shiftedBy(d[1]),
  330.                                              new Vector3D(d[2], d[3], d[ 4]),
  331.                                              new Vector3D(d[5], d[6], d[ 7]),
  332.                                              new Vector3D(d[8], d[9], d[10]));
  333.         }

  334.     }

  335. }