From b838cfb5ee1fb72f19976d0fa0427bfa8cb39a1d Mon Sep 17 00:00:00 2001
From: petrush <petrus.hyvonen@sscspace.com>
Date: Thu, 28 Feb 2019 09:43:58 +0100
Subject: [PATCH] reserved SNAN keyword, updated tests.

---
 orekit-conda-recipe/bld.bat                   |   9 +
 orekit-conda-recipe/build.sh                  |   9 +
 orekit-conda-recipe/meta.yaml                 |   8 +-
 orekit-conda-recipe/run_test.sh               |   1 +
 .../test/InterSatDirectViewDetectorTest.py    | 173 ++++++++++++++++++
 python_files/test/IodGibbsTest.py             | 144 ---------------
 python_files/test/NodeDetectorTest.py         |  25 +--
 python_files/test/OrekitStepHandlerTest.py    | 153 +++++++---------
 8 files changed, 279 insertions(+), 243 deletions(-)
 create mode 100644 python_files/test/InterSatDirectViewDetectorTest.py
 delete mode 100644 python_files/test/IodGibbsTest.py

diff --git a/orekit-conda-recipe/bld.bat b/orekit-conda-recipe/bld.bat
index 20a6b31..0ddb996 100644
--- a/orekit-conda-recipe/bld.bat
+++ b/orekit-conda-recipe/bld.bat
@@ -35,6 +35,7 @@ java.io.StringWriter ^
 java.lang.System ^
 java.text.DecimalFormat ^
 java.text.DecimalFormatSymbols ^
+java.util.ArrayDeque  ^
 java.util.ArrayList  ^
 java.util.Arrays  ^
 java.util.Collection  ^
@@ -47,6 +48,13 @@ java.util.Locale ^
 java.util.Map ^
 java.util.Set ^
 java.util.TreeSet ^
+java.util.concurrent.Executors ^
+java.util.concurrent.TimeUnit ^
+java.util.concurrent.ExecutorService ^
+java.util.stream.Collectors ^
+java.util.stream.Stream ^
+java.util.stream.DoubleStream ^
+java.util.concurrent.atomic.AtomicReference ^
 --module %SRC_DIR%\pyhelpers.py ^
 --reserved INFINITE ^
 --reserved ERROR ^
@@ -56,6 +64,7 @@ java.util.TreeSet ^
 --reserved min ^
 --reserved max ^
 --reserved mean ^
+--reserved SNAN ^
 --files 10 ^
 --build ^
 --install
diff --git a/orekit-conda-recipe/build.sh b/orekit-conda-recipe/build.sh
index eeb676e..aa31c1d 100644
--- a/orekit-conda-recipe/build.sh
+++ b/orekit-conda-recipe/build.sh
@@ -29,6 +29,7 @@ java.io.StringWriter \
 java.lang.System \
 java.text.DecimalFormat \
 java.text.DecimalFormatSymbols \
+java.util.ArrayDeque  \
 java.util.ArrayList \
 java.util.Arrays \
 java.util.Collection \
@@ -41,6 +42,13 @@ java.util.Locale \
 java.util.Map \
 java.util.Set \
 java.util.TreeSet \
+java.util.concurrent.Executors \
+java.util.concurrent.TimeUnit \
+java.util.concurrent.ExecutorService \
+java.util.stream.Collectors \
+java.util.stream.Stream \
+java.util.stream.DoubleStream \
+java.util.concurrent.atomic.AtomicReference \
 --module $SRC_DIR/pyhelpers.py \
 --reserved INFINITE \
 --reserved ERROR \
@@ -50,6 +58,7 @@ java.util.TreeSet \
 --reserved min \
 --reserved max \
 --reserved mean \
+--reserved SNAN \
 --files 10 \
 --build \
 --install
