map and chainage calculation
This commit is contained in:
87
db/init.sql
87
db/init.sql
@@ -222,3 +222,90 @@ CREATE TABLE IF NOT EXISTS project_folders (
|
||||
folder TEXT NOT NULL, -- directory part of rel_path ('' = project root)
|
||||
PRIMARY KEY (project_id, folder)
|
||||
);
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- GPS pipeline (map view + chainage). A background sweep extracts each video's
|
||||
-- GPS track with exiftool (dashcam Doc{N} samples), one video at a time:
|
||||
-- gps_status: 'pending' → 'ok' (track stored) | 'none' (no GPS metadata)
|
||||
-- | 'error' (exiftool/mount failure, see gps_error)
|
||||
-- The RAW track is immutable once scanned; a kept "Viterbi" correction goes to
|
||||
-- gps_track_corrected (map/chainage prefer it, raw is never modified).
|
||||
-- Track format: [[lat, lon, t_s], ...] (t_s = seconds from first sample).
|
||||
-- ---------------------------------------------------------------------------
|
||||
ALTER TABLE videos ADD COLUMN IF NOT EXISTS gps_status TEXT NOT NULL DEFAULT 'pending';
|
||||
ALTER TABLE videos ADD COLUMN IF NOT EXISTS gps_track JSONB;
|
||||
ALTER TABLE videos ADD COLUMN IF NOT EXISTS gps_len_m DOUBLE PRECISION;
|
||||
ALTER TABLE videos ADD COLUMN IF NOT EXISTS gps_error TEXT;
|
||||
ALTER TABLE videos ADD COLUMN IF NOT EXISTS gps_scanned_at TIMESTAMPTZ;
|
||||
ALTER TABLE videos ADD COLUMN IF NOT EXISTS gps_track_corrected JSONB;
|
||||
ALTER TABLE videos ADD COLUMN IF NOT EXISTS gps_corrected_by TEXT;
|
||||
ALTER TABLE videos ADD COLUMN IF NOT EXISTS gps_corrected_at TIMESTAMPTZ;
|
||||
-- Human-readable summary of what the correction did ("2 spikes · start stitched …").
|
||||
ALTER TABLE videos ADD COLUMN IF NOT EXISTS gps_corrected_note TEXT;
|
||||
-- Data-quality + continuity metadata from the raw scan: absolute epoch of the
|
||||
-- first/last GPS fix (lets consecutive files stitch across a missing start),
|
||||
-- raw sample count and the largest inter-fix gap (dropout visibility).
|
||||
ALTER TABLE videos ADD COLUMN IF NOT EXISTS gps_start_epoch DOUBLE PRECISION;
|
||||
ALTER TABLE videos ADD COLUMN IF NOT EXISTS gps_end_epoch DOUBLE PRECISION;
|
||||
ALTER TABLE videos ADD COLUMN IF NOT EXISTS gps_sample_count INTEGER;
|
||||
ALTER TABLE videos ADD COLUMN IF NOT EXISTS gps_max_gap_s DOUBLE PRECISION;
|
||||
-- Real media duration read from the container by the exiftool scan. Load-bearing for
|
||||
-- the stitch guard: an inter-file gap is only "missing start" when the track covers
|
||||
-- LESS than the file's duration — otherwise the camera simply wasn't recording.
|
||||
ALTER TABLE videos ADD COLUMN IF NOT EXISTS duration_s DOUBLE PRECISION;
|
||||
CREATE INDEX IF NOT EXISTS idx_videos_gps ON videos(gps_status) WHERE gps_status = 'pending';
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Road types: admin-defined per-project labels (LHS/RHS/MCW/Servicelane, …)
|
||||
-- assigned to videos. Injected into the export/claim JSON as `road_type` and
|
||||
-- re-stamped on push (server-authoritative).
|
||||
-- ---------------------------------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS project_road_types (
|
||||
project_id INTEGER NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
||||
name TEXT NOT NULL,
|
||||
PRIMARY KEY (project_id, name)
|
||||
);
|
||||
ALTER TABLE videos ADD COLUMN IF NOT EXISTS road_type TEXT NOT NULL DEFAULT '';
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Chainage (linear referencing with piecewise-linear calibration).
|
||||
-- chainage_points = admin-entered client calibration pairs (lat/lon ↔ chainage).
|
||||
-- Optional road_type tag scopes a point to one calibration group (LHS vs RHS are
|
||||
-- separate routes); '' = usable by any group.
|
||||
-- Per video:
|
||||
-- sr_chainage_* = ACTUAL measured position along the GPS route (immutable,
|
||||
-- regenerated only from GPS — never admin-editable)
|
||||
-- chainage_* = client-calibrated values (error distributed between
|
||||
-- consecutive control points)
|
||||
-- route_seq = position of the video along the calibrated route
|
||||
-- ---------------------------------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS chainage_points (
|
||||
id SERIAL PRIMARY KEY,
|
||||
project_id INTEGER NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
||||
lat DOUBLE PRECISION NOT NULL,
|
||||
lon DOUBLE PRECISION NOT NULL,
|
||||
chainage_m DOUBLE PRECISION NOT NULL,
|
||||
note TEXT NOT NULL DEFAULT '',
|
||||
road_type TEXT NOT NULL DEFAULT '',
|
||||
created_by TEXT NOT NULL DEFAULT '',
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_chainage_points_project ON chainage_points(project_id);
|
||||
ALTER TABLE videos ADD COLUMN IF NOT EXISTS chainage_start_m DOUBLE PRECISION;
|
||||
ALTER TABLE videos ADD COLUMN IF NOT EXISTS chainage_end_m DOUBLE PRECISION;
|
||||
ALTER TABLE videos ADD COLUMN IF NOT EXISTS sr_chainage_start_m DOUBLE PRECISION;
|
||||
ALTER TABLE videos ADD COLUMN IF NOT EXISTS sr_chainage_end_m DOUBLE PRECISION;
|
||||
ALTER TABLE videos ADD COLUMN IF NOT EXISTS route_seq INTEGER;
|
||||
|
||||
-- The piecewise-linear calibration itself (per project + group), persisted at
|
||||
-- recompute time as sorted [s_m, chainage_m] anchors. Needed to evaluate chainage at
|
||||
-- ANY route position later — e.g. frame-exact per-annotation chainage in exports.
|
||||
CREATE TABLE IF NOT EXISTS chainage_calibrations (
|
||||
project_id INTEGER NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
||||
road_type TEXT NOT NULL DEFAULT '',
|
||||
anchors JSONB NOT NULL,
|
||||
route_len_m DOUBLE PRECISION NOT NULL DEFAULT 0,
|
||||
computed_by TEXT NOT NULL DEFAULT '',
|
||||
computed_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
PRIMARY KEY (project_id, road_type)
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user