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));

what is this?i can’t find it,Is it local variable. Is it self-defining.

This question has been a bit long and I have forgotten a little, but it is certain that the point I was trying to make at the time was that simply using the “if” judgment would eliminate the “maximum” of those unreasonably negative numbers. The “trackingCircle” at the end should be a local variable that I defined to save the results.

I currently want to output the satellite visibility window of the ground station, and output the maximum elevation Angle of the ground station of each window. I see that you are doing the same thing in this post, so I want to quote it. The following is the program for the output of the visual window that I wrote. I found that trackingCircle is a local variable that needs to be defined by itself. Is the CircleEvent class well defined? Still need to define yourself.

//定义事件处理器,用于处理事件
final double maxcheck = 60.0;
final double threshold = 0.01;
final EventDetector sta1Visi =
new ElevationDetector(maxcheck, threshold, sta1Frame)
.withConstantElevation(minElevation)
.withHandler((s, detector, increasing) → {
if (increasing) {
System.out.println(“地面站名称: “+((ElevationDetector) detector).getTopocentricFrame().getName()
+” 跟踪开始时间: " + s.getDate()
+” 入境方位角: “+FastMath.toDegrees(((ElevationDetector) detector).getTopocentricFrame().getAzimuth(s.getPosition(), s.getFrame(), s.getDate()))
+” 入境俯仰角: "+FastMath.toDegrees(((ElevationDetector) detector).getTopocentricFrame().getElevation(s.getPosition(), s.getFrame(), s.getDate()))
);
} else {
System.out.println(“地面站名称: “+((ElevationDetector) detector).getTopocentricFrame().getName()
+” 跟踪结束时间: " + s.getDate()
+” 入境方位角: “+FastMath.toDegrees(((ElevationDetector) detector).getTopocentricFrame().getAzimuth(s.getPosition(), s.getFrame(), s.getDate()))
+” 入境俯仰角: "+FastMath.toDegrees(((ElevationDetector) detector).getTopocentricFrame().getElevation(s.getPosition(), s.getFrame(), s.getDate()))
);
}
return Action.CONTINUE; // Continue processing the event
});
// Add event to be detected
tlePropagator.addEventDetector(sta1Visi);
//最大仰角定制化检测器
ElevationExtremumDetector extremumDetector = new ElevationExtremumDetector(sta1Frame);
final EventSlopeFilter maxElevationDetector = new EventSlopeFilter(extremumDetector,
FilterType.TRIGGER_ONLY_DECREASING_EVENTS);
EventHandler handler = (s, detector, 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;
    };
    tlePropagator.addEventDetector(maxElevationDetector.withHandler(handler));

This is useless for you, please ignore it.
Cheers

Thank you for your reply. I’ll have a try it.

No thanks,Bro.
Sorry for the trouble I caused by posting my own code without “cleaning it up”.
It’s a pleasure to see my compatriots in the forum.
By the way, my English is poor, but, :stuck_out_tongue_winking_eye: which one do you prefer, ‘I’ll have a try’ or ‘I’ll try it’?

1 Like