Commit 2ac17cd6 authored by Luc Maisonobe's avatar Luc Maisonobe
Browse files

Merge branch 'issue-474' into develop

parents f44699de 8c314b1e
Pipeline #1049 passed with stages
in 32 minutes and 18 seconds
......@@ -117,6 +117,7 @@ public class XmlGenerator extends AbstractGenerator {
* @param value element value
* @param attributeName attribute name
* @param attributeValue attribute value
* @throws IOException if an I/O error occurs.
*/
public void writeOneAttributeElement(final String name, final String value,
final String attributeName, final String attributeValue)
......@@ -133,6 +134,7 @@ public class XmlGenerator extends AbstractGenerator {
* @param attribute1Value attribute 1 value
* @param attribute2Name attribute 2 name
* @param attribute2Value attribute 2 value
* @throws IOException if an I/O error occurs.
*/
public void writeTwoAttributesElement(final String name, final String value,
final String attribute1Name, final String attribute1Value,
......
......@@ -25,6 +25,8 @@ import org.hipparchus.geometry.euclidean.threed.Rotation;
import org.hipparchus.geometry.euclidean.threed.RotationConvention;
import org.hipparchus.geometry.euclidean.threed.RotationOrder;
import org.hipparchus.geometry.euclidean.threed.Vector3D;
import org.hipparchus.util.Decimal64;
import org.hipparchus.util.Decimal64Field;
import org.hipparchus.util.FastMath;
import org.junit.Assert;
import org.junit.Before;
......@@ -32,12 +34,14 @@ import org.junit.Test;
import org.orekit.Utils;
import org.orekit.attitudes.Attitude;
import org.orekit.attitudes.BoundedAttitudeProvider;
import org.orekit.attitudes.FieldAttitude;
import org.orekit.bodies.CelestialBodyFactory;
import org.orekit.data.DataContext;
import org.orekit.data.DataSource;
import org.orekit.errors.OrekitException;
import org.orekit.errors.OrekitMessages;
import org.orekit.files.ccsds.definitions.CelestialBodyFrame;
import org.orekit.files.ccsds.definitions.OrbitRelativeFrame;
import org.orekit.files.ccsds.definitions.SpacecraftBodyFrame;
import org.orekit.files.ccsds.definitions.TimeSystem;
import org.orekit.files.ccsds.ndm.ParserBuilder;
......@@ -45,10 +49,15 @@ import org.orekit.files.ccsds.ndm.adm.AttitudeType;
import org.orekit.files.ccsds.section.Segment;
import org.orekit.frames.FramesFactory;
import org.orekit.frames.ITRFVersion;
import org.orekit.orbits.CircularOrbit;
import org.orekit.orbits.FieldCircularOrbit;
import org.orekit.orbits.PositionAngle;
import org.orekit.time.AbsoluteDate;
import org.orekit.time.FieldAbsoluteDate;
import org.orekit.time.TimeScale;
import org.orekit.time.TimeScalesFactory;
import org.orekit.utils.AngularDerivativesFilter;
import org.orekit.utils.Constants;
import org.orekit.utils.IERSConventions;
import org.orekit.utils.TimeStampedAngularCoordinates;
......@@ -465,6 +474,72 @@ public class AEMParserTest {
}
@Test
public void testParseAEM13() throws URISyntaxException {
final TimeScale tai = TimeScalesFactory.getTAI();
final String ex = "/ccsds/adm/aem/AEMExample13.xml";
final DataSource source = new DataSource(ex, () -> getClass().getResourceAsStream(ex));
final AemParser parser = new ParserBuilder().buildAemParser();
final AemFile file = parser.parseMessage(source);
final Segment<AemMetadata, AemData> segment0 = file.getSegments().get(0);
Assert.assertEquals(TimeSystem.TAI, segment0.getMetadata().getTimeSystem());
Assert.assertEquals("OREKIT SAT", segment0.getMetadata().getObjectName());
Assert.assertEquals("2020-012A", segment0.getMetadata().getObjectID());
Assert.assertEquals(OrbitRelativeFrame.LVLH, segment0.getMetadata().getEndpoints().getFrameA().asOrbitRelativeFrame());
Assert.assertEquals(SpacecraftBodyFrame.BaseEquipment.IMU_FRAME, segment0.getMetadata().getEndpoints().getFrameB().asSpacecraftBodyFrame().getBaseEquipment());
Assert.assertEquals("1", segment0.getMetadata().getEndpoints().getFrameB().asSpacecraftBodyFrame().getLabel());
Assert.assertFalse(segment0.getMetadata().getEndpoints().isA2b());
Assert.assertEquals(new AbsoluteDate("2021-04-15T13:31:20.000", tai), segment0.getMetadata().getStartTime());
Assert.assertEquals(new AbsoluteDate("2021-04-15T13:31:23.000", tai), segment0.getMetadata().getStopTime());
Assert.assertEquals(AttitudeType.QUATERNION_DERIVATIVE, segment0.getMetadata().getAttitudeType());
Assert.assertTrue(segment0.getMetadata().isFirst());
final AbsoluteDate refDate = new AbsoluteDate("2021-04-15T13:31:20.000", tai);
Assert.assertEquals(7, segment0.getData().getAngularCoordinates().size());
final TimeStampedAngularCoordinates ac0 = segment0.getData().getAngularCoordinates().get(0);
Assert.assertEquals(0.0, ac0.getDate().durationFrom(refDate), 1.0e-5);
Assert.assertEquals(0.0,
Rotation.distance(new Rotation(-0.488615, -0.402157, 0.581628, 0.511111, true),
ac0.getRotation()),
1.0e-10);
final TimeStampedAngularCoordinates ac1 = segment0.getData().getAngularCoordinates().get(1);
Assert.assertEquals(0.5, ac1.getDate().durationFrom(refDate), 1.0e-5);
Assert.assertEquals(0.0,
Rotation.distance(new Rotation(-0.488765, -0.402027, 0.581486, 0.511231, true),
ac1.getRotation()),
1.0e-10);
final TimeStampedAngularCoordinates ac2 = segment0.getData().getAngularCoordinates().get(2);
Assert.assertEquals(1.0, ac2.getDate().durationFrom(refDate), 1.0e-5);
Assert.assertEquals(0.0,
Rotation.distance(new Rotation(-0.488916, -0.401898, 0.581344, 0.511350, true),
ac2.getRotation()),
1.0e-10);
final CircularOrbit o = new CircularOrbit(6992992, -5e-04, 1.2e-03,
FastMath.toRadians(97.83), FastMath.toRadians(80.95),
FastMath.toRadians(179.86), PositionAngle.MEAN,
FramesFactory.getEME2000(),
new AbsoluteDate("2021-04-15T13:31:22.000", tai),
Constants.EIGEN5C_EARTH_MU);
final FieldCircularOrbit<Decimal64> fo =
new FieldCircularOrbit<>(new Decimal64(o.getA()),
new Decimal64(o.getCircularEx()), new Decimal64(o.getCircularEy()),
new Decimal64(o.getI()), new Decimal64(o.getRightAscensionOfAscendingNode()),
new Decimal64(o.getAlphaM()), PositionAngle.MEAN,
o.getFrame(), new FieldAbsoluteDate<>(Decimal64Field.getInstance(), o.getDate()),
new Decimal64(o.getMu()));
final AemSatelliteEphemeris ephemeris = file.getSatellites().get("2020-012A");
final BoundedAttitudeProvider provider = ephemeris.getAttitudeProvider();
Attitude a = provider.getAttitude(o, o.getDate(), o.getFrame());
FieldAttitude<Decimal64> fa = provider.getAttitude(fo, fo.getDate(), fo.getFrame());
Assert.assertEquals(a.getRotation().getQ0(), fa.getRotation().getQ0().getReal(), 0.00001);
Assert.assertEquals(a.getRotation().getQ1(), fa.getRotation().getQ1().getReal(), 0.00001);
Assert.assertEquals(a.getRotation().getQ2(), fa.getRotation().getQ2().getReal(), 0.00001);
Assert.assertEquals(a.getRotation().getQ3(), fa.getRotation().getQ3().getReal(), 0.00001);
}
@Test
public void testWrongNDMType() {
final String name = "/ccsds/odm/opm/OPMExample1.txt";
......
......@@ -107,4 +107,9 @@ public class AemWriterTest extends AbstractNdmWriterTest<Header, AemSegment, Aem
doTest("/ccsds/adm/aem/AEMExample12.txt");
}
@Test
public void testWriteExample13() {
doTest("/ccsds/adm/aem/AEMExample13.xml");
}
}
......@@ -122,6 +122,10 @@ public class APMParserTest {
Assert.assertEquals(0.40949, segment.getData().getQuaternionBlock().getQuaternion().getQ3(), QUATERNION_PRECISION);
Assert.assertFalse(segment.getData().getQuaternionBlock().hasRates());
Assert.assertTrue(Double.isNaN(segment.getData().getQuaternionBlock().getQuaternionDot().getQ1()));
Assert.assertEquals(new AbsoluteDate(2003, 9, 30, 14, 28, 15.1172,
TimeScalesFactory.getUTC()),
segment.getData().getQuaternionBlock().getAttitude(null, null).getDate());
Assert.assertEquals(0.0, segment.getData().getQuaternionBlock().getAttitude(null, null).getSpin().getNorm(), 1.0e-15);
Attitude attitude = file.getAttitude(null, null);
Assert.assertEquals(new AbsoluteDate(2003, 9, 30, 14, 28, 15.1172, TimeScalesFactory.getUTC()),
......@@ -416,6 +420,12 @@ public class APMParserTest {
Assert.assertEquals(0.00001, segment.getData().getQuaternionBlock().getQuaternionDot().getQ1(), QUATERNION_PRECISION);
Assert.assertEquals(0.07543, segment.getData().getQuaternionBlock().getQuaternionDot().getQ2(), QUATERNION_PRECISION);
Assert.assertEquals(0.00949, segment.getData().getQuaternionBlock().getQuaternionDot().getQ3(), QUATERNION_PRECISION);
Assert.assertEquals(new AbsoluteDate(2003, 9, 30, 14, 28, 15.1172,
TimeScalesFactory.getUTC()),
segment.getData().getQuaternionBlock().getAttitude(null, null).getDate());
Assert.assertEquals(8.63363e-2,
segment.getData().getQuaternionBlock().getAttitude(null, null).getSpin().getNorm(),
1.0e-7);
Attitude attitude = file.getAttitude(null, null);
Assert.assertEquals(segment.getData().getQuaternionBlock().getEpoch(),
......@@ -899,6 +909,22 @@ public class APMParserTest {
}
}
@Test
public void testMissingQuaternionComponent() throws URISyntaxException {
final String name = "/ccsds/adm/apm/APM-missing-quaternion-component.txt";
try {
final DataSource source = new DataSource(name, () -> getClass().getResourceAsStream(name));
new ParserBuilder().
withMissionReferenceDate(AbsoluteDate.J2000_EPOCH).
buildApmParser().
parseMessage(source);
Assert.fail("an exception should have been thrown");
} catch (OrekitException oe) {
Assert.assertEquals(OrekitMessages.UNINITIALIZED_VALUE_FOR_KEY, oe.getSpecifier());
Assert.assertEquals("Q{C|1|2|3}", oe.getParts()[0]);
}
}
@Test
public void testWrongKeyword() throws URISyntaxException {
final String name = "/ccsds/adm/apm/APM-wrong-keyword.txt";
......
<?xml version="1.0" encoding="UTF-8"?>
<aem id="CCSDS_AEM_VERS" version="1.0">
<header>
<CREATION_DATE>2021-04-15T13:31:24.0</CREATION_DATE>
<ORIGINATOR>CS GROUP</ORIGINATOR>
</header>
<body>
<segment>
<metadata>
<OBJECT_NAME>OREKIT SAT</OBJECT_NAME>
<OBJECT_ID>2020-012A</OBJECT_ID>
<REF_FRAME_A>LVLH</REF_FRAME_A>
<REF_FRAME_B>IMU_FRAME_1</REF_FRAME_B>
<ATTITUDE_DIR>B2A</ATTITUDE_DIR>
<TIME_SYSTEM>TAI</TIME_SYSTEM>
<START_TIME>2021-04-15T13:31:20.0</START_TIME>
<STOP_TIME>2021-04-15T13:31:23.0</STOP_TIME>
<ATTITUDE_TYPE>QUATERNION/DERIVATIVE</ATTITUDE_TYPE>
<QUATERNION_TYPE>FIRST</QUATERNION_TYPE>
<INTERPOLATION_DEGREE>1</INTERPOLATION_DEGREE>
</metadata>
<data>
<attitudeState>
<quaternionDerivative>
<EPOCH>2021-04-15T13:31:20.0</EPOCH>
<quaternion>
<QC>0.4886148886986714</QC>
<Q1>-0.40215690839288926</Q1>
<Q2>0.5816278675112939</Q2>
<Q3>0.5111108835743206</Q3>
</quaternion>
<quaternionRate>
<QC_DOT units="1/s">3.0077619996648645E-4</QC_DOT>
<Q1_DOT units="1/s">2.5945771992435184E-4</Q1_DOT>
<Q2_DOT units="1/s">-2.8362061580605415E-4</Q2_DOT>
<Q3_DOT units="1/s">2.393622263168597E-4</Q3_DOT>
</quaternionRate>
</quaternionDerivative>
</attitudeState>
<attitudeState>
<quaternionDerivative>
<EPOCH>2021-04-15T13:31:20.5</EPOCH>
<quaternion>
<QC>0.4887649908329683</QC>
<Q1>-0.40202699245978285</Q1>
<Q2>0.5814859890939396</Q2>
<Q3>0.5112309904116072</Q3>
</quaternion>
<quaternionRate>
<QC_DOT units="1/s">3.0071481809516165E-4</QC_DOT>
<Q1_DOT units="1/s">2.5950414011706777E-4</Q1_DOT>
<Q2_DOT units="1/s">-2.837152043818123E-4</Q2_DOT>
<Q3_DOT units="1/s">2.3927581114550022E-4</Q3_DOT>
</quaternionRate>
</quaternionDerivative>
</attitudeState>
<attitudeState>
<quaternionDerivative>
<EPOCH>2021-04-15T13:31:21.0</EPOCH>
<quaternion>
<QC>0.48891587134278325</QC>
<Q1>-0.40189789424138683</Q1>
<Q2>0.5813438470205494</Q2>
<Q3>0.5113498654393233</Q3>
</quaternion>
<quaternionRate>
<QC_DOT units="1/s">3.006517334171891E-4</QC_DOT>
<Q1_DOT units="1/s">2.5955208580067334E-4</Q1_DOT>
<Q2_DOT units="1/s">-2.8380814822340114E-4</Q2_DOT>
<Q3_DOT units="1/s">2.3919074098857043E-4</Q3_DOT>
</quaternionRate>
</quaternionDerivative>
</attitudeState>
<attitudeState>
<quaternionDerivative>
<EPOCH>2021-04-15T13:31:21.5</EPOCH>
<quaternion>
<QC>0.4890659012370637</QC>
<Q1>-0.4017679188661911</Q1>
<Q2>0.5812018826309413</Q2>
<Q3>0.5114698967127566</Q3>
</quaternion>
<quaternionRate>
<QC_DOT units="1/s">3.005886439556086E-4</QC_DOT>
<Q1_DOT units="1/s">2.596001902002068E-4</Q1_DOT>
<Q2_DOT units="1/s">-2.8390129365150717E-4</Q2_DOT>
<Q3_DOT units="1/s">2.391056428420167E-4</Q3_DOT>
</quaternionRate>
</quaternionDerivative>
</attitudeState>
<attitudeState>
<quaternionDerivative>
<EPOCH>2021-04-15T13:31:22.0</EPOCH>
<quaternion>
<QC>0.4892161452431583</QC>
<Q1>-0.4016381192421581</Q1>
<Q2>0.5810601725106898</Q2>
<Q3>0.51158915188547</Q3>
</quaternion>
<quaternionRate>
<QC_DOT units="1/s">3.005240863786447E-4</QC_DOT>
<Q1_DOT units="1/s">2.5965107942241364E-4</Q1_DOT>
<Q2_DOT units="1/s">-2.839930876922821E-4</Q2_DOT>
<Q3_DOT units="1/s">2.3902306798958108E-4</Q3_DOT>
</quaternionRate>
</quaternionDerivative>
</attitudeState>
<attitudeState>
<quaternionDerivative>
<EPOCH>2021-04-15T13:31:22.5</EPOCH>
<quaternion>
<QC>0.48936686342800423</QC>
<Q1>-0.4015078879475958</Q1>
<Q2>0.5809178378780534</Q2>
<Q3>0.5117088571928238</Q3>
</quaternion>
<quaternionRate>
<QC_DOT units="1/s">3.0046090906165154E-4</QC_DOT>
<Q1_DOT units="1/s">2.5969893333732414E-4</Q1_DOT>
<Q2_DOT units="1/s">-2.840859291292821E-4</Q2_DOT>
<Q3_DOT units="1/s">2.3893692590818883E-4</Q3_DOT>
</quaternionRate>
</quaternionDerivative>
</attitudeState>
<attitudeState>
<quaternionDerivative>
<EPOCH>2021-04-15T13:31:23.0</EPOCH>
<quaternion>
<QC>0.48951703526162665</QC>
<Q1>-0.40137802891266533</Q1>
<Q2>0.5807760418353325</Q2>
<Q3>0.5118280368687662</Q3>
</quaternion>
<quaternionRate>
<QC_DOT units="1/s">3.00400025108563E-4</QC_DOT>
<Q1_DOT units="1/s">2.597440158653036E-4</Q1_DOT>
<Q2_DOT units="1/s">-2.841810163540131E-4</Q2_DOT>
<Q3_DOT units="1/s">2.3885002083304103E-4</Q3_DOT>
</quaternionRate>
</quaternionDerivative>
</attitudeState>
</data>
</segment>
</body>
</aem>
CCSDS_APM_VERS = 1.0
CREATION_DATE = 2004-02-14T19:23:57
ORIGINATOR = JPL
OBJECT_NAME = MARS SPIRIT
OBJECT_ID = 2004-003A
CENTER_NAME = EARTH
TIME_SYSTEM = UTC
EPOCH = 2004-02-14T14:28:15.1172
Q_FRAME_A = INSTRUMENT_A
Q_FRAME_B = ITRF-97
Q_DIR = A2B
Q1 = 0.03123
Q2 = 0.78543
QC = 0.47832
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