Logging detectors from ConfigurableLowThrustManeuver

Hello all, am I am new to Orekit and it’s my first time using this forum, so thank you for the support!

I am trying to propagate a low-thrust maneuver and to get a list of when the manoeuvre start/stop events occur. However, I am struggling with getting the detector loggers to work correctly.

My propblem is the following: I have created start/stop detectors for thrusting during sunlight and within a specified thrusting range. I have added these detectors to the configurableLowThrustManeuver, and I have also created loggers for these detectors and added them to the propagation. However, when I get the logged events after propagating, the results seem off. I have tried logging the detectors in a propagation without the configurableLowThrustManeuver and they seem to work properly (I have validated the Epochs against a GMAT propagation).

Here are the eclipse events when propagated without any maneuver:

Engine start events                    Engine stop events
'2023-06-05T00:05:00',            '2023-06-05T00:48:40.634351'
'2023-06-05T01:23:19.062900',     '2023-06-05T02:22:53.964727'
'2023-06-05T02:57:32.325628',     '2023-06-05T03:57:07.315703'
'2023-06-05T04:31:45.605503',     '2023-06-05T05:31:20.692967'
'2023-06-05T06:05:58.905969',     '2023-06-05T07:05:34.096441'
'2023-06-05T07:40:12.227887',     '2023-06-05T08:39:47.519825'
'2023-06-05T09:14:25.571138',     '2023-06-05T10:14:00.951855'
'2023-06-05T10:48:38.931774',     '2023-06-05T11:48:14.380554'

And here are the events when I propagate with a configurableLowThrustManeuver

Engine start events,                   Engine stop events
'2023-06-05T00:05:00',            '2023-06-05T00:48:40.767388'
'2023-06-05T01:23:19.148172',     '2023-06-05T02:22:54.758058'
'2023-06-05T02:57:32.995634',     '2023-06-05T03:57:09.272901'
'2023-06-05T03:57:09.272901',     '2023-06-05T04:31:47.363816'
'2023-06-05T04:31:47.363816',     '2023-06-05T05:31:24.317741'
'2023-06-05T04:31:47.363816',     '2023-06-05T06:06:02.256293'
'2023-06-05T06:06:02.256293',     '2023-06-05T07:05:39.892636'
'2023-06-05T06:06:02.256293',     '2023-06-05T08:39:55.991434'
'2023-06-05T07:05:39.892636',     '2023-06-05T10:14:12.603024'
'2023-06-05T07:40:17.674071',     '2023-06-05T11:48:29.715588'

Starting from the fourth row, the dates get repeated.

Here is a simplification of my Python code with the relevant parts:

from orekit.pyhelpers import datetime_to_absolutedate, absolutedate_to_datetime
from org.orekit.forces.maneuvers import ConfigurableLowThrustManeuver
from org.orekit.propagation.numerical import NumericalPropagator
import datetime as dt

def genEclipseDetectorsInRange(enterRangeEpoch, exitRangeEpoch):
    from org.orekit.propagation.events import EclipseDetector, NegateDetector, ParameterDrivenDateIntervalDetector, BooleanDetector, handlers
    from org.orekit.utils import Constants

    # Detect sunlight (positive in sunlight and umbra, negative in eclipse)
    sunlightDetector = EclipseDetector(self.sun, Constants.SUN_RADIUS,
                                    self.earth).withUmbra()
    
    # Detect if in thrust range (positive between the two epochs, negative elsewhere)
    inEpochRangeDetector = ParameterDrivenDateIntervalDetector(
        '', datetime_to_absolutedate(enterRangeEpoch), datetime_to_absolutedate(exitRangeEpoch)) # Use a dummy '' prefix.
    
    # Combine both detectors into a detector that is only positive when in sunlight AND in between burn epochs
    startDetector = BooleanDetector.andCombine([sunlightDetector, inEpochRangeDetector]).withHandler(handlers.ContinueOnEvent())

    # CUTOFF detector (if in eclipse OR out of thrust range)
    eclipseDetector = NegateDetector(sunlightDetector) # Positive in eclipse
    outEpochRangeDetector = NegateDetector(inEpochRangeDetector) # Positive outside of the epoch range.
    
    # Combine detectors into one that's positive in eclipse OR outside of the given
    stopDetector = BooleanDetector.orCombine([eclipseDetector, outEpochRangeDetector]).withHandler(handlers.ContinueOnEvent())
    
    return startDetector, stopDetector

# Create a propagator object (spared the details for simplicity)
myPropagator = NumericalPropagator(integrator)

# Propagation epochs
epoch0 = dt.datetime(2023,6,5,0,0,0)
epochF = dt.datetime(2023,6,5,12,0,0)

# Thrust range
enterRangeEpoch = dt.datetime(2023,6,5,0,5,0)
exitRangeEpoch = enterRangeEpoch + dt.timedelta(days=1)

# Generate the start/stop detectors
startDetector, stopDetector = genEclipseDetectorsInRange(enterRangeEpoch, exitRangeEpoch)

# Add low-thrust manoeuvre to propagator
LowThrustMan = configurableLowThrustManeuver(thrustDirProvider, startDetector, stopDetector, thrust, isp)
myPropagator.addForceModel(LowThrustMan)

# Log the start/stop detectors
startLogger = EventsLogger()
stopLogger = EventsLogger()

startLoggerDetector = startLogger.monitorDetector(startDetector)
stopLoggerDetector = stopLogger.monitorDetector(stopDetector)

myPropagator.addEventDetector(startLoggerDetector)
myPropagator.addEventDetector(stopLoggerDetector)

# Propagate
myPropagator.propagate(datetime_to_absolutedate(epochF))

# Retrieve the logged start/stop events
startEvents = []
for log in startLogger.getLoggedEvents():
    if log.isIncreasing():
        startEvents.append(absolutedate_to_datetime(log.getDate()))

stopEvents = []
for log in stopLogger.getLoggedEvents():
    if log.isIncreasing():
        stopEvents.append(absolutedate_to_datetime(log.getDate()))

I don’t think I am understanding correctly the functionality of the event detectors and the loggers when inside a low-thrust manoeuvre object. Is there any different way of obtaining this information?

I hope my problem is clear enough. Thank you!

Hi,

That is a straightforward way to do it, sometimes it is easier to use a single logger and then check what type of event you are handling in your for-loop, I think (but not sure it is a 100% assumption) that the logged events are in a time sequence, which helps in finding visibilities etc.

You can also make a custom EventsHandler for selecting and storing the events.

Greets

Hello @e.martin,

look at the getFirings() method.

See:
https://www.orekit.org/site-orekit-latest/apidocs/org/orekit/forces/maneuvers/trigger/AbstractManeuverTriggers.html#getFirings()