-- 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)