TimeOffsettedPropagator?

Hi,

In some cases, operationally, it is found that the orbital elements estimated are not describing the orbit of a spacecraft accurately and a small time offset is applied until a better orbit element is available.

Is there already a convenience function in orekit for this? I think basically it would be to make a TimeOffsettedPropagator from an existing propagator and then .shiftedBy(X) for each time element?

This is maybe trivial to do on user side in java, but in python this would have a large performance penalty. Should I make a ticket and a PR for such feature in java? Any side effects that may be needed to consider?

Regards Petrus

I guess something could be done using AdapterPropagator as a model. It embeds another propagator and adds some differential effects. Here you would just want to shift the date.

Hi Luc,

Not sure I understand the adaptorPropagator in this context. I would have thought one need to shift the actual inputs to the propagator but not sure? When I look on the adaptorPropagator it seems it manages the states the propagator returns and applies some effects on those states. It is a bit late tonight but I cannot think that is the same thing as shifting the actual orbit? Maybe I don’t get fully what the adaptorPropagator does.

example, if i have a reference spacecraft which TLE is +2s early, I would need to shift the inputs to the propagator in order for the event detectors to work (if for example a conjunction detector).

Probably I don’t get it… :slight_smile:

Hi Petrus,

Here’s an example of a Java implementation based on Luc’s idea, which shifts the PV and the attitude but keeps the same date as the original state. I didn’t include the additional states though but it’s probably not hard to shift them and add them to the new SpacecraftState too.

package org.orekit.propagation.analytical;

import org.orekit.attitudes.Attitude;
import org.orekit.propagation.SpacecraftState;
import org.orekit.utils.AbsolutePVCoordinates;

public class TimeOffsetDifferentialEffect implements AdapterPropagator.DifferentialEffect {
    private final double timeShift; // time shift in seconds

    public TimeOffsetDifferentialEffect(double timeShift) {
        this.timeShift = timeShift;
    }

    @Override
    public SpacecraftState apply(SpacecraftState original) {
        SpacecraftState stateShifted = original.shiftedBy(timeShift);
        // shift PV and attitude but use original date
        AbsolutePVCoordinates absPvaShifted = new AbsolutePVCoordinates(original.getFrame(), original.getDate(), stateShifted.getPVCoordinates());
        Attitude attitudeShifted = new Attitude(original.getDate(), original.getFrame(), stateShifted.getAttitude().getOrientation());
        return new SpacecraftState(absPvaShifted, attitudeShifted, original.getMass());
    }
}

Then after compiling the JAR (with a Maven pom.xml file and running mvn package) here’s the orekit Python jpype script to use the Java class. I tested it on my machine:

import pathlib
jar_path = <PATH TO JAR>

import orekit_jpype
orekit_jpype.initVM(additional_classpaths=[jar_path])

import orekit_jpype.pyhelpers
orekit_jpype.pyhelpers.setup_orekit_data(from_pip_library=True)

from org.orekit.frames import FramesFactory
eme2000 = FramesFactory.getEME2000()

from org.orekit.attitudes import FrameAlignedProvider
inertial_pointing = FrameAlignedProvider(eme2000)

from org.orekit.propagation.analytical.tle import TLE, SGP4
tle_line_1 = '1 48900U 21059X   22235.12477084  .00003084  00000+0  17186-3 0  9995'
tle_line_2 = '2 48900  97.5615   3.9377 0008844 228.2777 240.1256 15.14325763 64001'
tle = TLE(tle_line_1, tle_line_2)

sgp4_prop = SGP4(tle, inertial_pointing, 50.0)

from org.orekit.propagation.analytical import TimeOffsetDifferentialEffect
time_shift_s = 2.0  # two seconds offset
time_offset_effect = TimeOffsetDifferentialEffect(time_shift_s)

from org.orekit.propagation.analytical import AdapterPropagator
adapter_prop = AdapterPropagator(sgp4_prop)
adapter_prop.addEffect(time_offset_effect)

date_start = tle.getDate()
duration = 3600.0
date_end = date_start.shiftedBy(duration)
date_end_shifted = date_end.shiftedBy(time_shift_s)

state_end = sgp4_prop.propagate(date_end)
pv_end = state_end.getPVCoordinates()

state_end_adapter_prop = adapter_prop.propagate(date_end)
pv_end_adapter_prop = state_end_adapter_prop.getPVCoordinates()

state_end_manually_shifted = state_end.shiftedBy(time_shift_s)
pv_end_manually_shifted = state_end_manually_shifted.getPVCoordinates()

assert state_end.getDate().durationFrom(state_end_adapter_prop.getDate()) == 0.0

from org.orekit.utils import PVCoordinates
delta_pv = PVCoordinates(pv_end_adapter_prop, pv_end_manually_shifted)
assert delta_pv.getPosition().getNorm() == 0.0
assert delta_pv.getVelocity().getNorm() == 0.0

Btw we could/should add examples in the orekit jpype repo on how to easily use custom Java code to avoid for loops in Orekit Python, because it’s one of the most useful features of jpype.

3 Likes

Many thanks Clément!

This is indeed an excellent help for my question as well as a good demonstration of custom jar’s in orekit_jpype! Many thanks!

Yes maybe we should include some example of custom jars also in the orekit_jpype repo, I have a standalone example at GitHub - petrushy/jpype_java_extension_example I was trying to get it all to build at same time but landed in a two-step approach, but think it should be possible to both compile java and pip install in one go. But it can likely be made simpler.

Again, thanks!

Indeed it would be nice to call javac or maven when pip installing, but the easiest is to do like in the orekit jpype repo: the developer compiles the jar locally and pushes it to the repo, as the developer needs a java toolchain anyways for development and testing. A further step could be building the .jar in a CI pipeline and pushing it to the gitlab package registry, but I could not find a way to downlad the JAR from the gitlab package registry when pip installing the project.