1 /* Copyright 2002-2021 CS GROUP
2 * Licensed to CS GROUP (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.util.List;
20 import java.util.stream.Collectors;
21 import java.util.stream.Stream;
22
23 import org.hipparchus.Field;
24 import org.hipparchus.CalculusFieldElement;
25 import org.hipparchus.geometry.euclidean.threed.FieldRotation;
26 import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
27 import org.hipparchus.geometry.euclidean.threed.Rotation;
28 import org.hipparchus.geometry.euclidean.threed.RotationConvention;
29 import org.hipparchus.geometry.euclidean.threed.Vector3D;
30 import org.orekit.frames.Frame;
31 import org.orekit.frames.Transform;
32 import org.orekit.time.FieldAbsoluteDate;
33 import org.orekit.time.FieldTimeInterpolable;
34 import org.orekit.time.FieldTimeShiftable;
35 import org.orekit.time.FieldTimeStamped;
36 import org.orekit.utils.AngularDerivativesFilter;
37 import org.orekit.utils.FieldAngularCoordinates;
38 import org.orekit.utils.TimeStampedFieldAngularCoordinates;
39
40
41 /** This class handles attitude definition at a given date.
42
43 * <p>This class represents the rotation between a reference frame and
44 * the satellite frame, as well as the spin of the satellite (axis and
45 * rotation rate).</p>
46 * <p>
47 * The state can be slightly shifted to close dates. This shift is based on
48 * a linear extrapolation for attitude taking the spin rate into account.
49 * It is <em>not</em> intended as a replacement for proper attitude propagation
50 * but should be sufficient for either small time shifts or coarse accuracy.
51 * </p>
52 * <p>The instance <code>Attitude</code> is guaranteed to be immutable.</p>
53 * @see org.orekit.orbits.Orbit
54 * @see AttitudeProvider
55 * @author Véronique Pommier-Maurussane
56 */
57
58 public class FieldAttitude<T extends CalculusFieldElement<T>>
59 implements FieldTimeStamped<T>, FieldTimeShiftable<FieldAttitude<T>, T>, FieldTimeInterpolable<FieldAttitude<T>, T> {
60
61
62 /** Reference frame. */
63 private final Frame referenceFrame;
64
65 /** Attitude and spin. */
66 private final TimeStampedFieldAngularCoordinates<T> orientation;
67
68 /** Creates a new instance.
69 * @param referenceFrame reference frame from which attitude is defined
70 * @param orientation complete orientation between reference frame and satellite frame,
71 * including rotation rate
72 */
73 public FieldAttitude(final Frame referenceFrame, final TimeStampedFieldAngularCoordinates<T> orientation) {
74 this.referenceFrame = referenceFrame;
75 this.orientation = orientation;
76 }
77
78 /** Creates a new instance.
79 * @param date date at which attitude is defined
80 * @param referenceFrame reference frame from which attitude is defined
81 * @param orientation complete orientation between reference frame and satellite frame,
82 * including rotation rate
83 */
84 public FieldAttitude(final FieldAbsoluteDate<T> date, final Frame referenceFrame,
85 final FieldAngularCoordinates<T> orientation) {
86 this(referenceFrame,
87 new TimeStampedFieldAngularCoordinates<>(date,
88 orientation.getRotation(),
89 orientation.getRotationRate(),
90 orientation.getRotationAcceleration()));
91 }
92
93 /** Creates a new instance.
94 * @param date date at which attitude is defined
95 * @param referenceFrame reference frame from which attitude is defined
96 * @param attitude rotation between reference frame and satellite frame
97 * @param spin satellite spin (axis and velocity, in <strong>satellite</strong> frame)
98 * @param acceleration satellite rotation acceleration (in <strong>satellite</strong> frame)
99 */
100 public FieldAttitude(final FieldAbsoluteDate<T> date, final Frame referenceFrame,
101 final FieldRotation<T> attitude, final FieldVector3D<T> spin, final FieldVector3D<T> acceleration) {
102 this(referenceFrame, new TimeStampedFieldAngularCoordinates<>(date, attitude, spin, acceleration));
103 }
104
105 /** Creates a new instance.
106 * @param date date at which attitude is defined
107 * @param referenceFrame reference frame from which attitude is defined
108 * @param attitude rotation between reference frame and satellite frame
109 * @param spin satellite spin (axis and velocity, in <strong>satellite</strong> frame)
110 * @param acceleration satellite rotation acceleration (in <strong>satellite</strong> frame)
111 * @param field field used by default
112 */
113 public FieldAttitude(final FieldAbsoluteDate<T> date, final Frame referenceFrame,
114 final Rotation attitude, final Vector3D spin, final Vector3D acceleration, final Field<T> field) {
115 this(referenceFrame, new TimeStampedFieldAngularCoordinates<>(date,
116 new FieldRotation<>(field, attitude),
117 new FieldVector3D<>(field, spin),
118 new FieldVector3D<>(field, acceleration)));
119 }
120
121 /** Builds an instance for a regular {@link Attitude}.
122 * @param field fields to which the elements belong
123 * @param attitude attitude to convert
124 */
125 public FieldAttitude(final Field<T> field, final Attitude attitude) {
126 this(attitude.getReferenceFrame(), new TimeStampedFieldAngularCoordinates<>(field, attitude.getOrientation()));
127 }
128
129 /** Get a time-shifted attitude.
130 * <p>
131 * The state can be slightly shifted to close dates. This shift is based on
132 * a linear extrapolation for attitude taking the spin rate into account.
133 * It is <em>not</em> intended as a replacement for proper attitude propagation
134 * but should be sufficient for either small time shifts or coarse accuracy.
135 * </p>
136 * @param dt time shift in seconds
137 * @return a new attitude, shifted with respect to the instance (which is immutable)
138 */
139 public FieldAttitude<T> shiftedBy(final double dt) {
140 return new FieldAttitude<>(referenceFrame, orientation.shiftedBy(dt));
141 }
142
143 /** Get a time-shifted attitude.
144 * <p>
145 * The state can be slightly shifted to close dates. This shift is based on
146 * a linear extrapolation for attitude taking the spin rate into account.
147 * It is <em>not</em> intended as a replacement for proper attitude propagation
148 * but should be sufficient for either small time shifts or coarse accuracy.
149 * </p>
150 * @param dt time shift in seconds
151 * @return a new attitude, shifted with respect to the instance (which is immutable)
152 */
153 public FieldAttitude<T> shiftedBy(final T dt) {
154 return new FieldAttitude<>(referenceFrame, orientation.shiftedBy(dt));
155 }
156
157 /** Get a similar attitude with a specific reference frame.
158 * <p>
159 * If the instance reference frame is already the specified one, the instance
160 * itself is returned without any object creation. Otherwise, a new instance
161 * will be created with the specified reference frame. In this case, the
162 * required intermediate rotation and spin between the specified and the
163 * original reference frame will be inserted.
164 * </p>
165 * @param newReferenceFrame desired reference frame for attitude
166 * @return an attitude that has the same orientation and motion as the instance,
167 * but guaranteed to have the specified reference frame
168 */
169 public FieldAttitude<T> withReferenceFrame(final Frame newReferenceFrame) {
170
171 if (newReferenceFrame == referenceFrame) {
172 // simple case, the instance is already compliant
173 return this;
174 }
175
176 // we have to take an intermediate rotation into account
177 final Transform t = newReferenceFrame.getTransformTo(referenceFrame, orientation.getDate().toAbsoluteDate());
178 return new FieldAttitude<>(orientation.getDate(), newReferenceFrame,
179 orientation.getRotation().compose(t.getRotation(), RotationConvention.VECTOR_OPERATOR),
180 orientation.getRotationRate().add(orientation.getRotation().applyTo(t.getRotationRate())),
181 orientation.getRotationAcceleration().add(orientation.getRotation().applyTo(t.getRotationAcceleration())));
182
183 }
184
185 /** Get the date of attitude parameters.
186 * @return date of the attitude parameters
187 */
188 public FieldAbsoluteDate<T> getDate() {
189 return orientation.getDate();
190 }
191
192 /** Get the reference frame.
193 * @return referenceFrame reference frame from which attitude is defined.
194 */
195 public Frame getReferenceFrame() {
196 return referenceFrame;
197 }
198
199 /** Get the complete orientation including spin.
200 * @return complete orientation including spin
201 * @see #getRotation()
202 * @see #getSpin()
203 */
204 public TimeStampedFieldAngularCoordinates<T> getOrientation() {
205 return orientation;
206 }
207
208 /** Get the attitude rotation.
209 * @return attitude satellite rotation from reference frame.
210 * @see #getOrientation()
211 * @see #getSpin()
212 */
213 public FieldRotation<T> getRotation() {
214 return orientation.getRotation();
215 }
216
217 /** Get the satellite spin.
218 * <p>The spin vector is defined in <strong>satellite</strong> frame.</p>
219 * @return spin satellite spin (axis and velocity).
220 * @see #getOrientation()
221 * @see #getRotation()
222 */
223 public FieldVector3D<T> getSpin() {
224 return orientation.getRotationRate();
225 }
226
227 /** Get the satellite rotation acceleration.
228 * <p>The rotation acceleration. vector is defined in <strong>satellite</strong> frame.</p>
229 * @return rotation acceleration
230 * @see #getOrientation()
231 * @see #getRotation()
232 */
233 public FieldVector3D<T> getRotationAcceleration() {
234 return orientation.getRotationAcceleration();
235 }
236
237 /** Get an interpolated instance.
238 * <p>
239 * The interpolated instance is created by polynomial Hermite interpolation
240 * on Rodrigues vector ensuring rotation rate remains the exact derivative of rotation.
241 * </p>
242 * <p>
243 * As this implementation of interpolation is polynomial, it should be used only
244 * with small samples (about 10-20 points) in order to avoid <a
245 * href="http://en.wikipedia.org/wiki/Runge%27s_phenomenon">Runge's phenomenon</a>
246 * and numerical problems (including NaN appearing).
247 * </p>
248 * @param interpolationDate interpolation date
249 * @param sample sample points on which interpolation should be done
250 * @return a new instance, interpolated at specified date
251 */
252 public FieldAttitude<T> interpolate(final FieldAbsoluteDate<T> interpolationDate,
253 final Stream<FieldAttitude<T>> sample) {
254 final List<TimeStampedFieldAngularCoordinates<T>> datedPV =
255 sample.map(attitude -> attitude.orientation).collect(Collectors.toList());
256 final TimeStampedFieldAngularCoordinates<T> interpolated =
257 TimeStampedFieldAngularCoordinates.interpolate(interpolationDate, AngularDerivativesFilter.USE_RR, datedPV);
258 return new FieldAttitude<>(referenceFrame, interpolated);
259 }
260 /**
261 * Converts to an Attitude instance.
262 * @return Attitude with same properties
263 */
264 public Attitude toAttitude() {
265 return new Attitude(orientation.getDate().toAbsoluteDate(), referenceFrame, orientation.toAngularCoordinates());
266 }
267
268 }