1   /* Copyright 2022-2025 Romain Serra
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.attitudes;
18  
19  import org.hipparchus.CalculusFieldElement;
20  import org.hipparchus.Field;
21  import org.hipparchus.analysis.differentiation.UnivariateDerivative1;
22  import org.hipparchus.geometry.euclidean.threed.FieldRotation;
23  import org.hipparchus.geometry.euclidean.threed.Rotation;
24  import org.hipparchus.geometry.euclidean.threed.Vector3D;
25  import org.hipparchus.util.Binary64;
26  import org.hipparchus.util.Binary64Field;
27  import org.junit.jupiter.api.Assertions;
28  import org.junit.jupiter.api.Test;
29  import org.mockito.Mockito;
30  import org.orekit.frames.Frame;
31  import org.orekit.frames.FramesFactory;
32  import org.orekit.orbits.CartesianOrbit;
33  import org.orekit.propagation.FieldSpacecraftState;
34  import org.orekit.propagation.SpacecraftState;
35  import org.orekit.propagation.events.EventDetector;
36  import org.orekit.time.AbsoluteDate;
37  import org.orekit.time.FieldAbsoluteDate;
38  import org.orekit.utils.*;
39  
40  import java.util.ArrayList;
41  import java.util.List;
42  import java.util.stream.Stream;
43  
44  class AttitudeProviderTest {
45  
46      private static final Frame REFERENCE_FRAME = FramesFactory.getGCRF();
47  
48      private static class TestAttitudeProvider implements AttitudeProvider {
49          private static final AngularCoordinates ANGULAR_COORDINATES = new AngularCoordinates(new Rotation(Vector3D.MINUS_I, Vector3D.MINUS_K));
50  
51          @Override
52          public Attitude getAttitude(PVCoordinatesProvider pvProv, AbsoluteDate date, Frame frame) {
53              return new Attitude(date, frame, ANGULAR_COORDINATES);
54          }
55  
56          @Override
57          public <T extends CalculusFieldElement<T>> FieldAttitude<T> getAttitude(FieldPVCoordinatesProvider<T> pvProv, FieldAbsoluteDate<T> date, Frame frame) {
58              return new FieldAttitude<>(date, frame, new FieldAngularCoordinates<>(date.getField(), ANGULAR_COORDINATES));
59          }
60      }
61  
62      @Test
63      void testGetAttitudeRotationModelField() {
64          // GIVEN
65          final TestAttitudeProvider attitudeProvider = new TestAttitudeProvider();
66          final AbsoluteDate date = AbsoluteDate.ARBITRARY_EPOCH;
67          final SpacecraftState state = new SpacecraftState(new CartesianOrbit(new PVCoordinates(Vector3D.MINUS_J, Vector3D.MINUS_K),
68                  FramesFactory.getEME2000(), date, 1.));
69          final Binary64Field field = Binary64Field.getInstance();
70          final FieldSpacecraftState<Binary64> fieldState = new FieldSpacecraftState<>(field, state);
71          // WHEN
72          final FieldRotation<Binary64> actualRotation = attitudeProvider.getAttitudeRotation(fieldState, null);
73          // THEN
74          final FieldRotation<Binary64> expectedRotation = attitudeProvider.getAttitudeRotation(fieldState.getOrbit(), fieldState.getDate(),
75                  state.getFrame());
76          Assertions.assertEquals(0., Rotation.distance(expectedRotation.toRotation(), actualRotation.toRotation()));
77      }
78  
79      @Test
80      void testGetAttitudeRotationModelFieldAbsolutePV() {
81          // GIVEN
82          final TestAttitudeProvider attitudeProvider = new TestAttitudeProvider();
83          final AbsoluteDate date = AbsoluteDate.ARBITRARY_EPOCH;
84          final SpacecraftState state = new SpacecraftState(new AbsolutePVCoordinates(FramesFactory.getEME2000(), date,
85                  new PVCoordinates(Vector3D.MINUS_J, Vector3D.MINUS_K)));
86          final Binary64Field field = Binary64Field.getInstance();
87          final FieldSpacecraftState<Binary64> fieldState = new FieldSpacecraftState<>(field, state);
88          // WHEN
89          final FieldRotation<Binary64> actualRotation = attitudeProvider.getAttitudeRotation(fieldState, null);
90          // THEN
91          final FieldRotation<Binary64> expectedRotation = attitudeProvider.getAttitudeRotation(fieldState.getAbsPVA(), fieldState.getDate(),
92                  state.getFrame());
93          Assertions.assertEquals(0., Rotation.distance(expectedRotation.toRotation(), actualRotation.toRotation()));
94      }
95  
96      @Test
97      void testGetAttitudeRotationModel() {
98          // GIVEN
99          final TestAttitudeProvider attitudeProvider = new TestAttitudeProvider();
100         final AbsoluteDate date = AbsoluteDate.ARBITRARY_EPOCH;
101         final SpacecraftState state = new SpacecraftState(new CartesianOrbit(new PVCoordinates(Vector3D.MINUS_J, Vector3D.MINUS_K),
102                 FramesFactory.getEME2000(), date, 1.));
103         // WHEN
104         final Rotation actualRotation = attitudeProvider.getAttitudeRotation(state, new double[0]);
105         // THEN
106         final Rotation expectedRotation = attitudeProvider.getAttitudeRotation(state.getOrbit(), date, state.getFrame());
107         Assertions.assertEquals(0., Rotation.distance(expectedRotation, actualRotation));
108     }
109 
110     @Test
111     void testGetAttitudeRotationModelAbsolutePV() {
112         // GIVEN
113         final TestAttitudeProvider attitudeProvider = new TestAttitudeProvider();
114         final AbsoluteDate date = AbsoluteDate.ARBITRARY_EPOCH;
115         final SpacecraftState state = new SpacecraftState(new AbsolutePVCoordinates(FramesFactory.getEME2000(), date,
116                 new PVCoordinates(Vector3D.MINUS_J, Vector3D.MINUS_K)));
117         // WHEN
118         final Rotation actualRotation = attitudeProvider.getAttitudeRotation(state, new double[0]);
119         // THEN
120         final Rotation expectedRotation = attitudeProvider.getAttitudeRotation(state.getAbsPVA(), date, state.getFrame());
121         Assertions.assertEquals(0., Rotation.distance(expectedRotation, actualRotation));
122     }
123 
124     @Test
125     void testGetAttitudeRotation() {
126         // GIVEN
127         final TestAttitudeProvider attitudeProvider = new TestAttitudeProvider();
128         final PVCoordinatesProvider mockPvCoordinatesProvider = Mockito.mock(PVCoordinatesProvider.class);
129         final AbsoluteDate date = AbsoluteDate.ARBITRARY_EPOCH;
130         // WHEN
131         final Rotation actualRotation = attitudeProvider.getAttitudeRotation(mockPvCoordinatesProvider, date, REFERENCE_FRAME);
132         // THEN
133         final Rotation expectedRotation = attitudeProvider.getAttitude(mockPvCoordinatesProvider, date, REFERENCE_FRAME)
134                 .getRotation();
135         Assertions.assertEquals(0., Rotation.distance(expectedRotation, actualRotation));
136     }
137 
138     @Test
139     void testGetEventDetectors() {
140         // GIVEN
141         final AttitudeProvider mockedProvider = Mockito.mock(AttitudeProvider.class);
142         Mockito.when(mockedProvider.getParametersDrivers()).thenReturn(new ArrayList<>());
143         // WHEN
144         final Stream<EventDetector> detectorStream = mockedProvider.getEventDetectors();
145         // THEN
146         Assertions.assertEquals(0, detectorStream.count());
147     }
148 
149     @Test
150     void testGetParametersDrivers() {
151         // GIVEN
152         final AttitudeProvider mockedProvider = new TestAttitudeProvider();
153         // WHEN
154         final List<ParameterDriver> driverList = mockedProvider.getParametersDrivers();
155         // THEN
156         Assertions.assertTrue(driverList.isEmpty());
157     }
158 
159     @Test
160     void testGetAttitudeRotationFieldBinary64() {
161         templateTestGetRotationField(Binary64Field.getInstance());
162     }
163 
164     @Test
165     void testGetAttitudeRotationFieldUnivariateDerivative1() {
166         templateTestGetRotationField(new UnivariateDerivative1(0., 0.).getField());
167     }
168 
169     <T extends CalculusFieldElement<T>> void templateTestGetRotationField(final Field<T> field) {
170         // GIVEN
171         final TestAttitudeProvider attitudeProvider = new TestAttitudeProvider();
172         @SuppressWarnings("unchecked")
173         final FieldPVCoordinatesProvider<T> mockPvCoordinatesProvider = Mockito.mock(FieldPVCoordinatesProvider.class);
174         final AbsoluteDate date = AbsoluteDate.ARBITRARY_EPOCH;
175         final FieldAbsoluteDate<T> fieldDate = new FieldAbsoluteDate<T>(field, date);
176         // WHEN
177         final FieldRotation<T> actualRotation = attitudeProvider.getAttitudeRotation(mockPvCoordinatesProvider, fieldDate, REFERENCE_FRAME);
178         // THEN
179         final FieldRotation<T> expectedRotation = attitudeProvider.getAttitude(mockPvCoordinatesProvider, fieldDate, REFERENCE_FRAME)
180                 .getRotation();
181         Assertions.assertEquals(0., Rotation.distance(expectedRotation.toRotation(), actualRotation.toRotation()));
182     }
183 
184 }