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  package org.orekit.files.ccsds.definitions;
18  
19  import org.junit.jupiter.api.Assertions;
20  import org.junit.jupiter.api.DisplayName;
21  import org.junit.jupiter.api.Test;
22  import org.orekit.errors.OrekitException;
23  import org.orekit.frames.LOFType;
24  
25  class OrbitRelativeFrameTest {
26      @Test
27      @DisplayName("Test OrbitRelativeFrame definitions and their LOFType equivalent")
28      void testOrbitRelativeFrameDefinitionsAndLOFTypeEquivalent() {
29          // Given
30          final OrbitRelativeFrame eqwInertial  = OrbitRelativeFrame.EQW_INERTIAL;
31          final OrbitRelativeFrame lvlhRotating = OrbitRelativeFrame.LVLH_ROTATING;
32          final OrbitRelativeFrame lvlhInertial = OrbitRelativeFrame.LVLH_INERTIAL;
33          final OrbitRelativeFrame lvlh         = OrbitRelativeFrame.LVLH;
34          final OrbitRelativeFrame nswRotating  = OrbitRelativeFrame.NSW_ROTATING;
35          final OrbitRelativeFrame nswInertial  = OrbitRelativeFrame.NSW_INERTIAL;
36          final OrbitRelativeFrame ntwRotating  = OrbitRelativeFrame.NTW_ROTATING;
37          final OrbitRelativeFrame ntwInertial  = OrbitRelativeFrame.NTW_INERTIAL;
38          final OrbitRelativeFrame pqwInertial  = OrbitRelativeFrame.PQW_INERTIAL;
39          final OrbitRelativeFrame rswRotating  = OrbitRelativeFrame.RSW_ROTATING;
40          final OrbitRelativeFrame rswInertial  = OrbitRelativeFrame.RSW_INERTIAL;
41          final OrbitRelativeFrame rsw          = OrbitRelativeFrame.RSW;
42          final OrbitRelativeFrame ric          = OrbitRelativeFrame.RIC;
43          final OrbitRelativeFrame rtn          = OrbitRelativeFrame.RTN;
44          final OrbitRelativeFrame qsw          = OrbitRelativeFrame.QSW;
45          final OrbitRelativeFrame tnwRotating  = OrbitRelativeFrame.TNW_ROTATING;
46          final OrbitRelativeFrame tnwInertial  = OrbitRelativeFrame.TNW_INERTIAL;
47          final OrbitRelativeFrame tnw          = OrbitRelativeFrame.TNW;
48          final OrbitRelativeFrame sezRotating  = OrbitRelativeFrame.SEZ_ROTATING;
49          final OrbitRelativeFrame sezInertial  = OrbitRelativeFrame.SEZ_INERTIAL;
50          final OrbitRelativeFrame vncRotating  = OrbitRelativeFrame.VNC_ROTATING;
51          final OrbitRelativeFrame vncInertial  = OrbitRelativeFrame.VNC_INERTIAL;
52  
53          // When
54          final LOFType eqwInertialLOF  = eqwInertial.getLofType();
55          final LOFType lvlhRotatingLOF = lvlhRotating.getLofType();
56          final LOFType lvlhInertialLOF = lvlhInertial.getLofType();
57          final LOFType lvlhLOF         = lvlh.getLofType();
58          final LOFType nswRotatingLOF  = nswRotating.getLofType();
59          final LOFType nswInertialLOF  = nswInertial.getLofType();
60          final LOFType ntwRotatingLOF  = ntwRotating.getLofType();
61          final LOFType ntwInertialLOF  = ntwInertial.getLofType();
62          final LOFType pqwInertialLOF  = pqwInertial.getLofType();
63          final LOFType rswRotatingLOF  = rswRotating.getLofType();
64          final LOFType rswInertialLOF  = rswInertial.getLofType();
65          final LOFType rswLOF          = rsw.getLofType();
66          final LOFType ricLOF          = ric.getLofType();
67          final LOFType rtnLOF          = rtn.getLofType();
68          final LOFType qswLOF          = qsw.getLofType();
69          final LOFType tnwRotatingLOF  = tnwRotating.getLofType();
70          final LOFType tnwInertialLOF  = tnwInertial.getLofType();
71          final LOFType tnwLOF          = tnw.getLofType();
72          final LOFType sezRotatingLOF  = sezRotating.getLofType();
73          final LOFType sezInertialLOF  = sezInertial.getLofType();
74          final LOFType vncRotatingLOF  = vncRotating.getLofType();
75          final LOFType vncInertialLOF  = vncInertial.getLofType();
76  
77          // Then
78          Assertions.assertEquals(eqwInertialLOF.isQuasiInertial(), eqwInertialLOF.isQuasiInertial());
79          Assertions.assertEquals(lvlhRotating.isQuasiInertial(), lvlhRotatingLOF.isQuasiInertial());
80          Assertions.assertEquals(lvlhInertial.isQuasiInertial(), lvlhInertialLOF.isQuasiInertial());
81          Assertions.assertEquals(lvlh.isQuasiInertial(), lvlhLOF.isQuasiInertial());
82          Assertions.assertNull(nswRotatingLOF);
83          Assertions.assertNull(nswInertialLOF);
84          Assertions.assertEquals(ntwRotating.isQuasiInertial(), ntwRotatingLOF.isQuasiInertial());
85          Assertions.assertEquals(ntwInertialLOF.isQuasiInertial(), ntwInertialLOF.isQuasiInertial());
86          Assertions.assertNull(pqwInertialLOF);
87          Assertions.assertEquals(rswRotating.isQuasiInertial(), rswRotatingLOF.isQuasiInertial());
88          Assertions.assertEquals(rswInertial.isQuasiInertial(), rswInertialLOF.isQuasiInertial());
89          Assertions.assertEquals(rsw.isQuasiInertial(), rswLOF.isQuasiInertial());
90          Assertions.assertEquals(ric.isQuasiInertial(), ricLOF.isQuasiInertial());
91          Assertions.assertEquals(rtn.isQuasiInertial(), rtnLOF.isQuasiInertial());
92          Assertions.assertEquals(qsw.isQuasiInertial(), qswLOF.isQuasiInertial());
93          Assertions.assertEquals(tnwRotating.isQuasiInertial(), tnwRotatingLOF.isQuasiInertial());
94          Assertions.assertEquals(tnwInertial.isQuasiInertial(), tnwInertialLOF.isQuasiInertial());
95          Assertions.assertEquals(tnw.isQuasiInertial(), tnwLOF.isQuasiInertial());
96          Assertions.assertNull(sezRotatingLOF);
97          Assertions.assertNull(sezInertialLOF);
98          Assertions.assertEquals(vncRotating.isQuasiInertial(), vncRotatingLOF.isQuasiInertial());
99          Assertions.assertEquals(vncInertial.isQuasiInertial(), vncInertialLOF.isQuasiInertial());
100     }
101 
102     @Test
103     @DisplayName("test conversion from/to orbit relative frame to/from orekit local orbital frame")
104     void testConversionFromToOrbitRelativeFrameToFromLOFType() {
105         for (OrbitRelativeFrame ccsdsFrame : OrbitRelativeFrame.values()) {
106             final LOFType orekitEquivalentLOF = ccsdsFrame.getLofType();
107 
108             // Bypass cases where there is no Orekit equivalent
109             if (orekitEquivalentLOF != null) {
110                 // Assert that we come back to the initial CCSDS frame
111                 final OrbitRelativeFrame ccsdsFrameFromOrekitLOF = orekitEquivalentLOF.toOrbitRelativeFrame();
112 
113                 // Filter out special cases for RTN local orbital frame
114                 if (!isRTNNotInertialEquivalent(ccsdsFrame.name(), ccsdsFrameFromOrekitLOF.name())) {
115                     // Cases where we start from a "_ROTATING" enum and go back to the equivalent version without "_ROTATION" are
116                     // necessary equivalent
117                     if (!(ccsdsFrameFromOrekitLOF.name() + "_ROTATING").equals(ccsdsFrame.name())) {
118                         Assertions.assertEquals(ccsdsFrame, ccsdsFrameFromOrekitLOF);
119                     }
120                 }
121 
122             }
123         }
124     }
125 
126     private boolean isRTNNotInertialEquivalent(final String ccsdsFrameName, final String ccsdsFrameFromOrekitLOFName) {
127         return !ccsdsFrameFromOrekitLOFName.contains("_INERTIAL") && ccsdsFrameFromOrekitLOFName.contains("QSW")
128                 && (ccsdsFrameName.contains("RSW") || ccsdsFrameName.contains("RTN") || ccsdsFrameName.contains("RIC"));
129     }
130 
131     @Test
132     @DisplayName("test error thrown when trying to convert LVLH LOFType to its OrbitRelativeFrame equivalent")
133     void testErrorThrownWhenTryingToConvertLVLHLOFTypeToOrbitRelativeFrame() {
134         // Given
135         final LOFType lvlh         = LOFType.LVLH;
136         final LOFType lvlhInertial = LOFType.LVLH_INERTIAL;
137 
138         // When
139         final Exception firstException  = Assertions.assertThrows(OrekitException.class, lvlh::toOrbitRelativeFrame);
140         final Exception secondException = Assertions.assertThrows(OrekitException.class, lvlhInertial::toOrbitRelativeFrame);
141 
142         // Then
143         final String expectedErrorMessage =
144                 "this LVLH local orbital frame uses a different definition, please use LVLH_CCSDS instead";
145 
146         Assertions.assertEquals(expectedErrorMessage, firstException.getMessage());
147         Assertions.assertEquals(expectedErrorMessage, secondException.getMessage());
148 
149     }
150 }