diff --git a/orekit-conda-recipe/meta.yaml b/orekit-conda-recipe/meta.yaml
index cc075a4..d2d5374 100644
--- a/orekit-conda-recipe/meta.yaml
+++ b/orekit-conda-recipe/meta.yaml
@@ -1,7 +1,7 @@
 {% set name = "orekit" %}
 {% set version = "9.3" %}
-{% set filename = "v9_3" %}
-{% set sha256 = "5d221350bc9f7fccefeb6405f87dc424d8cd4fcdd3a379d8170d20978a7593c7" %}
+{% set filename = "v9_3_2" %}
+{% set sha256 = "c369e544442a32d39fc12cf5de569b4d5afd29174a73b8cd0c006c07dbe916d8" %}
 
 package:
   name: {{ name|lower }}
@@ -13,9 +13,7 @@ source:
   sha256: {{ sha256 }}
 
 build:
-  skip: true  # [win32 or linux32]
-
-  number: 0
+  number: 2
 
   rpaths:
     - lib/
diff --git a/orekit-conda-recipe/run_test.sh b/orekit-conda-recipe/run_test.sh
index 8483014..06f212b 100644
--- a/orekit-conda-recipe/run_test.sh
+++ b/orekit-conda-recipe/run_test.sh
@@ -1,4 +1,5 @@
 #!/usr/bin/env bash
 cd test
+set -e
 for f in *.py; do python "$f"; done || exit 1
 
