mirror of
https://github.com/Horizontal42/f1-telemetry.git
synced 2026-11-10 15:22:03 +03:00
document profile mode, new flags, and tunable constants
This commit is contained in:
parent
0661ff4322
commit
22ca7cc24f
4 changed files with 64 additions and 8 deletions
|
|
@ -17,7 +17,8 @@ telemetry/
|
|||
report_technique.py Driving report (corners, straights, cost, trace).
|
||||
report_setup.py Car report (setup, balance, tyres, brakes, suspension, phases).
|
||||
report_compare.py Two+ laps side by side, per-corner and cumulative delta.
|
||||
report_race.py A folder of laps: lap times (with position), stints, wear, thermals, ERS.
|
||||
report_race.py A folder of laps: lap times (with position), stints, wear, thermals, ERS. Dedups duplicate lap numbers.
|
||||
report_profile.py A folder of laps: cheap cross-lap corner tendencies (median per corner, per dominant compound) + auto-picked deep-dive laps. No trace.
|
||||
rename.py Insert session type + lap number (P1_L7) into filenames; with races_dir, sort into races/<track>/<session>/ and recurse subdirectories.
|
||||
gui.py tkinter window; per-mode browse memory; runs generation/rename on a worker thread.
|
||||
prompts/ LLM analysis prompts, ru/ and en/ subdirectories, one file per mode. Auto-appended to every report.
|
||||
|
|
@ -30,7 +31,7 @@ tests/ pytest suite + fixture laps.
|
|||
2. **`parser.load_lap`** reads the file as UTF-8 and splits it into four meta blocks (session, track, setup) plus the 108-channel telemetry table. Channel names are normalised by stripping the ` [unit]` suffix. Every column that is entirely zero is dropped — the game writes many dead channels (see Gotchas).
|
||||
3. **`segments.detect_corners`** walks the samples, marks each as "cornering" when `|Steer| > STEER_ON` or `Brake > BRAKE_ON`, merges adjacent zones closer than `MERGE_GAP_M`, drops zones shorter than `MIN_LEN_M`, and numbers what's left T1..Tn by distance. For each zone it calls **`corner_metrics.corner_from_zone`**, which extracts the braking point, apex, gear, full-throttle point, peak brake/gLat, relative lock%/spin%, coast distance, and rear tyre temperature peak. `straights` fills the gaps between corners.
|
||||
4. **`resample.adaptive_points`** builds a distance grid that is dense inside (and on approach to) corners and sparse on straights — the step sizes default to the lap's own median sample spacing via `auto_steps`, so denser raw telemetry yields a denser trace. **`sample_at`** interpolates each channel onto that grid (nearest-sample for discrete channels like Gear/DRS).
|
||||
5. The **`report_<mode>.generate(…, lang)`** function assembles Markdown from `report_common` helpers (`header_block`, `md_table`, `legend`) and the data above. It then calls **`load_prompt(mode, lang)`** to read the matching prompt from `prompts/<lang>/<mode>.md` and appends it after a `---` separator. Finally **`write_report`** writes atomically (temp file + `os.replace`) and returns `(abs_path, tokens)`.
|
||||
5. The **`report_<mode>.generate(…, lang, include_prompt=True)`** function assembles Markdown from `report_common` helpers (`header_block`, `md_table`, `legend`) and the data above. When `include_prompt` is set it calls **`load_prompt(mode, lang)`** to read the matching prompt from `prompts/<lang>/<mode>.md` and appends it after a `---` separator (CLI `--no-prompt` / GUI checkbox turn this off). Finally **`write_report`** writes atomically (temp file + `os.replace`) and returns `(abs_path, tokens)`. Before generating, `__main__` skips the run via **`is_fresh(report, sources)`** when an up-to-date report exists (override with `--force`).
|
||||
6. **`__main__`** prints that path and `~N tokens (budget 60k)`. The **GUI** shows the same tuple in its log instead of printing.
|
||||
|
||||
## Adding things
|
||||
|
|
@ -41,6 +42,23 @@ tests/ pytest suite + fixture laps.
|
|||
|
||||
**A new corner metric.** Add a field to the `Corner` dataclass in `segments.py` and compute it in `corner_metrics.corner_from_zone`. Because `Corner` is frozen, set it through the constructor.
|
||||
|
||||
## Assumptions & tunables
|
||||
|
||||
Two kinds of constants. **Detection** thresholds are in telemetry units and uniform across F1 22 — they decide *where* a boundary is, not the conclusion, so they are not track-tuned. **Interpretation** constants encode racing judgment that genuinely varies; reports always print the raw number next to any flag/verdict, so a debatable threshold never hides the data.
|
||||
|
||||
| Constant | File | Kind | Basis / sensitivity |
|
||||
|----------|------|------|---------------------|
|
||||
| `STEER_ON 6`, `BRAKE_ON 5`, `BRAKE_MARK 20`, `FULL_THROTTLE 98` | `segments` / `corner_metrics` | detection | percent of input range, game-uniform |
|
||||
| `MERGE_GAP_M 40` + `merge_gap_for` (clamp 28–60) | `segments` | detection | **adaptive**: scales with `Tracklen` around the Zandvoort anchor so chicanes/long circuits self-tune |
|
||||
| `MIN_LEN_M 15`, `_SAFE_SPEED_FLOOR 30`, `0.3 s` throttle window | `segments` / `corner_metrics` | detection | geometry / divide guard / debounce |
|
||||
| `resample` dense=median, sparse=8×median | `resample` | detection | self-tunes to sample rate |
|
||||
| `LOCKUP −10 %`, `SPIN +8 %` | `segments` | interpretation | severe-only flags; raw `lock%`/`spin%` always shown |
|
||||
| `FUEL 0.03–0.05 s/kg` | `report_compare` | interpretation | track-varying; emitted as a **range** with the rate printed |
|
||||
| `diff ±0.5` US/OS | `report_setup` | interpretation | relative to the lap's slip baseline; raw front/rear slip shown |
|
||||
| profile `*_REL` multipliers + `*_FLOOR` / `TR` margins | `report_profile` | interpretation | multipliers are **relative to the session median**; floors are noise gates; medians shown in the table |
|
||||
|
||||
If a future track needs a different corner grouping, `merge_gap_for` already adapts by length; only a genuinely unusual layout would want a manual nudge there.
|
||||
|
||||
## Gotchas
|
||||
|
||||
**Files are UTF-8, the OS default here is cp1251.** `parser.load_lap` always passes `encoding='utf-8'`; opening a telemetry file with the default codec raises `UnicodeDecodeError` on the first non-ASCII byte. `rename.read_lap_number` reads only the first five lines but must use the same encoding.
|
||||
|
|
|
|||
|
|
@ -17,7 +17,8 @@ telemetry/
|
|||
report_technique.py Отчёт о пилотировании (повороты, прямые, расход, трасса).
|
||||
report_setup.py Отчёт о машине (сетап, баланс, шины, тормоза, подвеска, фазы).
|
||||
report_compare.py Два+ круга рядом, дельта по поворотам и накопленная.
|
||||
report_race.py Папка кругов: лаптаймы (с позицией), стинты, износ, тепло, ERS.
|
||||
report_race.py Папка кругов: лаптаймы (с позицией), стинты, износ, тепло, ERS. Дедуп дублей номеров кругов.
|
||||
report_profile.py Папка кругов: дешёвые тенденции по поворотам (медиана на поворот, по доминирующему составу) + авто-выбор кругов для разбора. Без трассы.
|
||||
rename.py Вставка типа сессии + номера круга (P1_L7) в имя; с races_dir — сортировка в races/<track>/<session>/ и рекурсия по подпапкам.
|
||||
gui.py Окно tkinter; память последней папки по режиму; генерация/переименование в потоке.
|
||||
prompts/ Промпты LLM, подпапки ru/ и en/, по одному файлу на режим. Добавляются в конец каждого отчёта.
|
||||
|
|
@ -30,7 +31,7 @@ tests/ Набор pytest + фикстуры-круги.
|
|||
2. **`parser.load_lap`** читает файл как UTF-8 и делит на четыре мета-блока (session, track, setup) плюс таблицу телеметрии на 108 каналов. Имена каналов нормализуются срезанием суффикса ` [unit]`. Каждая колонка, целиком состоящая из нулей, отбрасывается — игра пишет много мёртвых каналов (см. «Подводные камни»).
|
||||
3. **`segments.detect_corners`** проходит по сэмплам, помечает сэмпл как «в повороте», если `|Steer| > STEER_ON` или `Brake > BRAKE_ON`, сливает соседние зоны с зазором меньше `MERGE_GAP_M`, отбрасывает зоны короче `MIN_LEN_M` и нумерует оставшиеся T1..Tn по дистанции. Для каждой зоны вызывается **`corner_metrics.corner_from_zone`**, которая извлекает точку торможения, апекс, передачу, точку полного газа, пик тормоза/gLat, относительные lock%/spin%, дистанцию наката и пик температуры задней шины. `straights` заполняет промежутки между поворотами.
|
||||
4. **`resample.adaptive_points`** строит сетку по дистанции — плотную внутри поворотов (и на подходе) и редкую на прямых; шаги по умолчанию берутся из медианного интервала сэмплов круга через `auto_steps`, так что более плотная сырая телеметрия даёт более плотную трассу. **`sample_at`** интерполирует каждый канал на эту сетку (ближайший сэмпл для дискретных вроде Gear/DRS).
|
||||
5. Функция **`report_<режим>.generate(…, lang)`** собирает Markdown из помощников `report_common` (`header_block`, `md_table`, `legend`) и данных выше. Затем вызывает **`load_prompt(mode, lang)`**, которая читает промпт из `prompts/<lang>/<mode>.md` и добавляет его после разделителя `---`. Финальный текст пишется через **`write_report`** атомарно (временный файл + `os.replace`), возвращается `(abs_path, tokens)`.
|
||||
5. Функция **`report_<режим>.generate(…, lang, include_prompt=True)`** собирает Markdown из помощников `report_common` (`header_block`, `md_table`, `legend`) и данных выше. При `include_prompt` вызывает **`load_prompt(mode, lang)`**, которая читает промпт из `prompts/<lang>/<mode>.md` и добавляет его после разделителя `---` (CLI `--no-prompt` / чекбокс GUI это отключают). Финальный текст пишется через **`write_report`** атомарно (временный файл + `os.replace`), возвращается `(abs_path, tokens)`. Перед генерацией `__main__` пропускает прогон через **`is_fresh(report, sources)`**, если свежий отчёт уже есть (override — `--force`).
|
||||
6. **`__main__`** печатает путь и `~N tokens (budget 60k)`. **GUI** показывает тот же кортеж в логе вместо печати.
|
||||
|
||||
## Как добавлять
|
||||
|
|
@ -41,6 +42,23 @@ tests/ Набор pytest + фикстуры-круги.
|
|||
|
||||
**Новая метрика поворота.** Добавь поле в dataclass `Corner` в `segments.py` и посчитай его в `corner_metrics.corner_from_zone`. Поскольку `Corner` — frozen, задавай через конструктор.
|
||||
|
||||
## Допущения и тюнящиеся константы
|
||||
|
||||
Два рода констант. **Детекция** — пороги в единицах телеметрии, одинаковы во всей F1 22: решают, *где* граница, а не вывод, поэтому не тюнингуются под трассу. **Интерпретация** — доменное суждение, которое реально варьируется; в отчётах рядом с любым флагом/вердиктом всегда печатается сырое число, так что спорный порог не прячет данные.
|
||||
|
||||
| Константа | Файл | Род | Основа / чувствительность |
|
||||
|-----------|------|-----|---------------------------|
|
||||
| `STEER_ON 6`, `BRAKE_ON 5`, `BRAKE_MARK 20`, `FULL_THROTTLE 98` | `segments` / `corner_metrics` | детекция | % от диапазона ввода, одинаково в игре |
|
||||
| `MERGE_GAP_M 40` + `merge_gap_for` (clamp 28–60) | `segments` | детекция | **адаптивно**: масштабируется по `Tracklen` вокруг якоря Zandvoort — шиканы/длинные трассы самотюнятся |
|
||||
| `MIN_LEN_M 15`, `_SAFE_SPEED_FLOOR 30`, окно газа `0.3 с` | `segments` / `corner_metrics` | детекция | геометрия / защита деления / дебаунс |
|
||||
| `resample` dense=median, sparse=8×median | `resample` | детекция | самонастройка под частоту данных |
|
||||
| `LOCKUP −10 %`, `SPIN +8 %` | `segments` | интерпретация | флаги severe-only; сырые `lock%`/`spin%` всегда показаны |
|
||||
| `FUEL 0.03–0.05 с/кг` | `report_compare` | интерпретация | зависит от трассы; выдаётся **диапазоном** с печатью ставки |
|
||||
| `diff ±0.5` US/OS | `report_setup` | интерпретация | относительно baseline скольжения круга; сырое front/rear показано |
|
||||
| profile `*_REL` множители + `*_FLOOR` / `TR` поля | `report_profile` | интерпретация | множители **относительно медианы сессии**; полы — шумовые гейты; медианы в таблице |
|
||||
|
||||
Если будущая трасса потребует другой группировки поворотов — `merge_gap_for` уже адаптируется по длине; ручная правка нужна лишь на совсем нестандартной конфигурации.
|
||||
|
||||
## Подводные камни
|
||||
|
||||
**Файлы в UTF-8, а кодировка ОС здесь — cp1251.** `parser.load_lap` всегда передаёт `encoding='utf-8'`; открытие файла телеметрии дефолтным кодеком падает с `UnicodeDecodeError` на первом не-ASCII байте. `rename.read_lap_number` читает только первые пять строк, но обязан использовать ту же кодировку.
|
||||
|
|
|
|||
14
README.md
14
README.md
|
|
@ -21,18 +21,23 @@ Download or clone the repository. Keep your telemetry CSVs in the parent folder
|
|||
|
||||
## What it does
|
||||
|
||||
Five modes. Four produce reports, one renames files.
|
||||
Six modes. Five produce reports, one renames files.
|
||||
|
||||
| Mode | Input | Use it to analyse |
|
||||
|------|-------|-------------------|
|
||||
| `technique` | one lap | **how** you drive — braking points, apex speeds, throttle application, lockups, resource cost |
|
||||
| `setup` | one lap | **what** is set — balance (US/OS), tyre temps, brakes, suspension rake & roll |
|
||||
| `compare` | two+ laps | **where** one lap is faster — per-corner and cumulative delta |
|
||||
| `compare` | two+ laps | **where** one lap is faster — per-corner and cumulative delta, plus a deterministic `Verdict` (fuel-corrected) |
|
||||
| `race` | a folder of laps | the whole race — pace, stint degradation, tyre wear, ERS per lap |
|
||||
| `profile` | a folder of laps | **cheap** (~400 tokens) cross-lap driver tendencies per tyre compound (median coast/lock/spin per corner, flagged relative to the session) + auto-picked laps to deep-dive. Track-agnostic: corners are clustered by apex distance, not index |
|
||||
| `rename` | files/folder | insert session type and lap number into each filename (`..._74.074_...` → `..._P1_L7_74.074_...`) |
|
||||
|
||||
Reports include a legend explaining every column and have the analysis prompt auto-appended at the end — just drop the file into an LLM. Prompts come in RU and EN; pick with `--lang en` on the CLI or the language radio in the GUI.
|
||||
|
||||
**Flags:** `--no-prompt` omits the embedded analysis prompt (smaller files for agent pipelines; in the GUI it's the **Include prompt** checkbox). `--force` regenerates even when an up-to-date report already exists (runs are otherwise skipped as `cached`).
|
||||
|
||||
> Typical optimized flow: run `profile` first to see chronic tendencies and which laps matter, then generate `technique`/`setup`/`compare` only for those laps with `--no-prompt`.
|
||||
|
||||
### Folder layout
|
||||
|
||||
```
|
||||
|
|
@ -66,10 +71,15 @@ python -m telemetry technique races/Zandvoort/Practice/lap.csv
|
|||
python -m telemetry setup races/Zandvoort/Practice/lap.csv
|
||||
python -m telemetry compare races/Zandvoort/Practice/lap_a.csv races/Zandvoort/Practice/lap_b.csv
|
||||
python -m telemetry race races/Zandvoort/Race
|
||||
python -m telemetry profile races/Zandvoort/Race # cheap cross-lap tendencies + lap picks
|
||||
python -m telemetry rename races/Zandvoort/Practice # or individual files
|
||||
|
||||
# choose prompt language (default: ru)
|
||||
python -m telemetry technique races/Zandvoort/Practice/lap.csv --lang en
|
||||
|
||||
# agent pipeline: drop the prompt, reuse fresh reports
|
||||
python -m telemetry technique races/Zandvoort/Practice/lap.csv --no-prompt
|
||||
python -m telemetry technique races/Zandvoort/Practice/lap.csv --force # ignore cache
|
||||
```
|
||||
|
||||
Every report run prints the output path and a token estimate:
|
||||
|
|
|
|||
14
README.ru.md
14
README.ru.md
|
|
@ -21,18 +21,23 @@ python -m telemetry technique "races/Zandvoort/Практика/zandvoort_P1_L7_
|
|||
|
||||
## Что умеет
|
||||
|
||||
Пять режимов. Четыре строят отчёты, один переименовывает файлы.
|
||||
Шесть режимов. Пять строят отчёты, один переименовывает файлы.
|
||||
|
||||
| Режим | Вход | Для анализа |
|
||||
|-------|------|-------------|
|
||||
| `technique` | один круг | **как** едешь — точки торможения, скорости в апексах, работа газом, блокировки, расход ресурсов |
|
||||
| `setup` | один круг | **что** настроено — баланс (US/OS), температуры шин, тормоза, rake и крен подвески |
|
||||
| `compare` | два+ круга | **где** один круг быстрее — дельта по поворотам и накопленная |
|
||||
| `compare` | два+ круга | **где** один круг быстрее — дельта по поворотам и накопленная, плюс детерминированный `Verdict` (с топливной поправкой) |
|
||||
| `race` | папка кругов | вся гонка — темп, деградация в стинтах, износ резины, ERS по кругам |
|
||||
| `profile` | папка кругов | **дёшево** (~400 токенов) тенденции пилота по каждому составу (медиана coast/lock/spin на поворот, флаги относительно сессии) + авто-выбор кругов. Универсально: повороты кластеризуются по дистанции апекса, не по индексу |
|
||||
| `rename` | файлы/папка | вставить тип сессии и номер круга в имя файла (`..._74.074_...` → `..._P1_L7_74.074_...`) |
|
||||
|
||||
Отчёты содержат легенду с пояснением каждой колонки, а промпт анализа добавляется в конец файла автоматически — достаточно скинуть файл в LLM. Промпты доступны на RU и EN; выбирается флагом `--lang en` в CLI или переключателем языка в GUI.
|
||||
|
||||
**Флаги:** `--no-prompt` убирает встроенный промпт (меньше файлы для агентных конвейеров; в GUI — чекбокс **Включить промпт**). `--force` перегенерирует, даже если свежий отчёт уже есть (иначе прогон пропускается как `cached`).
|
||||
|
||||
> Оптимальный порядок: сначала `profile` — увидеть хронические тенденции и какие круги важны, затем `technique`/`setup`/`compare` только по этим кругам с `--no-prompt`.
|
||||
|
||||
### Структура папок
|
||||
|
||||
```
|
||||
|
|
@ -66,10 +71,15 @@ python -m telemetry technique races/Zandvoort/Практика/lap.csv
|
|||
python -m telemetry setup races/Zandvoort/Практика/lap.csv
|
||||
python -m telemetry compare races/Zandvoort/Практика/lap_a.csv races/Zandvoort/Практика/lap_b.csv
|
||||
python -m telemetry race races/Zandvoort/Гонка
|
||||
python -m telemetry profile races/Zandvoort/Гонка # дешёвые тенденции по всем кругам + авто-выбор
|
||||
python -m telemetry rename races/Zandvoort/Практика # или отдельные файлы
|
||||
|
||||
# выбор языка промпта (по умолчанию: ru)
|
||||
python -m telemetry technique races/Zandvoort/Практика/lap.csv --lang en
|
||||
|
||||
# агентный конвейер: убрать промпт, переиспользовать свежие отчёты
|
||||
python -m telemetry technique races/Zandvoort/Практика/lap.csv --no-prompt
|
||||
python -m telemetry technique races/Zandvoort/Практика/lap.csv --force # игнорировать кэш
|
||||
```
|
||||
|
||||
Каждый прогон печатает путь к отчёту и оценку токенов:
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue