Measurements with correlated noise

I am writing a measurement class for RA/Dec and RA/Dec-rates. I’d like to be able to specify a covariance matrix for the measurement noise, similar to the Position or PV measurements classes.

Writing the measurement class is fine, but I’m unsure about how to incorporate the covariance into the estimators.

For the KalmanEstimator I can see where the covariance matrix is used in the decorate method. My plan is to write a class that inherits from KalmanEstimator and overloads decorate to include my new measurement class.

On the other hand I can’t see where the measurement noise covariance is used in the BatchLSEstimator? How do I ensure that the correlated measurements are used in the batch estimator?

Hi,

That’s a very interesting point. I think the decorate method of KalmanEstimator must be updated to take into account user-defined measurement covariance matrix. Currently, Orekit supposes the measurement covariance matrix only relevant for position-based measurements (i.e., Position or PV). However, in the literature, I never seen any measurement-type limitation about the measurement covariance matrix when calculating the Kalman gain.

There is no measurement covariance matrix in the batch least squares model like in the Kalman filter. In order to handle noisy measurements in a batch least squares process, users must “play” with the values of the base weight and the theoretical standard deviation of the measurement.

Best regards,
Bryan

Thanks Bryan. It sounds like I’m on the right track.

There’s no mathematical reason why batch least squares couldn’t use measurement noise defined with a covariance matrix. I’ll take a closer look at the code to see if those types of measurements can fit in the Orekit/Hipparchus framework.

Thanks,
Mark.

What I wanted to say is that in a BLS algorithm there is no equivalent use of the observation covariance matrix like in the Kalman filter (see Eq.3). In a batch least squares process, you can use this observation covariance matrix to initialize the base weight of the measurement.

Regards,
Bryan

I’ve constructed an (unrealistically extreme) example. I’ve generated 50 random PV measurements very close together (2s apart) on a GEO so that the estimation problem is very nearly linear. Then I compare the KalmanEstimator with BatchLSEstimator and a modified version of the batch estimator which uses the full measurement noise covariance.

With diagonal measurement noise the covariances are all the same (first line is estimated state, second line estimated covariance and third line the diagonal terms of the estimated covariance):

Kalman
{2021-09-06T21:20:36.603392, P(-8475610.440083588, 4.128925894860553E7, 393872.28261222516), V(-3010.8710607937933, -618.4523223660585, 139.9452309389648), A(0.04510795512277359, -0.21974512076417566, -0.0020962234370933914)}
Array2DRowRealMatrix{{24432.6042699602,-0.0969458157,-0.0009116675,90.4593889324,-0.0032741395,-0.0000309808},{-0.0969458157,24433.0653280152,0.0045082135,-0.0032741398,90.4748515029,0.0001522197},{-0.0009116675,0.0045082135,24432.5847326879,-0.0000309808,0.0001522197,90.4587248402},{90.4593889324,-0.0032741398,-0.0000309808,1.8461968529,-0.0000092543,-0.0000000885},{-0.0032741395,90.4748515029,0.0001522197,-0.0000092543,1.8462400312,0.0000004301},{-0.0000309808,0.0001522197,90.4587248402,-0.0000000885,0.0000004301,1.8461949552}}
[24432.604269960244, 24433.065328015193, 24432.584732687945, 1.8461968529427581, 1.8462400311504565, 1.8461949552447077]

Batch
{2021-09-06T21:20:36.603392, P(-8475610.440080741, 4.128925894860974E7, 393872.2826147967), V(-3010.8710608518722, -618.4523223371904, 139.94523097379584), A(0.04510795512274696, -0.21974512076414213, -0.0020962234371065436)}
BlockRealMatrix{{24432.6045932587,-0.0969449449,-0.000911203,90.4593891628,-0.0032741523,-0.000030973},{-0.0969449449,24433.065653571,0.0045059552,-0.0032741525,90.4748518298,0.0001521812},{-0.000911203,0.0045059552,24432.5850563649,-0.000030973,0.0001521812,90.4587250686},{90.4593891628,-0.0032741525,-0.000030973,1.8461968951,-0.0000092546,-0.0000000885},{-0.0032741523,90.4748518298,0.0001521812,-0.0000092546,1.8462400737,0.0000004302},{-0.000030973,0.0001521812,90.4587250686,-0.0000000885,0.0000004302,1.8461949973}}
[24432.604593258704, 24433.065653570993, 24432.585056364933, 1.846196895111237, 1.8462400736987334, 1.846194997334234]

Modified batch
{2021-09-06T21:20:36.603392, P(-8475610.440080741, 4.128925894860974E7, 393872.2826147967), V(-3010.8710608518722, -618.4523223371904, 139.94523097379584), A(0.04510795512274696, -0.21974512076414213, -0.0020962234371065436)}
BlockRealMatrix{{24432.6045932587,-0.0969449449,-0.000911203,90.4593891628,-0.0032741523,-0.000030973},{-0.0969449449,24433.065653571,0.0045059552,-0.0032741525,90.4748518298,0.0001521812},{-0.000911203,0.0045059552,24432.5850563649,-0.000030973,0.0001521812,90.4587250686},{90.4593891628,-0.0032741525,-0.000030973,1.8461968951,-0.0000092546,-0.0000000885},{-0.0032741523,90.4748518298,0.0001521812,-0.0000092546,1.8462400737,0.0000004302},{-0.000030973,0.0001521812,90.4587250686,-0.0000000885,0.0000004302,1.8461949973}}
[24432.604593258704, 24433.065653570993, 24432.585056364933, 1.8461968951112369, 1.8462400736987334, 1.846194997334234]