diff --git a/python_files/test/InterSatDirectViewDetectorTest.py b/python_files/test/InterSatDirectViewDetectorTest.py
new file mode 100644
index 0000000..fc100d1
--- /dev/null
+++ b/python_files/test/InterSatDirectViewDetectorTest.py
@@ -0,0 +1,173 @@
+# -*- coding: utf-8 -*-
+
+"""
+/* Copyright 2002-2018 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 Petrus Hyvönen, SSC 2019
+
+"""
+
+import sys
+import unittest
+
+import orekit
+
+orekit.initVM()
+from orekit.pyhelpers import setup_orekit_curdir
+
+setup_orekit_curdir()  # orekit-data.zip shall be in current dir
+
+from org.orekit.propagation.events import EventsLogger
+from org.hipparchus.util import FastMath
+from org.orekit.frames import FramesFactory
+from org.orekit.orbits import PositionAngle
+from org.orekit.time import AbsoluteDate
+from org.orekit.time import TimeScalesFactory
+from org.orekit.utils import Constants
+from org.orekit.python import PythonOrekitFixedStepHandler
+from org.orekit.propagation.events import InterSatDirectViewDetector
+from org.hipparchus.geometry.euclidean.threed import Line
+from org.hipparchus.geometry.euclidean.threed import Vector3D
+from org.orekit.bodies import OneAxisEllipsoid
+from org.orekit.frames import TopocentricFrame
+from org.orekit.orbits import CircularOrbit
+from org.orekit.propagation.analytical import KeplerianPropagator
+from org.orekit.propagation.events.handlers import EventHandler
+from org.orekit.utils import IERSConventions
+from org.orekit.python import PythonEventHandler
+
+
+class GrazingHandler(PythonEventHandler):
+
+    def eventOccurred(self, s, detector, increasing):
+        # just before increasing events and just after decreasing events,
+        # the master/slave line intersects Earth limb
+        detector = InterSatDirectViewDetector.cast_(detector)  # Otherwise this is just a plain EventDetector
+        earth = detector.getCentralBody()
+        frame = earth.getBodyFrame()
+        dt = -1.0e-8 if increasing else +1.0e-8
+
+        grazingDate = s.getDate().shiftedBy(dt)
+        pMaster = s.shiftedBy(dt).getPVCoordinates(frame).getPosition()
+        pSlave = detector.getSlave().getPVCoordinates(grazingDate, frame).getPosition()
+        grazing = earth.getCartesianIntersectionPoint(Line(pMaster, pSlave, 1.0),
+                                                      pMaster, frame, grazingDate)
+
+        topo = TopocentricFrame(earth, earth.transform(grazing, frame, grazingDate),
+                                "grazing")
+
+        testvalue = FastMath.toDegrees(topo.getElevation(pMaster, frame, grazingDate))
+        assert -2.0e4 < testvalue < 2.0e4
+
+        testvalue = FastMath.abs(FastMath.toDegrees(topo.getAzimuth(pSlave, frame, grazingDate) -
+                                                    topo.getAzimuth(pMaster, frame, grazingDate)))
+        assert -6.0e-14 < testvalue - 180.0 < 6.0e-15
+
+        return EventHandler.Action.CONTINUE
+
+    # The full interface is required for java to accept it as a class of that type
+    def resetState(self, detector, oldState):
+        pass
+
+
+class InterSatDirectViewDetectorTest(unittest.TestCase):
+
+    def testFormationFlying(self):
+        earth = OneAxisEllipsoid(Constants.WGS84_EARTH_EQUATORIAL_RADIUS,
+                                 Constants.WGS84_EARTH_FLATTENING,
+                                 FramesFactory.getITRF(IERSConventions.IERS_2010, True))
+        utc = TimeScalesFactory.getUTC()
+        o1 = CircularOrbit(7200000.0, 1.0e-3, 2.0e-4,
+                           FastMath.toRadians(98.7), FastMath.toRadians(134.0),
+                           FastMath.toRadians(21.0), PositionAngle.MEAN, FramesFactory.getGCRF(),
+                           AbsoluteDate("2003-02-14T01:02:03.000", utc),
+                           Constants.EIGEN5C_EARTH_MU)
+
+        o2 = CircularOrbit(o1.getA(), 2.0e-4, 1.0e-3,
+                           o1.getI() + 1.0e-6, o1.getRightAscensionOfAscendingNode() - 3.5e-7,
+                           o1.getAlphaM() + 2.2e-6, PositionAngle.MEAN, o1.getFrame(),
+                           o1.getDate(),
+                           Constants.EIGEN5C_EARTH_MU)
+
+        self.assertAlmostEqual(o1.getKeplerianPeriod(), o2.getKeplerianPeriod(), delta=1.0e-10)
+        p = KeplerianPropagator(o1)
+        logger = EventsLogger()
+        p.addEventDetector(logger.monitorDetector(InterSatDirectViewDetector(earth, o2).
+                                                  withMaxCheck(60.0)))
+
+        class StepHandler(PythonOrekitFixedStepHandler):
+
+            def init(self, s0, t, step):
+                pass
+
+            def handleStep(self, state, isLast):
+                pos1 = state.getPVCoordinates().getPosition()
+                pos2 = o2.getPVCoordinates(state.getDate(), state.getFrame()).getPosition()
+
+                assert Vector3D.distance(pos1, pos2) > 8100.0
+                assert Vector3D.distance(pos1, pos2) < 16400.0
+
+        p.setMasterMode(10.0, StepHandler())
+        p.propagate(o1.getDate().shiftedBy(o1.getKeplerianPeriod()))
+        self.assertEqual(0, logger.getLoggedEvents().size())
+
+    def testLeoMeo(self):
+        earth = OneAxisEllipsoid(Constants.WGS84_EARTH_EQUATORIAL_RADIUS,
+                                 Constants.WGS84_EARTH_FLATTENING,
+                                 FramesFactory.getITRF(IERSConventions.IERS_2010, True))
+
+        utc = TimeScalesFactory.getUTC()
+        o1 = CircularOrbit(7200000.0, 1.0e-3, 2.0e-4,
+                           FastMath.toRadians(50.0), FastMath.toRadians(134.0),
+                           FastMath.toRadians(21.0), PositionAngle.MEAN, FramesFactory.getGCRF(),
+                           AbsoluteDate("2003-02-14T01:02:03.000", utc),
+                           Constants.EIGEN5C_EARTH_MU)
+
+        o2 = CircularOrbit(29600000.0, 2.0e-4, 1.0e-3,
+                           FastMath.toRadians(56.0), FastMath.toRadians(111.0),
+                           o1.getAlphaM() + 2.2e-6, PositionAngle.MEAN, o1.getFrame(),
+                           o1.getDate(),
+                           Constants.EIGEN5C_EARTH_MU);
+
+        # LEO as master, MEO as slave
+        pA = KeplerianPropagator(o1)
+        loggerA = EventsLogger()
+        pA.addEventDetector(loggerA.monitorDetector(InterSatDirectViewDetector(earth, o2).
+                                                    withMaxCheck(10.0).
+                                                    withHandler(GrazingHandler().of_(InterSatDirectViewDetector))))
+
+        propdate = o1.getDate().shiftedBy(4 * o1.getKeplerianPeriod())
+        pA.propagate(propdate)
+
+        self.assertEqual(7, loggerA.getLoggedEvents().size())
+
+        # LEO as slave, MEO as master
+        pB = KeplerianPropagator(o2)
+        loggerB = EventsLogger()
+        pB.addEventDetector(loggerB.monitorDetector(InterSatDirectViewDetector(earth, o1).
+                                                    withMaxCheck(10.0).
+                                                    withHandler(GrazingHandler().of_(InterSatDirectViewDetector))))
+
+        pB.propagate(o1.getDate().shiftedBy(4 * o1.getKeplerianPeriod()))
+        self.assertEqual(7, loggerB.getLoggedEvents().size())
+
+
+if __name__ == '__main__':
+    suite = unittest.TestLoader().loadTestsFromTestCase(InterSatDirectViewDetectorTest)
+    ret = not unittest.TextTestRunner(verbosity=2).run(suite).wasSuccessful()
+    sys.exit(ret)
diff --git a/python_files/test/IodGibbsTest.py b/python_files/test/IodGibbsTest.py
deleted file mode 100644
index ba418ce..0000000
--- a/python_files/test/IodGibbsTest.py
+++ /dev/null
@@ -1,144 +0,0 @@
-# -*- coding: utf-8 -*-
-
-"""
-
-/**
- *
- * Source: http://ccar.colorado.edu/asen5050/projects/projects_2012/kemble/gibbs_derivation.htm
- *
- * @author Joris Olympio
- * @since 7.1
- *
- */
-
-Java version translated to Python by Petrus Hyvönen, SSC 2017
-
- """
-
-import orekit
-
-orekit.initVM()
-from orekit.pyhelpers import setup_orekit_curdir
-
-import java.util.List;
-
-import org.hipparchus.geometry.euclidean.threed.Vector3D;
-import org.junit.Assert;
-import org.junit.Test;
-import org.orekit.errors.OrekitException;
-import org.orekit.estimation.Context;
-import org.orekit.estimation.EstimationTestUtils;
-import org.orekit.estimation.measurements.ObservedMeasurement;
-import org.orekit.estimation.measurements.PV;
-import org.orekit.estimation.measurements.PVMeasurementCreator;
-import org.orekit.frames.Frame;
-import org.orekit.frames.FramesFactory;
-import org.orekit.orbits.KeplerianOrbit;
-import org.orekit.orbits.OrbitType;
-import org.orekit.orbits.PositionAngle;
-import org.orekit.propagation.Propagator;
-import org.orekit.propagation.conversion.NumericalPropagatorBuilder;
-import org.orekit.time.AbsoluteDate;
-import org.orekit.time.TimeScalesFactory;
-
-
-
-from org.orekit.orbits import PositionAngle
-from org.orekit.propagation.conversion import FiniteDifferencePropagatorConverter
-from org.orekit.propagation.conversion import TLEPropagatorBuilder
-from org.orekit.propagation.analytical.tle import TLE
-from org.orekit.propagation.analytical.tle import TLEPropagator
-from org.orekit.data import DataProvidersManager, ZipJarCrawler
-from java.util import Arrays
-from java.io import File
-
-import unittest
-import sys
-
-class IodGibbsTest(unittest.TestCase):
-    def testGibbs1(self):
-        context = EstimationTestUtils.eccentricContext("regular-data:potential:tides");
-    final
-    double
-    mu = context.initialOrbit.getMu();
-    final
-    Frame
-    frame = context.initialOrbit.getFrame();
-
-    final
-    NumericalPropagatorBuilder
-    propagatorBuilder = \
-        context.createBuilder(OrbitType.KEPLERIAN, PositionAngle.TRUE, true,
-                              1.0e-6, 60.0, 0.001);
-
-    // create
-    perfect
-    range
-    measurements
-    final
-    Propagator
-    propagator = EstimationTestUtils.createPropagator(context.initialOrbit,
-                                                      propagatorBuilder);
-
-    final
-    List < ObservedMeasurement <? >> measurements =
-    EstimationTestUtils.createMeasurements(propagator,
-                                           new
-    PVMeasurementCreator(),
-    0.0, 1.0, 60.0);
-
-    final
-    Vector3D
-    position1 = new
-    Vector3D(measurements.get(0).getObservedValue()[0],
-             measurements.get(0).getObservedValue()[1],
-             measurements.get(0).getObservedValue()[2]);
-    final
-    PV
-    pv1 = new
-    PV(measurements.get(0).getDate(), position1, Vector3D.ZERO, 0., 0., 1.);
-
-    final
-    Vector3D
-    position2 = new
-    Vector3D(measurements.get(1).getObservedValue()[0],
-             measurements.get(1).getObservedValue()[1],
-             measurements.get(1).getObservedValue()[2]);
-    final
-    PV
-    pv2 = new
-    PV(measurements.get(1).getDate(), position2, Vector3D.ZERO, 0., 0., 1.);
-
-    final
-    Vector3D
-    position3 = new
-    Vector3D(measurements.get(2).getObservedValue()[0],
-             measurements.get(2).getObservedValue()[1],
-             measurements.get(2).getObservedValue()[2]);
-    final
-    PV
-    pv3 = new
-    PV(measurements.get(2).getDate(), position3, Vector3D.ZERO, 0., 0., 1.);
-
-    // instantiate
-    the
-    IOD
-    method
-    final
-    IodGibbs
-    gibbs = new
-    IodGibbs(mu);
-    final
-    KeplerianOrbit
-    orbit = gibbs.estimate(frame, pv1, pv2, pv3);
-
-    Assert.assertEquals(context.initialOrbit.getA(), orbit.getA(), 1.0e-9 * context.initialOrbit.getA());
-    Assert.assertEquals(context.initialOrbit.getE(), orbit.getE(), 1.0e-9 * context.initialOrbit.getE());
-    Assert.assertEquals(context.initialOrbit.getI(), orbit.getI(), 1.0e-9 * context.initialOrbit.getI());
-    }
-
-
-if __name__ == '__main__':
-    suite = unittest.TestLoader().loadTestsFromTestCase(IodGibbsTest)
-    ret = not unittest.TextTestRunner(verbosity=2).run(suite).wasSuccessful()
-    sys.exit(ret)
diff --git a/python_files/test/NodeDetectorTest.py b/python_files/test/NodeDetectorTest.py
index 043ae29..e9fb561 100644
--- a/python_files/test/NodeDetectorTest.py
+++ b/python_files/test/NodeDetectorTest.py
@@ -25,13 +25,15 @@ Python version translated from Java by Petrus Hyvönen, SSC 2014
 
 # Python orekit specifics
 import orekit
