How to get the maximum elevation for each visible arcs?

Hello everyone, I have just learned to use the NumericalPropagator and ElevationDetector to obtain the visible arcs of a satellite tracked by a ground station over a period of time. However, how do I record the maximum elevation and its occurrence time for each arc segment simultaneously? Moreover, my idea is to organize and display the tracking process based on tracking passes, using five time points: “start of tracking (just above 3 degrees), good signal (just above 5 degrees), time of reaching the maximum elevation (Max elevation value), signal deterioration (beginning to fall below 5 degrees), and end of tracking (beginning to fall below 3 degrees).” My initial thought is to add two ElevationDetector to a Propagator and then a setStepHandler to record every point where the Elevation is greater than 3 degrees. I’m wondering if there’s a better way to showcase the tracking process by combining these points with time filtering and comparison?

There is a dedicated event detector for that: ElevationExtremumDetector. So you just have to register one ElevationDetector for 3° elevation, one ElevationDetector for 5° elevation and one ElevationExtremumDetector to get the maximum elevation reached during the pass. There is no need for a step handler.

Thank you very much for your prompt reply. I tried it, and it seems I used it incorrectly, resulting in a negative number. It should be that I didn’t understand the usage of this class, but I couldn’t find a similar topic in the forum. It seems I’m also not familiar with the forum’s functions.

 // Create a detector to find the maximum elevation

        ElevationExtremumDetector extremumDetector = new ElevationExtremumDetector(sta1Frame);
        final EventSlopeFilter<ElevationExtremumDetector> maxElevationDetector =
                new EventSlopeFilter<ElevationExtremumDetector>(extremumDetector, FilterType.TRIGGER_ONLY_DECREASING_EVENTS);

        EventHandler handler = new EventHandler() {
            @Override
            public Action eventOccurred(SpacecraftState s, EventDetector detector, boolean increasing) {
     
                System.out.println("Elevation extremum event occurred at " + s.getDate());
                double elevation = extremumDetector.getElevation(s);
                System.out.println("Elevation at event: " + FastMath.toDegrees(elevation)
                        + " Degrees");
           
                return Action.CONTINUE;
            }

        };
        propagator.addEventDetector(maxElevationDetector.withHandler(handler));


It seems that the ordinary event detector is correct. Am I right?

 final double[] elevations  = {3.0, 5.0};
        final EventDetector[] sta1Visi = new EventDetector[elevations.length];
        final List<AbsoluteDate> visibilityTimes = new ArrayList<>();
        final List<Double> elevationValues = new ArrayList<>();
    
        for (int i = 0; i < elevations.length; i++) {
            double elevation = FastMath.toRadians(elevations[i]);
            sta1Visi[i] = new ElevationDetector(maxcheck, threshold, sta1Frame)
                    .withConstantElevation(elevation)
                    .withHandler((s, d, increasing) -> {
                        visibilityTimes.add(s.getDate());
                        elevationValues.add(((ElevationDetector) d).getMinElevation());
                        System.out.println("Visibility event at " + s.getDate() +
                                " with elevation "
                                + FastMath.toDegrees(((ElevationDetector) d).getMinElevation())
                                + " Degree "
                                + (increasing ? "In":"Out"));
                        return  Action.CONTINUE;
                    });
        }
        // Add event detectors to be detected
        for (EventDetector detector : sta1Visi) {
            propagator.addEventDetector(detector);
        }

Hi,

At least one problem is that you detect all local Maxima of elevation, event when the object is not visible (elevation too small, typically negative)
You could wrap your detector with EventEnablingPredicateFilter whose condition would be an elevation big enough.

Cheers,
Romain.

Hi, @houmingyang and all.

My current approach is a two-step process, with the first step being to search for the arcs that satisfy the conditions (e.g., above the min elevation, ElevationDetector, whether or not they are illuminated by the sun, EclipseDetector, whether or not the station is at night, GroundAtNightDetector, etc.), and then to search for the highest elevation angle one by one arc, ElevationExtremumDetector with EventSlopeFilter.

However, it does seem a bit of a waste of resources, which needs to be propagated again.

About the EventEnablingPredicateFilter suggested by @Serrof, I don’t know how to use it yet. I’ll try it later.

Hi, @Serrof and all
It( EventEnablingPredicateFilter) seem much more complex than EventSlopeFilter. Maybe I will try it next time :sweat_smile:.I have read two or three posts related to this class, but I still haven’t fully understood them. I think it’s possible to solve this problem by comparing the maximum elevation angle with the threshold elevation angle (because the maximum elevation angle is obviously greater than the threshold elevation angle). Can I use an simple “if” instead of a “visual filter”?

Blockquote
ElevationExtremumDetector extremumDetector = new ElevationExtremumDetector(sta1Frame);
final EventSlopeFilter maxElevationDetector =
new EventSlopeFilter
(extremumDetector, FilterType.TRIGGER_ONLY_DECREASING_EVENTS);

    EventHandler handler = new EventHandler() {
        @Override
        public Action eventOccurred(SpacecraftState s, EventDetector detector, boolean increasing) {

            double elevation = extremumDetector.getElevation(s);
            if (elevation<FastMath.toRadians(3.0)) {
                return Action.CONTINUE;
            }
            double azimuth = sta1Frame.getAzimuth(
                    s.getPVCoordinates().getPosition(),
                    s.getFrame(),
                    s.getDate()
            );

            String eventName = "Max";
            trackingCircle.addEvent(eventName,new CircleEvent(
                    s.getDate(),
                    FastMath.toDegrees(azimuth), FastMath.toDegrees(elevation)
            ));
            return Action.CONTINUE;
        }
    };

Thank you very much. My current solution is to add several detectors to a propagator, but to add an if judgment to the handler of the ElevationExtremumDetector.

 for (EventDetector detector : sta1Visi) {
            propagator.addEventDetector(detector);
        }
//...
 propagator.addEventDetector(maxElevationDetector.withHandler(handler));