# Numerical Propagator different results

Hi all,

I am trying to propagate a satellite’s state using numerical propagator. I am referring the tutorial to code the propagator.
The tutorial is using the following method to propagate to a specific timestamp.

``````final SpacecraftState finalState = propagator.propagate(pDate);
final CartesianOrbit orbit = (CartesianOrbit) OrbitType.CARTESIAN.convertType(finalState.getOrbit());
System.out.println(pDate.toString()+" position2 = "+finalState.getPVCoordinates().getPosition().getX());
``````

In the orbit determination tutorials the state is propagated using EphemerisGenerator. The two methods produces slightly different results when propagated to the same time stamp.
For example,

``````2022-11-17T23:58:36.501Z position  = -2.687806757116504E7 ( With EphemerisGenerator)
2022-11-17T23:58:36.501Z position2 = -2.68780675711712E7
``````

I am not sure why and appreciate some help to understand what is happening.

Thank you.

Following is the code

``````public class PropagateSatellite {
public static void main(String[] args) throws Exception {

final String satId = "00000";
initializeOrekitData();
propagateSatellite(satId);
}

public static void propagateSatellite(final String satId) {
final FactoryManagedFrame orbitFrame = FramesFactory.getEME2000();
final double kmToMeters = 1e3;

JsonNode data = getStateData(satId,0);
double xpos = -42096.595969393245*kmToMeters;
double ypos = -2287.448341771474*kmToMeters;
double zpos = 85.43497860699213*kmToMeters;
double xvel = 0.16757315787000582*kmToMeters;
double yvel = -3.070583889218538*kmToMeters;
double zvel = -2.722574558365106e-4*kmToMeters;
double cr = 0.044294;
final String epochStr = "2022-11-19T23:45:43.501000Z";
System.out.println(epochStr);

final AbsoluteDate epoch = new AbsoluteDate(epochStr,TimeScalesFactory.getUTC());
final double[] pos = {xpos,ypos,zpos};
final double[] vel = {xvel,yvel,zvel};

//Gravity field
final int degree =20;
final int order  = 20;
final NormalizedSphericalHarmonicsProvider gravityProvider = GravityFieldFactory.getConstantNormalizedProvider(degree, order);
/** Initial Orbit */
final Orbit initialOrbit = new CartesianOrbit(new PVCoordinates(new Vector3D(pos), new Vector3D(vel)),orbitFrame,epoch,gravityProvider.getMu());
final OrbitType propagationType = OrbitType.CARTESIAN;
/** Spacecraft state*/
SpacecraftState initialState = new SpacecraftState(initialOrbit);

final int secondsPerDay = 86400;
final double days = 4.0;
final double deltaTime = 30*60.0;
final AbsoluteDate startEpoch = epoch.shiftedBy(-secondsPerDay*days);

/** Initialize Propagator*/
//Integrator
final double minStep = 0.001;
final double maxStep = 300.0;
final double positionError = 10.0;

final double[][] tolerances = NumericalPropagator.tolerances(positionError, initialOrbit, propagationType);

final DormandPrince853Integrator integrator = new DormandPrince853Integrator(minStep,maxStep,tolerances[0],tolerances[1]);
// Initialize the numerical builder

final NumericalPropagator propagator = new NumericalPropagator(integrator);
propagator.setOrbitType(propagationType);
final CelestialBody bodySun = CelestialBodyFactory.getBody("sun");
final CelestialBody bodyMoon = CelestialBodyFactory.getBody("moon");
//Gravity

//Initial stae
propagator.setInitialState(initialState);

// Ephemeris generator
final EphemerisGenerator generator = propagator.getEphemerisGenerator();
propagator.propagate(startEpoch,epoch);
final Propagator boundedPropagator = generator.getGeneratedEphemeris();

AbsoluteDate pDate = startEpoch;
while (pDate.compareTo(epoch)<=0) {
//First Method with bounded propagator
PVCoordinates pv = boundedPropagator.getPVCoordinates(pDate, orbitFrame);
Vector3D posProp = pv.getPosition();
Vector3D velProp = pv.getVelocity();
System.out.println(pDate.toString()+" position  = "+posProp.getX());

//Second method
// Extrapolate from the initial to the final date
final SpacecraftState finalState = propagator.propagate(pDate);
final CartesianOrbit orbit = (CartesianOrbit) OrbitType.CARTESIAN.convertType(finalState.getOrbit());
System.out.println(pDate.toString()+" position2 = "+orbit.getPVCoordinates().getPosition().getX());

pDate = pDate.shiftedBy(deltaTime);
}

}

}
``````

Hi there,

Here are my two cents (from not having coded it): the ephemeris mode means that first, you propagate between the two dates in question. Then, using the existing, calculated integration steps, you interpolate w.r.t. to time to get any intermediate dates you requested (instead of actually computing step after step to reach them). So there is some difference, normally negligible if your integrator is well tuned for your trajectory. But it’s more performant, as the cost of interpolation is usually lower than starting and stopping your integration repeatedly, especially if you want many intermediate state.

Best,
Romain S.

1 Like

Hi ,

Thank you for the explanations. This helps a lot. The difference of position values are less than 1mm. Therefore, I think it can be ignored.

That actually raises a question from me to the dev team: what does the `EphemerisGenerator` do in practise with propagators that are not based on an integration scheme, such as `KeplerianPropagator`?

Edit: found the answer in the docstring of `EphemerisGenerator.java`:

Analytical propagators will mainly store only the start and stop date and the model itself, so ephemeris will just call the model back.

Cheers,
Romain.

1 Like