+
 orekit.initVM()
 
 import sys
 import unittest
 
 from orekit.pyhelpers import setup_orekit_curdir
-setup_orekit_curdir()   # orekit-data.zip shall be in current dir
+
+setup_orekit_curdir()  # orekit-data.zip shall be in current dir
 
 from org.orekit.propagation.events import EventsLogger
 from org.orekit.propagation.events import NodeDetector
@@ -61,24 +63,25 @@ class NodeDetectorTest(unittest.TestCase):
 
         inertialFrame = FramesFactory.getEME2000()
         initialDate = AbsoluteDate(2014, 1, 1, 0, 0, 0.0, TimeScalesFactory.getUTC())
-        finalDate = initialDate.shiftedBy(70*24*60*60.0)
-        initialOrbit = KeplerianOrbit(a, e, i, w, raan, v, PositionAngle.TRUE, inertialFrame, initialDate, Constants.WGS84_EARTH_MU)
+        finalDate = initialDate.shiftedBy(70 * 24 * 60 * 60.0)
+        initialOrbit = KeplerianOrbit(a, e, i, w, raan, v, PositionAngle.TRUE, inertialFrame, initialDate,
+                                      Constants.WGS84_EARTH_MU)
         initialState = SpacecraftState(initialOrbit, 1000.0)
 
         tol = NumericalPropagator.tolerances(10.0, initialOrbit, initialOrbit.getType())
 
         # Double array of doubles needs to be retyped to work
         integrator = DormandPrince853Integrator(0.001, 1000.0,
-            JArray_double.cast_(tol[0]),
-            JArray_double.cast_(tol[1]))
+                                                JArray_double.cast_(tol[0]),
+                                                JArray_double.cast_(tol[1]))
 
         propagator = NumericalPropagator(integrator)
         propagator.setInitialState(initialState)
 
         # Define 2 instances of NodeDetector:
         rawDetector = NodeDetector(1e-6,
-                initialState.getOrbit(),
-                initialState.getFrame()).withHandler(ContinueOnEvent().of_(NodeDetector))
+                                   initialState.getOrbit(),
+                                   initialState.getFrame()).withHandler(ContinueOnEvent().of_(NodeDetector))
 
         logger1 = EventsLogger()
         node1 = logger1.monitorDetector(rawDetector)
