1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.forces;
18
19
20 import java.util.List;
21
22 import org.hipparchus.Field;
23 import org.hipparchus.analysis.differentiation.DSFactory;
24 import org.hipparchus.analysis.differentiation.DerivativeStructure;
25 import org.hipparchus.geometry.euclidean.threed.FieldRotation;
26 import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
27 import org.hipparchus.geometry.euclidean.threed.Rotation;
28 import org.hipparchus.geometry.euclidean.threed.Vector3D;
29 import org.hipparchus.util.Decimal64;
30 import org.hipparchus.util.Decimal64Field;
31 import org.hipparchus.util.FastMath;
32 import org.hipparchus.util.Precision;
33 import org.junit.Assert;
34 import org.junit.Before;
35 import org.junit.Test;
36 import org.orekit.OrekitMatchers;
37 import org.orekit.Utils;
38 import org.orekit.attitudes.LofOffset;
39 import org.orekit.bodies.CelestialBody;
40 import org.orekit.bodies.CelestialBodyFactory;
41 import org.orekit.errors.OrekitException;
42 import org.orekit.errors.OrekitMessages;
43 import org.orekit.forces.drag.DragSensitive;
44 import org.orekit.forces.radiation.RadiationSensitive;
45 import org.orekit.frames.Frame;
46 import org.orekit.frames.FramesFactory;
47 import org.orekit.frames.LOFType;
48 import org.orekit.orbits.CircularOrbit;
49 import org.orekit.orbits.Orbit;
50 import org.orekit.orbits.PositionAngle;
51 import org.orekit.propagation.Propagator;
52 import org.orekit.propagation.SpacecraftState;
53 import org.orekit.propagation.analytical.EcksteinHechlerPropagator;
54 import org.orekit.time.AbsoluteDate;
55 import org.orekit.time.DateComponents;
56 import org.orekit.time.FieldAbsoluteDate;
57 import org.orekit.time.TimeComponents;
58 import org.orekit.time.TimeScalesFactory;
59 import org.orekit.utils.ParameterDriver;
60 import org.orekit.utils.TimeStampedPVCoordinates;
61
62 public class BoxAndSolarArraySpacecraftTest {
63
64 @Test
65 public void testParametersDrivers() throws OrekitException {
66
67 CelestialBody sun = CelestialBodyFactory.getSun();
68 BoxAndSolarArraySpacecraft.Facet[] facets = new BoxAndSolarArraySpacecraft.Facet[] {
69 new BoxAndSolarArraySpacecraft.Facet(Vector3D.MINUS_I, 3.0),
70 new BoxAndSolarArraySpacecraft.Facet(Vector3D.PLUS_I, 3.0),
71 new BoxAndSolarArraySpacecraft.Facet(Vector3D.MINUS_J, 3.0),
72 new BoxAndSolarArraySpacecraft.Facet(Vector3D.PLUS_J, 3.0),
73 new BoxAndSolarArraySpacecraft.Facet(Vector3D.MINUS_K, 3.0),
74 new BoxAndSolarArraySpacecraft.Facet(Vector3D.PLUS_K, 3.0)
75 };
76
77 BoxAndSolarArraySpacecraft s1 =
78 new BoxAndSolarArraySpacecraft(1.5, 3.5, 2.5, sun, 20.0, Vector3D.PLUS_J, 2.0, 0.8, 0.1);
79 Assert.assertEquals(1, s1.getDragParametersDrivers().length);
80 Assert.assertEquals(DragSensitive.DRAG_COEFFICIENT, s1.getDragParametersDrivers()[0].getName());
81 Assert.assertEquals(2.0, s1.getDragParametersDrivers()[0].getValue(), 1.0e-15);
82 Assert.assertEquals(2, s1.getRadiationParametersDrivers().length);
83 Assert.assertEquals(RadiationSensitive.ABSORPTION_COEFFICIENT, s1.getRadiationParametersDrivers()[0].getName());
84 Assert.assertEquals(0.8, s1.getRadiationParametersDrivers()[0].getValue(), 1.0e-15);
85 Assert.assertEquals(RadiationSensitive.REFLECTION_COEFFICIENT, s1.getRadiationParametersDrivers()[1].getName());
86 Assert.assertEquals(0.1, s1.getRadiationParametersDrivers()[1].getValue(), 1.0e-15);
87
88 BoxAndSolarArraySpacecraft s2 =
89 new BoxAndSolarArraySpacecraft(1.5, 3.5, 2.5, sun, 20.0, Vector3D.PLUS_J, 2.0, 0.4, 0.8, 0.1);
90 Assert.assertEquals(2, s2.getDragParametersDrivers().length);
91 Assert.assertEquals(DragSensitive.DRAG_COEFFICIENT, s2.getDragParametersDrivers()[0].getName());
92 Assert.assertEquals(2.0, s2.getDragParametersDrivers()[0].getValue(), 1.0e-15);
93 Assert.assertEquals(DragSensitive.LIFT_RATIO, s2.getDragParametersDrivers()[1].getName());
94 Assert.assertEquals(0.4, s2.getDragParametersDrivers()[1].getValue(), 1.0e-15);
95 Assert.assertEquals(2, s2.getRadiationParametersDrivers().length);
96 Assert.assertEquals(RadiationSensitive.ABSORPTION_COEFFICIENT, s2.getRadiationParametersDrivers()[0].getName());
97 Assert.assertEquals(0.8, s2.getRadiationParametersDrivers()[0].getValue(), 1.0e-15);
98 Assert.assertEquals(RadiationSensitive.REFLECTION_COEFFICIENT, s2.getRadiationParametersDrivers()[1].getName());
99 Assert.assertEquals(0.1, s2.getRadiationParametersDrivers()[1].getValue(), 1.0e-15);
100
101 BoxAndSolarArraySpacecraft s3 =
102 new BoxAndSolarArraySpacecraft(facets, sun, 20.0, Vector3D.PLUS_J, 2.0, 0.8, 0.1);
103 Assert.assertEquals(1, s3.getDragParametersDrivers().length);
104 Assert.assertEquals(DragSensitive.DRAG_COEFFICIENT, s3.getDragParametersDrivers()[0].getName());
105 Assert.assertEquals(2.0, s3.getDragParametersDrivers()[0].getValue(), 1.0e-15);
106 Assert.assertEquals(2, s3.getRadiationParametersDrivers().length);
107 Assert.assertEquals(RadiationSensitive.ABSORPTION_COEFFICIENT, s3.getRadiationParametersDrivers()[0].getName());
108 Assert.assertEquals(0.8, s3.getRadiationParametersDrivers()[0].getValue(), 1.0e-15);
109 Assert.assertEquals(RadiationSensitive.REFLECTION_COEFFICIENT, s3.getRadiationParametersDrivers()[1].getName());
110 Assert.assertEquals(0.1, s3.getRadiationParametersDrivers()[1].getValue(), 1.0e-15);
111
112 BoxAndSolarArraySpacecraft s4 =
113 new BoxAndSolarArraySpacecraft(facets, sun, 20.0, Vector3D.PLUS_J, 2.0, 0.4, 0.8, 0.1);
114 Assert.assertEquals(2, s4.getDragParametersDrivers().length);
115 Assert.assertEquals(DragSensitive.DRAG_COEFFICIENT, s4.getDragParametersDrivers()[0].getName());
116 Assert.assertEquals(2.0, s4.getDragParametersDrivers()[0].getValue(), 1.0e-15);
117 Assert.assertEquals(DragSensitive.LIFT_RATIO, s4.getDragParametersDrivers()[1].getName());
118 Assert.assertEquals(0.4, s4.getDragParametersDrivers()[1].getValue(), 1.0e-15);
119 Assert.assertEquals(2, s4.getRadiationParametersDrivers().length);
120 Assert.assertEquals(RadiationSensitive.ABSORPTION_COEFFICIENT, s4.getRadiationParametersDrivers()[0].getName());
121 Assert.assertEquals(0.8, s4.getRadiationParametersDrivers()[0].getValue(), 1.0e-15);
122 Assert.assertEquals(RadiationSensitive.REFLECTION_COEFFICIENT, s4.getRadiationParametersDrivers()[1].getName());
123 Assert.assertEquals(0.1, s4.getRadiationParametersDrivers()[1].getValue(), 1.0e-15);
124
125 BoxAndSolarArraySpacecraft s5 =
126 new BoxAndSolarArraySpacecraft(1.5, 3.5, 2.5, sun, 20.0, Vector3D.PLUS_J,
127 AbsoluteDate.J2000_EPOCH, Vector3D.PLUS_I, 7.292e-5,
128 2.0, 0.8, 0.1);
129 Assert.assertEquals(1, s5.getDragParametersDrivers().length);
130 Assert.assertEquals(DragSensitive.DRAG_COEFFICIENT, s5.getDragParametersDrivers()[0].getName());
131 Assert.assertEquals(2.0, s5.getDragParametersDrivers()[0].getValue(), 1.0e-15);
132 Assert.assertEquals(2, s5.getRadiationParametersDrivers().length);
133 Assert.assertEquals(RadiationSensitive.ABSORPTION_COEFFICIENT, s5.getRadiationParametersDrivers()[0].getName());
134 Assert.assertEquals(0.8, s5.getRadiationParametersDrivers()[0].getValue(), 1.0e-15);
135 Assert.assertEquals(RadiationSensitive.REFLECTION_COEFFICIENT, s5.getRadiationParametersDrivers()[1].getName());
136 Assert.assertEquals(0.1, s5.getRadiationParametersDrivers()[1].getValue(), 1.0e-15);
137
138 BoxAndSolarArraySpacecraft s6 =
139 new BoxAndSolarArraySpacecraft(1.5, 3.5, 2.5, sun, 20.0, Vector3D.PLUS_J,
140 AbsoluteDate.J2000_EPOCH, Vector3D.PLUS_I, 7.292e-5,
141 2.0, 0.4, 0.8, 0.1);
142 Assert.assertEquals(2, s6.getDragParametersDrivers().length);
143 Assert.assertEquals(DragSensitive.DRAG_COEFFICIENT, s6.getDragParametersDrivers()[0].getName());
144 Assert.assertEquals(2.0, s6.getDragParametersDrivers()[0].getValue(), 1.0e-15);
145 Assert.assertEquals(DragSensitive.LIFT_RATIO, s6.getDragParametersDrivers()[1].getName());
146 Assert.assertEquals(0.4, s6.getDragParametersDrivers()[1].getValue(), 1.0e-15);
147 Assert.assertEquals(2, s6.getRadiationParametersDrivers().length);
148 Assert.assertEquals(RadiationSensitive.ABSORPTION_COEFFICIENT, s6.getRadiationParametersDrivers()[0].getName());
149 Assert.assertEquals(0.8, s6.getRadiationParametersDrivers()[0].getValue(), 1.0e-15);
150 Assert.assertEquals(RadiationSensitive.REFLECTION_COEFFICIENT, s6.getRadiationParametersDrivers()[1].getName());
151 Assert.assertEquals(0.1, s6.getRadiationParametersDrivers()[1].getValue(), 1.0e-15);
152
153 BoxAndSolarArraySpacecraft s7 =
154 new BoxAndSolarArraySpacecraft(facets, sun, 20.0, Vector3D.PLUS_J,
155 AbsoluteDate.J2000_EPOCH, Vector3D.PLUS_I, 7.292e-5,
156 2.0, 0.8, 0.1);
157 Assert.assertEquals(1, s7.getDragParametersDrivers().length);
158 Assert.assertEquals(DragSensitive.DRAG_COEFFICIENT, s7.getDragParametersDrivers()[0].getName());
159 Assert.assertEquals(2.0, s7.getDragParametersDrivers()[0].getValue(), 1.0e-15);
160 Assert.assertEquals(2, s7.getRadiationParametersDrivers().length);
161 Assert.assertEquals(RadiationSensitive.ABSORPTION_COEFFICIENT, s7.getRadiationParametersDrivers()[0].getName());
162 Assert.assertEquals(0.8, s7.getRadiationParametersDrivers()[0].getValue(), 1.0e-15);
163 Assert.assertEquals(RadiationSensitive.REFLECTION_COEFFICIENT, s7.getRadiationParametersDrivers()[1].getName());
164 Assert.assertEquals(0.1, s7.getRadiationParametersDrivers()[1].getValue(), 1.0e-15);
165
166 BoxAndSolarArraySpacecraft s8 =
167 new BoxAndSolarArraySpacecraft(facets, sun, 20.0, Vector3D.PLUS_J,
168 AbsoluteDate.J2000_EPOCH, Vector3D.PLUS_I, 7.292e-5,
169 2.0, 0.4, 0.8, 0.1);
170 Assert.assertEquals(2, s8.getDragParametersDrivers().length);
171 Assert.assertEquals(DragSensitive.DRAG_COEFFICIENT, s8.getDragParametersDrivers()[0].getName());
172 Assert.assertEquals(2.0, s8.getDragParametersDrivers()[0].getValue(), 1.0e-15);
173 Assert.assertEquals(DragSensitive.LIFT_RATIO, s8.getDragParametersDrivers()[1].getName());
174 Assert.assertEquals(0.4, s8.getDragParametersDrivers()[1].getValue(), 1.0e-15);
175 Assert.assertEquals(2, s8.getRadiationParametersDrivers().length);
176 Assert.assertEquals(RadiationSensitive.ABSORPTION_COEFFICIENT, s8.getRadiationParametersDrivers()[0].getName());
177 Assert.assertEquals(0.8, s8.getRadiationParametersDrivers()[0].getValue(), 1.0e-15);
178 Assert.assertEquals(RadiationSensitive.REFLECTION_COEFFICIENT, s8.getRadiationParametersDrivers()[1].getName());
179 Assert.assertEquals(0.1, s8.getRadiationParametersDrivers()[1].getValue(), 1.0e-15);
180
181 }
182
183 @Test
184 public void testBestPointing() throws OrekitException {
185
186 AbsoluteDate initialDate = propagator.getInitialState().getDate();
187 CelestialBody sun = CelestialBodyFactory.getSun();
188 BoxAndSolarArraySpacecraft s =
189 new BoxAndSolarArraySpacecraft(1.5, 3.5, 2.5, sun, 20.0, Vector3D.PLUS_J, 0.0, 0.0, 0.0);
190 for (double dt = 0; dt < 4000; dt += 60) {
191
192 SpacecraftState state = propagator.propagate(initialDate.shiftedBy(dt));
193
194 Vector3D sunInert = sun.getPVCoordinates(initialDate, state.getFrame()).getPosition();
195 Vector3D momentum = state.getPVCoordinates().getMomentum();
196 double sunElevation = FastMath.PI / 2 - Vector3D.angle(sunInert, momentum);
197 Assert.assertEquals(15.1, FastMath.toDegrees(sunElevation), 0.1);
198
199 Vector3D n = s.getNormal(state.getDate(), state.getFrame(),
200 state.getPVCoordinates().getPosition(),
201 state.getAttitude().getRotation());
202 Assert.assertEquals(0.0, n.getY(), 1.0e-10);
203
204
205 Vector3D sunSat = state.getAttitude().getRotation().applyTo(sunInert);
206 double misAlignment = Vector3D.angle(sunSat, n);
207 Assert.assertEquals(sunElevation, misAlignment, 1.0e-3);
208
209 }
210 }
211
212 @Test
213 public void testCorrectFixedRate() throws OrekitException {
214
215 AbsoluteDate initialDate = propagator.getInitialState().getDate();
216 CelestialBody sun = CelestialBodyFactory.getSun();
217 BoxAndSolarArraySpacecraft s =
218 new BoxAndSolarArraySpacecraft(1.5, 3.5, 2.5, sun, 20.0, Vector3D.PLUS_J,
219 initialDate,
220 new Vector3D(0.46565509814462996, 0.0, 0.884966287251619),
221 propagator.getInitialState().getKeplerianMeanMotion(),
222 0.0, 0.0, 0.0);
223
224 for (double dt = 0; dt < 4000; dt += 60) {
225
226 SpacecraftState state = propagator.propagate(initialDate.shiftedBy(dt));
227
228 Vector3D sunInert = sun.getPVCoordinates(initialDate, state.getFrame()).getPosition();
229 Vector3D momentum = state.getPVCoordinates().getMomentum();
230 double sunElevation = FastMath.PI / 2 - Vector3D.angle(sunInert, momentum);
231 Assert.assertEquals(15.1, FastMath.toDegrees(sunElevation), 0.1);
232
233 Vector3D n = s.getNormal(state.getDate(), state.getFrame(),
234 state.getPVCoordinates().getPosition(),
235 state.getAttitude().getRotation());
236 Assert.assertEquals(0.0, n.getY(), 1.0e-10);
237
238
239 Vector3D sunSat = state.getAttitude().getRotation().applyTo(sunInert);
240 double misAlignment = Vector3D.angle(sunSat, n);
241 Assert.assertEquals(sunElevation, misAlignment, 1.0e-3);
242
243 }
244 }
245
246 @Test
247 public void testTooSlowFixedRate() throws OrekitException {
248
249 AbsoluteDate initialDate = propagator.getInitialState().getDate();
250 CelestialBody sun = CelestialBodyFactory.getSun();
251 BoxAndSolarArraySpacecraft s =
252 new BoxAndSolarArraySpacecraft(1.5, 3.5, 2.5, sun, 20.0, Vector3D.PLUS_J,
253 initialDate,
254 new Vector3D(0.46565509814462996, 0.0, 0.884966287251619),
255 0.1 * propagator.getInitialState().getKeplerianMeanMotion(),
256 0.0, 0.0, 0.0);
257
258 double maxDelta = 0;
259 for (double dt = 0; dt < 4000; dt += 60) {
260
261 SpacecraftState state = propagator.propagate(initialDate.shiftedBy(dt));
262
263 Vector3D sunInert = sun.getPVCoordinates(initialDate, state.getFrame()).getPosition();
264 Vector3D momentum = state.getPVCoordinates().getMomentum();
265 double sunElevation = FastMath.PI / 2 - Vector3D.angle(sunInert, momentum);
266 Assert.assertEquals(15.1, FastMath.toDegrees(sunElevation), 0.1);
267
268 Vector3D n = s.getNormal(state.getDate(), state.getFrame(),
269 state.getPVCoordinates().getPosition(),
270 state.getAttitude().getRotation());
271 Assert.assertEquals(0.0, n.getY(), 1.0e-10);
272
273
274 Vector3D sunSat = state.getAttitude().getRotation().applyTo(sunInert);
275 double misAlignment = Vector3D.angle(sunSat, n);
276 maxDelta = FastMath.max(maxDelta, FastMath.abs(sunElevation - misAlignment));
277
278 }
279 Assert.assertTrue(FastMath.toDegrees(maxDelta) > 120.0);
280
281 }
282
283 @Test
284 public void testNoLiftWithoutReflection() throws OrekitException {
285
286 AbsoluteDate initialDate = propagator.getInitialState().getDate();
287 CelestialBody sun = CelestialBodyFactory.getSun();
288 BoxAndSolarArraySpacecraft s =
289 new BoxAndSolarArraySpacecraft(1.5, 3.5, 2.5, sun, 20.0, Vector3D.PLUS_J, 1.0, 0.0, 1.0, 0.0);
290
291 Vector3D earthRot = new Vector3D(0.0, 0.0, 7.292115e-4);
292 for (double dt = 0; dt < 4000; dt += 60) {
293
294 AbsoluteDate date = initialDate.shiftedBy(dt);
295 SpacecraftState state = propagator.propagate(date);
296
297
298 Vector3D p = state.getPVCoordinates().getPosition();
299 Vector3D v = state.getPVCoordinates().getVelocity();
300 Vector3D vAtm = Vector3D.crossProduct(earthRot, p);
301 Vector3D relativeVelocity = vAtm.subtract(v);
302
303 Vector3D drag = s.dragAcceleration(state.getDate(), state.getFrame(),
304 state.getPVCoordinates().getPosition(),
305 state.getAttitude().getRotation(),
306 state.getMass(), 0.001, relativeVelocity,
307 getDragParameters(s));
308 Assert.assertEquals(0.0, Vector3D.angle(relativeVelocity, drag), 1.0e-15);
309
310 Vector3D sunDirection = sun.getPVCoordinates(date, state.getFrame()).getPosition().normalize();
311 Vector3D flux = new Vector3D(-4.56e-6, sunDirection);
312 Vector3D radiation = s.radiationPressureAcceleration(state.getDate(), state.getFrame(),
313 state.getPVCoordinates().getPosition(),
314 state.getAttitude().getRotation(),
315 state.getMass(), flux,
316 getRadiationParameters(s));
317 Assert.assertEquals(0.0, Vector3D.angle(flux, radiation), 1.0e-9);
318
319 }
320
321 }
322
323 @Test
324 public void testOnlyLiftWithoutReflection() throws OrekitException {
325
326 AbsoluteDate initialDate = propagator.getInitialState().getDate();
327 CelestialBody sun = CelestialBodyFactory.getSun();
328 BoxAndSolarArraySpacecraft s =
329 new BoxAndSolarArraySpacecraft(1.5, 3.5, 2.5, sun, 20.0, Vector3D.PLUS_J, 1.0, 1.0, 1.0, 0.0);
330
331 Vector3D earthRot = new Vector3D(0.0, 0.0, 7.292115e-4);
332 for (double dt = 0; dt < 4000; dt += 60) {
333
334 AbsoluteDate date = initialDate.shiftedBy(dt);
335 SpacecraftState state = propagator.propagate(date);
336
337
338 Vector3D p = state.getPVCoordinates().getPosition();
339 Vector3D v = state.getPVCoordinates().getVelocity();
340 Vector3D vAtm = Vector3D.crossProduct(earthRot, p);
341 Vector3D relativeVelocity = vAtm.subtract(v);
342
343 Vector3D drag = s.dragAcceleration(state.getDate(), state.getFrame(),
344 state.getPVCoordinates().getPosition(),
345 state.getAttitude().getRotation(),
346 state.getMass(), 0.001, relativeVelocity,
347 getDragParameters(s));
348 Assert.assertTrue(Vector3D.angle(relativeVelocity, drag) > 0.167);
349 Assert.assertTrue(Vector3D.angle(relativeVelocity, drag) < 0.736);
350
351 Vector3D sunDirection = sun.getPVCoordinates(date, state.getFrame()).getPosition().normalize();
352 Vector3D flux = new Vector3D(-4.56e-6, sunDirection);
353 Vector3D radiation = s.radiationPressureAcceleration(state.getDate(), state.getFrame(),
354 state.getPVCoordinates().getPosition(),
355 state.getAttitude().getRotation(),
356 state.getMass(), flux,
357 getRadiationParameters(s));
358 Assert.assertEquals(0.0, Vector3D.angle(flux, radiation), 1.0e-9);
359
360 }
361
362 }
363
364 @Test
365 public void testLiftVsNoLift()
366 throws OrekitException, NoSuchFieldException, SecurityException,
367 IllegalArgumentException, IllegalAccessException {
368
369 CelestialBody sun = CelestialBodyFactory.getSun();
370
371
372
373
374
375 BoxAndSolarArraySpacecraft.Facet[] facets = new BoxAndSolarArraySpacecraft.Facet[] {
376 new BoxAndSolarArraySpacecraft.Facet(Vector3D.MINUS_I, 3.0),
377 new BoxAndSolarArraySpacecraft.Facet(Vector3D.PLUS_I, 3.0),
378 new BoxAndSolarArraySpacecraft.Facet(Vector3D.MINUS_J, 3.0),
379 new BoxAndSolarArraySpacecraft.Facet(Vector3D.PLUS_J, 3.0),
380 new BoxAndSolarArraySpacecraft.Facet(Vector3D.MINUS_K, 3.0),
381 new BoxAndSolarArraySpacecraft.Facet(Vector3D.PLUS_K, 3.0)
382 };
383 BoxAndSolarArraySpacecraft cube =
384 new BoxAndSolarArraySpacecraft(facets, sun, 0.0, Vector3D.PLUS_J, 1.0, 1.0, 1.0, 0.0);
385
386 AbsoluteDate date = AbsoluteDate.J2000_EPOCH;
387 Frame frame = FramesFactory.getEME2000();
388 Vector3D position = new Vector3D(1234567.8, 9876543.21, 121212.3434);
389 double mass = 1000.0;
390 double density = 0.001;
391 Rotation rotation = Rotation.IDENTITY;
392
393
394 Vector3D headOnVelocity = new Vector3D(2000, 0.0, 0.0);
395 Vector3D newHeadOnDrag = cube.dragAcceleration(date, frame, position, rotation, mass, density, headOnVelocity,
396 getDragParameters(cube));
397 Vector3D oldHeadOnDrag = oldDragAcceleration(cube, date, frame, position, rotation, mass, density, headOnVelocity);
398 Assert.assertThat(newHeadOnDrag, OrekitMatchers.vectorCloseTo(oldHeadOnDrag.scalarMultiply(2), 1));
399
400
401
402
403
404
405
406 Vector3D diagonalVelocity = new Vector3D(2000, 2000, 2000);
407 Vector3D newDiagDrag= cube.dragAcceleration(date, frame, position, rotation, mass, density, diagonalVelocity,
408 getDragParameters(cube));
409 Vector3D oldDiagDrag = oldDragAcceleration(cube, date, frame, position, rotation, mass, density, diagonalVelocity);
410 double oldMissingCoeff = 2.0 / FastMath.sqrt(3.0);
411 Vector3D fixedOldDrag = new Vector3D(oldMissingCoeff, oldDiagDrag);
412 Assert.assertThat(newDiagDrag, OrekitMatchers.vectorCloseTo(fixedOldDrag, 1));
413
414 }
415
416
417
418
419 private Vector3D oldDragAcceleration(final BoxAndSolarArraySpacecraft bsa,
420 final AbsoluteDate date, final Frame frame, final Vector3D position,
421 final Rotation rotation, final double mass,
422 final double density, final Vector3D relativeVelocity)
423 throws OrekitException, IllegalArgumentException, IllegalAccessException,
424 NoSuchFieldException, SecurityException {
425
426 java.lang.reflect.Field facetsField = BoxAndSolarArraySpacecraft.class.getDeclaredField("facets");
427 facetsField.setAccessible(true);
428 @SuppressWarnings("unchecked")
429 final List<BoxAndSolarArraySpacecraft.Facet> facets = (List<BoxAndSolarArraySpacecraft.Facet>) facetsField.get(bsa);
430
431 java.lang.reflect.Field saAreaField = BoxAndSolarArraySpacecraft.class.getDeclaredField("solarArrayArea");
432 saAreaField.setAccessible(true);
433 final double solarArrayArea = (Double) saAreaField.get(bsa);
434
435 final double dragCoeff = bsa.getDragParametersDrivers()[0].getValue();
436
437
438 final Vector3D v = rotation.applyTo(relativeVelocity);
439
440
441 final Vector3D solarArrayFacet = new Vector3D(solarArrayArea, bsa.getNormal(date, frame, position, rotation));
442 double sv = FastMath.abs(Vector3D.dotProduct(solarArrayFacet, v));
443
444
445 for (final BoxAndSolarArraySpacecraft.Facet facet : facets) {
446 final double dot = Vector3D.dotProduct(facet.getNormal(), v);
447 if (dot < 0) {
448
449 sv -= facet.getArea() * dot;
450 }
451 }
452
453 return new Vector3D(sv * density * dragCoeff / (2.0 * mass), relativeVelocity);
454
455 }
456
457 @Test
458 public void testPlaneSpecularReflection() throws OrekitException {
459
460 AbsoluteDate initialDate = propagator.getInitialState().getDate();
461 CelestialBody sun = CelestialBodyFactory.getSun();
462 BoxAndSolarArraySpacecraft s =
463 new BoxAndSolarArraySpacecraft(0, 0, 0, sun, 20.0, Vector3D.PLUS_J, 0.0, 0.0, 1.0);
464
465 for (double dt = 0; dt < 4000; dt += 60) {
466
467 AbsoluteDate date = initialDate.shiftedBy(dt);
468 SpacecraftState state = propagator.propagate(date);
469
470 Vector3D sunDirection = sun.getPVCoordinates(date, state.getFrame()).getPosition().normalize();
471 Vector3D flux = new Vector3D(-4.56e-6, sunDirection);
472 Vector3D acceleration = s.radiationPressureAcceleration(state.getDate(), state.getFrame(),
473 state.getPVCoordinates().getPosition(),
474 state.getAttitude().getRotation(),
475 state.getMass(), flux,
476 getRadiationParameters(s));
477 Vector3D normal = state.getAttitude().getRotation().applyInverseTo(s.getNormal(state.getDate(), state.getFrame(),
478 state.getPVCoordinates().getPosition(),
479 state.getAttitude().getRotation()));
480
481
482 Assert.assertEquals(15.1, FastMath.toDegrees(Vector3D.angle(sunDirection, normal)), 0.11);
483
484
485 Assert.assertEquals(180.0, FastMath.toDegrees(Vector3D.angle(acceleration, normal)), 1.0e-3);
486
487 }
488
489 }
490
491 @Test
492 public void testPlaneAbsorption() throws OrekitException {
493
494 AbsoluteDate initialDate = propagator.getInitialState().getDate();
495 CelestialBody sun = CelestialBodyFactory.getSun();
496 BoxAndSolarArraySpacecraft s =
497 new BoxAndSolarArraySpacecraft(0, 0, 0, sun, 20.0, Vector3D.PLUS_J, 0.0, 1.0, 0.0);
498
499 for (double dt = 0; dt < 4000; dt += 60) {
500
501 AbsoluteDate date = initialDate.shiftedBy(dt);
502 SpacecraftState state = propagator.propagate(date);
503
504 Vector3D sunDirection = sun.getPVCoordinates(date, state.getFrame()).getPosition().normalize();
505 Vector3D flux = new Vector3D(-4.56e-6, sunDirection);
506 Vector3D acceleration =
507 s.radiationPressureAcceleration(state.getDate(), state.getFrame(),
508 state.getPVCoordinates().getPosition(),
509 state.getAttitude().getRotation(),
510 state.getMass(), flux,
511 getRadiationParameters(s));
512 Vector3D normal = state.getAttitude().getRotation().applyInverseTo(s.getNormal(state.getDate(), state.getFrame(),
513 state.getPVCoordinates().getPosition(),
514 state.getAttitude().getRotation()));
515
516
517 Assert.assertEquals(15.1, FastMath.toDegrees(Vector3D.angle(sunDirection, normal)), 0.11);
518
519
520 Assert.assertEquals(180.0, FastMath.toDegrees(Vector3D.angle(acceleration, sunDirection)), 1.0e-3);
521
522 }
523
524 }
525
526 @Test
527 public void testWrongParameterDrag() throws OrekitException {
528 SpacecraftState state = propagator.getInitialState();
529 CelestialBody sun = CelestialBodyFactory.getSun();
530 BoxAndSolarArraySpacecraft s =
531 new BoxAndSolarArraySpacecraft(0, 0, 0, sun, 20.0, Vector3D.PLUS_J, 0.0, 1.0, 0.0);
532 try {
533 s.dragAcceleration(state.getDate(), state.getFrame(),
534 state.getPVCoordinates().getPosition(),
535 state.getAttitude().getRotation(),
536 state.getMass(), 1.0e-6, Vector3D.PLUS_I,
537 getDragParameters(s),
538 "wrong");
539 Assert.fail("an exception should have been thrown");
540 } catch (OrekitException oe) {
541 Assert.assertEquals(OrekitMessages.UNSUPPORTED_PARAMETER_NAME,
542 oe.getSpecifier());
543 Assert.assertEquals("wrong", (String) oe.getParts()[0]);
544 }
545 }
546
547 @Test
548 public void testMissingParameterLift() throws OrekitException {
549 SpacecraftState state = propagator.getInitialState();
550 CelestialBody sun = CelestialBodyFactory.getSun();
551 BoxAndSolarArraySpacecraft s =
552 new BoxAndSolarArraySpacecraft(0, 0, 0, sun, 20.0, Vector3D.PLUS_J, 2.0, 1.0, 0.0);
553 try {
554 s.dragAcceleration(state.getDate(), state.getFrame(),
555 state.getPVCoordinates().getPosition(),
556 state.getAttitude().getRotation(),
557 state.getMass(), 1.0e-6, Vector3D.PLUS_I,
558 getDragParameters(s),
559 DragSensitive.LIFT_RATIO);
560 Assert.fail("an exception should have been thrown");
561 } catch (OrekitException oe) {
562 Assert.assertEquals(OrekitMessages.UNSUPPORTED_PARAMETER_NAME,
563 oe.getSpecifier());
564 Assert.assertEquals(2, oe.getParts().length);
565 Assert.assertEquals(DragSensitive.LIFT_RATIO, (String) oe.getParts()[0]);
566 Assert.assertEquals(DragSensitive.DRAG_COEFFICIENT, (String) oe.getParts()[1]);
567 }
568 }
569
570 @Test
571 public void testPresentParameterLift() throws OrekitException {
572 SpacecraftState state = propagator.getInitialState();
573 CelestialBody sun = CelestialBodyFactory.getSun();
574 BoxAndSolarArraySpacecraft s =
575 new BoxAndSolarArraySpacecraft(0, 0, 0, sun, 20.0, Vector3D.PLUS_J, 2.0, 0.4, 1.0, 0.0);
576 FieldVector3D<DerivativeStructure> a = s.dragAcceleration(state.getDate(), state.getFrame(),
577 state.getPVCoordinates().getPosition(),
578 state.getAttitude().getRotation(),
579 state.getMass(), 1.0e-6, Vector3D.PLUS_I,
580 getDragParameters(s),
581 DragSensitive.LIFT_RATIO);
582 Assert.assertEquals(5.58e-10, a.getNorm().getReal(), 1.0e-12);
583 }
584
585 @Test
586 public void testWrongParameterLift() throws OrekitException {
587 SpacecraftState state = propagator.getInitialState();
588 CelestialBody sun = CelestialBodyFactory.getSun();
589 BoxAndSolarArraySpacecraft s =
590 new BoxAndSolarArraySpacecraft(0, 0, 0, sun, 20.0, Vector3D.PLUS_J, 2.0, 0.4, 1.0, 0.0);
591 try {
592 s.dragAcceleration(state.getDate(), state.getFrame(),
593 state.getPVCoordinates().getPosition(),
594 state.getAttitude().getRotation(),
595 state.getMass(), 1.0e-6, Vector3D.PLUS_I,
596 getDragParameters(s),
597 "wrong");
598 Assert.fail("an exception should have been thrown");
599 } catch (OrekitException oe) {
600 Assert.assertEquals(OrekitMessages.UNSUPPORTED_PARAMETER_NAME,
601 oe.getSpecifier());
602 Assert.assertEquals(3, oe.getParts().length);
603 Assert.assertEquals("wrong", (String) oe.getParts()[0]);
604 Assert.assertEquals(DragSensitive.DRAG_COEFFICIENT, (String) oe.getParts()[1]);
605 Assert.assertEquals(DragSensitive.LIFT_RATIO, (String) oe.getParts()[2]);
606 }
607 }
608
609 @Test
610 public void testWrongParameterRadiation() throws OrekitException {
611 SpacecraftState state = propagator.getInitialState();
612 CelestialBody sun = CelestialBodyFactory.getSun();
613 BoxAndSolarArraySpacecraft s =
614 new BoxAndSolarArraySpacecraft(0, 0, 0, sun, 20.0, Vector3D.PLUS_J, 0.0, 1.0, 0.0);
615 try {
616 s.radiationPressureAcceleration(state.getDate(), state.getFrame(),
617 state.getPVCoordinates().getPosition(),
618 state.getAttitude().getRotation(),
619 state.getMass(), Vector3D.PLUS_I,
620 getRadiationParameters(s),
621 "wrong");
622 Assert.fail("an exception should have been thrown");
623 } catch (OrekitException oe) {
624 Assert.assertEquals(OrekitMessages.UNSUPPORTED_PARAMETER_NAME,
625 oe.getSpecifier());
626 Assert.assertEquals("wrong", (String) oe.getParts()[0]);
627 }
628 }
629
630 @Test
631 public void testNullIllumination() throws OrekitException {
632 SpacecraftState state = propagator.getInitialState();
633 CelestialBody sun = CelestialBodyFactory.getSun();
634 BoxAndSolarArraySpacecraft s =
635 new BoxAndSolarArraySpacecraft(0, 0, 0, sun, 20.0, Vector3D.PLUS_J, 0.0, 1.0, 0.0);
636 FieldVector3D<DerivativeStructure> a =
637 s.radiationPressureAcceleration(state.getDate(), state.getFrame(),
638 state.getPVCoordinates().getPosition(),
639 state.getAttitude().getRotation(),
640 state.getMass(), new Vector3D(Precision.SAFE_MIN / 2,
641 Vector3D.PLUS_I),
642 getRadiationParameters(s),
643 RadiationSensitive.ABSORPTION_COEFFICIENT);
644 Assert.assertEquals(0.0, a.getNorm().getReal(), Double.MIN_VALUE);
645 }
646
647 @Test
648 public void testBackwardIllumination() throws OrekitException {
649 SpacecraftState state = propagator.getInitialState();
650 CelestialBody sun = CelestialBodyFactory.getSun();
651 BoxAndSolarArraySpacecraft s =
652 new BoxAndSolarArraySpacecraft(0, 0, 0, sun, 20.0, Vector3D.PLUS_J, 0.0, 1.0, 0.0);
653 Vector3D n = s.getNormal(state.getDate(), state.getFrame(),
654 state.getPVCoordinates().getPosition(),
655 state.getAttitude().getRotation());
656 FieldVector3D<DerivativeStructure> aPlus =
657 s.radiationPressureAcceleration(state.getDate(), state.getFrame(),
658 state.getPVCoordinates().getPosition(),
659 state.getAttitude().getRotation(),
660 state.getMass(), n,
661 getRadiationParameters(s),
662 RadiationSensitive.ABSORPTION_COEFFICIENT);
663 FieldVector3D<DerivativeStructure> aMinus =
664 s.radiationPressureAcceleration(state.getDate(), state.getFrame(),
665 state.getPVCoordinates().getPosition(),
666 state.getAttitude().getRotation(),
667 state.getMass(), n.negate(),
668 getRadiationParameters(s),
669 RadiationSensitive.ABSORPTION_COEFFICIENT);
670 Assert.assertEquals(0.0, aPlus.add(aMinus).getNorm().getReal(), Double.MIN_VALUE);
671 }
672
673 @Test
674 public void testNormalOptimalRotationDouble() throws OrekitException {
675 AbsoluteDate initialDate = propagator.getInitialState().getDate();
676 CelestialBody sun = CelestialBodyFactory.getSun();
677 BoxAndSolarArraySpacecraft s =
678 new BoxAndSolarArraySpacecraft(0, 0, 0, sun, 20.0, Vector3D.PLUS_J, 0.0, 1.0, 0.0);
679 for (double dt = 0; dt < 4000; dt += 60) {
680 AbsoluteDate date = initialDate.shiftedBy(dt);
681 SpacecraftState state = propagator.propagate(date);
682 Vector3D normal = s.getNormal(state.getDate(), state.getFrame(),
683 state.getPVCoordinates().getPosition(),
684 state.getAttitude().getRotation());
685 Assert.assertEquals(0, Vector3D.dotProduct(normal, Vector3D.PLUS_J), 1.0e-16);
686 }
687 }
688
689 @Test
690 public void testNormalOptimalRotationField() throws OrekitException {
691 AbsoluteDate initialDate = propagator.getInitialState().getDate();
692 CelestialBody sun = CelestialBodyFactory.getSun();
693 BoxAndSolarArraySpacecraft s =
694 new BoxAndSolarArraySpacecraft(0, 0, 0, sun, 20.0, Vector3D.PLUS_J, 0.0, 1.0, 0.0);
695 Field<Decimal64> field = Decimal64Field.getInstance();
696 for (double dt = 0; dt < 4000; dt += 60) {
697 AbsoluteDate date = initialDate.shiftedBy(dt);
698 SpacecraftState state = propagator.propagate(date);
699 FieldVector3D<Decimal64> normal = s.getNormal(new FieldAbsoluteDate<>(field, state.getDate()),
700 state.getFrame(),
701 new FieldVector3D<>(field, state.getPVCoordinates().getPosition()),
702 new FieldRotation<>(field, state.getAttitude().getRotation()));
703 Assert.assertEquals(0, FieldVector3D.dotProduct(normal, Vector3D.PLUS_J).getReal(), 1.0e-16);
704 }
705 }
706
707 @Test
708 public void testNormalOptimalRotationDS() throws OrekitException {
709 AbsoluteDate initialDate = propagator.getInitialState().getDate();
710 CelestialBody sun = CelestialBodyFactory.getSun();
711 BoxAndSolarArraySpacecraft s =
712 new BoxAndSolarArraySpacecraft(0, 0, 0, sun, 20.0, Vector3D.PLUS_J, 0.0, 1.0, 0.0);
713 DSFactory factory = new DSFactory(1, 2);
714 for (double dt = 0; dt < 4000; dt += 60) {
715 AbsoluteDate date = initialDate.shiftedBy(dt);
716 SpacecraftState state = propagator.propagate(date);
717 FieldVector3D<DerivativeStructure> normal = s.getNormal(state.getDate(),
718 state.getFrame(),
719 new FieldVector3D<>(factory.getDerivativeField(), state.getPVCoordinates().getPosition()),
720 new FieldRotation<>(factory.getDerivativeField(), state.getAttitude().getRotation()));
721 Assert.assertEquals(0, FieldVector3D.dotProduct(normal, Vector3D.PLUS_J).getReal(), 1.0e-16);
722 }
723 }
724
725 @Test
726 public void testNormalFixedRateDouble() throws OrekitException {
727 AbsoluteDate initialDate = propagator.getInitialState().getDate();
728 CelestialBody sun = CelestialBodyFactory.getSun();
729 BoxAndSolarArraySpacecraft s =
730 new BoxAndSolarArraySpacecraft(0, 0, 0, sun, 20.0, Vector3D.PLUS_J,
731 initialDate, Vector3D.PLUS_K, 1.0e-3,
732 0.0, 1.0, 0.0);
733 for (double dt = 0; dt < 4000; dt += 60) {
734 AbsoluteDate date = initialDate.shiftedBy(dt);
735 SpacecraftState state = propagator.propagate(date);
736 Vector3D normal = s.getNormal(state.getDate(), state.getFrame(),
737 state.getPVCoordinates().getPosition(),
738 state.getAttitude().getRotation());
739 Assert.assertEquals(0, Vector3D.dotProduct(normal, Vector3D.PLUS_J), 1.0e-16);
740 }
741 }
742
743 @Test
744 public void testNormalFixedRateField() throws OrekitException {
745 AbsoluteDate initialDate = propagator.getInitialState().getDate();
746 CelestialBody sun = CelestialBodyFactory.getSun();
747 BoxAndSolarArraySpacecraft s =
748 new BoxAndSolarArraySpacecraft(0, 0, 0, sun, 20.0, Vector3D.PLUS_J,
749 initialDate, Vector3D.PLUS_K, 1.0e-3,
750 0.0, 1.0, 0.0);
751 Field<Decimal64> field = Decimal64Field.getInstance();
752 for (double dt = 0; dt < 4000; dt += 60) {
753 AbsoluteDate date = initialDate.shiftedBy(dt);
754 SpacecraftState state = propagator.propagate(date);
755 FieldVector3D<Decimal64> normal = s.getNormal(new FieldAbsoluteDate<>(field, state.getDate()),
756 state.getFrame(),
757 new FieldVector3D<>(field, state.getPVCoordinates().getPosition()),
758 new FieldRotation<>(field, state.getAttitude().getRotation()));
759 Assert.assertEquals(0, FieldVector3D.dotProduct(normal, Vector3D.PLUS_J).getReal(), 1.0e-16);
760 }
761 }
762
763 @Test
764 public void testNormalFixedRateDS() throws OrekitException {
765 AbsoluteDate initialDate = propagator.getInitialState().getDate();
766 CelestialBody sun = CelestialBodyFactory.getSun();
767 BoxAndSolarArraySpacecraft s =
768 new BoxAndSolarArraySpacecraft(0, 0, 0, sun, 20.0, Vector3D.PLUS_J,
769 initialDate, Vector3D.PLUS_K, 1.0e-3,
770 0.0, 1.0, 0.0);
771 DSFactory factory = new DSFactory(1, 2);
772 for (double dt = 0; dt < 4000; dt += 60) {
773 AbsoluteDate date = initialDate.shiftedBy(dt);
774 SpacecraftState state = propagator.propagate(date);
775 FieldVector3D<DerivativeStructure> normal = s.getNormal(state.getDate(),
776 state.getFrame(),
777 new FieldVector3D<>(factory.getDerivativeField(), state.getPVCoordinates().getPosition()),
778 new FieldRotation<>(factory.getDerivativeField(), state.getAttitude().getRotation()));
779 Assert.assertEquals(0, FieldVector3D.dotProduct(normal, Vector3D.PLUS_J).getReal(), 1.0e-16);
780 }
781 }
782
783 @Test
784 public void testNormalSunAlignedDouble() throws OrekitException {
785 BoxAndSolarArraySpacecraft s =
786 new BoxAndSolarArraySpacecraft(0, 0, 0,
787 (date, frame) -> new TimeStampedPVCoordinates(date, new Vector3D(0, 1e6, 0), Vector3D.ZERO),
788 20.0, Vector3D.PLUS_J, 0.0, 1.0, 0.0);
789 Vector3D normal = s.getNormal(AbsoluteDate.J2000_EPOCH, FramesFactory.getEME2000(),
790 Vector3D.ZERO, Rotation.IDENTITY);
791 Assert.assertEquals(0, Vector3D.dotProduct(normal, Vector3D.PLUS_J), 1.0e-16);
792 }
793
794 @Test
795 public void testNormalSunAlignedField() throws OrekitException {
796 BoxAndSolarArraySpacecraft s =
797 new BoxAndSolarArraySpacecraft(0, 0, 0,
798 (date, frame) -> new TimeStampedPVCoordinates(date, new Vector3D(0, 1e6, 0), Vector3D.ZERO),
799 20.0, Vector3D.PLUS_J, 0.0, 1.0, 0.0);
800 Field<Decimal64> field = Decimal64Field.getInstance();
801 FieldVector3D<Decimal64> normal = s.getNormal(FieldAbsoluteDate.getJ2000Epoch(field),
802 FramesFactory.getEME2000(),
803 FieldVector3D.getZero(field),
804 FieldRotation.getIdentity(field));
805 Assert.assertEquals(0, FieldVector3D.dotProduct(normal, Vector3D.PLUS_J).getReal(), 1.0e-16);
806 }
807
808 @Test
809 public void testNormalSunAlignedDS() throws OrekitException {
810 BoxAndSolarArraySpacecraft s =
811 new BoxAndSolarArraySpacecraft(0, 0, 0,
812 (date, frame) -> new TimeStampedPVCoordinates(date, new Vector3D(0, 1e6, 0), Vector3D.ZERO),
813 20.0, Vector3D.PLUS_J, 0.0, 1.0, 0.0);
814 DSFactory factory = new DSFactory(1, 2);
815 FieldVector3D<DerivativeStructure> normal = s.getNormal(AbsoluteDate.J2000_EPOCH,
816 FramesFactory.getEME2000(),
817 FieldVector3D.getZero(factory.getDerivativeField()),
818 FieldRotation.getIdentity(factory.getDerivativeField()));
819 Assert.assertEquals(0, FieldVector3D.dotProduct(normal, Vector3D.PLUS_J).getReal(), 1.0e-16);
820 }
821
822 private double[] getDragParameters(final BoxAndSolarArraySpacecraft basa) {
823 final ParameterDriver[] drivers = basa.getDragParametersDrivers();
824 final double[] parameters = new double[drivers.length];
825 for (int i = 0; i < drivers.length; ++i) {
826 parameters[i] = drivers[i].getValue();
827 }
828 return parameters;
829 }
830
831 private double[] getRadiationParameters(final BoxAndSolarArraySpacecraft basa) {
832 final ParameterDriver[] drivers = basa.getRadiationParametersDrivers();
833 final double[] parameters = new double[drivers.length];
834 for (int i = 0; i < drivers.length; ++i) {
835 parameters[i] = drivers[i].getValue();
836 }
837 return parameters;
838 }
839
840 @Before
841 public void setUp() {
842 try {
843 Utils.setDataRoot("regular-data");
844 mu = 3.9860047e14;
845 double ae = 6.378137e6;
846 double c20 = -1.08263e-3;
847 double c30 = 2.54e-6;
848 double c40 = 1.62e-6;
849 double c50 = 2.3e-7;
850 double c60 = -5.5e-7;
851
852 AbsoluteDate date = new AbsoluteDate(new DateComponents(1970, 7, 1),
853 new TimeComponents(13, 59, 27.816),
854 TimeScalesFactory.getUTC());
855
856
857
858 Orbit circ =
859 new CircularOrbit(7178000.0, 0.5e-4, -0.5e-4, FastMath.toRadians(50.), FastMath.toRadians(280),
860 FastMath.toRadians(10.0), PositionAngle.MEAN,
861 FramesFactory.getEME2000(), date, mu);
862 propagator =
863 new EcksteinHechlerPropagator(circ,
864 new LofOffset(circ.getFrame(), LOFType.VVLH),
865 ae, mu, c20, c30, c40, c50, c60);
866 } catch (OrekitException oe) {
867 Assert.fail(oe.getLocalizedMessage());
868 }
869 }
870
871 private double mu;
872 private Propagator propagator;
873
874 }