1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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.hipparchus.linear.BlockFieldMatrix;
27 import org.hipparchus.linear.BlockRealMatrix;
28 import org.hipparchus.linear.FieldMatrix;
29 import org.hipparchus.linear.MatrixUtils;
30 import org.hipparchus.linear.RealMatrix;
31 import org.hipparchus.util.Binary64;
32 import org.hipparchus.util.Binary64Field;
33 import org.junit.jupiter.api.Assertions;
34 import org.junit.jupiter.api.BeforeEach;
35 import org.junit.jupiter.api.DisplayName;
36 import org.junit.jupiter.api.Test;
37 import org.orekit.TestUtils;
38 import org.orekit.orbits.KeplerianOrbit;
39 import org.orekit.orbits.Orbit;
40 import org.orekit.orbits.PositionAngleType;
41 import org.orekit.propagation.analytical.KeplerianPropagator;
42 import org.orekit.time.AbsoluteDate;
43 import org.orekit.time.FieldAbsoluteDate;
44 import org.orekit.utils.FieldPVCoordinates;
45 import org.orekit.utils.PVCoordinates;
46 import org.orekit.utils.PVCoordinatesProvider;
47
48 public class LocalOrbitalFrameTest {
49
50 @Test
51 public void testIssue1282() {
52
53 final Vector3D position = new Vector3D(0,0,1);
54 final Vector3D velocity = new Vector3D(0,1,0);
55 final PVCoordinates pvCoordinates = new PVCoordinates(position, velocity);
56
57
58 final Rotation actualRotation = LOFType.EQW.rotationFromInertial(pvCoordinates);
59
60
61 final Rotation expectedRotation = new Rotation(Vector3D.MINUS_J,Vector3D.MINUS_I, Vector3D.PLUS_I, Vector3D.PLUS_K);
62 Assertions.assertArrayEquals(expectedRotation.getMatrix(), actualRotation.getMatrix());
63 }
64
65 @Test
66 public void testIssue977() {
67 LOFType type = LOFType.TNW;
68 LocalOrbitalFrame lof = new LocalOrbitalFrame(FramesFactory.getGCRF(), type, provider, type.name());
69 Assertions.assertThrows(UnsupportedOperationException.class, () -> {
70 lof.getTransformProvider().getTransform(FieldAbsoluteDate.getJ2000Epoch(Binary64Field.getInstance()));
71 });
72 }
73
74 @Test
75 public void testTNW() {
76 AbsoluteDate date = initDate.shiftedBy(400);
77 PVCoordinates pv = provider.getPVCoordinates(date, inertialFrame);
78 checkFrame(LOFType.TNW, date,
79 pv.getVelocity(),
80 Vector3D.crossProduct(pv.getMomentum(), pv.getVelocity()),
81 pv.getMomentum(),
82 pv.getMomentum().negate());
83 }
84
85 @Test
86 public void testQSW() {
87 AbsoluteDate date = initDate.shiftedBy(400);
88 PVCoordinates pv = provider.getPVCoordinates(date, inertialFrame);
89 checkFrame(LOFType.QSW, date,
90 pv.getPosition(),
91 Vector3D.crossProduct(pv.getMomentum(), pv.getPosition()),
92 pv.getMomentum(),
93 pv.getMomentum().negate());
94 }
95
96 @Test
97 public void testLVLH() {
98 AbsoluteDate date = initDate.shiftedBy(400);
99 PVCoordinates pv = provider.getPVCoordinates(date, inertialFrame);
100 checkFrame(LOFType.LVLH, date,
101 pv.getPosition(),
102 Vector3D.crossProduct(pv.getMomentum(), pv.getPosition()),
103 pv.getMomentum(),
104 pv.getMomentum().negate());
105 }
106
107 @Test
108 public void testLVLH_CCSDS() {
109 AbsoluteDate date = initDate.shiftedBy(400);
110 PVCoordinates pv = provider.getPVCoordinates(date, inertialFrame);
111 checkFrame(LOFType.LVLH_CCSDS, date,
112 Vector3D.crossProduct(pv.getMomentum(), pv.getPosition()),
113 pv.getMomentum().negate(),
114 pv.getPosition().negate(),
115 pv.getMomentum().negate());
116 }
117
118 @Test
119 public void testVVLH() {
120 AbsoluteDate date = initDate.shiftedBy(400);
121 PVCoordinates pv = provider.getPVCoordinates(date, inertialFrame);
122 checkFrame(LOFType.VVLH, date,
123 Vector3D.crossProduct(pv.getMomentum(), pv.getPosition()),
124 pv.getMomentum().negate(),
125 pv.getPosition().negate(),
126 pv.getMomentum().negate());
127 }
128
129 @Test
130 public void testVNC() {
131 AbsoluteDate date = initDate.shiftedBy(400);
132 PVCoordinates pv = provider.getPVCoordinates(date, inertialFrame);
133 checkFrame(LOFType.VNC, date,
134 pv.getVelocity(),
135 pv.getMomentum(),
136 Vector3D.crossProduct(pv.getVelocity(), pv.getMomentum()),
137 pv.getMomentum().negate());
138 }
139
140 @Test
141 @DisplayName("Test transformFromLOFInToLOFOut method")
142 void should_return_expected_transform_from_LOFIn_To_LOFOut() {
143
144 final AbsoluteDate date = new AbsoluteDate();
145 final PVCoordinates pv = new PVCoordinates(new Vector3D(6378000 + 400000, 0, 0),
146 new Vector3D(0, 7669, 0));
147
148
149 final Transform transformFromTNWToQSW = LOF.transformFromLOFInToLOFOut(LOFType.TNW, LOFType.QSW, date, pv);
150 final Transform transformFromQSWToNTW = LOF.transformFromLOFInToLOFOut(LOFType.QSW, LOFType.NTW, date, pv);
151 final Transform transformFromNTWToTNW = LOF.transformFromLOFInToLOFOut(LOFType.NTW, LOFType.TNW, date, pv);
152 final Transform composedTransform = composeTransform(date,
153 transformFromTNWToQSW,
154 transformFromQSWToNTW,
155 transformFromNTWToTNW);
156
157 final Vector3D computedTranslation = composedTransform.getTranslation();
158 final BlockRealMatrix computedRotation = new BlockRealMatrix(composedTransform.getRotation().getMatrix());
159
160
161 final Vector3D expectedTranslation = new Vector3D(0, 0, 0);
162 final RealMatrix expectedRotation = MatrixUtils.createRealIdentityMatrix(3);
163
164 TestUtils.validateVector3D(expectedTranslation, computedTranslation, 1e-15);
165 TestUtils.validateRealMatrix(expectedRotation, computedRotation, 1e-15);
166
167 }
168
169 @Test
170 @DisplayName("Test transformFromLOFInToLOFOut (field version) method")
171 void should_return_expected_field_transform_from_LOFIn_To_LOFOut() {
172
173 final Field<Binary64> field = Binary64Field.getInstance();
174 final FieldAbsoluteDate<Binary64> date = new FieldAbsoluteDate<>(field);
175 final FieldPVCoordinates<Binary64> pv =
176 new FieldPVCoordinates<>(new FieldVector3D<>(new Binary64(6378000 + 400000),
177 new Binary64(0),
178 new Binary64(0)),
179 new FieldVector3D<>(new Binary64(0),
180 new Binary64(7669),
181 new Binary64(0)));
182
183
184 final FieldTransform<Binary64> transformFromTNWToQSW =
185 LOF.transformFromLOFInToLOFOut(LOFType.TNW, LOFType.QSW, date, pv);
186 final FieldTransform<Binary64> transformFromQSWToNTW =
187 LOF.transformFromLOFInToLOFOut(LOFType.QSW, LOFType.NTW, date, pv);
188 final FieldTransform<Binary64> transformFromNTWToTNW =
189 LOF.transformFromLOFInToLOFOut(LOFType.NTW, LOFType.TNW, date, pv);
190 final FieldTransform<Binary64> composedTransform = composeFieldTransform(date,
191 transformFromTNWToQSW,
192 transformFromQSWToNTW,
193 transformFromNTWToTNW);
194
195 final FieldVector3D<Binary64> computedTranslation = composedTransform.getTranslation();
196 final BlockFieldMatrix<Binary64> computedRotation =
197 new BlockFieldMatrix<>(composedTransform.getRotation().getMatrix());
198
199
200 final Vector3D expectedTranslation = new Vector3D(0, 0, 0);
201 final RealMatrix expectedRotation = MatrixUtils.createRealIdentityMatrix(3);
202
203 TestUtils.validateFieldVector3D(expectedTranslation, computedTranslation, 1e-15);
204 TestUtils.validateFieldMatrix(expectedRotation, computedRotation, 1e-15);
205
206 }
207
208 @Test
209 @DisplayName("Test transformFromInertial method")
210 void should_return_expected_transform_from_inertial() {
211
212 final AbsoluteDate date = new AbsoluteDate();
213 final PVCoordinates pv = new PVCoordinates(new Vector3D(6378000 + 400000, 0, 0),
214 new Vector3D(0, 7669, 0));
215
216
217 final Transform transformFromInertialToLOF = LOFType.TNW.transformFromInertial(date, pv);
218 final Vector3D computedTranslation = transformFromInertialToLOF.getTranslation();
219 final RealMatrix computedRotation =
220 new BlockRealMatrix(transformFromInertialToLOF.getRotation().getMatrix());
221
222
223 final Vector3D expectedTranslation = new Vector3D(-(6378000 + 400000), 0, 0);
224 final RealMatrix expectedRotation = new BlockRealMatrix(new double[][] {
225 { 0, 1, 0 },
226 { -1, 0, 0 },
227 { 0, 0, 1 }
228 });
229
230 TestUtils.validateVector3D(expectedTranslation, computedTranslation, 1e-15);
231 TestUtils.validateRealMatrix(expectedRotation, computedRotation, 1e-15);
232
233 }
234
235 @Test
236 @DisplayName("Test transformFromInertial (field version) method")
237 void should_return_expected_field_transform_from_inertial() {
238
239 final Field<Binary64> field = Binary64Field.getInstance();
240 final FieldAbsoluteDate<Binary64> date = new FieldAbsoluteDate<>(field);
241 final FieldPVCoordinates<Binary64> pv =
242 new FieldPVCoordinates<>(new FieldVector3D<>(new Binary64(6378000 + 400000),
243 new Binary64(0),
244 new Binary64(0)),
245 new FieldVector3D<>(new Binary64(0),
246 new Binary64(7669),
247 new Binary64(0)));
248
249
250 final FieldTransform<Binary64> transformFromInertialToLOF = LOFType.TNW.transformFromInertial(date, pv);
251 final FieldVector3D<Binary64> computedTranslation = transformFromInertialToLOF.getTranslation();
252 final BlockFieldMatrix<Binary64> computedRotation =
253 new BlockFieldMatrix<>(transformFromInertialToLOF.getRotation().getMatrix());
254
255
256 final Vector3D expectedTranslation = new Vector3D(-(6378000 + 400000), 0, 0);
257 final RealMatrix expectedRotation = new BlockRealMatrix(new double[][] {
258 { 0, 1, 0 },
259 { -1, 0, 0 },
260 { 0, 0, 1 }
261 });
262
263 TestUtils.validateFieldVector3D(expectedTranslation, computedTranslation, 1e-15);
264 TestUtils.validateFieldMatrix(expectedRotation, computedRotation, 1e-15);
265
266 }
267
268 @Test
269 @DisplayName("Test all rotation methods using default method of the interface")
270 void should_return_initial_value_after_multiple_rotations_default_method() {
271
272 final AbsoluteDate arbitraryEpoch = AbsoluteDate.ARBITRARY_EPOCH;
273 final PVCoordinates pv = new PVCoordinates(new Vector3D(6378000 + 400000, 0, 0),
274 new Vector3D(0, 5422.8, 5422.8));
275
276
277 final Rotation rotationFromTNWToTNWInertial =
278 LOFType.TNW_INERTIAL.rotationFromLOF(LOFType.TNW, arbitraryEpoch, pv);
279
280 final Rotation rotationFromTNWInertialToQSW =
281 LOFType.QSW.rotationFromLOF(LOFType.TNW_INERTIAL, arbitraryEpoch, pv);
282
283 final Rotation rotationFromQSWToQSWInertial =
284 LOFType.QSW_INERTIAL.rotationFromLOF(LOFType.QSW, arbitraryEpoch, pv);
285
286 final Rotation rotationFromQSWInertialToLVLH =
287 LOFType.LVLH.rotationFromLOF(LOFType.QSW_INERTIAL, arbitraryEpoch, pv);
288
289 final Rotation rotationFromLVLHToLVLHInertial =
290 LOFType.LVLH_INERTIAL.rotationFromLOF(LOFType.LVLH, arbitraryEpoch, pv);
291
292 final Rotation rotationFromLVLHInertialToLVLH_CCSDS =
293 LOFType.LVLH_CCSDS.rotationFromLOF(LOFType.LVLH_INERTIAL, arbitraryEpoch, pv);
294
295 final Rotation rotationFromLVLH_CCSDSToLVLH_CCSDSInertial =
296 LOFType.LVLH_CCSDS_INERTIAL.rotationFromLOF(LOFType.LVLH_CCSDS, arbitraryEpoch, pv);
297
298 final Rotation rotationFromLVLH_CCSDSInertialToVVLH =
299 LOFType.VVLH.rotationFromLOF(LOFType.LVLH_CCSDS_INERTIAL, arbitraryEpoch, pv);
300
301 final Rotation rotationFromVVLHToVVLHInertial =
302 LOFType.VVLH_INERTIAL.rotationFromLOF(LOFType.VVLH, arbitraryEpoch, pv);
303
304 final Rotation rotationFromVVLHInertialToVNC =
305 LOFType.VNC.rotationFromLOF(LOFType.VVLH_INERTIAL, arbitraryEpoch, pv);
306
307 final Rotation rotationFromVNCToVNCInertial =
308 LOFType.VNC_INERTIAL.rotationFromLOF(LOFType.VNC, arbitraryEpoch, pv);
309
310 final Rotation rotationFromVNCInertialToNTW =
311 LOFType.NTW.rotationFromLOF(LOFType.VNC_INERTIAL, arbitraryEpoch, pv);
312
313 final Rotation rotationFromNTWToNTWInertial =
314 LOFType.NTW_INERTIAL.rotationFromLOF(LOFType.NTW, arbitraryEpoch, pv);
315
316 final Rotation rotationFromNTWInertialToEQW =
317 LOFType.EQW.rotationFromLOF(LOFType.NTW_INERTIAL, arbitraryEpoch, pv);
318
319 final Rotation rotationFromEQWToTNW =
320 LOF.rotationFromLOFInToLOFOut(LOFType.EQW, LOFType.TNW, arbitraryEpoch, pv);
321
322 final Rotation rotationFromTNWToTNW =
323 composeRotations(rotationFromTNWToTNWInertial,
324 rotationFromTNWInertialToQSW,
325 rotationFromQSWToQSWInertial,
326 rotationFromQSWInertialToLVLH,
327 rotationFromLVLHToLVLHInertial,
328 rotationFromLVLHInertialToLVLH_CCSDS,
329 rotationFromLVLH_CCSDSToLVLH_CCSDSInertial,
330 rotationFromLVLH_CCSDSInertialToVVLH,
331 rotationFromVVLHToVVLHInertial,
332 rotationFromVVLHInertialToVNC,
333 rotationFromVNCToVNCInertial,
334 rotationFromVNCInertialToNTW,
335 rotationFromNTWToNTWInertial,
336 rotationFromNTWInertialToEQW,
337 rotationFromEQWToTNW);
338
339 final RealMatrix rotationMatrixFromTNWToTNW =
340 new BlockRealMatrix(rotationFromTNWToTNW.getMatrix());
341
342
343 final RealMatrix identityMatrix = MatrixUtils.createRealIdentityMatrix(3);
344
345 TestUtils.validateRealMatrix(identityMatrix, rotationMatrixFromTNWToTNW, 1e-15);
346
347 }
348
349 @Test
350 @DisplayName("Test all rotation methods (field version) using default method of the interface")
351 void should_return_initial_value_after_multiple_field_rotations_default_method() {
352
353 final Binary64Field field = Binary64Field.getInstance();
354 final FieldAbsoluteDate<Binary64> arbitraryEpoch = new FieldAbsoluteDate<>(field, AbsoluteDate.ARBITRARY_EPOCH);
355 final FieldPVCoordinates<Binary64> pv =
356 new FieldPVCoordinates<>(new FieldVector3D<>(new Binary64(6378000 + 400000),
357 new Binary64(0),
358 new Binary64(0)),
359 new FieldVector3D<>(new Binary64(0),
360 new Binary64(5422.8),
361 new Binary64(5422.8)));
362
363
364 final FieldRotation<Binary64> rotationFromTNWToTNWInertial =
365 LOFType.TNW_INERTIAL.rotationFromLOF(field, LOFType.TNW, arbitraryEpoch, pv);
366
367 final FieldRotation<Binary64> rotationFromTNWInertialToQSW =
368 LOFType.QSW.rotationFromLOF(field, LOFType.TNW_INERTIAL, arbitraryEpoch, pv);
369
370 final FieldRotation<Binary64> rotationFromQSWToQSWInertial =
371 LOFType.QSW_INERTIAL.rotationFromLOF(field, LOFType.QSW, arbitraryEpoch, pv);
372
373 final FieldRotation<Binary64> rotationFromQSWInertialToLVLH =
374 LOFType.LVLH.rotationFromLOF(field, LOFType.QSW_INERTIAL, arbitraryEpoch, pv);
375
376 final FieldRotation<Binary64> rotationFromLVLHToLVLHInertial =
377 LOFType.LVLH_INERTIAL.rotationFromLOF(field, LOFType.LVLH, arbitraryEpoch, pv);
378
379 final FieldRotation<Binary64> rotationFromLVLHInertialToLVLH_CCSDS =
380 LOFType.LVLH_CCSDS.rotationFromLOF(field, LOFType.LVLH_INERTIAL, arbitraryEpoch, pv);
381
382 final FieldRotation<Binary64> rotationFromLVLH_CCSDSToLVLH_CCSDSInertial =
383 LOFType.LVLH_CCSDS_INERTIAL.rotationFromLOF(field, LOFType.LVLH_CCSDS, arbitraryEpoch, pv);
384
385 final FieldRotation<Binary64> rotationFromLVLH_CCSDSInertialToVVLH =
386 LOFType.VVLH.rotationFromLOF(field, LOFType.LVLH_CCSDS_INERTIAL, arbitraryEpoch, pv);
387
388 final FieldRotation<Binary64> rotationFromVVLHToVVLHInertial =
389 LOFType.VVLH_INERTIAL.rotationFromLOF(field, LOFType.VVLH, arbitraryEpoch, pv);
390
391 final FieldRotation<Binary64> rotationFromVVLHInertialToVNC =
392 LOFType.VNC.rotationFromLOF(field, LOFType.VVLH_INERTIAL, arbitraryEpoch, pv);
393
394 final FieldRotation<Binary64> rotationFromVNCToVNCInertial =
395 LOFType.VNC_INERTIAL.rotationFromLOF(field, LOFType.VNC, arbitraryEpoch, pv);
396
397 final FieldRotation<Binary64> rotationFromVNCInertialToNTW =
398 LOFType.NTW.rotationFromLOF(field, LOFType.VNC_INERTIAL, arbitraryEpoch, pv);
399
400 final FieldRotation<Binary64> rotationFromNTWToNTWInertial =
401 LOFType.NTW_INERTIAL.rotationFromLOF(field, LOFType.NTW, arbitraryEpoch, pv);
402
403 final FieldRotation<Binary64> rotationFromNTWInertialToEQW =
404 LOFType.EQW.rotationFromLOF(field, LOFType.NTW_INERTIAL, arbitraryEpoch, pv);
405
406 final FieldRotation<Binary64> rotationFromEQWToTNW =
407 LOF.rotationFromLOFInToLOFOut(field, LOFType.EQW, LOFType.TNW, arbitraryEpoch, pv);
408
409 final FieldRotation<Binary64> rotationFromTNWToTNW =
410 composeFieldRotations(rotationFromTNWToTNWInertial,
411 rotationFromTNWInertialToQSW,
412 rotationFromQSWToQSWInertial,
413 rotationFromQSWInertialToLVLH,
414 rotationFromLVLHToLVLHInertial,
415 rotationFromLVLHInertialToLVLH_CCSDS,
416 rotationFromLVLH_CCSDSToLVLH_CCSDSInertial,
417 rotationFromLVLH_CCSDSInertialToVVLH,
418 rotationFromVVLHToVVLHInertial,
419 rotationFromVVLHInertialToVNC,
420 rotationFromVNCToVNCInertial,
421 rotationFromVNCInertialToNTW,
422 rotationFromNTWToNTWInertial,
423 rotationFromNTWInertialToEQW,
424 rotationFromEQWToTNW);
425
426 final FieldMatrix<Binary64> rotationMatrixFromTNWToTNW =
427 new BlockFieldMatrix<>(rotationFromTNWToTNW.getMatrix());
428
429
430 final RealMatrix identityMatrix = MatrixUtils.createRealIdentityMatrix(3);
431
432 TestUtils.validateFieldMatrix(identityMatrix, rotationMatrixFromTNWToTNW, 1e-15);
433
434 }
435
436 @Test
437 @DisplayName("Test all rotation methods")
438 void should_return_initial_value_after_multiple_rotations() {
439
440 final PVCoordinates pv = new PVCoordinates(new Vector3D(6378000 + 400000, 0, 0),
441 new Vector3D(0, 5422.8, 5422.8));
442
443
444 final Rotation rotationFromTNWToTNWInertial =
445 LOFType.TNW_INERTIAL.rotationFromLOF(LOFType.TNW, pv);
446
447 final Rotation rotationFromTNWInertialToQSW =
448 LOFType.QSW.rotationFromLOF(LOFType.TNW_INERTIAL, pv);
449
450 final Rotation rotationFromQSWToQSWInertial =
451 LOFType.QSW_INERTIAL.rotationFromLOF(LOFType.QSW, pv);
452
453 final Rotation rotationFromQSWInertialToLVLH =
454 LOFType.LVLH.rotationFromLOF(LOFType.QSW_INERTIAL, pv);
455
456 final Rotation rotationFromLVLHToLVLHInertial =
457 LOFType.LVLH_INERTIAL.rotationFromLOF(LOFType.LVLH, pv);
458
459 final Rotation rotationFromLVLHInertialToLVLH_CCSDS =
460 LOFType.LVLH_CCSDS.rotationFromLOF(LOFType.LVLH_INERTIAL, pv);
461
462 final Rotation rotationFromLVLH_CCSDSToLVLH_CCSDSInertial =
463 LOFType.LVLH_CCSDS_INERTIAL.rotationFromLOF(LOFType.LVLH_CCSDS, pv);
464
465 final Rotation rotationFromLVLH_CCSDSInertialToVVLH =
466 LOFType.VVLH.rotationFromLOF(LOFType.LVLH_CCSDS_INERTIAL, pv);
467
468 final Rotation rotationFromVVLHToVVLHInertial =
469 LOFType.VVLH_INERTIAL.rotationFromLOF(LOFType.VVLH, pv);
470
471 final Rotation rotationFromVVLHInertialToVNC =
472 LOFType.VNC.rotationFromLOF(LOFType.VVLH_INERTIAL, pv);
473
474 final Rotation rotationFromVNCToVNCInertial =
475 LOFType.VNC_INERTIAL.rotationFromLOF(LOFType.VNC, pv);
476
477 final Rotation rotationFromVNCInertialToNTW =
478 LOFType.NTW.rotationFromLOF(LOFType.VNC_INERTIAL, pv);
479
480 final Rotation rotationFromNTWToNTWInertial =
481 LOFType.NTW_INERTIAL.rotationFromLOF(LOFType.NTW, pv);
482
483 final Rotation rotationFromNTWInertialToEQW =
484 LOFType.EQW.rotationFromLOF(LOFType.NTW_INERTIAL, pv);
485
486 final Rotation rotationFromEQWToTNW =
487 LOFType.rotationFromLOFInToLOFOut(LOFType.EQW, LOFType.TNW, pv);
488
489 final Rotation rotationFromTNWToTNW =
490 composeRotations(rotationFromTNWToTNWInertial,
491 rotationFromTNWInertialToQSW,
492 rotationFromQSWToQSWInertial,
493 rotationFromQSWInertialToLVLH,
494 rotationFromLVLHToLVLHInertial,
495 rotationFromLVLHInertialToLVLH_CCSDS,
496 rotationFromLVLH_CCSDSToLVLH_CCSDSInertial,
497 rotationFromLVLH_CCSDSInertialToVVLH,
498 rotationFromVVLHToVVLHInertial,
499 rotationFromVVLHInertialToVNC,
500 rotationFromVNCToVNCInertial,
501 rotationFromVNCInertialToNTW,
502 rotationFromNTWToNTWInertial,
503 rotationFromNTWInertialToEQW,
504 rotationFromEQWToTNW);
505
506 final RealMatrix rotationMatrixFromTNWToTNW =
507 new BlockRealMatrix(rotationFromTNWToTNW.getMatrix());
508
509
510 final RealMatrix identityMatrix = MatrixUtils.createRealIdentityMatrix(3);
511
512 TestUtils.validateRealMatrix(identityMatrix, rotationMatrixFromTNWToTNW, 1e-15);
513
514 }
515
516 @Test
517 @DisplayName("Test all rotation methods (field version)")
518 void should_return_initial_value_after_multiple_field_rotations() {
519
520 final Binary64Field field = Binary64Field.getInstance();
521 final FieldPVCoordinates<Binary64> pv =
522 new FieldPVCoordinates<>(new FieldVector3D<>(new Binary64(6378000 + 400000),
523 new Binary64(0),
524 new Binary64(0)),
525 new FieldVector3D<>(new Binary64(0),
526 new Binary64(5422.8),
527 new Binary64(5422.8)));
528
529
530 final FieldRotation<Binary64> rotationFromTNWToTNWInertial =
531 LOFType.TNW_INERTIAL.rotationFromLOF(field, LOFType.TNW, pv);
532
533 final FieldRotation<Binary64> rotationFromTNWInertialToQSW =
534 LOFType.QSW.rotationFromLOF(field, LOFType.TNW_INERTIAL, pv);
535
536 final FieldRotation<Binary64> rotationFromQSWToQSWInertial =
537 LOFType.QSW_INERTIAL.rotationFromLOF(field, LOFType.QSW, pv);
538
539 final FieldRotation<Binary64> rotationFromQSWInertialToLVLH =
540 LOFType.LVLH.rotationFromLOF(field, LOFType.QSW_INERTIAL, pv);
541
542 final FieldRotation<Binary64> rotationFromLVLHToLVLHInertial =
543 LOFType.LVLH_INERTIAL.rotationFromLOF(field, LOFType.LVLH, pv);
544
545 final FieldRotation<Binary64> rotationFromLVLHInertialToLVLH_CCSDS =
546 LOFType.LVLH_CCSDS.rotationFromLOF(field, LOFType.LVLH_INERTIAL, pv);
547
548 final FieldRotation<Binary64> rotationFromLVLH_CCSDSToLVLH_CCSDSInertial =
549 LOFType.LVLH_CCSDS_INERTIAL.rotationFromLOF(field, LOFType.LVLH_CCSDS, pv);
550
551 final FieldRotation<Binary64> rotationFromLVLH_CCSDSInertialToVVLH =
552 LOFType.VVLH.rotationFromLOF(field, LOFType.LVLH_CCSDS_INERTIAL, pv);
553
554 final FieldRotation<Binary64> rotationFromVVLHToVVLHInertial =
555 LOFType.VVLH_INERTIAL.rotationFromLOF(field, LOFType.VVLH, pv);
556
557 final FieldRotation<Binary64> rotationFromVVLHInertialToVNC =
558 LOFType.VNC.rotationFromLOF(field, LOFType.VVLH_INERTIAL, pv);
559
560 final FieldRotation<Binary64> rotationFromVNCToVNCInertial =
561 LOFType.VNC_INERTIAL.rotationFromLOF(field, LOFType.VNC, pv);
562
563 final FieldRotation<Binary64> rotationFromVNCInertialToNTW =
564 LOFType.NTW.rotationFromLOF(field, LOFType.VNC_INERTIAL, pv);
565
566 final FieldRotation<Binary64> rotationFromNTWToNTWInertial =
567 LOFType.NTW_INERTIAL.rotationFromLOF(field, LOFType.NTW, pv);
568
569 final FieldRotation<Binary64> rotationFromNTWInertialToEQW =
570 LOFType.EQW.rotationFromLOF(field, LOFType.NTW_INERTIAL, pv);
571
572 final FieldRotation<Binary64> rotationFromEQWToTNW =
573 LOFType.rotationFromLOFInToLOFOut(field, LOFType.EQW, LOFType.TNW, pv);
574
575 final FieldRotation<Binary64> rotationFromTNWToTNW =
576 composeFieldRotations(rotationFromTNWToTNWInertial,
577 rotationFromTNWInertialToQSW,
578 rotationFromQSWToQSWInertial,
579 rotationFromQSWInertialToLVLH,
580 rotationFromLVLHToLVLHInertial,
581 rotationFromLVLHInertialToLVLH_CCSDS,
582 rotationFromLVLH_CCSDSToLVLH_CCSDSInertial,
583 rotationFromLVLH_CCSDSInertialToVVLH,
584 rotationFromVVLHToVVLHInertial,
585 rotationFromVVLHInertialToVNC,
586 rotationFromVNCToVNCInertial,
587 rotationFromVNCInertialToNTW,
588 rotationFromNTWToNTWInertial,
589 rotationFromNTWInertialToEQW,
590 rotationFromEQWToTNW);
591
592 final FieldMatrix<Binary64> rotationMatrixFromTNWToTNW =
593 new BlockFieldMatrix<>(rotationFromTNWToTNW.getMatrix());
594
595
596 final RealMatrix identityMatrix = MatrixUtils.createRealIdentityMatrix(3);
597
598 TestUtils.validateFieldMatrix(identityMatrix, rotationMatrixFromTNWToTNW, 1e-15);
599
600 }
601
602 @Test
603 @DisplayName("Test isQuasiInertialMethod")
604 void should_return_expected_boolean() {
605
606
607 Assertions.assertTrue(LOFType.TNW_INERTIAL.isQuasiInertial());
608 Assertions.assertTrue(LOFType.NTW_INERTIAL.isQuasiInertial());
609 Assertions.assertTrue(LOFType.QSW_INERTIAL.isQuasiInertial());
610 Assertions.assertTrue(LOFType.VNC_INERTIAL.isQuasiInertial());
611 Assertions.assertTrue(LOFType.LVLH_INERTIAL.isQuasiInertial());
612 Assertions.assertTrue(LOFType.LVLH_CCSDS_INERTIAL.isQuasiInertial());
613 Assertions.assertTrue(LOFType.EQW.isQuasiInertial());
614 Assertions.assertTrue(LOFType.VVLH_INERTIAL.isQuasiInertial());
615
616
617 Assertions.assertFalse(LOFType.TNW.isQuasiInertial());
618 Assertions.assertFalse(LOFType.NTW.isQuasiInertial());
619 Assertions.assertFalse(LOFType.QSW.isQuasiInertial());
620 Assertions.assertFalse(LOFType.VNC.isQuasiInertial());
621 Assertions.assertFalse(LOFType.LVLH.isQuasiInertial());
622 Assertions.assertFalse(LOFType.LVLH_CCSDS.isQuasiInertial());
623 Assertions.assertFalse(LOFType.VVLH.isQuasiInertial());
624
625 }
626
627 private Rotation composeRotations(final Rotation... rotations) {
628
629 Rotation composedRotations = null;
630
631 for (Rotation rotation : rotations) {
632 if (composedRotations == null) {
633 composedRotations = rotation;
634 }
635 else {
636 composedRotations = composedRotations.compose(rotation, RotationConvention.FRAME_TRANSFORM);
637 }
638 }
639
640 return composedRotations;
641 }
642
643 @SafeVarargs private final <T extends CalculusFieldElement<T>> FieldRotation<T> composeFieldRotations(
644 final FieldRotation<T>... rotations) {
645
646 FieldRotation<T> composedRotations = null;
647
648 for (FieldRotation<T> rotation : rotations) {
649 if (composedRotations == null) {
650 composedRotations = rotation;
651 }
652 else {
653 composedRotations = composedRotations.compose(rotation, RotationConvention.FRAME_TRANSFORM);
654 }
655 }
656
657 return composedRotations;
658 }
659
660 private Transform composeTransform(final AbsoluteDate date, final Transform... transforms){
661 Transform composedTransform = null;
662
663 for (Transform transform : transforms) {
664 if (composedTransform == null) {
665 composedTransform = transform;
666 }
667 else {
668 composedTransform = new Transform(date, composedTransform, transform);
669 }
670 }
671
672 return composedTransform;
673 }
674
675 @SafeVarargs
676 private final <T extends CalculusFieldElement<T>> FieldTransform<T> composeFieldTransform(
677 final FieldAbsoluteDate<T> date,
678 final FieldTransform<T>... transforms) {
679 FieldTransform<T> composedTransform = null;
680
681 for (FieldTransform<T> transform : transforms) {
682 if (composedTransform == null) {
683 composedTransform = transform;
684 }
685 else {
686 composedTransform = new FieldTransform<>(date, composedTransform, transform);
687 }
688 }
689
690 return composedTransform;
691 }
692
693 private void checkFrame(LOFType type, AbsoluteDate date,
694 Vector3D expectedXDirection, Vector3D expectedYDirection,
695 Vector3D expectedZDirection, Vector3D expectedRotationDirection) {
696 LocalOrbitalFrame lof = new LocalOrbitalFrame(FramesFactory.getGCRF(), type, provider, type.name());
697
698 Transform t = lof.getTransformTo(FramesFactory.getGCRF(), date);
699 PVCoordinates pv1 = t.transformPVCoordinates(PVCoordinates.ZERO);
700 Vector3D p1 = pv1.getPosition();
701 Vector3D v1 = pv1.getVelocity();
702 PVCoordinates pv2 = provider.getPVCoordinates(date, FramesFactory.getGCRF());
703 Vector3D p2 = pv2.getPosition();
704 Vector3D v2 = pv2.getVelocity();
705 Assertions.assertEquals(0, p1.subtract(p2).getNorm(), 1.0e-14 * p1.getNorm());
706 Assertions.assertEquals(0, v1.subtract(v2).getNorm(), 1.0e-14 * v1.getNorm());
707
708 Vector3D xDirection = t.transformVector(Vector3D.PLUS_I);
709 Vector3D yDirection = t.transformVector(Vector3D.PLUS_J);
710 Vector3D zDirection = t.transformVector(Vector3D.PLUS_K);
711 Assertions.assertEquals(0, Vector3D.angle(expectedXDirection, xDirection), 2.0e-15);
712 Assertions.assertEquals(0, Vector3D.angle(expectedYDirection, yDirection), 1.0e-15);
713 Assertions.assertEquals(0, Vector3D.angle(expectedZDirection, zDirection), 1.0e-15);
714 Assertions.assertEquals(0, Vector3D.angle(expectedRotationDirection, t.getRotationRate()), 1.0e-15);
715
716 Assertions.assertEquals(initialOrbit.getKeplerianMeanMotion(), t.getRotationRate().getNorm(), 1.0e-7);
717
718 }
719
720 @BeforeEach
721 public void setUp() {
722 inertialFrame = FramesFactory.getGCRF();
723 initDate = AbsoluteDate.J2000_EPOCH.shiftedBy(584.);
724 initialOrbit =
725 new KeplerianOrbit(7209668.0, 0.5e-4, 1.7, 2.1, 2.9, 6.2, PositionAngleType.TRUE,
726 inertialFrame, initDate, 3.986004415e14);
727 provider = new KeplerianPropagator(initialOrbit);
728
729 }
730
731 private Frame inertialFrame;
732 private AbsoluteDate initDate;
733 private Orbit initialOrbit;
734 private PVCoordinatesProvider provider;
735
736 }