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?
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.
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)
However, because PropagatorBuilder will implement Cloneable, maybe it could be interesting that Propagator also implement this interface
Could you open a feature request in our Gitlab repository?
@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.”
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.
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
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.