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.*;
24 import org.hipparchus.util.Binary64Field;
25 import org.hipparchus.util.FastMath;
26 import org.junit.jupiter.api.AfterEach;
27 import org.junit.jupiter.api.Assertions;
28 import org.junit.jupiter.api.BeforeEach;
29 import org.junit.jupiter.api.Test;
30 import org.orekit.Utils;
31 import org.orekit.bodies.OneAxisEllipsoid;
32 import org.orekit.errors.OrekitException;
33 import org.orekit.errors.OrekitMessages;
34 import org.orekit.frames.Frame;
35 import org.orekit.frames.FramesFactory;
36 import org.orekit.frames.LOFType;
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.IERSConventions;
49 import org.orekit.utils.TimeStampedFieldPVCoordinates;
50 import org.orekit.utils.TimeStampedPVCoordinates;
51
52
53 class LofOffsetPointingTest {
54
55
56 private AbsoluteDate date;
57
58
59 private double mu;
60
61
62 private Frame frameItrf;
63
64
65 OneAxisEllipsoid earthSpheric;
66
67
68
69 @Test
70 void testLof() {
71
72
73 final CircularOrbit circ =
74 new CircularOrbit(7178000.0, 0.5e-4, -0.5e-4, FastMath.toRadians(0.), FastMath.toRadians(270.),
75 FastMath.toRadians(5.300), PositionAngleType.MEAN,
76 FramesFactory.getEME2000(), date, mu);
77
78
79
80 final LofOffset lofLaw = new LofOffset(circ.getFrame(), LOFType.LVLH_CCSDS);
81 final LofOffsetPointing lofPointing = new LofOffsetPointing(circ.getFrame(), earthSpheric, lofLaw, Vector3D.PLUS_K);
82 final Rotation
83 lofRot = lofPointing.getAttitude(circ, date, circ.getFrame()).getRotation();
84
85
86
87 final BodyCenterPointing centerLaw = new BodyCenterPointing(circ.getFrame(), earthSpheric);
88 final Rotation centerRot = centerLaw.getAttitude(circ, date, circ.getFrame()).getRotation();
89 final double angleBodyCenter = centerRot.composeInverse(lofRot, RotationConvention.VECTOR_OPERATOR).getAngle();
90 Assertions.assertEquals(0., angleBodyCenter, Utils.epsilonAngle);
91
92
93
94 final NadirPointing nadirLaw = new NadirPointing(circ.getFrame(), earthSpheric);
95 final Rotation nadirRot = nadirLaw.getAttitude(circ, date, circ.getFrame()).getRotation();
96 final double angleNadir = nadirRot.composeInverse(lofRot, RotationConvention.VECTOR_OPERATOR).getAngle();
97 Assertions.assertEquals(0., angleNadir, Utils.epsilonAngle);
98
99 }
100
101 @Test
102 void testMiss() {
103 final CircularOrbit circ =
104 new CircularOrbit(7178000.0, 0.5e-4, -0.5e-4, FastMath.toRadians(0.), FastMath.toRadians(270.),
105 FastMath.toRadians(5.300), PositionAngleType.MEAN,
106 FramesFactory.getEME2000(), date, mu);
107 final LofOffset upsideDown = new LofOffset(circ.getFrame(), LOFType.LVLH_CCSDS, RotationOrder.XYX, FastMath.PI, 0, 0);
108 final LofOffsetPointing pointing = new LofOffsetPointing(circ.getFrame(), earthSpheric, upsideDown, Vector3D.PLUS_K);
109 try {
110 pointing.getTargetPV(circ, date, circ.getFrame());
111 Assertions.fail("an exception should have been thrown");
112 } catch (OrekitException oe) {
113 Assertions.assertEquals(OrekitMessages.ATTITUDE_POINTING_LAW_DOES_NOT_POINT_TO_GROUND, oe.getSpecifier());
114 }
115 }
116
117 @Test
118 void testSpin() {
119
120 AbsoluteDate date = new AbsoluteDate(new DateComponents(1970, 1, 1),
121 new TimeComponents(3, 25, 45.6789),
122 TimeScalesFactory.getUTC());
123 KeplerianOrbit orbit =
124 new KeplerianOrbit(7178000.0, 1.e-4, FastMath.toRadians(50.),
125 FastMath.toRadians(10.), FastMath.toRadians(20.),
126 FastMath.toRadians(30.), PositionAngleType.MEAN,
127 FramesFactory.getEME2000(), date, 3.986004415e14);
128
129 final AttitudeProvider law =
130 new LofOffsetPointing(orbit.getFrame(), earthSpheric,
131 new LofOffset(orbit.getFrame(), LOFType.LVLH_CCSDS, RotationOrder.XYX, 0.1, 0.2, 0.3),
132 Vector3D.PLUS_K);
133
134 Propagator propagator = new KeplerianPropagator(orbit, law);
135
136 double h = 0.01;
137 SpacecraftState sMinus = propagator.propagate(date.shiftedBy(-h));
138 SpacecraftState s0 = propagator.propagate(date);
139 SpacecraftState sPlus = propagator.propagate(date.shiftedBy(h));
140
141
142 double errorAngleMinus = Rotation.distance(sMinus.shiftedBy(h).getAttitude().getRotation(),
143 s0.getAttitude().getRotation());
144 double evolutionAngleMinus = Rotation.distance(sMinus.getAttitude().getRotation(),
145 s0.getAttitude().getRotation());
146 Assertions.assertEquals(0.0, errorAngleMinus, 1.0e-6 * evolutionAngleMinus);
147 double errorAnglePlus = Rotation.distance(s0.getAttitude().getRotation(),
148 sPlus.shiftedBy(-h).getAttitude().getRotation());
149 double evolutionAnglePlus = Rotation.distance(s0.getAttitude().getRotation(),
150 sPlus.getAttitude().getRotation());
151 Assertions.assertEquals(0.0, errorAnglePlus, 1.0e-6 * evolutionAnglePlus);
152
153 Vector3D spin0 = s0.getAttitude().getSpin();
154 Vector3D reference = AngularCoordinates.estimateRate(sMinus.getAttitude().getRotation(),
155 sPlus.getAttitude().getRotation(),
156 2 * h);
157 Assertions.assertTrue(spin0.getNorm() > 1.0e-3);
158 Assertions.assertEquals(0.0, spin0.subtract(reference).getNorm(), 1.0e-10);
159
160 }
161
162 @Test
163 void testTypesField() {
164 AbsoluteDate date = new AbsoluteDate(new DateComponents(1970, 1, 1),
165 new TimeComponents(3, 25, 45.6789),
166 TimeScalesFactory.getUTC());
167 KeplerianOrbit orbit =
168 new KeplerianOrbit(7178000.0, 1.e-4, FastMath.toRadians(50.),
169 FastMath.toRadians(10.), FastMath.toRadians(20.),
170 FastMath.toRadians(30.), PositionAngleType.MEAN,
171 FramesFactory.getEME2000(), date, 3.986004415e14);
172
173 for (final LOFType type : LOFType.values()) {
174 RotationOrder order = RotationOrder.ZXY;
175 double alpha1 = 0.123;
176 double alpha2 = 0.456;
177 double alpha3 = 0.789;
178 LofOffset law = new LofOffset(orbit.getFrame(), type, order, alpha1, alpha2, alpha3);
179 final Vector3D dir;
180 switch (type) {
181 case TNW:
182 dir = Vector3D.PLUS_J;
183 break;
184 case QSW:
185 dir = Vector3D.MINUS_I;
186 break;
187 case LVLH:
188 dir = Vector3D.MINUS_I;
189 break;
190 case LVLH_CCSDS:
191 dir = Vector3D.PLUS_K;
192 break;
193 case VNC:
194 dir = Vector3D.MINUS_K;
195 break;
196 case NTW:
197 dir = Vector3D.MINUS_I;
198 break;
199 default :
200
201 continue;
202 }
203 LofOffsetPointing lop = new LofOffsetPointing(orbit.getFrame(), earthSpheric, law, dir);
204 checkField(Binary64Field.getInstance(), lop, orbit, date, orbit.getFrame());
205 }
206 }
207
208 private <T extends CalculusFieldElement<T>> void checkField(final Field<T> field, final GroundPointing provider,
209 final Orbit orbit, final AbsoluteDate date,
210 final Frame frame)
211 {
212
213 final Attitude attitudeD = provider.getAttitude(orbit, date, frame);
214 final FieldOrbit<T> orbitF = new FieldSpacecraftState<>(field, new SpacecraftState(orbit)).getOrbit();
215 final FieldAbsoluteDate<T> dateF = new FieldAbsoluteDate<>(field, date);
216 final FieldAttitude<T> attitudeF = provider.getAttitude(orbitF, dateF, frame);
217 final double tolerance = 1e-15;
218 Assertions.assertEquals(0.0, Rotation.distance(attitudeD.getRotation(), attitudeF.getRotation().toRotation()), tolerance);
219 Assertions.assertEquals(0.0, Vector3D.distance(attitudeD.getSpin(), attitudeF.getSpin().toVector3D()), tolerance);
220 Assertions.assertEquals(0.0, Vector3D.distance(attitudeD.getRotationAcceleration(), attitudeF.getRotationAcceleration().toVector3D()), tolerance);
221
222 final Rotation rotationD = provider.getAttitudeRotation(orbit, date, frame);
223 final FieldRotation<T> rotationF = provider.getAttitudeRotation(orbitF, dateF, frame);
224 Assertions.assertEquals(0.0, Rotation.distance(rotationD, rotationF.toRotation()), tolerance);
225
226 final TimeStampedPVCoordinates pvD = provider.getTargetPV(orbit, date, frame);
227 final TimeStampedFieldPVCoordinates<T> pvF = provider.getTargetPV(orbitF, dateF, frame);
228
229 Assertions.assertEquals(0.0, Vector3D.distance(pvD.getPosition(), pvF.getPosition().toVector3D()), 2.0e-8);
230 Assertions.assertEquals(0.0, Vector3D.distance(pvD.getVelocity(), pvF.getVelocity().toVector3D()), 3.0e-8);
231 Assertions.assertEquals(0.0, Vector3D.distance(pvD.getAcceleration(), pvF.getAcceleration().toVector3D()), 2.0e-5);
232 }
233
234 @Test
235 void testGetAttitudeRotation() {
236
237 final CircularOrbit circ =
238 new CircularOrbit(7178000.0, 0.5e-4, -0.5e-4, FastMath.toRadians(0.), FastMath.toRadians(270.),
239 FastMath.toRadians(5.300), PositionAngleType.MEAN,
240 FramesFactory.getEME2000(), date, mu);
241 final LofOffset upsideDown = new LofOffset(circ.getFrame(), LOFType.LVLH_CCSDS, RotationOrder.XYX, FastMath.PI, 0, 0);
242 final LofOffsetPointing pointing = new LofOffsetPointing(circ.getFrame(), earthSpheric, upsideDown, Vector3D.PLUS_K);
243
244 final Rotation actualRotation = pointing.getAttitudeRotation(circ, circ.getDate(), circ.getFrame());
245
246 final Rotation expectedRotation = pointing.getAttitude(circ, circ.getDate(), circ.getFrame()).getRotation();
247 Assertions.assertEquals(0., Rotation.distance(expectedRotation, actualRotation));
248 }
249
250 @Test
251 void testGetTargetPosition() {
252
253 final CircularOrbit circ =
254 new CircularOrbit(7178000.0, 0.5e-4, -0.5e-4, FastMath.toRadians(0.), FastMath.toRadians(270.),
255 FastMath.toRadians(5.300), PositionAngleType.MEAN,
256 FramesFactory.getEME2000(), date, mu);
257 final LofOffset upsideDown = new LofOffset(circ.getFrame(), LOFType.QSW, RotationOrder.XYX, -1., 2., 3.);
258 final LofOffsetPointing pointing = new LofOffsetPointing(circ.getFrame(), earthSpheric, upsideDown, Vector3D.PLUS_K);
259
260 final Vector3D targetPosition = pointing.getTargetPosition(circ, circ.getDate(), circ.getFrame());
261
262 final Vector3D expectedPosition = pointing.getTargetPV(circ, circ.getDate(), circ.getFrame()).getPosition();
263 Assertions.assertEquals(expectedPosition, targetPosition);
264 }
265
266 @Test
267 void testGetTargetPositionField() {
268
269 final CircularOrbit circ =
270 new CircularOrbit(7178000.0, 0.5e-4, -0.5e-4, FastMath.toRadians(0.), FastMath.toRadians(270.),
271 FastMath.toRadians(5.300), PositionAngleType.MEAN,
272 FramesFactory.getEME2000(), date, mu);
273 final LofOffset upsideDown = new LofOffset(circ.getFrame(), LOFType.QSW, RotationOrder.XYX, -1., 2., 3.);
274 final LofOffsetPointing pointing = new LofOffsetPointing(circ.getFrame(), earthSpheric, upsideDown, Vector3D.PLUS_K);
275 final FieldCircularOrbit<Complex> fieldOrbit = new FieldCircularOrbit<>(ComplexField.getInstance(), circ);
276
277 final FieldVector3D<Complex> targetPosition = pointing.getTargetPosition(fieldOrbit, fieldOrbit.getDate(), fieldOrbit.getFrame());
278
279 final FieldVector3D<Complex> expectedPosition = pointing.getTargetPV(fieldOrbit, fieldOrbit.getDate(), fieldOrbit.getFrame()).getPosition();
280 Assertions.assertEquals(0., expectedPosition.subtract(targetPosition).getNorm().getReal(), 1.4e-9);
281 }
282
283 @BeforeEach
284 public void setUp() {
285 try {
286
287 Utils.setDataRoot("regular-data");
288
289
290 date = new AbsoluteDate(new DateComponents(2008, 4, 7),
291 TimeComponents.H00,
292 TimeScalesFactory.getUTC());
293
294
295 mu = 3.9860047e14;
296
297
298 frameItrf = FramesFactory.getITRF(IERSConventions.IERS_2010, false);
299
300
301 earthSpheric =
302 new OneAxisEllipsoid(6378136.460, 0., frameItrf);
303
304 } catch (OrekitException oe) {
305 Assertions.fail(oe.getMessage());
306 }
307
308 }
309
310 @AfterEach
311 public void tearDown() {
312 date = null;
313 frameItrf = null;
314 earthSpheric = null;
315 }
316 }
317