1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.attitudes;
18
19 import org.hipparchus.CalculusFieldElement;
20 import org.hipparchus.Field;
21 import org.hipparchus.complex.Complex;
22 import org.hipparchus.complex.ComplexField;
23 import org.hipparchus.geometry.euclidean.threed.FieldRotation;
24 import org.hipparchus.geometry.euclidean.threed.Rotation;
25 import org.hipparchus.geometry.euclidean.threed.Vector3D;
26 import org.hipparchus.util.Binary64Field;
27 import org.hipparchus.util.FastMath;
28 import org.junit.jupiter.api.Assertions;
29 import org.junit.jupiter.api.BeforeEach;
30 import org.junit.jupiter.api.Test;
31 import org.orekit.Utils;
32 import org.orekit.annotation.DefaultDataContext;
33 import org.orekit.bodies.CelestialBody;
34 import org.orekit.bodies.CelestialBodyFactory;
35 import org.orekit.frames.Frame;
36 import org.orekit.frames.FramesFactory;
37 import org.orekit.orbits.*;
38 import org.orekit.propagation.FieldSpacecraftState;
39 import org.orekit.propagation.Propagator;
40 import org.orekit.propagation.SpacecraftState;
41 import org.orekit.propagation.analytical.KeplerianPropagator;
42 import org.orekit.time.AbsoluteDate;
43 import org.orekit.time.DateComponents;
44 import org.orekit.time.FieldAbsoluteDate;
45 import org.orekit.time.TimeComponents;
46 import org.orekit.time.TimeScalesFactory;
47 import org.orekit.utils.AngularCoordinates;
48 import org.orekit.utils.Constants;
49 import org.orekit.utils.PVCoordinates;
50 import org.orekit.utils.PVCoordinatesProvider;
51
52 class SpinStabilizedTest {
53
54 @Test
55 @DefaultDataContext
56 void testBBQMode() {
57 CelestialBody sun = CelestialBodyFactory.getSun();
58 AbsoluteDate date = new AbsoluteDate(new DateComponents(1970, 1, 1),
59 new TimeComponents(3, 25, 45.6789),
60 TimeScalesFactory.getTAI());
61 double rate = 2.0 * FastMath.PI / (12 * 60);
62 AttitudeProvider cbp = new CelestialBodyPointed(FramesFactory.getEME2000(), sun, Vector3D.PLUS_K,
63 Vector3D.PLUS_I, Vector3D.PLUS_K);
64 SpinStabilized bbq = new SpinStabilized(cbp, date, Vector3D.PLUS_K, rate);
65 PVCoordinates pv =
66 new PVCoordinates(new Vector3D(28812595.32012577, 5948437.4640250085, 0),
67 new Vector3D(0, 0, 3680.853673522056));
68 KeplerianOrbit kep = new KeplerianOrbit(pv, FramesFactory.getEME2000(), date, 3.986004415e14);
69 Attitude attitude = bbq.getAttitude(kep, date, kep.getFrame());
70 checkField(Binary64Field.getInstance(), bbq, kep, kep.getDate(), kep.getFrame());
71 Vector3D xDirection = attitude.getRotation().applyInverseTo(Vector3D.PLUS_I);
72 Assertions.assertEquals(FastMath.atan(1.0 / 5000.0),
73 Vector3D.angle(xDirection, sun.getPosition(date, FramesFactory.getEME2000())),
74 2.0e-15);
75 Assertions.assertEquals(rate, attitude.getSpin().getNorm(), 1.0e-6);
76 Assertions.assertSame(cbp, bbq.getUnderlyingAttitudeProvider());
77
78 }
79
80 @Test
81 @DefaultDataContext
82 void testGetAttitudeRotation() {
83
84 final Orbit orbit = getOrbit();
85 final AttitudeProvider baseProvider = new FrameAlignedProvider(FramesFactory.getEME2000());
86 final AbsoluteDate startDate = orbit.getDate().shiftedBy(-10.);
87 final SpinStabilized spinStabilized = new SpinStabilized(baseProvider, startDate, Vector3D.PLUS_K, 0.1);
88
89 final Rotation rotation = spinStabilized.getAttitudeRotation(orbit, orbit.getDate(), orbit.getFrame());
90
91 final Attitude attitude = spinStabilized.getAttitude(orbit, orbit.getDate(), orbit.getFrame());
92 Assertions.assertEquals(0., Rotation.distance(rotation, attitude.getRotation()));
93 }
94
95 @Test
96 @DefaultDataContext
97 void testFieldGetAttitudeRotation() {
98
99 final CartesianOrbit orbit = getOrbit();
100 final AbsoluteDate startDate = orbit.getDate().shiftedBy(-10.);
101
102 final AttitudeProvider baseProvider = new FrameAlignedProvider(FramesFactory.getEME2000());
103 final SpinStabilized spinStabilized = new SpinStabilized(baseProvider, startDate, Vector3D.PLUS_K, 0.1);
104 final FieldOrbit<Complex> fieldOrbit = new FieldCircularOrbit<>(ComplexField.getInstance(), orbit);
105
106 final FieldRotation<Complex> rotation = spinStabilized.getAttitudeRotation(fieldOrbit, fieldOrbit.getDate(), fieldOrbit.getFrame());
107
108 final FieldAttitude<Complex> attitude = spinStabilized.getAttitude(fieldOrbit, fieldOrbit.getDate(), fieldOrbit.getFrame());
109 Assertions.assertEquals(0., Rotation.distance(rotation.toRotation(), attitude.getRotation().toRotation()));
110 }
111
112 @DefaultDataContext
113 private CartesianOrbit getOrbit() {
114 final PVCoordinates pv =
115 new PVCoordinates(new Vector3D(28812595.32012577, 5948437.4640250085, 0),
116 new Vector3D(0, 0, 3680.853673522056));
117 return new CartesianOrbit(pv, FramesFactory.getGCRF(), AbsoluteDate.ARBITRARY_EPOCH, Constants.EIGEN5C_EARTH_MU);
118 }
119
120 @Test
121 @DefaultDataContext
122 void testSpin() {
123
124 AbsoluteDate date = new AbsoluteDate(new DateComponents(1970, 1, 1),
125 new TimeComponents(3, 25, 45.6789),
126 TimeScalesFactory.getUTC());
127 double rate = 2.0 * FastMath.PI / (12 * 60);
128 AttitudeProvider law =
129 new SpinStabilized(new FrameAlignedProvider(Rotation.IDENTITY),
130 date, Vector3D.PLUS_K, rate);
131 KeplerianOrbit orbit =
132 new KeplerianOrbit(7178000.0, 1.e-4, FastMath.toRadians(50.),
133 FastMath.toRadians(10.), FastMath.toRadians(20.),
134 FastMath.toRadians(30.), PositionAngleType.MEAN,
135 FramesFactory.getEME2000(), date, 3.986004415e14);
136
137 Propagator propagator = new KeplerianPropagator(orbit, law);
138
139 double h = 10.0;
140 SpacecraftState sMinus = propagator.propagate(date.shiftedBy(-h));
141 SpacecraftState s0 = propagator.propagate(date);
142 SpacecraftState sPlus = propagator.propagate(date.shiftedBy(h));
143 Vector3D spin0 = s0.getAttitude().getSpin();
144
145
146 double errorAngleMinus = Rotation.distance(sMinus.shiftedBy(h).getAttitude().getRotation(),
147 s0.getAttitude().getRotation());
148 double evolutionAngleMinus = Rotation.distance(sMinus.getAttitude().getRotation(),
149 s0.getAttitude().getRotation());
150 Assertions.assertTrue(errorAngleMinus <= 1.0e-6 * evolutionAngleMinus);
151 double errorAnglePlus = Rotation.distance(s0.getAttitude().getRotation(),
152 sPlus.shiftedBy(-h).getAttitude().getRotation());
153 double evolutionAnglePlus = Rotation.distance(s0.getAttitude().getRotation(),
154 sPlus.getAttitude().getRotation());
155 Assertions.assertTrue(errorAnglePlus <= 1.0e-6 * evolutionAnglePlus);
156
157
158 Rotation rM = sMinus.getAttitude().getRotation();
159 Rotation rP = sPlus.getAttitude().getRotation();
160 Vector3D reference = AngularCoordinates.estimateRate(rM, rP, 2 * h);
161
162 Assertions.assertEquals(2 * FastMath.PI / reference.getNorm(), 2 * FastMath.PI / spin0.getNorm(), 0.05);
163 Assertions.assertEquals(0.0, FastMath.toDegrees(Vector3D.angle(reference, spin0)), 1.0e-10);
164 Assertions.assertEquals(0.0, FastMath.toDegrees(Vector3D.angle(Vector3D.PLUS_K, spin0)), 1.0e-10);
165
166 }
167
168 private <T extends CalculusFieldElement<T>> void checkField(final Field<T> field, final AttitudeProvider provider,
169 final Orbit orbit, final AbsoluteDate date,
170 final Frame frame)
171 {
172 Attitude attitudeD = provider.getAttitude(orbit, date, frame);
173 final FieldOrbit<T> orbitF = new FieldSpacecraftState<>(field, new SpacecraftState(orbit)).getOrbit();
174 final FieldAbsoluteDate<T> dateF = new FieldAbsoluteDate<>(field, date);
175 FieldAttitude<T> attitudeF = provider.getAttitude(orbitF, dateF, frame);
176 Assertions.assertEquals(0.0, Rotation.distance(attitudeD.getRotation(), attitudeF.getRotation().toRotation()), 1.0e-15);
177 Assertions.assertEquals(0.0, Vector3D.distance(attitudeD.getSpin(), attitudeF.getSpin().toVector3D()), 1.0e-15);
178 Assertions.assertEquals(0.0, Vector3D.distance(attitudeD.getRotationAcceleration(), attitudeF.getRotationAcceleration().toVector3D()), 1.0e-15);
179 }
180
181 @BeforeEach
182 public void setUp() {
183 Utils.setDataRoot("regular-data");
184 }
185
186 }
187