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