1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.files.general;
18
19 import static org.junit.Assert.assertEquals;
20 import static org.junit.Assert.assertNotNull;
21
22 import java.io.BufferedWriter;
23 import java.io.IOException;
24 import java.nio.charset.StandardCharsets;
25 import java.nio.file.Files;
26 import java.nio.file.Paths;
27 import java.util.ArrayList;
28 import java.util.List;
29
30 import org.hipparchus.geometry.euclidean.threed.Rotation;
31 import org.junit.Assert;
32 import org.junit.Before;
33 import org.junit.Test;
34 import org.orekit.Utils;
35 import org.orekit.attitudes.Attitude;
36 import org.orekit.attitudes.AttitudeProvider;
37 import org.orekit.attitudes.InertialProvider;
38 import org.orekit.bodies.CelestialBody;
39 import org.orekit.bodies.CelestialBodyFactory;
40 import org.orekit.data.DataSource;
41 import org.orekit.errors.OrekitIllegalArgumentException;
42 import org.orekit.errors.OrekitMessages;
43 import org.orekit.files.ccsds.definitions.CelestialBodyFrame;
44 import org.orekit.files.ccsds.definitions.FrameFacade;
45 import org.orekit.files.ccsds.definitions.SpacecraftBodyFrame;
46 import org.orekit.files.ccsds.definitions.TimeSystem;
47 import org.orekit.files.ccsds.ndm.ParserBuilder;
48 import org.orekit.files.ccsds.ndm.WriterBuilder;
49 import org.orekit.files.ccsds.ndm.adm.AttitudeType;
50 import org.orekit.files.ccsds.ndm.adm.aem.AemMetadata;
51 import org.orekit.files.ccsds.ndm.adm.aem.AemSegment;
52 import org.orekit.files.ccsds.ndm.adm.aem.AttitudeWriter;
53 import org.orekit.files.ccsds.utils.FileFormat;
54 import org.orekit.files.general.AttitudeEphemerisFile.AttitudeEphemerisSegment;
55 import org.orekit.files.general.OrekitAttitudeEphemerisFile.OrekitSatelliteAttitudeEphemeris;
56 import org.orekit.frames.Frame;
57 import org.orekit.frames.FramesFactory;
58 import org.orekit.orbits.KeplerianOrbit;
59 import org.orekit.orbits.PositionAngle;
60 import org.orekit.propagation.SpacecraftState;
61 import org.orekit.propagation.analytical.KeplerianPropagator;
62 import org.orekit.time.AbsoluteDate;
63 import org.orekit.utils.AngularDerivativesFilter;
64 import org.orekit.utils.Constants;
65 import org.orekit.utils.TimeStampedAngularCoordinates;
66
67 public class OrekitAttitudeEphemerisFileTest {
68
69 @Before
70 public void setUp() throws Exception {
71 Utils.setDataRoot("regular-data");
72 }
73
74 @Test
75 public void testGetSatellites() {
76 final String id1 = "ID1";
77 final String id2 = "ID2";
78 OrekitAttitudeEphemerisFile file = new OrekitAttitudeEphemerisFile();
79 OrekitSatelliteAttitudeEphemeris ephem1 = file.addSatellite(id1);
80 assertNotNull(ephem1);
81 OrekitSatelliteAttitudeEphemeris ephem2 = file.addSatellite(id2);
82 assertNotNull(ephem2);
83 }
84
85 @Test
86 public void testWritingToAEM() throws IOException {
87 final double quaternionTolerance = 1e-5;
88 final String satId = "SATELLITE1";
89 final double sma = 10000000;
90 final double inc = Math.toRadians(45.0);
91 final double ecc = 0.1;
92 final double raan = 0.0;
93 final double pa = 0.0;
94 final double ta = 0.0;
95 final AbsoluteDate date = new AbsoluteDate();
96 final Frame frame = FramesFactory.getEME2000();
97 final CelestialBody body = CelestialBodyFactory.getEarth();
98 final double mu = body.getGM();
99 KeplerianOrbit initialOrbit = new KeplerianOrbit(sma, ecc, inc, pa, raan, ta, PositionAngle.TRUE,
100 frame, date, mu);
101
102
103
104 final Rotation refRot = new Rotation(0.72501, -0.64585, 0.018542, -0.23854, false);
105 AttitudeProvider inertialPointing = new InertialProvider(refRot);
106 KeplerianPropagator propagator = new KeplerianPropagator(initialOrbit, inertialPointing);
107
108 final double propagationDurationSeconds = 1200.0;
109 final double stepSizeSeconds = 60.0;
110 List<SpacecraftState> states = new ArrayList<SpacecraftState>();
111
112 for (double dt = 0.0; dt < propagationDurationSeconds; dt += stepSizeSeconds) {
113 states.add(propagator.propagate(date.shiftedBy(dt)));
114 }
115
116 OrekitAttitudeEphemerisFile ephemerisFile = new OrekitAttitudeEphemerisFile();
117 OrekitSatelliteAttitudeEphemeris satellite = ephemerisFile.addSatellite(satId);
118 satellite.addNewSegment(states,
119 OrekitSatelliteAttitudeEphemeris.DEFAULT_INTERPOLATION_METHOD,
120 OrekitSatelliteAttitudeEphemeris.DEFAULT_INTERPOLATION_SIZE,
121 AngularDerivativesFilter.USE_RR);
122
123
124 assertEquals(satId, satellite.getId());
125 assertEquals(0.0, states.get(0).getDate().durationFrom(satellite.getStart()), 1.0e-15);
126 assertEquals(0.0, states.get(states.size() - 1).getDate().durationFrom(satellite.getStop()), 1.0e-15);
127
128
129 AttitudeEphemerisSegment<TimeStampedAngularCoordinates> segment = satellite.getSegments().get(0);
130 assertEquals(OrekitSatelliteAttitudeEphemeris.DEFAULT_INTERPOLATION_METHOD, segment.getInterpolationMethod());
131 assertEquals(OrekitSatelliteAttitudeEphemeris.DEFAULT_INTERPOLATION_SIZE, segment.getInterpolationSamples());
132 assertEquals(0.0, states.get(0).getDate().durationFrom(segment.getStart()), 1.0e-15);
133 assertEquals(0.0, states.get(states.size() - 1).getDate().durationFrom(segment.getStop()), 1.0e-15);
134 Assert.assertEquals(AngularDerivativesFilter.USE_RR, segment.getAvailableDerivatives());
135
136
137 final Attitude attitude = segment.getAttitudeProvider().getAttitude(initialOrbit, date, frame);
138 Assert.assertEquals(frame, attitude.getReferenceFrame());
139 Assert.assertEquals(refRot.getQ0(), attitude.getRotation().getQ0(), quaternionTolerance);
140 Assert.assertEquals(refRot.getQ1(), attitude.getRotation().getQ1(), quaternionTolerance);
141 Assert.assertEquals(refRot.getQ2(), attitude.getRotation().getQ2(), quaternionTolerance);
142 Assert.assertEquals(refRot.getQ3(), attitude.getRotation().getQ3(), quaternionTolerance);
143
144 String tempAem = Files.createTempFile("OrekitAttitudeEphemerisFileTest", ".aem").toString();
145 try (BufferedWriter writer = Files.newBufferedWriter(Paths.get(tempAem), StandardCharsets.UTF_8)) {
146 new AttitudeWriter(new WriterBuilder().buildAemWriter(),
147 null, dummyMetadata(), FileFormat.KVN, "", 60).write(writer, ephemerisFile);
148 }
149
150 AttitudeEphemerisFile<TimeStampedAngularCoordinates, AemSegment> ephemerisFrom =
151 new ParserBuilder().buildAemParser().parseMessage(new DataSource(tempAem));
152 Files.delete(Paths.get(tempAem));
153
154 segment = ephemerisFrom.getSatellites().get(satId).getSegments().get(0);
155 assertEquals(states.get(0).getDate(), segment.getStart());
156 assertEquals(states.get(states.size() - 1).getDate(), segment.getStop());
157 assertEquals(states.size(), segment.getAngularCoordinates().size());
158 for (int i = 0; i < states.size(); i++) {
159 TimeStampedAngularCoordinates expected = states.get(i).getAttitude().getOrientation();
160 TimeStampedAngularCoordinates actual = segment.getAngularCoordinates().get(i);
161 assertEquals(expected.getDate(), actual.getDate());
162 assertEquals(0.0, Rotation.distance(refRot, actual.getRotation()), quaternionTolerance);
163 }
164
165 }
166
167 @Test
168 public void testNoStates() {
169
170
171 final String satId = "SATELLITE1";
172
173
174 List<SpacecraftState> states = new ArrayList<SpacecraftState>();
175
176
177 OrekitAttitudeEphemerisFile ephemerisFile = new OrekitAttitudeEphemerisFile();
178 OrekitSatelliteAttitudeEphemeris satellite = ephemerisFile.addSatellite(satId);
179
180
181 try {
182 satellite.addNewSegment(states,
183 OrekitSatelliteAttitudeEphemeris.DEFAULT_INTERPOLATION_METHOD,
184 OrekitSatelliteAttitudeEphemeris.DEFAULT_INTERPOLATION_SIZE,
185 AngularDerivativesFilter.USE_RR);
186 } catch (OrekitIllegalArgumentException oiae) {
187 Assert.assertEquals(OrekitMessages.NULL_ARGUMENT, oiae.getSpecifier());
188 }
189
190
191 }
192
193 @Test
194 public void testNoEnoughDataForInterpolation() {
195
196
197 final String satId = "SATELLITE1";
198 final double sma = 10000000;
199 final double inc = Math.toRadians(45.0);
200 final double ecc = 0.1;
201 final double raan = 0.0;
202 final double pa = 0.0;
203 final double ta = 0.0;
204 final AbsoluteDate date = new AbsoluteDate();
205 final Frame frame = FramesFactory.getEME2000();
206 final CelestialBody body = CelestialBodyFactory.getEarth();
207 final double mu = body.getGM();
208 KeplerianOrbit initialOrbit = new KeplerianOrbit(sma, ecc, inc, pa, raan, ta, PositionAngle.TRUE,
209 frame, date, mu);
210 SpacecraftState state = new SpacecraftState(initialOrbit);
211
212
213 List<SpacecraftState> states = new ArrayList<SpacecraftState>();
214 states.add(state);
215
216
217 OrekitAttitudeEphemerisFile ephemerisFile = new OrekitAttitudeEphemerisFile();
218 OrekitSatelliteAttitudeEphemeris satellite = ephemerisFile.addSatellite(satId);
219
220
221 try {
222 satellite.addNewSegment(states, "LINEAR", 1, AngularDerivativesFilter.USE_R);
223 } catch (OrekitIllegalArgumentException oiae) {
224 Assert.assertEquals(OrekitMessages.NOT_ENOUGH_DATA_FOR_INTERPOLATION, oiae.getSpecifier());
225 }
226 }
227
228 private AemMetadata dummyMetadata() {
229 AemMetadata metadata = new AemMetadata(4);
230 metadata.setTimeSystem(TimeSystem.TT);
231 metadata.setObjectID("SATELLITE1");
232 metadata.setObjectName("transgalactic");
233 metadata.getEndpoints().setFrameA(new FrameFacade(FramesFactory.getGCRF(), CelestialBodyFrame.GCRF,
234 null, null, "GCRF"));
235 metadata.getEndpoints().setFrameB(new FrameFacade(null, null, null,
236 new SpacecraftBodyFrame(SpacecraftBodyFrame.BaseEquipment.GYRO_FRAME, "1"),
237 "GYRO FRAME 1"));
238 metadata.getEndpoints().setA2b(true);
239 metadata.setStartTime(AbsoluteDate.J2000_EPOCH.shiftedBy(80 * Constants.JULIAN_CENTURY));
240 metadata.setStopTime(metadata.getStartTime().shiftedBy(Constants.JULIAN_YEAR));
241 metadata.setAttitudeType(AttitudeType.QUATERNION_DERIVATIVE);
242 metadata.setIsFirst(true);
243 return metadata;
244 }
245
246 }
247