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.utils;
18  
19  import java.util.Collection;
20  import java.util.stream.Stream;
21  
22  import org.hipparchus.CalculusFieldElement;
23  import org.hipparchus.analysis.differentiation.FieldDerivative;
24  import org.hipparchus.analysis.differentiation.FieldDerivativeStructure;
25  import org.hipparchus.analysis.interpolation.FieldHermiteInterpolator;
26  import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
27  import org.orekit.annotation.DefaultDataContext;
28  import org.orekit.data.DataContext;
29  import org.orekit.errors.OrekitInternalError;
30  import org.orekit.time.AbsoluteDate;
31  import org.orekit.time.FieldAbsoluteDate;
32  import org.orekit.time.FieldTimeStamped;
33  import org.orekit.time.TimeScale;
34  import org.orekit.time.TimeStamped;
35  
36  /** {@link TimeStamped time-stamped} version of {@link FieldPVCoordinates}.
37   * <p>Instances of this class are guaranteed to be immutable.</p>
38   * @param <T> the type of the field elements
39   * @author Luc Maisonobe
40   * @since 7.0
41   */
42  public class TimeStampedFieldPVCoordinates<T extends CalculusFieldElement<T>>
43      extends FieldPVCoordinates<T> implements FieldTimeStamped<T> {
44  
45      /** The date. */
46      private final FieldAbsoluteDate<T> date;
47  
48      /** Builds a PVCoordinates pair.
49       * @param date coordinates date
50       * @param position the position vector (m)
51       * @param velocity the velocity vector (m/s)
52       * @param acceleration the acceleration vector (m/s²)
53       */
54      public TimeStampedFieldPVCoordinates(final AbsoluteDate date,
55                                           final FieldVector3D<T> position,
56                                           final FieldVector3D<T> velocity,
57                                           final FieldVector3D<T> acceleration) {
58          this(new FieldAbsoluteDate<>(position.getX().getField(), date),
59               position, velocity, acceleration);
60      }
61  
62      /** Builds a PVCoordinates pair.
63       * @param date coordinates date
64       * @param position the position vector (m)
65       * @param velocity the velocity vector (m/s)
66       * @param acceleration the acceleration vector (m/s²)
67       */
68      public TimeStampedFieldPVCoordinates(final FieldAbsoluteDate<T> date,
69                                           final FieldVector3D<T> position,
70                                           final FieldVector3D<T> velocity,
71                                           final FieldVector3D<T> acceleration) {
72          super(position, velocity, acceleration);
73          this.date = date;
74      }
75  
76      /** Basic constructor.
77       * <p>Build a PVCoordinates from another one at a given date</p>
78       * <p>The PVCoordinates built will be pv</p>
79       * @param date date of the built coordinates
80       * @param pv base (unscaled) PVCoordinates
81       */
82      public TimeStampedFieldPVCoordinates(final AbsoluteDate date, final FieldPVCoordinates<T> pv) {
83          this(new FieldAbsoluteDate<>(pv.getPosition().getX().getField(), date), pv);
84      }
85  
86      /** Basic constructor.
87       * <p>Build a PVCoordinates from another one at a given date</p>
88       * <p>The PVCoordinates built will be pv</p>
89       * @param date date of the built coordinates
90       * @param pv base (unscaled) PVCoordinates
91       */
92      public TimeStampedFieldPVCoordinates(final FieldAbsoluteDate<T> date, final FieldPVCoordinates<T> pv) {
93          super(pv.getPosition(),
94                pv.getVelocity(),
95                pv.getAcceleration());
96          this.date = date;
97      }
98  
99      /** Multiplicative constructor
100      * <p>Build a PVCoordinates from another one and a scale factor.</p>
101      * <p>The PVCoordinates built will be a * pv</p>
102      * @param date date of the built coordinates
103      * @param a scale factor
104      * @param pv base (unscaled) PVCoordinates
105      */
106     public TimeStampedFieldPVCoordinates(final AbsoluteDate date,
107                                          final double a, final FieldPVCoordinates<T> pv) {
108         this(new FieldAbsoluteDate<>(pv.getPosition().getX().getField(), date), a, pv);
109     }
110 
111     /** Multiplicative constructor
112      * <p>Build a PVCoordinates from another one and a scale factor.</p>
113      * <p>The PVCoordinates built will be a * pv</p>
114      * @param date date of the built coordinates
115      * @param a scale factor
116      * @param pv base (unscaled) PVCoordinates
117      */
118     public TimeStampedFieldPVCoordinates(final FieldAbsoluteDate<T> date,
119                                          final double a, final FieldPVCoordinates<T> pv) {
120         super(new FieldVector3D<>(a, pv.getPosition()),
121               new FieldVector3D<>(a, pv.getVelocity()),
122               new FieldVector3D<>(a, pv.getAcceleration()));
123         this.date = date;
124     }
125 
126     /** Multiplicative constructor
127      * <p>Build a PVCoordinates from another one and a scale factor.</p>
128      * <p>The PVCoordinates built will be a * pv</p>
129      * @param date date of the built coordinates
130      * @param a scale factor
131      * @param pv base (unscaled) PVCoordinates
132      */
133     public TimeStampedFieldPVCoordinates(final AbsoluteDate date,
134                                          final T a, final FieldPVCoordinates<T> pv) {
135         this(new FieldAbsoluteDate<>(a.getField(), date), a, pv);
136     }
137 
138     /** Multiplicative constructor
139      * <p>Build a PVCoordinates from another one and a scale factor.</p>
140      * <p>The PVCoordinates built will be a * pv</p>
141      * @param date date of the built coordinates
142      * @param a scale factor
143      * @param pv base (unscaled) PVCoordinates
144      */
145     public TimeStampedFieldPVCoordinates(final FieldAbsoluteDate<T> date,
146                                          final T a, final FieldPVCoordinates<T> pv) {
147         super(new FieldVector3D<>(a, pv.getPosition()),
148               new FieldVector3D<>(a, pv.getVelocity()),
149               new FieldVector3D<>(a, pv.getAcceleration()));
150         this.date = date;
151     }
152 
153     /** Multiplicative constructor
154      * <p>Build a PVCoordinates from another one and a scale factor.</p>
155      * <p>The PVCoordinates built will be a * pv</p>
156      * @param date date of the built coordinates
157      * @param a scale factor
158      * @param pv base (unscaled) PVCoordinates
159      */
160     public TimeStampedFieldPVCoordinates(final AbsoluteDate date,
161                                          final T a, final PVCoordinates pv) {
162         this(new FieldAbsoluteDate<>(a.getField(), date), a, pv);
163     }
164 
165     /** Multiplicative constructor
166      * <p>Build a PVCoordinates from another one and a scale factor.</p>
167      * <p>The PVCoordinates built will be a * pv</p>
168      * @param date date of the built coordinates
169      * @param a scale factor
170      * @param pv base (unscaled) PVCoordinates
171      */
172     public TimeStampedFieldPVCoordinates(final FieldAbsoluteDate<T> date,
173                                          final T a, final PVCoordinates pv) {
174         super(new FieldVector3D<>(a, pv.getPosition()),
175               new FieldVector3D<>(a, pv.getVelocity()),
176               new FieldVector3D<>(a, pv.getAcceleration()));
177         this.date = date;
178     }
179 
180     /** Subtractive constructor
181      * <p>Build a relative PVCoordinates from a start and an end position.</p>
182      * <p>The PVCoordinates built will be end - start.</p>
183      * @param date date of the built coordinates
184      * @param start Starting PVCoordinates
185      * @param end ending PVCoordinates
186      */
187     public TimeStampedFieldPVCoordinates(final AbsoluteDate date,
188                                          final FieldPVCoordinates<T> start, final FieldPVCoordinates<T> end) {
189         this(new FieldAbsoluteDate<>(start.getPosition().getX().getField(), date), start, end);
190     }
191 
192     /** Subtractive constructor
193      * <p>Build a relative PVCoordinates from a start and an end position.</p>
194      * <p>The PVCoordinates built will be end - start.</p>
195      * @param date date of the built coordinates
196      * @param start Starting PVCoordinates
197      * @param end ending PVCoordinates
198      */
199     public TimeStampedFieldPVCoordinates(final FieldAbsoluteDate<T> date,
200                                          final FieldPVCoordinates<T> start, final FieldPVCoordinates<T> end) {
201         super(end.getPosition().subtract(start.getPosition()),
202               end.getVelocity().subtract(start.getVelocity()),
203               end.getAcceleration().subtract(start.getAcceleration()));
204         this.date = date;
205     }
206 
207     /** Linear constructor
208      * <p>Build a PVCoordinates from two other ones and corresponding scale factors.</p>
209      * <p>The PVCoordinates built will be a1 * u1 + a2 * u2</p>
210      * @param date date of the built coordinates
211      * @param a1 first scale factor
212      * @param pv1 first base (unscaled) PVCoordinates
213      * @param a2 second scale factor
214      * @param pv2 second base (unscaled) PVCoordinates
215      */
216     public TimeStampedFieldPVCoordinates(final AbsoluteDate date,
217                                          final double a1, final FieldPVCoordinates<T> pv1,
218                                          final double a2, final FieldPVCoordinates<T> pv2) {
219         this(new FieldAbsoluteDate<>(pv1.getPosition().getX().getField(), date),
220              a1, pv1, a2, pv2);
221     }
222 
223     /** Linear constructor
224      * <p>Build a PVCoordinates from two other ones and corresponding scale factors.</p>
225      * <p>The PVCoordinates built will be a1 * u1 + a2 * u2</p>
226      * @param date date of the built coordinates
227      * @param a1 first scale factor
228      * @param pv1 first base (unscaled) PVCoordinates
229      * @param a2 second scale factor
230      * @param pv2 second base (unscaled) PVCoordinates
231      */
232     public TimeStampedFieldPVCoordinates(final FieldAbsoluteDate<T> date,
233                                          final double a1, final FieldPVCoordinates<T> pv1,
234                                          final double a2, final FieldPVCoordinates<T> pv2) {
235         super(new FieldVector3D<>(a1, pv1.getPosition(),     a2, pv2.getPosition()),
236               new FieldVector3D<>(a1, pv1.getVelocity(),     a2, pv2.getVelocity()),
237               new FieldVector3D<>(a1, pv1.getAcceleration(), a2, pv2.getAcceleration()));
238         this.date = date;
239     }
240 
241     /** Linear constructor
242      * <p>Build a PVCoordinates from two other ones and corresponding scale factors.</p>
243      * <p>The PVCoordinates built will be a1 * u1 + a2 * u2</p>
244      * @param date date of the built coordinates
245      * @param a1 first scale factor
246      * @param pv1 first base (unscaled) PVCoordinates
247      * @param a2 second scale factor
248      * @param pv2 second base (unscaled) PVCoordinates
249      */
250     public TimeStampedFieldPVCoordinates(final AbsoluteDate date,
251                                          final T a1, final FieldPVCoordinates<T> pv1,
252                                          final T a2, final FieldPVCoordinates<T> pv2) {
253         this(new FieldAbsoluteDate<>(a1.getField(), date),
254              a1, pv1, a2, pv2);
255     }
256 
257     /** Linear constructor
258      * <p>Build a PVCoordinates from two other ones and corresponding scale factors.</p>
259      * <p>The PVCoordinates built will be a1 * u1 + a2 * u2</p>
260      * @param date date of the built coordinates
261      * @param a1 first scale factor
262      * @param pv1 first base (unscaled) PVCoordinates
263      * @param a2 second scale factor
264      * @param pv2 second base (unscaled) PVCoordinates
265      */
266     public TimeStampedFieldPVCoordinates(final FieldAbsoluteDate<T> date,
267                                          final T a1, final FieldPVCoordinates<T> pv1,
268                                          final T a2, final FieldPVCoordinates<T> pv2) {
269         super(new FieldVector3D<>(a1, pv1.getPosition(),     a2, pv2.getPosition()),
270               new FieldVector3D<>(a1, pv1.getVelocity(),     a2, pv2.getVelocity()),
271               new FieldVector3D<>(a1, pv1.getAcceleration(), a2, pv2.getAcceleration()));
272         this.date = date;
273     }
274 
275     /** Linear constructor
276      * <p>Build a PVCoordinates from two other ones and corresponding scale factors.</p>
277      * <p>The PVCoordinates built will be a1 * u1 + a2 * u2</p>
278      * @param date date of the built coordinates
279      * @param a1 first scale factor
280      * @param pv1 first base (unscaled) PVCoordinates
281      * @param a2 second scale factor
282      * @param pv2 second base (unscaled) PVCoordinates
283      */
284     public TimeStampedFieldPVCoordinates(final AbsoluteDate date,
285                                          final T a1, final PVCoordinates pv1,
286                                          final T a2, final PVCoordinates pv2) {
287         this(new FieldAbsoluteDate<>(a1.getField(), date),
288              a1, pv1, a2, pv2);
289     }
290 
291     /** Linear constructor
292      * <p>Build a PVCoordinates from two other ones and corresponding scale factors.</p>
293      * <p>The PVCoordinates built will be a1 * u1 + a2 * u2</p>
294      * @param date date of the built coordinates
295      * @param a1 first scale factor
296      * @param pv1 first base (unscaled) PVCoordinates
297      * @param a2 second scale factor
298      * @param pv2 second base (unscaled) PVCoordinates
299      */
300     public TimeStampedFieldPVCoordinates(final FieldAbsoluteDate<T> date,
301                                          final T a1, final PVCoordinates pv1,
302                                          final T a2, final PVCoordinates pv2) {
303         super(new FieldVector3D<>(a1, pv1.getPosition(),     a2, pv2.getPosition()),
304               new FieldVector3D<>(a1, pv1.getVelocity(),     a2, pv2.getVelocity()),
305               new FieldVector3D<>(a1, pv1.getAcceleration(), a2, pv2.getAcceleration()));
306         this.date = date;
307     }
308 
309     /** Linear constructor
310      * <p>Build a PVCoordinates from three other ones and corresponding scale factors.</p>
311      * <p>The PVCoordinates built will be a1 * u1 + a2 * u2 + a3 * u3</p>
312      * @param date date of the built coordinates
313      * @param a1 first scale factor
314      * @param pv1 first base (unscaled) PVCoordinates
315      * @param a2 second scale factor
316      * @param pv2 second base (unscaled) PVCoordinates
317      * @param a3 third scale factor
318      * @param pv3 third base (unscaled) PVCoordinates
319      */
320     public TimeStampedFieldPVCoordinates(final AbsoluteDate date,
321                                          final double a1, final FieldPVCoordinates<T> pv1,
322                                          final double a2, final FieldPVCoordinates<T> pv2,
323                                          final double a3, final FieldPVCoordinates<T> pv3) {
324         this(new FieldAbsoluteDate<>(pv1.getPosition().getX().getField(), date),
325              a1, pv1, a2, pv2, a3, pv3);
326     }
327 
328     /** Linear constructor
329      * <p>Build a PVCoordinates from three other ones and corresponding scale factors.</p>
330      * <p>The PVCoordinates built will be a1 * u1 + a2 * u2 + a3 * u3</p>
331      * @param date date of the built coordinates
332      * @param a1 first scale factor
333      * @param pv1 first base (unscaled) PVCoordinates
334      * @param a2 second scale factor
335      * @param pv2 second base (unscaled) PVCoordinates
336      * @param a3 third scale factor
337      * @param pv3 third base (unscaled) PVCoordinates
338      */
339     public TimeStampedFieldPVCoordinates(final FieldAbsoluteDate<T> date,
340                                          final double a1, final FieldPVCoordinates<T> pv1,
341                                          final double a2, final FieldPVCoordinates<T> pv2,
342                                          final double a3, final FieldPVCoordinates<T> pv3) {
343         super(new FieldVector3D<>(a1, pv1.getPosition(),     a2, pv2.getPosition(),     a3, pv3.getPosition()),
344               new FieldVector3D<>(a1, pv1.getVelocity(),     a2, pv2.getVelocity(),     a3, pv3.getVelocity()),
345               new FieldVector3D<>(a1, pv1.getAcceleration(), a2, pv2.getAcceleration(), a3, pv3.getAcceleration()));
346         this.date = date;
347     }
348 
349     /** Linear constructor
350      * <p>Build a PVCoordinates from three other ones and corresponding scale factors.</p>
351      * <p>The PVCoordinates built will be a1 * u1 + a2 * u2 + a3 * u3</p>
352      * @param date date of the built coordinates
353      * @param a1 first scale factor
354      * @param pv1 first base (unscaled) PVCoordinates
355      * @param a2 second scale factor
356      * @param pv2 second base (unscaled) PVCoordinates
357      * @param a3 third scale factor
358      * @param pv3 third base (unscaled) PVCoordinates
359      */
360     public TimeStampedFieldPVCoordinates(final AbsoluteDate date,
361                                          final T a1, final FieldPVCoordinates<T> pv1,
362                                          final T a2, final FieldPVCoordinates<T> pv2,
363                                          final T a3, final FieldPVCoordinates<T> pv3) {
364         this(new FieldAbsoluteDate<>(a1.getField(), date),
365              a1, pv1, a2, pv2, a3, pv3);
366     }
367 
368     /** Linear constructor
369      * <p>Build a PVCoordinates from three other ones and corresponding scale factors.</p>
370      * <p>The PVCoordinates built will be a1 * u1 + a2 * u2 + a3 * u3</p>
371      * @param date date of the built coordinates
372      * @param a1 first scale factor
373      * @param pv1 first base (unscaled) PVCoordinates
374      * @param a2 second scale factor
375      * @param pv2 second base (unscaled) PVCoordinates
376      * @param a3 third scale factor
377      * @param pv3 third base (unscaled) PVCoordinates
378      */
379     public TimeStampedFieldPVCoordinates(final FieldAbsoluteDate<T> date,
380                                          final T a1, final FieldPVCoordinates<T> pv1,
381                                          final T a2, final FieldPVCoordinates<T> pv2,
382                                          final T a3, final FieldPVCoordinates<T> pv3) {
383         super(new FieldVector3D<>(a1, pv1.getPosition(),     a2, pv2.getPosition(),     a3, pv3.getPosition()),
384               new FieldVector3D<>(a1, pv1.getVelocity(),     a2, pv2.getVelocity(),     a3, pv3.getVelocity()),
385               new FieldVector3D<>(a1, pv1.getAcceleration(), a2, pv2.getAcceleration(), a3, pv3.getAcceleration()));
386         this.date = date;
387     }
388 
389     /** Linear constructor
390      * <p>Build a PVCoordinates from three other ones and corresponding scale factors.</p>
391      * <p>The PVCoordinates built will be a1 * u1 + a2 * u2 + a3 * u3</p>
392      * @param date date of the built coordinates
393      * @param a1 first scale factor
394      * @param pv1 first base (unscaled) PVCoordinates
395      * @param a2 second scale factor
396      * @param pv2 second base (unscaled) PVCoordinates
397      * @param a3 third scale factor
398      * @param pv3 third base (unscaled) PVCoordinates
399      */
400     public TimeStampedFieldPVCoordinates(final AbsoluteDate date,
401                                          final T a1, final PVCoordinates pv1,
402                                          final T a2, final PVCoordinates pv2,
403                                          final T a3, final PVCoordinates pv3) {
404         this(new FieldAbsoluteDate<>(a1.getField(), date),
405              a1, pv1, a2, pv2, a3, pv3);
406     }
407 
408     /** Linear constructor
409      * <p>Build a PVCoordinates from three other ones and corresponding scale factors.</p>
410      * <p>The PVCoordinates built will be a1 * u1 + a2 * u2 + a3 * u3</p>
411      * @param date date of the built coordinates
412      * @param a1 first scale factor
413      * @param pv1 first base (unscaled) PVCoordinates
414      * @param a2 second scale factor
415      * @param pv2 second base (unscaled) PVCoordinates
416      * @param a3 third scale factor
417      * @param pv3 third base (unscaled) PVCoordinates
418      */
419     public TimeStampedFieldPVCoordinates(final FieldAbsoluteDate<T> date,
420                                          final T a1, final PVCoordinates pv1,
421                                          final T a2, final PVCoordinates pv2,
422                                          final T a3, final PVCoordinates pv3) {
423         super(new FieldVector3D<>(a1, pv1.getPosition(),     a2, pv2.getPosition(),     a3, pv3.getPosition()),
424               new FieldVector3D<>(a1, pv1.getVelocity(),     a2, pv2.getVelocity(),     a3, pv3.getVelocity()),
425               new FieldVector3D<>(a1, pv1.getAcceleration(), a2, pv2.getAcceleration(), a3, pv3.getAcceleration()));
426         this.date = date;
427     }
428 
429     /** Linear constructor
430      * <p>Build a PVCoordinates from four other ones and corresponding scale factors.</p>
431      * <p>The PVCoordinates built will be a1 * u1 + a2 * u2 + a3 * u3 + a4 * u4</p>
432      * @param date date of the built coordinates
433      * @param a1 first scale factor
434      * @param pv1 first base (unscaled) PVCoordinates
435      * @param a2 second scale factor
436      * @param pv2 second base (unscaled) PVCoordinates
437      * @param a3 third scale factor
438      * @param pv3 third base (unscaled) PVCoordinates
439      * @param a4 fourth scale factor
440      * @param pv4 fourth base (unscaled) PVCoordinates
441      */
442     public TimeStampedFieldPVCoordinates(final AbsoluteDate date,
443                                          final double a1, final FieldPVCoordinates<T> pv1,
444                                          final double a2, final FieldPVCoordinates<T> pv2,
445                                          final double a3, final FieldPVCoordinates<T> pv3,
446                                          final double a4, final FieldPVCoordinates<T> pv4) {
447         this(new FieldAbsoluteDate<>(pv1.getPosition().getX().getField(), date),
448              a1, pv1, a2, pv2, a3, pv3, a4, pv4);
449     }
450 
451     /** Linear constructor
452      * <p>Build a PVCoordinates from four other ones and corresponding scale factors.</p>
453      * <p>The PVCoordinates built will be a1 * u1 + a2 * u2 + a3 * u3 + a4 * u4</p>
454      * @param date date of the built coordinates
455      * @param a1 first scale factor
456      * @param pv1 first base (unscaled) PVCoordinates
457      * @param a2 second scale factor
458      * @param pv2 second base (unscaled) PVCoordinates
459      * @param a3 third scale factor
460      * @param pv3 third base (unscaled) PVCoordinates
461      * @param a4 fourth scale factor
462      * @param pv4 fourth base (unscaled) PVCoordinates
463      */
464     public TimeStampedFieldPVCoordinates(final FieldAbsoluteDate<T> date,
465                                          final double a1, final FieldPVCoordinates<T> pv1,
466                                          final double a2, final FieldPVCoordinates<T> pv2,
467                                          final double a3, final FieldPVCoordinates<T> pv3,
468                                          final double a4, final FieldPVCoordinates<T> pv4) {
469         super(new FieldVector3D<>(a1, pv1.getPosition(),     a2, pv2.getPosition(),
470                                   a3, pv3.getPosition(),     a4, pv4.getPosition()),
471               new FieldVector3D<>(a1, pv1.getVelocity(),     a2, pv2.getVelocity(),
472                                   a3, pv3.getVelocity(),     a4, pv4.getVelocity()),
473               new FieldVector3D<>(a1, pv1.getAcceleration(), a2, pv2.getAcceleration(),
474                                   a3, pv3.getAcceleration(), a4, pv4.getAcceleration()));
475         this.date = date;
476     }
477 
478     /** Linear constructor
479      * <p>Build a PVCoordinates from four other ones and corresponding scale factors.</p>
480      * <p>The PVCoordinates built will be a1 * u1 + a2 * u2 + a3 * u3 + a4 * u4</p>
481      * @param date date of the built coordinates
482      * @param a1 first scale factor
483      * @param pv1 first base (unscaled) PVCoordinates
484      * @param a2 second scale factor
485      * @param pv2 second base (unscaled) PVCoordinates
486      * @param a3 third scale factor
487      * @param pv3 third base (unscaled) PVCoordinates
488      * @param a4 fourth scale factor
489      * @param pv4 fourth base (unscaled) PVCoordinates
490      */
491     public TimeStampedFieldPVCoordinates(final AbsoluteDate date,
492                                          final T a1, final FieldPVCoordinates<T> pv1,
493                                          final T a2, final FieldPVCoordinates<T> pv2,
494                                          final T a3, final FieldPVCoordinates<T> pv3,
495                                          final T a4, final FieldPVCoordinates<T> pv4) {
496         this(new FieldAbsoluteDate<>(a1.getField(), date),
497              a1, pv1, a2, pv2, a3, pv3, a4, pv4);
498     }
499 
500     /** Linear constructor
501      * <p>Build a PVCoordinates from four other ones and corresponding scale factors.</p>
502      * <p>The PVCoordinates built will be a1 * u1 + a2 * u2 + a3 * u3 + a4 * u4</p>
503      * @param date date of the built coordinates
504      * @param a1 first scale factor
505      * @param pv1 first base (unscaled) PVCoordinates
506      * @param a2 second scale factor
507      * @param pv2 second base (unscaled) PVCoordinates
508      * @param a3 third scale factor
509      * @param pv3 third base (unscaled) PVCoordinates
510      * @param a4 fourth scale factor
511      * @param pv4 fourth base (unscaled) PVCoordinates
512      */
513     public TimeStampedFieldPVCoordinates(final FieldAbsoluteDate<T> date,
514                                          final T a1, final FieldPVCoordinates<T> pv1,
515                                          final T a2, final FieldPVCoordinates<T> pv2,
516                                          final T a3, final FieldPVCoordinates<T> pv3,
517                                          final T a4, final FieldPVCoordinates<T> pv4) {
518         super(new FieldVector3D<>(a1, pv1.getPosition(),     a2, pv2.getPosition(),
519                                   a3, pv3.getPosition(),     a4, pv4.getPosition()),
520               new FieldVector3D<>(a1, pv1.getVelocity(),     a2, pv2.getVelocity(),
521                                   a3, pv3.getVelocity(),     a4, pv4.getVelocity()),
522               new FieldVector3D<>(a1, pv1.getAcceleration(), a2, pv2.getAcceleration(),
523                                   a3, pv3.getAcceleration(), a4, pv4.getAcceleration()));
524         this.date = date;
525     }
526 
527     /** Linear constructor
528      * <p>Build a PVCoordinates from four other ones and corresponding scale factors.</p>
529      * <p>The PVCoordinates built will be a1 * u1 + a2 * u2 + a3 * u3 + a4 * u4</p>
530      * @param date date of the built coordinates
531      * @param a1 first scale factor
532      * @param pv1 first base (unscaled) PVCoordinates
533      * @param a2 second scale factor
534      * @param pv2 second base (unscaled) PVCoordinates
535      * @param a3 third scale factor
536      * @param pv3 third base (unscaled) PVCoordinates
537      * @param a4 fourth scale factor
538      * @param pv4 fourth base (unscaled) PVCoordinates
539      */
540     public TimeStampedFieldPVCoordinates(final AbsoluteDate date,
541                                          final T a1, final PVCoordinates pv1,
542                                          final T a2, final PVCoordinates pv2,
543                                          final T a3, final PVCoordinates pv3,
544                                          final T a4, final PVCoordinates pv4) {
545         this(new FieldAbsoluteDate<>(a1.getField(), date),
546              a1, pv1, a2, pv2, a3, pv3, a4, pv4);
547     }
548 
549     /** Linear constructor
550      * <p>Build a PVCoordinates from four other ones and corresponding scale factors.</p>
551      * <p>The PVCoordinates built will be a1 * u1 + a2 * u2 + a3 * u3 + a4 * u4</p>
552      * @param date date of the built coordinates
553      * @param a1 first scale factor
554      * @param pv1 first base (unscaled) PVCoordinates
555      * @param a2 second scale factor
556      * @param pv2 second base (unscaled) PVCoordinates
557      * @param a3 third scale factor
558      * @param pv3 third base (unscaled) PVCoordinates
559      * @param a4 fourth scale factor
560      * @param pv4 fourth base (unscaled) PVCoordinates
561      */
562     public TimeStampedFieldPVCoordinates(final FieldAbsoluteDate<T> date,
563                                          final T a1, final PVCoordinates pv1,
564                                          final T a2, final PVCoordinates pv2,
565                                          final T a3, final PVCoordinates pv3,
566                                          final T a4, final PVCoordinates pv4) {
567         super(new FieldVector3D<>(a1, pv1.getPosition(),     a2, pv2.getPosition(),
568                                   a3, pv3.getPosition(),     a4, pv4.getPosition()),
569               new FieldVector3D<>(a1, pv1.getVelocity(),     a2, pv2.getVelocity(),
570                                   a3, pv3.getVelocity(),     a4, pv4.getVelocity()),
571               new FieldVector3D<>(a1, pv1.getAcceleration(), a2, pv2.getAcceleration(),
572                                   a3, pv3.getAcceleration(), a4, pv4.getAcceleration()));
573         this.date = date;
574     }
575 
576     /** Builds a TimeStampedFieldPVCoordinates triplet from  a {@link FieldVector3D}&lt;{@link FieldDerivativeStructure}&gt;.
577      * <p>
578      * The vector components must have time as their only derivation parameter and
579      * have consistent derivation orders.
580      * </p>
581      * @param date date of the built coordinates
582      * @param <U> type of the derivative
583      * @param p vector with time-derivatives embedded within the coordinates
584      */
585     public <U extends FieldDerivative<T, U>> TimeStampedFieldPVCoordinates(final FieldAbsoluteDate<T> date,
586                                                                            final FieldVector3D<U> p) {
587         super(p);
588         this.date = date;
589     }
590 
591     /** {@inheritDoc} */
592     @Override
593     public FieldAbsoluteDate<T> getDate() {
594         return date;
595     }
596 
597     /** Get a time-shifted state.
598      * <p>
599      * The state can be slightly shifted to close dates. This shift is based on
600      * a simple linear model. It is <em>not</em> intended as a replacement for
601      * proper orbit propagation (it is not even Keplerian!) but should be sufficient
602      * for either small time shifts or coarse accuracy.
603      * </p>
604      * @param dt time shift in seconds
605      * @return a new state, shifted with respect to the instance (which is immutable)
606      */
607     public TimeStampedFieldPVCoordinates<T> shiftedBy(final double dt) {
608         final FieldPVCoordinates<T> spv = super.shiftedBy(dt);
609         return new TimeStampedFieldPVCoordinates<>(date.shiftedBy(dt),
610                                                    spv.getPosition(), spv.getVelocity(), spv.getAcceleration());
611     }
612 
613     /** Get a time-shifted state.
614      * <p>
615      * The state can be slightly shifted to close dates. This shift is based on
616      * a simple linear model. It is <em>not</em> intended as a replacement for
617      * proper orbit propagation (it is not even Keplerian!) but should be sufficient
618      * for either small time shifts or coarse accuracy.
619      * </p>
620      * @param dt time shift in seconds
621      * @return a new state, shifted with respect to the instance (which is immutable)
622      */
623     public TimeStampedFieldPVCoordinates<T> shiftedBy(final T dt) {
624         final FieldPVCoordinates<T> spv = super.shiftedBy(dt);
625         return new TimeStampedFieldPVCoordinates<>(date.shiftedBy(dt),
626                                                    spv.getPosition(), spv.getVelocity(), spv.getAcceleration());
627     }
628 
629     /** Interpolate position-velocity.
630      * <p>
631      * The interpolated instance is created by polynomial Hermite interpolation
632      * ensuring velocity remains the exact derivative of position.
633      * </p>
634      * <p>
635      * Note that even if first time derivatives (velocities)
636      * from sample can be ignored, the interpolated instance always includes
637      * interpolated derivatives. This feature can be used explicitly to
638      * compute these derivatives when it would be too complex to compute them
639      * from an analytical formula: just compute a few sample points from the
640      * explicit formula and set the derivatives to zero in these sample points,
641      * then use interpolation to add derivatives consistent with the positions.
642      * </p>
643      * @param date interpolation date
644      * @param filter filter for derivatives from the sample to use in interpolation
645      * @param sample sample points on which interpolation should be done
646      * @param <T> the type of the field elements
647      * @return a new position-velocity, interpolated at specified date
648      */
649     public static <T extends CalculusFieldElement<T>>
650         TimeStampedFieldPVCoordinates<T> interpolate(final FieldAbsoluteDate<T> date,
651                                                      final CartesianDerivativesFilter filter,
652                                                      final Collection<TimeStampedFieldPVCoordinates<T>> sample) {
653         return interpolate(date, filter, sample.stream());
654     }
655 
656     /** Interpolate position-velocity.
657      * <p>
658      * The interpolated instance is created by polynomial Hermite interpolation
659      * ensuring velocity remains the exact derivative of position.
660      * </p>
661      * <p>
662      * Note that even if first time derivatives (velocities)
663      * from sample can be ignored, the interpolated instance always includes
664      * interpolated derivatives. This feature can be used explicitly to
665      * compute these derivatives when it would be too complex to compute them
666      * from an analytical formula: just compute a few sample points from the
667      * explicit formula and set the derivatives to zero in these sample points,
668      * then use interpolation to add derivatives consistent with the positions.
669      * </p>
670      * @param date interpolation date
671      * @param filter filter for derivatives from the sample to use in interpolation
672      * @param sample sample points on which interpolation should be done
673      * @param <T> the type of the field elements
674      * @return a new position-velocity, interpolated at specified date
675      */
676     public static <T extends CalculusFieldElement<T>>
677         TimeStampedFieldPVCoordinates<T> interpolate(final FieldAbsoluteDate<T> date,
678                                                      final CartesianDerivativesFilter filter,
679                                                      final Stream<TimeStampedFieldPVCoordinates<T>> sample) {
680 
681         // set up an interpolator taking derivatives into account
682         final FieldHermiteInterpolator<T> interpolator = new FieldHermiteInterpolator<>();
683 
684         // add sample points
685         switch (filter) {
686             case USE_P :
687                 // populate sample with position data, ignoring velocity
688                 sample.forEach(pv -> {
689                     final FieldVector3D<T> position = pv.getPosition();
690                     interpolator.addSamplePoint(pv.getDate().durationFrom(date),
691                                                 position.toArray());
692                 });
693                 break;
694             case USE_PV :
695                 // populate sample with position and velocity data
696                 sample.forEach(pv -> {
697                     final FieldVector3D<T> position = pv.getPosition();
698                     final FieldVector3D<T> velocity = pv.getVelocity();
699                     interpolator.addSamplePoint(pv.getDate().durationFrom(date),
700                                                 position.toArray(), velocity.toArray());
701                 });
702                 break;
703             case USE_PVA :
704                 // populate sample with position, velocity and acceleration data
705                 sample.forEach(pv -> {
706                     final FieldVector3D<T> position     = pv.getPosition();
707                     final FieldVector3D<T> velocity     = pv.getVelocity();
708                     final FieldVector3D<T> acceleration = pv.getAcceleration();
709                     interpolator.addSamplePoint(pv.getDate().durationFrom(date),
710                                                 position.toArray(), velocity.toArray(), acceleration.toArray());
711                 });
712                 break;
713             default :
714                 // this should never happen
715                 throw new OrekitInternalError(null);
716         }
717 
718         // interpolate
719         final T[][] p = interpolator.derivatives(date.getField().getZero(), 2);
720 
721         // build a new interpolated instance
722 
723         return new TimeStampedFieldPVCoordinates<>(date,
724                                                    new FieldVector3D<>(p[0]),
725                                                    new FieldVector3D<>(p[1]),
726                                                    new FieldVector3D<>(p[2]));
727 
728     }
729 
730     /** Convert to a constant position-velocity.
731      * @return a constant position-velocity
732      * @since 9.0
733      */
734     public TimeStampedPVCoordinates toTimeStampedPVCoordinates() {
735         return new TimeStampedPVCoordinates(date.toAbsoluteDate(),
736                                             getPosition().toVector3D(),
737                                             getVelocity().toVector3D(),
738                                             getAcceleration().toVector3D());
739     }
740 
741     /** Return a string representation of this date, position, velocity, and acceleration.
742      *
743      * <p>This method uses the {@link DataContext#getDefault() default data context}.
744      *
745      * @return string representation of this.
746      */
747     @Override
748     @DefaultDataContext
749     public String toString() {
750         return toTimeStampedPVCoordinates().toString();
751     }
752 
753     /**
754      * Return a string representation of this date, position, velocity, and acceleration.
755      *
756      * @param utc time scale used to print the date.
757      * @return string representation of this.
758      */
759     public String toString(final TimeScale utc) {
760         return toTimeStampedPVCoordinates().toString(utc);
761     }
762 
763 }