1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.attitudes;
18
19 import static org.hamcrest.CoreMatchers.is;
20 import static org.hamcrest.CoreMatchers.not;
21 import static org.orekit.OrekitMatchers.attitudeIs;
22 import static org.orekit.OrekitMatchers.closeTo;
23 import static org.orekit.OrekitMatchers.distanceIs;
24
25 import org.hamcrest.MatcherAssert;
26 import org.hipparchus.CalculusFieldElement;
27 import org.hipparchus.Field;
28 import org.hipparchus.analysis.differentiation.GradientField;
29 import org.hipparchus.complex.ComplexField;
30 import org.hipparchus.geometry.euclidean.threed.FieldRotation;
31 import org.hipparchus.geometry.euclidean.threed.Rotation;
32 import org.hipparchus.geometry.euclidean.threed.RotationConvention;
33 import org.hipparchus.geometry.euclidean.threed.Vector3D;
34 import org.hipparchus.util.Binary64;
35 import org.hipparchus.util.Binary64Field;
36 import org.hipparchus.util.FastMath;
37 import org.junit.jupiter.api.AfterEach;
38 import org.junit.jupiter.api.Assertions;
39 import org.junit.jupiter.api.BeforeEach;
40 import org.junit.jupiter.api.Test;
41 import org.orekit.Utils;
42 import org.orekit.annotation.DefaultDataContext;
43 import org.orekit.errors.OrekitException;
44 import org.orekit.frames.Frame;
45 import org.orekit.frames.FramesFactory;
46 import org.orekit.frames.Transform;
47 import org.orekit.orbits.FieldCartesianOrbit;
48 import org.orekit.orbits.FieldOrbit;
49 import org.orekit.orbits.KeplerianOrbit;
50 import org.orekit.orbits.Orbit;
51 import org.orekit.orbits.PositionAngleType;
52 import org.orekit.propagation.FieldSpacecraftState;
53 import org.orekit.propagation.Propagator;
54 import org.orekit.propagation.SpacecraftState;
55 import org.orekit.propagation.analytical.KeplerianPropagator;
56 import org.orekit.time.AbsoluteDate;
57 import org.orekit.time.DateComponents;
58 import org.orekit.time.FieldAbsoluteDate;
59 import org.orekit.time.TimeComponents;
60 import org.orekit.time.TimeScalesFactory;
61 import org.orekit.utils.AngularCoordinates;
62 import org.orekit.utils.FieldPVCoordinates;
63 import org.orekit.utils.FieldPVCoordinatesProvider;
64
65
66 public class FrameAlignedProviderTest {
67
68 private AbsoluteDate t0;
69 private Orbit orbit0;
70
71 @Test
72 @DefaultDataContext
73 void testIsInertial() {
74 FrameAlignedProvider law = new FrameAlignedProvider(new Rotation(new Vector3D(0.6, 0.48, 0.64), 0.9,
75 RotationConvention.VECTOR_OPERATOR));
76 KeplerianPropagator propagator = new KeplerianPropagator(orbit0, law);
77 Attitude initial = propagator.propagate(t0).getAttitude();
78 for (double t = 0; t < 10000.0; t += 100) {
79 SpacecraftState state = propagator.propagate(t0.shiftedBy(t));
80 checkField(Binary64Field.getInstance(), law, state.getOrbit(), state.getDate(), state.getFrame());
81 Attitude attitude = state.getAttitude();
82 Rotation evolution = attitude.getRotation().compose(initial.getRotation().revert(),
83 RotationConvention.VECTOR_OPERATOR);
84 Assertions.assertEquals(0, evolution.getAngle(), 1.0e-10);
85 Assertions.assertEquals(FramesFactory.getEME2000(), attitude.getReferenceFrame());
86 }
87 }
88
89 @Test
90 @DefaultDataContext
91 void testCompensateMomentum() {
92 FrameAlignedProvider law = new FrameAlignedProvider(new Rotation(new Vector3D(-0.64, 0.6, 0.48), 0.2,
93 RotationConvention.VECTOR_OPERATOR));
94 KeplerianPropagator propagator = new KeplerianPropagator(orbit0, law);
95 Attitude initial = propagator.propagate(t0).getAttitude();
96 for (double t = 0; t < 10000.0; t += 100) {
97 Attitude attitude = propagator.propagate(t0.shiftedBy(t)).getAttitude();
98 Rotation evolution = attitude.getRotation().compose(initial.getRotation().revert(),
99 RotationConvention.VECTOR_OPERATOR);
100 Assertions.assertEquals(0, evolution.getAngle(), 1.0e-10);
101 Assertions.assertEquals(FramesFactory.getEME2000(), attitude.getReferenceFrame());
102 }
103 }
104
105 @Test
106 @DefaultDataContext
107 void testSpin() {
108 AbsoluteDate date = new AbsoluteDate(new DateComponents(1970, 1, 1),
109 new TimeComponents(3, 25, 45.6789),
110 TimeScalesFactory.getUTC());
111
112 AttitudeProvider law = new FrameAlignedProvider(new Rotation(new Vector3D(-0.64, 0.6, 0.48), 0.2,
113 RotationConvention.VECTOR_OPERATOR));
114 KeplerianOrbit orbit =
115 new KeplerianOrbit(7178000.0, 1.e-4, FastMath.toRadians(50.),
116 FastMath.toRadians(10.), FastMath.toRadians(20.),
117 FastMath.toRadians(30.), PositionAngleType.MEAN,
118 FramesFactory.getEME2000(), date, 3.986004415e14);
119
120 Propagator propagator = new KeplerianPropagator(orbit, law);
121
122 double h = 100.0;
123 SpacecraftState sMinus = propagator.propagate(date.shiftedBy(-h));
124 SpacecraftState s0 = propagator.propagate(date);
125 SpacecraftState sPlus = propagator.propagate(date.shiftedBy(h));
126
127
128 double errorAngleMinus = Rotation.distance(sMinus.shiftedBy(h).getAttitude().getRotation(),
129 s0.getAttitude().getRotation());
130 double evolutionAngleMinus = Rotation.distance(sMinus.getAttitude().getRotation(),
131 s0.getAttitude().getRotation());
132 Assertions.assertEquals(0.0, errorAngleMinus, 1.0e-6 * evolutionAngleMinus);
133 double errorAnglePlus = Rotation.distance(s0.getAttitude().getRotation(),
134 sPlus.shiftedBy(-h).getAttitude().getRotation());
135 double evolutionAnglePlus = Rotation.distance(s0.getAttitude().getRotation(),
136 sPlus.getAttitude().getRotation());
137 Assertions.assertEquals(0.0, errorAnglePlus, 1.0e-6 * evolutionAnglePlus);
138
139
140 Rotation rMinus = sMinus.getAttitude().getRotation();
141 Rotation rPlus = sPlus.getAttitude().getRotation();
142 Rotation dr = rPlus.compose(rMinus.revert(), RotationConvention.VECTOR_OPERATOR);
143 Assertions.assertEquals(0, dr.getAngle(), 1.0e-10);
144
145 Vector3D spin0 = s0.getAttitude().getSpin();
146 Assertions.assertEquals(0, spin0.getNorm(), 1.0e-10);
147
148 }
149
150 private <T extends CalculusFieldElement<T>> void checkField(final Field<T> field, final AttitudeProvider provider,
151 final Orbit orbit, final AbsoluteDate date,
152 final Frame frame)
153 {
154 Attitude attitudeD = provider.getAttitude(orbit, date, frame);
155 final FieldOrbit<T> orbitF = new FieldSpacecraftState<>(field, new SpacecraftState(orbit)).getOrbit();
156 final FieldAbsoluteDate<T> dateF = new FieldAbsoluteDate<>(field, date);
157 FieldAttitude<T> attitudeF = provider.getAttitude(orbitF, dateF, frame);
158 Assertions.assertEquals(0.0, Rotation.distance(attitudeD.getRotation(), attitudeF.getRotation().toRotation()), 1.0e-15);
159 Assertions.assertEquals(0.0, Vector3D.distance(attitudeD.getSpin(), attitudeF.getSpin().toVector3D()), 1.0e-15);
160 Assertions.assertEquals(0.0, Vector3D.distance(attitudeD.getRotationAcceleration(), attitudeF.getRotationAcceleration().toVector3D()), 1.0e-15);
161 }
162
163 @Test
164 void testGetAttitude() {
165
166 Frame eci = orbit0.getFrame();
167 Attitude expected = new Attitude(t0, eci, AngularCoordinates.IDENTITY);
168 AttitudeProvider law = FrameAlignedProvider.of(eci);
169
170
171 Attitude actual = law.getAttitude(orbit0, t0, eci);
172 MatcherAssert.assertThat(actual.getReferenceFrame(), is(eci));
173 MatcherAssert.assertThat(actual, attitudeIs(expected));
174 actual = law.getAttitude(orbit0.shiftedBy(1e3), t0.shiftedBy(1e3), eci);
175 MatcherAssert.assertThat(actual.getReferenceFrame(), is(eci));
176 MatcherAssert.assertThat(actual, attitudeIs(expected));
177
178 Rotation rotation = new Rotation(
179 Vector3D.PLUS_K,
180 FastMath.PI / 2.0,
181 RotationConvention.FRAME_TRANSFORM);
182 Transform angular = new Transform(
183 t0,
184 rotation,
185 new Vector3D(1, 2, 3),
186 new Vector3D(-4, 5, 6));
187 Transform translation = new Transform(
188 t0,
189 new Vector3D(-1, 2, -3),
190 new Vector3D(4, -5, 6),
191 new Vector3D(7, 8, -9));
192 Frame other = new Frame(eci, new Transform(t0, angular, translation), "other");
193 actual = law.getAttitude(orbit0.shiftedBy(1e3), t0.shiftedBy(1e3), other);
194 MatcherAssert.assertThat(actual.getReferenceFrame(), is(other));
195 MatcherAssert.assertThat(actual, attitudeIs(expected));
196
197 MatcherAssert.assertThat(actual.getRotation(),
198 not(distanceIs(Rotation.IDENTITY, closeTo(0.0, 1e-1))));
199 }
200
201
202
203
204
205
206 @Test
207 void testGetAttitudeField() {
208
209 Frame eci = orbit0.getFrame();
210 Attitude expected = new Attitude(t0, eci, AngularCoordinates.IDENTITY);
211 AttitudeProvider law = FrameAlignedProvider.of(eci);
212 Binary64 one = Binary64.ONE;
213 FieldAbsoluteDate<Binary64> date = new FieldAbsoluteDate<>(one.getField(), t0);
214 FieldOrbit<Binary64> orbit = new FieldCartesianOrbit<>(
215 new FieldPVCoordinates<>(one, this.orbit0.getPVCoordinates()),
216 eci,
217 date,
218 one.newInstance(orbit0.getMu()));
219
220
221 FieldAttitude<Binary64> actual = law.getAttitude(orbit, date, eci);
222 MatcherAssert.assertThat(actual.getReferenceFrame(), is(eci));
223 MatcherAssert.assertThat(actual.toAttitude(), attitudeIs(expected));
224 actual = law.getAttitude(orbit.shiftedBy(1e3), date.shiftedBy(1e3), eci);
225 MatcherAssert.assertThat(actual.getReferenceFrame(), is(eci));
226 MatcherAssert.assertThat(actual.toAttitude(), attitudeIs(expected));
227
228 Rotation rotation = new Rotation(
229 Vector3D.PLUS_K,
230 FastMath.PI / 2.0,
231 RotationConvention.FRAME_TRANSFORM);
232 Transform angular = new Transform(
233 t0,
234 rotation,
235 new Vector3D(1, 2, 3),
236 new Vector3D(-4, 5, 6));
237 Transform translation = new Transform(
238 t0,
239 new Vector3D(-1, 2, -3),
240 new Vector3D(4, -5, 6),
241 new Vector3D(7, 8, -9));
242 Frame other = new Frame(eci, new Transform(t0, angular, translation), "other");
243 actual = law.getAttitude(orbit.shiftedBy(1e3), date.shiftedBy(1e3), other);
244 MatcherAssert.assertThat(actual.getReferenceFrame(), is(other));
245 MatcherAssert.assertThat(actual.toAttitude(), attitudeIs(expected));
246
247 MatcherAssert.assertThat(actual.getRotation().toRotation(),
248 not(distanceIs(Rotation.IDENTITY, closeTo(0.0, 1e-1))));
249 }
250
251 @Test
252 @DefaultDataContext
253 void testGetAttitudeRotation() {
254
255 final Frame frame1 = FramesFactory.getGCRF();
256 final Frame frame2 = FramesFactory.getEME2000();
257 final AbsoluteDate date = orbit0.getDate();
258 final FrameAlignedProvider frameAlignedProvider = new FrameAlignedProvider(frame1);
259
260 final Rotation actualRotation = frameAlignedProvider.getAttitudeRotation(orbit0, date, frame2);
261
262 final Rotation expectedRotation = frameAlignedProvider.getAttitude(orbit0, date, frame2).getRotation();
263 Assertions.assertEquals(0., Rotation.distance(expectedRotation, actualRotation));
264 }
265
266 @Test
267 @DefaultDataContext
268 void testGetAttitudeRotationFieldComplex() {
269 final ComplexField complexField = ComplexField.getInstance();
270 templateTestGetRotationField(complexField);
271 }
272
273 @Test
274 @DefaultDataContext
275 void testGetAttitudeRotationFieldGradient() {
276 final GradientField gradientField = GradientField.getField(1);
277 templateTestGetRotationField(gradientField);
278 }
279
280 @DefaultDataContext
281 <T extends CalculusFieldElement<T>> void templateTestGetRotationField(final Field<T> field) {
282
283 final Frame frame1 = FramesFactory.getGCRF();
284 final Frame frame2 = FramesFactory.getEME2000();
285 final FrameAlignedProvider frameAlignedProvider = new FrameAlignedProvider(frame1);
286 final SpacecraftState state = new SpacecraftState(orbit0);
287 final FieldSpacecraftState<T> fieldState = new FieldSpacecraftState<>(field, state);
288
289 final FieldRotation<T> actualRotation = frameAlignedProvider.getAttitudeRotation(fieldState.getOrbit(), fieldState.getDate(), frame2);
290
291 final FieldRotation<T> expectedRotation = frameAlignedProvider.getAttitude(fieldState.getOrbit(), fieldState.getDate(), frame2).getRotation();
292 Assertions.assertEquals(0., Rotation.distance(expectedRotation.toRotation(), actualRotation.toRotation()));
293 }
294
295 @BeforeEach
296 @DefaultDataContext
297 public void setUp() {
298 try {
299 Utils.setDataRoot("regular-data");
300
301 t0 = new AbsoluteDate(new DateComponents(2008, 6, 3), TimeComponents.H12,
302 TimeScalesFactory.getUTC());
303 orbit0 =
304 new KeplerianOrbit(12345678.9, 0.001, 2.3, 0.1, 3.04, 2.4,
305 PositionAngleType.TRUE, FramesFactory.getEME2000(),
306 t0, 3.986004415e14);
307 } catch (OrekitException oe) {
308 Assertions.fail(oe.getMessage());
309 }
310 }
311
312 @AfterEach
313 public void tearDown() {
314 t0 = null;
315 orbit0 = null;
316 }
317
318 }
319