1   /* Copyright 2002-2025 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  
18  package org.orekit.frames;
19  
20  import org.hipparchus.geometry.euclidean.threed.Rotation;
21  import org.hipparchus.geometry.euclidean.threed.Vector3D;
22  import org.junit.jupiter.api.Assertions;
23  import org.junit.jupiter.api.Test;
24  import org.orekit.time.AbsoluteDate;
25  import org.orekit.utils.PVCoordinates;
26  import org.orekit.utils.TimeStampedPVCoordinates;
27  
28  class KinematicTransformTest {
29  
30      @Test
31      void testCompositeVelocity() {
32          // GIVEN
33          final KinematicTransform kinematicTransform = createArbitraryKineticTransform();
34          // WHEN
35          final Vector3D actualCompositeVelocity = KinematicTransform.compositeVelocity(kinematicTransform,
36                  KinematicTransform.getIdentity());
37          // THEN
38          final Vector3D expectedCompositeVelocity = kinematicTransform.getVelocity();
39          Assertions.assertEquals(expectedCompositeVelocity, actualCompositeVelocity);
40      }
41  
42      @Test
43      void testCompositeRotationRate() {
44          // GIVEN
45          final KinematicTransform kinematicTransform = createArbitraryKineticTransform();
46          // WHEN
47          final Vector3D actualCompositeRotationRate = KinematicTransform.compositeRotationRate(kinematicTransform,
48                  KinematicTransform.getIdentity());
49          // THEN
50          final Vector3D expectedCompositeRotationRate = kinematicTransform.getRotationRate();
51          Assertions.assertEquals(expectedCompositeRotationRate, actualCompositeRotationRate);
52      }
53  
54      @Test
55      void testTransformPVOnly() {
56          // GIVEN
57          final KinematicTransform kinematicTransform = createArbitraryKineticTransform();
58          final PVCoordinates pvCoordinates = new PVCoordinates(new Vector3D(1, 2, 3), new Vector3D(4, 5, 6));
59          // WHEN
60          final PVCoordinates convertedPV = kinematicTransform.transformOnlyPV(pvCoordinates);
61          final PVCoordinates reconvertedPV = kinematicTransform.getInverse().transformOnlyPV(convertedPV);
62          // THEN
63          comparePVCoordinates(pvCoordinates, reconvertedPV);
64      }
65  
66      @Test
67      void testTransformTimeStampedPVCoordinatesWithoutA() {
68          // GIVEN
69          final KinematicTransform kinematicTransform = createArbitraryKineticTransform();
70          final TimeStampedPVCoordinates pvCoordinates = new TimeStampedPVCoordinates(AbsoluteDate.ARBITRARY_EPOCH,
71                  new Vector3D(1, 2, 3), new Vector3D(4, 5, 6));
72          // WHEN
73          final PVCoordinates convertedPV = kinematicTransform.transformOnlyPV(pvCoordinates);
74          final PVCoordinates reconvertedPV = kinematicTransform.getInverse().transformOnlyPV(convertedPV);
75          // THEN
76          comparePVCoordinates(pvCoordinates, reconvertedPV);
77      }
78  
79      private void comparePVCoordinates(final PVCoordinates pvCoordinates, final PVCoordinates reconvertedPV) {
80          final double tolerance = 1e-10;
81          final double[] expectedPosition = pvCoordinates.getPosition().toArray();
82          final double[] actualPosition = reconvertedPV.getPosition().toArray();
83          final double[] expectedVelocity = pvCoordinates.getVelocity().toArray();
84          final double[] actualVelocity = reconvertedPV.getVelocity().toArray();
85          for (int i = 0; i < 3; i++) {
86              Assertions.assertEquals(expectedPosition[i], actualPosition[i], tolerance);
87              Assertions.assertEquals(expectedVelocity[i], actualVelocity[i], tolerance);
88          }
89      }
90  
91      @Test
92      void testOfWithoutRotation() {
93          // GIVEN
94          final AbsoluteDate expectedDate = AbsoluteDate.ARBITRARY_EPOCH;
95          final PVCoordinates pvCoordinates = new PVCoordinates(Vector3D.MINUS_I, Vector3D.PLUS_J);
96          // WHEN
97          final KinematicTransform kinematicTransform = KinematicTransform.of(expectedDate, pvCoordinates);
98          // THEN
99          Assertions.assertEquals(expectedDate, kinematicTransform.getDate());
100         Assertions.assertEquals(pvCoordinates.getPosition(), kinematicTransform.getTranslation());
101         Assertions.assertEquals(pvCoordinates.getVelocity(), kinematicTransform.getVelocity());
102         Assertions.assertEquals(0., Rotation.distance(Rotation.IDENTITY, kinematicTransform.getRotation()));
103         Assertions.assertEquals(Vector3D.ZERO, kinematicTransform.getRotationRate());
104     }
105 
106     @Test
107     void testOfTranslation() {
108         final AbsoluteDate expectedDate = AbsoluteDate.ARBITRARY_EPOCH;
109         final Rotation expectedRotation = new Rotation(Vector3D.MINUS_K, Vector3D.PLUS_I);
110         final Vector3D expectedRotationRate = Vector3D.MINUS_J;
111         // WHEN
112         final KinematicTransform kinematicTransform = KinematicTransform.of(expectedDate, expectedRotation,
113                 expectedRotationRate);
114         // THEN
115         Assertions.assertEquals(expectedDate, kinematicTransform.getDate());
116         Assertions.assertEquals(Vector3D.ZERO, kinematicTransform.getTranslation());
117         Assertions.assertEquals(Vector3D.ZERO, kinematicTransform.getVelocity());
118         Assertions.assertEquals(0., Rotation.distance(expectedRotation, kinematicTransform.getRotation()));
119         Assertions.assertEquals(expectedRotationRate, kinematicTransform.getRotationRate());
120     }
121 
122     @Test
123     void testOfInverse() {
124         final KinematicTransform kinematicTransform = createArbitraryKineticTransform();
125         // WHEN
126         final KinematicTransform inverseKinematicTransform = kinematicTransform.getInverse();
127         final KinematicTransform composedTransform = KinematicTransform.compose(kinematicTransform.getDate(),
128                 kinematicTransform, inverseKinematicTransform);
129         // THEN
130         Assertions.assertEquals(kinematicTransform.getDate(), composedTransform.getDate());
131         Assertions.assertEquals(Vector3D.ZERO, composedTransform.getTranslation());
132         Assertions.assertEquals(Vector3D.ZERO, composedTransform.getVelocity());
133         Assertions.assertEquals(0., Rotation.distance(Rotation.IDENTITY, composedTransform.getRotation()));
134         Assertions.assertEquals(Vector3D.ZERO, composedTransform.getRotationRate());
135     }
136 
137     private KinematicTransform createArbitraryKineticTransform() {
138         return KinematicTransform.of(AbsoluteDate.ARBITRARY_EPOCH, new PVCoordinates(Vector3D.MINUS_I, Vector3D.PLUS_J),
139                 new Rotation(Vector3D.MINUS_K, Vector3D.PLUS_I), Vector3D.MINUS_J);
140     }
141 
142 }