TelemetrySign in

Speed

Algorithm speed-1.0.0 · source engine/src/dtta/engine/speed/{analysis,metrics,filters}.py.

Which speed

The GoPro receiver reports a 2-D speed with every position. Reconnaissance on the real files showed it behaves like a receiver velocity solution: smooth and unbiased against the positions (1 s window bias −0.02…+0.09 m/s), while sample-to-sample position differencing at 18 Hz is unusable (RMS disagreement 3.2–3.8 m/s, "roughness" 7.4 vs 0.13). The reported speed is therefore the primary channel and position-derived speed is the independent witness (the consistency check in GPS validation).

Definitions

  • vrawv_{raw}: reported 2-D speed with its quality flags (served as v_raw).
  • vvalidv_{valid}: vrawv_{raw} with SPEED_SPIKE, NO_FIX, PRELOCK samples removed; gaps up to speed_gap_fill_s (0.5 s) linearly filled and flagged INTERPOLATED; longer gaps left open.
  • vanalysisv_{analysis}: zero-phase Butterworth low-pass of vvalidv_{valid} — order 2 applied forward and backward (sosfiltfilt, effective order 4, no phase lag) with cutoff speed_cutoff_hz = 1.0 Hz, computed on a uniform time grid per contiguous run and mapped back to the samples, then resampled onto the 1 m track grid. This is the speed on every chart and in every metric.
  • Longitudinal (path) acceleration: along=dvanalysis/dta_{long} = dv_{analysis}/dt by Savitzky–Golay derivative with window sg_window_long_s = 0.7 s and polynomial order sg_polyorder = 2. Positive = accelerating.

Why 1.0 Hz

Selected in Phase 6 on the real files (docs/proofs/phase-06/filter_selection.md) from candidates 0.5 / 1.0 / 2.0 Hz: the lowest cutoff whose residual is near-white and whose brake/acceleration events shift by less than 3 m against the 2 Hz candidate; a one-sample injected spike changes the maximum speed by < 0.1 m/s. The heading window (1.0 s) was chosen for Cornering G noise of 0.02–0.04 g (1σ) on straights with no corner bias; the longitudinal window (0.7 s) reproduces a synthetic ramp within 3 %.

Metrics

metric definition units shown
Max / min / average speed (lap) max and min of vanalysisv_{analysis} in the lap; average = centerline length / lap time mph
Entry / exit speed (segment) vanalysisv_{analysis} at the first / last grid point of the segment mph
Minimum speed (segment) lowest vanalysisv_{analysis} in the segment and its position min_speed_s mph, m
Speed loss entry − minimum mph
Brake point first position where along<a_{long} < -brake_threshold_ms2 (2 m/s²) is sustained for brake_sustain_s (0.3 s) m of track position
Acceleration point first position after the minimum speed where along>+a_{long} > +accel_threshold_ms2 (1 m/s²) is sustained for accel_sustain_s (0.5 s) m of track position

Positions are track progress s in metres from the start/finish gate (the API keys end in _s for "s coordinate", not seconds).

Display conversions

mph = m/s × 3600 / 1609.344 (exact). Nothing else is recomputed in the browser: the values shown at the cursor are the engine's grid values at the nearest 1 m grid point.

Limitations

  • The receiver's speed trails true motion by 0.15–0.40 s (gps_lag_s, measured per session against the accelerometer). It is constant within a session and common to both laps of a comparison, so it does not affect deltas; it does shift brake points slightly later on the video.
  • Speeds below 3 m/s carry no heading (Cornering G undefined); lap detection ignores samples below lap_cross_min_speed_ms at the gate.
  • Reported speed above 80 m/s (179 mph) or a physically impossible step is rejected as a spike.

Verified

  • Per-s standard deviation of speed across racing laps < 2 m/s on the straights of both fixtures.
  • along<12|a_{long}| < 12 m/s² everywhere on the fixtures; minimum-speed locations fall inside the corner arcs.
  • Tests: engine/tests/unit/test_speed_filters.py (impulse symmetry, unit DC gain, SG derivative of a known polynomial), synthetic ramp within 3 %, regression goldens (max/min/avg ± 0.05 m/s).