1 /* Copyright 2002-2024 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.frames;
18
19 import org.hipparchus.CalculusFieldElement;
20 import org.hipparchus.Field;
21 import org.hipparchus.geometry.euclidean.threed.FieldRotation;
22 import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
23 import org.hipparchus.geometry.euclidean.threed.Rotation;
24 import org.hipparchus.geometry.euclidean.threed.RotationConvention;
25 import org.hipparchus.geometry.euclidean.threed.Vector3D;
26 import org.orekit.time.AbsoluteDate;
27 import org.orekit.time.FieldAbsoluteDate;
28 import org.orekit.utils.AngularCoordinates;
29 import org.orekit.utils.FieldPVCoordinates;
30 import org.orekit.utils.PVCoordinates;
31
32 /**
33 * Interface for local orbital frame.
34 *
35 * @author Vincent Cucchietti
36 */
37 public interface LOF {
38
39 /**
40 * Get the rotation from input to output {@link LOF local orbital frame}.
41 * <p>
42 * This rotation does not include any time derivatives. If first time derivatives (i.e. rotation rate) is needed as well,
43 * the full {@link #transformFromLOFInToLOFOut(LOF, LOF, FieldAbsoluteDate, FieldPVCoordinates)} method must be called and
44 * the complete rotation transform must be extracted from it.
45 *
46 * @param field field to which the elements belong
47 * @param in input commonly used local orbital frame
48 * @param out output commonly used local orbital frame
49 * @param date date of the rotation
50 * @param pv position-velocity of the spacecraft in some inertial frame
51 * @param <T> type of the field elements
52 *
53 * @return rotation from input to output local orbital frame
54 *
55 * @since 11.3
56 */
57 static <T extends CalculusFieldElement<T>> FieldRotation<T> rotationFromLOFInToLOFOut(final Field<T> field,
58 final LOF in, final LOF out,
59 final FieldAbsoluteDate<T> date,
60 final FieldPVCoordinates<T> pv) {
61 return out.rotationFromLOF(field, in, date, pv);
62 }
63
64 /**
65 * Get the transform from input to output {@link LOF local orbital frame}.
66 *
67 * @param in input commonly used local orbital frame
68 * @param out output commonly used local orbital frame
69 * @param date date of the transform
70 * @param pv position-velocity of the spacecraft in some inertial frame
71 * @param <T> type of the field elements
72 *
73 * @return rotation from input to output local orbital frame.
74 *
75 * @since 11.3
76 */
77 static <T extends CalculusFieldElement<T>> FieldTransform<T> transformFromLOFInToLOFOut(final LOF in, final LOF out,
78 final FieldAbsoluteDate<T> date,
79 final FieldPVCoordinates<T> pv) {
80 return out.transformFromLOF(in, date, pv);
81 }
82
83 /**
84 * Get the rotation from input to output {@link LOF local orbital frame}.
85 * <p>
86 * This rotation does not include any time derivatives. If first time derivatives (i.e. rotation rate) is needed as well,
87 * the full {@link #transformFromLOFInToLOFOut(LOF, LOF, AbsoluteDate, PVCoordinates)} method must be called and
88 * the complete rotation transform must be extracted from it.
89 *
90 * @param in input commonly used local orbital frame
91 * @param out output commonly used local orbital frame
92 * @param date date of the rotation
93 * @param pv position-velocity of the spacecraft in some inertial frame
94 *
95 * @return rotation from input to output local orbital frame.
96 *
97 * @since 11.3
98 */
99 static Rotation rotationFromLOFInToLOFOut(final LOF in, final LOF out, final AbsoluteDate date, final PVCoordinates pv) {
100 return out.rotationFromLOF(in, date, pv);
101 }
102
103 /**
104 * Get the transform from input to output {@link LOF local orbital frame}.
105 *
106 * @param in input commonly used local orbital frame
107 * @param out output commonly used local orbital frame
108 * @param date date of the transform
109 * @param pv position-velocity of the spacecraft in some inertial frame
110 *
111 * @return rotation from input to output local orbital frame
112 *
113 * @since 11.3
114 */
115 static Transform transformFromLOFInToLOFOut(final LOF in, final LOF out, final AbsoluteDate date,
116 final PVCoordinates pv) {
117 return out.transformFromLOF(in, date, pv);
118 }
119
120 /**
121 * Get the rotation from input {@link LOF local orbital frame} to the instance.
122 * <p>
123 * This rotation does not include any time derivatives. If first time derivatives (i.e. rotation rate) is needed as well,
124 * the full {@link #transformFromLOF(LOF, FieldAbsoluteDate, FieldPVCoordinates)} method must be called and
125 * the complete rotation transform must be extracted from it.
126 *
127 * @param field field to which the elements belong
128 * @param fromLOF input local orbital frame
129 * @param date date of the rotation
130 * @param pv position-velocity of the spacecraft in some inertial frame
131 * @param <T> type of the field elements
132 *
133 * @return rotation from input local orbital frame to the instance
134 *
135 * @since 11.3
136 */
137 default <T extends CalculusFieldElement<T>> FieldRotation<T> rotationFromLOF(final Field<T> field,
138 final LOF fromLOF,
139 final FieldAbsoluteDate<T> date,
140 final FieldPVCoordinates<T> pv) {
141
142 // First compute the rotation from the input LOF to the pivot inertial
143 final FieldRotation<T> fromLOFToInertial = fromLOF.rotationFromInertial(field, date, pv).revert();
144
145 // Then compute the rotation from the pivot inertial to the output LOF
146 final FieldRotation<T> inertialToThis = this.rotationFromInertial(field, date, pv);
147
148 // Output composed rotation
149 return fromLOFToInertial.compose(inertialToThis, RotationConvention.FRAME_TRANSFORM);
150 }
151
152 /**
153 * Get the rotation from input {@link LOF commonly used local orbital frame} to the instance.
154 *
155 * @param fromLOF input local orbital frame
156 * @param date date of the transform
157 * @param pv position-velocity of the spacecraft in some inertial frame
158 * @param <T> type of the field elements
159 *
160 * @return rotation from input local orbital frame to the instance
161 *
162 * @since 11.3
163 */
164 default <T extends CalculusFieldElement<T>> FieldTransform<T> transformFromLOF(final LOF fromLOF,
165 final FieldAbsoluteDate<T> date,
166 final FieldPVCoordinates<T> pv) {
167
168 // Get transform from input local orbital frame to inertial
169 final FieldTransform<T> fromLOFToInertial = fromLOF.transformFromInertial(date, pv).getInverse();
170
171 // Get transform from inertial to output local orbital frame
172 final FieldTransform<T> inertialToLOFOut = this.transformFromInertial(date, pv);
173
174 // Output composition of both transforms
175 return new FieldTransform<>(date, fromLOFToInertial, inertialToLOFOut);
176 }
177
178 /**
179 * Get the transform from an inertial frame defining position-velocity and the local orbital frame.
180 *
181 * @param date current date
182 * @param pv position-velocity of the spacecraft in some inertial frame
183 * @param <T> type of the fields elements
184 *
185 * @return transform from the frame where position-velocity are defined to local orbital frame
186 *
187 * @since 9.0
188 */
189 default <T extends CalculusFieldElement<T>> FieldTransform<T> transformFromInertial(final FieldAbsoluteDate<T> date,
190 final FieldPVCoordinates<T> pv) {
191 if (isQuasiInertial()) {
192 final Field<T> field = date.getField();
193 return new FieldTransform<>(date, pv.getPosition().negate(), rotationFromInertial(field, date, pv));
194 }
195
196 // compute the translation part of the transform
197 final FieldTransform<T> translation = new FieldTransform<>(date, pv.negate());
198
199 // compute the rotation part of the transform
200 final FieldRotation<T> r = rotationFromInertial(date.getField(), date, pv);
201 final FieldVector3D<T> p = pv.getPosition();
202 final FieldVector3D<T> momentum = pv.getMomentum();
203 final FieldTransform<T> rotation = new FieldTransform<>(date, r,
204 new FieldVector3D<>(p.getNormSq().reciprocal(),
205 r.applyTo(momentum)));
206
207 return new FieldTransform<>(date, translation, rotation);
208 }
209
210 /**
211 * Get the rotation from inertial frame to local orbital frame.
212 * <p>
213 * This rotation does not include any time derivatives. If first time derivatives (i.e. rotation rate) is needed as well,
214 * the full {@link #transformFromInertial(FieldAbsoluteDate, FieldPVCoordinates)} method must be
215 * called and the complete rotation transform must be extracted from it.
216 * </p>
217 *
218 * @param field field to which the elements belong
219 * @param date date of the rotation
220 * @param pv position-velocity of the spacecraft in some inertial frame
221 * @param <T> type of the field elements
222 *
223 * @return rotation from inertial frame to local orbital frame
224 *
225 * @since 9.0
226 */
227 <T extends CalculusFieldElement<T>> FieldRotation<T> rotationFromInertial(Field<T> field, FieldAbsoluteDate<T> date,
228 FieldPVCoordinates<T> pv);
229
230 /**
231 * Get the rotation from input {@link LOF local orbital frame} to the instance.
232 * <p>
233 * This rotation does not include any time derivatives. If first time derivatives (i.e. rotation rate) is needed as well,
234 * the full {@link #transformFromLOF(LOF, AbsoluteDate, PVCoordinates)} method must be called and
235 * the complete rotation transform must be extracted from it.
236 *
237 * @param fromLOF input local orbital frame
238 * @param date date of the rotation
239 * @param pv position-velocity of the spacecraft in some inertial frame
240 *
241 * @return rotation from input local orbital frame to the instance
242 *
243 * @since 11.3
244 */
245 default Rotation rotationFromLOF(final LOF fromLOF, final AbsoluteDate date, final PVCoordinates pv) {
246
247 // First compute the rotation from the input LOF to the pivot inertial
248 final Rotation fromLOFToInertial = fromLOF.rotationFromInertial(date, pv).revert();
249
250 // Then compute the rotation from the pivot inertial to the output LOF
251 final Rotation inertialToThis = this.rotationFromInertial(date, pv);
252
253 // Output composed rotation
254 return fromLOFToInertial.compose(inertialToThis, RotationConvention.FRAME_TRANSFORM);
255 }
256
257 /**
258 * Get the rotation from input {@link LOF local orbital frame} to the instance.
259 *
260 * @param fromLOF input local orbital frame
261 * @param date date of the transform
262 * @param pv position-velocity of the spacecraft in some inertial frame
263 *
264 * @return rotation from input local orbital frame to the instance
265 *
266 * @since 11.3
267 */
268 default Transform transformFromLOF(final LOF fromLOF, final AbsoluteDate date, final PVCoordinates pv) {
269
270 // First compute the rotation from the input LOF to the pivot inertial
271 final Transform fromLOFToInertial = fromLOF.transformFromInertial(date, pv).getInverse();
272
273 // Then compute the rotation from the pivot inertial to the output LOF
274 final Transform inertialToThis = this.transformFromInertial(date, pv);
275
276 // Output composed rotation
277 return new Transform(date, fromLOFToInertial, inertialToThis);
278 }
279
280 /**
281 * Get the transform from an inertial frame defining position-velocity and the local orbital frame.
282 *
283 * @param date current date
284 * @param pv position-velocity of the spacecraft in some inertial frame
285 *
286 * @return transform from the frame where position-velocity are defined to local orbital frame
287 */
288 default Transform transformFromInertial(final AbsoluteDate date, final PVCoordinates pv) {
289 if (isQuasiInertial()) {
290 return new Transform(date, pv.getPosition().negate(), rotationFromInertial(date, pv));
291 }
292
293 // compute the rotation part of the transform
294 final Rotation r = rotationFromInertial(date, pv);
295 final Vector3D p = pv.getPosition();
296 final Vector3D momentum = pv.getMomentum();
297 final AngularCoordinates angularCoordinates = new AngularCoordinates(r, new Vector3D(1.0 / p.getNormSq(), r.applyTo(momentum)));
298
299 return new Transform(date, pv.negate(), angularCoordinates);
300 }
301
302 /**
303 * Get the rotation from inertial frame to local orbital frame.
304 * <p>
305 * This rotation does not include any time derivatives. If first time derivatives (i.e. rotation rate) is needed as well,
306 * the full {@link #transformFromInertial(AbsoluteDate, PVCoordinates) transformFromInertial} method must be called and
307 * the complete rotation transform must be extracted from it.
308 *
309 * @param date date of the rotation
310 * @param pv position-velocity of the spacecraft in some inertial frame
311 *
312 * @return rotation from inertial frame to local orbital frame
313 */
314 Rotation rotationFromInertial(AbsoluteDate date, PVCoordinates pv);
315
316 /** Get flag that indicates if current local orbital frame shall be treated as pseudo-inertial.
317 * @return flag that indicates if current local orbital frame shall be treated as pseudo-inertial
318 */
319 default boolean isQuasiInertial() {
320 return false;
321 }
322
323 /** Get name of the local orbital frame.
324 * @return name of the local orbital frame
325 */
326 String getName();
327
328 }