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.GeodeticPoint;
32 import org.orekit.bodies.OneAxisEllipsoid;
33 import org.orekit.errors.OrekitException;
34 import org.orekit.errors.OrekitMessages;
35 import org.orekit.frames.Frame;
36 import org.orekit.frames.FramesFactory;
37 import org.orekit.frames.StaticTransform;
38 import org.orekit.orbits.*;
39 import org.orekit.propagation.FieldSpacecraftState;
40 import org.orekit.propagation.Propagator;
41 import org.orekit.propagation.SpacecraftState;
42 import org.orekit.propagation.analytical.KeplerianPropagator;
43 import org.orekit.time.AbsoluteDate;
44 import org.orekit.time.DateComponents;
45 import org.orekit.time.FieldAbsoluteDate;
46 import org.orekit.time.TimeComponents;
47 import org.orekit.time.TimeScalesFactory;
48 import org.orekit.utils.AngularCoordinates;
49 import org.orekit.utils.Constants;
50 import org.orekit.utils.IERSConventions;
51 import org.orekit.utils.PVCoordinates;
52 import org.orekit.utils.TimeStampedFieldPVCoordinates;
53 import org.orekit.utils.TimeStampedPVCoordinates;
54
55
56 class TargetPointingTest {
57
58
59 private AbsoluteDate date;
60
61
62 private double mu;
63
64
65 private Frame itrf;
66
67
68 private StaticTransform eme2000ToItrf;
69
70
71
72 @Test
73 void testConstructors() {
74
75
76
77 CircularOrbit circ =
78 new CircularOrbit(7178000.0, 0.5e-4, -0.5e-4, FastMath.toRadians(50.), FastMath.toRadians(270.),
79 FastMath.toRadians(5.300), PositionAngleType.MEAN,
80 FramesFactory.getEME2000(), date, mu);
81
82
83
84
85 OneAxisEllipsoid earthShape = new OneAxisEllipsoid(6378136.460, 1 / 298.257222101, itrf);
86
87
88 GeodeticPoint geoTargetITRF = new GeodeticPoint(FastMath.toRadians(43.36), FastMath.toRadians(1.26), 600.);
89 Vector3D pTargetITRF = earthShape.transform(geoTargetITRF);
90
91
92 TargetPointing geoTargetAttitudeLaw = new TargetPointing(circ.getFrame(), geoTargetITRF, earthShape);
93
94
95 TargetPointing pvTargetAttitudeLaw = new TargetPointing(circ.getFrame(), itrf, pTargetITRF);
96
97
98
99 Rotation rotPv = pvTargetAttitudeLaw.getAttitude(circ, date, circ.getFrame()).getRotation();
100
101
102 Rotation rotGeo = geoTargetAttitudeLaw.getAttitude(circ, date, circ.getFrame()).getRotation();
103
104
105 Rotation rotCompo = rotGeo.composeInverse(rotPv, RotationConvention.VECTOR_OPERATOR);
106 double angle = rotCompo.getAngle();
107 Assertions.assertEquals(angle, 0.0, Utils.epsilonAngle);
108
109 }
110
111
112
113 @Test
114 void testGeodeticConstructor() {
115
116
117
118 CircularOrbit circ =
119 new CircularOrbit(7178000.0, 0.5e-4, -0.5e-4, FastMath.toRadians(50.), FastMath.toRadians(270.),
120 FastMath.toRadians(5.300), PositionAngleType.MEAN,
121 FramesFactory.getEME2000(), date, mu);
122
123
124
125
126
127 OneAxisEllipsoid earthShape = new OneAxisEllipsoid(6378136.460, 1 / 298.257222101, itrf);
128
129
130 GeodeticPoint geoTargetITRF = new GeodeticPoint(FastMath.toRadians(43.36), FastMath.toRadians(1.26), 600.);
131
132
133 TargetPointing geoTargetAttitudeLaw = new TargetPointing(circ.getFrame(), geoTargetITRF, earthShape);
134
135
136 Vector3D pObservedEME2000 = geoTargetAttitudeLaw.getTargetPV(circ, date, FramesFactory.getEME2000()).getPosition();
137 GeodeticPoint geoObserved = earthShape.transform(pObservedEME2000, FramesFactory.getEME2000(), date);
138
139 Assertions.assertEquals(geoObserved.getLongitude(), geoTargetITRF.getLongitude(), Utils.epsilonAngle);
140 Assertions.assertEquals(geoObserved.getLatitude(), geoTargetITRF.getLatitude(), Utils.epsilonAngle);
141 Assertions.assertEquals(geoObserved.getAltitude(), geoTargetITRF.getAltitude(), 1.1e-8);
142
143 }
144
145 @Test
146 void testIssue115() {
147
148
149
150 CircularOrbit circ =
151 new CircularOrbit(7178000.0, 0.5e-4, -0.5e-4, FastMath.toRadians(50.), FastMath.toRadians(270.),
152 FastMath.toRadians(5.300), PositionAngleType.MEAN,
153 FramesFactory.getEME2000(), date, mu);
154
155
156
157
158
159 OneAxisEllipsoid earthShape = new OneAxisEllipsoid(6378136.460, 1 / 298.257222101, itrf);
160
161
162 GeodeticPoint geoTargetITRF = new GeodeticPoint(FastMath.toRadians(43.36), FastMath.toRadians(1.26), 600.);
163
164
165 TargetPointing geoTargetAttitudeLaw = new TargetPointing(circ.getFrame(), geoTargetITRF, earthShape);
166
167
168 Frame cirf = FramesFactory.getCIRF(IERSConventions.IERS_2010, true);
169 Attitude att1 = geoTargetAttitudeLaw.getAttitude(circ, date, cirf);
170 Attitude att2 = geoTargetAttitudeLaw.getAttitude(circ, date, itrf);
171 Attitude att3 = att2.withReferenceFrame(cirf);
172 Assertions.assertEquals(0.0, Rotation.distance(att3.getRotation(), att1.getRotation()), 1.0e-15);
173
174 }
175
176 @Test
177 void testWrongFrame() {
178 try {
179
180 new TargetPointing(itrf, FramesFactory.getEME2000(),
181 new Vector3D(Constants.WGS84_EARTH_EQUATORIAL_RADIUS, 0, 0));
182 Assertions.fail("an exception should have been thrown");
183 } catch (OrekitException oe) {
184 Assertions.assertEquals(OrekitMessages.NON_PSEUDO_INERTIAL_FRAME, oe.getSpecifier());
185 Assertions.assertEquals(itrf.getName(), oe.getParts()[0]);
186 }
187 }
188
189
190
191
192 @Test
193 void testNadirTarget() {
194
195
196 OneAxisEllipsoid earthShape = new OneAxisEllipsoid(6378136.460, 1 / 298.257222101, itrf);
197
198
199 CircularOrbit circOrbit =
200 new CircularOrbit(7178000.0, 1.e-5, 0., FastMath.toRadians(50.), 0.,
201 FastMath.toRadians(90.), PositionAngleType.TRUE,
202 FramesFactory.getEME2000(), date, mu);
203
204
205
206
207
208 NadirPointing nadirAttitudeLaw = new NadirPointing(circOrbit.getFrame(), earthShape);
209
210
211 Vector3D pNadirTarget = nadirAttitudeLaw.getTargetPV(circOrbit, date, itrf).getPosition();
212 GeodeticPoint geoNadirTarget = earthShape.transform(pNadirTarget, itrf, date);
213
214
215 TargetPointing targetAttitudeLaw = new TargetPointing(circOrbit.getFrame(), geoNadirTarget, earthShape);
216
217
218
219
220
221
222
223 Rotation rotTarget = targetAttitudeLaw.getAttitude(circOrbit, date, circOrbit.getFrame()).getRotation();
224
225
226 Rotation rotNadir = nadirAttitudeLaw.getAttitude(circOrbit, date, circOrbit.getFrame()).getRotation();
227
228
229 Rotation rotCompo = rotTarget.composeInverse(rotNadir, RotationConvention.VECTOR_OPERATOR);
230 double angle = rotCompo.getAngle();
231 Assertions.assertEquals(angle, 0.0, Utils.epsilonAngle);
232
233
234
235
236
237
238 KeplerianPropagator extrapolator = new KeplerianPropagator(circOrbit);
239 double delta_t = 60.0;
240 AbsoluteDate extrapDate = date.shiftedBy(delta_t);
241 Orbit extrapOrbit = extrapolator.propagate(extrapDate).getOrbit();
242
243
244
245 Rotation extrapRotTarget = targetAttitudeLaw.getAttitude(extrapOrbit, extrapDate, extrapOrbit.getFrame()).getRotation();
246
247
248 Rotation extrapRotNadir = nadirAttitudeLaw.getAttitude(extrapOrbit, extrapDate, extrapOrbit.getFrame()).getRotation();
249
250
251 Rotation extrapRotCompo = extrapRotTarget.composeInverse(extrapRotNadir, RotationConvention.VECTOR_OPERATOR);
252 double extrapAngle = extrapRotCompo.getAngle();
253 Assertions.assertEquals(extrapAngle, FastMath.toRadians(24.684793905118823), Utils.epsilonAngle);
254
255 }
256
257
258
259 @Test
260 void testTargetInPointingDirection() {
261
262
263 AbsoluteDate date = new AbsoluteDate(new DateComponents(2008, 04, 07),
264 TimeComponents.H00,
265 TimeScalesFactory.getUTC());
266
267
268 Frame itrf = FramesFactory.getITRF(IERSConventions.IERS_2010, true);
269
270
271 OneAxisEllipsoid earthShape = new OneAxisEllipsoid(6378136.460, 1 / 298.257222101, itrf);
272
273
274 GeodeticPoint geoTarget = new GeodeticPoint(FastMath.toRadians(43.36), FastMath.toRadians(1.26), 600.);
275 TargetPointing targetAttitudeLaw = new TargetPointing(FramesFactory.getEME2000(), geoTarget, earthShape);
276
277
278
279
280 CircularOrbit circ =
281 new CircularOrbit(7178000.0, 0.5e-4, -0.5e-4, FastMath.toRadians(50.), FastMath.toRadians(270.),
282 FastMath.toRadians(5.300), PositionAngleType.MEAN,
283 FramesFactory.getEME2000(), date, mu);
284
285
286 PVCoordinates pvSatEME2000 = circ.getPVCoordinates();
287
288
289
290
291 Rotation rotSatEME2000 = targetAttitudeLaw.getAttitude(circ, date, circ.getFrame()).getRotation();
292
293
294 Vector3D zSatEME2000 = rotSatEME2000.applyInverseTo(Vector3D.PLUS_K);
295
296
297 Vector3D p = eme2000ToItrf.transformPosition(pvSatEME2000.getPosition());
298 Line pointingLine = new Line(p,
299 p.add(Constants.WGS84_EARTH_EQUATORIAL_RADIUS,
300 eme2000ToItrf.transformVector(zSatEME2000)),
301 1.0e-10);
302
303
304 double distance = pointingLine.distance(earthShape.transform(geoTarget));
305
306 Assertions.assertEquals(0, distance, 1.e-7);
307 }
308
309
310
311 @Test
312 void testSlewedTarget() {
313
314
315 OneAxisEllipsoid earthShape = new OneAxisEllipsoid(6378136.460, 0., itrf);
316
317
318
319
320 CircularOrbit circ =
321 new CircularOrbit(42164000.0, 0.5e-8, -0.5e-8, 0., 0.,
322 FastMath.toRadians(5.300), PositionAngleType.MEAN,
323 FramesFactory.getEME2000(), date, mu);
324
325
326
327 NadirPointing nadirAttitudeLaw = new NadirPointing(circ.getFrame(), earthShape);
328
329
330 Vector3D pNadirObservedEME2000 = nadirAttitudeLaw.getTargetPV(circ, date, FramesFactory.getEME2000()).getPosition();
331 Vector3D pNadirObservedITRF = eme2000ToItrf.transformPosition(pNadirObservedEME2000);
332
333 GeodeticPoint geoNadirObserved = earthShape.transform(pNadirObservedITRF, itrf, date);
334
335
336
337 TargetPointing targetLawRef = new TargetPointing(circ.getFrame(), itrf, pNadirObservedITRF);
338
339
340 Rotation rotSatRefEME2000 = targetLawRef.getAttitude(circ, date, circ.getFrame()).getRotation();
341
342
343
344 GeodeticPoint geoTarget = new GeodeticPoint(geoNadirObserved.getLatitude(),
345 geoNadirObserved.getLongitude() - FastMath.toRadians(5), geoNadirObserved.getAltitude());
346 Vector3D pTargetITRF = earthShape.transform(geoTarget);
347 TargetPointing targetLaw = new TargetPointing(circ.getFrame(), itrf, pTargetITRF);
348
349
350 Rotation rotSatEME2000 = targetLaw.getAttitude(circ, date, circ.getFrame()).getRotation();
351
352 checkField(Binary64Field.getInstance(), targetLaw, circ, circ.getDate(), circ.getFrame());
353
354
355
356
357
358 double tanDeltaExpected = (6378136.460/(42164000.0-6378136.460))*FastMath.tan(FastMath.toRadians(5));
359 double deltaExpected = FastMath.atan(tanDeltaExpected);
360
361
362 double deltaReal = Rotation.distance(rotSatEME2000, rotSatRefEME2000);
363
364 Assertions.assertEquals(deltaReal, deltaExpected, 1.e-4);
365
366 }
367
368 @Test
369 void testSpin() {
370
371 Frame itrf = FramesFactory.getITRF(IERSConventions.IERS_2010, true);
372
373
374 OneAxisEllipsoid earthShape = new OneAxisEllipsoid(6378136.460, 1 / 298.257222101, itrf);
375
376
377 GeodeticPoint geoTarget = new GeodeticPoint(FastMath.toRadians(43.36), FastMath.toRadians(1.26), 600.);
378 AttitudeProvider law = new TargetPointing(FramesFactory.getEME2000(), geoTarget, earthShape);
379
380 KeplerianOrbit orbit =
381 new KeplerianOrbit(7178000.0, 1.e-4, FastMath.toRadians(50.),
382 FastMath.toRadians(10.), FastMath.toRadians(20.),
383 FastMath.toRadians(30.), PositionAngleType.MEAN,
384 FramesFactory.getEME2000(), date, 3.986004415e14);
385
386 Propagator propagator = new KeplerianPropagator(orbit, law);
387
388 double h = 0.01;
389 SpacecraftState sMinus = propagator.propagate(date.shiftedBy(-h));
390 SpacecraftState s0 = propagator.propagate(date);
391 SpacecraftState sPlus = propagator.propagate(date.shiftedBy(h));
392
393
394 double errorAngleMinus = Rotation.distance(sMinus.shiftedBy(h).getAttitude().getRotation(),
395 s0.getAttitude().getRotation());
396 double evolutionAngleMinus = Rotation.distance(sMinus.getAttitude().getRotation(),
397 s0.getAttitude().getRotation());
398 Assertions.assertEquals(0.0, errorAngleMinus, 1.0e-5 * evolutionAngleMinus);
399 double errorAnglePlus = Rotation.distance(s0.getAttitude().getRotation(),
400 sPlus.shiftedBy(-h).getAttitude().getRotation());
401 double evolutionAnglePlus = Rotation.distance(s0.getAttitude().getRotation(),
402 sPlus.getAttitude().getRotation());
403 Assertions.assertEquals(0.0, errorAnglePlus, 1.0e-5 * evolutionAnglePlus);
404
405 Vector3D spin0 = s0.getAttitude().getSpin();
406 Vector3D reference = AngularCoordinates.estimateRate(sMinus.getAttitude().getRotation(),
407 sPlus.getAttitude().getRotation(),
408 2 * h);
409 Assertions.assertEquals(0.0, spin0.subtract(reference).getNorm(), 1.1e-10);
410
411 }
412
413 private <T extends CalculusFieldElement<T>> void checkField(final Field<T> field, final GroundPointing provider,
414 final Orbit orbit, final AbsoluteDate date,
415 final Frame frame)
416 {
417
418 final Attitude attitudeD = provider.getAttitude(orbit, date, frame);
419 final FieldOrbit<T> orbitF = new FieldSpacecraftState<>(field, new SpacecraftState(orbit)).getOrbit();
420 final FieldAbsoluteDate<T> dateF = new FieldAbsoluteDate<>(field, date);
421 final FieldAttitude<T> attitudeF = provider.getAttitude(orbitF, dateF, frame);
422 Assertions.assertEquals(0.0, Rotation.distance(attitudeD.getRotation(), attitudeF.getRotation().toRotation()), 1.0e-15);
423 Assertions.assertEquals(0.0, Vector3D.distance(attitudeD.getSpin(), attitudeF.getSpin().toVector3D()), 1.0e-15);
424 Assertions.assertEquals(0.0, Vector3D.distance(attitudeD.getRotationAcceleration(), attitudeF.getRotationAcceleration().toVector3D()), 1.0e-15);
425
426 final TimeStampedPVCoordinates pvD = provider.getTargetPV(orbit, date, frame);
427 final TimeStampedFieldPVCoordinates<T> pvF = provider.getTargetPV(orbitF, dateF, frame);
428 Assertions.assertEquals(0.0, Vector3D.distance(pvD.getPosition(), pvF.getPosition().toVector3D()), 1.0e-15);
429 Assertions.assertEquals(0.0, Vector3D.distance(pvD.getVelocity(), pvF.getVelocity().toVector3D()), 1.0e-15);
430 Assertions.assertEquals(0.0, Vector3D.distance(pvD.getAcceleration(), pvF.getAcceleration().toVector3D()), 1.0e-15);
431
432 }
433
434
435 @Test
436 void testGetTargetPosition() {
437
438 final CircularOrbit circOrbit =
439 new CircularOrbit(7178000.0, 1.e-5, 0., FastMath.toRadians(50.), 0.,
440 FastMath.toRadians(90.), PositionAngleType.TRUE, FramesFactory.getEME2000(), date, mu);
441 final TargetPointing law = new TargetPointing(circOrbit.getFrame(), FramesFactory.getGTOD(false),
442 Vector3D.PLUS_J);
443
444 final Vector3D actualPosition = law.getTargetPosition(circOrbit, circOrbit.getDate(), circOrbit.getFrame());
445
446 final Vector3D expectedPosition = law.getTargetPV(circOrbit, circOrbit.getDate(), circOrbit.getFrame()).getPosition();
447 Assertions.assertEquals(expectedPosition, actualPosition);
448 }
449
450 @Test
451 void testGetTargetPositionField() {
452
453 final CircularOrbit circOrbit =
454 new CircularOrbit(7178000.0, 1.e-5, 0., FastMath.toRadians(50.), 0.,
455 FastMath.toRadians(90.), PositionAngleType.TRUE, FramesFactory.getEME2000(), date, mu);
456 final TargetPointing law = new TargetPointing(circOrbit.getFrame(), FramesFactory.getGTOD(false),
457 Vector3D.PLUS_J);
458 final FieldCircularOrbit<Complex> fieldOrbit = new FieldCircularOrbit<>(ComplexField.getInstance(), circOrbit);
459
460 final FieldVector3D<Complex> actualPosition = law.getTargetPosition(fieldOrbit, fieldOrbit.getDate(), fieldOrbit.getFrame());
461
462 final FieldVector3D<Complex> expectedPosition = law.getTargetPV(fieldOrbit, fieldOrbit.getDate(), fieldOrbit.getFrame()).getPosition();
463 Assertions.assertEquals(0., actualPosition.subtract(expectedPosition).getNorm().getReal(), 1e-10);
464 }
465
466 @BeforeEach
467 public void setUp() {
468 try {
469
470 Utils.setDataRoot("regular-data");
471
472
473 date = new AbsoluteDate(new DateComponents(2008, 04, 07),
474 TimeComponents.H00,
475 TimeScalesFactory.getUTC());
476
477
478 mu = 3.9860047e14;
479
480
481 itrf = FramesFactory.getITRF(IERSConventions.IERS_2010, true);
482
483
484 eme2000ToItrf = FramesFactory.getEME2000().getStaticTransformTo(itrf, date);
485
486 } catch (OrekitException oe) {
487 Assertions.fail(oe.getMessage());
488 }
489
490 }
491
492 @AfterEach
493 public void tearDown() {
494 date = null;
495 itrf = null;
496 eme2000ToItrf = null;
497 }
498
499 }
500