Profile-based maneuvers

I would like to implement a simple profile-based maneuver.
The idea would be to set up a TimeSpanMap with several segments, each one representing a smooth thrust. A typical example would be a ramp up, then a constant thrust, then a ramp down.
How do you think we should handle the angular point when going from ramp up to constant? It is not a firing event, but should probably be notified to propagator with a RESET_DERIVATIVE event.

I was considering either adding a getEventsDetectors to the PropulsionModel interface, that would only be used to insert the RESET_DERIVATIVE events in my profile use case, with a big warning in the documentation to tell this is not intended for replacing the triggers, but is rather intended to manage thrust changes. Another possibility would be to reuse the event detectors from ManeuverTriggers, but we have to make a distinction between events that are start/stop and events that are just regime change. It seems also not straightforward to generalize the already complex management of the isFiring method in EventBasedManeuverTriggers by adding custom detectors.

What do you think?

Hi @luc,

Looks like a very good idea! Orekit is clearly lacking that type of model.

Do you intend to use it only for maneuvers based on dates triggers or also for maneuvers based on “any” event? Said otherwise can you build the TimeSpanMap at construction of the maneuver object or do you intend to build it on the fly once the start and stop events are known?
The time transitions are definitely gonna be hard to handle, even more since the date estimation capacity was added a year and a half back…

Why not implement a specific PropulsionModel that would embark a TimeSpan<PropulsionModel> and a set of events for transitions that would take care of the RESET_DERIVATIVE?
That way you don’t have to add events to the generic interface PropulsionModel or use the ones from the triggers.
Then write a ProfileBasedManeuver extending Maneuver and taking your propulsion model and date-based triggers. And finally, overwrite getEventDetectors by adding the propulsion models trigger so that the propagator is aware of them and can reset the derivatives accordingly.

I wonder if an object TimeTransitionMap wouldn’t be better for your use case though.
With transitions, the linear interpolation is straight-forward. With spans it can be a bit of a headache sometimes :slight_smile:

Since we’re talking about maneuvers I was wondering if it wouldn’t be better to add genericity to the Maneuver object (like <P implements PropulsionModel, T implements ManeuverTriggers>), rather than the actual version that sometimes requires object casting (see the getters of ConstantThrustManeuver for example).
What do you think? Would it get too verbose if we do that?

I set up a first implementation with predefined transition times. I think it will be difficult to select different ones with undefined dates. For sure we could set up some internal state the builds the map on the fly, but this is more difficult, so I refrained to do this immediately. We can improve later on. The current use case is for predefined dates.

The propulsion model is not visible to the propagator, only Maneuver is because it implements ForceModel. So I added the getEventDetectors with a default implementation that returns an empty stream, and Maneuver concatenates the streams from trigger and thrust model. It was really simple to do it this way and it seems consistent with the existing architecture.

In the use case that I attempted to solve, the models are already polynomials, so a Span is OK, we just use internal data for each segment (a reference date and polynomial coefficients).

It is a good idea.

ok, no problem here if this suits you.

Nice!