Attitude.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.io.Serializable;
  19. import java.util.List;
  20. import java.util.stream.Collectors;
  21. import java.util.stream.Stream;

  22. import org.hipparchus.geometry.euclidean.threed.Rotation;
  23. import org.hipparchus.geometry.euclidean.threed.RotationConvention;
  24. import org.hipparchus.geometry.euclidean.threed.Vector3D;
  25. import org.orekit.errors.OrekitException;
  26. import org.orekit.frames.Frame;
  27. import org.orekit.frames.Transform;
  28. import org.orekit.time.AbsoluteDate;
  29. import org.orekit.time.TimeInterpolable;
  30. import org.orekit.time.TimeShiftable;
  31. import org.orekit.time.TimeStamped;
  32. import org.orekit.utils.AngularCoordinates;
  33. import org.orekit.utils.AngularDerivativesFilter;
  34. import org.orekit.utils.TimeStampedAngularCoordinates;


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

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

  50. public class Attitude
  51.     implements TimeStamped, TimeShiftable<Attitude>, TimeInterpolable<Attitude>, Serializable {

  52.     /** Serializable UID. */
  53.     private static final long serialVersionUID = 20140611L;

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

  56.      /** Attitude and spin.  */
  57.     private final TimeStampedAngularCoordinates orientation;

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

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

  81.     /** Creates a new instance.
  82.      * @param date date at which attitude is defined
  83.      * @param referenceFrame reference frame from which attitude is defined
  84.      * @param attitude rotation between reference frame and satellite frame
  85.      * @param spin satellite spin (axis and velocity, in <strong>satellite</strong> frame)
  86.      * @param acceleration satellite rotation acceleration (in <strong>satellite</strong> frame)
  87.      */
  88.     public Attitude(final AbsoluteDate date, final Frame referenceFrame,
  89.                     final Rotation attitude, final Vector3D spin, final Vector3D acceleration) {
  90.         this(referenceFrame, new TimeStampedAngularCoordinates(date, attitude, spin, acceleration));
  91.     }

  92.     /** Get a time-shifted attitude.
  93.      * <p>
  94.      * The state can be slightly shifted to close dates. This shift is based on
  95.      * a linear extrapolation for attitude taking the spin rate into account.
  96.      * It is <em>not</em> intended as a replacement for proper attitude propagation
  97.      * but should be sufficient for either small time shifts or coarse accuracy.
  98.      * </p>
  99.      * @param dt time shift in seconds
  100.      * @return a new attitude, shifted with respect to the instance (which is immutable)
  101.      */
  102.     public Attitude shiftedBy(final double dt) {
  103.         return new Attitude(referenceFrame, orientation.shiftedBy(dt));
  104.     }

  105.     /** Get a similar attitude with a specific reference frame.
  106.      * <p>
  107.      * If the instance reference frame is already the specified one, the instance
  108.      * itself is returned without any object creation. Otherwise, a new instance
  109.      * will be created with the specified reference frame. In this case, the
  110.      * required intermediate rotation and spin between the specified and the
  111.      * original reference frame will be inserted.
  112.      * </p>
  113.      * @param newReferenceFrame desired reference frame for attitude
  114.      * @return an attitude that has the same orientation and motion as the instance,
  115.      * but guaranteed to have the specified reference frame
  116.      * @exception OrekitException if conversion between reference frames fails
  117.      */
  118.     public Attitude withReferenceFrame(final Frame newReferenceFrame)
  119.         throws OrekitException {

  120.         if (newReferenceFrame == referenceFrame) {
  121.             // simple case, the instance is already compliant
  122.             return this;
  123.         }

  124.         // we have to take an intermediate rotation into account
  125.         final Transform t = newReferenceFrame.getTransformTo(referenceFrame, orientation.getDate());
  126.         return new Attitude(orientation.getDate(), newReferenceFrame,
  127.                             orientation.getRotation().compose(t.getRotation(), RotationConvention.VECTOR_OPERATOR),
  128.                             orientation.getRotationRate().add(orientation.getRotation().applyTo(t.getRotationRate())),
  129.                             orientation.getRotationAcceleration().add(orientation.getRotation().applyTo(t.getRotationAcceleration())));

  130.     }

  131.     /** Get the date of attitude parameters.
  132.      * @return date of the attitude parameters
  133.      */
  134.     public AbsoluteDate getDate() {
  135.         return orientation.getDate();
  136.     }

  137.     /** Get the reference frame.
  138.      * @return referenceFrame reference frame from which attitude is defined.
  139.      */
  140.     public Frame getReferenceFrame() {
  141.         return referenceFrame;
  142.     }

  143.     /** Get the complete orientation including spin.
  144.      * @return complete orientation including spin
  145.      * @see #getRotation()
  146.      * @see #getSpin()
  147.      */
  148.     public TimeStampedAngularCoordinates getOrientation() {
  149.         return orientation;
  150.     }

  151.     /** Get the attitude rotation.
  152.      * @return attitude satellite rotation from reference frame.
  153.      * @see #getOrientation()
  154.      * @see #getSpin()
  155.      */
  156.     public Rotation getRotation() {
  157.         return orientation.getRotation();
  158.     }

  159.     /** Get the satellite spin.
  160.      * <p>The spin vector is defined in <strong>satellite</strong> frame.</p>
  161.      * @return spin satellite spin (axis and velocity).
  162.      * @see #getOrientation()
  163.      * @see #getRotation()
  164.      */
  165.     public Vector3D getSpin() {
  166.         return orientation.getRotationRate();
  167.     }

  168.     /** Get the satellite rotation acceleration.
  169.      * <p>The rotation acceleration. vector is defined in <strong>satellite</strong> frame.</p>
  170.      * @return rotation acceleration
  171.      * @see #getOrientation()
  172.      * @see #getRotation()
  173.      */
  174.     public Vector3D getRotationAcceleration() {
  175.         return orientation.getRotationAcceleration();
  176.     }

  177.     /** {@inheritDoc}
  178.      * <p>
  179.      * The interpolated instance is created by polynomial Hermite interpolation
  180.      * on Rodrigues vector ensuring rotation rate remains the exact derivative of rotation.
  181.      * </p>
  182.      * <p>
  183.      * As this implementation of interpolation is polynomial, it should be used only
  184.      * with small samples (about 10-20 points) in order to avoid <a
  185.      * href="http://en.wikipedia.org/wiki/Runge%27s_phenomenon">Runge's phenomenon</a>
  186.      * and numerical problems (including NaN appearing).
  187.      * </p>
  188.      * @exception OrekitException if the number of point is too small for interpolating
  189.      */
  190.     public Attitude interpolate(final AbsoluteDate interpolationDate, final Stream<Attitude> sample)
  191.         throws OrekitException {
  192.         final List<TimeStampedAngularCoordinates> datedPV =
  193.              sample.map(attitude -> attitude.orientation).collect(Collectors.toList());
  194.         final TimeStampedAngularCoordinates interpolated =
  195.                 TimeStampedAngularCoordinates.interpolate(interpolationDate, AngularDerivativesFilter.USE_RR, datedPV);
  196.         return new Attitude(referenceFrame, interpolated);
  197.     }

  198. }