Now if I introduce some correlation between position and velocity in each dimension (actually very, very highly correlated), then we get

Kalman
{2021-09-06T21:20:36.603392, P(-8475619.988698082, 4.1289088922449805E7, 393658.10435862746), V(-3009.195298645621, -618.9399324191224, 138.68762104595274), A(0.04510854088083182, -0.21974682183417707, -0.002095108407079441)}
Array2DRowRealMatrix{{30471.6742278559,-0.6181182869,-0.0058200262,192.1808656536,-0.007371976,-0.0000695977},{-0.6181182869,30474.6093005574,0.0287389391,-0.007371978,192.2157629069,0.0003426963},{-0.0058200262,0.0287389391,30471.5494806069,-0.0000695977,0.0003426962,192.1793736223},{192.1808656536,-0.007371978,-0.0000695977,1.3800931274,-0.000066813,-0.0000006315},{-0.007371976,192.2157629069,0.0003426962,-0.000066813,1.3804090048,0.0000031057},{-0.0000695977,0.0003426963,192.1793736223,-0.0000006315,0.0000031057,1.3800795892}}
[30471.674227855867, 30474.60930055741, 30471.549480606904, 1.3800931273653623, 1.380409004752787, 1.3800795892268705]

Batch
{2021-09-06T21:20:36.603392, P(-8475482.729999227, 4.128929786842432E7, 393861.7144600353), V(-3008.2647908311346, -617.6580008234339, 139.7294848936114), A(0.04510723580462631, -0.21974513481884472, -0.0020961653506389516)}
BlockRealMatrix{{24432.6045932364,-0.0969448846,-0.0009112013,90.4593891564,-0.0032741321,-0.0000309724},{-0.0969448846,24433.0656535884,0.0045059503,-0.0032741323,90.4748518344,0.0001521795},{-0.0009112013,0.0045059503,24432.5850563698,-0.0000309724,0.0001521795,90.4587250705},{90.4593891564,-0.0032741323,-0.0000309724,1.8461968951,-0.0000092544,-0.0000000885},{-0.0032741321,90.4748518344,0.0001521795,-0.0000092544,1.8462400737,0.0000004301},{-0.0000309724,0.0001521795,90.4587250705,-0.0000000885,0.0000004301,1.8461949973}}
[24432.604593236425, 24433.0656535884, 24432.585056369764, 1.846196895065386, 1.846240073730767, 1.846194997348047]

Modified batch
{2021-09-06T21:20:36.603392, P(-8475533.60078832, 4.1289257695126854E7, 393879.9046541134), V(-3008.3925687513292, -617.539965677755, 140.32538733109985), A(0.04510759949079521, -0.2197453738146689, -0.002096266479901374)}
BlockRealMatrix{{30471.6747354189,-0.6181204377,-0.0058181151,192.1808690117,-0.0073720047,-0.0000695875},{-0.6181204377,30474.6098011869,0.0287291956,-0.0073720068,192.215766153,0.0003426419},{-0.0058181151,0.0287291956,30471.549986862,-0.0000695875,0.0003426418,192.1793769637},{192.1808690117,-0.0073720068,-0.0000695875,1.3800931501,-0.0000668133,-0.0000006314},{-0.0073720047,192.215766153,0.0003426418,-0.0000668133,1.3804090263,0.0000031054},{-0.0000695875,0.0003426419,192.1793769637,-0.0000006314,0.0000031054,1.3800796118}}
[30471.674735418856, 30474.60980118688, 30471.549986861974, 1.3800931500819553, 1.3804090263491087, 1.3800796117859755]

The results from the KalmanEstimator have changed due to the correlation in the measurement noise, whereas the BatchLSEstimator covariance is unchanged (as expected). The modified batch estimator matches the Kalman results.

I’m just putting this here as an example, rather than advocating for something to change. It’s an unusual type of measurement and I’m demonstrating estimation in an unrealistic scenario.

Apologies for resurrecting this old thread.

I’ve (finally) implemented my new measurement class. In order to incorporate the new measurement class into the Kalman estimator, I’ve had to make copies of KalmanEstimatorBuilder and KalmanEstimator so that I can modify the decorate method in KalmanEstimator. I’d prefer to be able to add a measurement class without having to replicate code.

I’d like to add two methods to AbstractMeasurement: getCovarianceMatrix and getCorrelationCoefficientsMatrix, similar to those currently implemented in PV and Position. By default the covariance would be a diagonal matrix containing “sigmas” (squared) and the correlation coefficients matrix would be the identity. PV and Position can overload those methods to return more appropriate values. I think this will allow adding measurement classes easily, with the added benefit of simplifying the decorate method.

Does that sound like a reasonable way to generalise the measurements? If so, I’m happy to lodge an issue and make a pull request.