@@ -92,8 +95,8 @@ class NodeDetectorTest(unittest.TestCase):
         propagator.setEphemerisMode()
         propagator.propagate(finalDate)
 
-        assert 1998==logger1.getLoggedEvents().size()
-        assert 1998== logger2.getLoggedEvents().size();
+        assert 1998 == logger1.getLoggedEvents().size()
+        assert 1998 == logger2.getLoggedEvents().size();
         logger1.clearLoggedEvents()
         logger2.clearLoggedEvents()
 
@@ -103,8 +106,8 @@ class NodeDetectorTest(unittest.TestCase):
         postpro.addEventDetector(node1)
         postpro.addEventDetector(node2)
         postpro.propagate(finalDate)
-        assert 1998==logger1.getLoggedEvents().size()
-        assert 1998==logger2.getLoggedEvents().size()
+        assert 1998 == logger1.getLoggedEvents().size()
+        assert 1998 == logger2.getLoggedEvents().size()
 
         print("NodeDetectorTest Successfully run")
 
diff --git a/python_files/test/OrekitStepHandlerTest.py b/python_files/test/OrekitStepHandlerTest.py
index be8f20d..a9ffeb1 100644
--- a/python_files/test/OrekitStepHandlerTest.py
+++ b/python_files/test/OrekitStepHandlerTest.py
@@ -24,33 +24,27 @@ Python version translated from Java by Petrus Hyvönen, SSC 2019
 import sys
 import unittest
 from collections import deque
