FieldAttitude.java

  1. /* Copyright 2002-2018 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.attitudes;

  18. import java.util.List;
  19. import java.util.stream.Collectors;
  20. import java.util.stream.Stream;

  21. import org.hipparchus.Field;
  22. import org.hipparchus.RealFieldElement;
  23. import org.hipparchus.geometry.euclidean.threed.FieldRotation;
  24. import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
  25. import org.hipparchus.geometry.euclidean.threed.Rotation;
  26. import org.hipparchus.geometry.euclidean.threed.RotationConvention;
  27. import org.hipparchus.geometry.euclidean.threed.Vector3D;
  28. import org.orekit.errors.OrekitException;
  29. import org.orekit.frames.Frame;
  30. import org.orekit.frames.Transform;
  31. import org.orekit.time.FieldAbsoluteDate;
  32. import org.orekit.time.FieldTimeInterpolable;
  33. import org.orekit.time.FieldTimeShiftable;
  34. import org.orekit.time.FieldTimeStamped;
  35. import org.orekit.utils.AngularDerivativesFilter;
  36. import org.orekit.utils.FieldAngularCoordinates;
  37. import org.orekit.utils.TimeStampedFieldAngularCoordinates;


  38. /** This class handles attitude definition at a given date.

  39.  * <p>This class represents the rotation between a reference frame and
  40.  * the satellite frame, as well as the spin of the satellite (axis and
  41.  * rotation rate).</p>
  42.  * <p>
  43.  * The state can be slightly shifted to close dates. This shift is based on
  44.  * a linear extrapolation for attitude taking the spin rate into account.
  45.  * It is <em>not</em> intended as a replacement for proper attitude propagation
  46.  * but should be sufficient for either small time shifts or coarse accuracy.
  47.  * </p>
  48.  * <p>The instance <code>Attitude</code> is guaranteed to be immutable.</p>
  49.  * @see     org.orekit.orbits.Orbit
  50.  * @see AttitudeProvider
  51.  * @author V&eacute;ronique Pommier-Maurussane
  52.  */

  53. public class FieldAttitude<T extends RealFieldElement<T>>
  54.     implements FieldTimeStamped<T>, FieldTimeShiftable<FieldAttitude<T>, T>, FieldTimeInterpolable<FieldAttitude<T>, T> {


  55.     /** Reference frame. */
  56.     private final Frame referenceFrame;

  57.      /** Attitude and spin.  */
  58.     private final TimeStampedFieldAngularCoordinates<T> orientation;

  59.     /** Creates a new instance.
  60.      * @param referenceFrame reference frame from which attitude is defined
  61.      * @param orientation complete orientation between reference frame and satellite frame,
  62.      * including rotation rate
  63.      */
  64.     public FieldAttitude(final Frame referenceFrame, final TimeStampedFieldAngularCoordinates<T> orientation) {
  65.         this.referenceFrame = referenceFrame;
  66.         this.orientation    = orientation;
  67.     }

  68.     /** Creates a new instance.
  69.      * @param date date at which attitude is defined
  70.      * @param referenceFrame reference frame from which attitude is defined
  71.      * @param orientation complete orientation between reference frame and satellite frame,
  72.      * including rotation rate
  73.      */
  74.     public FieldAttitude(final FieldAbsoluteDate<T> date, final Frame referenceFrame,
  75.                          final FieldAngularCoordinates<T> orientation) {
  76.         this(referenceFrame,
  77.              new TimeStampedFieldAngularCoordinates<>(date,
  78.                                                       orientation.getRotation(),
  79.                                                       orientation.getRotationRate(),
  80.                                                       orientation.getRotationAcceleration()));
  81.     }

  82.     /** Creates a new instance.
  83.      * @param date date at which attitude is defined
  84.      * @param referenceFrame reference frame from which attitude is defined
  85.      * @param attitude rotation between reference frame and satellite frame
  86.      * @param spin satellite spin (axis and velocity, in <strong>satellite</strong> frame)
  87.      * @param acceleration satellite rotation acceleration (in <strong>satellite</strong> frame)
  88.      */
  89.     public FieldAttitude(final FieldAbsoluteDate<T> date, final Frame referenceFrame,
  90.                          final FieldRotation<T> attitude, final FieldVector3D<T> spin, final FieldVector3D<T> acceleration) {
  91.         this(referenceFrame, new TimeStampedFieldAngularCoordinates<>(date, attitude, spin, acceleration));
  92.     }

  93.     /** Creates a new instance.
  94.      * @param date date at which attitude is defined
  95.      * @param referenceFrame reference frame from which attitude is defined
  96.      * @param attitude rotation between reference frame and satellite frame
  97.      * @param spin satellite spin (axis and velocity, in <strong>satellite</strong> frame)
  98.      * @param acceleration satellite rotation acceleration (in <strong>satellite</strong> frame)
  99.      * @param field field used by default
  100.      */
  101.     public FieldAttitude(final FieldAbsoluteDate<T> date, final Frame referenceFrame,
  102.                          final Rotation attitude, final Vector3D spin, final Vector3D acceleration, final Field<T> field) {
  103.         this(referenceFrame, new TimeStampedFieldAngularCoordinates<>(date,
  104.                                                                       new FieldRotation<>(field, attitude),
  105.                                                                       new FieldVector3D<>(field, spin),
  106.                                                                       new FieldVector3D<>(field, acceleration)));
  107.     }

  108.     /** Builds an instance for a regular {@link Attitude}.
  109.      * @param field fields to which the elements belong
  110.      * @param attitude attitude to convert
  111.      */
  112.     public FieldAttitude(final Field<T> field, final Attitude attitude) {
  113.         this(attitude.getReferenceFrame(), new TimeStampedFieldAngularCoordinates<>(field, attitude.getOrientation()));
  114.     }

  115.     /** Get a time-shifted attitude.
  116.      * <p>
  117.      * The state can be slightly shifted to close dates. This shift is based on
  118.      * a linear extrapolation for attitude taking the spin rate into account.
  119.      * It is <em>not</em> intended as a replacement for proper attitude propagation
  120.      * but should be sufficient for either small time shifts or coarse accuracy.
  121.      * </p>
  122.      * @param dt time shift in seconds
  123.      * @return a new attitude, shifted with respect to the instance (which is immutable)
  124.      */
  125.     public FieldAttitude<T> shiftedBy(final double dt) {
  126.         return new FieldAttitude<>(referenceFrame, orientation.shiftedBy(dt));
  127.     }

  128.     /** Get a time-shifted attitude.
  129.      * <p>
  130.      * The state can be slightly shifted to close dates. This shift is based on
  131.      * a linear extrapolation for attitude taking the spin rate into account.
  132.      * It is <em>not</em> intended as a replacement for proper attitude propagation
  133.      * but should be sufficient for either small time shifts or coarse accuracy.
  134.      * </p>
  135.      * @param dt time shift in seconds
  136.      * @return a new attitude, shifted with respect to the instance (which is immutable)
  137.      */
  138.     public FieldAttitude<T> shiftedBy(final T dt) {
  139.         return new FieldAttitude<>(referenceFrame, orientation.shiftedBy(dt));
  140.     }

  141.     /** Get a similar attitude with a specific reference frame.
  142.      * <p>
  143.      * If the instance reference frame is already the specified one, the instance
  144.      * itself is returned without any object creation. Otherwise, a new instance
  145.      * will be created with the specified reference frame. In this case, the
  146.      * required intermediate rotation and spin between the specified and the
  147.      * original reference frame will be inserted.
  148.      * </p>
  149.      * @param newReferenceFrame desired reference frame for attitude
  150.      * @return an attitude that has the same orientation and motion as the instance,
  151.      * but guaranteed to have the specified reference frame
  152.      * @exception OrekitException if conversion between reference frames fails
  153.      */
  154.     public FieldAttitude<T> withReferenceFrame(final Frame newReferenceFrame)
  155.         throws OrekitException {

  156.         if (newReferenceFrame == referenceFrame) {
  157.             // simple case, the instance is already compliant
  158.             return this;
  159.         }

  160.         // we have to take an intermediate rotation into account
  161.         final Transform t = newReferenceFrame.getTransformTo(referenceFrame, orientation.getDate().toAbsoluteDate());
  162.         return new FieldAttitude<>(orientation.getDate(), newReferenceFrame,
  163.                                    orientation.getRotation().compose(t.getRotation(), RotationConvention.VECTOR_OPERATOR),
  164.                                    orientation.getRotationRate().add(orientation.getRotation().applyTo(t.getRotationRate())),
  165.                                    orientation.getRotationAcceleration().add(orientation.getRotation().applyTo(t.getRotationAcceleration())));

  166.     }

  167.     /** Get the date of attitude parameters.
  168.      * @return date of the attitude parameters
  169.      */
  170.     public FieldAbsoluteDate<T> getDate() {
  171.         return orientation.getDate();
  172.     }

  173.     /** Get the reference frame.
  174.      * @return referenceFrame reference frame from which attitude is defined.
  175.      */
  176.     public Frame getReferenceFrame() {
  177.         return referenceFrame;
  178.     }

  179.     /** Get the complete orientation including spin.
  180.      * @return complete orientation including spin
  181.      * @see #getRotation()
  182.      * @see #getSpin()
  183.      */
  184.     public TimeStampedFieldAngularCoordinates<T> getOrientation() {
  185.         return orientation;
  186.     }

  187.     /** Get the attitude rotation.
  188.      * @return attitude satellite rotation from reference frame.
  189.      * @see #getOrientation()
  190.      * @see #getSpin()
  191.      */
  192.     public FieldRotation<T> getRotation() {
  193.         return orientation.getRotation();
  194.     }

  195.     /** Get the satellite spin.
  196.      * <p>The spin vector is defined in <strong>satellite</strong> frame.</p>
  197.      * @return spin satellite spin (axis and velocity).
  198.      * @see #getOrientation()
  199.      * @see #getRotation()
  200.      */
  201.     public FieldVector3D<T> getSpin() {
  202.         return orientation.getRotationRate();
  203.     }

  204.     /** Get the satellite rotation acceleration.
  205.      * <p>The rotation acceleration. vector is defined in <strong>satellite</strong> frame.</p>
  206.      * @return rotation acceleration
  207.      * @see #getOrientation()
  208.      * @see #getRotation()
  209.      */
  210.     public FieldVector3D<T> getRotationAcceleration() {
  211.         return orientation.getRotationAcceleration();
  212.     }

  213.     /** Get an interpolated instance.
  214.      * <p>
  215.      * The interpolated instance is created by polynomial Hermite interpolation
  216.      * on Rodrigues vector ensuring rotation rate remains the exact derivative of rotation.
  217.      * </p>
  218.      * <p>
  219.      * As this implementation of interpolation is polynomial, it should be used only
  220.      * with small samples (about 10-20 points) in order to avoid <a
  221.      * href="http://en.wikipedia.org/wiki/Runge%27s_phenomenon">Runge's phenomenon</a>
  222.      * and numerical problems (including NaN appearing).
  223.      * </p>
  224.      * @param interpolationDate interpolation date
  225.      * @param sample sample points on which interpolation should be done
  226.      * @return a new instance, interpolated at specified date
  227.      * @exception OrekitException if the number of point is too small for interpolating
  228.      */
  229.     public FieldAttitude<T> interpolate(final FieldAbsoluteDate<T> interpolationDate,
  230.                                         final Stream<FieldAttitude<T>> sample)
  231.         throws OrekitException {
  232.         final List<TimeStampedFieldAngularCoordinates<T>> datedPV =
  233.                 sample.map(attitude -> attitude.orientation).collect(Collectors.toList());
  234.         final TimeStampedFieldAngularCoordinates<T> interpolated =
  235.                 TimeStampedFieldAngularCoordinates.interpolate(interpolationDate, AngularDerivativesFilter.USE_RR, datedPV);
  236.         return new FieldAttitude<>(referenceFrame, interpolated);
  237.     }
  238.     /**
  239.      * Converts to an Attitude instance.
  240.      * @return Attitude with same properties
  241.      */
  242.     public Attitude toAttitude() {
  243.         return new Attitude(orientation.getDate().toAbsoluteDate(), referenceFrame, orientation.toAngularCoordinates());
  244.     }

  245. }