FieldAttitude.java
- /* Copyright 2002-2018 CS Systèmes d'Information
- * Licensed to CS Systèmes d'Information (CS) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * CS licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- package org.orekit.attitudes;
- import java.util.List;
- import java.util.stream.Collectors;
- import java.util.stream.Stream;
- import org.hipparchus.Field;
- import org.hipparchus.RealFieldElement;
- import org.hipparchus.geometry.euclidean.threed.FieldRotation;
- import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
- import org.hipparchus.geometry.euclidean.threed.Rotation;
- import org.hipparchus.geometry.euclidean.threed.RotationConvention;
- import org.hipparchus.geometry.euclidean.threed.Vector3D;
- import org.orekit.errors.OrekitException;
- import org.orekit.frames.Frame;
- import org.orekit.frames.Transform;
- import org.orekit.time.FieldAbsoluteDate;
- import org.orekit.time.FieldTimeInterpolable;
- import org.orekit.time.FieldTimeShiftable;
- import org.orekit.time.FieldTimeStamped;
- import org.orekit.utils.AngularDerivativesFilter;
- import org.orekit.utils.FieldAngularCoordinates;
- import org.orekit.utils.TimeStampedFieldAngularCoordinates;
- /** This class handles attitude definition at a given date.
- * <p>This class represents the rotation between a reference frame and
- * the satellite frame, as well as the spin of the satellite (axis and
- * rotation rate).</p>
- * <p>
- * The state can be slightly shifted to close dates. This shift is based on
- * a linear extrapolation for attitude taking the spin rate into account.
- * It is <em>not</em> intended as a replacement for proper attitude propagation
- * but should be sufficient for either small time shifts or coarse accuracy.
- * </p>
- * <p>The instance <code>Attitude</code> is guaranteed to be immutable.</p>
- * @see org.orekit.orbits.Orbit
- * @see AttitudeProvider
- * @author Véronique Pommier-Maurussane
- */
- public class FieldAttitude<T extends RealFieldElement<T>>
- implements FieldTimeStamped<T>, FieldTimeShiftable<FieldAttitude<T>, T>, FieldTimeInterpolable<FieldAttitude<T>, T> {
- /** Reference frame. */
- private final Frame referenceFrame;
- /** Attitude and spin. */
- private final TimeStampedFieldAngularCoordinates<T> orientation;
- /** Creates a new instance.
- * @param referenceFrame reference frame from which attitude is defined
- * @param orientation complete orientation between reference frame and satellite frame,
- * including rotation rate
- */
- public FieldAttitude(final Frame referenceFrame, final TimeStampedFieldAngularCoordinates<T> orientation) {
- this.referenceFrame = referenceFrame;
- this.orientation = orientation;
- }
- /** Creates a new instance.
- * @param date date at which attitude is defined
- * @param referenceFrame reference frame from which attitude is defined
- * @param orientation complete orientation between reference frame and satellite frame,
- * including rotation rate
- */
- public FieldAttitude(final FieldAbsoluteDate<T> date, final Frame referenceFrame,
- final FieldAngularCoordinates<T> orientation) {
- this(referenceFrame,
- new TimeStampedFieldAngularCoordinates<>(date,
- orientation.getRotation(),
- orientation.getRotationRate(),
- orientation.getRotationAcceleration()));
- }
- /** Creates a new instance.
- * @param date date at which attitude is defined
- * @param referenceFrame reference frame from which attitude is defined
- * @param attitude rotation between reference frame and satellite frame
- * @param spin satellite spin (axis and velocity, in <strong>satellite</strong> frame)
- * @param acceleration satellite rotation acceleration (in <strong>satellite</strong> frame)
- */
- public FieldAttitude(final FieldAbsoluteDate<T> date, final Frame referenceFrame,
- final FieldRotation<T> attitude, final FieldVector3D<T> spin, final FieldVector3D<T> acceleration) {
- this(referenceFrame, new TimeStampedFieldAngularCoordinates<>(date, attitude, spin, acceleration));
- }
- /** Creates a new instance.
- * @param date date at which attitude is defined
- * @param referenceFrame reference frame from which attitude is defined
- * @param attitude rotation between reference frame and satellite frame
- * @param spin satellite spin (axis and velocity, in <strong>satellite</strong> frame)
- * @param acceleration satellite rotation acceleration (in <strong>satellite</strong> frame)
- * @param field field used by default
- */
- public FieldAttitude(final FieldAbsoluteDate<T> date, final Frame referenceFrame,
- final Rotation attitude, final Vector3D spin, final Vector3D acceleration, final Field<T> field) {
- this(referenceFrame, new TimeStampedFieldAngularCoordinates<>(date,
- new FieldRotation<>(field, attitude),
- new FieldVector3D<>(field, spin),
- new FieldVector3D<>(field, acceleration)));
- }
- /** Builds an instance for a regular {@link Attitude}.
- * @param field fields to which the elements belong
- * @param attitude attitude to convert
- */
- public FieldAttitude(final Field<T> field, final Attitude attitude) {
- this(attitude.getReferenceFrame(), new TimeStampedFieldAngularCoordinates<>(field, attitude.getOrientation()));
- }
- /** Get a time-shifted attitude.
- * <p>
- * The state can be slightly shifted to close dates. This shift is based on
- * a linear extrapolation for attitude taking the spin rate into account.
- * It is <em>not</em> intended as a replacement for proper attitude propagation
- * but should be sufficient for either small time shifts or coarse accuracy.
- * </p>
- * @param dt time shift in seconds
- * @return a new attitude, shifted with respect to the instance (which is immutable)
- */
- public FieldAttitude<T> shiftedBy(final double dt) {
- return new FieldAttitude<>(referenceFrame, orientation.shiftedBy(dt));
- }
- /** Get a time-shifted attitude.
- * <p>
- * The state can be slightly shifted to close dates. This shift is based on
- * a linear extrapolation for attitude taking the spin rate into account.
- * It is <em>not</em> intended as a replacement for proper attitude propagation
- * but should be sufficient for either small time shifts or coarse accuracy.
- * </p>
- * @param dt time shift in seconds
- * @return a new attitude, shifted with respect to the instance (which is immutable)
- */
- public FieldAttitude<T> shiftedBy(final T dt) {
- return new FieldAttitude<>(referenceFrame, orientation.shiftedBy(dt));
- }
- /** Get a similar attitude with a specific reference frame.
- * <p>
- * If the instance reference frame is already the specified one, the instance
- * itself is returned without any object creation. Otherwise, a new instance
- * will be created with the specified reference frame. In this case, the
- * required intermediate rotation and spin between the specified and the
- * original reference frame will be inserted.
- * </p>
- * @param newReferenceFrame desired reference frame for attitude
- * @return an attitude that has the same orientation and motion as the instance,
- * but guaranteed to have the specified reference frame
- * @exception OrekitException if conversion between reference frames fails
- */
- public FieldAttitude<T> withReferenceFrame(final Frame newReferenceFrame)
- throws OrekitException {
- if (newReferenceFrame == referenceFrame) {
- // simple case, the instance is already compliant
- return this;
- }
- // we have to take an intermediate rotation into account
- final Transform t = newReferenceFrame.getTransformTo(referenceFrame, orientation.getDate().toAbsoluteDate());
- return new FieldAttitude<>(orientation.getDate(), newReferenceFrame,
- orientation.getRotation().compose(t.getRotation(), RotationConvention.VECTOR_OPERATOR),
- orientation.getRotationRate().add(orientation.getRotation().applyTo(t.getRotationRate())),
- orientation.getRotationAcceleration().add(orientation.getRotation().applyTo(t.getRotationAcceleration())));
- }
- /** Get the date of attitude parameters.
- * @return date of the attitude parameters
- */
- public FieldAbsoluteDate<T> getDate() {
- return orientation.getDate();
- }
- /** Get the reference frame.
- * @return referenceFrame reference frame from which attitude is defined.
- */
- public Frame getReferenceFrame() {
- return referenceFrame;
- }
- /** Get the complete orientation including spin.
- * @return complete orientation including spin
- * @see #getRotation()
- * @see #getSpin()
- */
- public TimeStampedFieldAngularCoordinates<T> getOrientation() {
- return orientation;
- }
- /** Get the attitude rotation.
- * @return attitude satellite rotation from reference frame.
- * @see #getOrientation()
- * @see #getSpin()
- */
- public FieldRotation<T> getRotation() {
- return orientation.getRotation();
- }
- /** Get the satellite spin.
- * <p>The spin vector is defined in <strong>satellite</strong> frame.</p>
- * @return spin satellite spin (axis and velocity).
- * @see #getOrientation()
- * @see #getRotation()
- */
- public FieldVector3D<T> getSpin() {
- return orientation.getRotationRate();
- }
- /** Get the satellite rotation acceleration.
- * <p>The rotation acceleration. vector is defined in <strong>satellite</strong> frame.</p>
- * @return rotation acceleration
- * @see #getOrientation()
- * @see #getRotation()
- */
- public FieldVector3D<T> getRotationAcceleration() {
- return orientation.getRotationAcceleration();
- }
- /** Get an interpolated instance.
- * <p>
- * The interpolated instance is created by polynomial Hermite interpolation
- * on Rodrigues vector ensuring rotation rate remains the exact derivative of rotation.
- * </p>
- * <p>
- * As this implementation of interpolation is polynomial, it should be used only
- * with small samples (about 10-20 points) in order to avoid <a
- * href="http://en.wikipedia.org/wiki/Runge%27s_phenomenon">Runge's phenomenon</a>
- * and numerical problems (including NaN appearing).
- * </p>
- * @param interpolationDate interpolation date
- * @param sample sample points on which interpolation should be done
- * @return a new instance, interpolated at specified date
- * @exception OrekitException if the number of point is too small for interpolating
- */
- public FieldAttitude<T> interpolate(final FieldAbsoluteDate<T> interpolationDate,
- final Stream<FieldAttitude<T>> sample)
- throws OrekitException {
- final List<TimeStampedFieldAngularCoordinates<T>> datedPV =
- sample.map(attitude -> attitude.orientation).collect(Collectors.toList());
- final TimeStampedFieldAngularCoordinates<T> interpolated =
- TimeStampedFieldAngularCoordinates.interpolate(interpolationDate, AngularDerivativesFilter.USE_RR, datedPV);
- return new FieldAttitude<>(referenceFrame, interpolated);
- }
- /**
- * Converts to an Attitude instance.
- * @return Attitude with same properties
- */
- public Attitude toAttitude() {
- return new Attitude(orientation.getDate().toAbsoluteDate(), referenceFrame, orientation.toAngularCoordinates());
- }
- }