+import threading
+import time
 
 import orekit
-orekit.initVM()
 
-#package org.orekit.propagation.sampling
+jcc = orekit.initVM()
 
-#import static org.junit.Assert.assertEquals
-#import static org.junit.Assert.assertNotNull
-#import static org.junit.Assert.assertTrue
+# package org.orekit.propagation.sampling
+
+# import static org.junit.Assert.assertEquals
+# import static org.junit.Assert.assertNotNull
+# import static org.junit.Assert.assertTrue
 
 from org.orekit.data import DataProvidersManager, ZipJarCrawler
 from java.io import File
 
-#from java.util import ArrayDeque
 from java.util import Arrays
 from java.util import Queue
-#from java.util.concurrent.Callable
-#from java.util.concurrent.ExecutionException
-#from java.util.concurrent.ExecutorService
-#from java.util.concurrent import Executors
-#from java.util.concurrent.Future
 
 from org.hipparchus.ode.nonstiff import ClassicalRungeKuttaIntegrator
 from org.hipparchus.util import FastMath
-#from org.junit.Before
-#from org.junit.Test
-#from org.orekit import Utils
 from org.orekit.bodies import CelestialBodyFactory
 from org.orekit.frames import FactoryManagedFrame
 from org.orekit.frames import Frame
@@ -68,75 +62,68 @@ from org.orekit.time import AbsoluteDate
 from org.orekit.time import TimeScalesFactory
 from org.orekit.utils import Constants
 from org.orekit.python import PythonOrekitStepHandler
