Range rate: topocentric residuals now include an optional 4th component (dot(Δr, v_ecef) / |Δr|) with OD_RR_SCALE=10.0 for unit balancing. Controlled via fit_range_rate parameter on tle_from_topocentric(). Weighted observations: per-observation weights applied as √w scaling to both residuals and Jacobian rows, producing the weighted normal equations H'WH without explicit W construction. Weights parameter added to tle_from_eci, tle_from_topocentric, and tle_from_angles. Gauss angles-only IOD: Vallado Algorithm 52 implementation for seed-free orbit recovery from 3+ RA/Dec observations. New RA/Dec residual function with cos(dec) scaling and wrap-around handling. New tle_from_angles() and tle_from_angles_multi() SQL functions accepting RA in hours [0,24), Dec in degrees [-90,90]. New standalone test suite: test_od_gauss (17 assertions). New regression tests: Tests 18-25 covering range rate, weights, angles-only with/without seed, and error cases.
115 lines
6.0 KiB
SQL
115 lines
6.0 KiB
SQL
-- pg_orrery 0.5.0 -> 0.6.0 migration
|
|
--
|
|
-- Adds range rate fitting, per-observation weights, and
|
|
-- angles-only orbit determination (Gauss method).
|
|
--
|
|
-- Range rate and weights change the input signatures of
|
|
-- tle_from_eci and tle_from_topocentric (added trailing
|
|
-- DEFAULT parameters), which requires DROP + re-CREATE.
|
|
|
|
-- ============================================================
|
|
-- Drop old OD function signatures
|
|
-- ============================================================
|
|
|
|
DROP FUNCTION IF EXISTS tle_from_eci(eci_position[], timestamptz[], tle, boolean, int4);
|
|
DROP FUNCTION IF EXISTS tle_from_topocentric(topocentric[], timestamptz[], observer, tle, boolean, int4);
|
|
DROP FUNCTION IF EXISTS tle_from_topocentric(topocentric[], timestamptz[], observer[], int4[], tle, boolean, int4);
|
|
|
|
-- ============================================================
|
|
-- Re-create with range_rate + weights parameters
|
|
-- ============================================================
|
|
|
|
-- Fit TLE from ECI position/velocity ephemeris
|
|
-- weights: per-observation weighting (NULL = uniform)
|
|
|
|
CREATE FUNCTION tle_from_eci(
|
|
positions eci_position[], times timestamptz[],
|
|
seed tle DEFAULT NULL, fit_bstar boolean DEFAULT false,
|
|
max_iter int4 DEFAULT 15,
|
|
weights float8[] DEFAULT NULL,
|
|
OUT fitted_tle tle, OUT iterations int4,
|
|
OUT rms_final float8, OUT rms_initial float8, OUT status text,
|
|
OUT condition_number float8, OUT covariance float8[], OUT nstate int4
|
|
) RETURNS RECORD
|
|
AS 'MODULE_PATHNAME' LANGUAGE C STABLE PARALLEL SAFE;
|
|
COMMENT ON FUNCTION tle_from_eci(eci_position[], timestamptz[], tle, boolean, int4, float8[]) IS
|
|
'Fit a TLE from ECI position/velocity observations via differential correction. Optional per-observation weights for heterogeneous sensor fusion. Returns fitted TLE, RMS residuals, convergence status, condition number, and formal covariance matrix.';
|
|
|
|
-- Fit TLE from topocentric observations (az/el/range) — single observer
|
|
-- fit_range_rate: include range_rate as 4th residual component
|
|
-- weights: per-observation weighting (NULL = uniform)
|
|
|
|
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,
|
|
fit_range_rate boolean DEFAULT false,
|
|
weights float8[] DEFAULT NULL,
|
|
OUT fitted_tle tle, OUT iterations int4,
|
|
OUT rms_final float8, OUT rms_initial float8, OUT status text,
|
|
OUT condition_number float8, OUT covariance float8[], OUT nstate int4
|
|
) RETURNS RECORD
|
|
AS 'MODULE_PATHNAME' LANGUAGE C STABLE PARALLEL SAFE;
|
|
COMMENT ON FUNCTION tle_from_topocentric(topocentric[], timestamptz[], observer, tle, boolean, int4, boolean, float8[]) IS
|
|
'Fit a TLE from topocentric (az/el/range) observations via differential correction. Optional range_rate fitting and per-observation weights. Returns fitted TLE, RMS residuals, convergence status, condition number, and formal covariance matrix.';
|
|
|
|
-- Fit TLE from topocentric observations — multiple observers
|
|
|
|
CREATE FUNCTION tle_from_topocentric(
|
|
observations topocentric[], times timestamptz[],
|
|
observers observer[], observer_ids int4[],
|
|
seed tle DEFAULT NULL, fit_bstar boolean DEFAULT false,
|
|
max_iter int4 DEFAULT 15,
|
|
fit_range_rate boolean DEFAULT false,
|
|
weights float8[] DEFAULT NULL,
|
|
OUT fitted_tle tle, OUT iterations int4,
|
|
OUT rms_final float8, OUT rms_initial float8, OUT status text,
|
|
OUT condition_number float8, OUT covariance float8[], OUT nstate int4
|
|
) RETURNS RECORD
|
|
AS 'MODULE_PATHNAME', 'tle_from_topocentric_multi'
|
|
LANGUAGE C STABLE PARALLEL SAFE;
|
|
COMMENT ON FUNCTION tle_from_topocentric(topocentric[], timestamptz[], observer[], int4[], tle, boolean, int4, boolean, float8[]) IS
|
|
'Fit a TLE from topocentric observations collected by multiple ground stations. observer_ids[i] indexes into observers[]. Optional range_rate fitting and per-observation weights.';
|
|
|
|
-- ============================================================
|
|
-- Angles-only orbit determination (new in v0.6.0)
|
|
-- ============================================================
|
|
|
|
-- Fit TLE from RA/Dec observations — single observer
|
|
-- Uses Gauss method for initial orbit determination when no seed is provided.
|
|
-- RA in hours [0,24), Dec in degrees [-90,90] (matches star_observe convention).
|
|
-- RMS output is in radians for angles-only mode.
|
|
|
|
CREATE FUNCTION tle_from_angles(
|
|
ra_hours float8[], dec_degrees float8[],
|
|
times timestamptz[],
|
|
obs observer,
|
|
seed tle DEFAULT NULL, fit_bstar boolean DEFAULT false,
|
|
max_iter int4 DEFAULT 15,
|
|
weights float8[] DEFAULT NULL,
|
|
OUT fitted_tle tle, OUT iterations int4,
|
|
OUT rms_final float8, OUT rms_initial float8, OUT status text,
|
|
OUT condition_number float8, OUT covariance float8[], OUT nstate int4
|
|
) RETURNS RECORD AS 'MODULE_PATHNAME' LANGUAGE C STABLE PARALLEL SAFE;
|
|
COMMENT ON FUNCTION tle_from_angles(float8[], float8[], timestamptz[], observer, tle, boolean, int4, float8[]) IS
|
|
'Fit a TLE from angles-only (RA/Dec) observations via Gauss IOD + differential correction. RA in hours [0,24), Dec in degrees [-90,90]. RMS output in radians. Uses Gauss method for seed-free initial guess.';
|
|
|
|
-- Fit TLE from RA/Dec observations — multiple observers
|
|
|
|
CREATE FUNCTION tle_from_angles(
|
|
ra_hours float8[], dec_degrees float8[],
|
|
times timestamptz[],
|
|
observers observer[], observer_ids int4[],
|
|
seed tle DEFAULT NULL, fit_bstar boolean DEFAULT false,
|
|
max_iter int4 DEFAULT 15,
|
|
weights float8[] DEFAULT NULL,
|
|
OUT fitted_tle tle, OUT iterations int4,
|
|
OUT rms_final float8, OUT rms_initial float8, OUT status text,
|
|
OUT condition_number float8, OUT covariance float8[], OUT nstate int4
|
|
) RETURNS RECORD
|
|
AS 'MODULE_PATHNAME', 'tle_from_angles_multi'
|
|
LANGUAGE C STABLE PARALLEL SAFE;
|
|
COMMENT ON FUNCTION tle_from_angles(float8[], float8[], timestamptz[], observer[], int4[], tle, boolean, int4, float8[]) IS
|
|
'Fit a TLE from angles-only (RA/Dec) observations from multiple ground stations via Gauss IOD + differential correction.';
|