Casting np.array into JArray_double2D

Hello everyone,

I am trying to use the second constructor in this class to feed my PV measurements to the BatchLeastSquare method:

PV(AbsoluteDate date, Vector3D position, Vector3D velocity, double[][] covarianceMatrix, double baseWeight, ObservableSatellite satellite)

Well, I believe everything is correct except the covarianceMatrix. I have a numpy array, while the constuctor accepts JArray_double2D. So I need to convert my covarianceMatrix from numpy array to 2 dimensional (6x6) JArray. I am not hundred percent sure but some casting must be done in order to accomplish this.

from orekit.pyhelpers import datetime_to_absolutedate, JArray, JArray_double2D
from org.orekit.estimation.measurements import PV, ObservableSatellite
from org.hipparchus.geometry.euclidean.threed import Vector3D
from orekit import JArray_double
from org.hipparchus.linear import Array2DRowRealMatrix

observableSatellite = ObservableSatellite(0) # Propagator index = 0

covarianceMatrix  = np.zeros((6, 6))

for i in range(1000): #4321
    pos3D = Vector3D(float(truedata_df['pos_x'][i])*1000,
                     float(truedata_df['pos_y'][i])*1000,
                     float(truedata_df['pos_z'][i])*1000)                  # in [m]

   vel3D = Vector3D(float(truedata_df['vel_x'][i])*1000,
                     float(truedata_df['vel_y'][i])*1000,
                     float(truedata_df['vel_z'][i])*1000)                  # in [m/s]
    
    date = AbsoluteDate(truedata_df['date'][i].year,
                        truedata_df['date'][i].month,
                        truedata_df['date'][i].day,
                        truedata_df['date'][i].hour,
                        truedata_df['date'][i].minute,
                        float(truedata_df['date'][i].second)+0.566,
                        UTC)
    
    covarianceMatrix = np.array([[float(df_cov[i][0]), float(df_cov[i][1]), float(df_cov[i][3]), float(df_cov[i][6]), float(df_cov[i][10]), float(df_cov[i][15])],
                                 [float(df_cov[i][1]), float(df_cov[i][2]), float(df_cov[i][4]), float(df_cov[i][7]), float(df_cov[i][11]), float(df_cov[i][16])],
                                 [float(df_cov[i][3]), float(df_cov[i][4]), float(df_cov[i][5]), float(df_cov[i][8]), float(df_cov[i][12]), float(df_cov[i][17])],
                                 [float(df_cov[i][6]), float(df_cov[i][7]), float(df_cov[i][8]), float(df_cov[i][9]), float(df_cov[i][13]), float(df_cov[i][18])],
                                 [float(df_cov[i][10]), float(df_cov[i][11]), float(df_cov[i][12]), float(df_cov[i][13]), float(df_cov[i][14]), float(df_cov[i][19])],
                                 [float(df_cov[i][15]), float(df_cov[i][16]), float(df_cov[i][17]), float(df_cov[i][18]), float(df_cov[i][19]), float(df_cov[i][20])]])

    covarianceMatrix_1 = JArray_double.cast_(JArray('double')(covarianceMatrix[0]))
    covarianceMatrix_2 = JArray_double.cast_(JArray('double')(covarianceMatrix[1]))
    covarianceMatrix_3 = JArray_double.cast_(JArray('double')(covarianceMatrix[2]))
    covarianceMatrix_4 = JArray_double.cast_(JArray('double')(covarianceMatrix[3]))
    covarianceMatrix_5 = JArray_double.cast_(JArray('double')(covarianceMatrix[4]))
    covarianceMatrix_6 = JArray_double.cast_(JArray('double')(covarianceMatrix[5]))
    
    orekitPV_est = PV(date, pos3D, vel3D, covarianceMatrix, baseweight, observableSatellite)
    estimator.addMeasurement(orekitPV_est)

Individual elements in numpy covariance matrix can be cast into JArray_double object, but how can I get a 2D JArray using these elements? Below line returns an empty 2D JArray, but how can I assign above casted elements into this 2D JArray?

    covarianceMatrix = JArray_double2D(6,6)

Also, after creating JArray_double2D method we again need another .cast_ right? Do you have any idea how can it be done @petrus.hyvonen?

Basically, I couldn’t add my covariance matrix (np.array) to my estimations and this is my problem in a nutshell :sweat_smile: Anyone else faced a similar issue before? Any advice is appreciated.

Thanks,
Baris

Hi there,

I have never used Jarray to create a matrix for Orekit, but instead you can instantiate an Array2DRowRealMatrix and fill its elements with setEntry.

Best,
Romain.

Hi,

Hard to test without an working example (truedata_df missing), but I think you should be able to similar as in the JArray_double2D routine:

  arr = JArray('object')(x)

    for i in range(x):
        arr[i] = JArray('double')(y)

There arr[i] is your casted arrays and merging these into a JArray object and arr would be your final 2D matrix.

Hello @petrus.hyvonen , thanks for the reply. I’ve tried your suggestion as following:

arr = JArray('object')(6)

for i in range(6):        
   arr[i] = JArray('double')(covarianceMatrix[i])
            
