6 custom types (tle, eci_position, geodetic, topocentric, observer, pass_event), 67 SQL functions, 2 operators (&&, <->), and a GiST operator class for altitude-band indexing. Wraps Bill Gray's sat_code for SGP4/SDP4 propagation with WGS-72 constants for propagation and WGS-84 for coordinate output. All 5 regression tests pass on PG 18.
92 lines
3.3 KiB
Plaintext
92 lines
3.3 KiB
Plaintext
-- Test pass prediction functions
|
|
CREATE EXTENSION IF NOT EXISTS pg_orbit;
|
|
NOTICE: extension "pg_orbit" already exists, skipping
|
|
-- Predict ISS passes over Boulder in 24-hour window
|
|
WITH iss AS (
|
|
SELECT '1 25544U 98067A 24001.50000000 .00016717 00000-0 10270-3 0 9025
|
|
2 25544 51.6400 208.9163 0006703 30.1694 61.7520 15.50100486 00001'::tle AS t
|
|
)
|
|
SELECT count(*) AS pass_count
|
|
FROM iss, predict_passes(t, '40.0N 105.3W 1655m'::observer,
|
|
'2024-01-01 12:00:00+00', '2024-01-02 12:00:00+00');
|
|
pass_count
|
|
------------
|
|
7
|
|
(1 row)
|
|
|
|
-- Pass details: max elevation should be positive, duration reasonable
|
|
WITH iss AS (
|
|
SELECT '1 25544U 98067A 24001.50000000 .00016717 00000-0 10270-3 0 9025
|
|
2 25544 51.6400 208.9163 0006703 30.1694 61.7520 15.50100486 00001'::tle AS t
|
|
)
|
|
SELECT
|
|
round(pass_max_elevation(p)::numeric, 1) AS max_el,
|
|
pass_aos_time(p) < pass_max_el_time(p) AS aos_before_max,
|
|
pass_max_el_time(p) < pass_los_time(p) AS max_before_los,
|
|
pass_aos_azimuth(p) >= 0 AND pass_aos_azimuth(p) <= 360 AS az_valid,
|
|
extract(epoch from pass_duration(p)) BETWEEN 60 AND 900 AS duration_ok
|
|
FROM iss, predict_passes(t, '40.0N 105.3W 1655m'::observer,
|
|
'2024-01-01 12:00:00+00', '2024-01-02 12:00:00+00') AS p
|
|
LIMIT 3;
|
|
max_el | aos_before_max | max_before_los | az_valid | duration_ok
|
|
--------+----------------+----------------+----------+-------------
|
|
3.3 | t | t | t | t
|
|
46.4 | t | t | t | t
|
|
24.4 | t | t | t | t
|
|
(3 rows)
|
|
|
|
-- next_pass returns same first pass as predict_passes
|
|
WITH iss AS (
|
|
SELECT '1 25544U 98067A 24001.50000000 .00016717 00000-0 10270-3 0 9025
|
|
2 25544 51.6400 208.9163 0006703 30.1694 61.7520 15.50100486 00001'::tle AS t
|
|
),
|
|
np AS (
|
|
SELECT next_pass(t, '40.0N 105.3W 1655m'::observer, '2024-01-01 12:00:00+00') AS p FROM iss
|
|
),
|
|
pp AS (
|
|
SELECT p AS pass FROM iss, predict_passes(t, '40.0N 105.3W 1655m'::observer,
|
|
'2024-01-01 12:00:00+00', '2024-01-02 12:00:00+00') AS p
|
|
LIMIT 1
|
|
)
|
|
SELECT
|
|
pass_aos_time(np.p) = pass_aos_time(pp.pass) AS same_aos
|
|
FROM np, pp;
|
|
same_aos
|
|
----------
|
|
t
|
|
(1 row)
|
|
|
|
-- pass_visible should be true for ISS over Boulder in a 24h window
|
|
WITH iss AS (
|
|
SELECT '1 25544U 98067A 24001.50000000 .00016717 00000-0 10270-3 0 9025
|
|
2 25544 51.6400 208.9163 0006703 30.1694 61.7520 15.50100486 00001'::tle AS t
|
|
)
|
|
SELECT pass_visible(t, '40.0N 105.3W 1655m'::observer,
|
|
'2024-01-01 12:00:00+00', '2024-01-02 12:00:00+00') AS visible
|
|
FROM iss;
|
|
visible
|
|
---------
|
|
t
|
|
(1 row)
|
|
|
|
-- Minimum elevation filter should reduce pass count
|
|
WITH iss AS (
|
|
SELECT '1 25544U 98067A 24001.50000000 .00016717 00000-0 10270-3 0 9025
|
|
2 25544 51.6400 208.9163 0006703 30.1694 61.7520 15.50100486 00001'::tle AS t
|
|
),
|
|
all_passes AS (
|
|
SELECT count(*) AS total FROM iss, predict_passes(t, '40.0N 105.3W 1655m'::observer,
|
|
'2024-01-01 12:00:00+00', '2024-01-02 12:00:00+00')
|
|
),
|
|
high_passes AS (
|
|
SELECT count(*) AS high FROM iss, predict_passes(t, '40.0N 105.3W 1655m'::observer,
|
|
'2024-01-01 12:00:00+00', '2024-01-02 12:00:00+00', 30.0)
|
|
)
|
|
SELECT high <= total AS filter_works
|
|
FROM all_passes, high_passes;
|
|
filter_works
|
|
--------------
|
|
t
|
|
(1 row)
|
|
|