1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.forces.maneuvers.propulsion;
18
19 import org.hipparchus.geometry.euclidean.threed.Rotation;
20 import org.hipparchus.geometry.euclidean.threed.RotationConvention;
21 import org.hipparchus.geometry.euclidean.threed.Vector3D;
22 import org.hipparchus.util.Decimal64;
23 import org.hipparchus.util.FastMath;
24 import org.junit.Assert;
25 import org.junit.Before;
26 import org.junit.Test;
27 import org.orekit.Utils;
28 import org.orekit.attitudes.Attitude;
29 import org.orekit.attitudes.AttitudeProvider;
30 import org.orekit.attitudes.LofOffset;
31 import org.orekit.errors.OrekitException;
32 import org.orekit.frames.FactoryManagedFrame;
33 import org.orekit.frames.FramesFactory;
34 import org.orekit.frames.LOFType;
35 import org.orekit.orbits.KeplerianOrbit;
36 import org.orekit.orbits.PositionAngle;
37 import org.orekit.propagation.analytical.KeplerianPropagator;
38 import org.orekit.time.AbsoluteDate;
39 import org.orekit.time.FieldAbsoluteDate;
40 import org.orekit.time.TimeScalesFactory;
41 import org.orekit.utils.Constants;
42 import org.orekit.utils.IERSConventions;
43 import org.orekit.utils.PVCoordinatesProvider;
44
45 public class ThrustDirectionAndAttitudeProviderTest {
46
47 private static final double EPSILON_ROTATION = 1E-15;
48
49 private FactoryManagedFrame frame;
50
51 private AbsoluteDate date;
52
53 private PVCoordinatesProvider pvProv;
54
55 private final Vector3D thrusterAxisInSatelliteFrame = Vector3D.PLUS_J;
56
57 @Before
58 public void setUp() {
59 Utils.setDataRoot("regular-data");
60 frame = FramesFactory.getCIRF(IERSConventions.IERS_2010, true);
61 date = new AbsoluteDate(2020, 01, 01, TimeScalesFactory.getUTC());
62 final double sma = Constants.EGM96_EARTH_EQUATORIAL_RADIUS + 700e3;
63 final double ecc = 0.01;
64 final double inc = FastMath.toRadians(60);
65 final double pa = FastMath.toRadians(0);
66 final double raan = 0.;
67 final double anomaly = FastMath.toRadians(0);
68
69 final KeplerianOrbit initialOrbit = new KeplerianOrbit(sma, ecc, inc, pa, raan, anomaly, PositionAngle.TRUE,
70 FramesFactory.getCIRF(IERSConventions.IERS_2010, true), date, Constants.EGM96_EARTH_MU);
71 pvProv = new KeplerianPropagator(initialOrbit);
72 }
73
74 private AttitudeProvider buildVelocityAttitudeProvider() {
75 return new LofOffset(frame, LOFType.TNW);
76 }
77
78 @Test(expected = OrekitException.class)
79 public void fixedDirectionCanNotProvideTheAttitude() {
80
81 final ThrustDirectionAndAttitudeProvider provider = ThrustDirectionAndAttitudeProvider
82 .buildFromFixedDirectionInSatelliteFrame(Vector3D.PLUS_I);
83 Assert.assertNull(provider.getManeuverAttitudeProvider());
84 provider.getAttitude(pvProv, date, frame);
85 }
86
87 @Test(expected = OrekitException.class)
88 public void missingParameterTest() {
89 ThrustDirectionAndAttitudeProvider.buildFromDirectionInFrame(frame, null, thrusterAxisInSatelliteFrame);
90 }
91
92 @Test
93 public void attitudeFromDirectionInFrame() {
94
95 final Vector3D fixedThrustDirection = new Vector3D(1, 2, 3).normalize();
96 final ConstantThrustDirectionProvider thrustDirectionInertial = new ConstantThrustDirectionProvider(
97 fixedThrustDirection);
98
99 final ThrustDirectionAndAttitudeProvider provider = ThrustDirectionAndAttitudeProvider
100 .buildFromDirectionInFrame(frame, thrustDirectionInertial, thrusterAxisInSatelliteFrame);
101
102 Assert.assertNotNull(provider.getManeuverAttitudeProvider());
103
104
105 final Attitude inertialToSat = provider.getAttitude(pvProv, date, frame);
106
107 final Vector3D thrustDirectionRecomputed = inertialToSat.getRotation().revert()
108 .applyTo(thrusterAxisInSatelliteFrame);
109 Assert.assertEquals(0, fixedThrustDirection.subtract(thrustDirectionRecomputed).getNorm(), EPSILON_ROTATION);
110
111 }
112
113 @Test
114 public void attitudeFromDirectionInLOF() {
115 final Vector3D fixedThrustDirection = Vector3D.PLUS_I;
116 final ConstantThrustDirectionProvider thrustDirectionTNW = new ConstantThrustDirectionProvider(Vector3D.PLUS_I);
117
118 final ThrustDirectionAndAttitudeProvider provider = ThrustDirectionAndAttitudeProvider
119 .buildFromDirectionInLOF(LOFType.TNW, thrustDirectionTNW, thrusterAxisInSatelliteFrame);
120
121 Assert.assertNotNull(provider.getManeuverAttitudeProvider());
122
123
124 final Attitude inertialToSat = provider.getAttitude(pvProv, date, frame);
125
126
127 final Rotation inertialToLof = LOFType.TNW.transformFromInertial(date, pvProv.getPVCoordinates(date, frame))
128 .getRotation();
129 final Rotation satToLof = inertialToLof.compose(inertialToSat.getRotation().revert(),
130 RotationConvention.VECTOR_OPERATOR);
131
132 final Vector3D thrustDirectionRecomputed = satToLof.applyTo(thrusterAxisInSatelliteFrame);
133 Assert.assertEquals(0., fixedThrustDirection.subtract(thrustDirectionRecomputed).getNorm(), EPSILON_ROTATION);
134 }
135
136 @Test
137 public void attitudeFromCustomProvider() {
138 final ThrustDirectionAndAttitudeProvider provider = ThrustDirectionAndAttitudeProvider
139 .buildFromCustomAttitude(buildVelocityAttitudeProvider(), thrusterAxisInSatelliteFrame);
140 Assert.assertNotNull(provider.getManeuverAttitudeProvider());
141 Assert.assertEquals(
142 buildVelocityAttitudeProvider().getAttitude(pvProv, date, frame).getRotation()
143 .applyTo(thrusterAxisInSatelliteFrame),
144 provider.getAttitude(pvProv, date, frame).getRotation().applyTo(thrusterAxisInSatelliteFrame));
145 }
146
147 @Test(expected = OrekitException.class)
148 public void getAttitudeFieldError() {
149
150 final ThrustDirectionAndAttitudeProvider provider = ThrustDirectionAndAttitudeProvider
151 .buildFromCustomAttitude(buildVelocityAttitudeProvider(), Vector3D.PLUS_I);
152 Assert.assertNotNull(provider.getManeuverAttitudeProvider());
153 provider.getAttitude(null, new FieldAbsoluteDate<>(date, new Decimal64(0)), frame);
154 }
155 }