Impulse Maneuvers when initial state not at the start of propagation


#1

Hello,

I have a question about the management of ImpulseManeuvers when they occur outside propagation. This can happen when the impulse maneuver date is between the initial SpacecraftState date and the propagation starting date.
In this case, the propagator will first propagate from initial state to starting date, without taking the EventDetector into account, then comes the main propagation, from initial to final date, with all the EventDetector (in AbstractIntegratedPropagator.propagate(final AbsoluteDate tStart, final AbsoluteDate tEnd)).
Thus, as impulse maneuvers are basically EventDetector, they are skipped if they occur during the initial propagation and not the main propagation.
I would like to know if this design is deliberate and if there is a way to take impulse maneuvers (or other detectors) into account when occuring outside main propagation.
I send you a test case to illustrate my question. In this test two propagations are performed, with same initial state and impulse maneuver, only the propagation start date changes :


import org.hipparchus.geometry.euclidean.threed.Vector3D;
import org.hipparchus.ode.nonstiff.DormandPrince853Integrator;
import org.hipparchus.util.FastMath;
import org.junit.Test;
import org.orekit.attitudes.LofOffset;
import org.orekit.errors.OrekitException;
import org.orekit.forces.maneuvers.ImpulseManeuver;
import org.orekit.frames.FactoryManagedFrame;
import org.orekit.frames.FramesFactory;
import org.orekit.frames.LOFType;
import org.orekit.orbits.CircularOrbit;
import org.orekit.orbits.Orbit;
import org.orekit.orbits.PositionAngle;
import org.orekit.propagation.SpacecraftState;
import org.orekit.propagation.events.DateDetector;
import org.orekit.propagation.numerical.NumericalPropagator;
import org.orekit.time.AbsoluteDate;
import org.orekit.time.TimeScalesFactory;
import org.orekit.utils.Constants;


public class ImpulseManeuverTest {

    @Test
    public void testOrekitPropagator() throws OrekitException {
        FactoryManagedFrame referenceFrame = FramesFactory.getTOD(false);

        AbsoluteDate initialDate = new AbsoluteDate(2020, 1, 1, 0, 0, 0, TimeScalesFactory.getUTC());
        AbsoluteDate maneuverDate = new AbsoluteDate(2020, 1, 1, 0, 30, 0, TimeScalesFactory.getUTC());
        AbsoluteDate endDate = new AbsoluteDate(2020, 1, 1, 1, 0, 0, TimeScalesFactory.getUTC());

        Orbit orbit = new CircularOrbit(7000e3, 0, 0, 89 * FastMath.PI / 180., 0, 0, PositionAngle.TRUE, referenceFrame, initialDate, Constants.WGS84_EARTH_MU);
        ImpulseManeuver<DateDetector> maneuver = new ImpulseManeuver<DateDetector>(new DateDetector(maneuverDate), new LofOffset(referenceFrame, LOFType.QSW),
                                                                                   new Vector3D(100.0, 0., 0.), 1000);

        NumericalPropagator propagator1 = createPropagator(orbit, maneuver);
        NumericalPropagator propagator2 = createPropagator(orbit, maneuver);

        SpacecraftState state1 = propagator1.propagate(endDate, endDate);
        SpacecraftState state2 = propagator2.propagate(initialDate, endDate);

        System.out.println(state1.getPVCoordinates().getPosition().subtract(state2.getPVCoordinates().getPosition()));
    }

    private NumericalPropagator createPropagator(Orbit orbit, ImpulseManeuver<DateDetector> maneuver) throws OrekitException {
        NumericalPropagator propagator = new NumericalPropagator(new DormandPrince853Integrator(5e-3, 60, 1e-3, 1e-3));
        propagator.resetInitialState(new SpacecraftState(orbit));
        propagator.addEventDetector(maneuver);
        return propagator;
    }

}

One can verify that final states are not the same, as maneuver is not taken into account in first case.

Regards,
Valérian Piento


#2

Hello Valerian,

Yes the design is intended (See javadoc of class Propagator).
It allows a very fast propagation until main propagation start date, without the event detection that can be time consuming.

If you want to register events between initialDate and endDateMainPropagation then you could use:

propagator.propagate(initialDate, startDateMainPropagation);
propagator.propagate(startDateMainPropagation, endDateMainPropagation);

Or:

propagator.propagate(initialDate, endDateMainPropagation);

Or even:

propagator.propagate(endDateMainPropagation);

Does that answer your question ?


#3

Hello Maxime,

Thank you for your quick answer.
I understand the necessity for event detection to not be taken into account before main propagation. My question is more about the difference between impulse maneuvers and others event detectors.
Generally, event detectors do not have an effect on spacecraft trajectory whereas impulse maneuvers will modify it.

Let’s suppose I have an initial state at t0, and I want an ephemeris of nodes only between t1 and t2 (t0<t1<t2). I also have impulse maneuvers, at least one between t0 and t1. I add a NodeDetector and all the ImpulseManeuver to the propagator.
Then, if I use :

propagator.propagate(t1, t2);

some impulse maneuvers will not be taken into account, so the ephemeris will be wrong. If I use :

propagator.propagate(t0,t2);

the node ephemeris will be too long.

I suppose that one solution in this situation could be to propagate first from t0 to t1 with only ImpulseManeuver detectors, then to add other detectors and propagate a second time from t1 to t2.
The problem here is the special status of ImpulseManeuver, as they are maneuvers, influencing the trajectory as a ConstantThrustManeuver would do (not the same way though), but they are also detectors. Thus, the behavior of ImpulseManeuver and ConstantThrustManeuver is different outside main propagation : the ConstantThrustManeuver are taken into account between initial date and startDateMainPropagation but not ImpulseManeuver, which can be confusing.

On a related case, let’s suppose I want an orbit counter which count how many orbit my spacecraft has made. I can build it with a NodeDetector for example. In this case, I want this detector always active, I don’t want to miss a node or my counter will be false. Again, if initial date is different from start date, the node detector will not be activated before start date and I may miss the orbit change period.

In these both cases it appears that I could need two differents Detector types. One I want to be always active, and one only during main propagation. ImpulseManeuver would be in the first type.

What do you think about it?

Thank you,

Valérian


#4

Hi Valerian,

You raise an interesting question. Maybe some other users/developers could tell you their feelings about implementing the feature you suggest.

I understand the special status of the impulse maneuver among the detectors and it can sure get confusing, especially for a non-expert user.

However, as it is now, Orekit can easily work around the issue by:

  • As you suggest, doing a first propagation with only the impulse maneuver detector added to the propagator;
  • Another work-around could be to use the ConstantThrustManeuver with a very small duration and an appropriate thrust modulus

So I’m not convinced that it is a urgent feature to add to the library. Nevertheless, if you think it is a feature that can benefit to a lot of users I invite you to open an issue on the Giltab forge.

As for your other example with the orbit counter, once again, the only way is to propagate first with only the node detector added in the propagator, then do the “main” propagation with all the detectors added.

Cheers,
Maxime