An existing product called PG Orbit (a mobile PostgreSQL client) creates a naming conflict. pg_orrery — a database orrery built from Keplerian parameters and SQL instead of brass gears. Build system: control file, Makefile, Dockerfile, docker init script. C source: GUC prefix, PG_FUNCTION_INFO_V1 symbol, header guards, ereport prefixes, comments across ~30 files including vendored SGP4. SQL: all 5 install/migration scripts, function name pg_orrery_ephemeris_info. Tests: 9 SQL suites, 8 expected outputs, standalone DE reader test. Documentation: CLAUDE.md, README.md, DESIGN.md, Starlight site infra, 36 MDX pages, OG renderer, logo SVG, docker-compose, agent threads. All 13 regression suites pass. Docs site builds (37 pages).
109 lines
3.4 KiB
Plaintext
109 lines
3.4 KiB
Plaintext
-- convenience functions requested by Craft (Astrolock) integration
|
|
CREATE EXTENSION IF NOT EXISTS pg_orrery;
|
|
NOTICE: extension "pg_orrery" already exists, skipping
|
|
-- tle_from_lines: two-argument constructor
|
|
SELECT tle_norad_id(tle_from_lines(
|
|
'1 25544U 98067A 24001.50000000 .00016717 00000-0 10270-3 0 9002',
|
|
'2 25544 51.6400 208.5000 0007417 68.5000 291.5000 15.49560000100001'
|
|
)) AS iss_norad_id;
|
|
iss_norad_id
|
|
--------------
|
|
25544
|
|
(1 row)
|
|
|
|
-- observer_from_geodetic: numeric constructor
|
|
SELECT observer_from_geodetic(40.0, -105.3, 1655);
|
|
observer_from_geodetic
|
|
--------------------------
|
|
40.0000N 105.3000W 1655m
|
|
(1 row)
|
|
|
|
-- observer_from_geodetic: default altitude = 0
|
|
SELECT observer_from_geodetic(40.0, -105.3);
|
|
observer_from_geodetic
|
|
------------------------
|
|
40.0000N 105.3000W 0m
|
|
(1 row)
|
|
|
|
-- sgp4_propagate_safe: normal propagation returns result
|
|
SELECT (sgp4_propagate_safe(
|
|
'1 25544U 98067A 24001.50000000 .00016717 00000-0 10270-3 0 9002
|
|
2 25544 51.6400 208.5000 0007417 68.5000 291.5000 15.49560000100001'::tle,
|
|
'2024-01-01 12:00:00+00'::timestamptz
|
|
) IS NOT NULL) AS safe_returns_result;
|
|
safe_returns_result
|
|
---------------------
|
|
t
|
|
(1 row)
|
|
|
|
-- sgp4_propagate_safe: diverged orbit returns NULL
|
|
SELECT sgp4_propagate_safe(
|
|
'1 25544U 98067A 24001.50000000 .00016717 00000-0 10270-3 0 9002
|
|
2 25544 51.6400 208.5000 0007417 68.5000 291.5000 15.49560000100001'::tle,
|
|
'2124-01-01 12:00:00+00'::timestamptz
|
|
) IS NULL AS safe_null_on_diverge;
|
|
safe_null_on_diverge
|
|
----------------------
|
|
t
|
|
(1 row)
|
|
|
|
-- observe: single-call propagate + topocentric
|
|
SELECT observe(
|
|
'1 25544U 98067A 24001.50000000 .00016717 00000-0 10270-3 0 9002
|
|
2 25544 51.6400 208.5000 0007417 68.5000 291.5000 15.49560000100001'::tle,
|
|
observer_from_geodetic(40.0, -105.3, 1655),
|
|
'2024-01-01 12:00:00+00'::timestamptz
|
|
);
|
|
observe
|
|
----------------------------------------
|
|
(134.5927,-21.2008,5580.842,-2.373498)
|
|
(1 row)
|
|
|
|
-- observe_safe: returns NULL on diverged orbit
|
|
SELECT observe_safe(
|
|
'1 25544U 98067A 24001.50000000 .00016717 00000-0 10270-3 0 9002
|
|
2 25544 51.6400 208.5000 0007417 68.5000 291.5000 15.49560000100001'::tle,
|
|
'40.0N 105.3W 1655m'::observer,
|
|
'2124-01-01 12:00:00+00'::timestamptz
|
|
) IS NULL AS observe_safe_null;
|
|
observe_safe_null
|
|
-------------------
|
|
t
|
|
(1 row)
|
|
|
|
-- observe matches manual eci_to_topocentric pipeline
|
|
-- (verify observe() produces same result as the two-step approach)
|
|
WITH propagated AS (
|
|
SELECT sgp4_propagate(
|
|
'1 25544U 98067A 24001.50000000 .00016717 00000-0 10270-3 0 9002
|
|
2 25544 51.6400 208.5000 0007417 68.5000 291.5000 15.49560000100001'::tle,
|
|
'2024-01-01 12:00:00+00'::timestamptz
|
|
) AS eci
|
|
),
|
|
manual AS (
|
|
SELECT eci_to_topocentric(
|
|
eci,
|
|
'40.0N 105.3W 1655m'::observer,
|
|
'2024-01-01 12:00:00+00'::timestamptz
|
|
) AS topo
|
|
FROM propagated
|
|
),
|
|
single_call AS (
|
|
SELECT observe(
|
|
'1 25544U 98067A 24001.50000000 .00016717 00000-0 10270-3 0 9002
|
|
2 25544 51.6400 208.5000 0007417 68.5000 291.5000 15.49560000100001'::tle,
|
|
'40.0N 105.3W 1655m'::observer,
|
|
'2024-01-01 12:00:00+00'::timestamptz
|
|
) AS topo
|
|
)
|
|
SELECT
|
|
topo_azimuth(m.topo) = topo_azimuth(s.topo) AS az_match,
|
|
topo_elevation(m.topo) = topo_elevation(s.topo) AS el_match,
|
|
topo_range(m.topo) = topo_range(s.topo) AS range_match
|
|
FROM manual m, single_call s;
|
|
az_match | el_match | range_match
|
|
----------+----------+-------------
|
|
t | t | t
|
|
(1 row)
|
|
|