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