1 /* Copyright 2002-2024 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.utils;
18
19
20 import org.hipparchus.CalculusFieldElement;
21 import org.hipparchus.analysis.differentiation.DerivativeStructure;
22 import org.hipparchus.analysis.differentiation.FieldDerivative;
23 import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
24 import org.orekit.errors.OrekitException;
25 import org.orekit.errors.OrekitIllegalArgumentException;
26 import org.orekit.errors.OrekitMessages;
27 import org.orekit.frames.FieldStaticTransform;
28 import org.orekit.frames.FieldTransform;
29 import org.orekit.frames.Frame;
30 import org.orekit.time.FieldAbsoluteDate;
31 import org.orekit.time.FieldTimeStamped;
32
33 /** Field implementation of AbsolutePVCoordinates.
34 * @see AbsolutePVCoordinates
35 * @author Vincent Mouraux
36 * @param <T> type of the field elements
37 */
38 public class FieldAbsolutePVCoordinates<T extends CalculusFieldElement<T>> extends TimeStampedFieldPVCoordinates<T>
39 implements FieldTimeStamped<T>, FieldPVCoordinatesProvider<T> {
40
41 /** Frame in which are defined the coordinates. */
42 private final Frame frame;
43
44 /** Build from position, velocity, acceleration.
45 * @param frame the frame in which the coordinates are defined
46 * @param date coordinates date
47 * @param position the position vector (m)
48 * @param velocity the velocity vector (m/s)
49 * @param acceleration the acceleration vector (m/sÂý)
50 */
51 public FieldAbsolutePVCoordinates(final Frame frame, final FieldAbsoluteDate<T> date,
52 final FieldVector3D<T> position, final FieldVector3D<T> velocity, final FieldVector3D<T> acceleration) {
53 super(date, position, velocity, acceleration);
54 this.frame = frame;
55 }
56
57 /** Build from position and velocity. Acceleration is set to zero.
58 * @param frame the frame in which the coordinates are defined
59 * @param date coordinates date
60 * @param position the position vector (m)
61 * @param velocity the velocity vector (m/s)
62 */
63 public FieldAbsolutePVCoordinates(final Frame frame, final FieldAbsoluteDate<T> date,
64 final FieldVector3D<T> position,
65 final FieldVector3D<T> velocity) {
66 this(frame, date, position, velocity, FieldVector3D.getZero(date.getField()));
67 }
68
69 /** Build from frame, date and FieldPVA coordinates.
70 * @param frame the frame in which the coordinates are defined
71 * @param date date of the coordinates
72 * @param pva TimeStampedPVCoordinates
73 */
74 public FieldAbsolutePVCoordinates(final Frame frame, final FieldAbsoluteDate<T> date, final FieldPVCoordinates<T> pva) {
75 super(date, pva);
76 this.frame = frame;
77 }
78
79 /** Build from frame and TimeStampedFieldPVCoordinates.
80 * @param frame the frame in which the coordinates are defined
81 * @param pva TimeStampedFieldPVCoordinates
82 */
83 public FieldAbsolutePVCoordinates(final Frame frame, final TimeStampedFieldPVCoordinates<T> pva) {
84 super(pva.getDate(), pva);
85 this.frame = frame;
86 }
87
88 /** Multiplicative constructor
89 * <p>Build a FieldAbsolutePVCoordinates from another one and a scale factor.</p>
90 * <p>The TimeStampedFieldPVCoordinates built will be a * AbsPva</p>
91 * @param date date of the built coordinates
92 * @param a scale factor
93 * @param AbsPva base (unscaled) FieldAbsolutePVCoordinates
94 */
95 public FieldAbsolutePVCoordinates(final FieldAbsoluteDate<T> date,
96 final T a, final FieldAbsolutePVCoordinates<T> AbsPva) {
97 super(date, a, AbsPva);
98 this.frame = AbsPva.frame;
99 }
100
101 /** Subtractive constructor
102 * <p>Build a relative FieldAbsolutePVCoordinates from a start and an end position.</p>
103 * <p>The FieldAbsolutePVCoordinates built will be end - start.</p>
104 * <p>In case start and end use two different pseudo-inertial frames,
105 * the new FieldAbsolutePVCoordinates arbitrarily be defined in the start frame. </p>
106 * @param date date of the built coordinates
107 * @param start Starting FieldAbsolutePVCoordinates
108 * @param end ending FieldAbsolutePVCoordinates
109 */
110 public FieldAbsolutePVCoordinates(final FieldAbsoluteDate<T> date,
111 final FieldAbsolutePVCoordinates<T> start, final FieldAbsolutePVCoordinates<T> end) {
112 super(date, start, end);
113 ensureIdenticalFrames(start, end);
114 this.frame = start.frame;
115 }
116
117 /** Linear constructor
118 * <p>Build a FieldAbsolutePVCoordinates from two other ones and corresponding scale factors.</p>
119 * <p>The FieldAbsolutePVCoordinates built will be a1 * u1 + a2 * u2</p>
120 * <p>In case the FieldAbsolutePVCoordinates use different pseudo-inertial frames,
121 * the new FieldAbsolutePVCoordinates arbitrarily be defined in the first frame. </p>
122 * @param date date of the built coordinates
123 * @param a1 first scale factor
124 * @param absPv1 first base (unscaled) FieldAbsolutePVCoordinates
125 * @param a2 second scale factor
126 * @param absPv2 second base (unscaled) FieldAbsolutePVCoordinates
127 */
128 public FieldAbsolutePVCoordinates(final FieldAbsoluteDate<T> date,
129 final T a1, final FieldAbsolutePVCoordinates<T> absPv1,
130 final T a2, final FieldAbsolutePVCoordinates<T> absPv2) {
131 super(date, a1, absPv1.getPVCoordinates(), a2, absPv2.getPVCoordinates());
132 ensureIdenticalFrames(absPv1, absPv2);
133 this.frame = absPv1.getFrame();
134 }
135
136 /** Linear constructor
137 * <p>Build a FieldAbsolutePVCoordinates from three other ones and corresponding scale factors.</p>
138 * <p>The FieldAbsolutePVCoordinates built will be a1 * u1 + a2 * u2 + a3 * u3</p>
139 * <p>In case the FieldAbsolutePVCoordinates use different pseudo-inertial frames,
140 * the new FieldAbsolutePVCoordinates arbitrarily be defined in the first frame. </p>
141 * @param date date of the built coordinates
142 * @param a1 first scale factor
143 * @param absPv1 first base (unscaled) FieldAbsolutePVCoordinates
144 * @param a2 second scale factor
145 * @param absPv2 second base (unscaled) FieldAbsolutePVCoordinates
146 * @param a3 third scale factor
147 * @param absPv3 third base (unscaled) FieldAbsolutePVCoordinates
148 */
149 public FieldAbsolutePVCoordinates(final FieldAbsoluteDate<T> date,
150 final T a1, final FieldAbsolutePVCoordinates<T> absPv1,
151 final T a2, final FieldAbsolutePVCoordinates<T> absPv2,
152 final T a3, final FieldAbsolutePVCoordinates<T> absPv3) {
153 super(date, a1, absPv1.getPVCoordinates(), a2, absPv2.getPVCoordinates(),
154 a3, absPv3.getPVCoordinates());
155 ensureIdenticalFrames(absPv1, absPv2);
156 ensureIdenticalFrames(absPv1, absPv3);
157 this.frame = absPv1.getFrame();
158 }
159
160 /** Linear constructor
161 * <p>Build a FieldAbsolutePVCoordinates from four other ones and corresponding scale factors.</p>
162 * <p>The FieldAbsolutePVCoordinates built will be a1 * u1 + a2 * u2 + a3 * u3 + a4 * u4</p>
163 * <p>In case the FieldAbsolutePVCoordinates use different pseudo-inertial frames,
164 * the new AbsolutePVCoordinates arbitrarily be defined in the first frame. </p>
165 * @param date date of the built coordinates
166 * @param a1 first scale factor
167 * @param absPv1 first base (unscaled) FieldAbsolutePVCoordinates
168 * @param a2 second scale factor
169 * @param absPv2 second base (unscaled) FieldAbsolutePVCoordinates
170 * @param a3 third scale factor
171 * @param absPv3 third base (unscaled) FieldAbsolutePVCoordinates
172 * @param a4 fourth scale factor
173 * @param absPv4 fourth base (unscaled) FieldAbsolutePVCoordinates
174 */
175 public FieldAbsolutePVCoordinates(final FieldAbsoluteDate<T> date,
176 final T a1, final FieldAbsolutePVCoordinates<T> absPv1,
177 final T a2, final FieldAbsolutePVCoordinates<T> absPv2,
178 final T a3, final FieldAbsolutePVCoordinates<T> absPv3,
179 final T a4, final FieldAbsolutePVCoordinates<T> absPv4) {
180 super(date, a1, absPv1.getPVCoordinates(), a2, absPv2.getPVCoordinates(),
181 a3, absPv3.getPVCoordinates(), a4, absPv4.getPVCoordinates());
182 ensureIdenticalFrames(absPv1, absPv2);
183 ensureIdenticalFrames(absPv1, absPv3);
184 ensureIdenticalFrames(absPv1, absPv4);
185 this.frame = absPv1.getFrame();
186 }
187
188 /** Builds a FieldAbsolutePVCoordinates triplet from a {@link FieldVector3D}<{@link DerivativeStructure}>.
189 * <p>
190 * The vector components must have time as their only derivation parameter and
191 * have consistent derivation orders.
192 * </p>
193 * @param frame the frame in which the parameters are defined
194 * @param date date of the built coordinates
195 * @param p vector with time-derivatives embedded within the coordinates
196 * @param <U> type of the derivative
197 */
198 public <U extends FieldDerivative<T, U>> FieldAbsolutePVCoordinates(final Frame frame, final FieldAbsoluteDate<T> date,
199 final FieldVector3D<U> p) {
200 super(date, p);
201 this.frame = frame;
202 }
203
204 /** Ensure that the frames from two FieldAbsolutePVCoordinates are identical.
205 * @param absPv1 first FieldAbsolutePVCoordinates
206 * @param absPv2 first FieldAbsolutePVCoordinates
207 * @param <T> the type of the field elements
208 * @throws OrekitIllegalArgumentException if frames are different
209 */
210 private static <T extends CalculusFieldElement<T>> void ensureIdenticalFrames(final FieldAbsolutePVCoordinates<T> absPv1, final FieldAbsolutePVCoordinates<T> absPv2)
211 throws OrekitIllegalArgumentException {
212 if (!absPv1.frame.equals(absPv2.frame)) {
213 throw new OrekitIllegalArgumentException(OrekitMessages.INCOMPATIBLE_FRAMES,
214 absPv1.frame.getName(), absPv2.frame.getName());
215 }
216 }
217
218 /** Get a time-shifted state.
219 * <p>
220 * The state can be slightly shifted to close dates. This shift is based on
221 * a simple Taylor expansion. It is <em>not</em> intended as a replacement for
222 * proper orbit propagation (it is not even Keplerian!) but should be sufficient
223 * for either small time shifts or coarse accuracy.
224 * </p>
225 * @param dt time shift in seconds
226 * @return a new state, shifted with respect to the instance (which is immutable)
227 */
228 public FieldAbsolutePVCoordinates<T> shiftedBy(final T dt) {
229 final TimeStampedFieldPVCoordinates<T> spv = super.shiftedBy(dt);
230 return new FieldAbsolutePVCoordinates<>(frame, spv);
231 }
232
233 /** Get a time-shifted state.
234 * <p>
235 * The state can be slightly shifted to close dates. This shift is based on
236 * a simple Taylor expansion. It is <em>not</em> intended as a replacement for
237 * proper orbit propagation (it is not even Keplerian!) but should be sufficient
238 * for either small time shifts or coarse accuracy.
239 * </p>
240 * @param dt time shift in seconds
241 * @return a new state, shifted with respect to the instance (which is immutable)
242 */
243 public FieldAbsolutePVCoordinates<T> shiftedBy(final double dt) {
244 final TimeStampedFieldPVCoordinates<T> spv = super.shiftedBy(dt);
245 return new FieldAbsolutePVCoordinates<>(frame, spv);
246 }
247
248 /** Create a local provider using simply Taylor expansion through {@link #shiftedBy(double)}.
249 * <p>
250 * The time evolution is based on a simple Taylor expansion. It is <em>not</em> intended as a
251 * replacement for proper orbit propagation (it is not even Keplerian!) but should be sufficient
252 * for either small time shifts or coarse accuracy.
253 * </p>
254 * @return provider based on Taylor expansion, for small time shifts around instance date
255 */
256 public FieldPVCoordinatesProvider<T> toTaylorProvider() {
257 return new FieldPVCoordinatesProvider<T>() {
258 /** {@inheritDoc} */
259 public FieldVector3D<T> getPosition(final FieldAbsoluteDate<T> d, final Frame f) {
260 final TimeStampedFieldPVCoordinates<T> shifted = shiftedBy(d.durationFrom(getDate()));
261 final FieldStaticTransform<T> transform = frame.getStaticTransformTo(f, d);
262 return transform.transformPosition(shifted.getPosition());
263 }
264 /** {@inheritDoc} */
265 public TimeStampedFieldPVCoordinates<T> getPVCoordinates(final FieldAbsoluteDate<T> d, final Frame f) {
266 final TimeStampedFieldPVCoordinates<T> shifted = shiftedBy(d.durationFrom(getDate()));
267 final FieldTransform<T> transform = frame.getTransformTo(f, d);
268 return transform.transformPVCoordinates(shifted);
269 }
270 };
271 }
272
273 /** Get the frame in which the coordinates are defined.
274 * @return frame in which the coordinates are defined
275 */
276 public Frame getFrame() {
277 return frame;
278 }
279
280 /** Get the TimeStampedFieldPVCoordinates.
281 * @return TimeStampedFieldPVCoordinates
282 */
283 public TimeStampedFieldPVCoordinates<T> getPVCoordinates() {
284 return this;
285 }
286
287 /** Get the position in a specified frame.
288 * @param outputFrame frame in which the position coordinates shall be computed
289 * @return position
290 * @see #getPVCoordinates(Frame)
291 * @since 12.0
292 */
293 public FieldVector3D<T> getPosition(final Frame outputFrame) {
294 // If output frame requested is the same as definition frame,
295 // Position vector is returned directly
296 if (outputFrame == frame) {
297 return getPosition();
298 }
299
300 // Else, position vector is transformed to output frame
301 final FieldStaticTransform<T> t = frame.getStaticTransformTo(outputFrame, getDate());
302 return t.transformPosition(getPosition());
303 }
304
305 /** Get the TimeStampedFieldPVCoordinates in a specified frame.
306 * @param outputFrame frame in which the position/velocity coordinates shall be computed
307 * @return TimeStampedFieldPVCoordinates
308 * @exception OrekitException if transformation between frames cannot be computed
309 * @see #getPVCoordinates()
310 */
311 public TimeStampedFieldPVCoordinates<T> getPVCoordinates(final Frame outputFrame) {
312 // If output frame requested is the same as definition frame,
313 // PV coordinates are returned directly
314 if (outputFrame == frame) {
315 return getPVCoordinates();
316 }
317
318 // Else, PV coordinates are transformed to output frame
319 final FieldTransform<T> t = frame.getTransformTo(outputFrame, getDate());
320 return t.transformPVCoordinates(getPVCoordinates());
321 }
322
323 @Override
324 public TimeStampedFieldPVCoordinates<T> getPVCoordinates(final FieldAbsoluteDate<T> otherDate, final Frame outputFrame) {
325 return shiftedBy(otherDate.durationFrom(getDate())).getPVCoordinates(outputFrame);
326 }
327
328 /**
329 * Converts to an AbsolutePVCoordinates instance.
330 * @return AbsolutePVCoordinates with same properties
331 */
332 public AbsolutePVCoordinates toAbsolutePVCoordinates() {
333 return new AbsolutePVCoordinates(frame, this.getDate()
334 .toAbsoluteDate(), this.getPVCoordinates().toPVCoordinates());
335 }
336 }