Optimizing use case: Line of sight to largish number of ground points

I have a situation where I need to establish start/stop times for Line of Sight to multiple ground targets (1.6K) over a period over 30 days.
DEFAULT_MAXCHECK = 20 # Requirement

I experimented with the following:

  1. Add every target to the propagator as an elevation detector, then propagate for the full duration. Time 44 mins.
  2. Propagate for each target individually. Time 16 mins.
  3. Utilize python multiprocessing, encountered two problems; java objects cannot be serialized and JVM cannot be forket. I’ve not tired multiprocessing spawn as it requires a lot more work.

16 mins still seems kind of excessive, any ideas on how to speed this up?


assuming I understood your situation correctly, I would use a propagation without event detectors and with an EphemerisGenerator, then hooking all the detectors to the resulting BoundedPropagator. Using a BoundedPropagator should speed things up quite a bit…

One thing that has been added very recently (10 days ago) and is currently only in the develop branch is to use ElevationDetectionAdaptableIntervalFactory.getAdaptableInterval. This reduces the number of checks to perform as it uses a larger check interval when the satellite is far from the ground point and reduces the check interval when it comes closer.

Hi there,

The first question is do your events impact your propagation itself? If not you need to use an analytical propagator, so for numerical models use the IntegratedEphemeris as Glauco suggested.

Then as Luc said there is on the develop branch (soon to become release-12.1) an AdaptabelInterval that would avoid using a constant 20s step all the time.

Beyond that, it might be beneficial to combine your detectors into a single, custom one (or at least less than hundreds, which would need to handle multiple stations). It’s possible that the event detection doesn’t scale up very well with individual instances. In other words, might be better to divide and conquer. Ideally you should do some java profiling to see what’s best.


I tried the suggestion of @glauco.digenova. Basically:

prop = EcksteinHechlerPropagator(initial_orbit, ...)
gen = prop.getEphemerisGenerator()
prop.propagate(epoch, epoch.shiftedBy(DURATION))
prop2 = gen.getGeneratedEphemeris()
for target in targets:
    # Make target into elevationdetector (ed)...
prop2.propagate(epoch, epoch.shiftedBy(DURATION))

… alas, I could see no change in performance. Did I get it wrong?

@Serrof , no the events do not affect the propagation.

My targets are essentially a grid covering the globe. The aim is to be able to generate a heat map of acquisition opportunities.

Then maybe a step handler would be more appropriate than thousands of even handlers.

Hi @5tardust,

This is already an analytical propagator (no time-step and integration involved) so unfortunately you won’t get a large (or even any) increase in performance by using the IntegratedEphemeris.

This gives around 0.6s per propagation. For 30 days, I’m not sure you could get something better but maybe I’m wrong.

I suspect there must be some intertwining between events’ detection loops involved here, when the satellite enters in visibility of several ground points. I would be interested in running the code to see what happens.

Given your requirement, I think Luc’s answer is the best: you should use a step handler. The drawback is that the precision of your event detection will be limited by the step used (probably 20s in your case).


Maybe you could use something more involved.
If I understand well, you have a grid, so I assume it is mostly regular, say 5° step in longitude and 5° step in latitude (or any other values, the exact numbers is not the point). Such a grid would almost be 2.6k point. If instead of having one detector for each cell you use one detector for each longitude plus one detector for each latitude, you would get sightly more than 100 detectors so 26 times less. You would however need to set up a slightly more complex event handler, a single handler registered to all detectors and that would remember the last longitude crossing and last latitude crossing, hence it would precisely know when it leaves one grid cell and enter the next one, so you could update the time spent within each cell and create your heat map.

For you @MaximeJ :

performance2.py (8.3 KB)

A bit messy, because som boiler plate code was pulled from the bigger project, and various approaches where tested.

@luc A very interesting outline for a better solution. I’ll definitely consider it. I am however afraid that the requirements gives room for even finer grids to be defined covering for instance a country. I’ll have to think about this.

Thanks for all the speedy feedback.

1 Like

I guess you can even go much further in reducing the number of event detectors and still using very fine grids. In fact I think we can go down to one detector only (and this gives me an itch to scratch). The idea would be to have the detector managing a longitude grid given by a longitude range (we could be the full range from -180° to +180° or limited to an area) and a grid step size, and a latitude grid too. This detector would have several zeros in its g functions, corresponding to row or column changes. I am not sure yet if we could really combine both longitude and latitude or if we should have two detectors because crossing a cell corner would imply two sign changes and hence could be missed. We already have something similar with DateDetector which can have several triggering dates (it is even more complex as dates can be added on the fly, which would not be necessary here). The detectors would be triggered at cell changes, when the satellite flies over one cell. This is not exactly the same as being visible since you can be visible from a cell you don’t fly over, but for a heat map this could be sufficient information.

I kinda followed most of what you said, but sadly a heat-map of flyovers isn’t sufficient. The heat map is about what the satellite can possible observe with its sensors.Ultimately, this is not based upon pure line of sight, but factors such sensor FOV, distance, sun angle, and more. But line-of-sight is the first step.

The you may look at the TrackCorridor tutorial. Unfortunately there are no documentation for it, you just have the code.

The idea would be that if you have just one satellite (or a small number) but a large grid, most of the grid points will be out of sight, so they should not be computed unless the satellite sees them. So using a step handler to first have an idea of the ground region that is visible at each time step would help identifying the grid cells that are worth analyzing for elevation, range, lighting… Then you may update some counters on these cells only. As the satellite moves, it would update only a few hundreds of cells at each step rather than thousands. You may need to use the interpolation feature if you want to retrieve accurate times for cells near the border of the field of view, so maybe a general step handler would be better than a fixed step handler (but it puts the burden of finding the accurate interpolation dates to you).


Super thanks for the tip. I will look into it. Maybe this is an argument to implement Short circuit BooleanDetector (#475) · Issues · Orekit / Orekit · GitLab?