+from org.orekit.python import PythonOrekitFixedStepHandler
+
 
 class OrekitStepHandlerTest(unittest.TestCase):
-    #
-    #     def testForwardBackwardStep():
-    #         initialDate = AbsoluteDate(2014, 01, 01, 00, 00,
-    #                                                           00.000,
-    #                                                           TimeScalesFactory.getUTC())
-    #
-    #         mu = CelestialBodyFactory.getEarth().getGM()
-    #         inertialFrame = FramesFactory.getEME2000()
-    #
-    #         propagationTime = 7200.0 # seconds
-    #         fixedStepSize = 3600 # seconds
-    #
-    #         semimajorAxis = 8000e3 # meters
-    #         eccentricity = 0.001 # unitless
-    #         inclination = FastMath.toRadians(15.0)
-    #         argPerigee = FastMath.toRadians(10.0)
-    #         raan = FastMath.toRadians(45.0)
-    #         trueAnomaly = FastMath.toRadians(10.0)
-    #
-    #         initialOrbit = KeplerianOrbit(semimajorAxis,
-    #                                                          eccentricity,
-    #                                                          inclination,
-    #                                                          argPerigee, raan,
-    #                                                          trueAnomaly,
-    #                                                          PositionAngle.TRUE,
-    #                                                          inertialFrame,
-    #                                                          initialDate, mu)
-    #
-    #         kepler = KeplerianPropagator(initialOrbit)
-    #
-    #         class MyHandler(PythonOrekitStepHandler):
-    #             def init(self):  # All native defined calls needs to be implemented
-    #                 pass
-    #
-    #             def handleStep(self, currentState, isLast):
-    #                 pass
-    #
-    #         kepler.setMasterMode(fixedStepSize, MyHandler())
-    #
-    #         kepler.propagate(initialDate.shiftedBy(propagationTime))
-    #
-    #         stepSizeInSeconds = 120
-    #         longestWaitTimeMS = 20
-    #         service = Executors.ingleThreadExecutor()
-    #         for (elapsedTime = 0 elapsedTime <= propagationTime elapsedTime += stepSizeInSeconds) {
-    #             final double dt = elapsedTime
-    #             Future<SpacecraftState> stateFuture = service
-    #                 .submit(Callable<SpacecraftState>() {
-    #
-    #                     public SpacecraftState call()
-    #                         {
-    #                         return kepler.propagate(initialDate.shiftedBy(dt))
-    #                     }
-    #                 })
-    #
-    #             Thread.sleep(longestWaitTimeMS)
-    #             assertTrue(stateFuture.isDone())
-    #             SpacecraftState finalState = stateFuture.get()
-    #             assertNotNull(finalState)
-    #         }
-    #     }
-
-    #     /**
-    #      * Check {@link OrekitStepInterpolator#isPreviousStateInterpolated()} and {@link
-    #      * OrekitStepInterpolator#isCurrentStateInterpolated()}.
-    #      */
 
