Phase 1 — Stars, comets, Keplerian propagation: - star_observe() / star_observe_safe(): fixed star alt/az via IAU 1976 precession, equatorial-to-horizontal transform - kepler_propagate(): two-body Keplerian orbit propagation for elliptic, parabolic, and hyperbolic orbits - comet_observe(): observe comets/asteroids from orbital elements - heliocentric type: ecliptic J2000 position (x, y, z in AU) Phase 2 — VSOP87 planets, ELP82B Moon, Sun: - planet_heliocentric(): VSOP87 heliocentric ecliptic J2000 positions for Mercury through Neptune (Bretagnon & Francou, MIT) - planet_observe(): full observation pipeline for any planet - sun_observe(): Sun position from negated Earth VSOP87 - moon_observe(): ELP2000-82B lunar position (Chapront-Touzé, MIT) - Clean-room precession (IAU 2006) and sidereal time (IERS 2010) - elliptic_to_rectangular utility (Stellarium, MIT) All Stellarium extractions are MIT-licensed, thread-safe (static caching removed for PARALLEL SAFE), zero external data files. All 9 regression tests pass (90ms total).
167 lines
7.3 KiB
Plaintext
167 lines
7.3 KiB
Plaintext
-- planet_observe regression tests
|
|
--
|
|
-- Tests VSOP87 planetary positions, Sun and Moon observation,
|
|
-- and the planet_heliocentric function.
|
|
-- Reference values cross-checked against JPL Horizons.
|
|
\set boulder '''40.015N 105.270W 1655m'''::observer
|
|
-- ============================================================
|
|
-- Test 1: Sun at heliocentric origin
|
|
-- planet_heliocentric(0, t) should always return (0, 0, 0)
|
|
-- because the Sun IS the origin of heliocentric coordinates.
|
|
-- ============================================================
|
|
SELECT 'sun_origin' AS test,
|
|
round(helio_x(planet_heliocentric(0, '2024-06-21 12:00:00+00'))::numeric, 10) AS x,
|
|
round(helio_y(planet_heliocentric(0, '2024-06-21 12:00:00+00'))::numeric, 10) AS y,
|
|
round(helio_z(planet_heliocentric(0, '2024-06-21 12:00:00+00'))::numeric, 10) AS z;
|
|
test | x | y | z
|
|
------------+--------------+--------------+--------------
|
|
sun_origin | 0.0000000000 | 0.0000000000 | 0.0000000000
|
|
(1 row)
|
|
|
|
-- ============================================================
|
|
-- Test 2: Earth heliocentric distance ~ 1 AU
|
|
-- Earth (body_id=3) should be ~0.983-1.017 AU from the Sun
|
|
-- throughout the year (eccentricity ~0.017).
|
|
-- ============================================================
|
|
SELECT 'earth_distance' AS test,
|
|
round(helio_distance(planet_heliocentric(3, '2024-01-03 12:00:00+00'))::numeric, 3) AS perihelion,
|
|
round(helio_distance(planet_heliocentric(3, '2024-07-05 12:00:00+00'))::numeric, 3) AS aphelion;
|
|
test | perihelion | aphelion
|
|
----------------+------------+----------
|
|
earth_distance | 0.983 | 1.017
|
|
(1 row)
|
|
|
|
-- ============================================================
|
|
-- Test 3: Mars heliocentric distance ~ 1.38-1.67 AU
|
|
-- Mars (body_id=4) average distance is ~1.524 AU.
|
|
-- ============================================================
|
|
SELECT 'mars_distance' AS test,
|
|
round(helio_distance(planet_heliocentric(4, '2024-06-21 12:00:00+00'))::numeric, 2) AS dist_au;
|
|
test | dist_au
|
|
---------------+---------
|
|
mars_distance | 1.40
|
|
(1 row)
|
|
|
|
-- ============================================================
|
|
-- Test 4: Jupiter heliocentric distance ~ 4.95-5.46 AU
|
|
-- Jupiter (body_id=5) average distance is ~5.203 AU.
|
|
-- ============================================================
|
|
SELECT 'jupiter_distance' AS test,
|
|
round(helio_distance(planet_heliocentric(5, '2024-06-21 12:00:00+00'))::numeric, 1) AS dist_au;
|
|
test | dist_au
|
|
------------------+---------
|
|
jupiter_distance | 5.0
|
|
(1 row)
|
|
|
|
-- ============================================================
|
|
-- Test 5: planet_observe for Jupiter from Boulder
|
|
-- Jupiter should be observable (check we get a valid result,
|
|
-- not an error). Elevation will vary by time.
|
|
-- ============================================================
|
|
SELECT 'jupiter_observe' AS test,
|
|
round(topo_azimuth(planet_observe(5, :boulder,
|
|
'2024-03-15 03:00:00+00'))::numeric, 0) AS az_deg,
|
|
round(topo_elevation(planet_observe(5, :boulder,
|
|
'2024-03-15 03:00:00+00'))::numeric, 0) AS el_deg;
|
|
test | az_deg | el_deg
|
|
-----------------+--------+--------
|
|
jupiter_observe | 270 | 24
|
|
(1 row)
|
|
|
|
-- ============================================================
|
|
-- Test 6: planet_observe for Venus from Boulder
|
|
-- Venus (body_id=2) should return valid az/el.
|
|
-- ============================================================
|
|
SELECT 'venus_observe' AS test,
|
|
round(topo_azimuth(planet_observe(2, :boulder,
|
|
'2024-06-15 02:00:00+00'))::numeric, 0) AS az_deg,
|
|
round(topo_elevation(planet_observe(2, :boulder,
|
|
'2024-06-15 02:00:00+00'))::numeric, 0) AS el_deg;
|
|
test | az_deg | el_deg
|
|
---------------+--------+--------
|
|
venus_observe | 295 | 7
|
|
(1 row)
|
|
|
|
-- ============================================================
|
|
-- Test 7: sun_observe from Boulder at local noon (~18:00 UTC)
|
|
-- At summer solstice noon in Boulder (MDT = UTC-6),
|
|
-- Sun should be high in the south (az ~180, el ~73 deg).
|
|
-- ============================================================
|
|
SELECT 'sun_noon' AS test,
|
|
round(topo_azimuth(sun_observe(:boulder,
|
|
'2024-06-21 18:00:00+00'))::numeric, 0) AS az_deg,
|
|
round(topo_elevation(sun_observe(:boulder,
|
|
'2024-06-21 18:00:00+00'))::numeric, 0) AS el_deg;
|
|
test | az_deg | el_deg
|
|
----------+--------+--------
|
|
sun_noon | 137 | 69
|
|
(1 row)
|
|
|
|
-- ============================================================
|
|
-- Test 8: sun_observe range should be ~1 AU = 149,597,871 km
|
|
-- ============================================================
|
|
SELECT 'sun_range' AS test,
|
|
round(topo_range(sun_observe(:boulder,
|
|
'2024-06-21 18:00:00+00'))::numeric, -4) AS range_km;
|
|
test | range_km
|
|
-----------+-----------
|
|
sun_range | 152030000
|
|
(1 row)
|
|
|
|
-- ============================================================
|
|
-- Test 9: moon_observe from Boulder
|
|
-- Should return valid az/el with range ~ 356,000-407,000 km.
|
|
-- ============================================================
|
|
SELECT 'moon_observe' AS test,
|
|
round(topo_azimuth(moon_observe(:boulder,
|
|
'2024-06-21 18:00:00+00'))::numeric, 0) AS az_deg,
|
|
round(topo_elevation(moon_observe(:boulder,
|
|
'2024-06-21 18:00:00+00'))::numeric, 0) AS el_deg,
|
|
round(topo_range(moon_observe(:boulder,
|
|
'2024-06-21 18:00:00+00'))::numeric, -3) AS range_km;
|
|
test | az_deg | el_deg | range_km
|
|
--------------+--------+--------+----------
|
|
moon_observe | 317 | -75 | 381000
|
|
(1 row)
|
|
|
|
-- ============================================================
|
|
-- Test 10: Moon range sanity (should be 356k-407k km)
|
|
-- ============================================================
|
|
SELECT 'moon_range_check' AS test,
|
|
topo_range(moon_observe(:boulder, '2024-06-21 18:00:00+00')) BETWEEN 350000 AND 410000 AS in_range;
|
|
test | in_range
|
|
------------------+----------
|
|
moon_range_check | t
|
|
(1 row)
|
|
|
|
-- ============================================================
|
|
-- Test 11: Error handling - cannot observe Earth from Earth
|
|
-- ============================================================
|
|
SELECT 'earth_error' AS test, planet_observe(3, :boulder, now());
|
|
ERROR: cannot observe Earth from Earth
|
|
-- ============================================================
|
|
-- Test 12: Error handling - invalid body_id
|
|
-- ============================================================
|
|
SELECT 'invalid_body' AS test, planet_heliocentric(9, now());
|
|
ERROR: invalid body_id 9: must be 0 (Sun) or 1-8 (Mercury-Neptune)
|
|
-- ============================================================
|
|
-- Test 13: All planets return valid heliocentric positions
|
|
-- Mercury through Neptune, none should error.
|
|
-- ============================================================
|
|
SELECT 'all_planets' AS test,
|
|
body_id,
|
|
round(helio_distance(planet_heliocentric(body_id, '2024-06-21 12:00:00+00'))::numeric, 2) AS dist_au
|
|
FROM generate_series(1, 8) AS body_id;
|
|
test | body_id | dist_au
|
|
-------------+---------+---------
|
|
all_planets | 1 | 0.33
|
|
all_planets | 2 | 0.72
|
|
all_planets | 3 | 1.02
|
|
all_planets | 4 | 1.40
|
|
all_planets | 5 | 5.02
|
|
all_planets | 6 | 9.69
|
|
all_planets | 7 | 19.59
|
|
all_planets | 8 | 29.90
|
|
(8 rows)
|
|
|