Hi,
I have a question regarding the Orekit’s Python wrapper.
The aim of my code is to solve an orbit determination problem making use of range measurements. In my code I have extended the class PythonAbstractMeasurement to create a new class (NewRange) which is very similar to the Range one and everything is working fine (i.e. the orbit determination problem is carried out without errors).
Now, I would like to estimate also the clock offset and the clock drift (now I am estimating just the 6 orbital parameters) and I have followed the code written in the Range class. Therefore, I have added the parameter drivers for the clock offset and the clock drift in the constructor of my class, but I get a “AttributeError: ‘NewRange’ object has no attribute ‘addParameterDriver’” when calling the method addParameterDriver. I guess it is due to the fact that it is a protected method and hence not wrapped, is it right? And if so, is there a way to overcome this problem?
Thank you in advance.
Best,
Samuele
Hi @samuele
Unfortunately, I can’t help you for your Python issues. Howerver, I have a small question. Why did you extend the Range
measurement class?
Estimating the clock offset is straightforward using the current implementation of the Range
measurement. After initialing the ObservableSatellite
object used in the Range
measurement’s constructor, you can set the clock estimation like that:
satellite = ObservableSatellite(0)
satellite.getClockOffsetDriver().setSelected(true)
For the GroundStation, you can do the same thing:
station = GroundStation(...)
station.getClockOffsetDriver().setSelected(true)
Please note that the spacecraft and station clock drifts are not used in Range
measurement, they are only used for the RangeRate
measurement (that’s maybe the reason why you extended the class).
Best regards,
Bryan
Hi @bcazabonne,
thank you for your reply! I have extended the Range class because my range is not computed as a satellite-station range but it is instead a range between the satellite and the Solar System Barycentre. You can see the detailed description of my problem here. So I have re-written the theoreticalEvaluation() method, but I can’t call the addParameterDriver() method…
Best regards,
Samuele
Hi @samuele
Thank you for your answer. Therefore, it’s probably a Python issue, and unfortunately I cannot help you for that…
I hope our Orekit-Python experts will help you.
Best regards,
Bryan
Hi Samuele,
Yes, the addParameterDriver is private in the AbstractMeasurement class and is not modified in the PythonAbstractMeasurements so that is why.
It seems to have a quite trivial function, so you could just do a “self.supportedParameters.add(driver)”.
Otherwise if this is a reasonable method to open, I can add this method to next release?
Regards
/Petrus
Hi Petrus,
thank you for your reply!
if I just do a “self.supportedParameters.add(driver)” I get a ‘NewRange’ object has no attribute ‘supportedParameters’. So I thought to just create the attribute ‘supportedParameters’ in my class and it seems to work.
However, it is still not clear to me how to get the estimated values for the satellite clock offset and drift starting from the method ‘BatchLSEstimator.estimate()’, that I run in my main code after adding N ‘NewRange’ measurements. Should I select (with the method setSelected()) the two clock ParameterDrivers before calling the estimate method? The only part of my code which deals with the two clock ParameterDrivers is contained in the ‘NewRange’ class, as it is done in the ‘Range’ class. So I thought it was sufficient to just add the ‘NewRange’ measurements to the estimator, but I don’t see any estimated values of the clock parameters…
Thank you so much!
Samuele
Hi @samuele,
You need indeed to select the drivers to estimate them with the batch LS.
Orbital parameter drivers (the state vector) are automatically selected while other drivers (propagation and measurement drivers) are un-selected by default.
It is the up to the user to set their selection to true if they must be estimated.
Hi @MaximeJ,
many thanks! Sure, it makes sense.
My question is: where and how should I select the drivers? The code of interest is:
estimator = BatchLSEstimator(optimizer, propagatorBuilder)
estimator.setParametersConvergenceThreshold(estimator_convergence_thres)
estimator.setMaxIterations(estimator_max_iterations)
estimator.setMaxEvaluations(estimator_max_evaluations)
observableSatellite = ObservableSatellite(0)
for i in range(0, number_of_measurements):
sat = ArrayList()
sat.add(observableSatellite)
psr_range = NewRange(date[i], float(0.0), float(sigma), float(range_weight), sat, .....)
estimator.addMeasurement(psr_range)
while the ‘NewRange’ class manages the clock parameters exactly as done in the ‘Range’ class, as you suggested me some time ago 
Best,
Samuele
Hi @samuele,
If I understood well you added the two ParameterDrivers
to your NewRange
class, along with a new attribute supportedParameters
that somehow replaces the one you don’t have access to in the AbstractMeasurement
class. Is that correct ?
First, do you have access to these new drivers so that you can use the method setSelected(true)
on them ?
Then, the batch LS gets the estimable measurements parameters in BatchLSEstimator. getMeasurementsParametersDrivers method.
You will note that it calls the ObservedMeasurement.getParametersDrivers()
method which should be defined in your case in AbstractMeasurement.getParametersDrivers.
This last method refers to the attribute supportedParameters
from the AbstractMeasurement
class and not the attribute supportedParameters
that you added to your NewRange
class.
So you probably need to overwrite the method getParametersDrivers
in your NewRange
class so that the batch LS can see your new drivers.
I’m not proficient enough in Python to tell you if it will work. But this looks a bit sketchy,I think the best way would be to open the method addParameterDriver
in the PythonAbstractMeasurement
class as @petrus.hyvonen suggested.
To check if your drivers are visible from the batch LS point of view, once you’ve added your measurement you can call the BatchLSEstimator.getMeasurementsParametersDrivers
method and see if you drivers’ names in the ParamaterDriversList
returned.
Hope this will help you,
Maxime
Hi @MaximeJ,
Yes, exactly. Here it is my class with the constructor and the getParametersDrivers method.
class NewRange(PythonAbstractMeasurement):
supportedParametersNew = []
def __init__(self, date, observed, sigma, base_weight, satellite):
super().__init__(date, observed, sigma, base_weight, satellite)
# Select the ParameterDrivers
self.getSatellites().get(0).getClockOffsetDriver().setSelected(True)
self.getSatellites().get(0).getClockDriftDriver().setSelected(True)
# add the selected ParameterDrivers to the attribute supportedParametersNew.
self.supportedParametersNew.append(self.getSatellites().get(0).getClockOffsetDriver())
self.supportedParametersNew.append(self.getSatellites().get(0).getClockDriftDriver())
def getParametersDrivers(self):
array_list = ArrayList()
array_list.add(self.supportedParametersNew[0])
array_list.add(self.supportedParametersNew[1])
return Collections.unmodifiableList(array_list)
When I print the results of the method BatchLSEstimator.getMeasurementsParametersDrivers I get just “org.orekit.utils.ParameterDriversList@5905d963” so I can’t understand if the drivers are visible…
It would be great indeed!
Thank you so much,
Samuele
I have tried to print something inside the overwritten getParametersDrivers method and it is not visualized during the execution of the code. I guess this means that the NewRange object still calls the getParametersDrivers method which refers to the supportedParameters attribute I can’t touch…