Elevation Detector questions


I am trying to make a simple case using Orekit.

Can I see the ISS from a point on earth (lat, lon, alt)?
I used the Elevation Detector and set a min elevation of 10 degrees (converted to rads).

lat, lon, alt
38.832772, -104.74755, 0

1 25544U 98067A 24138.72899227 .00027305 00000+0 46004-3 0 9997
2 25544 51.6391 106.3505 0003428 178.2016 240.1821 15.51476363453820
I got the TLE on May 17.

I get the following…

2024-05-17T04:04:04.1858721476782Z - 2024-05-17T04:10:02.58929252677478Z
2024-05-17T15:39:15.79438301392224Z - 2024-05-17T15:45:50.16509320176226Z
2024-05-18T03:14:04.17439860809941Z - 2024-05-18T03:20:39.53114979256139Z
2024-05-18T14:49:37.78214182136054Z - 2024-05-18T14:56:02.03920258961591Z
2024-05-19T14:00:39.09400263707869Z - 2024-05-19T14:05:27.5236060276826Z

I am comparing my results to what I get from

AS you can see the results are quite different. Any suggestion on what should I look for?
For reference, I used one of the tutorials as a guide (I used a TLE propagator instead of the propagator used in the tutorial.)

Thanks in advance!

It is hard to tell without looking at your code.
Here are the most common errors you should check for:

  • station coordinates units (Orekit uses radians for all angles)
  • minimum elevation (which here again should be in radians)
  • Earth frame (you should select ITRF when building the OneAxisEllipsoid representing Earth)
  • Earth Orientation Parameters (did you update your orekit-data folder)

Thanks for responding…

