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