Latitude and Longitude Crossing Detector

Dear Orekit community.
Is there any existing solution to capture events in crossing latitude or longitude area?
Like event captured if crossing range from +40 to +45 deg of latitude?

If not, would it be interesting to add to the EventDetector portfolio?
Any suggestion?
Let me know.

Alberto

Hi @alberto-ferrero ,

You can look at BooleanDetector and EventEnablingPredicateFilter for what you want to do.

Thanks @pascal.parraud
Never used the EventEnablingPredicateFilter.
Could you give me some hints?

In the meantime, I was creating custom event detectors. If interested, I might merge them.
Like for the LatitudeRangeCrossingDetector, supposing we define two parameters, double fromLatitude and double toLatitude, and we define the sign as double sign = FastMath.signum(toLatitude - fromLatitude)
The detector g function might simply be:

public double g(final SpacecraftState s) {

    // convert state to geodetic coordinates
    final GeodeticPoint gp = body.transform(s.getPVCoordinates().getPosition(),
        s.getFrame(), s.getDate());
    
    // point latitude
    final double latitude = gp.getLatitude();

    // inside or outside latitude range
    return sign * FastMath.signum(latitude - fromLatitude)
        * (toLatitude - latitude);

  }

while for the LongiutudeRangeCrossingDetector, if we have range definition as double fromLongitude and double toLongitude, we can ensure continuity converting (naivly) the negative angles as

private double ensureContinuitiyNegativeLongitude(double longitude) {
   if (longitude < 0) {
     return longitude + 2 * FastMath.PI;
   } else {
      return longitude;
   }
}

so to have for negative longitude (in degrees for simplicity) -174 + 360 = 186, then the g function is the same as the latitude case:

public double g(final SpacecraftState s) {

    // convert state to geodetic coordinates
    final GeodeticPoint gp = body.transform(s.getPVCoordinates().getPosition(),
        s.getFrame(), s.getDate());
    
    // point longitude
    final double longitude = ensureContinuitiyNegativeLongitude(gp.getLongitude());

    // inside or outside longitude range
    return sign * FastMath.signum(longitude - fromLongitude)
        * (toLongitude - longitude);

Just did some simple tests. I will see more cases if it works properly.

Thanks in any case for the suggestion.
Kindly
Alberto

Thanks for sharing your solution, which is just right, that’s the great advantage of the EventDetector interface, which makes it easy to build :wink: a specialized detector to suit your needs.

For the record, assuming fromLatitude < toLatitude, the equivalent of your LatitudeRangeCrossingDetector can be obtained by combining 2 LatitudeCrossingDetectors:

LatitudeCrossingDetector fromLatDetector = new LatitudeCrossingDetector(earthShape, fromLatitude);
LatitudeCrossingDetector toLatDetector = new LatitudeCrossingDetector(earthShape, toLatitude);
EventDetector latRangeDetector = BooleanDetector.andCombine(fromLatDetector, BooleanDetector.notCombine(toLatDetector));

Thus, the g function of the combined detector is zero at toLatitude and fromLatitude, positive in the range fromLatitude to toLatitude and negative outside.

But the BooleanDetector is not suitable for the LongitudeCrossingDetector, as its increasing flag is not usable in practice. This is where the EventEnablingPredicateFilter comes in handy :slight_smile: We then need to implement the EnablingPredicate interface to filter out events occurring outside the [fromLongitude, toLongitude] interval, assuming again fromLongitude < toLongitude, as in the following example:

class LongitudeFilter implements EnablingPredicate {
    private OneAxisEllipsoid earth;
    private final double from;
    private final double to;

    public LongitudeFilter(OneAxisEllipsoid eartShape, double fromLongitude, double toLongitude) {
            earth = earthShape;
            from = fromLongitude;
            to = toLongitude;
    }

    @Override
    public boolean eventIsEnabled(SpacecraftState s, EventDetector d, double g) {
        double longitude = earth.transform(s.getPVCoordinates().getPosition(),
                                           s.getFrame(), s.getDate()).getLongitude();
        return from <= longitude && longitude <= to;
    }
}

You can then write the following new detector, which will detect the passage between fromLatitude and toLatitude when the longitude is between fromLongitude and toLongitude:

LongitudeFilter predicate = new LongitudeFilter(eartShape, fromLongitude, toLongitude);
EventDetector LatLonRangeDetector = new EventEnablingPredicateFilter(latRangeDetector, predicate);

The advantage of using an EventPredicate, rather than combining detectors, is that it speeds up detection, but it also has the disadvantage of potentially missing events if the maxCheck parameter isn’t set correctly.

Note: all snippets have been written on the fly, please check before use…

Thanks Pascal!
now I have good insights in using the EventEnablingPredicateFilter, it is basically an extension for Boolean, but for your own g function, and not combining 2 detectors. All clear.
I will propose the two crossing detectors in the forge if they are useful.
Thanks
Alberto