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.errors.OrekitException;
39 import org.orekit.errors.OrekitMessages;
40 import org.orekit.files.ccsds.definitions.OrbitRelativeFrame;
41 import org.orekit.orbits.KeplerianOrbit;
42 import org.orekit.orbits.Orbit;
43 import org.orekit.orbits.PositionAngleType;
44 import org.orekit.propagation.analytical.KeplerianPropagator;
45 import org.orekit.time.AbsoluteDate;
46 import org.orekit.time.FieldAbsoluteDate;
47 import org.orekit.utils.FieldPVCoordinates;
48 import org.orekit.utils.PVCoordinates;
49 import org.orekit.utils.PVCoordinatesProvider;
50
51 public class LocalOrbitalFrameTest {
52
53 @Test
54 public void testIssue1282() {
55
56 final Vector3D position = new Vector3D(0, 0, 1);
57 final Vector3D velocity = new Vector3D(0, 1, 0);
58 final PVCoordinates pvCoordinates = new PVCoordinates(position, velocity);
59
60
61 final Rotation actualRotation = LOFType.EQW.rotationFromInertial(pvCoordinates);
62
63
64 final Rotation expectedRotation = new Rotation(Vector3D.MINUS_J,Vector3D.MINUS_I, Vector3D.PLUS_I, Vector3D.PLUS_K);
65 Assertions.assertArrayEquals(expectedRotation.getMatrix(), actualRotation.getMatrix());
66 }
67
68 @Test
69 public void testIssue977() {
70 LOFType type = LOFType.TNW;
71 LocalOrbitalFrame lof = new LocalOrbitalFrame(FramesFactory.getGCRF(), type, provider, type.name());
72 Assertions.assertThrows(UnsupportedOperationException.class,
73 () -> lof.getTransformProvider().getTransform(FieldAbsoluteDate.getJ2000Epoch(Binary64Field.getInstance())));
74 }
75
76 @Test
77 public void testTNW() {
78 AbsoluteDate date = initDate.shiftedBy(400);
79 PVCoordinates pv = provider.getPVCoordinates(date, inertialFrame);
80 checkFrame(LOFType.TNW, date,
81 pv.getVelocity(),
82 Vector3D.crossProduct(pv.getMomentum(), pv.getVelocity()),
83 pv.getMomentum(),
84 pv.getMomentum().negate());
85 Assertions.assertEquals(OrbitRelativeFrame.TNW, LOFType.TNW.toOrbitRelativeFrame());
86 }
87
88 @Test
89 public void testQSW() {
90 AbsoluteDate date = initDate.shiftedBy(400);
91 PVCoordinates pv = provider.getPVCoordinates(date, inertialFrame);
92 checkFrame(LOFType.QSW, date,
93 pv.getPosition(),
94 Vector3D.crossProduct(pv.getMomentum(), pv.getPosition()),
95 pv.getMomentum(),
96 pv.getMomentum().negate());
97 Assertions.assertEquals(OrbitRelativeFrame.QSW, LOFType.QSW.toOrbitRelativeFrame());
98 }
99
100 @Test
101 public void testLVLH() {
102 AbsoluteDate date = initDate.shiftedBy(400);
103 PVCoordinates pv = provider.getPVCoordinates(date, inertialFrame);
104 checkFrame(LOFType.LVLH, date,
105 pv.getPosition(),
106 Vector3D.crossProduct(pv.getMomentum(), pv.getPosition()),
107 pv.getMomentum(),
108 pv.getMomentum().negate());
109 try {
110 LOFType.LVLH.toOrbitRelativeFrame();
111 Assertions.fail("an exception should have been thrown");
112 } catch (OrekitException oe) {
113 Assertions.assertEquals(OrekitMessages.CCSDS_DIFFERENT_LVLH_DEFINITION, oe.getSpecifier());
114 }
115 }
116
117 @Test
118 public void testLVLH_CCSDS() {
119 AbsoluteDate date = initDate.shiftedBy(400);
120 PVCoordinates pv = provider.getPVCoordinates(date, inertialFrame);
121 checkFrame(LOFType.LVLH_CCSDS, date,
122 Vector3D.crossProduct(pv.getMomentum(), pv.getPosition()),
123 pv.getMomentum().negate(),
124 pv.getPosition().negate(),
125 pv.getMomentum().negate());
126 Assertions.assertEquals(OrbitRelativeFrame.LVLH, LOFType.LVLH_CCSDS.toOrbitRelativeFrame());
127 }
128
129 @Test
130 public void testVVLH() {
131 AbsoluteDate date = initDate.shiftedBy(400);
132 PVCoordinates pv = provider.getPVCoordinates(date, inertialFrame);
133 checkFrame(LOFType.VVLH, date,
134 Vector3D.crossProduct(pv.getMomentum(), pv.getPosition()),
135 pv.getMomentum().negate(),
136 pv.getPosition().negate(),
137 pv.getMomentum().negate());
138 Assertions.assertEquals(OrbitRelativeFrame.LVLH, LOFType.VVLH.toOrbitRelativeFrame());
139 }
140
141 @Test
142 public void testVNC() {
143 AbsoluteDate date = initDate.shiftedBy(400);
144 PVCoordinates pv = provider.getPVCoordinates(date, inertialFrame);
145 checkFrame(LOFType.VNC, date,
146 pv.getVelocity(),
147 pv.getMomentum(),
148 Vector3D.crossProduct(pv.getVelocity(), pv.getMomentum()),
149 pv.getMomentum().negate());
150 Assertions.assertEquals(OrbitRelativeFrame.VNC_ROTATING, LOFType.VNC.toOrbitRelativeFrame());
151 }
152
153 @Test
154 public void testENU() {
155 AbsoluteDate date = initDate.shiftedBy(400);
156 PVCoordinates pv = provider.getPVCoordinates(date, inertialFrame);
157 Transform t = LOFType.ENU.transformFromInertial(date, pv).getInverse();
158 Assertions.assertEquals("ENU", LOFType.ENU.getName());
159 Assertions.assertNull(LOFType.ENU.toOrbitRelativeFrame());
160
161
162 Assertions.assertEquals(0.0,
163 Vector3D.angle(t.transformVector(Vector3D.PLUS_K), pv.getPosition()),
164 2.0e-16);
165
166
167 Vector3D northPole = t.getInverse().transformVector(Vector3D.PLUS_K);
168 Assertions.assertEquals(0.0, northPole.getX(), 2.0e-16);
169 Assertions.assertTrue(northPole.getY() > 0.0);
170
171 }
172
173 @Test
174 public void testENUField() {
175 final Field<Binary64> field = Binary64Field.getInstance();
176 FieldAbsoluteDate<Binary64> date = new FieldAbsoluteDate<>(field, initDate.shiftedBy(400));
177 FieldPVCoordinates<Binary64> pv = new FieldPVCoordinates<>(field,
178 provider.getPVCoordinates(date.toAbsoluteDate(),
179 inertialFrame));
180 FieldTransform<Binary64> t = LOFType.ENU.transformFromInertial(date, pv).getInverse();
181 FieldVector3D<Binary64> pK = FieldVector3D.getPlusK(field);
182
183
184 Assertions.assertEquals(0.0,
185 FieldVector3D.angle(t.transformVector(pK), pv.getPosition()).getReal(),
186 2.0e-16);
187
188
189 FieldVector3D<Binary64> northPole = t.getInverse().transformVector(pK);
190 Assertions.assertEquals(0.0, northPole.getX().getReal(), 2.0e-16);
191 Assertions.assertTrue(northPole.getY().getReal() > 0.0);
192
193 }
194
195 @Test
196 public void testENUAtNorthPole() {
197 AbsoluteDate date = initDate.shiftedBy(400);
198 PVCoordinates atNorth = new PVCoordinates(new Vector3D(0.0, 0.0, 8.0e6),
199 new Vector3D(8.0e3, 0.0, 0.0));
200 Transform t = LOFType.ENU.transformFromInertial(date, atNorth).getInverse();
201 Assertions.assertEquals(0, Vector3D.angle(Vector3D.PLUS_J, t.transformVector(Vector3D.PLUS_I)), 3.0e-16);
202 Assertions.assertEquals(0, Vector3D.angle(Vector3D.MINUS_I, t.transformVector(Vector3D.PLUS_J)), 3.0e-16);
203 Assertions.assertEquals(0, Vector3D.angle(Vector3D.PLUS_K, t.transformVector(Vector3D.PLUS_K)), 3.0e-16);
204 }
205
206 @Test
207 public void testENUAtNorthPoleField() {
208 final Field<Binary64> field = Binary64Field.getInstance();
209 FieldAbsoluteDate<Binary64> date = new FieldAbsoluteDate<>(field, initDate.shiftedBy(400));
210 FieldPVCoordinates<Binary64> atNorth = new FieldPVCoordinates<>(new FieldVector3D<>(new Binary64(0.0),
211 new Binary64(0.0),
212 new Binary64(8.0e6)),
213 new FieldVector3D<>(new Binary64(8.0e3),
214 new Binary64(0.0),
215 new Binary64(0.0)));
216 FieldTransform<Binary64> t = LOFType.ENU.transformFromInertial(date, atNorth).getInverse();
217 FieldVector3D<Binary64> pI = FieldVector3D.getPlusI(field);
218 FieldVector3D<Binary64> mI = FieldVector3D.getMinusI(field);
219 FieldVector3D<Binary64> pJ = FieldVector3D.getPlusJ(field);
220 FieldVector3D<Binary64> pK = FieldVector3D.getPlusK(field);
221 Assertions.assertEquals(0, FieldVector3D.angle(pJ, t.transformVector(pI)).getReal(), 3.0e-16);
222 Assertions.assertEquals(0, FieldVector3D.angle(mI, t.transformVector(pJ)).getReal(), 3.0e-16);
223 Assertions.assertEquals(0, FieldVector3D.angle(pK, t.transformVector(pK)).getReal(), 3.0e-16);
224 }
225
226 @Test
227 public void testENUAtSouthPole() {
228 AbsoluteDate date = initDate.shiftedBy(400);
229 PVCoordinates atSouth = new PVCoordinates(new Vector3D(0.0, 0.0, -8.0e6),
230 new Vector3D(-8.0e3, 0.0, 0.0));
231 Transform t = LOFType.ENU.transformFromInertial(date, atSouth).getInverse();
232 Assertions.assertEquals(0, Vector3D.angle(Vector3D.PLUS_J, t.transformVector(Vector3D.PLUS_I)), 3.0e-16);
233 Assertions.assertEquals(0, Vector3D.angle(Vector3D.PLUS_I, t.transformVector(Vector3D.PLUS_J)), 3.0e-16);
234 Assertions.assertEquals(0, Vector3D.angle(Vector3D.MINUS_K, t.transformVector(Vector3D.PLUS_K)), 3.0e-16);
235 }
236
237 @Test
238 public void testENUAtSouthPoleField() {
239 final Field<Binary64> field = Binary64Field.getInstance();
240 FieldAbsoluteDate<Binary64> date = new FieldAbsoluteDate<>(field, initDate.shiftedBy(400));
241 FieldPVCoordinates<Binary64> atSouth = new FieldPVCoordinates<>(new FieldVector3D<>(new Binary64(0.0),
242 new Binary64(0.0),
243 new Binary64(-8.0e6)),
244 new FieldVector3D<>(new Binary64(-8.0e3),
245 new Binary64(0.0),
246 new Binary64(0.0)));
247 FieldTransform<Binary64> t = LOFType.ENU.transformFromInertial(date, atSouth).getInverse();
248 FieldVector3D<Binary64> pI = FieldVector3D.getPlusI(field);
249 FieldVector3D<Binary64> pJ = FieldVector3D.getPlusJ(field);
250 FieldVector3D<Binary64> pK = FieldVector3D.getPlusK(field);
251 FieldVector3D<Binary64> mK = FieldVector3D.getMinusK(field);
252 Assertions.assertEquals(0, FieldVector3D.angle(pJ, t.transformVector(pI)).getReal(), 3.0e-16);
253 Assertions.assertEquals(0, FieldVector3D.angle(pI, t.transformVector(pJ)).getReal(), 3.0e-16);
254 Assertions.assertEquals(0, FieldVector3D.angle(mK, t.transformVector(pK)).getReal(), 3.0e-16);
255 }
256
257 @Test
258 public void testNED() {
259 AbsoluteDate date = initDate.shiftedBy(400);
260 PVCoordinates pv = provider.getPVCoordinates(date, inertialFrame);
261 Transform t = LOFType.NED.transformFromInertial(date, pv).getInverse();
262 Assertions.assertNull(LOFType.NED.toOrbitRelativeFrame());
263
264
265 Assertions.assertEquals(0.0,
266 Vector3D.angle(t.transformVector(Vector3D.PLUS_K), pv.getPosition().negate()),
267 2.0e-16);
268
269
270 Vector3D northPole = t.getInverse().transformVector(Vector3D.PLUS_K);
271 Assertions.assertEquals(0.0, northPole.getY(), 2.0e-16);
272 Assertions.assertTrue(northPole.getX() > 0.0);
273
274 }
275
276 @Test
277 public void testNEDField() {
278 final Field<Binary64> field = Binary64Field.getInstance();
279 FieldAbsoluteDate<Binary64> date = new FieldAbsoluteDate<>(field, initDate.shiftedBy(400));
280 FieldPVCoordinates<Binary64> pv = new FieldPVCoordinates<>(field,
281 provider.getPVCoordinates(date.toAbsoluteDate(),
282 inertialFrame));
283 FieldTransform<Binary64> t = LOFType.NED.transformFromInertial(date, pv).getInverse();
284 FieldVector3D<Binary64> pK = FieldVector3D.getPlusK(field);
285
286
287 Assertions.assertEquals(0.0,
288 FieldVector3D.angle(t.transformVector(pK), pv.getPosition().negate()).getReal(),
289 2.0e-16);
290
291
292 FieldVector3D<Binary64> northPole = t.getInverse().transformVector(pK);
293 Assertions.assertEquals(0.0, northPole.getY().getReal(), 2.0e-16);
294 Assertions.assertTrue(northPole.getX().getReal() > 0.0);
295
296 }
297
298 @Test
299 public void testNEDAtNorthPole() {
300 AbsoluteDate date = initDate.shiftedBy(400);
301 PVCoordinates atNorth = new PVCoordinates(new Vector3D(0.0, 0.0, 8.0e6),
302 new Vector3D(8.0e3, 0.0, 0.0));
303 Transform t = LOFType.NED.transformFromInertial(date, atNorth).getInverse();
304 Assertions.assertEquals(0, Vector3D.angle(Vector3D.MINUS_I, t.transformVector(Vector3D.PLUS_I)), 3.0e-16);
305 Assertions.assertEquals(0, Vector3D.angle(Vector3D.PLUS_J, t.transformVector(Vector3D.PLUS_J)), 3.0e-16);
306 Assertions.assertEquals(0, Vector3D.angle(Vector3D.MINUS_K, t.transformVector(Vector3D.PLUS_K)), 3.0e-16);
307 }
308
309 @Test
310 public void testNEDAtNorthPoleField() {
311 final Field<Binary64> field = Binary64Field.getInstance();
312 FieldAbsoluteDate<Binary64> date = new FieldAbsoluteDate<>(field, initDate.shiftedBy(400));
313 FieldPVCoordinates<Binary64> atNorth = new FieldPVCoordinates<>(new FieldVector3D<>(new Binary64(0.0),
314 new Binary64(0.0),
315 new Binary64(8.0e6)),
316 new FieldVector3D<>(new Binary64(8.0e3),
317 new Binary64(0.0),
318 new Binary64(0.0)));
319 FieldTransform<Binary64> t = LOFType.NED.transformFromInertial(date, atNorth).getInverse();
320 FieldVector3D<Binary64> pI = FieldVector3D.getPlusI(field);
321 FieldVector3D<Binary64> mI = FieldVector3D.getMinusI(field);
322 FieldVector3D<Binary64> pJ = FieldVector3D.getPlusJ(field);
323 FieldVector3D<Binary64> pK = FieldVector3D.getPlusK(field);
324 FieldVector3D<Binary64> mK = FieldVector3D.getMinusK(field);
325 Assertions.assertEquals(0, FieldVector3D.angle(mI, t.transformVector(pI)).getReal(), 3.0e-16);
326 Assertions.assertEquals(0, FieldVector3D.angle(pJ, t.transformVector(pJ)).getReal(), 3.0e-16);
327 Assertions.assertEquals(0, FieldVector3D.angle(mK, t.transformVector(pK)).getReal(), 3.0e-16);
328 }
329
330 @Test
331 public void testNEDAtSouthPole() {
332 AbsoluteDate date = initDate.shiftedBy(400);
333 PVCoordinates atSouth = new PVCoordinates(new Vector3D(0.0, 0.0, -8.0e6),
334 new Vector3D(-8.0e3, 0.0, 0.0));
335 Transform t = LOFType.NED.transformFromInertial(date, atSouth).getInverse();
336 Assertions.assertEquals(0, Vector3D.angle(Vector3D.PLUS_I, t.transformVector(Vector3D.PLUS_I)), 3.0e-16);
337 Assertions.assertEquals(0, Vector3D.angle(Vector3D.PLUS_J, t.transformVector(Vector3D.PLUS_J)), 3.0e-16);
338 Assertions.assertEquals(0, Vector3D.angle(Vector3D.PLUS_K, t.transformVector(Vector3D.PLUS_K)), 3.0e-16);
339 }
340
341 @Test
342 public void testNEDAtSouthPoleField() {
343 final Field<Binary64> field = Binary64Field.getInstance();
344 FieldAbsoluteDate<Binary64> date = new FieldAbsoluteDate<>(field, initDate.shiftedBy(400));
345 FieldPVCoordinates<Binary64> atSouth = new FieldPVCoordinates<>(new FieldVector3D<>(new Binary64(0.0),
346 new Binary64(0.0),
347 new Binary64(-8.0e6)),
348 new FieldVector3D<>(new Binary64(-8.0e3),
349 new Binary64(0.0),
350 new Binary64(0.0)));
351 FieldTransform<Binary64> t = LOFType.NED.transformFromInertial(date, atSouth).getInverse();
352 FieldVector3D<Binary64> pI = FieldVector3D.getPlusI(field);
353 FieldVector3D<Binary64> pJ = FieldVector3D.getPlusJ(field);
354 FieldVector3D<Binary64> pK = FieldVector3D.getPlusK(field);
355 Assertions.assertEquals(0, FieldVector3D.angle(pI, t.transformVector(pI)).getReal(), 3.0e-16);
356 Assertions.assertEquals(0, FieldVector3D.angle(pJ, t.transformVector(pJ)).getReal(), 3.0e-16);
357 Assertions.assertEquals(0, FieldVector3D.angle(pK, t.transformVector(pK)).getReal(), 3.0e-16);
358 }
359
360 @Test
361 @DisplayName("Test transformFromLOFInToLOFOut method")
362 void should_return_expected_transform_from_LOFIn_To_LOFOut() {
363
364 final AbsoluteDate date = new AbsoluteDate();
365 final PVCoordinates pv = new PVCoordinates(new Vector3D(6378000 + 400000, 0, 0),
366 new Vector3D(0, 7669, 0));
367
368
369 final Transform transformFromTNWToQSW = LOF.transformFromLOFInToLOFOut(LOFType.TNW, LOFType.QSW, date, pv);
370 final Transform transformFromQSWToNTW = LOF.transformFromLOFInToLOFOut(LOFType.QSW, LOFType.NTW, date, pv);
371 final Transform transformFromNTWToTNW = LOF.transformFromLOFInToLOFOut(LOFType.NTW, LOFType.TNW, date, pv);
372 final Transform composedTransform = composeTransform(date,
373 transformFromTNWToQSW,
374 transformFromQSWToNTW,
375 transformFromNTWToTNW);
376
377 final Vector3D computedTranslation = composedTransform.getTranslation();
378 final BlockRealMatrix computedRotation = new BlockRealMatrix(composedTransform.getRotation().getMatrix());
379
380
381 final Vector3D expectedTranslation = new Vector3D(0, 0, 0);
382 final RealMatrix expectedRotation = MatrixUtils.createRealIdentityMatrix(3);
383
384 TestUtils.validateVector3D(expectedTranslation, computedTranslation, 1e-15);
385 TestUtils.validateRealMatrix(expectedRotation, computedRotation, 1e-15);
386
387 }
388
389 @Test
390 @DisplayName("Test transformFromLOFInToLOFOut (field version) method")
391 void should_return_expected_field_transform_from_LOFIn_To_LOFOut() {
392
393 final Field<Binary64> field = Binary64Field.getInstance();
394 final FieldAbsoluteDate<Binary64> date = new FieldAbsoluteDate<>(field);
395 final FieldPVCoordinates<Binary64> pv =
396 new FieldPVCoordinates<>(new FieldVector3D<>(new Binary64(6378000 + 400000),
397 new Binary64(0),
398 new Binary64(0)),
399 new FieldVector3D<>(new Binary64(0),
400 new Binary64(7669),
401 new Binary64(0)));
402
403
404 final FieldTransform<Binary64> transformFromTNWToQSW =
405 LOF.transformFromLOFInToLOFOut(LOFType.TNW, LOFType.QSW, date, pv);
406 final FieldTransform<Binary64> transformFromQSWToNTW =
407 LOF.transformFromLOFInToLOFOut(LOFType.QSW, LOFType.NTW, date, pv);
408 final FieldTransform<Binary64> transformFromNTWToTNW =
409 LOF.transformFromLOFInToLOFOut(LOFType.NTW, LOFType.TNW, date, pv);
410 final FieldTransform<Binary64> composedTransform = composeFieldTransform(date,
411 transformFromTNWToQSW,
412 transformFromQSWToNTW,
413 transformFromNTWToTNW);
414
415 final FieldVector3D<Binary64> computedTranslation = composedTransform.getTranslation();
416 final BlockFieldMatrix<Binary64> computedRotation =
417 new BlockFieldMatrix<>(composedTransform.getRotation().getMatrix());
418
419
420 final Vector3D expectedTranslation = new Vector3D(0, 0, 0);
421 final RealMatrix expectedRotation = MatrixUtils.createRealIdentityMatrix(3);
422
423 TestUtils.validateFieldVector3D(expectedTranslation, computedTranslation, 1e-15);
424 TestUtils.validateFieldMatrix(expectedRotation, computedRotation, 1e-15);
425
426 }
427
428 @Test
429 @DisplayName("Test transformFromInertial method")
430 void should_return_expected_transform_from_inertial() {
431
432 final AbsoluteDate date = new AbsoluteDate();
433 final PVCoordinates pv = new PVCoordinates(new Vector3D(6378000 + 400000, 0, 0),
434 new Vector3D(0, 7669, 0));
435
436
437 final Transform transformFromInertialToLOF = LOFType.TNW.transformFromInertial(date, pv);
438 final Vector3D computedTranslation = transformFromInertialToLOF.getTranslation();
439 final RealMatrix computedRotation =
440 new BlockRealMatrix(transformFromInertialToLOF.getRotation().getMatrix());
441
442
443 final Vector3D expectedTranslation = new Vector3D(-(6378000 + 400000), 0, 0);
444 final RealMatrix expectedRotation = new BlockRealMatrix(new double[][] {
445 { 0, 1, 0 },
446 { -1, 0, 0 },
447 { 0, 0, 1 }
448 });
449
450 TestUtils.validateVector3D(expectedTranslation, computedTranslation, 1e-15);
451 TestUtils.validateRealMatrix(expectedRotation, computedRotation, 1e-15);
452
453 }
454
455 @Test
456 @DisplayName("Test transformFromInertial (field version) method")
457 void should_return_expected_field_transform_from_inertial() {
458
459 final Field<Binary64> field = Binary64Field.getInstance();
460 final FieldAbsoluteDate<Binary64> date = new FieldAbsoluteDate<>(field);
461 final FieldPVCoordinates<Binary64> pv =
462 new FieldPVCoordinates<>(new FieldVector3D<>(new Binary64(6378000 + 400000),
463 new Binary64(0),
464 new Binary64(0)),
465 new FieldVector3D<>(new Binary64(0),
466 new Binary64(7669),
467 new Binary64(0)));
468
469
470 final FieldTransform<Binary64> transformFromInertialToLOF = LOFType.TNW.transformFromInertial(date, pv);
471 final FieldVector3D<Binary64> computedTranslation = transformFromInertialToLOF.getTranslation();
472 final BlockFieldMatrix<Binary64> computedRotation =
473 new BlockFieldMatrix<>(transformFromInertialToLOF.getRotation().getMatrix());
474
475
476 final Vector3D expectedTranslation = new Vector3D(-(6378000 + 400000), 0, 0);
477 final RealMatrix expectedRotation = new BlockRealMatrix(new double[][] {
478 { 0, 1, 0 },
479 { -1, 0, 0 },
480 { 0, 0, 1 }
481 });
482
483 TestUtils.validateFieldVector3D(expectedTranslation, computedTranslation, 1e-15);
484 TestUtils.validateFieldMatrix(expectedRotation, computedRotation, 1e-15);
485
486 }
487
488 @Test
489 @DisplayName("Test all rotation methods using default method of the interface")
490 void should_return_initial_value_after_multiple_rotations_default_method() {
491
492 final AbsoluteDate arbitraryEpoch = AbsoluteDate.ARBITRARY_EPOCH;
493 final PVCoordinates pv = new PVCoordinates(new Vector3D(6378000 + 400000, 0, 0),
494 new Vector3D(0, 5422.8, 5422.8));
495
496
497 final Rotation rotationFromTNWToTNWInertial =
498 LOFType.TNW_INERTIAL.rotationFromLOF(LOFType.TNW, arbitraryEpoch, pv);
499
500 final Rotation rotationFromTNWInertialToQSW =
501 LOFType.QSW.rotationFromLOF(LOFType.TNW_INERTIAL, arbitraryEpoch, pv);
502
503 final Rotation rotationFromQSWToQSWInertial =
504 LOFType.QSW_INERTIAL.rotationFromLOF(LOFType.QSW, arbitraryEpoch, pv);
505
506 final Rotation rotationFromQSWInertialToLVLH =
507 LOFType.LVLH.rotationFromLOF(LOFType.QSW_INERTIAL, arbitraryEpoch, pv);
508
509 final Rotation rotationFromLVLHToLVLHInertial =
510 LOFType.LVLH_INERTIAL.rotationFromLOF(LOFType.LVLH, arbitraryEpoch, pv);
511
512 final Rotation rotationFromLVLHInertialToLVLH_CCSDS =
513 LOFType.LVLH_CCSDS.rotationFromLOF(LOFType.LVLH_INERTIAL, arbitraryEpoch, pv);
514
515 final Rotation rotationFromLVLH_CCSDSToLVLH_CCSDSInertial =
516 LOFType.LVLH_CCSDS_INERTIAL.rotationFromLOF(LOFType.LVLH_CCSDS, arbitraryEpoch, pv);
517
518 final Rotation rotationFromLVLH_CCSDSInertialToVVLH =
519 LOFType.VVLH.rotationFromLOF(LOFType.LVLH_CCSDS_INERTIAL, arbitraryEpoch, pv);
520
521 final Rotation rotationFromVVLHToVVLHInertial =
522 LOFType.VVLH_INERTIAL.rotationFromLOF(LOFType.VVLH, arbitraryEpoch, pv);
523
524 final Rotation rotationFromVVLHInertialToVNC =
525 LOFType.VNC.rotationFromLOF(LOFType.VVLH_INERTIAL, arbitraryEpoch, pv);
526
527 final Rotation rotationFromVNCToVNCInertial =
528 LOFType.VNC_INERTIAL.rotationFromLOF(LOFType.VNC, arbitraryEpoch, pv);
529
530 final Rotation rotationFromVNCInertialToNTW =
531 LOFType.NTW.rotationFromLOF(LOFType.VNC_INERTIAL, arbitraryEpoch, pv);
532
533 final Rotation rotationFromNTWToNTWInertial =
534 LOFType.NTW_INERTIAL.rotationFromLOF(LOFType.NTW, arbitraryEpoch, pv);
535
536 final Rotation rotationFromNTWInertialToEQW =
537 LOFType.EQW.rotationFromLOF(LOFType.NTW_INERTIAL, arbitraryEpoch, pv);
538
539 final Rotation rotationFromEQWToENU =
540 LOFType.ENU.rotationFromLOF(LOFType.EQW, arbitraryEpoch, pv);
541
542 final Rotation rotationFromENUToNED =
543 LOFType.NED.rotationFromLOF(LOFType.ENU, arbitraryEpoch, pv);
544
545 final Rotation rotationFromNEDToTNW =
546 LOF.rotationFromLOFInToLOFOut(LOFType.NED, LOFType.TNW, arbitraryEpoch, pv);
547
548 final Rotation rotationFromTNWToTNW =
549 composeRotations(rotationFromTNWToTNWInertial,
550 rotationFromTNWInertialToQSW,
551 rotationFromQSWToQSWInertial,
552 rotationFromQSWInertialToLVLH,
553 rotationFromLVLHToLVLHInertial,
554 rotationFromLVLHInertialToLVLH_CCSDS,
555 rotationFromLVLH_CCSDSToLVLH_CCSDSInertial,
556 rotationFromLVLH_CCSDSInertialToVVLH,
557 rotationFromVVLHToVVLHInertial,
558 rotationFromVVLHInertialToVNC,
559 rotationFromVNCToVNCInertial,
560 rotationFromVNCInertialToNTW,
561 rotationFromNTWToNTWInertial,
562 rotationFromNTWInertialToEQW,
563 rotationFromEQWToENU,
564 rotationFromENUToNED,
565 rotationFromNEDToTNW);
566
567 final RealMatrix rotationMatrixFromTNWToTNW =
568 new BlockRealMatrix(rotationFromTNWToTNW.getMatrix());
569
570
571 final RealMatrix identityMatrix = MatrixUtils.createRealIdentityMatrix(3);
572
573 TestUtils.validateRealMatrix(identityMatrix, rotationMatrixFromTNWToTNW, 1e-15);
574
575 }
576
577 @Test
578 @DisplayName("Test all rotation methods (field version) using default method of the interface")
579 void should_return_initial_value_after_multiple_field_rotations_default_method() {
580
581 final Binary64Field field = Binary64Field.getInstance();
582 final FieldAbsoluteDate<Binary64> arbitraryEpoch = new FieldAbsoluteDate<>(field, AbsoluteDate.ARBITRARY_EPOCH);
583 final FieldPVCoordinates<Binary64> pv =
584 new FieldPVCoordinates<>(new FieldVector3D<>(new Binary64(6378000 + 400000),
585 new Binary64(0),
586 new Binary64(0)),
587 new FieldVector3D<>(new Binary64(0),
588 new Binary64(5422.8),
589 new Binary64(5422.8)));
590
591
592 final FieldRotation<Binary64> rotationFromTNWToTNWInertial =
593 LOFType.TNW_INERTIAL.rotationFromLOF(field, LOFType.TNW, arbitraryEpoch, pv);
594
595 final FieldRotation<Binary64> rotationFromTNWInertialToQSW =
596 LOFType.QSW.rotationFromLOF(field, LOFType.TNW_INERTIAL, arbitraryEpoch, pv);
597
598 final FieldRotation<Binary64> rotationFromQSWToQSWInertial =
599 LOFType.QSW_INERTIAL.rotationFromLOF(field, LOFType.QSW, arbitraryEpoch, pv);
600
601 final FieldRotation<Binary64> rotationFromQSWInertialToLVLH =
602 LOFType.LVLH.rotationFromLOF(field, LOFType.QSW_INERTIAL, arbitraryEpoch, pv);
603
604 final FieldRotation<Binary64> rotationFromLVLHToLVLHInertial =
605 LOFType.LVLH_INERTIAL.rotationFromLOF(field, LOFType.LVLH, arbitraryEpoch, pv);
606
607 final FieldRotation<Binary64> rotationFromLVLHInertialToLVLH_CCSDS =
608 LOFType.LVLH_CCSDS.rotationFromLOF(field, LOFType.LVLH_INERTIAL, arbitraryEpoch, pv);
609
610 final FieldRotation<Binary64> rotationFromLVLH_CCSDSToLVLH_CCSDSInertial =
611 LOFType.LVLH_CCSDS_INERTIAL.rotationFromLOF(field, LOFType.LVLH_CCSDS, arbitraryEpoch, pv);
612
613 final FieldRotation<Binary64> rotationFromLVLH_CCSDSInertialToVVLH =
614 LOFType.VVLH.rotationFromLOF(field, LOFType.LVLH_CCSDS_INERTIAL, arbitraryEpoch, pv);
615
616 final FieldRotation<Binary64> rotationFromVVLHToVVLHInertial =
617 LOFType.VVLH_INERTIAL.rotationFromLOF(field, LOFType.VVLH, arbitraryEpoch, pv);
618
619 final FieldRotation<Binary64> rotationFromVVLHInertialToVNC =
620 LOFType.VNC.rotationFromLOF(field, LOFType.VVLH_INERTIAL, arbitraryEpoch, pv);
621
622 final FieldRotation<Binary64> rotationFromVNCToVNCInertial =
623 LOFType.VNC_INERTIAL.rotationFromLOF(field, LOFType.VNC, arbitraryEpoch, pv);
624
625 final FieldRotation<Binary64> rotationFromVNCInertialToNTW =
626 LOFType.NTW.rotationFromLOF(field, LOFType.VNC_INERTIAL, arbitraryEpoch, pv);
627
628 final FieldRotation<Binary64> rotationFromNTWToNTWInertial =
629 LOFType.NTW_INERTIAL.rotationFromLOF(field, LOFType.NTW, arbitraryEpoch, pv);
630
631 final FieldRotation<Binary64> rotationFromNTWInertialToEQW =
632 LOFType.EQW.rotationFromLOF(field, LOFType.NTW_INERTIAL, arbitraryEpoch, pv);
633
634 final FieldRotation<Binary64> rotationFromEQWToENU =
635 LOFType.ENU.rotationFromLOF(field, LOFType.EQW, arbitraryEpoch, pv);
636
637 final FieldRotation<Binary64> rotationFromENUToNED =
638 LOFType.NED.rotationFromLOF(field, LOFType.ENU, arbitraryEpoch, pv);
639
640 final FieldRotation<Binary64> rotationFromNEDToTNW =
641 LOF.rotationFromLOFInToLOFOut(field, LOFType.NED, LOFType.TNW, arbitraryEpoch, pv);
642
643 final FieldRotation<Binary64> rotationFromTNWToTNW =
644 composeFieldRotations(rotationFromTNWToTNWInertial,
645 rotationFromTNWInertialToQSW,
646 rotationFromQSWToQSWInertial,
647 rotationFromQSWInertialToLVLH,
648 rotationFromLVLHToLVLHInertial,
649 rotationFromLVLHInertialToLVLH_CCSDS,
650 rotationFromLVLH_CCSDSToLVLH_CCSDSInertial,
651 rotationFromLVLH_CCSDSInertialToVVLH,
652 rotationFromVVLHToVVLHInertial,
653 rotationFromVVLHInertialToVNC,
654 rotationFromVNCToVNCInertial,
655 rotationFromVNCInertialToNTW,
656 rotationFromNTWToNTWInertial,
657 rotationFromNTWInertialToEQW,
658 rotationFromEQWToENU,
659 rotationFromENUToNED,
660 rotationFromNEDToTNW);
661
662 final FieldMatrix<Binary64> rotationMatrixFromTNWToTNW =
663 new BlockFieldMatrix<>(rotationFromTNWToTNW.getMatrix());
664
665
666 final RealMatrix identityMatrix = MatrixUtils.createRealIdentityMatrix(3);
667
668 TestUtils.validateFieldMatrix(identityMatrix, rotationMatrixFromTNWToTNW, 1e-15);
669
670 }
671
672 @Test
673 @DisplayName("Test all rotation methods")
674 void should_return_initial_value_after_multiple_rotations() {
675
676 final PVCoordinates pv = new PVCoordinates(new Vector3D(6378000 + 400000, 0, 0),
677 new Vector3D(0, 5422.8, 5422.8));
678
679
680 final Rotation rotationFromTNWToTNWInertial =
681 LOFType.TNW_INERTIAL.rotationFromLOF(LOFType.TNW, pv);
682
683 final Rotation rotationFromTNWInertialToQSW =
684 LOFType.QSW.rotationFromLOF(LOFType.TNW_INERTIAL, pv);
685
686 final Rotation rotationFromQSWToQSWInertial =
687 LOFType.QSW_INERTIAL.rotationFromLOF(LOFType.QSW, pv);
688
689 final Rotation rotationFromQSWInertialToLVLH =
690 LOFType.LVLH.rotationFromLOF(LOFType.QSW_INERTIAL, pv);
691
692 final Rotation rotationFromLVLHToLVLHInertial =
693 LOFType.LVLH_INERTIAL.rotationFromLOF(LOFType.LVLH, pv);
694
695 final Rotation rotationFromLVLHInertialToLVLH_CCSDS =
696 LOFType.LVLH_CCSDS.rotationFromLOF(LOFType.LVLH_INERTIAL, pv);
697
698 final Rotation rotationFromLVLH_CCSDSToLVLH_CCSDSInertial =
699 LOFType.LVLH_CCSDS_INERTIAL.rotationFromLOF(LOFType.LVLH_CCSDS, pv);
700
701 final Rotation rotationFromLVLH_CCSDSInertialToVVLH =
702 LOFType.VVLH.rotationFromLOF(LOFType.LVLH_CCSDS_INERTIAL, pv);
703
704 final Rotation rotationFromVVLHToVVLHInertial =
705 LOFType.VVLH_INERTIAL.rotationFromLOF(LOFType.VVLH, pv);
706
707 final Rotation rotationFromVVLHInertialToVNC =
708 LOFType.VNC.rotationFromLOF(LOFType.VVLH_INERTIAL, pv);
709
710 final Rotation rotationFromVNCToVNCInertial =
711 LOFType.VNC_INERTIAL.rotationFromLOF(LOFType.VNC, pv);
712
713 final Rotation rotationFromVNCInertialToNTW =
714 LOFType.NTW.rotationFromLOF(LOFType.VNC_INERTIAL, pv);
715
716 final Rotation rotationFromNTWToNTWInertial =
717 LOFType.NTW_INERTIAL.rotationFromLOF(LOFType.NTW, pv);
718
719 final Rotation rotationFromNTWInertialToEQW =
720 LOFType.EQW.rotationFromLOF(LOFType.NTW_INERTIAL, pv);
721
722 final Rotation rotationFromEQWToENU =
723 LOFType.ENU.rotationFromLOF(LOFType.EQW, pv);
724
725 final Rotation rotationFromENUToNED =
726 LOFType.NED.rotationFromLOF(LOFType.ENU, pv);
727
728 final Rotation rotationFromNEDToTNW =
729 LOFType.rotationFromLOFInToLOFOut(LOFType.NED, LOFType.TNW, pv);
730
731 final Rotation rotationFromTNWToTNW =
732 composeRotations(rotationFromTNWToTNWInertial,
733 rotationFromTNWInertialToQSW,
734 rotationFromQSWToQSWInertial,
735 rotationFromQSWInertialToLVLH,
736 rotationFromLVLHToLVLHInertial,
737 rotationFromLVLHInertialToLVLH_CCSDS,
738 rotationFromLVLH_CCSDSToLVLH_CCSDSInertial,
739 rotationFromLVLH_CCSDSInertialToVVLH,
740 rotationFromVVLHToVVLHInertial,
741 rotationFromVVLHInertialToVNC,
742 rotationFromVNCToVNCInertial,
743 rotationFromVNCInertialToNTW,
744 rotationFromNTWToNTWInertial,
745 rotationFromNTWInertialToEQW,
746 rotationFromEQWToENU,
747 rotationFromENUToNED,
748 rotationFromNEDToTNW);
749
750 final RealMatrix rotationMatrixFromTNWToTNW =
751 new BlockRealMatrix(rotationFromTNWToTNW.getMatrix());
752
753
754 final RealMatrix identityMatrix = MatrixUtils.createRealIdentityMatrix(3);
755
756 TestUtils.validateRealMatrix(identityMatrix, rotationMatrixFromTNWToTNW, 1e-15);
757
758 }
759
760 @Test
761 @DisplayName("Test all rotation methods (field version)")
762 void should_return_initial_value_after_multiple_field_rotations() {
763
764 final Binary64Field field = Binary64Field.getInstance();
765 final FieldPVCoordinates<Binary64> pv =
766 new FieldPVCoordinates<>(new FieldVector3D<>(new Binary64(6378000 + 400000),
767 new Binary64(0),
768 new Binary64(0)),
769 new FieldVector3D<>(new Binary64(0),
770 new Binary64(5422.8),
771 new Binary64(5422.8)));
772
773
774 final FieldRotation<Binary64> rotationFromTNWToTNWInertial =
775 LOFType.TNW_INERTIAL.rotationFromLOF(field, LOFType.TNW, pv);
776
777 final FieldRotation<Binary64> rotationFromTNWInertialToQSW =
778 LOFType.QSW.rotationFromLOF(field, LOFType.TNW_INERTIAL, pv);
779
780 final FieldRotation<Binary64> rotationFromQSWToQSWInertial =
781 LOFType.QSW_INERTIAL.rotationFromLOF(field, LOFType.QSW, pv);
782
783 final FieldRotation<Binary64> rotationFromQSWInertialToLVLH =
784 LOFType.LVLH.rotationFromLOF(field, LOFType.QSW_INERTIAL, pv);
785
786 final FieldRotation<Binary64> rotationFromLVLHToLVLHInertial =
787 LOFType.LVLH_INERTIAL.rotationFromLOF(field, LOFType.LVLH, pv);
788
789 final FieldRotation<Binary64> rotationFromLVLHInertialToLVLH_CCSDS =
790 LOFType.LVLH_CCSDS.rotationFromLOF(field, LOFType.LVLH_INERTIAL, pv);
791
792 final FieldRotation<Binary64> rotationFromLVLH_CCSDSToLVLH_CCSDSInertial =
793 LOFType.LVLH_CCSDS_INERTIAL.rotationFromLOF(field, LOFType.LVLH_CCSDS, pv);
794
795 final FieldRotation<Binary64> rotationFromLVLH_CCSDSInertialToVVLH =
796 LOFType.VVLH.rotationFromLOF(field, LOFType.LVLH_CCSDS_INERTIAL, pv);
797
798 final FieldRotation<Binary64> rotationFromVVLHToVVLHInertial =
799 LOFType.VVLH_INERTIAL.rotationFromLOF(field, LOFType.VVLH, pv);
800
801 final FieldRotation<Binary64> rotationFromVVLHInertialToVNC =
802 LOFType.VNC.rotationFromLOF(field, LOFType.VVLH_INERTIAL, pv);
803
804 final FieldRotation<Binary64> rotationFromVNCToVNCInertial =
805 LOFType.VNC_INERTIAL.rotationFromLOF(field, LOFType.VNC, pv);
806
807 final FieldRotation<Binary64> rotationFromVNCInertialToNTW =
808 LOFType.NTW.rotationFromLOF(field, LOFType.VNC_INERTIAL, pv);
809
810 final FieldRotation<Binary64> rotationFromNTWToNTWInertial =
811 LOFType.NTW_INERTIAL.rotationFromLOF(field, LOFType.NTW, pv);
812
813 final FieldRotation<Binary64> rotationFromNTWInertialToEQW =
814 LOFType.EQW.rotationFromLOF(field, LOFType.NTW_INERTIAL, pv);
815
816 final FieldRotation<Binary64> rotationFromEQWToENU =
817 LOFType.ENU.rotationFromLOF(field, LOFType.EQW, pv);
818
819 final FieldRotation<Binary64> rotationFromENUToNED =
820 LOFType.NED.rotationFromLOF(field, LOFType.ENU, pv);
821
822 final FieldRotation<Binary64> rotationFromNEDToTNW =
823 LOFType.rotationFromLOFInToLOFOut(field, LOFType.NED, LOFType.TNW, pv);
824
825 final FieldRotation<Binary64> rotationFromTNWToTNW =
826 composeFieldRotations(rotationFromTNWToTNWInertial,
827 rotationFromTNWInertialToQSW,
828 rotationFromQSWToQSWInertial,
829 rotationFromQSWInertialToLVLH,
830 rotationFromLVLHToLVLHInertial,
831 rotationFromLVLHInertialToLVLH_CCSDS,
832 rotationFromLVLH_CCSDSToLVLH_CCSDSInertial,
833 rotationFromLVLH_CCSDSInertialToVVLH,
834 rotationFromVVLHToVVLHInertial,
835 rotationFromVVLHInertialToVNC,
836 rotationFromVNCToVNCInertial,
837 rotationFromVNCInertialToNTW,
838 rotationFromNTWToNTWInertial,
839 rotationFromNTWInertialToEQW,
840 rotationFromEQWToENU,
841 rotationFromENUToNED,
842 rotationFromNEDToTNW);
843
844 final FieldMatrix<Binary64> rotationMatrixFromTNWToTNW =
845 new BlockFieldMatrix<>(rotationFromTNWToTNW.getMatrix());
846
847
848 final RealMatrix identityMatrix = MatrixUtils.createRealIdentityMatrix(3);
849
850 TestUtils.validateFieldMatrix(identityMatrix, rotationMatrixFromTNWToTNW, 1e-15);
851
852 }
853
854 @Test
855 @DisplayName("Test isQuasiInertialMethod")
856 void should_return_expected_boolean() {
857
858
859 Assertions.assertTrue(LOFType.TNW_INERTIAL.isQuasiInertial());
860 Assertions.assertTrue(LOFType.NTW_INERTIAL.isQuasiInertial());
861 Assertions.assertTrue(LOFType.QSW_INERTIAL.isQuasiInertial());
862 Assertions.assertTrue(LOFType.VNC_INERTIAL.isQuasiInertial());
863 Assertions.assertTrue(LOFType.LVLH_INERTIAL.isQuasiInertial());
864 Assertions.assertTrue(LOFType.LVLH_CCSDS_INERTIAL.isQuasiInertial());
865 Assertions.assertTrue(LOFType.EQW.isQuasiInertial());
866 Assertions.assertTrue(LOFType.VVLH_INERTIAL.isQuasiInertial());
867
868
869 Assertions.assertFalse(LOFType.TNW.isQuasiInertial());
870 Assertions.assertFalse(LOFType.NTW.isQuasiInertial());
871 Assertions.assertFalse(LOFType.QSW.isQuasiInertial());
872 Assertions.assertFalse(LOFType.VNC.isQuasiInertial());
873 Assertions.assertFalse(LOFType.LVLH.isQuasiInertial());
874 Assertions.assertFalse(LOFType.LVLH_CCSDS.isQuasiInertial());
875 Assertions.assertFalse(LOFType.VVLH.isQuasiInertial());
876 Assertions.assertFalse(LOFType.ENU.isQuasiInertial());
877 Assertions.assertFalse(LOFType.NED.isQuasiInertial());
878
879 }
880
881 private Rotation composeRotations(final Rotation... rotations) {
882
883 Rotation composedRotations = null;
884
885 for (Rotation rotation : rotations) {
886 if (composedRotations == null) {
887 composedRotations = rotation;
888 }
889 else {
890 composedRotations = composedRotations.compose(rotation, RotationConvention.FRAME_TRANSFORM);
891 }
892 }
893
894 return composedRotations;
895 }
896
897 @SafeVarargs private final <T extends CalculusFieldElement<T>> FieldRotation<T> composeFieldRotations(
898 final FieldRotation<T>... rotations) {
899
900 FieldRotation<T> composedRotations = null;
901
902 for (FieldRotation<T> rotation : rotations) {
903 if (composedRotations == null) {
904 composedRotations = rotation;
905 }
906 else {
907 composedRotations = composedRotations.compose(rotation, RotationConvention.FRAME_TRANSFORM);
908 }
909 }
910
911 return composedRotations;
912 }
913
914 private Transform composeTransform(final AbsoluteDate date, final Transform... transforms){
915 Transform composedTransform = null;
916
917 for (Transform transform : transforms) {
918 if (composedTransform == null) {
919 composedTransform = transform;
920 }
921 else {
922 composedTransform = new Transform(date, composedTransform, transform);
923 }
924 }
925
926 return composedTransform;
927 }
928
929 @SafeVarargs
930 private final <T extends CalculusFieldElement<T>> FieldTransform<T> composeFieldTransform(
931 final FieldAbsoluteDate<T> date,
932 final FieldTransform<T>... transforms) {
933 FieldTransform<T> composedTransform = null;
934
935 for (FieldTransform<T> transform : transforms) {
936 if (composedTransform == null) {
937 composedTransform = transform;
938 }
939 else {
940 composedTransform = new FieldTransform<>(date, composedTransform, transform);
941 }
942 }
943
944 return composedTransform;
945 }
946
947 private void checkFrame(LOFType type, AbsoluteDate date,
948 Vector3D expectedXDirection, Vector3D expectedYDirection,
949 Vector3D expectedZDirection, Vector3D expectedRotationDirection) {
950 LocalOrbitalFrame lof = new LocalOrbitalFrame(FramesFactory.getGCRF(), type, provider, type.name());
951
952 Transform t = lof.getTransformTo(FramesFactory.getGCRF(), date);
953 PVCoordinates pv1 = t.transformPVCoordinates(PVCoordinates.ZERO);
954 Vector3D p1 = pv1.getPosition();
955 Vector3D v1 = pv1.getVelocity();
956 PVCoordinates pv2 = provider.getPVCoordinates(date, FramesFactory.getGCRF());
957 Vector3D p2 = pv2.getPosition();
958 Vector3D v2 = pv2.getVelocity();
959 Assertions.assertEquals(0, p1.subtract(p2).getNorm(), 1.0e-14 * p1.getNorm());
960 Assertions.assertEquals(0, v1.subtract(v2).getNorm(), 1.0e-14 * v1.getNorm());
961
962 Vector3D xDirection = t.transformVector(Vector3D.PLUS_I);
963 Vector3D yDirection = t.transformVector(Vector3D.PLUS_J);
964 Vector3D zDirection = t.transformVector(Vector3D.PLUS_K);
965 Assertions.assertEquals(0, Vector3D.angle(expectedXDirection, xDirection), 2.0e-15);
966 Assertions.assertEquals(0, Vector3D.angle(expectedYDirection, yDirection), 1.0e-15);
967 Assertions.assertEquals(0, Vector3D.angle(expectedZDirection, zDirection), 1.0e-15);
968 Assertions.assertEquals(0, Vector3D.angle(expectedRotationDirection, t.getRotationRate()), 1.0e-15);
969
970 Assertions.assertEquals(initialOrbit.getKeplerianMeanMotion(), t.getRotationRate().getNorm(), 1.0e-7);
971
972 }
973
974 @BeforeEach
975 public void setUp() {
976 inertialFrame = FramesFactory.getGCRF();
977 initDate = AbsoluteDate.J2000_EPOCH.shiftedBy(584.);
978 initialOrbit =
979 new KeplerianOrbit(7209668.0, 0.5e-4, 1.7, 2.1, 2.9, 6.2, PositionAngleType.TRUE,
980 inertialFrame, initDate, 3.986004415e14);
981 provider = new KeplerianPropagator(initialOrbit);
982
983 }
984
985 private Frame inertialFrame;
986 private AbsoluteDate initDate;
987 private Orbit initialOrbit;
988 private PVCoordinatesProvider provider;
989
990 }