1   /* Copyright 2022-2025 Luc Maisonobe
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.attitudes;
18  
19  import org.hipparchus.CalculusFieldElement;
20  import org.hipparchus.analysis.differentiation.FieldUnivariateDerivative2;
21  import org.hipparchus.analysis.differentiation.UnivariateDerivative2;
22  import org.hipparchus.analysis.differentiation.UnivariateDerivative2Field;
23  import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
24  import org.hipparchus.geometry.euclidean.threed.Vector3D;
25  import org.orekit.bodies.FieldGeodeticPoint;
26  import org.orekit.bodies.GeodeticPoint;
27  import org.orekit.bodies.OneAxisEllipsoid;
28  import org.orekit.frames.FieldStaticTransform;
29  import org.orekit.frames.Frame;
30  import org.orekit.frames.StaticTransform;
31  import org.orekit.time.AbsoluteDate;
32  import org.orekit.time.FieldAbsoluteDate;
33  import org.orekit.utils.ExtendedPositionProvider;
34  import org.orekit.utils.PVCoordinates;
35  import org.orekit.utils.TimeStampedFieldPVCoordinates;
36  import org.orekit.utils.TimeStampedPVCoordinates;
37  
38  /**
39   * Predefined targets for {@link AlignedAndConstrained}.
40   * @author Luc Maisonobe
41   * @since 12.2
42   */
43  public enum PredefinedTarget implements TargetProvider
44  {
45  
46      /** Sun direction. */
47      SUN {
48  
49          /** {@inheritDoc} */
50          @Override
51          public FieldVector3D<UnivariateDerivative2> getDerivative2TargetDirection(final ExtendedPositionProvider sun,
52                                                                                    final OneAxisEllipsoid earth,
53                                                                                    final TimeStampedPVCoordinates pv,
54                                                                                    final Frame frame) {
55              return new PVCoordinates(pv, sun.getPVCoordinates(pv.getDate(), frame)).
56                     toUnivariateDerivative2Vector().
57                     normalize();
58          }
59  
60          /** {@inheritDoc} */
61          @Override
62          public Vector3D getTargetDirection(final ExtendedPositionProvider sun, final OneAxisEllipsoid earth,
63                                             final TimeStampedPVCoordinates pv, final Frame frame) {
64              return sun.getPosition(pv.getDate(), frame).subtract(pv.getPosition()).normalize();
65          }
66  
67          /** {@inheritDoc} */
68          @Override
69          public <T extends CalculusFieldElement<T>> FieldVector3D<T> getTargetDirection(final ExtendedPositionProvider sun,
70                                                                                         final OneAxisEllipsoid earth,
71                                                                                         final TimeStampedFieldPVCoordinates<T> pv,
72                                                                                         final Frame frame) {
73              return sun.getPosition(pv.getDate(), frame).subtract(pv.getPosition()).normalize();
74          }
75      },
76  
77      /** Earth direction (assumes the frame is Earth centered). */
78      EARTH {
79  
80          /** {@inheritDoc} */
81          @Override
82          public FieldVector3D<UnivariateDerivative2> getDerivative2TargetDirection(final ExtendedPositionProvider sun,
83                                                                                    final OneAxisEllipsoid earth,
84                                                                                    final TimeStampedPVCoordinates pv,
85                                                                                    final Frame frame) {
86              return pv.toUnivariateDerivative2Vector().negate().normalize();
87          }
88  
89          /** {@inheritDoc} */
90          @Override
91          public Vector3D getTargetDirection(final ExtendedPositionProvider sun, final OneAxisEllipsoid earth,
92                                             final TimeStampedPVCoordinates pv, final Frame frame) {
93              return pv.getPosition().negate().normalize();
94          }
95  
96          /** {@inheritDoc} */
97          @Override
98          public <T extends CalculusFieldElement<T>> FieldVector3D<FieldUnivariateDerivative2<T>> getDerivative2TargetDirection(final ExtendedPositionProvider sun,
99                                                                                                                                final OneAxisEllipsoid earth,
100                                                                                                                               final TimeStampedFieldPVCoordinates<T> pv,
101                                                                                                                               final Frame frame) {
102             return pv.toUnivariateDerivative2Vector().negate().normalize();
103         }
104 
105         /** {@inheritDoc} */
106         @Override
107         public <T extends CalculusFieldElement<T>> FieldVector3D<T> getTargetDirection(final ExtendedPositionProvider sun,
108                                                                                        final OneAxisEllipsoid earth,
109                                                                                        final TimeStampedFieldPVCoordinates<T> pv,
110                                                                                        final Frame frame) {
111             return pv.getPosition().negate().normalize();
112         }
113     },
114 
115     /** Nadir. */
116     NADIR {
117 
118         /** {@inheritDoc} */
119         @Override
120         public FieldVector3D<UnivariateDerivative2> getDerivative2TargetDirection(final ExtendedPositionProvider sun,
121                                                                                   final OneAxisEllipsoid earth,
122                                                                                   final TimeStampedPVCoordinates pv,
123                                                                                   final Frame frame) {
124             final FieldStaticTransform<UnivariateDerivative2> inert2Earth = inert2Earth(earth, pv.getDate(), frame);
125             final FieldGeodeticPoint<UnivariateDerivative2> gp = toGeodeticPoint(earth, pv, inert2Earth);
126             return inert2Earth.getStaticInverse().transformVector(gp.getNadir());
127         }
128 
129         /** {@inheritDoc} */
130         @Override
131         public Vector3D getTargetDirection(final ExtendedPositionProvider sun, final OneAxisEllipsoid earth,
132                                            final TimeStampedPVCoordinates pv, final Frame frame) {
133             final StaticTransform inert2Earth = frame.getStaticTransformTo(earth.getBodyFrame(), pv.getDate());
134             final GeodeticPoint geodeticPoint = earth.transform(inert2Earth.transformPosition(pv.getPosition()),
135                     earth.getBodyFrame(), pv.getDate());
136             return inert2Earth.getStaticInverse().transformVector(geodeticPoint.getNadir());
137         }
138 
139         /** {@inheritDoc} */
140         @Override
141         public <T extends CalculusFieldElement<T>> FieldVector3D<T> getTargetDirection(final ExtendedPositionProvider sun,
142                                                                                        final OneAxisEllipsoid earth,
143                                                                                        final TimeStampedFieldPVCoordinates<T> pv,
144                                                                                        final Frame frame) {
145             final FieldStaticTransform<T> inert2Earth = frame.getStaticTransformTo(earth.getBodyFrame(), pv.getDate());
146             final FieldGeodeticPoint<T> geodeticPoint = earth.transform(inert2Earth.transformPosition(pv.getPosition()),
147                     earth.getBodyFrame(), pv.getDate());
148             return inert2Earth.getStaticInverse().transformVector(geodeticPoint.getNadir());
149         }
150     },
151 
152     /** North direction. */
153     NORTH {
154 
155         /** {@inheritDoc} */
156         @Override
157         public FieldVector3D<UnivariateDerivative2> getDerivative2TargetDirection(final ExtendedPositionProvider sun,
158                                                                                   final OneAxisEllipsoid earth,
159                                                                                   final TimeStampedPVCoordinates pv,
160                                                                                   final Frame frame) {
161             final FieldStaticTransform<UnivariateDerivative2> inert2Earth = inert2Earth(earth, pv.getDate(), frame);
162             final FieldGeodeticPoint<UnivariateDerivative2> gp = toGeodeticPoint(earth, pv, inert2Earth);
163             return inert2Earth.getStaticInverse().transformVector(gp.getNorth());
164         }
165 
166         /** {@inheritDoc} */
167         @Override
168         public Vector3D getTargetDirection(final ExtendedPositionProvider sun, final OneAxisEllipsoid earth,
169                                            final TimeStampedPVCoordinates pv, final Frame frame) {
170             final StaticTransform inert2Earth = frame.getStaticTransformTo(earth.getBodyFrame(), pv.getDate());
171             final GeodeticPoint geodeticPoint = earth.transform(inert2Earth.transformPosition(pv.getPosition()),
172                     earth.getBodyFrame(), pv.getDate());
173             return inert2Earth.getStaticInverse().transformVector(geodeticPoint.getNorth());
174         }
175 
176         /** {@inheritDoc} */
177         @Override
178         public <T extends CalculusFieldElement<T>> FieldVector3D<T> getTargetDirection(final ExtendedPositionProvider sun,
179                                                                                        final OneAxisEllipsoid earth,
180                                                                                        final TimeStampedFieldPVCoordinates<T> pv,
181                                                                                        final Frame frame) {
182             final FieldStaticTransform<T> inert2Earth = frame.getStaticTransformTo(earth.getBodyFrame(), pv.getDate());
183             final FieldGeodeticPoint<T> geodeticPoint = earth.transform(inert2Earth.transformPosition(pv.getPosition()),
184                     earth.getBodyFrame(), pv.getDate());
185             return inert2Earth.getStaticInverse().transformVector(geodeticPoint.getNorth());
186         }
187     },
188 
189     /** East direction. */
190     EAST {
191 
192         /** {@inheritDoc} */
193         @Override
194         public FieldVector3D<UnivariateDerivative2> getDerivative2TargetDirection(final ExtendedPositionProvider sun,
195                                                                                   final OneAxisEllipsoid earth,
196                                                                                   final TimeStampedPVCoordinates pv,
197                                                                                   final Frame frame) {
198             final FieldStaticTransform<UnivariateDerivative2> inert2Earth = inert2Earth(earth, pv.getDate(), frame);
199             final FieldGeodeticPoint<UnivariateDerivative2> gp = toGeodeticPoint(earth, pv, inert2Earth);
200             return inert2Earth.getStaticInverse().transformVector(gp.getEast());
201         }
202 
203         /** {@inheritDoc} */
204         @Override
205         public Vector3D getTargetDirection(final ExtendedPositionProvider sun, final OneAxisEllipsoid earth,
206                                            final TimeStampedPVCoordinates pv, final Frame frame) {
207             final StaticTransform inert2Earth = frame.getStaticTransformTo(earth.getBodyFrame(), pv.getDate());
208             final GeodeticPoint geodeticPoint = earth.transform(inert2Earth.transformPosition(pv.getPosition()),
209                     earth.getBodyFrame(), pv.getDate());
210             return inert2Earth.getStaticInverse().transformVector(geodeticPoint.getEast());
211         }
212 
213         /** {@inheritDoc} */
214         @Override
215         public <T extends CalculusFieldElement<T>> FieldVector3D<T> getTargetDirection(final ExtendedPositionProvider sun,
216                                                                                        final OneAxisEllipsoid earth,
217                                                                                        final TimeStampedFieldPVCoordinates<T> pv,
218                                                                                        final Frame frame) {
219             final FieldStaticTransform<T> inert2Earth = frame.getStaticTransformTo(earth.getBodyFrame(), pv.getDate());
220             final FieldGeodeticPoint<T> geodeticPoint = earth.transform(inert2Earth.transformPosition(pv.getPosition()),
221                     earth.getBodyFrame(), pv.getDate());
222             return inert2Earth.getStaticInverse().transformVector(geodeticPoint.getEast());
223         }
224     },
225 
226     /** Satellite velocity. */
227     VELOCITY {
228 
229         /** {@inheritDoc} */
230         @Override
231         public FieldVector3D<UnivariateDerivative2> getDerivative2TargetDirection(final ExtendedPositionProvider sun,
232                                                                                   final OneAxisEllipsoid earth,
233                                                                                   final TimeStampedPVCoordinates pv,
234                                                                                   final Frame frame) {
235             return pv.toUnivariateDerivative2PV().getVelocity().normalize();
236         }
237 
238         /** {@inheritDoc} */
239         @Override
240         public Vector3D getTargetDirection(final ExtendedPositionProvider sun, final OneAxisEllipsoid earth,
241                                                 final TimeStampedPVCoordinates pv, final Frame frame) {
242             return pv.getVelocity().normalize();
243         }
244 
245         /** {@inheritDoc} */
246         @Override
247         public <T extends CalculusFieldElement<T>> FieldVector3D<FieldUnivariateDerivative2<T>> getDerivative2TargetDirection(final ExtendedPositionProvider sun,
248                                                                                                                               final OneAxisEllipsoid earth,
249                                                                                                                               final TimeStampedFieldPVCoordinates<T> pv,
250                                                                                                                               final Frame frame) {
251             return pv.toUnivariateDerivative2PV().getVelocity().normalize();
252         }
253 
254         /** {@inheritDoc} */
255         @Override
256         public <T extends CalculusFieldElement<T>> FieldVector3D<T> getTargetDirection(final ExtendedPositionProvider sun,
257                                                                                        final OneAxisEllipsoid earth,
258                                                                                        final TimeStampedFieldPVCoordinates<T> pv,
259                                                                                        final Frame frame) {
260             return pv.getVelocity().normalize();
261         }
262     },
263 
264     /** Satellite orbital momentum. */
265     MOMENTUM {
266 
267         /** {@inheritDoc} */
268         @Override
269         public FieldVector3D<UnivariateDerivative2> getDerivative2TargetDirection(final ExtendedPositionProvider sun,
270                                                                                   final OneAxisEllipsoid earth,
271                                                                                   final TimeStampedPVCoordinates pv,
272                                                                                   final Frame frame) {
273             return pv.toUnivariateDerivative2PV().getMomentum().normalize();
274         }
275 
276         /** {@inheritDoc} */
277         @Override
278         public Vector3D getTargetDirection(final ExtendedPositionProvider sun, final OneAxisEllipsoid earth,
279                                            final TimeStampedPVCoordinates pv, final Frame frame) {
280             return pv.getMomentum().normalize();
281         }
282 
283         /** {@inheritDoc} */
284         @Override
285         public <T extends CalculusFieldElement<T>> FieldVector3D<FieldUnivariateDerivative2<T>> getDerivative2TargetDirection(final ExtendedPositionProvider sun,
286                                                                                                                               final OneAxisEllipsoid earth,
287                                                                                                                               final TimeStampedFieldPVCoordinates<T> pv,
288                                                                                                                               final Frame frame) {
289             return pv.toUnivariateDerivative2PV().getMomentum().normalize();
290         }
291 
292         /** {@inheritDoc} */
293         @Override
294         public <T extends CalculusFieldElement<T>> FieldVector3D<T> getTargetDirection(final ExtendedPositionProvider sun,
295                                                                                        final OneAxisEllipsoid earth,
296                                                                                        final TimeStampedFieldPVCoordinates<T> pv,
297                                                                                        final Frame frame) {
298             return pv.getMomentum().normalize();
299         }
300     };
301 
302     /** Get transform from inertial frame to Earth frame.
303      * @param earth Earth model
304      * @param date  date
305      * @param frame inertial frame
306      * @return geodetic point with derivatives
307      */
308     private static FieldStaticTransform<UnivariateDerivative2> inert2Earth(final OneAxisEllipsoid earth,
309                                                                      final AbsoluteDate date,
310                                                                      final Frame frame) {
311         final FieldAbsoluteDate<UnivariateDerivative2> dateU2 =
312             new FieldAbsoluteDate<>(UnivariateDerivative2Field.getInstance(), date).
313             shiftedBy(new UnivariateDerivative2(0.0, 1.0, 0.0));
314         return frame.getStaticTransformTo(earth.getBodyFrame(), dateU2);
315     }
316 
317     /** Convert to geodetic point with derivatives.
318      * @param earth       Earth model
319      * @param pv          spacecraft position and velocity
320      * @param inert2Earth transform from inertial frame to Earth frame
321      * @return geodetic point with derivatives
322      */
323     private static FieldGeodeticPoint<UnivariateDerivative2> toGeodeticPoint(final OneAxisEllipsoid earth,
324                                                                              final TimeStampedPVCoordinates pv,
325                                                                              final FieldStaticTransform<UnivariateDerivative2> inert2Earth) {
326         return earth.transform(inert2Earth.transformPosition(pv.toUnivariateDerivative2Vector()),
327                                earth.getBodyFrame(), inert2Earth.getFieldDate());
328     }
329 }