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