mirror of
https://github.com/Horizontal42/f1-telemetry.git
synced 2026-11-10 15:22:03 +03:00
152 lines
4.1 KiB
Python
152 lines
4.1 KiB
Python
from dataclasses import dataclass
|
|
|
|
from .parser import Lap
|
|
|
|
STEER_ON = 6.0
|
|
BRAKE_ON = 5.0
|
|
MERGE_GAP_M = 40.0
|
|
MIN_LEN_M = 15.0
|
|
BRAKE_MARK = 20.0
|
|
FULL_THROTTLE = 98.0
|
|
LOCKUP_REL_PCT = -10.0
|
|
SPIN_REL_PCT = 8.0
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class Corner:
|
|
number: int
|
|
start_m: float
|
|
end_m: float
|
|
brake_start_m: float | None
|
|
v_entry: float
|
|
v_min: float
|
|
apex_m: float
|
|
gear_apex: int
|
|
full_throttle_m: float | None
|
|
v_exit: float
|
|
brake_max: float
|
|
g_lat_max: float
|
|
time_s: float
|
|
lock_pct: float
|
|
spin_pct: float
|
|
coast_m: float
|
|
rear_tyre_temp_peak: float
|
|
lockup: bool
|
|
wheelspin: bool
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class Straight:
|
|
start_m: float
|
|
end_m: float
|
|
v_max: float
|
|
drs: bool
|
|
time_s: float
|
|
|
|
|
|
def _get(lap: Lap, ch: str) -> list[float]:
|
|
return lap.ch.get(ch, [])
|
|
|
|
|
|
def _indices_in_range(dist: list[float], start: float, end: float) -> list[int]:
|
|
return [i for i, d in enumerate(dist) if start <= d <= end]
|
|
|
|
|
|
def detect_corners(lap: Lap) -> list[Corner]:
|
|
from .corner_metrics import corner_from_zone
|
|
|
|
dist = _get(lap, 'LapDistance')
|
|
steer = _get(lap, 'Steer')
|
|
brake = _get(lap, 'BrakePercentage')
|
|
speed = _get(lap, 'Speed')
|
|
gear = _get(lap, 'Gear')
|
|
throttle = _get(lap, 'ThrottlePercentage')
|
|
glat = _get(lap, 'GForceLatitudinal')
|
|
laptime = _get(lap, 'LapTime')
|
|
slip_rl = _get(lap, 'WheelSlipRearLeft')
|
|
slip_rr = _get(lap, 'WheelSlipRearRight')
|
|
slip_fl = _get(lap, 'WheelSlipFrontLeft')
|
|
slip_fr = _get(lap, 'WheelSlipFrontRight')
|
|
tyre_temp_rl = _get(lap, 'TyreTemperatureRearLeft')
|
|
tyre_temp_rr = _get(lap, 'TyreTemperatureRearRight')
|
|
|
|
n = len(dist)
|
|
if n < 2:
|
|
return []
|
|
|
|
cornering = [
|
|
(abs(steer[i]) > STEER_ON if i < len(steer) else False) or
|
|
(brake[i] > BRAKE_ON if i < len(brake) else False)
|
|
for i in range(n)
|
|
]
|
|
|
|
zones: list[tuple[int, int]] = []
|
|
in_zone = False
|
|
z_start = 0
|
|
for i, c in enumerate(cornering):
|
|
if c and not in_zone:
|
|
in_zone = True
|
|
z_start = i
|
|
elif not c and in_zone:
|
|
in_zone = False
|
|
zones.append((z_start, i - 1))
|
|
if in_zone:
|
|
zones.append((z_start, n - 1))
|
|
|
|
merged: list[tuple[int, int]] = []
|
|
for z in zones:
|
|
if merged and (dist[z[0]] - dist[merged[-1][1]]) < MERGE_GAP_M:
|
|
merged[-1] = (merged[-1][0], z[1])
|
|
else:
|
|
merged.append(list(z))
|
|
|
|
valid = [(a, b) for a, b in merged if (dist[b] - dist[a]) >= MIN_LEN_M]
|
|
|
|
return [
|
|
corner_from_zone(
|
|
lap, ia, ib, num,
|
|
dist, speed, brake, throttle, gear, glat, laptime,
|
|
slip_fl, slip_fr, slip_rl, slip_rr,
|
|
tyre_temp_rl, tyre_temp_rr,
|
|
)
|
|
for num, (ia, ib) in enumerate(valid, 1)
|
|
]
|
|
|
|
|
|
def straights(corners: list[Corner], lap: Lap) -> list[Straight]:
|
|
dist = _get(lap, 'LapDistance')
|
|
speed = _get(lap, 'Speed')
|
|
drs_ch = _get(lap, 'DRS')
|
|
laptime = _get(lap, 'LapTime')
|
|
|
|
if not dist:
|
|
return []
|
|
|
|
track_start = dist[0]
|
|
track_end = dist[-1]
|
|
|
|
gaps: list[tuple[float, float]] = []
|
|
if not corners:
|
|
gaps = [(track_start, track_end)]
|
|
else:
|
|
if corners[0].start_m > track_start + MIN_LEN_M:
|
|
gaps.append((track_start, corners[0].start_m))
|
|
for i in range(len(corners) - 1):
|
|
gaps.append((corners[i].end_m, corners[i + 1].start_m))
|
|
if corners[-1].end_m < track_end - MIN_LEN_M:
|
|
gaps.append((corners[-1].end_m, track_end))
|
|
|
|
result: list[Straight] = []
|
|
for start, end in gaps:
|
|
idxs = _indices_in_range(dist, start, end)
|
|
if not idxs:
|
|
continue
|
|
spds = [speed[i] for i in idxs if i < len(speed)]
|
|
v_max = max(spds) if spds else 0.0
|
|
drs_used = any(drs_ch[i] == 1.0 for i in idxs if i < len(drs_ch))
|
|
time_zone = 0.0
|
|
if laptime and idxs:
|
|
time_zone = laptime[idxs[-1]] - laptime[idxs[0]]
|
|
result.append(Straight(start_m=start, end_m=end, v_max=v_max, drs=drs_used, time_s=time_zone))
|
|
|
|
return result
|