+    def testForwardBackwardStep(self):
+        initialDate = AbsoluteDate(2014, 1, 1, 00, 00,
+                                   00.000,
+                                   TimeScalesFactory.getUTC())
+
+        mu = CelestialBodyFactory.getEarth().getGM()
+        inertialFrame = FramesFactory.getEME2000()
+
+        propagationTime = 7200.0  # seconds
+        fixedStepSize = 3600.0  # seconds
+
+        semimajorAxis = 8000e3  # meters
+        eccentricity = 0.001  # unitless
+        inclination = FastMath.toRadians(15.0)
+        argPerigee = FastMath.toRadians(10.0)
+        raan = FastMath.toRadians(45.0)
+        trueAnomaly = FastMath.toRadians(10.0)
+
+        initialOrbit = KeplerianOrbit(semimajorAxis,
+                                      eccentricity,
+                                      inclination,
+                                      argPerigee, raan,
+                                      trueAnomaly,
+                                      PositionAngle.TRUE,
+                                      inertialFrame,
+                                      initialDate, mu)
+
+        kepler = KeplerianPropagator(initialOrbit)
+
+        class MyFixedHandler(PythonOrekitFixedStepHandler):
+            def init(self, s0, t, step):  # All native defined calls needs to be implemented
+                pass
+
+            def handleStep(self, currentState, isLast):
+                pass
+
+        kepler.setMasterMode(fixedStepSize, MyFixedHandler())
+        kepler.propagate(initialDate.shiftedBy(propagationTime))
+
+        stepSizeInSeconds = 120
+        longestWaitTimeMS = 20
+
+        from multiprocessing.pool import ThreadPool
+        pool = ThreadPool(processes=1)
+
+        def propagate_piece(to):
+            jcc.attachCurrentThread()
+            return kepler.propagate(initialDate.shiftedBy(to))
+
+        elapsedTime = 0.0
+        while elapsedTime <= propagationTime:
+            dt = elapsedTime
+            result = pool.apply_async(propagate_piece, (dt,))
+            finalstate = result.get(longestWaitTimeMS)
+            self.assertTrue(result.ready())
+            self.assertTrue(finalstate)
+            elapsedTime += stepSizeInSeconds
 
     def testIsInterpolated(self):
         # setup
@@ -144,7 +131,7 @@ class OrekitStepHandlerTest(unittest.TestCase):
         date = AbsoluteDate.J2000_EPOCH
         eci = FramesFactory.getGCRF()
         ic = SpacecraftState(KeplerianOrbit(6378137 + 500e3, 1e-3, 0.0, 0.0, 0.0, 0.0,
-                 PositionAngle.TRUE, eci, date, Constants.EIGEN5C_EARTH_MU))
+                                            PositionAngle.TRUE, eci, date, Constants.EIGEN5C_EARTH_MU))
         propagator.setInitialState(ic)
         propagator.setOrbitType(OrbitType.CARTESIAN)
         # detector triggers half way through second step
@@ -159,8 +146,8 @@ class OrekitStepHandlerTest(unittest.TestCase):
                 pass
 
             def handleStep(self, interpolator, isLast):
-                assert(expected.popleft() == interpolator.isPreviousStateInterpolated())
-                assert(expected.popleft() == interpolator.isCurrentStateInterpolated())
+                assert (expected.popleft() == interpolator.isPreviousStateInterpolated())
+                assert (expected.popleft() == interpolator.isCurrentStateInterpolated())
 
         propagator.setMasterMode(MyHandler())
         end = date.shiftedBy(120.0)
-- 
GitLab