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 }