auto-sync: 2026-04-26 11:30:01

This commit is contained in:
Stream
2026-04-26 11:30:02 +03:00
parent 3eb4e487df
commit f9defca0c1

View File

@@ -0,0 +1,178 @@
-- ============================================================
-- ADS-B Track Quality Metrics
-- Замени: 56.121, 37.216 — координаты антенны
-- Замени: 150 — радиус ЗУП в км (начни с 150)
-- ============================================================
-- ============================================================
-- 0. Вспомогательная функция: расстояние от точки до антенны (км)
-- Используется PostGIS ST_Distance с geography
-- ============================================================
-- ============================================================
-- 1. ГИСТОГРАММА РАССТОЯНИЙ — для определения ЗУП
-- Показывает плотность точек по кольцам от антенны
-- ============================================================
WITH antenna AS (
SELECT ST_SetSRID(ST_MakePoint(37.216, 56.121), 4326)::geography AS pt
),
point_distances AS (
SELECT
tp.track_id,
ST_Distance(tp.geom::geography, a.pt) / 1000 AS dist_km
FROM fr24.track_points tp, antenna a
WHERE tp.observed_at >= NOW() - INTERVAL '7 days'
)
SELECT
(dist_km / 10)::int * 10 AS dist_bucket_km, -- кольца по 10 км
COUNT(*) AS point_count,
COUNT(DISTINCT track_id) AS track_count
FROM point_distances
GROUP BY dist_bucket_km
ORDER BY dist_bucket_km;
-- ============================================================
-- 2. МЕТРИКИ ПО ТРЕКАМ (M1M4) за последние 7 дней
-- Только треки с точками в ЗУП
-- ============================================================
WITH antenna AS (
SELECT ST_SetSRID(ST_MakePoint(37.216, 56.121), 4326)::geography AS pt
),
-- Точки с расстоянием от антенны
pts AS (
SELECT
tp.track_id,
tp.track_point_id,
tp.observed_at,
tp.geom,
tp.ground_speed_kt,
tp.heading_deg,
ST_Distance(tp.geom::geography, a.pt) / 1000 AS dist_km
FROM fr24.track_points tp, antenna a
WHERE tp.observed_at >= NOW() - INTERVAL '7 days'
),
-- Только точки в ЗУП
zup_pts AS (
SELECT * FROM pts WHERE dist_km <= 150
),
-- Последовательные пары точек для M1/M2/скорость
pairs AS (
SELECT
track_id,
observed_at,
dist_km,
ground_speed_kt,
-- расстояние до следующей точки (м)
ST_Distance(
geom::geography,
LEAD(geom) OVER (PARTITION BY track_id ORDER BY observed_at)::geography
) AS step_dist_m,
-- временной интервал до следующей точки (сек)
EXTRACT(EPOCH FROM (
LEAD(observed_at) OVER (PARTITION BY track_id ORDER BY observed_at) - observed_at
)) AS step_dt_sec
FROM zup_pts
),
-- Производная скорость между точками
pairs_with_speed AS (
SELECT *,
CASE WHEN step_dt_sec > 0 THEN step_dist_m / step_dt_sec ELSE NULL END AS computed_speed_ms
FROM pairs
WHERE step_dist_m IS NOT NULL AND step_dt_sec IS NOT NULL
),
-- Агрегация по треку
track_metrics AS (
SELECT
track_id,
-- M3: кол-во точек в ЗУП
COUNT(*) AS n_zup,
-- M1: медианное расстояние между точками
PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY step_dist_m) AS median_step_m,
MAX(step_dist_m) AS max_step_m,
-- M2: медианный интервал между точками
PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY step_dt_sec) AS median_dt_sec,
MAX(step_dt_sec) AS max_gap_sec,
-- gap rate: доля интервалов > 30 сек
ROUND(
SUM(CASE WHEN step_dt_sec > 30 THEN 1 ELSE 0 END)::numeric
/ NULLIF(COUNT(*), 0), 3
) AS gap_rate,
-- M4: outlier ratio — вычисленная скорость > 350 м/с (Mach 1)
ROUND(
SUM(CASE WHEN computed_speed_ms > 350 THEN 1 ELSE 0 END)::numeric
/ NULLIF(COUNT(*), 0), 3
) AS outlier_ratio,
MIN(dist_km) AS min_dist_km,
MAX(dist_km) AS max_dist_km
FROM pairs_with_speed
GROUP BY track_id
HAVING COUNT(*) >= 5 -- минимальный значимый трек
),
-- ============================================================
-- 3. TRACK QUALITY SCORE (TQS)
-- TQS = 0.3*(1-gap_rate) + 0.3*(1-outlier_ratio)
-- + 0.2*min(n_zup/20, 1) + 0.2*(coverage_ratio ≈ 1 - gap_rate)
-- ============================================================
tqs AS (
SELECT
track_id,
n_zup,
median_step_m,
median_dt_sec,
max_gap_sec,
gap_rate,
outlier_ratio,
min_dist_km,
max_dist_km,
ROUND(
0.3 * (1 - COALESCE(gap_rate, 0))
+ 0.3 * (1 - COALESCE(outlier_ratio, 0))
+ 0.2 * LEAST(n_zup::numeric / 20, 1)
+ 0.2 * (1 - COALESCE(gap_rate, 0)) -- coverage ≈ 1 - gap_rate
, 3) AS tqs
FROM track_metrics
)
SELECT * FROM tqs
ORDER BY tqs DESC;
-- ============================================================
-- 4. RECEPTION HEALTH INDEX (RHI) — итоговый по дням
-- Мониторинг деградации антенны/приёмника во времени
-- ============================================================
WITH antenna AS (
SELECT ST_SetSRID(ST_MakePoint(37.216, 56.121), 4326)::geography AS pt
),
daily AS (
SELECT
DATE(tp.observed_at) AS day,
COUNT(DISTINCT tp.track_id) AS tracks_total,
COUNT(*) AS points_total,
-- точки в ЗУП
COUNT(*) FILTER (
WHERE ST_Distance(tp.geom::geography, a.pt) / 1000 <= 150
) AS points_in_zup,
COUNT(DISTINCT tp.track_id) FILTER (
WHERE ST_Distance(tp.geom::geography, a.pt) / 1000 <= 150
) AS tracks_in_zup
FROM fr24.track_points tp, antenna a
WHERE tp.observed_at >= NOW() - INTERVAL '14 days'
GROUP BY DATE(tp.observed_at)
)
SELECT
day,
tracks_total,
tracks_in_zup,
points_total,
points_in_zup,
ROUND(points_in_zup::numeric / NULLIF(points_total, 0), 3) AS zup_ratio,
-- RHI: нормализуем tracks_in_zup на медиану по периоду
ROUND(
tracks_in_zup::numeric
/ NULLIF(AVG(tracks_in_zup) OVER (), 0)
, 3) AS rhi
FROM daily
ORDER BY day;