-- Test TLE type: parsing, round-trip, accessors CREATE EXTENSION IF NOT EXISTS pg_orbit; -- Parse a valid ISS TLE 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 IS NOT NULL AS parse_ok; parse_ok ---------- t (1 row) -- Accessor functions 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 tle_norad_id(t) AS norad_id, round(tle_inclination(t)::numeric, 4) AS inc_deg, round(tle_eccentricity(t)::numeric, 7) AS ecc, round(tle_mean_motion(t)::numeric, 8) AS mm_rev_day, round(tle_period(t)::numeric, 2) AS period_min, round(tle_perigee(t)::numeric, 1) AS perigee_km, round(tle_apogee(t)::numeric, 1) AS apogee_km, tle_intl_desig(t) AS cospar FROM iss; norad_id | inc_deg | ecc | mm_rev_day | period_min | perigee_km | apogee_km | cospar ----------+---------+-----------+-------------+------------+------------+-----------+---------- 25544 | 51.6400 | 0.0006703 | 15.50100486 | 92.90 | 411.9 | 421.0 | 98067A (1 row) -- Observer type parsing SELECT '40.0N 105.3W 1655m'::observer IS NOT NULL AS observer_ok; observer_ok ------------- t (1 row) SELECT observer_lat('40.0N 105.3W 1655m'::observer) AS lat, observer_lon('40.0N 105.3W 1655m'::observer) AS lon; lat | lon -----+-------- 40 | -105.3 (1 row) -- ECI type parsing SELECT '(1000.0,2000.0,3000.0,1.0,2.0,3.0)'::eci_position IS NOT NULL AS eci_ok; eci_ok -------- t (1 row) SELECT eci_x('(1000.0,2000.0,3000.0,1.0,2.0,3.0)'::eci_position) AS x; x ------ 1000 (1 row) -- SGP4 propagation at epoch 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(eci_speed(sgp4_propagate(t, '2024-01-01 12:00:00+00'))::numeric, 2) AS speed_kms, round(eci_altitude(sgp4_propagate(t, '2024-01-01 12:00:00+00'))::numeric, 0) AS alt_km FROM iss; speed_kms | alt_km -----------+-------- 7.67 | 407 (1 row) -- Altitude overlap operator WITH sats 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 iss, '1 28874U 05038A 24001.50000000 .00000012 00000+0 00000+0 0 9993 2 28874 55.4408 300.3467 0117034 51.6543 309.5420 2.00557079 00006'::tle AS gps ) SELECT iss && iss AS same_overlap, iss && gps AS different_no_overlap FROM sats; same_overlap | different_no_overlap --------------+---------------------- t | f (1 row) -- Subsatellite point 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(geodetic_lat(subsatellite_point(t, '2024-01-01 12:00:00+00'))::numeric, 2) AS lat, round(geodetic_alt(subsatellite_point(t, '2024-01-01 12:00:00+00'))::numeric, 0) AS alt_km FROM iss; lat | alt_km -------+-------- 51.75 | 420 (1 row) -- GiST index creation CREATE TABLE test_sats (id serial, tle tle); INSERT INTO test_sats (tle) VALUES ( '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'); CREATE INDEX test_sats_gist ON test_sats USING gist (tle); SELECT count(*) FROM test_sats WHERE tle && ( '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); count ------- 1 (1 row) DROP TABLE test_sats;