1 /* Copyright 2002-2013 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 19 import java.io.Serializable; 20 import java.util.ArrayList; 21 import java.util.Collection; 22 import java.util.List; 23 24 import org.apache.commons.math3.geometry.euclidean.threed.Rotation; 25 import org.apache.commons.math3.geometry.euclidean.threed.Vector3D; 26 import org.apache.commons.math3.util.Pair; 27 import org.orekit.errors.OrekitException; 28 import org.orekit.frames.Frame; 29 import org.orekit.frames.Transform; 30 import org.orekit.time.AbsoluteDate; 31 import org.orekit.time.TimeInterpolable; 32 import org.orekit.time.TimeShiftable; 33 import org.orekit.time.TimeStamped; 34 import org.orekit.utils.AngularCoordinates; 35 36 37 /** This class handles attitude definition at a given date. 38 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éronique Pommier-Maurussane 52 */ 53 54 public class Attitude 55 implements TimeStamped, TimeShiftable<Attitude>, TimeInterpolable<Attitude>, Serializable { 56 57 /** Serializable UID. */ 58 private static final long serialVersionUID = -947817502698754209L; 59 60 /** Current date. */ 61 private final AbsoluteDate date; 62 63 /** Reference frame. */ 64 private final Frame referenceFrame; 65 66 /** Attitude and spin. */ 67 private final AngularCoordinates orientation; 68 69 /** Creates a new instance. 70 * @param date date at which attitude is defined 71 * @param referenceFrame reference frame from which attitude is defined 72 * @param orientation complete orientation between reference frame and satellite frame, 73 * including rotation rate 74 */ 75 public Attitude(final AbsoluteDate date, final Frame referenceFrame, 76 final AngularCoordinates orientation) { 77 this.date = date; 78 this.referenceFrame = referenceFrame; 79 this.orientation = orientation; 80 } 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 */ 88 public Attitude(final AbsoluteDate date, final Frame referenceFrame, 89 final Rotation attitude, final Vector3D spin) { 90 this(date, referenceFrame, new AngularCoordinates(attitude, spin)); 91 } 92 93 /** Estimate spin between two orientations. 94 * <p>Estimation is based on a simple fixed rate rotation 95 * during the time interval between the two attitude.</p> 96 * @param start start orientation 97 * @param end end orientation 98 * @param dt time elapsed between the dates of the two orientations 99 * @return spin allowing to go from start to end orientation 100 * @deprecated as of 6.0 superseded by {@link 101 * AngularCoordinates#estimateRate(Rotation, Rotation, double)} 102 */ 103 @Deprecated 104 public static Vector3D estimateSpin(final Rotation start, final Rotation end, 105 final double dt) { 106 return AngularCoordinates.estimateRate(start, end, dt); 107 } 108 109 /** Get a time-shifted attitude. 110 * <p> 111 * The state can be slightly shifted to close dates. This shift is based on 112 * a linear extrapolation for attitude taking the spin rate into account. 113 * It is <em>not</em> intended as a replacement for proper attitude propagation 114 * but should be sufficient for either small time shifts or coarse accuracy. 115 * </p> 116 * @param dt time shift in seconds 117 * @return a new attitude, shifted with respect to the instance (which is immutable) 118 */ 119 public Attitude shiftedBy(final double dt) { 120 return new Attitude(date.shiftedBy(dt), referenceFrame, orientation.shiftedBy(dt)); 121 } 122 123 /** Get a similar attitude with a specific reference frame. 124 * <p> 125 * If the instance reference frame is already the specified one, the instance 126 * itself is returned without any object creation. Otherwise, a new instance 127 * will be created with the specified reference frame. In this case, the 128 * required intermediate rotation and spin between the specified and the 129 * original reference frame will be inserted. 130 * </p> 131 * @param newReferenceFrame desired reference frame for attitude 132 * @return an attitude that has the same orientation and motion as the instance, 133 * but guaranteed to have the specified reference frame 134 * @exception OrekitException if conversion between reference frames fails 135 */ 136 public Attitude withReferenceFrame(final Frame newReferenceFrame) 137 throws OrekitException { 138 139 if (newReferenceFrame == referenceFrame) { 140 // simple case, the instance is already compliant 141 return this; 142 } 143 144 // we have to take an intermediate rotation into account 145 final Transform t = newReferenceFrame.getTransformTo(referenceFrame, date); 146 return new Attitude(date, newReferenceFrame, 147 orientation.getRotation().applyTo(t.getRotation()), 148 orientation.getRotationRate().add(orientation.getRotation().applyTo(t.getRotationRate()))); 149 150 } 151 152 /** Get the date of attitude parameters. 153 * @return date of the attitude parameters 154 */ 155 public AbsoluteDate getDate() { 156 return date; 157 } 158 159 /** Get the reference frame. 160 * @return referenceFrame reference frame from which attitude is defined. 161 */ 162 public Frame getReferenceFrame() { 163 return referenceFrame; 164 } 165 166 /** Get the complete orientation including spin. 167 * @return complete orientation including spin 168 * @see #getRotation() 169 * @see #getSpin() 170 */ 171 public AngularCoordinates getOrientation() { 172 return orientation; 173 } 174 175 /** Get the attitude rotation. 176 * @return attitude satellite rotation from reference frame. 177 * @see #getOrientation() 178 * @see #getSpin() 179 */ 180 public Rotation getRotation() { 181 return orientation.getRotation(); 182 } 183 184 /** Get the satellite spin. 185 * <p>The spin vector is defined in <strong>satellite</strong> frame.</p> 186 * @return spin satellite spin (axis and velocity). 187 * @see #getOrientation() 188 * @see #getRotation() 189 */ 190 public Vector3D getSpin() { 191 return orientation.getRotationRate(); 192 } 193 194 /** {@inheritDoc} 195 * <p> 196 * The interpolated instance is created by polynomial Hermite interpolation 197 * on Rodrigues vector ensuring rotation rate remains the exact derivative of rotation. 198 * </p> 199 * <p> 200 * As this implementation of interpolation is polynomial, it should be used only 201 * with small samples (about 10-20 points) in order to avoid <a 202 * href="http://en.wikipedia.org/wiki/Runge%27s_phenomenon">Runge's phenomenon</a> 203 * and numerical problems (including NaN appearing). 204 * </p> 205 */ 206 public Attitude interpolate(final AbsoluteDate interpolationDate, final Collection<Attitude> sample) { 207 final List<Pair<AbsoluteDate, AngularCoordinates>> datedPV = 208 new ArrayList<Pair<AbsoluteDate, AngularCoordinates>>(sample.size()); 209 for (final Attitude attitude : sample) { 210 datedPV.add(new Pair<AbsoluteDate, AngularCoordinates>(attitude.getDate(), attitude.getOrientation())); 211 } 212 final AngularCoordinates interpolated = AngularCoordinates.interpolate(interpolationDate, true, datedPV); 213 return new Attitude(interpolationDate, referenceFrame, interpolated); 214 } 215 216 }