Симулятор «мир БВС»: зачем он рядом с планировщиком¶
Этот раздел — бизнес-описание продукта simulate: что он делает, кому нужен, чем отличается от валидатора планировщика geoscan, что подаётся на вход и что получается на выходе. Пишем по коду ветки docs2/sim-business, без «бумажных» функций.
| Кому читать | Что взять из раздела |
|---|---|
| Заказчик / жюри | §1–2, диаграмма места в экосистеме, §6 «честно о готовности» |
| Новый разработчик | §3–4, команды с реальным выводом, ссылки на архитектуру и API (черновик) |
| Оператор | §5 пошаговый прогон, экраны web/, что значит UNRESOLVED на вкладке «Вердикт» |
Соседний продукт (планировщик): geoscan — бизнес-описание.
Дальше по симулятору: сценарии · архитектура · интерфейсы (черновик) · эксплуатация · матрица зрелости.
1. Что это за симулятор¶
Симулятор — отдельный сервис, который принимает уже готовое полётное задание планировщика (JSON / GeoJSON / KML после импорта) и прогоняет его в синтетическом 3D-мире с координатами WGS84: борт движется по фазам sortie, учитываются ветер, температура, связь по рельефу, часть ограничений парка Геоскан (201 / 801 / Gemini). На выходе — журнал прогона (телеметрия, события) и отчёт «план против факта» (fact_report.json), а не новый маршрут.
Краткая формулировка в корневом README продукта совпадает с кодом: симулятор не планирует галсы и не заменяет метрики качества плана — их считает валидатор (отдельный контур в geoscan и отдельный — внутри simulate для эталонов модели).
mindmap
root((simulate))
Вход
План планировщика
world_snapshot_id
seed детерминизма
Ядро прогона
Preflight analyze_plan
Интегратор engine
Журнал telemetry events
Выход
fact_report план vs факт
frames.jsonl сухая геометрия
HTTP API и web UI
Независимая проверка
sim validate --reference V-1…V-14
sim mutate мутанты
Граница импорта validator
Достоверность
fidelity_class
validation_level V1…V6
Вердикт UNRESOLVED
Вывод с mindmap. У симулятора три слоя смысла: (1) исполнение плана во времени, (2) независимые эталоны физики и геометрии (validator/), (3) пометки доверия к каждой цифре (fidelity_class). Путать «прогон» и «эталон V-10» нельзя: парашютный снос есть в sim validate, в fact_report прогона — только то, что собирает build_fact_report (см. LIMITATIONS.md).
2. Место в общей картине: планировщик, валидатор, симулятор¶
Зависимость односторонняя: симулятор читает выход планировщика; планировщик о симуляторе не знает (simulate/README.md, docs/90-final/01-business-requirements.md §2).
flowchart TB
subgraph geoscan["Планировщик geoscan"]
SC[Сценарий: полигон, парк, ЛЗП, ветер]
PL[План + метрики makespan coverage]
GV[Валидатор метрик плана<br/>геометрия без «воздуха»]
SC --> PL --> GV
end
subgraph simulate["Симулятор simulate"]
PF[Preflight analyze_plan<br/>зоны, клиренс, ветер по фазам]
RUN[sim run / POST /runs<br/>интегратор + мир]
FR[fact_report.json<br/>план ↔ факт]
REF[sim validate --reference<br/>V-1…V-14]
PF --> RUN --> FR
REF -.->|проверяет модель, не план| RUN
end
PL -->|файл плана| PF
PL -->|тот же план| RUN
GV -->|violations = 0<br/>не значит «полетит»| PF
Вывод. Планировщик отвечает на «как разложить работы оптимально». Его валидатор (docs/task5/70-plan/01-validator-first.md) пересчитывает геометрию и ограничения на бумаге: NFZ, ВП, ветер как скаляр, запас энергии, coverage_fraction по полосам захвата. Симулятор отвечает на «что произойдёт, если исполнять этот план в мире с рельефом, дискретными кадрами и потерей связи» — см. проблемы P-01…P-12 в docs/00-brief/02-vision-and-business.md.
2.1. Таблица: три способа «проверить план»¶
| Валидатор geoscan | Preflight + sim run | sim validate --reference |
|
|---|---|---|---|
| Вопрос | Допустим ли план по правилам ТЗ? | Какой факт даст прогон? | Верна ли модель (ТТХ, формулы)? |
| Вход | Сценарий + план | Файл плана + world_snapshot_id |
Нет плана; кейсы V-1…V-14 |
| Время | Секунды | Секунды–минуты (s01 ≈ 100 с на машине документации) | Секунды |
| Типичный результат | violations.*, метрики плана |
telemetry.jsonl, fact_report.json |
Таблица PASS/FAIL по эталонам |
| Независимость | Отдельный код от солвера | validator/ не импортирует engine/mission статически (tests/test_validator_import_boundary.py) |
Oracle в validator/independent/ |
| Чего не видит | CFIT по DEM, LOS, дискретные кадры | Не оптимизирует план заново | Не заменяет прогон сценария s01 |
Preflight явно позиционирован как анализ до полного 3D-движка (../../../src/geoscan_sim/mission/preflight.py), но уже тянет мир (check_clearance_along_geometry, зоны, покрытие по геометрии).
sequenceDiagram
participant Op as Оператор / CI
participant GS as geoscan
participant PF as simulate preflight
participant EN as simulate engine
participant FR as fact_report
Op->>GS: Сценарий → план + метрики
Op->>GS: validate plan (валидатор geoscan)
GS-->>Op: violations, coverage_fraction (план)
Op->>PF: sim run (тот же JSON)
PF->>PF: analyze_plan
alt fatal preflight
PF-->>Op: structured errors, exit ≠ 0
else ok
PF->>EN: integrator.run по фазам
EN-->>FR: телеметрия + RunResult
FR-->>Op: fact_report.json, makespan delta
end
3. Кому нужен и какие вопросы задаёт¶
| Роль | Вопрос | Где ответ в продукте |
|---|---|---|
| Разработчик планировщика | Не сломал ли я регрессию на s01? | sim run, сравнение fact_report / sha256 телеметрии (determinism в отчёте) |
| Команда → жюри | Показать 3D и числа | sim serve + web/ (../../../web/) (экран «Прогон») |
| Планировщик работ | План A vs B по факту, не по одной модели | Два прогона, таблица plan_vs_fact (../../../src/geoscan_sim/mission/fact_report.py) |
| Ревьюер | Модель не врёт на V-10 (парашют 168 м)? | sim validate --reference (../../../src/geoscan_sim/cli/__init__.py) |
| Оператор (в контуре команды) | Есть ли NFZ / низкий клиренс до выезда? | Preflight-коды + карта прогона |
Роли «внешний пилот заказчика» в контуре хакатона нет — в BRD это честно отмечено (Q-BIZ-04); симулятор всё равно даёт отчёт о находках, но не выдаёт бинарный «можно лететь» (см. §6).
4. Вход и выход глазами пользователя¶
4.1. Вход¶
| Что | Откуда | Проверка в коде |
|---|---|---|
| План | Экспорт из UI geoscan (файл) |
load_and_validate_plan, validate_plan_contract в sim run (../../../src/geoscan_sim/cli/__init__.py) |
| Мир | --world / world_snapshot_id (по умолчанию m0-synthetic-flat) |
Синтетика, не GLO-30 в поставке (LIMITATIONS.md) |
| Детерминизм | --seed (default 42) |
fact_report.determinism.stochastic: false (../../../src/geoscan_sim/mission/fact_report.py) |
| Строгие зоны | --strict |
ZONE_ALT_FRAME_REQUIRED при отсутствии altitude_frame |
Погода на прогон берётся из плана/сценария (ветер, температура) и попадает в блок environment отчёта с fidelity_class: assumed для полей сценария (../../../src/geoscan_sim/mission/fact_report.py).
4.2. Выход одного sim run¶
После успешного прогона CLI печатает JSON-summary с путями (проверено на fixtures/plans/s01.json):
{
"fact_report": "/tmp/sim-doc-out2/fact_report.json",
"frames_written": 380,
"frames_raster_count": 0,
"manifest": "/tmp/sim-doc-out2/run_manifest.json",
"telemetry": "/tmp/sim-doc-out2/telemetry.jsonl",
"telemetry_sha256": "e11273715f65affb7987923aeb444d85ded8c8919264af05a2cf446cf4b62371"
}
| Артефакт | Смысл для человека |
|---|---|
run_manifest.json |
Паспорт прогона: план, seed, ссылки, хеши |
world_manifest.json |
Какой мир подложен, layer_completeness |
telemetry.jsonl |
Позиция, скорости, энергия по шагу времени |
events.jsonl |
Фазы, связь, contingency |
frames.jsonl |
Сухая геометрия кадров (без JPEG/TIFF) |
fact_report.json |
План против факта + окружение |
4.3. Отчёт «план против факта»¶
Файл fact_report.json строится функцией build_fact_report (../../../src/geoscan_sim/mission/fact_report.py). Сверяемые с валидатором планировщика имена метрик зафиксированы:
```25:30:simulate/src/geoscan_sim/mission/fact_report.py VALIDATOR_PLAN_FACT_METRICS: tuple[str, ...] = ( "makespan_s", "total_flight_time_s", "coverage_fraction", "energy_used_frac", )
Для каждой метрики в `plan_vs_fact`:
- **planned** — из `plan.metrics` (класс `assumed`, `validation_level: V1`);
- **actual** — из прогона (`derived`, обычно `V2`, если метрика посчитана);
- **delta_pct** — относительное отклонение;
- для времени — **delta_components_s**: ветер, фазы, усечение, contingency (`../../../src/geoscan_sim/mission/fact_report.py`).
**Важно по честности (проверено на s01, seed 42).**
1. **`makespan_s.actual`** сейчас передаётся как сумма плановых длительностей sortie (`runner.py:323-324`), а не как независимый интегральный замер — в отчёте стоит флаг `suspicious_plan_copy: true` при совпадении с планом (`../../../src/geoscan_sim/mission/fact_report.py`). Это согласуется с [`LIMITATIONS.md`](../../extras/simulate/LIMITATIONS.md) (дефект Б-3 по makespan).
2. **`coverage_fraction`** в том же прогоне: `status: NOT_COMPUTED`, причина `frame footprints not available (B4)` — отчёт собирается **до** материализации кадров в `run_plan_headless` (`../../../src/geoscan_sim/mission/runner.py`), хотя `frames_written` в summary может быть > 0.
3. **Энергия** (`energy_used_frac`) считается по телеметрии двухякорной модели — на s01 дельта к плану может быть большой (это сигнал расхождения моделей, а не «ошибка UI»).
Пример структуры (фрагмент мока UI): `../../../web/src/fixtures/mocks/s01/fact_report.json`.
---
## 5. Оператор: прогон и чтение результата
### 5.1. CLI (минимальный сценарий)
Из каталога `simulate/` (нужен `.venv` после `uv sync`):
```bash
.venv/bin/sim run fixtures/plans/s01.json --seed 42 --output ./out-s01 --world m0-synthetic-flat
Коды выхода и preflight описаны в ../../../src/geoscan_sim/cli/exit_codes.py. Подкоманды на момент документации: run, serve, validate, mutate, identities — batch нет:
Error: No such command 'batch'.
(проверено: .venv/bin/sim batch --help).
Эталоны модели:
.venv/bin/sim validate --reference
Фрагмент реального вывода (все 14 строк PASS):
V-10 Parachute drift W=12 H=70 Vdesc=5 168 168 +0 ±2% PASS
V-14 Determinism 10× identical sha256 0 0 +0 exact match PASS
5.2. HTTP + веб-интерфейс¶
- API:
sim serve(../../../src/geoscan_sim/cli/__init__.py) — см. HTTP API (черновик). - UI: четыре маршрута — «Прогон», «Покрытие», «Эталоны», «Вердикт» (
../../../web/src/App.tsx).
На экране «Вердикт» оператор видит строку UNRESOLVED и список blockers — это не сбой, а задуманное состояние до закрытия полноты данных (../../../src/geoscan_sim/api/verdict.py).
stateDiagram-v2
[*] --> PlanLoaded: файл плана
PlanLoaded --> PreflightFailed: analyze_plan fatal
PlanLoaded --> Running: sim run / POST /runs
PreflightFailed --> [*]: exit FATAL
Running --> ArtifactsReady: telemetry + fact_report
ArtifactsReady --> Viewing: web / скачать JSON
ArtifactsReady --> VerdictUnresolved: GET .../verdict
VerdictUnresolved --> [*]: verdict = UNRESOLVED\nblockers fidelity / V3
6. fidelity_class: зачем и как читать¶
BRD требует пять полей на каждой выходной величине: value, unit, fidelity_class, depends_on, validation_level (SIM-BIZ-04, §7.2 BRD).
6.1. Три класса происхождения числа¶
Допустимые значения заданы в коде (../../../src/geoscan_sim/fidelity/quantity.py):
fidelity_class |
Смысл | Пример в fact_report |
|---|---|---|
measured |
Измерено (в поставке почти нет — нет реальных логов) | — |
derived |
Вычислено из модели и журнала | energy_used_frac.actual |
assumed |
Взято из допущения / сценария / плана | wind_speed_ms, planned метрики |
Правило BRD §7.2: величина с assumed или с validation_level ≤ V2 не может быть основанием для вердикта NO-GO — она только объясняет отчёт и попадает в перечень ограничений.
6.2. Связка с пирамидой V1…V6¶
Пирамида валидации описана в docs/00-brief/02-vision-and-business.md и сводная таблица «класс величин → макс. V» — в BRD §7.2. Практически:
- эталоны
sim validate --referenceзакрывают V1–V2 (и частично V4 по РЭ); - прогон + независимый validator/import boundary — задел под V3 для геометрии;
- V6 (сверка с реальным полётом) недостижим — телеметрии нет.
Проверка полноты пометок на артефактах одного прогона (инструмент из репозитория):
.venv/bin/python tools/audit_fidelity_coverage.py /tmp/sim-doc-out2
Пример вывода:
ИТОГО 194071 0 0.00%
Отчётные артефакты: 0 из 119 без класса — 0.00%
Тест приёмки A-12: tests/test_fidelity_class.py (полный прогон s01 в pytest — долгий; аудит по каталогу — быстрый суррогат).
7. Честно: что готово, что нет¶
7.1. Вердикт приёмки 96-acceptance¶
Каталог simulate/docs/96-acceptance/ в этой ветке отсутствует (файл 00-verdict.md не найден). Опираемся на:
LIMITATIONS.md— шестой артефакт ТЗ с доказательствами по коду;docs/93-audit/00-CHECKLIST.md— корзина B/C;- текущее поведение API вердикта.
7.2. Сводка «можно показывать / нельзя обещать»¶
| Область | Статус | Доказательство |
|---|---|---|
Одиночный прогон sim run + артефакты |
Работает | Команда в §5, runner.run_plan_headless |
| Эталоны V-1…V-14 | Работает | sim validate --reference, все PASS в сессии документации |
fidelity_class на выходе |
Работает на прогоне s01 | audit_fidelity_coverage.py → 0 % без класса |
| Preflight (NFZ, клиренс, …) | Частично | tests/test_preflight_detection.py, не все слои ВП |
Покрытие в fact_report |
Частично / баг порядка | NOT_COMPUTED (B4) при наличии frames.jsonl |
| Makespan «факт» | Частично | suspicious_plan_copy, плановая сумма длительностей |
| Реальный рельеф GLO-30 | Не реализовано | fixtures/mirror/manifest.json → blocked |
sim batch, docker-стенд |
Не реализовано | sim batch → No such command |
| Трёхзначный вердикт NO-GO / NO-FINDINGS | Не реализовано | Всегда UNRESOLVED + blockers (../../../src/geoscan_sim/api/verdict.py) |
| Гроза / снег / полный contingency | Не реализовано | LIMITATIONS.md, grep по src/geoscan_sim |
Детальная матрица по подсистемам — в 02-readiness-matrix.md.
7.3. Что говорить на защите (из BRD §7.4)¶
Формулировка без завышения достоверности:
Модель сверена с руководством по эксплуатации и с независимой геометрией; с реальным полётом не сверялась. Числа с допущениями помечены
fidelity_classи перечислены вLIMITATIONS.md. Автоматический вердикт «план годен / не годен» сейчас намеренноUNRESOLVED.
8. Связанные документы¶
| Тема | Путь |
|---|---|
| Головной BRD симулятора | docs/90-final/01-business-requirements.md |
| Известные ограничения (ТЗ п.5) | LIMITATIONS.md |
| Метод «валидатор первым» (geoscan) | docs/task5/70-plan/01-validator-first.md |
| Глоссарий (ПАФС, ЛАФС, галс, GSD) | docs/task5/00-brief/03-glossary.md |