Clone (copy) NumericalPropagator object in Python

Hello,

I am trying to clone/copy a NumericalPropagator object with the Python Wrapper. I tried the following and don’t know where to go from here:

str(type(num_prop)) is “<class ‘org.orekit.propagation.numerical.NumericalPropagator’>”

from java.lang import Object
java_object = Object.cast_(num_prop)

java_object returns successfully. However, it does not have the “clone” method I expected it to have based on the documentation, NumericalPropagator (OREKIT 12.1.2 API).

Is it possible to make a copy of a NumericalPropagator object in the Python Wrapper?

Thanks,
Sam

Hi @Sam

In 12.1.2, orbit propagators in Orekit are not Cloneable. You shall use the .copy() method instead.
Please note that in 12.2 they will be Cloneable. So, the clone method will be available and the copy method deprecated.

Best regards,
Bryan

Hi @bcazabonne,

Would you be able to share a snippet of how to copy in the Python wrapper? I can’t seem to figure it out, or even find a “copy” method that is available. I’m using v12.1.1, that’s the latest I found for the Python wrapper. (Python copy module doesn’t work since it can’t pickle the NumericalPropagator object)

Thanks,
Sam

Oh I said a mistake!
Propagators cannot be cloned of copied. That’s the PropagatorBuilder that can…

I’m sorry
Bryan

1 Like

However, because PropagatorBuilder will implement Cloneable, maybe it could be interesting that Propagator also implement this interface :slight_smile:
Could you open a feature request in our Gitlab repository?

Thank you!
Bryan

@bcazabonne will do. I’m just waiting for my account at the link you provided to be approved:

“Your account is pending approval from your GitLab administrator and hence blocked. Please contact your GitLab administrator if you think this is an error.”

Issue created here: Clone/copy propagator objects (Python Wrapper) (#1474) · Issues · Orekit / Orekit · GitLab

Hi,

Just a remark on this. I believe these clones are like shallow copies. Indeed in a propagator(builder) there is a lot of things (forces, detectors, etc). It’s the same objects that are kept in the new object, so using it might have consequences on the original.

Cheers,
Romain.

Hi Romain,

That’s a good point, I was looking for something like a deep copy.

I made a function that seems to work for my current purposes, the propagators can be independently used and still have identical position/velocity outputs for a given AbsoluteDate. Although the integrator needs to be remade each time (I couldn’t figure out how to get the integrator from the propagator, if that is in fact possible in Python Wrapper).

def copy_numerical_prop(numerical_prop, integrator_ref_orbit):
    
    # integrator_ref_orbit needs to be the same as it was when
    # the integrator for numerical_prop was first made
    
    init_state = numerical_prop.getInitialState()
            
    position_tolerance = 0.1 # m
    tol = o.NumericalPropagator.tolerances(position_tolerance, integrator_ref_orbit, o.OrbitType.CARTESIAN)
    
    init_step = 1. # s
    min_step = 0.0001 # s
    max_step = 1000.0 # s
    integrator = o.DormandPrince853Integrator(min_step, max_step, 
        o.JArray_double.cast_(tol[0]),  # Double array of doubles needs to be casted in Python
        o.JArray_double.cast_(tol[1]))
    integrator.setInitialStepSize(init_step)
    
    att_provider = numerical_prop.getAttitudeProvider()
    
    copy_prop = o.NumericalPropagator(integrator)
    copy_prop.setOrbitType(o.OrbitType.CARTESIAN)
    copy_prop.setInitialState(init_state)
    copy_prop.setAttitudeProvider(att_provider)
    
    force_models = list(numerical_prop.getAllForceModels())
    
    for ii in range(len(force_models)):
        if 'NewtonianAttraction' in str(force_models[ii]):
            pass
        elif ('org.orekit.forces.gravity.HolmesFeatherstoneAttractionModel' in str(force_models[ii])
               or 'org.orekit.forces.drag.DragForce'in str(force_models[ii])):
            copy_prop.addForceModel(force_models[ii])
        else:
            raise NotImplementedError(str(force_models[ii]))
             
    return copy_prop

Thanks,
Sam

Hi,

Indeed you don’t have access to the integrator of a propagator, to avoid side effects. However there is a getIntegratorName method (or a similar name I’m not sure) that should tell you which kind it is.
You should look into ODEIntegratorBuilder. It allows to create similar integrators at will. By the way, for adaptive schemes like Dormand Prince, it handles the tolerances itself, so that’s one less thing to worry about.

Cheers,
Romain.