TimeStampedAngularCoordinates.java

  1. /* Copyright 2002-2024 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.FieldRotation;
  20. import org.hipparchus.geometry.euclidean.threed.Rotation;
  21. import org.hipparchus.geometry.euclidean.threed.RotationConvention;
  22. import org.hipparchus.geometry.euclidean.threed.Vector3D;
  23. import org.orekit.time.AbsoluteDate;
  24. import org.orekit.time.TimeStamped;

  25. /** {@link TimeStamped time-stamped} version of {@link AngularCoordinates}.
  26.  * <p>Instances of this class are guaranteed to be immutable.</p>
  27.  * @author Luc Maisonobe
  28.  * @since 7.0
  29.  */
  30. public class TimeStampedAngularCoordinates extends AngularCoordinates implements TimeStamped {

  31.     /** Serializable UID. */
  32.     private static final long serialVersionUID = 20140723L;

  33.     /** The date. */
  34.     private final AbsoluteDate date;

  35.     /** Builds a rotation/rotation rate pair.
  36.      * @param date coordinates date
  37.      * @param rotation rotation
  38.      * @param rotationRate rotation rate Ω (rad/s)
  39.      * @param rotationAcceleration rotation acceleration dΩ/dt (rad²/s²)
  40.      */
  41.     public TimeStampedAngularCoordinates(final AbsoluteDate date,
  42.                                          final Rotation rotation,
  43.                                          final Vector3D rotationRate,
  44.                                          final Vector3D rotationAcceleration) {
  45.         super(rotation, rotationRate, rotationAcceleration);
  46.         this.date = date;
  47.     }

  48.     /** Build the rotation that transforms a pair of pv coordinates into another pair.

  49.      * <p><em>WARNING</em>! This method requires much more stringent assumptions on
  50.      * its parameters than the similar {@link Rotation#Rotation(Vector3D, Vector3D,
  51.      * Vector3D, Vector3D) constructor} from the {@link Rotation Rotation} class.
  52.      * As far as the Rotation constructor is concerned, the {@code v₂} vector from
  53.      * the second pair can be slightly misaligned. The Rotation constructor will
  54.      * compensate for this misalignment and create a rotation that ensure {@code
  55.      * v₁ = r(u₁)} and {@code v₂ ∈ plane (r(u₁), r(u₂))}. <em>THIS IS NOT
  56.      * TRUE ANYMORE IN THIS CLASS</em>! As derivatives are involved and must be
  57.      * preserved, this constructor works <em>only</em> if the two pairs are fully
  58.      * consistent, i.e. if a rotation exists that fulfill all the requirements: {@code
  59.      * v₁ = r(u₁)}, {@code v₂ = r(u₂)}, {@code dv₁/dt = dr(u₁)/dt}, {@code dv₂/dt
  60.      * = dr(u₂)/dt}, {@code d²v₁/dt² = d²r(u₁)/dt²}, {@code d²v₂/dt² = d²r(u₂)/dt²}.</p>

  61.      * @param date coordinates date
  62.      * @param u1 first vector of the origin pair
  63.      * @param u2 second vector of the origin pair
  64.      * @param v1 desired image of u1 by the rotation
  65.      * @param v2 desired image of u2 by the rotation
  66.      * @param tolerance relative tolerance factor used to check singularities
  67.      */
  68.     public TimeStampedAngularCoordinates(final AbsoluteDate date,
  69.                                          final PVCoordinates u1, final PVCoordinates u2,
  70.                                          final PVCoordinates v1, final PVCoordinates v2,
  71.                                          final double tolerance) {
  72.         super(u1, u2, v1, v2, tolerance);
  73.         this.date = date;
  74.     }

  75.     /** Build one of the rotations that transform one pv coordinates into another one.

  76.      * <p>Except for a possible scale factor, if the instance were
  77.      * applied to the vector u it will produce the vector v. There is an
  78.      * infinite number of such rotations, this constructor choose the
  79.      * one with the smallest associated angle (i.e. the one whose axis
  80.      * is orthogonal to the (u, v) plane). If u and v are collinear, an
  81.      * arbitrary rotation axis is chosen.</p>

  82.      * @param date coordinates date
  83.      * @param u origin vector
  84.      * @param v desired image of u by the rotation
  85.      */
  86.     public TimeStampedAngularCoordinates(final AbsoluteDate date,
  87.                                          final PVCoordinates u, final PVCoordinates v) {
  88.         super(u, v);
  89.         this.date = date;
  90.     }

  91.     /** Builds a TimeStampedAngularCoordinates from  a {@link FieldRotation}&lt;{@link Derivative}&gt;.
  92.      * <p>
  93.      * The rotation components must have time as their only derivation parameter and
  94.      * have consistent derivation orders.
  95.      * </p>
  96.      * @param date coordinates date
  97.      * @param r rotation with time-derivatives embedded within the coordinates
  98.      * @param <U> type of the derivative
  99.      */
  100.     public <U extends Derivative<U>>TimeStampedAngularCoordinates(final AbsoluteDate date,
  101.                                                                   final FieldRotation<U> r) {
  102.         super(r);
  103.         this.date = date;
  104.     }

  105.     /** {@inheritDoc} */
  106.     public AbsoluteDate getDate() {
  107.         return date;
  108.     }

  109.     /** Revert a rotation/rotation rate pair.
  110.      * Build a pair which reverse the effect of another pair.
  111.      * @return a new pair whose effect is the reverse of the effect
  112.      * of the instance
  113.      */
  114.     public TimeStampedAngularCoordinates revert() {
  115.         return new TimeStampedAngularCoordinates(date,
  116.                                                  getRotation().revert(),
  117.                                                  getRotation().applyInverseTo(getRotationRate().negate()),
  118.                                                  getRotation().applyInverseTo(getRotationAcceleration().negate()));
  119.     }

  120.     /** Get a time-shifted state.
  121.      * <p>
  122.      * The state can be slightly shifted to close dates. This shift is based on
  123.      * a simple linear model. It is <em>not</em> intended as a replacement for
  124.      * proper attitude propagation but should be sufficient for either small
  125.      * time shifts or coarse accuracy.
  126.      * </p>
  127.      * @param dt time shift in seconds
  128.      * @return a new state, shifted with respect to the instance (which is immutable)
  129.      */
  130.     public TimeStampedAngularCoordinates shiftedBy(final double dt) {
  131.         final AngularCoordinates sac = super.shiftedBy(dt);
  132.         return new TimeStampedAngularCoordinates(date.shiftedBy(dt),
  133.                                                  sac.getRotation(), sac.getRotationRate(), sac.getRotationAcceleration());

  134.     }

  135.     /** Add an offset from the instance.
  136.      * <p>
  137.      * We consider here that the offset rotation is applied first and the
  138.      * instance is applied afterward. Note that angular coordinates do <em>not</em>
  139.      * commute under this operation, i.e. {@code a.addOffset(b)} and {@code
  140.      * b.addOffset(a)} lead to <em>different</em> results in most cases.
  141.      * </p>
  142.      * <p>
  143.      * The two methods {@link #addOffset(AngularCoordinates) addOffset} and
  144.      * {@link #subtractOffset(AngularCoordinates) subtractOffset} are designed
  145.      * so that round trip applications are possible. This means that both {@code
  146.      * ac1.subtractOffset(ac2).addOffset(ac2)} and {@code
  147.      * ac1.addOffset(ac2).subtractOffset(ac2)} return angular coordinates equal to ac1.
  148.      * </p>
  149.      * @param offset offset to subtract
  150.      * @return new instance, with offset subtracted
  151.      * @see #subtractOffset(AngularCoordinates)
  152.      */
  153.     @Override
  154.     public TimeStampedAngularCoordinates addOffset(final AngularCoordinates offset) {
  155.         final Vector3D rOmega    = getRotation().applyTo(offset.getRotationRate());
  156.         final Vector3D rOmegaDot = getRotation().applyTo(offset.getRotationAcceleration());
  157.         return new TimeStampedAngularCoordinates(date,
  158.                                                  getRotation().compose(offset.getRotation(), RotationConvention.VECTOR_OPERATOR),
  159.                                                  getRotationRate().add(rOmega),
  160.                                                  new Vector3D( 1.0, getRotationAcceleration(),
  161.                                                                1.0, rOmegaDot,
  162.                                                               -1.0, Vector3D.crossProduct(getRotationRate(), rOmega)));
  163.     }

  164.     /** Subtract an offset from the instance.
  165.      * <p>
  166.      * We consider here that the offset rotation is applied first and the
  167.      * instance is applied afterward. Note that angular coordinates do <em>not</em>
  168.      * commute under this operation, i.e. {@code a.subtractOffset(b)} and {@code
  169.      * b.subtractOffset(a)} lead to <em>different</em> results in most cases.
  170.      * </p>
  171.      * <p>
  172.      * The two methods {@link #addOffset(AngularCoordinates) addOffset} and
  173.      * {@link #subtractOffset(AngularCoordinates) subtractOffset} are designed
  174.      * so that round trip applications are possible. This means that both {@code
  175.      * ac1.subtractOffset(ac2).addOffset(ac2)} and {@code
  176.      * ac1.addOffset(ac2).subtractOffset(ac2)} return angular coordinates equal to ac1.
  177.      * </p>
  178.      * @param offset offset to subtract
  179.      * @return new instance, with offset subtracted
  180.      * @see #addOffset(AngularCoordinates)
  181.      */
  182.     @Override
  183.     public TimeStampedAngularCoordinates subtractOffset(final AngularCoordinates offset) {
  184.         return addOffset(offset.revert());
  185.     }

  186. }