From 57d4e29e303192547d930d8a0539a7ff8c1ec9c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petrus=20Hyv=C3=B6nen?= <petrus.hyvonen@gmail.com> Date: Tue, 30 Jun 2020 19:45:37 +0200 Subject: [PATCH] Tests from Olivier Podevin --- .gitignore | 3 + python_files/test/AEMTest.py | 216 ++++++++++++++++++ .../OrekitFixedStepHandlerMultiplexerTest.py | 130 +++++++++++ python_files/test/TransformTest.py | 4 +- 4 files changed, 350 insertions(+), 3 deletions(-) create mode 100644 .gitignore create mode 100644 python_files/test/AEMTest.py create mode 100644 python_files/test/OrekitFixedStepHandlerMultiplexerTest.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f170d56 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +orekit-data-master +output +resources diff --git a/python_files/test/AEMTest.py b/python_files/test/AEMTest.py new file mode 100644 index 0000000..589f68a --- /dev/null +++ b/python_files/test/AEMTest.py @@ -0,0 +1,216 @@ +# -*- coding: utf-8 -*- + +""" + +/* Copyright 2002-2019 CS Syst��mes d'Information + * Licensed to CS Syst��mes d'Information (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. + */ + +Python version translated from Java by Olivier Podevin, CS Group 2020 + + """ + +import orekit + +orekit.initVM() +from orekit.pyhelpers import setup_orekit_curdir, datetime_to_absolutedate + +setup_orekit_curdir() + +import unittest +import sys +import os +import math +from datetime import datetime + +from java.util import ArrayList, List, HashMap, Map +from java.lang import Double, StringBuffer +from java.io import BufferedReader, StringReader + +from org.hipparchus.geometry.euclidean.threed import Rotation, Vector3D + +from org.orekit.attitudes import AttitudeProvider, InertialProvider +from org.orekit.bodies import CelestialBodyFactory +from org.orekit.files.ccsds import AEMParser, AEMWriter, AEMFile, Keyword, StreamingAemWriter +from org.orekit.frames import FramesFactory +from org.orekit.orbits import CartesianOrbit +from org.orekit.propagation.analytical import KeplerianPropagator +from org.orekit.time import AbsoluteDate, TimeScalesFactory, TimeScale +from org.orekit.utils import IERSConventions, PVCoordinates + +class AEMTest(unittest.TestCase): + + def testAemParsing(self): + """Test the parsing of an AEM file functionality""" + inFilename = "./resources/ccsds/AEMExample.txt" + aemParser = AEMParser() + aemParser = aemParser.withMu(CelestialBodyFactory.getEarth().getGM()). \ + withConventions(IERSConventions.IERS_2010). \ + withSimpleEOP(True) + aemFile = aemParser.parse(inFilename) + + ####### Checks + + # Start date + startRef = datetime_to_absolutedate(datetime(1996, 11, 28, 22, 8, 2, 555500)) + startFile = aemFile.getSatellites().get("1996-062A").getStart() + # print("start ref=" + startRef.toString() + ", type=" + str(type(startRef))) + # print("start file=" + startFile.toString() + ", type=" + str(type(startFile))) + # print("delta=" + str(startRef.durationFrom(startFile))) + self.assertTrue(math.isclose(startRef.durationFrom(startFile), 0, rel_tol=0.0, abs_tol=Double.MIN_VALUE)) + + # Stop date + stopRef = datetime_to_absolutedate(datetime(1996, 12, 28, 21, 23, 0, 555500)) + stopFile = aemFile.getSatellites().get("1996-062A").getStop() + self.assertTrue(math.isclose(stopRef.durationFrom(stopFile), 0, rel_tol=0.0, abs_tol=Double.MIN_VALUE)) + + def testAemWriting(self): + """Test the writing of an AEM file functionality""" + inFilename = "./resources/ccsds/AEMExample.txt" + + aemParser = AEMParser() + aemParser = aemParser.withMu(CelestialBodyFactory.getEarth().getGM()) \ + .withConventions(IERSConventions.IERS_2010) + + aemFile = aemParser.parse(inFilename) + + ####### Read values + originator = aemFile.getOriginator() + objectName = aemFile.getAttitudeBlocks().get(0).getMetaData().getObjectName() + objectID = aemFile.getAttitudeBlocks().get(0).getMetaData().getObjectID() + + ####### Create AEM file + outputDir = "./output/ccsds" + tempFilename = "TestWriteAEM1.aem" + tempAEMFilePath = os.path.join(outputDir, tempFilename) + + # Create output dir if needed + if (not os.path.isdir(outputDir)): + os.makedirs(outputDir) + + aemWriter = AEMWriter(originator, objectID, objectName) + aemWriter.write(tempAEMFilePath, aemFile) + + ####### Checks + generatedAemFile = aemParser.parse(tempAEMFilePath) + originatorOut = aemFile.getOriginator() + objectNameOut = aemFile.getAttitudeBlocks().get(0).getMetaData().getObjectName() + objectIDOut = aemFile.getAttitudeBlocks().get(0).getMetaData().getObjectID() + + self.assertEqual(originator, originatorOut) + self.assertEqual(objectName, objectNameOut) + self.assertEqual(objectID, objectIDOut) + + def testAemStreamWriting(self): + """Test the stream writing of an AEM file functionality""" + + QUATERNION_PRECISION = 1e-5 + DATE_PRECISION = 1e-3 + + # Time scale + utc = TimeScalesFactory.getUTC() + + inFilename = "./resources/ccsds/AEMExample.txt" + + # Create a list of files + files = ["./resources/ccsds/AEMExample7.txt"] + + for ex in files: + # Reference AEM file + aemParser = AEMParser() + aemParser = aemParser.withMu(CelestialBodyFactory.getEarth().getGM()) \ + .withConventions(IERSConventions.IERS_2010) + + aemFile = aemParser.parse(ex) + + # Satellite attitude ephemeris as read from the reference file + satellite = aemFile.getSatellites().values().iterator().next() + + # Meta data are extracted from the reference file + originator = aemFile.getOriginator() + objectName = satellite.getSegments().get(0).getMetaData().getObjectName() + objectID = satellite.getSegments().get(0).getMetaData().getObjectID() + headerCmt = aemFile.getHeaderComment().get(0) + attitudeDir = satellite.getSegments().get(0).getAttitudeDirection() + refFrameA = satellite.getSegments().get(0).getRefFrameAString() + refFrameB = satellite.getSegments().get(0).getRefFrameBString() + attitudeType = satellite.getSegments().get(0).getAttitudeType() + isFirst = "LAST" + + metadata = HashMap() + metadata.put(Keyword.ORIGINATOR, originator) + metadata.put(Keyword.OBJECT_NAME, "will be overwritten") + metadata.put(Keyword.OBJECT_ID, objectID) + metadata.put(Keyword.COMMENT, headerCmt) + + segmentData = HashMap() + segmentData.put(Keyword.OBJECT_NAME, objectName) + segmentData.put(Keyword.ATTITUDE_DIR, attitudeDir) + segmentData.put(Keyword.QUATERNION_TYPE, isFirst) + segmentData.put(Keyword.ATTITUDE_TYPE, attitudeType) + segmentData.put(Keyword.REF_FRAME_A, refFrameA) + segmentData.put(Keyword.REF_FRAME_B, refFrameB.replace(' ', '_')) + + # Initialize a Keplerian propagator with an Inertial attitude provider + # It is expected that all attitude data lines will have the same value + buffer = StringBuffer() + streamingAemWriter = StreamingAemWriter(buffer, utc, metadata) + streamingAemWriter.writeHeader() + segment = streamingAemWriter.newSegment(segmentData) + + #### Create a Keplerian propagator. + startingDate = satellite.getSegments().get(0).getStart() + attitudeProvider = InertialProvider(satellite.getSegments().get(0).getAngularCoordinates().get(0).getRotation(), \ + FramesFactory.getEME2000()) + position = Vector3D(-29536113.0, 30329259.0, -100125.0) + velocity = Vector3D(-2194.0, -2141.0, -8.0) + pvCoordinates = PVCoordinates( position, velocity) + mu = 3.9860047e14 + cartesianOrbit = CartesianOrbit(pvCoordinates, FramesFactory.getEME2000(), startingDate, mu) + propagator = KeplerianPropagator(cartesianOrbit, attitudeProvider) + + # We propagate 60 seconds after the start date with a step equals to 10.0 seconds + # It is expected to have an attitude data block containing 7 data lines + step = 10.0 + propagator.setMasterMode(step, segment) + propagator.propagate(satellite.getSegments().get(0).getStart().shiftedBy(60.0)) + + # Generated AEM file + reader = BufferedReader(StringReader(buffer.toString())) + generatedAemFile = aemParser.parse(reader, "buffer") + + # There is only one attitude ephemeris block + self.assertEqual(1, generatedAemFile.getAttitudeBlocks().size()) + # There are 7 data lines in the attitude ephemeris block + ac = generatedAemFile.getAttitudeBlocks().get(0).getAngularCoordinates() + self.assertEqual(7, ac.size()) + + # Verify + i = 0 + while (i < 7): + #self.assertEqual(step * i, ac.get(i).getDate().durationFrom(satellite.getSegments().get(0).getStart()), DATE_PRECISION) + self.assertTrue(math.isclose(step * i, ac.get(i).getDate().durationFrom(satellite.getSegments().get(0).getStart()), rel_tol=0.0, abs_tol=DATE_PRECISION)) + rot = ac.get(i).getRotation() + self.assertTrue(math.isclose(0.68427, rot.getQ0(), rel_tol=0.0, abs_tol=QUATERNION_PRECISION)) + self.assertTrue(math.isclose(0.56748, rot.getQ1(), rel_tol=0.0, abs_tol=QUATERNION_PRECISION)) + self.assertTrue(math.isclose(0.03146, rot.getQ2(), rel_tol=0.0, abs_tol=QUATERNION_PRECISION)) + self.assertTrue(math.isclose(0.45689, rot.getQ3(), rel_tol=0.0, abs_tol=QUATERNION_PRECISION)) + i += 1 + +if __name__ == '__main__': + suite = unittest.TestLoader().loadTestsFromTestCase(AEMTest) + ret = not unittest.TextTestRunner(verbosity=2).run(suite).wasSuccessful() + sys.exit(ret) diff --git a/python_files/test/OrekitFixedStepHandlerMultiplexerTest.py b/python_files/test/OrekitFixedStepHandlerMultiplexerTest.py new file mode 100644 index 0000000..a75c03d --- /dev/null +++ b/python_files/test/OrekitFixedStepHandlerMultiplexerTest.py @@ -0,0 +1,130 @@ +# -*- coding: utf-8 -*- + +""" + +/* Copyright 2002-2019 CS Syst��mes d'Information + * Licensed to CS Syst��mes d'Information (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. + */ + +Python version translated from Java by Olivier Podevin, CS Group 2020 + + """ + +import orekit + +orekit.initVM() +from orekit.pyhelpers import setup_orekit_curdir, datetime_to_absolutedate + +setup_orekit_curdir() + +import unittest +import sys +import os +import math +from datetime import datetime + +from java.util import ArrayList, List, HashMap, Map +from java.lang import Double, StringBuffer +from java.io import BufferedReader, StringReader + +from org.hipparchus.geometry.euclidean.threed import Rotation, Vector3D +from org.hipparchus.util import FastMath + +from org.orekit.attitudes import AttitudeProvider, InertialProvider +from org.orekit.bodies import CelestialBodyFactory +from org.orekit.files.ccsds import AEMParser, AEMWriter, AEMFile, Keyword, StreamingAemWriter +from org.orekit.frames import FramesFactory +from org.orekit.orbits import CartesianOrbit, KeplerianOrbit, PositionAngle +from org.orekit.propagation import SpacecraftState +from org.orekit.propagation.analytical import KeplerianPropagator +from org.orekit.propagation.sampling import OrekitFixedStepHandler, OrekitFixedStepHandlerMultiplexer, PythonOrekitFixedStepHandler +from org.orekit.time import AbsoluteDate, TimeScalesFactory, TimeScale +from org.orekit.utils import Constants, IERSConventions, PVCoordinates + + + +class InitCheckerHandler(PythonOrekitFixedStepHandler): + + def __init__(self, expected, initialized = False): + super(InitCheckerHandler, self).__init__() + self.expected = expected + self.initialized = initialized + + def init(self, s0, t, step): + self.initialized = True + + def handleStep(self, currentState, isLast): + self.expected = 2.0 + + def isInitialized(self): + return self.initialized + + def getExpected(self): + return self.expected + +class IncrementationHandler(PythonOrekitFixedStepHandler): + + def __init__(self): + super(IncrementationHandler, self).__init__() + self.value = 0 + + def init(self, s0, t, step): + self.value = 1 + + def handleStep(self, currentState, isLast): + self.value += 1 + + def getValue(self): + return self.value + +class OrekitFixedStepHandlerMultiplexerTest(unittest.TestCase): + + def testOrekitFixedStepHandlerMultiplexer(self): + """Test the Orekit fixed StepHandler Multiplexer functionality""" + + # init + initDate = AbsoluteDate(2020, 2, 28, 16, 15, 0.0, TimeScalesFactory.getUTC()) + + initHandler = InitCheckerHandler(1.0) + incrementationHandler = IncrementationHandler() + + multiplexer = OrekitFixedStepHandlerMultiplexer() + multiplexer.add(initHandler) + multiplexer.add(incrementationHandler) + + ic = KeplerianOrbit(6378137 + 500e3, 1e-3, 0.0, 0.0, 0.0, 0.0, + PositionAngle.TRUE, + FramesFactory.getGCRF(), + initDate, + Constants.WGS84_EARTH_MU) + + propagator = KeplerianPropagator(ic) + propagator.setMasterMode(60.0, multiplexer) + + self.assertFalse(initHandler.isInitialized()) + self.assertTrue(math.isclose(1.0, initHandler.getExpected(), rel_tol = 0.0, abs_tol = Double.MIN_VALUE)) + + propagator.propagate(initDate.shiftedBy(90.0)) + + # verify + self.assertTrue(initHandler.isInitialized()) + self.assertTrue(math.isclose(2.0, initHandler.getExpected(), rel_tol = 0.0, abs_tol = Double.MIN_VALUE)) + self.assertEqual(3, incrementationHandler.getValue()) + +if __name__ == '__main__': + suite = unittest.TestLoader().loadTestsFromTestCase(OrekitFixedStepHandlerMultiplexerTest) + ret = not unittest.TextTestRunner(verbosity=2).run(suite).wasSuccessful() + sys.exit(ret) diff --git a/python_files/test/TransformTest.py b/python_files/test/TransformTest.py index c973605..5b0da05 100644 --- a/python_files/test/TransformTest.py +++ b/python_files/test/TransformTest.py @@ -46,14 +46,13 @@ from org.orekit.utils import TimeStampedPVCoordinates; from org.orekit.frames import Transform from org.orekit.frames import FramesFactory - class TransformTest(unittest.TestCase): def testPythonTransformType(self): # Create initial TimeStampedPVCoordinates pos = Vector3D(10000., 20000., 30000.) vel = Vector3D(2000., 1000., 1500.) - date = datetime_to_absolutedate(datetime(2000, 3, 13)) + date = datetime_to_absolutedate(datetime(2019, 3, 13)) pvt1 = TimeStampedPVCoordinates(date, pos, vel) print(type(pvt1)) @@ -125,7 +124,6 @@ class TransformTest(unittest.TestCase): self.checkVector(rebuiltPV.getAcceleration(), transformedPV.getAcceleration(), 9.0e-11) dt += 0.01 - if __name__ == '__main__': suite = unittest.TestLoader().loadTestsFromTestCase(TransformTest) ret = not unittest.TextTestRunner(verbosity=2).run(suite).wasSuccessful() -- GitLab