1   /* Copyright 2022-2025 Romain Serra
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  
18  package org.orekit.utils;
19  
20  import org.hipparchus.CalculusFieldElement;
21  import org.hipparchus.Field;
22  import org.hipparchus.analysis.differentiation.FieldUnivariateDerivative1;
23  import org.hipparchus.analysis.differentiation.FieldUnivariateDerivative1Field;
24  import org.hipparchus.analysis.differentiation.FieldUnivariateDerivative2;
25  import org.hipparchus.analysis.differentiation.UnivariateDerivative1;
26  import org.hipparchus.analysis.differentiation.UnivariateDerivative1Field;
27  import org.hipparchus.analysis.differentiation.UnivariateDerivative2;
28  import org.hipparchus.analysis.differentiation.UnivariateDerivative2Field;
29  import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
30  import org.hipparchus.geometry.euclidean.threed.Vector3D;
31  import org.orekit.frames.Frame;
32  import org.orekit.time.AbsoluteDate;
33  import org.orekit.time.FieldAbsoluteDate;
34  
35  /**
36   * Interface for position providers (including for Field).
37   * Emulates position (and derivatives) vector as a function of time.
38   * @author Romain Serra
39   * @since 12.1
40   */
41  public interface ExtendedPositionProvider extends PVCoordinatesProvider {
42  
43      /** Get the position in the selected frame.
44       * @param date current date
45       * @param frame the frame where to define the position
46       * @param <T> field type
47       * @return position
48       */
49      <T extends CalculusFieldElement<T>> FieldVector3D<T> getPosition(FieldAbsoluteDate<T> date, Frame frame);
50  
51      /** {@inheritDoc} */
52      @Override
53      default Vector3D getVelocity(final AbsoluteDate date, final Frame frame) {
54          final UnivariateDerivative1Field ud1Field = UnivariateDerivative1Field.getInstance();
55          final UnivariateDerivative1 ud1Shift = new UnivariateDerivative1(0., 1.);
56          final FieldAbsoluteDate<UnivariateDerivative1> fieldDate = new FieldAbsoluteDate<>(ud1Field, date).shiftedBy(ud1Shift);
57          final FieldVector3D<UnivariateDerivative1> ud1Position = getPosition(fieldDate, frame);
58          return new Vector3D(ud1Position.getX().getFirstDerivative(), ud1Position.getY().getFirstDerivative(),
59                  ud1Position.getZ().getFirstDerivative());
60      }
61  
62      /** {@inheritDoc} */
63      @Override
64      default TimeStampedPVCoordinates getPVCoordinates(final AbsoluteDate date, final Frame frame) {
65          final UnivariateDerivative2Field ud2Field = UnivariateDerivative2Field.getInstance();
66          final UnivariateDerivative2 ud2Shift = new UnivariateDerivative2(0., 1., 0.);
67          final FieldAbsoluteDate<UnivariateDerivative2> fieldDate = new FieldAbsoluteDate<>(ud2Field, date).shiftedBy(ud2Shift);
68          final FieldVector3D<UnivariateDerivative2> ud2Position = getPosition(fieldDate, frame);
69          final Vector3D position = ud2Position.toVector3D();
70          final Vector3D velocity = new Vector3D(ud2Position.getX().getFirstDerivative(), ud2Position.getY().getFirstDerivative(),
71              ud2Position.getZ().getFirstDerivative());
72          final Vector3D acceleration = new Vector3D(ud2Position.getX().getSecondDerivative(), ud2Position.getY().getSecondDerivative(),
73                  ud2Position.getZ().getSecondDerivative());
74          return new TimeStampedPVCoordinates(date, new PVCoordinates(position, velocity, acceleration));
75      }
76  
77      /** Get the velocity vector in the selected frame.
78       * @param date current date
79       * @param frame the frame where to define the velocity
80       * @param <T> field type
81       * @return velocity
82       */
83      default <T extends CalculusFieldElement<T>> FieldVector3D<T> getVelocity(final FieldAbsoluteDate<T> date,
84                                                                               final Frame frame) {
85          final Field<T> field = date.getField();
86          final AbsoluteDate absoluteDate = date.toAbsoluteDate();
87          final FieldAbsoluteDate<FieldUnivariateDerivative1<T>> fud1Date = new FieldAbsoluteDate<>(FieldUnivariateDerivative1Field.getUnivariateDerivative1Field(field),
88                  absoluteDate);
89          final FieldUnivariateDerivative1<T> shift = new FieldUnivariateDerivative1<>(field.getZero(), field.getOne())
90                  .add(date.durationFrom(absoluteDate));
91          final FieldVector3D<FieldUnivariateDerivative1<T>> fud1Position = getPosition(fud1Date.shiftedBy(shift), frame);
92          return new FieldVector3D<>(fud1Position.getX().getFirstDerivative(), fud1Position.getY().getFirstDerivative(),
93                  fud1Position.getZ().getFirstDerivative());
94      }
95  
96      /** Get the position-velocity-acceleration in the selected frame.
97       * @param date current date
98       * @param frame the frame where to define the position
99       * @param <T> field type
100      * @return position-velocity-acceleration vector
101      */
102     default <T extends CalculusFieldElement<T>> TimeStampedFieldPVCoordinates<T> getPVCoordinates(final FieldAbsoluteDate<T> date,
103                                                                                                   final Frame frame) {
104         final FieldAbsoluteDate<FieldUnivariateDerivative2<T>> fud2Date = date.toFUD2Field();
105         final FieldVector3D<FieldUnivariateDerivative2<T>> fud2Position = getPosition(fud2Date, frame);
106         final FieldVector3D<T> position = new FieldVector3D<>(fud2Position.getX().getValue(), fud2Position.getY().getValue(),
107             fud2Position.getZ().getValue());
108         final FieldVector3D<T> velocity = new FieldVector3D<>(fud2Position.getX().getFirstDerivative(), fud2Position.getY().getFirstDerivative(),
109             fud2Position.getZ().getFirstDerivative());
110         final FieldVector3D<T> acceleration = new FieldVector3D<>(fud2Position.getX().getSecondDerivative(), fud2Position.getY().getSecondDerivative(),
111             fud2Position.getZ().getSecondDerivative());
112         return new TimeStampedFieldPVCoordinates<>(date, position, velocity, acceleration);
113     }
114 
115     /** Convert to a {@link FieldPVCoordinatesProvider} with a specific type.
116      * @param <T> the type of the field elements
117      * @param field field for the argument and value
118      * @return converted function
119      */
120     default <T extends CalculusFieldElement<T>> FieldPVCoordinatesProvider<T> toFieldPVCoordinatesProvider(final Field<T> field) {
121         return new FieldPVCoordinatesProvider<T>() {
122 
123             @Override
124             public FieldVector3D<T> getPosition(final FieldAbsoluteDate<T> date, final Frame frame) {
125                 return ExtendedPositionProvider.this.getPosition(date, frame);
126             }
127 
128             @Override
129             public TimeStampedFieldPVCoordinates<T> getPVCoordinates(final FieldAbsoluteDate<T> date,
130                                                                      final Frame frame) {
131                 return ExtendedPositionProvider.this.getPVCoordinates(date, frame);
132             }
133         };
134     }
135 
136 }