1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.attitudes;
18
19
20 import java.util.ArrayList;
21 import java.util.List;
22
23 import org.hipparchus.Field;
24 import org.hipparchus.CalculusFieldElement;
25 import org.hipparchus.geometry.euclidean.threed.Rotation;
26 import org.hipparchus.geometry.euclidean.threed.RotationConvention;
27 import org.hipparchus.geometry.euclidean.threed.Vector3D;
28 import org.hipparchus.util.Decimal64Field;
29 import org.hipparchus.util.FastMath;
30 import org.junit.After;
31 import org.junit.Assert;
32 import org.junit.Before;
33 import org.junit.Test;
34 import org.orekit.Utils;
35 import org.orekit.bodies.GeodeticPoint;
36 import org.orekit.bodies.OneAxisEllipsoid;
37 import org.orekit.errors.OrekitException;
38 import org.orekit.frames.Frame;
39 import org.orekit.frames.FramesFactory;
40 import org.orekit.orbits.CircularOrbit;
41 import org.orekit.orbits.FieldOrbit;
42 import org.orekit.orbits.KeplerianOrbit;
43 import org.orekit.orbits.Orbit;
44 import org.orekit.orbits.PositionAngle;
45 import org.orekit.propagation.FieldSpacecraftState;
46 import org.orekit.propagation.Propagator;
47 import org.orekit.propagation.SpacecraftState;
48 import org.orekit.propagation.analytical.KeplerianPropagator;
49 import org.orekit.time.AbsoluteDate;
50 import org.orekit.time.DateComponents;
51 import org.orekit.time.FieldAbsoluteDate;
52 import org.orekit.time.TimeComponents;
53 import org.orekit.time.TimeScalesFactory;
54 import org.orekit.utils.AngularCoordinates;
55 import org.orekit.utils.CartesianDerivativesFilter;
56 import org.orekit.utils.IERSConventions;
57 import org.orekit.utils.TimeStampedFieldPVCoordinates;
58 import org.orekit.utils.TimeStampedPVCoordinates;
59
60
61 public class NadirPointingTest {
62
63
64 private AbsoluteDate date;
65
66
67 private double mu;
68
69
70 private Frame itrf;
71
72
73
74
75 @Test
76 public void testSphericEarth() {
77
78
79 OneAxisEllipsoid earthShape = new OneAxisEllipsoid(6378136.460, 0., itrf);
80
81
82 NadirPointing nadirAttitudeLaw = new NadirPointing(FramesFactory.getEME2000(), earthShape);
83
84
85 BodyCenterPointing earthCenterAttitudeLaw =
86 new BodyCenterPointing(FramesFactory.getEME2000(), earthShape);
87
88
89 CircularOrbit circ =
90 new CircularOrbit(7178000.0, 0.5e-4, -0.5e-4, FastMath.toRadians(50.), FastMath.toRadians(270.),
91 FastMath.toRadians(5.300), PositionAngle.MEAN,
92 FramesFactory.getEME2000(), date, mu);
93
94
95 Rotation rotNadir = nadirAttitudeLaw.getAttitude(circ, date, circ.getFrame()).getRotation();
96
97
98 Rotation rotCenter = earthCenterAttitudeLaw.getAttitude(circ, date, circ.getFrame()).getRotation();
99
100
101
102
103 Rotation rotCompo = rotCenter.composeInverse(rotNadir, RotationConvention.VECTOR_OPERATOR);
104 double angle = rotCompo.getAngle();
105 Assert.assertEquals(angle, 0.0, Utils.epsilonAngle);
106
107 }
108
109
110
111
112
113 @Test
114 public void testNonSphericEarth() {
115
116
117 OneAxisEllipsoid earthShape = new OneAxisEllipsoid(6378136.460, 1 / 298.257222101, itrf);
118
119
120 NadirPointing nadirAttitudeLaw = new NadirPointing(FramesFactory.getEME2000(), earthShape);
121
122
123 BodyCenterPointing earthCenterAttitudeLaw =
124 new BodyCenterPointing(FramesFactory.getEME2000(), earthShape);
125
126
127
128 KeplerianOrbit kep =
129 new KeplerianOrbit(7178000.0, 1.e-8, FastMath.toRadians(50.), 0., 0.,
130 0., PositionAngle.TRUE, FramesFactory.getEME2000(), date, mu);
131
132
133 Rotation rotNadir = nadirAttitudeLaw.getAttitude(kep, date, kep.getFrame()).getRotation();
134
135 checkField(Decimal64Field.getInstance(), nadirAttitudeLaw, kep, kep.getDate(), kep.getFrame());
136
137
138 Rotation rotCenter = earthCenterAttitudeLaw.getAttitude(kep, date, kep.getFrame()).getRotation();
139
140
141
142
143 Rotation rotCompo = rotCenter.composeInverse(rotNadir, RotationConvention.VECTOR_OPERATOR);
144 double angle = rotCompo.getAngle();
145 Assert.assertEquals(0.0, angle, 5.e-6);
146
147
148
149 CircularOrbit circ =
150 new CircularOrbit(7178000.0, 1.e-5, 0., FastMath.toRadians(90.), 0.,
151 FastMath.toRadians(90.), PositionAngle.TRUE,
152 FramesFactory.getEME2000(), date, mu);
153
154
155 rotNadir = nadirAttitudeLaw.getAttitude(circ, date, circ.getFrame()).getRotation();
156
157
158 rotCenter = earthCenterAttitudeLaw.getAttitude(circ, date, circ.getFrame()).getRotation();
159
160
161
162
163 rotCompo = rotCenter.composeInverse(rotNadir, RotationConvention.VECTOR_OPERATOR);
164 angle = rotCompo.getAngle();
165 Assert.assertEquals(angle, 0.0, 5.e-6);
166
167
168
169 circ =
170 new CircularOrbit(7178000.0, 1.e-5, 0., FastMath.toRadians(50.), 0.,
171 FastMath.toRadians(90.), PositionAngle.TRUE,
172 FramesFactory.getEME2000(), date, mu);
173
174
175 rotNadir = nadirAttitudeLaw.getAttitude(circ, date, circ.getFrame()).getRotation();
176
177
178 rotCenter = earthCenterAttitudeLaw.getAttitude(circ, date, circ.getFrame()).getRotation();
179
180
181
182
183 rotCompo = rotCenter.composeInverse(rotNadir, RotationConvention.VECTOR_OPERATOR);
184 angle = rotCompo.getAngle();
185 Assert.assertEquals(angle, FastMath.toRadians(0.16797386586252272), Utils.epsilonAngle);
186 }
187
188
189
190
191
192
193
194 @Test
195 public void testVertical() {
196
197
198 OneAxisEllipsoid earthShape = new OneAxisEllipsoid(6378136.460, 1 / 298.257222101, itrf);
199
200
201 NadirPointing nadirAttitudeLaw = new NadirPointing(FramesFactory.getEME2000(), earthShape);
202
203
204 CircularOrbit circ =
205 new CircularOrbit(7178000.0, 1.e-5, 0., FastMath.toRadians(50.), 0.,
206 FastMath.toRadians(90.), PositionAngle.TRUE,
207 FramesFactory.getEME2000(), date, mu);
208
209
210
211
212 TimeStampedPVCoordinates pvTargetItrf = nadirAttitudeLaw.getTargetPV(circ, date, itrf);
213
214
215 GeodeticPoint geoTarget = earthShape.transform(pvTargetItrf.getPosition(), itrf, date);
216
217
218 double xVert = FastMath.cos(geoTarget.getLongitude())*FastMath.cos(geoTarget.getLatitude());
219 double yVert = FastMath.sin(geoTarget.getLongitude())*FastMath.cos(geoTarget.getLatitude());
220 double zVert = FastMath.sin(geoTarget.getLatitude());
221 Vector3D targetVertical = new Vector3D(xVert, yVert, zVert);
222
223
224 Rotation rotSatEME2000 = nadirAttitudeLaw.getAttitude(circ, date, circ.getFrame()).getRotation();
225
226
227 Vector3D zSatEME2000 = rotSatEME2000.applyInverseTo(Vector3D.PLUS_K);
228 Vector3D zSatItrf = FramesFactory.getEME2000().getTransformTo(itrf, date).transformVector(zSatEME2000);
229
230
231 double angle= Vector3D.angle(zSatItrf, targetVertical);
232 Assert.assertEquals(0.0, FastMath.sin(angle), Utils.epsilonTest);
233
234 }
235
236
237
238 @Test
239 public void testSlidingDerivatives() {
240
241
242 OneAxisEllipsoid earthShape = new OneAxisEllipsoid(6378136.460, 1 / 298.257222101, itrf);
243
244
245 NadirPointing nadirAttitudeLaw = new NadirPointing(FramesFactory.getEME2000(), earthShape);
246
247
248 CircularOrbit circ =
249 new CircularOrbit(7178000.0, 1.e-5, 0., FastMath.toRadians(50.), 0.,
250 FastMath.toRadians(90.), PositionAngle.TRUE,
251 FramesFactory.getEME2000(), date, mu);
252
253 List<TimeStampedPVCoordinates> sample = new ArrayList<TimeStampedPVCoordinates>();
254 for (double dt = -0.1; dt < 0.1; dt += 0.05) {
255 Orbit o = circ.shiftedBy(dt);
256 sample.add(nadirAttitudeLaw.getTargetPV(o, o.getDate(), o.getFrame()));
257 }
258 TimeStampedPVCoordinates reference =
259 TimeStampedPVCoordinates.interpolate(circ.getDate(),
260 CartesianDerivativesFilter.USE_P, sample);
261
262 TimeStampedPVCoordinates target =
263 nadirAttitudeLaw.getTargetPV(circ, circ.getDate(), circ.getFrame());
264
265 Assert.assertEquals(0.0,
266 Vector3D.distance(reference.getPosition(), target.getPosition()),
267 1.0e-15 * reference.getPosition().getNorm());
268 Assert.assertEquals(0.0,
269 Vector3D.distance(reference.getVelocity(), target.getVelocity()),
270 3.0e-11 * reference.getVelocity().getNorm());
271 Assert.assertEquals(0.0,
272 Vector3D.distance(reference.getAcceleration(), target.getAcceleration()),
273 1.3e-5 * reference.getAcceleration().getNorm());
274
275 }
276
277 @Test
278 public void testSpin() {
279
280
281 OneAxisEllipsoid earthShape = new OneAxisEllipsoid(6378136.460, 1 / 298.257222101, itrf);
282
283
284 NadirPointing law = new NadirPointing(FramesFactory.getEME2000(), earthShape);
285
286
287 KeplerianOrbit orbit =
288 new KeplerianOrbit(7178000.0, 1.e-4, FastMath.toRadians(50.),
289 FastMath.toRadians(10.), FastMath.toRadians(20.),
290 FastMath.toRadians(30.), PositionAngle.MEAN,
291 FramesFactory.getEME2000(), date, mu);
292
293 Propagator propagator = new KeplerianPropagator(orbit, law, mu, 2500.0);
294
295 double h = 0.1;
296 SpacecraftState sMinus = propagator.propagate(date.shiftedBy(-h));
297 SpacecraftState s0 = propagator.propagate(date);
298 SpacecraftState sPlus = propagator.propagate(date.shiftedBy(h));
299
300
301 double errorAngleMinus = Rotation.distance(sMinus.shiftedBy(h).getAttitude().getRotation(),
302 s0.getAttitude().getRotation());
303 double evolutionAngleMinus = Rotation.distance(sMinus.getAttitude().getRotation(),
304 s0.getAttitude().getRotation());
305 Assert.assertEquals(0.0, errorAngleMinus, 5.3e-9 * evolutionAngleMinus);
306 double errorAnglePlus = Rotation.distance(s0.getAttitude().getRotation(),
307 sPlus.shiftedBy(-h).getAttitude().getRotation());
308 double evolutionAnglePlus = Rotation.distance(s0.getAttitude().getRotation(),
309 sPlus.getAttitude().getRotation());
310 Assert.assertEquals(0.0, errorAnglePlus, 8.1e-9 * evolutionAnglePlus);
311
312 Vector3D spin0 = s0.getAttitude().getSpin();
313 Rotation rM = sMinus.getAttitude().getRotation();
314 Rotation rP = sPlus.getAttitude().getRotation();
315 Vector3D reference = AngularCoordinates.estimateRate(rM, rP, 2 * h);
316 Assert.assertTrue(Rotation.distance(rM, rP) > 2.0e-4);
317 Assert.assertEquals(0.0, spin0.subtract(reference).getNorm(), 2.0e-6);
318
319 }
320
321 private <T extends CalculusFieldElement<T>> void checkField(final Field<T> field, final GroundPointing provider,
322 final Orbit orbit, final AbsoluteDate date,
323 final Frame frame)
324 {
325
326 final Attitude attitudeD = provider.getAttitude(orbit, date, frame);
327 final FieldOrbit<T> orbitF = new FieldSpacecraftState<>(field, new SpacecraftState(orbit)).getOrbit();
328 final FieldAbsoluteDate<T> dateF = new FieldAbsoluteDate<>(field, date);
329 final FieldAttitude<T> attitudeF = provider.getAttitude(orbitF, dateF, frame);
330 Assert.assertEquals(0.0, Rotation.distance(attitudeD.getRotation(), attitudeF.getRotation().toRotation()), 1.0e-15);
331 Assert.assertEquals(0.0, Vector3D.distance(attitudeD.getSpin(), attitudeF.getSpin().toVector3D()), 2.0e-14);
332 Assert.assertEquals(0.0, Vector3D.distance(attitudeD.getRotationAcceleration(), attitudeF.getRotationAcceleration().toVector3D()), 4.0e-12);
333
334 final TimeStampedPVCoordinates pvD = provider.getTargetPV(orbit, date, frame);
335 final TimeStampedFieldPVCoordinates<T> pvF = provider.getTargetPV(orbitF, dateF, frame);
336 Assert.assertEquals(0.0, Vector3D.distance(pvD.getPosition(), pvF.getPosition().toVector3D()), 1.0e-15);
337 Assert.assertEquals(0.0, Vector3D.distance(pvD.getVelocity(), pvF.getVelocity().toVector3D()), 2.0e-8);
338 Assert.assertEquals(0.0, Vector3D.distance(pvD.getAcceleration(), pvF.getAcceleration().toVector3D()), 3.0e-5);
339
340 }
341
342 @Before
343 public void setUp() {
344 try {
345
346 Utils.setDataRoot("regular-data");
347
348
349 date = new AbsoluteDate(new DateComponents(2008, 04, 07),
350 TimeComponents.H00,
351 TimeScalesFactory.getUTC());
352
353
354 mu = 3.9860047e14;
355
356
357 itrf = FramesFactory.getITRF(IERSConventions.IERS_2010, true);
358
359 } catch (OrekitException oe) {
360 Assert.fail(oe.getMessage());
361 }
362
363 }
364
365 @After
366 public void tearDown() {
367 date = null;
368 itrf = null;
369 }
370
371 }
372