Python - Low thrust manoeuvre with different attitude profiles

Dear Orekit community,

I am working with the Python wrapper of Orekit and trying to implement a low-thrust maneuver profile with a varying yaw angle for a LEO orbit. This means the thrust vector continuously swings between out-of-plane and in-plane (e.g., 90° yaw angle at the ascending node, 0° at the poles, and -90° at the descending node).

For analysis purposes, I need the yaw-angle evolution to be highly flexible, allowing both steep/instant changes and gradual/constant variations. Two example profiles are:

  • Profile A: 90° yaw angle between -45° and +45° argument of latitude; -90° yaw angle between 135° and 225° argument of latitude; 0° yaw angle for the rest of the orbit (i.e., at the poles).
  • Profile B: Yaw angle always equal to the cosine of the argument of latitude.

On top of this, I need these manoeuvres to be triggered exclusively between given time ranges, due to operational requirements.

I have attempted multiple implementations, including:

  • Using attitude sequences
  • Using different interval triggers for different orbital arcs, first with constant and then with discontinuous g functions
  • Using predicateEnablingTriggers

However, every approach seems to have some sort of issues, and I cannot determine whether these are due to bugs (possibly in the Python version of Orekit) or, most probably, to mistakes in my implementation.

The main issues I have observed are:

  • Unexpected attitude behaviour when switching quickly between attitude profiles, sometimes leading to unintended braking manoeuvres.
  • Severe performance slowdowns when multiple manoeuvres with different triggers are added.
  • Propagation failure when a manoeuvre starts exactly at the end of the previous one, as the integrator appears to get stuck in an infinite evaluation of the g function of the two event triggers.

Before sharing the code I used for these implementations, I would first like to ask for your advice on how you would approach this problem.

Thank you so much for your time and help,
Riccardo

1 Like

Hi there,

If your code has to regularly call a method defined in Python, for instance the g function of an event detector, this can indeed significantly drag performance down.
There are ways to create “your own wrapper” (over your Java classes) with the jpype technology, as described in some posts that you can find on the forum or gitlab.
Beyond that, having many detectors or force models (like hundreds) also slows down propagation even in pure Java.

How are you using the AttitudeSequence? What’s the transition time? It might explain the braking you’re talking about. I’ve added an alternative class (AttitudeSwitcher) to appear in Orekit 13.0 that has instantaneous jumps between attitude modes.

For the infinite loop, be aware that having an ApsideDetector when your orbit suddenly becomes circular can cause a deadlock. Maybe you’re creating a similar situation?

Cheers,
Romain.