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.complex.Complex;
21  import org.hipparchus.complex.ComplexField;
22  import org.hipparchus.geometry.euclidean.threed.FieldRotation;
23  import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
24  import org.hipparchus.geometry.euclidean.threed.Rotation;
25  import org.hipparchus.geometry.euclidean.threed.Vector3D;
26  import org.junit.jupiter.api.Assertions;
27  import org.junit.jupiter.api.Test;
28  import org.mockito.Mockito;
29  import org.orekit.frames.Frame;
30  import org.orekit.time.AbsoluteDate;
31  import org.orekit.time.FieldAbsoluteDate;
32  import org.orekit.utils.FieldPVCoordinatesProvider;
33  import org.orekit.utils.PVCoordinatesProvider;
34  import org.orekit.utils.ParameterDriver;
35  import org.orekit.utils.TimeStampedAngularCoordinates;
36  import org.orekit.utils.TimeStampedFieldAngularCoordinates;
37  
38  import java.util.ArrayList;
39  import java.util.List;
40  
41  class AttitudeProviderModifierTest {
42  
43      @Test
44      void testGetAttitude() {
45          // GIVEN
46          final Rotation expectedRotation = new Rotation(Vector3D.MINUS_I, Vector3D.MINUS_K);
47          final AttitudeProvider attitudeProvider = new TestProvider(expectedRotation);
48          final AttitudeProviderModifier modifier = new TestModifier(attitudeProvider);
49          final PVCoordinatesProvider mockedPVCoordinatesProvider = Mockito.mock(PVCoordinatesProvider.class);
50          final AbsoluteDate date = AbsoluteDate.ARBITRARY_EPOCH;
51          final Frame mockedFrame = Mockito.mock(Frame.class);
52          // WHEN
53          final Attitude actualAttitude = modifier.getAttitude(mockedPVCoordinatesProvider, date, mockedFrame);
54          // THEN
55          final Attitude expectedAttitude = attitudeProvider.getAttitude(mockedPVCoordinatesProvider, date, mockedFrame);
56          Assertions.assertEquals(0, Rotation.distance(expectedRotation, actualAttitude.getRotation()));
57          Assertions.assertEquals(expectedAttitude.getSpin(), actualAttitude.getSpin());
58          Assertions.assertEquals(expectedAttitude.getRotationAcceleration(), actualAttitude.getRotationAcceleration());
59      }
60  
61      @SuppressWarnings("unchecked")
62      @Test
63      void testGetFieldAttitude() {
64          // GIVEN
65          final Rotation expectedRotation = new Rotation(Vector3D.MINUS_I, Vector3D.MINUS_K);
66          final AttitudeProvider attitudeProvider = new TestProvider(expectedRotation);
67          final ComplexField field = ComplexField.getInstance();
68          final FieldPVCoordinatesProvider<Complex> mockedPVCoordinatesProvider = Mockito.mock(FieldPVCoordinatesProvider.class);
69          final FieldAbsoluteDate<Complex> date = FieldAbsoluteDate.getArbitraryEpoch(field);
70          final Frame mockedFrame = Mockito.mock(Frame.class);
71          final AttitudeProviderModifier modifier = new TestModifier(attitudeProvider);
72          // WHEN
73          final FieldAttitude<Complex> attitude = modifier.getAttitude(mockedPVCoordinatesProvider, date,
74                  mockedFrame);
75          // THEN
76          final Rotation actualRotation = attitude.getRotation().toRotation();
77          Assertions.assertEquals(0., Rotation.distance(expectedRotation, actualRotation));
78          Assertions.assertEquals(FieldVector3D.getZero(field), attitude.getRotationAcceleration());
79          Assertions.assertEquals(FieldVector3D.getZero(field), attitude.getSpin());
80      }
81  
82      @Test
83      void testGetFrozenAttitudeProviderEventDetectors() {
84          // GIVEN
85          final AttitudeProvider attitudeProvider = new TestProvider(Rotation.IDENTITY);
86          final List<ParameterDriver> drivers = new ArrayList<>();
87          // WHEN
88          final AttitudeProviderModifier frozenAttitudeProvider = AttitudeProviderModifier
89                  .getFrozenAttitudeProvider(attitudeProvider);
90          // THEN
91          Assertions.assertEquals(attitudeProvider.getEventDetectors().count(),
92                  frozenAttitudeProvider.getEventDetectors().count());
93          Assertions.assertEquals(attitudeProvider.getEventDetectors(drivers).count(),
94                  frozenAttitudeProvider.getEventDetectors(drivers).count());
95      }
96  
97      @Test
98      void testGetFrozenAttitudeProvider() {
99          // GIVEN
100         final Rotation expectedRotation = new Rotation(Vector3D.MINUS_I, Vector3D.MINUS_K);
101         final AttitudeProvider attitudeProvider = new TestProvider(expectedRotation);
102         final PVCoordinatesProvider mockedPVCoordinatesProvider = Mockito.mock(PVCoordinatesProvider.class);
103         final AbsoluteDate date = AbsoluteDate.ARBITRARY_EPOCH;
104         final Frame mockedFrame = Mockito.mock(Frame.class);
105         // WHEN
106         final AttitudeProviderModifier frozenAttitudeProvider = AttitudeProviderModifier.getFrozenAttitudeProvider(attitudeProvider);
107         final Attitude attitude = frozenAttitudeProvider.getAttitude(mockedPVCoordinatesProvider, date, mockedFrame);
108         // THEN
109         Assertions.assertEquals(attitudeProvider, frozenAttitudeProvider.getUnderlyingAttitudeProvider());
110         final Rotation actualRotation = attitude.getRotation();
111         Assertions.assertEquals(0., Rotation.distance(expectedRotation, actualRotation));
112         Assertions.assertEquals(Vector3D.ZERO, attitude.getRotationAcceleration());
113         Assertions.assertEquals(Vector3D.ZERO, attitude.getSpin());
114         final Rotation rotation = frozenAttitudeProvider.getAttitudeRotation(mockedPVCoordinatesProvider, date, mockedFrame);
115         Assertions.assertEquals(0., Rotation.distance(rotation, actualRotation));
116     }
117 
118     @SuppressWarnings("unchecked")
119     @Test
120     void testGetFrozenAttitudeProviderField() {
121         // GIVEN
122         final Rotation expectedRotation = new Rotation(Vector3D.MINUS_I, Vector3D.MINUS_K);
123         final AttitudeProvider attitudeProvider = new TestProvider(expectedRotation);
124         final ComplexField field = ComplexField.getInstance();
125         final FieldPVCoordinatesProvider<Complex> mockedPVCoordinatesProvider = Mockito.mock(FieldPVCoordinatesProvider.class);
126         final FieldAbsoluteDate<Complex> date = FieldAbsoluteDate.getArbitraryEpoch(field);
127         final Frame mockedFrame = Mockito.mock(Frame.class);
128         // WHEN
129         final AttitudeProvider frozenAttitudeProvider = AttitudeProviderModifier.getFrozenAttitudeProvider(attitudeProvider);
130         final FieldAttitude<Complex> attitude = frozenAttitudeProvider.getAttitude(mockedPVCoordinatesProvider, date,
131                 mockedFrame);
132         // THEN
133         final Rotation actualRotation = attitude.getRotation().toRotation();
134         Assertions.assertEquals(0., Rotation.distance(expectedRotation, actualRotation));
135         Assertions.assertEquals(FieldVector3D.getZero(field), attitude.getRotationAcceleration());
136         Assertions.assertEquals(FieldVector3D.getZero(field), attitude.getSpin());
137         final Rotation rotation = frozenAttitudeProvider.getAttitudeRotation(mockedPVCoordinatesProvider, date,
138                 mockedFrame).toRotation();
139         Assertions.assertEquals(0., Rotation.distance(rotation, actualRotation));
140     }
141 
142     @Test
143     void testGetFrozenAttitudeProviderFieldEventDetectors() {
144         // GIVEN
145         final AttitudeProvider attitudeProvider = new TestProvider(Rotation.IDENTITY);
146         final ComplexField field = ComplexField.getInstance();
147         final List<ParameterDriver> driverList = new ArrayList<>();
148         // WHEN
149         final AttitudeProvider frozenAttitudeProvider = AttitudeProviderModifier.getFrozenAttitudeProvider(attitudeProvider);
150         // THEN
151         Assertions.assertEquals(attitudeProvider.getFieldEventDetectors(field).count(),
152                 frozenAttitudeProvider.getEventDetectors().count());
153         Assertions.assertEquals(attitudeProvider.getFieldEventDetectors(field, driverList).count(),
154                 frozenAttitudeProvider.getFieldEventDetectors(field, driverList).count());
155     }
156 
157     @Test
158     void testGetParametersDrivers() {
159         // GIVEN
160         final AttitudeProvider mockedProvider = new TestProvider(Rotation.IDENTITY);
161         final List<ParameterDriver> expectedDrivers = new ArrayList<>();
162         final AttitudeProviderModifier mockedProviderModifier = Mockito.mock(AttitudeProviderModifier.class);
163         Mockito.when(mockedProviderModifier.getUnderlyingAttitudeProvider()).thenReturn(mockedProvider);
164         // WHEN
165         final List<ParameterDriver> actualDrivers = mockedProviderModifier.getParametersDrivers();
166         // THEN
167         Assertions.assertEquals(expectedDrivers.size(), actualDrivers.size());
168     }
169 
170     @Test
171     void testGetFrozenAttitudeProviderGetParametersDrivers() {
172         // GIVEN
173         final AttitudeProvider attitudeProvider = new TestProvider(Rotation.IDENTITY);
174         final AttitudeProviderModifier frozenAttitudeProvider = AttitudeProviderModifier.getFrozenAttitudeProvider(attitudeProvider);
175         // WHEN
176         final List<ParameterDriver> drivers = frozenAttitudeProvider.getParametersDrivers();
177         // THEN
178         Assertions.assertEquals(attitudeProvider.getParametersDrivers().size(), drivers.size());
179     }
180 
181     private static class TestProvider implements AttitudeProvider {
182 
183         private final Rotation r;
184         TestProvider(final Rotation r) {
185             this.r = r;
186         }
187 
188         @Override
189         public Attitude getAttitude(final PVCoordinatesProvider pvProv, final AbsoluteDate date, final Frame frame) {
190             return new Attitude(frame, new TimeStampedAngularCoordinates(date, r, Vector3D.ZERO, Vector3D.ZERO));
191         }
192 
193         @Override
194         public <T extends CalculusFieldElement<T>> FieldAttitude<T> getAttitude(
195             final FieldPVCoordinatesProvider<T> pvProv, final FieldAbsoluteDate<T> date, final Frame frame) {
196             return new FieldAttitude<>(frame,
197                                        new TimeStampedFieldAngularCoordinates<>(date,
198                                                                                 new FieldRotation<>(date.getField(), r),
199                                                                                 FieldVector3D.getZero(date.getField()),
200                                                                                 FieldVector3D.getZero(date.getField())));
201         }
202 
203     }
204 
205     private static class TestModifier implements AttitudeProviderModifier {
206 
207         final AttitudeProvider attitudeProvider;
208 
209         TestModifier(final AttitudeProvider attitudeProvider) {
210             this.attitudeProvider = attitudeProvider;
211         }
212 
213         @Override
214         public AttitudeProvider getUnderlyingAttitudeProvider() {
215             return attitudeProvider;
216         }
217 
218     }
219 
220 }