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 }