pg_orrery/test/sql/pass_prediction.sql
Ryan Malloy 15a830dc40 Initial implementation of pg_orbit PostgreSQL extension
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.
2026-02-15 17:07:07 -07:00

69 lines
2.8 KiB
SQL

-- Test pass prediction functions
CREATE EXTENSION IF NOT EXISTS pg_orbit;
-- 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 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;
-- 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;
-- 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;
-- 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;