Commit 4343ea3e authored by Raphaël Fermé's avatar Raphaël Fermé
Browse files

Final commit with OrekitAttitudeEphemrisFile

parent adcf5099
......@@ -81,7 +81,7 @@ public class AEMParser extends ADMParser implements AttitudeEphemerisFileParser
* parsing by calling {@link #withInternationalDesignator(int, int, String)}
* </p>
* <p>
* The default interpolation degree is not set here. It is set to zero by default. If another value
* The default interpolation degree is not set here. It is set to one by default. If another value
* is needed it must be initialized before parsing by calling {@link #withInterpolationDegree(int)}
* </p>
*
......@@ -132,7 +132,7 @@ public class AEMParser extends ADMParser implements AttitudeEphemerisFileParser
* @see #withDataContext(DataContext)
*/
public AEMParser(final DataContext dataContext) {
this(AbsoluteDate.FUTURE_INFINITY, Double.NaN, null, true, 0, 0, "", 0, dataContext);
this(AbsoluteDate.FUTURE_INFINITY, Double.NaN, null, true, 0, 0, "", 1, dataContext);
}
/**
......@@ -206,7 +206,7 @@ public class AEMParser extends ADMParser implements AttitudeEphemerisFileParser
* <p>
* This method may be used to set a default interpolation degree which will be used
* when no interpolation degree is parsed in the meta-data of the file. Upon instantiation
* with {@link #AEMParser(DataContext)} the default interpolation degree is zero.
* with {@link #AEMParser(DataContext)} the default interpolation degree is one.
* </p>
* @param newInterpolationDegree default interpolation degree to use while parsing
* @return a new instance, with interpolation degree data replaced
......
......@@ -210,7 +210,7 @@ public class AEMWriter implements AttitudeEphemerisFileWriter {
/**
* Write the passed in {@link ephemerisFile} to a file at the output path specified.
* @param outputFilePath a file path that the corresponding file will be written to
* @param ephemerisFile a populated aem file to serialize into the buffer
* @param aemFile a populated aem file to serialize into the buffer
* @throws IOException if any file writing operations fail or if the underlying
* format doesn't support a configuration in the EphemerisFile
* (for example having multiple satellites in one file, having
......@@ -219,7 +219,7 @@ public class AEMWriter implements AttitudeEphemerisFileWriter {
public void write(final String outputFilePath, final AEMFile aemFile)
throws IOException {
try (BufferedWriter writer = Files.newBufferedWriter(Paths.get(outputFilePath), StandardCharsets.UTF_8)) {
write(writer, aemFile);
write(writer, (AttitudeEphemerisFile) aemFile);
}
}
......
......@@ -84,7 +84,7 @@ public class OEMParser extends ODMParser implements EphemerisFileParser {
* parsing by calling {@link #withInternationalDesignator(int, int, String)}
* </p>
* <p>
* The default interpolation degree is not set here. It is set to zero by default. If another value
* The default interpolation degree is not set here. It is set to one by default. If another value
* is needed it must be initialized before parsing by calling {@link #withInterpolationDegree(int)}
* </p>
*
......@@ -141,7 +141,7 @@ public class OEMParser extends ODMParser implements EphemerisFileParser {
* @since 10.1
*/
public OEMParser(final DataContext dataContext) {
this(AbsoluteDate.FUTURE_INFINITY, Double.NaN, null, true, 0, 0, "", 0, dataContext);
this(AbsoluteDate.FUTURE_INFINITY, Double.NaN, null, true, 0, 0, "", 1, dataContext);
}
/** Complete constructor.
......@@ -219,7 +219,7 @@ public class OEMParser extends ODMParser implements EphemerisFileParser {
* <p>
* This method may be used to set a default interpolation degree which will be used
* when no interpolation degree is parsed in the meta-data of the file. Upon instantiation
* with {@link #OEMParser(DataContext)} the default interpolation degree is zero.
* with {@link #OEMParser(DataContext)} the default interpolation degree is one.
* </p>
* @param newInterpolationDegree default interpolation degree to use while parsing
* @return a new instance, with interpolation degree data replaced
......
......@@ -55,6 +55,7 @@ public class OrekitEphemerisFile implements EphemerisFile {
this.satellites = new ConcurrentHashMap<String, OrekitSatelliteEphemeris>();
}
/** {@inheritDoc} */
@Override
public Map<String, OrekitSatelliteEphemeris> getSatellites() {
return Collections.unmodifiableMap(satellites);
......@@ -76,25 +77,24 @@ public class OrekitEphemerisFile implements EphemerisFile {
/**
* Inner class of {@link OrekitEphemerisFile} that defines the
* {@link OrekitSatelliteEphemeris} corresponding object for this ephemeris type.
*
*/
public static class OrekitSatelliteEphemeris implements SatelliteEphemeris {
/**
* Defines the default interpolation sample size if it is not specified
* on a segment.
**/
public static final int DEFAULT_INTERPOLATION_SIZE = 7;
public static final int DEFAULT_INTERPOLATION_SIZE = 7; // TODO change default interpolation size to 2 in 11.0
/** ID of the space object encapsulated here. **/
private final String id;
/** Earlist date of this file. **/
/** Earliest date of this file. **/
private AbsoluteDate startDate;
/** Latest date of this file. **/
private AbsoluteDate stopDate;
/** List of segements in the file. **/
/** List of segments in the file. **/
private final List<OrekitEphemerisSegment> segments;
/**
......@@ -108,11 +108,13 @@ public class OrekitEphemerisFile implements EphemerisFile {
this.segments = new ArrayList<OrekitEphemerisSegment>();
}
/** {@inheritDoc} */
@Override
public String getId() {
return id;
}
/** {@inheritDoc} */
@Override
public double getMu() {
if (this.segments.size() == 0) {
......@@ -122,19 +124,21 @@ public class OrekitEphemerisFile implements EphemerisFile {
}
}
/** {@inheritDoc} */
@Override
public List<? extends EphemerisSegment> getSegments() {
return Collections.unmodifiableList(this.segments);
}
/** {@inheritDoc} */
@Override
public AbsoluteDate getStart() {
return this.startDate;
}
/** {@inheritDoc} */
@Override
public AbsoluteDate getStop() {
// TODO Auto-generated method stub
return this.stopDate;
}
......@@ -216,12 +220,12 @@ public class OrekitEphemerisFile implements EphemerisFile {
* a list of {@link SpacecraftState} that will comprise this
* new unit.
* @param body
* the celestial body the state's frames are with respect to
* the celestial body from which the frames are defined
* @param interpolationSampleSize
* the number of interpolation samples that should be used
* when processed by another system
* @param timeScale
* used in the new segment.
* the time scale used in the new segment.
* @return the generated {@link OrekitEphemerisSegment}
* @since 10.1
*/
......@@ -266,26 +270,26 @@ public class OrekitEphemerisFile implements EphemerisFile {
}
public static class OrekitEphemerisSegment implements EphemerisSegment {
/** **/
/** coordinates for this ephemeris segment. **/
private final List<TimeStampedPVCoordinates> coordinates;
/** **/
/** the reference frame for this ephemeris segment. **/
private final Frame frame;
/** **/
/** The name of the frame center. **/
private final String frameCenterString;
/** **/
/** standard gravitational parameter for the satellite. **/
private final double mu;
/** **/
/** The time scale identifier, as specified in the ephemeris file. **/
private final String timeScaleString;
/** **/
/** The time scale for this segment. **/
private final TimeScale timeScale;
/** **/
private final int samples;
/** The number of interpolation samples. */
private final int interpolationSamples;
/**
* constructor for OrekitEphemerisSegment.
......@@ -297,14 +301,14 @@ public class OrekitEphemerisFile implements EphemerisFile {
* @param frameCenterString
* the name of celestial body the frame is attached to
* @param mu
* the gravitional constant used in force model evaluations
* the gravitational constant used in force model evaluations
* @param timeScale
* the time scale of these ephemeris points
* @param samples
* @param interpolationSamples
* the number of samples to use during interpolation
*/
public OrekitEphemerisSegment(final List<TimeStampedPVCoordinates> coordinates, final Frame frame,
final String frameCenterString, final double mu, final TimeScale timeScale, final int samples) {
final String frameCenterString, final double mu, final TimeScale timeScale, final int interpolationSamples) {
super();
this.coordinates = coordinates;
this.frame = frame;
......@@ -312,64 +316,76 @@ public class OrekitEphemerisFile implements EphemerisFile {
this.mu = mu;
this.timeScale = timeScale;
this.timeScaleString = timeScale.getName();
this.samples = samples;
this.interpolationSamples = interpolationSamples;
}
/** {@inheritDoc} */
@Override
public double getMu() {
return mu;
}
/** {@inheritDoc} */
@Override
public String getFrameCenterString() {
return frameCenterString;
}
/** {@inheritDoc} */
@Override
public String getFrameString() {
return frame.getName();
}
/** {@inheritDoc} */
@Override
public Frame getFrame() {
return frame;
}
/** {@inheritDoc} */
@Override
public Frame getInertialFrame() {
return frame;
}
/** {@inheritDoc} */
@Override
public String getTimeScaleString() {
return timeScaleString;
}
/** {@inheritDoc} */
@Override
public TimeScale getTimeScale() {
return timeScale;
}
/** {@inheritDoc} */
@Override
public int getInterpolationSamples() {
return samples;
return interpolationSamples;
}
/** {@inheritDoc} */
@Override
public CartesianDerivativesFilter getAvailableDerivatives() {
return CartesianDerivativesFilter.USE_PV;
}
/** {@inheritDoc} */
@Override
public List<TimeStampedPVCoordinates> getCoordinates() {
return Collections.unmodifiableList(coordinates);
}
/** {@inheritDoc} */
@Override
public AbsoluteDate getStart() {
return coordinates.get(0).getDate();
}
/** {@inheritDoc} */
@Override
public AbsoluteDate getStop() {
return coordinates.get(coordinates.size() - 1).getDate();
......
......@@ -445,7 +445,7 @@ public class AEMParserTest {
final AEMFile file = parser.parse(name);
Assert.assertEquals(7, file.getAttitudeBlocks().get(0).getInterpolationDegree());
Assert.assertEquals(0, file.getAttitudeBlocks().get(1).getInterpolationDegree());
Assert.assertEquals(1, file.getAttitudeBlocks().get(1).getInterpolationDegree());
parser = parser.withInterpolationDegree(5);
......
......@@ -469,7 +469,7 @@ public class OEMParserTest {
OEMParser parser = new OEMParser().withMu(CelestialBodyFactory.getEarth().getGM());
final OEMFile file = parser.parse(name);
Assert.assertEquals(0, file.getEphemeridesBlocks().get(0).getInterpolationDegree());
Assert.assertEquals(1, file.getEphemeridesBlocks().get(0).getInterpolationDegree());
Assert.assertEquals(7, file.getEphemeridesBlocks().get(1).getInterpolationDegree());
parser = parser.withInterpolationDegree(5);
......
/* Copyright 2002-2020 CS GROUP
* Licensed to CS GROUP (CS) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* CS licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.orekit.files.general;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import java.io.BufferedWriter;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import org.hipparchus.geometry.euclidean.threed.Rotation;
import org.junit.Before;
import org.junit.Test;
import org.orekit.Utils;
import org.orekit.attitudes.AttitudeProvider;
import org.orekit.attitudes.InertialProvider;
import org.orekit.bodies.CelestialBody;
import org.orekit.bodies.CelestialBodyFactory;
import org.orekit.data.DataContext;
import org.orekit.files.ccsds.AEMParser;
import org.orekit.files.ccsds.AEMWriter;
import org.orekit.files.general.AttitudeEphemerisFile.AttitudeEphemerisSegment;
import org.orekit.files.general.OrekitAttitudeEphemerisFile.OrekitSatelliteAttitudeEphemeris;
import org.orekit.frames.Frame;
import org.orekit.frames.FramesFactory;
import org.orekit.orbits.KeplerianOrbit;
import org.orekit.orbits.PositionAngle;
import org.orekit.propagation.SpacecraftState;
import org.orekit.propagation.analytical.KeplerianPropagator;
import org.orekit.time.AbsoluteDate;
import org.orekit.utils.TimeStampedAngularCoordinates;
public class OrekitAttitudeEphemerisFileTest {
@Before
public void setUp() throws Exception {
Utils.setDataRoot("regular-data");
}
@Test
public void testGetSatellites() {
final String id1 = "ID1";
final String id2 = "ID2";
OrekitAttitudeEphemerisFile file = new OrekitAttitudeEphemerisFile();
OrekitSatelliteAttitudeEphemeris ephem1 = file.addSatellite(id1);
assertNotNull(ephem1);
OrekitSatelliteAttitudeEphemeris ephem2 = file.addSatellite(id2);
assertNotNull(ephem2);
}
@Test
public void testWritingToAEM() throws IOException {
final double quaternionTolerance = 1e-5;
final String satId = "SATELLITE1";
final double sma = 10000000;
final double inc = Math.toRadians(45.0);
final double ecc = 0.1;
final double raan = 0.0;
final double pa = 0.0;
final double ta = 0.0;
final AbsoluteDate date = new AbsoluteDate();
final Frame frame = FramesFactory.getEME2000();
final CelestialBody body = CelestialBodyFactory.getEarth();
final double mu = body.getGM();
KeplerianOrbit initialOrbit = new KeplerianOrbit(sma, ecc, inc, pa, raan, ta, PositionAngle.TRUE,
frame, date, mu);
// Initialize a Keplerian propagator with an Inertial attitude provider
// It is expected that all attitude data lines will have the same value
final Rotation refRot = new Rotation(0.72501, -0.64585, 0.018542, -0.23854, false);
AttitudeProvider inertialPointing = new InertialProvider(refRot);
KeplerianPropagator propagator = new KeplerianPropagator(initialOrbit, inertialPointing);
final double propagationDurationSeconds = 1200.0;
final double stepSizeSeconds = 60.0;
List<SpacecraftState> states = new ArrayList<SpacecraftState>();
for (double dt = 0.0; dt < propagationDurationSeconds; dt += stepSizeSeconds) {
states.add(propagator.propagate(date.shiftedBy(dt)));
}
OrekitAttitudeEphemerisFile ephemerisFile = new OrekitAttitudeEphemerisFile();
OrekitSatelliteAttitudeEphemeris satellite = ephemerisFile.addSatellite(satId);
satellite.addNewSegment(states);
// Test of all getters for OrekitSatelliteAttitudeEphemeris
assertEquals(satId, satellite.getId());
assertEquals(0.0, states.get(0).getDate().durationFrom(satellite.getStart()), 1.0e-15);
assertEquals(0.0, states.get(states.size() - 1).getDate().durationFrom(satellite.getStop()), 1.0e-15);
// Test of all getters for OrekitAttitudeEphemerisSegment
AttitudeEphemerisSegment segment = satellite.getSegments().get(0);
assertEquals(OrekitSatelliteAttitudeEphemeris.DEFAULT_INTERPOLATION_METHOD, segment.getInterpolationMethod());
assertEquals(OrekitSatelliteAttitudeEphemeris.DEFAULT_INTERPOLATION_SIZE, segment.getInterpolationSamples());
assertEquals(OrekitSatelliteAttitudeEphemeris.DEFAULT_ATTITUDE_TYPE, segment.getAttitudeType());
assertEquals(OrekitSatelliteAttitudeEphemeris.DEFAULT_IS_FIRST, segment.isFirst());
assertEquals(OrekitSatelliteAttitudeEphemeris.DEFAULT_ROTATION_ORDER, segment.getRotationOrder());
assertEquals(OrekitSatelliteAttitudeEphemeris.DEFAULT_REF_FRAME_A, segment.getRefFrameAString());
assertEquals(OrekitSatelliteAttitudeEphemeris.DEFAULT_REF_FRAME_B, segment.getRefFrameBString());
assertEquals(OrekitSatelliteAttitudeEphemeris.DEFAULT_ATTITUDE_DIR, segment.getAttitudeDirection());
assertEquals(DataContext.getDefault().getCelestialBodies().getEarth().getName(), segment.getFrameCenterString());
assertEquals(DataContext.getDefault().getTimeScales().getUTC().getName(), segment.getTimeScaleString());
assertEquals(DataContext.getDefault().getTimeScales().getUTC(), segment.getTimeScale());
assertEquals(0.0, states.get(0).getDate().durationFrom(segment.getStart()), 1.0e-15);
assertEquals(0.0, states.get(states.size() - 1).getDate().durationFrom(segment.getStop()), 1.0e-15);
String tempAemFile = Files.createTempFile("OrekitAttitudeEphemerisFileTest", ".aem").toString();
try (BufferedWriter writer = Files.newBufferedWriter(Paths.get(tempAemFile), StandardCharsets.UTF_8)) {
new AEMWriter().write(writer, ephemerisFile);
}
AttitudeEphemerisFile ephemerisFromFile = new AEMParser().parse(tempAemFile);
Files.delete(Paths.get(tempAemFile));
segment = ephemerisFromFile.getSatellites().get(satId).getSegments().get(0);
assertEquals(states.get(0).getDate(), segment.getStart());
assertEquals(states.get(states.size() - 1).getDate(), segment.getStop());
assertEquals(states.size(), segment.getAngularCoordinates().size());
assertEquals(body.getName().toUpperCase(), segment.getFrameCenterString());
for (int i = 0; i < states.size(); i++) {
TimeStampedAngularCoordinates expected = states.get(i).getAttitude().getOrientation();
TimeStampedAngularCoordinates actual = segment.getAngularCoordinates().get(i);
assertEquals(expected.getDate(), actual.getDate());
assertEquals(0.0, Rotation.distance(refRot, actual.getRotation()), quaternionTolerance);
}
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment