Ground Facility Gaps

We can compute the gaps between the accesses of a satellite to a set of ground facilities using the function ground_facility_gaps (see also Ground Facility Accesses):

SatelliteAnalysis.ground_facility_gaps — Function
ground_facility_gaps(orbp, args...; duration::Number = 86400, initial_time::Number = 0, kwargs...) -> DataFrame

Compute the gaps between the accesses of ground facilities. The arguments and keywords are the same as the ones used in the function ground_facility_accesses.

Notice that the gap analysis starts in the orbit propagator epoch plus initial_time and lasts for duration [s].

Returns

  • DataFrame: The function returns a DataFrame with three columns:
    • gap_beginning: Time of the gap beginning [UTC] encoded using DateTime.
    • gap_end: Time of the gap end [UTC] encoded using DateTime.
    • duration: Duration of the gap [time_unit].
    The unit of each column is stored in the DataFrame using metadata.

Extended Help

Throws

  • ArgumentError: If step is not positive, if duration is negative, or if time_unit is not :s, :min, or :h.

Examples

julia> using SatelliteAnalysis

julia> jd₀ = date_to_jd(2024, 1, 1);

julia> orb = KeplerianElements(
           jd₀,
           7130.982e3,
           0.001111,
           98.405 |> deg2rad,
           ltdn_to_raan(10.5, jd₀),
           π / 2,
           0
       );

julia> orbp = Propagators.init(Val(:J2), orb);

julia> ground_facility_gaps(orbp, (0, 0, 0))
3×3 DataFrame
 Row │ gap_beginning            gap_end                  duration 
     │ DateTime                 DateTime                 Float64  
─────┼────────────────────────────────────────────────────────────
   1 │ 2024-01-01T00:00:00      2024-01-01T10:20:03.136  37203.1
   2 │ 2024-01-01T10:30:02.971  2024-01-01T22:49:55.910  44392.9
   3 │ 2024-01-01T22:59:23.470  2024-01-02T00:00:00       3636.53

julia> ground_facility_gaps(orbp, (0, 0, 0); time_unit = :min)
3×3 DataFrame
 Row │ gap_beginning            gap_end                  duration 
     │ DateTime                 DateTime                 Float64  
─────┼────────────────────────────────────────────────────────────
   1 │ 2024-01-01T00:00:00      2024-01-01T10:20:03.136  620.052
   2 │ 2024-01-01T10:30:02.971  2024-01-01T22:49:55.910  739.882
   3 │ 2024-01-01T22:59:23.470  2024-01-02T00:00:00       60.6088
source

Examples

Let's compute the gaps of the Amazonia-1 satellite to the INPE's ground station at Cuiabá, MT, Brazil.

First, we need to define an orbit propagator. In this case, we will use the TLE obtained from CelesTrak when this documentation was written:

julia> tle_amz1 = tle"""
           AMAZONIA 1
           1 47699U 21015A   24008.13079366  .00000299  00000+0  10693-3 0  9994
           2 47699  98.4120  87.2350 0001570  92.1147 268.0222 14.40836963150331
           """TLE: AMAZONIA 1 (Epoch = 2024-01-08T03:08:20.572):
  ├─ Line 1
  │    Satellite Number         : 47699
  │    Classification           : U
  │    International Designator : 21015A
  │    Epoch Year               : 24
  │    Epoch Day                : 8.13079366
  │    ṅ/2                      : 2.99e-6 rev/day²
  │    n̈/6                      : 0.0 rev/day³
  │    B*                       : 0.00010693 1/ER
  │    Ephemeris Type           : 0
  │    Element Set Number       : 999
  └─ Line 2
       Inclination              : 98.412°
       RA of the Ascending Node : 87.235°
       Eccentricity             : 0.000157
       Arg. of Perigee          : 92.1147°
       Mean Anomaly             : 268.0222°
       Mean Motion              : 14.40836963 rev/day
       Revolution Number        : 15033
julia> orbp = Propagators.init(Val(:SGP4), tle_amz1)OrbitPropagatorSgp4{Float64, Float64} (SGP4 Orbit Propagator): ├─ Mean Elements │ Epoch : 2.46032e6 (2024-01-08T03:08:20.572) │ Semi-Major Axis : 7133.871818 km │ Mean Motion : 14.40836963 rev/day │ Eccentricity : 0.000157 │ Inclination : 98.412° │ RA of Asc. Node : 87.235° │ Arg. of Periapsis : 92.1147° │ Mean Anomaly : 268.0222° │ B* : 0.00010693 1/ER ├─ Constants │ R₀ : 6378.137 km │ XKE : 0.07436685317 er^(3/2)/min │ J₂ : 0.001082629989 │ J₃ : -2.53215306e-6 │ J₄ : -1.61098761e-6 └─ Propagation Last Instant : 0.0 min

Now, we can compute the gaps during one day considering the INPE's station at Cuiabá:

julia> ground_facility_gaps(
           orbp,
           [(-(15 + 33 / 60) |> deg2rad, -(56 + 04 / 60) |> deg2rad, 0)];
           duration = 1 * 86400,
           minimum_elevation = 5 |> deg2rad,
           time_unit = :min
       )4×3 DataFrame
 Row │ gap_beginning            gap_end                  duration 
     │ DateTime                 DateTime                 Float64  
─────┼────────────────────────────────────────────────────────────
   1 │ 2024-01-08T03:09:16.311  2024-01-08T13:56:48.099  647.53
   2 │ 2024-01-08T14:08:50.888  2024-01-08T15:39:28.281   90.6232
   3 │ 2024-01-08T15:43:47.366  2024-01-09T02:18:02.879  634.259
   4 │ 2024-01-09T02:30:08.933  2024-01-09T03:08:20.572   38.194

If we want to change the reference frames used in the analysis, we must provide a function f_eci_to_ecef(r_i, jd) that converts the vector r_i to the desired ECEF frame at the instant jd [Julian Day]. For example, let's use the more precise ITRF instead of the PEF (default):

julia> const eop = fetch_iers_eop(Val(:IAU1980));
julia> function f_eci_to_ecef(r_teme, jd) D_itrf_teme = r_eci_to_ecef(TEME(), ITRF(), jd, eop) r_itrf = D_itrf_teme * r_teme return r_itrf endf_eci_to_ecef (generic function with 1 method)
julia> ground_facility_gaps( orbp, [(-(15 + 33 / 60) |> deg2rad, -(56 + 04 / 60) |> deg2rad, 0)]; duration = 1 * 86400, f_eci_to_ecef = f_eci_to_ecef, minimum_elevation = 5 |> deg2rad, time_unit = :min )4×3 DataFrame Row │ gap_beginning gap_end duration │ DateTime DateTime Float64 ─────┼──────────────────────────────────────────────────────────── 1 │ 2024-01-08T03:09:16.312 2024-01-08T13:56:48.098 647.53 2 │ 2024-01-08T14:08:50.887 2024-01-08T15:39:28.281 90.6232 3 │ 2024-01-08T15:43:47.364 2024-01-09T02:18:02.879 634.259 4 │ 2024-01-09T02:30:08.935 2024-01-09T03:08:20.572 38.194

We can also perform analyses using multiple ground facilities. For example, let's find the accumulated gap if we consider the INPE's stations at Cuiabá, MT, Brazil, and Alcântara, MA, Brazil:

julia> ground_facility_gaps(
           orbp,
           [
               (-(15 + 33 / 60) |> deg2rad, -(56 + 04 / 60) |> deg2rad, 0)
               (-( 2 + 20 / 60) |> deg2rad, -(44 + 24 / 60) |> deg2rad, 0)
           ];
           duration = 1 * 86400,
           minimum_elevation = 5 |> deg2rad,
           time_unit = :min
       )6×3 DataFrame
 Row │ gap_beginning            gap_end                  duration 
     │ DateTime                 DateTime                 Float64  
─────┼────────────────────────────────────────────────────────────
   1 │ 2024-01-08T03:09:16.311  2024-01-08T12:16:55.777  547.658
   2 │ 2024-01-08T12:23:20.782  2024-01-08T13:52:44.135   89.3892
   3 │ 2024-01-08T14:08:50.888  2024-01-08T15:39:28.281   90.6232
   4 │ 2024-01-08T15:43:47.366  2024-01-09T00:43:23.473  539.602
   5 │ 2024-01-09T00:53:25.918  2024-01-09T02:18:02.879   84.616
   6 │ 2024-01-09T02:32:05.994  2024-01-09T03:08:20.572   36.243

By default, the algorithm computes the accumulated gap, i.e., it considers the gap active if neither station has visibility to the satellite. We can change this logic by overloading the function in the keyword parameter reduction. For example, let's compute the gap when the satellite does not have visibility to both ground stations at the same time:

julia> ground_facility_gaps(
           orbp,
           [
               (-(15 + 33 / 60) |> deg2rad, -(56 + 04 / 60) |> deg2rad, 0)
               (-( 2 + 20 / 60) |> deg2rad, -(44 + 24 / 60) |> deg2rad, 0)
           ];
           duration = 1 * 86400,
           minimum_elevation = 5 |> deg2rad,
           reduction = v -> (&)(v...),
           time_unit = :min
       )3×3 DataFrame
 Row │ gap_beginning            gap_end                  duration 
     │ DateTime                 DateTime                 Float64  
─────┼────────────────────────────────────────────────────────────
   1 │ 2024-01-08T03:08:20.572  2024-01-08T13:56:48.099   648.459
   2 │ 2024-01-08T14:04:29.601  2024-01-09T02:21:47.636   737.301
   3 │ 2024-01-09T02:30:08.933  2024-01-09T03:08:20.572    38.194