orekitPV_est = PV(date, pos3D, vel3D, arr, baseweight, observableSatellite)    
estimator.addMeasurement(orekitPV_est)    

and recieved an error that looks like this:


JavaError                                 Traceback (most recent call last)
~\AppData\Local\Temp\ipykernel_19536\1758518618.py in <module>     
85     
86     covarianceMatrix = Array2DRowRealMatrix(arr)
---> 87     orekitPV_est = PV(date, pos3D, vel3D, arr, baseweight, observableSatellite)     
88     estimator.addMeasurement(orekitPV_est)     
89
JavaError: <super: <class 'JavaError'>, <JavaError object>>
    Java stacktrace:
java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [[D
	at org.orekit.estimation.measurements.PV.<init>(PV.java:173)

so it seems like after casting elements we are supposed to cast them once again but it does not let me. Could not proceed with this way.

On the other hand, hello @Serrof, I will try your suggestion and keep you updated.

@Echulion I use @Serrof 's method for setting the covariance matrix element by element and haven’t had any problems - though I am setting the initial covariance matrix for the Kalman Filter, not in a PV measurement like you.

from org.hipparchus.linear import Array2DRowRealMatrix

covariance_matrix = [<here I have 6 rows of 6-element lists (should be similar to your numpy approach)>]
num_params = len(covariance_matrix)
covariance_matrix_java = Array2DRowRealMatrix(num_params, num_params)
for row in range(num_params):
    for col in range(num_params):
        covariance_matrix_java.setEntry(row, col, covariance_matrix[row][col])

I’m having the same issue that I cannot construct a PV measurement with a covariance matrix. Does anyone have a working example? I’m having doubts the interface for setting the covariance is correctly exposed.

Approach A

The second constructor OP refers to is:

PV(AbsoluteDate date, Vector3D position, Vector3D velocity, double[][] covarianceMatrix, double baseWeight, ObservableSatellite satellite)

This should correspond with:

@typing.overload
    def __init__(self, absoluteDate: org.orekit.time.AbsoluteDate, vector3D: org.hipparchus.geometry.euclidean.threed.Vector3D, vector3D2: org.hipparchus.geometry.euclidean.threed.Vector3D, doubleArray: typing.List[typing.List[float]], double2: float, observableSatellite: ObservableSatellite): ...

This suggest a simple list of lists of floats should do. I construct mine from a numpy array using:

c_inertial : typing.List[typing.List[float]] = c_numpy.tolist()

This results in an ‘InvalidArgsError’

PV(date, pv_inertial.getPosition(), pv_inertial.getVelocity(), c_inertial, float(1.0), self.target_satellite)
*** orekit.InvalidArgsError: (<class 'org.orekit.estimation.measurements.PV'>, '__init__', (<AbsoluteDate: 2023-02-15T12:00:00.000Z>, <Vector3D: {3,387,827.030357755; -5,654,903.875181666; -8,761.6192870896}>, <Vector3D: {2,540.2427141317; 1,584.8845619678; 7,187.4378710901}>, [[1.0000000000000027, -5.551115123125783e-17, 4.336808689942018e-19, 0.0, 0.0, 0.0], [-5.551115123125783e-17, 1.0000000000000027, -1.0842021724855044e-18, 0.0, 0.0, 0.0], [4.336808689942018e-19, -1.0842021724855044e-18, 1.0000000000000029, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 1.0000000000000027, -5.551115123125783e-17, 4.336808689942018e-19], [0.0, 0.0, 0.0, -5.551115123125783e-17, 1.0000000000000027, -1.0842021724855044e-18], [0.0, 0.0, 0.0, 4.336808689942018e-19, -1.0842021724855044e-18, 1.0000000000000029]], 1.0, <ObservableSatellite: org.orekit.estimation.measurements.ObservableSatellite@67c119b7>))

Approach B

When I try the JArray('object')(6) approach suggested by @petrus.hyvonen the arguments gets accepted, but I get the same casting error, but I think this is a red herring.

PV(date, pv_inertial.getPosition(), pv_inertial.getVelocity(), arr, float(1.0), self.target_satellite)
*** orekit.JavaError: <super: <class 'JavaError'>, <JavaError object>>
    Java stacktrace:
java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [[D
	at org.orekit.estimation.measurements.PV.<init>(PV.java:173)

Approach C

Using the suggest approach of @Serrof , I still get the same InvalidArgsError. See the example below:

PV(date, pv_inertial.getPosition(), pv_inertial.getVelocity(), arr2, float(1.0), self.target_satellite)
*** orekit.InvalidArgsError: (<class 'org.orekit.estimation.measurements.PV'>, '__init__', (<AbsoluteDate: 2023-02-15T12:00:00.000Z>, <Vector3D: {3,387,827.030357755; -5,654,903.875181666; -8,761.6192870896}>, <Vector3D: {2,540.2427141317; 1,584.8845619678; 7,187.4378710901}>, <Array2DRowRealMatrix: Array2DRowRealMatrix{{1.0,-0.0,0.0,0.0,0.0,0.0},{-0.0,1.0,-0.0,0.0,0.0,0.0},{0.0,-0.0,1.0,0.0,0.0,0.0},{0.0,0.0,0.0,1.0,-0.0,0.0},{0.0,0.0,0.0,-0.0,1.0,-0.0},{0.0,0.0,0.0,0.0,-0.0,1.0}}>, 1.0, <ObservableSatellite: org.orekit.estimation.measurements.ObservableSatellite@67c119b7>))

Hey there,

The constructor wants double[][] so you need to call getData() on your matrix in approach C.

Edit: also, you don’t need to do float(1.). Writing the dot is enough.

Best,
Romain.

Hi @Serrof Many thanks for the swift reply. Unfortunately, I still get the same casting error.

Hopefully, by explaining what I do in more detail can help to narrow down the cause/proper way to call PV from Python.

I arrive at my starting matrix as follows:

cov : typing.List[typing.List[float]] = np.dot(R,np.dot(c_itrf, R.transpose())).tolist()

Its properties are:

> (type(cov),type(cov[0]),type(cov[0][0]))
(<class 'list'>, <class 'list'>, <class 'float'>)

> cov
[[1503277.1368901345, -1.1641532182693481e-10, 6.821210263296962e-13, 0.0, 0.0, 0.0], [0.0, 1503277.1368901348, 1.1368683772161603e-12, 0.0, 0.0, 0.0], [4.547473508864641e-13, 6.821210263296962e-13, 1503277.1368901345, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 150.32771368901345, 0.0, 8.326672684688674e-17], [0.0, 0.0, 0.0, 0.0, 150.32771368901345, 1.1102230246251565e-16], [0.0, 0.0, 0.0, 8.326672684688674e-17, 1.1102230246251565e-16, 150.32771368901345]]

To convert to an input matrix for the PV class, I apply the process suggested by Serrof (approach C in my earlier post).

cov_java = Array2DRowRealMatrix(6, 6)
for row in range(6):
    for col in range(6):
        cov_java.setEntry(row, col, cov[row][col])

This results in the following cov_java object and construction of pv_meas.

> (type(cov_java),type(cov_java.getData()))
(<class 'org.hipparchus.linear.Array2DRowRealMatrix'>, <class 'orekit._orekit.JArray_object'>)

cov_java.getData()
JArray<object>[<Object: [D@27f74733>, <Object: [D@7bef452c>, <Object: [D@4bb8855f>, <Object: [D@57fae983>, <Object: [D@4a29f290>, <Object: [D@4bee18dc>]

> pv_meas = PV(date, position, velocity, cov_java.getData(), 1.0, self.target_satellite)
*** orekit.JavaError: <super: <class 'JavaError'>, <JavaError object>>
    Java stacktrace:
java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [[D
	at org.orekit.estimation.measurements.PV.<init>(PV.java:173)

As you can see, I still get the same casting errors.

1 Like

So after banging my head against this for half a day (including trying everything listed here and a few things that weren’t) I suspect the only way to get around this is to write your own Measurement child class in Python that has a custom reader for the covariance reader (use the PythonAbstractMeasurement class in org.orekit.estimation.measurements as a parent). It’s the only thing I can think of that gets around the attempt to clone a double[][] in python.

I SOLVED IT!!! @Echulion @Serrof @petrus.hyvonen @magnific0 I know it’s been quite some time since you all initially posted this problem, but I figured you might like to know the answer anyway. The core of my solution depends on the fact that when you assign one variable to another variable in python, it doesn’t actually make a full copy, it just declares that the new variable points to the same place in memory as the old one, i.e.

a = 1
b = a
b = 2
# a now also equals 2

Solution

Step 1: Go ahead and create a dummy diagonal covariance with a JArray_double(6) and use it to create a PV object:

dummyCovDiag = JArray_double(6) # creates a double[6] array with default values of 0.0
meas = PV(date, pos, vel, dummyCovDiag, 1.0, ObservableSatellite(0))

Step 2: Use the appropriate function to call the covariance matrix associated with your measurement. This will give you a 6x6, 2D array of Java “objects”

cov = meas.getCovarianceMatrix()
# cov = JArray<object>[<Object: [D@3e79218>, <Object: [D@3ea8436d>, <Object: [D@8eb4380>, <Object: [D@2c82b066>, <Object: [D@13ca80bc>, <Object: [D@6f050a83>]

Step 3: Under the hood, cov is an array of JArray_double objects. Use the JArray_double.cast_ function to assign values to the individual members of the 2D array

x = JArray_double.cast_(cov[0])
x[0] = 1.0

Step 4: Call the covariance from your PV object again and you will see that the value has changed

cov2 = meas.getCovarianceMatrix()
x2 = JArray_double.cast_(cov2[0])[0] # x2 will equal 1.0
2 Likes

Hello!

Wow, congrats on solving this year-long problem! :clap::partying_face: And thanks for letting us know the answer. Although I somewhat forget the initial issue, I will definitely check it again with your solution.

Thank you very much for giving it time and thought. :slightly_smiling_face:

1 Like