I am using radians when creating the geodetic point

      new GeodeticPoint(

In code I am using Math.toRadians(10).

FactoryManagedFrame fmf = FramesFactory.getITRF(IERSConventions.IERS_2010, true);
ReferenceEllipsoid re = ReferenceEllipsoid.getWgs84(getEarthFrame());
TopocentricFrame tcfAtSource = new TopocentricFrame(re, geodeticPoint, "");

I may have older data… I updated to latest available from IERS - IERS - Earth orientation data

This is how i am using the eventDetector

        TopocentricFrame tcfAtSource = groundStation.getTcfAtSource();
        EventDetector ed = new ElevationDetector(tcfAtSource)
            .withHandler((s, d, increasing) -> {
                return Action.CONTINUE;
        sat.propagate(start, stop);

After updating the eop data and fixing some code (I was doing double rad conversions). This is what I get now:

2024-05-17T01:59:48.33369686194533Z - 2024-05-17T02:05:52.99855811384577Z
2024-05-17T06:52:50.07128344450939Z - 2024-05-17T06:58:39.78008787496117Z
2024-05-17T23:34:42.89762461683409Z - 2024-05-17T23:38:39.32197332339723Z
2024-05-18T06:03:20.05460703159395Z - 2024-05-18T06:08:18.69306953543122Z
2024-05-19T00:19:52.86089622467114Z - 2024-05-19T00:26:32.55505647605776Z
2024-05-19T05:13:51.05969556803086Z - 2024-05-19T05:17:43.04614782505331Z

Still different.

Here, it seems you build an earth frame but use another one, returned by the getEarthFrame method. Does this method also return a rotating Earth frame?



FactoryManagedFrame fmf = FramesFactory.getITRF(IERSConventions.IERS_2010, true);
ReferenceEllipsoid re = ReferenceEllipsoid.getWgs84(fmf);
TopocentricFrame tcfAtSource = new TopocentricFrame(re, geodeticPoint, "");

I looked quickly at the site and it seems :

  • they output the hours depending on the browser time zone even if you specify something different in the location setting
  • they filter out results depending on daylight (station not visible because of sky luminosity)
  • they filter out results depending on ISS being lit or not

Filtering can be removed by selecting “all” in the “Passes to include” toggle

When these features are considered, results are much closer.

The dates on the site are a bit weird… when i set london time (Which i expect to be Z, UTC, GMT-0) the site shows UTC+1

With that information… I get all visibilities and get one hit that matches 07:03:20 to 07:08:18

18 May - 00:34:42 10° SSE 00:36:40 15° SE 00:38:39 10° E daylight
18 May - 02:09:44 10° WSW 02:13:00 53° NW 02:16:17 10° NE daylight
18 May - 03:48:31 10° NW 03:50:15 13° NNW 03:51:59 10° NNE visible
18 May - 07:03:20 10° NNW 07:05:49 19° NNE 07:08:18 10° ENE visible
18 May - 08:39:27 10° WNW 08:42:45 65° SW 08:46:00 10° SE night (unlit)

My code (which i presume is +0) gives me only one hit for the 18 and missing all the other that are supposed to happen.
Curiously enough, that time is one of the two the site considers as visible.

enter: 2024-05-18T06:03:20.05460703159395Z
exit:  2024-05-18T06:08:18.69306953543122Z

For the 19, i get 2 out of 4 matches (one is visible and the other one is daylight)

I am at a lost and not sure what could I possible be doing wrong.

Another thing you could do is reduce the maxCheckInterval to something like 10s. This interval is used to separate zero crossings before launching the accurate root finding algorithm. If you have a very short visibility, it means there are two crossings that are close to each other in time (satellite goes above and then below threshold elevation). The propagator is enforced to perform at least one check each maxCheckInterval (but it may perform more checks), so you can consider this value to be the length of a visibility interval you accept to miss because it is too short. For visibility, we often set it to 60 seconds because operationaly short visibilities are not useful to retrieve telemetry or send telecommands. But the visibilities here are larger than one minute so the problem is probably different.

I have modified the VisibilityCheck tutorial to use your TLE and your dates. You can look at visibility-check.patch to see these modifications. When I run the modified tutorial, I get the following results which matches the list you give above (beware of the 1 hour UTC offset which moved one visibility from may 17th at 23:34 to May 18th at 00:34)

2024-05-17T00:23:23.113 -> 2024-05-17T00:29:08.036
2024-05-17T01:59:48.333 -> 2024-05-17T02:05:52.998
2024-05-17T03:39:21.030 -> 2024-05-17T03:41:16.436
2024-05-17T05:17:37.069 -> 2024-05-17T05:18:49.042
2024-05-17T06:52:50.071 -> 2024-05-17T06:58:39.779
2024-05-17T08:29:23.869 -> 2024-05-17T08:35:25.651
2024-05-17T23:34:42.898 -> 2024-05-17T23:38:39.321
2024-05-18T01:09:44.711 -> 2024-05-18T01:16:17.472
2024-05-18T02:48:32.005 -> 2024-05-18T02:51:59.361
2024-05-18T06:03:20.054 -> 2024-05-18T06:08:18.692
2024-05-18T07:39:27.124 -> 2024-05-18T07:46:01.148
2024-05-19T00:19:52.860 -> 2024-05-19T00:26:32.555
2024-05-19T01:57:52.918 -> 2024-05-19T02:02:32.216
2024-05-19T05:13:51.059 -> 2024-05-19T05:17:43.045
2024-05-19T06:49:38.571 -> 2024-05-19T06:56:14.249
2024-05-19T08:27:52.699 -> 2024-05-19T08:30:29.324
2024-05-19T23:30:15.844 -> 2024-05-19T23:36:35.115
 Final state duration from initial date (s) : 259200.0


Yes… this is exactly the problem…
We were jumping the visibility window.

The trick is making smaller “jumps”, but that come with the price speed.
Is there a way to improve performance while making smaller jumps?

Yes it is possible, using AdaptableInterval for the max check. In the case of visibility, one should perhaps propose some algorithm based on global Keplerian motion around perigee for the satellite and Earth rotation rate to estimate an upper bound of relative velocity and then use that to have large intervals when the satellite is on the other side of the Earth and short intervals when closing the ground point.
Could you open an issue for that? I may give it a try to solve it.


Hi all,

I’ve been thinking about such AdaptabelInterval actually. I thought it could use the angular speed w.r.t. the station to devise a predicted entry or exit of visibility. It should work ok for near circular orbits, less so for elliptical ones. You probably have a better insight Luc.


1 Like

Hi @jrivera

Regarding Heavens-Above’s timezone, you can specify it with &tz=UT if you want to use UTC. This is a tricky one, probably caused by DST issues. I discovered this early on. And contacted them about it.


That would be amazing!

FWIW, we had a similar idea on a project I was working, but for whatever reason, we never got around to implement it.

We implemented a variable step scheme using the angular speed, than in most cases worked well, but it was not great, like you said, for some orbits.

What did worked for us, was to make constant big-ish steps (7 minutes, but we did play with larger and smaller steps, and 7 minutes was kind of a good spot for us) and determine the following given 2 states:

  1. state 1 was approaching and state 2 is approaching = you are still approaching, next
  2. state 1 was approaching and state 2 is inside the area, compute the entry
  3. state 1 was inside, state 2 is not approaching, you got out, compute the exit
  4. state 1 was approaching, state 2 is not approaching, you may have skip a window, use bisection (or another root finding alg) to determine if you really skipped a window.

this in combination with luc idea could provide a very fast visibility finder.

I tried and did not worked for me… The site bombs if do that… :confused:
Thanks for the information tho… I will keep trying…maybe the site is having issues now

Hi @jrivera ,

The site is ok. Please try this link. It’s fine for me. What is the difference?


1 Like

Well… that worked!
I think the page i had opened was expired or something! No clue… but thanks for this… is very usefull!

I have created issue 1407 for this, and then solved it in the develop branch.