How to handle multiple thrust events happening at the same time?

Hello everyone,

At the moment, I’m having some trouble with the planning of my orbit propagation.
My current approach is as follows:

  1. I define my satellite (mass, surface area, thruster, etc.)

  2. I build my propagator and force model

  3. I add different thrust events (these can be date based, or event triggered) using ConstantThrustManeuver.

  4. I propagate my orbit and retrieve the intermediate states with a handler.

My issue is the following: What happens when two events occur at the same time?
I assume that both thrusts are applied simultaneously and therefore add up. For example, if I have a 1N thrust in the Velocity direction and another 1N thrust in the Normal direction, I would end up with a total thrust of √2 N at a 45° angle between the two directions.
The problem is that this final thrust magnitude would exceed the 1N limit defined for my thruster.

Is it possible to handle only the thrust directions beforehand and control the thrust magnitude during propagation? Or perhaps to limit the thrust magnitude?
Is there a feature I might have missed that could help?

Thanks for your help and your insights.

P.S. I am using the jpype Python wrapper, and I can provide some code snippets if necessary.

Hi there,

I’m a bit confused, but maybe I missunderstood. If you’re using ConstantThrustManeuver, then your trigger can only be date-based. Why would you then add several instances with overlapping time intervals? Coz yeah with these settings the two thrust vectors would indeed add up.

Cheers,
Romain.

Hi Romain,

You are right, I didn’t explain myself very well, I’m sorry.

I am currently using ConstantThrustManeuver only because I’m still working on the non date-based triggers. But for those triggers, I’ll use the generic Maneuver class.

Here is a snippet of my code showing that.

        for thrust_event in self.mission.thrust_sequence:

            if thrust_event["type"] == "date":

                # Get start date and duration

                startDate_obj = datetime.fromisoformat(thrust_event["triggerStart"])

                startDate = AbsoluteDate(startDate_obj.year, startDate_obj.month, startDate_obj.day, startDate_obj.hour, startDate_obj.minute, 0.0, TimeScalesFactory.getUTC())

                event_duration = int(thrust_event["triggerEnd"])

                # Get the direction

                V = thrust_event["v"]

                N = thrust_event["n"]

                B = thrust_event["b"]

                # Define thrust direction provider (thrust along velocity axis to increase sma)

                # LOFType.VNC : X axis aligned with velocity, Y is normal, Z is Co-normal (or bi-normal)

                direction = Vector3D(V, N, B)

                

                # Create the propulsion model

                propulsion_model = BasicConstantThrustPropulsionModel(self.spacecraft.thrust, self.spacecraft.isp, direction, "Propulsion_Model")

                

                # Create the triggers

                maneuver_triggers = DateBasedManeuverTriggers(startDate, event_duration)

                # Create the maneuver

                maneuver = ConstantThrustManeuver(attitude_provider, maneuver_triggers, propulsion_model)

                

                # Add the maneuver to the force model

                self.propagator.addForceModel(maneuver)

                maneuvers_list.append(maneuver)

                print(f"Thrust event added : Starting at {startDate}, thrust along [{V},{N},{B}] vector (VNB) at {self.spacecraft.thrust}N, for {event_duration} seconds")

            elif thrust_event["type"] == "threshold":

                # Get the thresholds

                if thrust_event["isTriggerStartDate"]:

                    print("Date start trigger not yet implemented")

                    continue

                else:

                    # Get the thresholds

                    triggerStart = float(thrust_event["triggerStart"]) * 1000.0 # convert to meters

                

                if thrust_event["isTriggerEndDuration"]:

                    triggerStop = float(thrust_event["triggerEnd"])     # duration in seconds

                    print("Duration end trigger not yet implemented")

                    continue

                else:

                    triggerStop = float(thrust_event["triggerEnd"]) * 1000.0 # convert to meters

                

                # Get the direction

                V = thrust_event["v"]

                N = thrust_event["n"]

                B = thrust_event["b"]

                # Define thrust direction provider

                # LOFType.VNC : X axis aligned with velocity, Y is normal, Z is Co-normal (or bi-normal)

                direction = Vector3D(V, N, B)

                # Create the propulsion model

                propulsion_model = BasicConstantThrustPropulsionModel(self.spacecraft.thrust, self.spacecraft.isp, direction, "Propulsion_Model")

                # Get the triggers

                if thrust_event["parameter"] == "semimajor_axis":

                    maneuver_triggers = getSMAThresholdTrigger(triggerStart, triggerStop, socketio)

                else:

                    print("Thrust event parameter not yet handled: ", thrust_event["parameter"])

                    continue

                # Create the maneuver

                maneuver = Maneuver(attitude_provider, maneuver_triggers, propulsion_model)

                # Add the maneuver to the force model

                self.propagator.addForceModel(maneuver)

                maneuvers_list.append(maneuver)

For all the date-based event, I have a verification function to ensure that there are no overlapping events. But for non date-based event, I can’t know before the propagation if two events will be triggered at the same time. So I don’t know how I can handle these cases.

Hi,

gotcha.
You seem to be using StartStopEventTrigger. So if you’re able to define a priority order among your maneuvers, then you could change your starting event by putting it into an EventPredicateFilter. The predicate would be !isFiring([...]) of the maneuver types that have priority over it. Or any other way you find to formulate it. Basically the non-priority ones would then not activate if the other already are. Does that make sense?

Another comment. If you have many date-based maneuvers and do not use their parameters in the State Transition Matrix, you might want to consider TimeIntervalsManeuverTrigger for computational performance.

Cheers,
Romain.

Hi,

So instead of merging the events, I just need to block the others if one is already ongoing.

Thank you for this workaround.

And thanks for the advice about TimeIntervalsManeuverTrigger, I’ll look at it :slight_smile:

Appreciate your help.

Have a good day.

Charles