pg_orrery/sql/pg_orrery--0.3.0--0.4.0.sql
Ryan Malloy 87ab81e7d0 Add observation-to-TLE fitting (orbit determination) for v0.4.0
Batch weighted least-squares differential correction using equinoctial
elements, LAPACK dgelss_() for SVD solve, vendored SGP4/SDP4 as the
propagation engine. Per Vallado & Crawford (2008) AIAA 2008-6770.

New SQL functions:
  - tle_from_eci(): fit TLE from ECI position/velocity ephemeris
  - tle_from_topocentric(): fit TLE from az/el/range observations
  - tle_fit_residuals(): per-observation position residuals diagnostic

Solver features: 6-state (orbital) or 7-state (+ B*) fitting,
equinoctial elements for singularity-free optimization, tiered step
limiting, Brouwer/Kozai Newton-Raphson conversion, auto initial guess
from first ECI observation when no seed TLE provided.

Tested: 8 regression tests (LEO/MEO/near-circular round-trips,
B* recovery, topocentric, seedless, error handling, diagnostics),
67 standalone math unit tests, all 14 suites pass.
2026-02-17 15:44:48 -07:00

65 lines
2.4 KiB
SQL

-- pg_orrery 0.3.0 -> 0.4.0 migration
--
-- Adds observation-to-TLE fitting via batch weighted least-squares
-- differential correction (Vallado & Crawford 2008, AIAA 2008-6770).
-- Uses equinoctial elements internally for singularity-free optimization.
-- LAPACK dgelss_() for SVD solve.
-- ============================================================
-- Phase 6: Orbit determination (TLE fitting from observations)
-- ============================================================
-- Fit TLE from ECI position/velocity ephemeris
CREATE FUNCTION tle_from_eci(
positions eci_position[],
times timestamptz[],
seed tle DEFAULT NULL,
fit_bstar boolean DEFAULT false,
max_iter int4 DEFAULT 15,
OUT fitted_tle tle,
OUT iterations int4,
OUT rms_final float8,
OUT rms_initial float8,
OUT status text
) RETURNS RECORD
AS 'MODULE_PATHNAME' LANGUAGE C STABLE PARALLEL SAFE;
COMMENT ON FUNCTION tle_from_eci(eci_position[], timestamptz[], tle, boolean, int4) IS
'Fit a TLE from ECI position/velocity observations via differential correction. Returns fitted TLE, iteration count, RMS residuals, and convergence status. Requires >= 6 observations.';
-- Fit TLE from topocentric observations (az/el/range)
CREATE FUNCTION tle_from_topocentric(
observations topocentric[],
times timestamptz[],
obs observer,
seed tle DEFAULT NULL,
fit_bstar boolean DEFAULT false,
max_iter int4 DEFAULT 15,
OUT fitted_tle tle,
OUT iterations int4,
OUT rms_final float8,
OUT rms_initial float8,
OUT status text
) RETURNS RECORD
AS 'MODULE_PATHNAME' LANGUAGE C STABLE PARALLEL SAFE;
COMMENT ON FUNCTION tle_from_topocentric(topocentric[], timestamptz[], observer, tle, boolean, int4) IS
'Fit a TLE from topocentric (az/el/range) observations via differential correction. Requires seed TLE and >= 6 observations.';
-- Per-observation residuals diagnostic
CREATE FUNCTION tle_fit_residuals(
fitted tle,
positions eci_position[],
times timestamptz[]
) RETURNS TABLE (
t timestamptz,
dx_km float8,
dy_km float8,
dz_km float8,
pos_err_km float8
)
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
COMMENT ON FUNCTION tle_fit_residuals(tle, eci_position[], timestamptz[]) IS
'Compute per-observation position residuals (km) between a TLE and ECI observations. Useful for fit quality assessment.';