Problem with method ComparableMeasurement.compareTo()

Hi everyone,

I am using Orekit for orbit determination purposes and it seems I have some troubles using the measurements. I had the following exception:

java.lang.RuntimeException: java.lang.IllegalArgumentException: Comparison method violates its general contract!
...
Caused by: java.lang.IllegalArgumentException: Comparison method violates its general contract!
	at java.util.TimSort.mergeLo(TimSort.java:777)
	at java.util.TimSort.mergeAt(TimSort.java:514)
	at java.util.TimSort.mergeCollapse(TimSort.java:439)
	at java.util.TimSort.sort(TimSort.java:245)
	at java.util.Arrays.sort(Arrays.java:1512)
	at org.orekit.estimation.leastsquares.BatchLSEstimator$Provider.getEstimatedMeasurement(BatchLSEstimator.java:645)

After some researches it seems this error shows when the transitivity of the method compareTo in ComparableMeasurements is not respected.

I think I understand why I had some trouble in my case.
I think the problem comes particularly form these lines (59-62) in ComparableMeasurement:

           if (thisV.length > otherV.length) {
                result = +1;
            } else if (thisV.length < otherV.length) {
                result = 1;
            } 

Therefore if I use AngularAzEl azEl measurement and Range range measurements at the same dates, azel.comareTo(range) = 1 and range.compareTo(azel) = 1, which violates the transitivity rule.

You can find this result by running the following test (after Orekit data initialization):

import org.hipparchus.util.FastMath;
import org.junit.jupiter.api.Test;
import org.orekit.bodies.GeodeticPoint;
import org.orekit.bodies.OneAxisEllipsoid;
import org.orekit.estimation.measurements.AngularAzEl;
import org.orekit.estimation.measurements.GroundStation;
import org.orekit.estimation.measurements.ObservableSatellite;
import org.orekit.estimation.measurements.Range;
import org.orekit.frames.FramesFactory;
import org.orekit.frames.TopocentricFrame;
import org.orekit.time.AbsoluteDate;
import org.orekit.utils.Constants;
import org.orekit.utils.IERSConventions;


public class EstimatedMeasurementsOrderTest {

    @Test
    public void testDifferentSize() {
        OneAxisEllipsoid earth = new OneAxisEllipsoid(Constants.WGS84_EARTH_EQUATORIAL_RADIUS, Constants.WGS84_EARTH_FLATTENING,
                                                      FramesFactory.getITRF(IERSConventions.IERS_2010, false));
        TopocentricFrame stationFrame = new TopocentricFrame(earth, new GeodeticPoint(FastMath.toRadians(45.0), FastMath.toRadians(0.0), 0.0), "station");
        GroundStation station = new GroundStation(stationFrame);
        AbsoluteDate date = AbsoluteDate.FIFTIES_EPOCH;

        ObservableSatellite satellite = new ObservableSatellite(0);
        Range range = new Range(station, false, date, 400e3, 1.0, 1.0, satellite);
        AngularAzEl azel = new AngularAzEl(station, date, new double[] {1.0, 0.5}, new double[] {1.0e-2, 1.0e-2}, new double[] {1.0, 1.0}, satellite);
        System.out.println(range.compareTo(azel));
        System.out.println(azel.compareTo(range));
    }

}

I think a simple solution would be just to return -1 when the length is lower (in line 62). What do you think?

Thank you for your time,

Dorian

Hi @Dorian,

I think you found a bug and your solution is the proper one.
Thank you for this.
Could you please take time to open a bug on the Giltab Forge ?

Regards,
Maxime

Thanks for your response. The issue is submitted :slight_smile:

You’re very welcome.
Issue is fixed in develop branch.