[Python] Error using ImpulseManeuver with PositionAngleDetector

Hi everyone,

First of all, I’m working with orekit through Python.

My objective: from an initial circular low-earth orbit, implement an impulse maneuver at a certain argument of latitude on the orbit, and then propagate this orbit for 1 hour, let’s say.

To do so, I have created an initial CircularOrbit and a DSSTPropagator first, and then an ImpulseManeuver using a PositionAngleDetector, with the argument of latitude wanted for the maneuver, as trigger. And finally I have added this maneuver to the propagator.

See code below:

orekit.initVM()
setup_orekit_curdir()

# create initial orbit
initialDate = AbsoluteDate(2020, 1, 1, 00, 00, 00.000, TimeScalesFactory.getUTC())
initialSemiMajorAxis = 600e3 + Constants.WGS84_EARTH_EQUATORIAL_RADIUS
initialEccentricityX = 0.0
initialEccentricityY = 0.001
initialInclination = math.radians(98.0)
initialRaan = math.radians(0.0)
initialAol = math.radians(0.0)
mass = 100.0
initialOrbit = CircularOrbit(initialSemiMajorAxis, initialEccentricityX,
                             initialEccentricityY, initialInclination,
                             initialRaan, initialAol,
                             PositionAngle.TRUE,
                             FramesFactory.getEME2000(),
                             initialDate,
                             Constants.WGS84_EARTH_MU)

# create propagator
builder = DSSTPropagatorBuilder(initialOrbit,
                                DormandPrince853IntegratorBuilder(600.0, 86400.0, 100.0),
                                1.0, PropagationType.MEAN, PropagationType.MEAN)
builder.setMass(mass)
propagator = builder.buildPropagator(builder.getSelectedNormalizedParameters())

# create maneuver's trigger
angle = math.radians(100.0)
trigger = PositionAngleDetector(OrbitType.CIRCULAR, PositionAngle.TRUE, angle)

# create maneuver
attitudeOverride = LofOffset(FramesFactory.getEME2000(), LOFType.TNW)
deltaVSat = Vector3D.PLUS_I
isp = 1500.0
maneuver = ImpulseManeuver(trigger, attitudeOverride, deltaVSat, isp)

# add maneuver to propagator
propagator.addEventDetector(maneuver)

# propagation
finalState = propagator.propagate(initialDate.shiftedBy(3600.0))

But, when I run this script I get the following error:

Traceback: finalState = propagator.propagate(initialDate.shiftedBy(3600.0))

JavaError: <super: <class 'JavaError'>, <JavaError object>>
Java stacktrace:
java.lang.NullPointerException
	at org.orekit.propagation.events.PositionAngleDetector.g(PositionAngleDetector.java:203)
	at org.orekit.forces.maneuvers.ImpulseManeuver.g(ImpulseManeuver.java:151)
	at org.orekit.propagation.integration.AbstractIntegratedPropagator$AdaptedEventDetector.g(AbstractIntegratedPropagator.java:784)
	at org.hipparchus.ode.events.EventState.reinitializeBegin(EventState.java:173)
	at org.hipparchus.ode.AbstractIntegrator.acceptStep(AbstractIntegrator.java:299)
	at org.hipparchus.ode.nonstiff.EmbeddedRungeKuttaIntegrator.integrate(EmbeddedRungeKuttaIntegrator.java:290)
	at org.orekit.propagation.integration.AbstractIntegratedPropagator.propagate(AbstractIntegratedPropagator.java:468)
	at org.orekit.propagation.integration.AbstractIntegratedPropagator.propagate(AbstractIntegratedPropagator.java:414)
	at org.orekit.propagation.integration.AbstractIntegratedPropagator.propagate(AbstractIntegratedPropagator.java:397)

Surprisingly, no error is raised when implemeting an ImpulseManeuver using another EventDetector such as DataDetector or NodeDetector

Could someone help me understand why an ImpulseManeuver triggered by a PositionAngleDetector doesn’t work on my case so I can fix it please?

Thank you very much for your help!

Kind regards,
Melvin

Hi @melvina

Welcome to the Orekit forum!

The problem is that the PositionAngleDetector is not initialized. Therefore, the offsetEstimators parameter of the PositionAngleDetector is not initialized too. That’s why you have a NullPointerException.

I wonder if the init() method of the ImpulseManeuverDetector should call the init() method of the trigger parameter to make sure it is initialized. Something like:

/** {@inheritDoc} */
public void init(final SpacecraftState s0, final AbsoluteDate t) {
    trigger.init(s0, t);
    forward = t.durationFrom(s0.getDate()) >= 0;
}

I’ve tried and it solves your problem.
@MaximeJ what do you think about this idea ?

Kind regards,
Bryan

Hi both,

It does look like a bug to me… and you found the fix!

I’m also wondering why we’re not calling super.init(s0, t) in ImpulseManeuver#init instead of repeating the line
forward = t.durationFrom(s0.getDate()) >= 0;

Seems like it’s “bug day” today :wink:

Cheers

Hi again,

Thank you both for the quick answer! :slight_smile:

So now I am wondering, is there a way to fix this without adding new lines in Orekit’s code?
Because, since I am only coding in Python, I don’t know if I can fix the problem or if I will have to find another way

Best,
Melvin

@melvina What you can do first is to call trigger.init(SpacecraftState s0, AbsoluteDate t) just after you created the PositionAngleDetector. This will solve the issue directly on your example.

  • s0 can be obtained from propagator.getInitialState());
  • t is the target time (i.e. initialDate.shiftedBy(3600.0) in your example)

However, the “cleanest” way to solve this issue is to correct the init() method of ImpulseManeuver class as suggested above. Could you please open an issue on the Gitlab forge ?

@MaximeJ Thank you for your reply. I agree with your remark, I don’t understand why this line is repeated in ImpulseManeuver. Maybe this has to be fixed too.

Bryan

@MaximeJ I think that is because the isForward() method of AbstractDetector class has been added after the creation of the class ImpulseManeuver. ImpulseManeuver’s init() method has not been updated after the addition of the new method.

Bryan

@bcazabonne Ok I will do this (temporarily), thank you :slight_smile:

By the way, the issue has been created: PositionAngleDetector not initialized when using in ImpulseManeuver

Best,
Melvin

Thank you!

If you want and have time you can also contribute the fix in Orekit, following guidelines from the contributing guide :wink:

Kind regards,
Bryan