17 KiB
BRD: Enduro Trails — Фаза 3.1 «Улучшение роутинга»
Версия: 1.0
Дата: 2026-05-04
Автор: Стрим 🌊
Статус: На согласовании
1. Контекст и цели
Что уже есть (Фаза 2–3)
- OSRM с кастомным профилем
enduro.lua— один маршрут A→B, до 5 альтернатив - Роутинг предпочитает грунтовки (rate=100) и избегает асфальт (rate=1–4)
- Статистика покрытия: % грунт / асфальт / тропа
Проблемы
- Мало альтернативных маршрутов — OSRM часто даёт 1–2 варианта вместо 3–5. Пользователь видит один путь и не может сравнить
- Шлагбаумы не блокируют проезд —
result.barrier = trueдобавляет penalty, но маршрут всё равно идёт через шлагбаум. Эндурист не знает — открыт шлагбаум или нет - Тротуары включены в роутинг —
footwayrate=60, OSRM считает тротуары «проезжей» дорогой. В городе маршрут может пойти по тротуару — это незаконно и опасно - Нет визуального предупреждения — пользователь не видит где на маршруте шлагбаумы, броды, частные территории
Цель
Сделать роутинг безопасным и разнообразным: больше вариантов на выбор, нет маршрутов через шлагбаумы и тротуары, визуальные предупреждения об препятствиях.
2. Фичи
F-07: Исключить шлагбаумы из роутинга
Описание
Дороги с шлагбаумами (gate, bollard, lift_gate), блокпостами (border_control), цепями (chain), столбиками (cycle_barrier, motorcycle_barrier) полностью исключаются из графа OSRM. Маршрут никогда не пойдёт через шлагбаум.
Зачем
Шлагбаум может быть закрыт. Эндурист приезжает — и путь заблокирован. Приходится искать объезд на месте. Лучше сразу строить маршрут без шлагбаумов.
Use Cases
UC-07.1 — Маршрут без шлагбаумов
Слава строит маршрут через лесной массив. Раньше OSRM мог провести через дорогу с шлагбаумом. Теперь маршрут обходит шлагбаум, даже если путь длиннее.
UC-07.2 — Шлагбаум на единственной дороге
Единственная дорога к точке B перекрыта шлагбаумом. OSRM не находит маршрут. Пользователь видит: «Маршрут не найден: на пути есть препятствия (шлагбаумы)».
Исключаемые типы препятствий (OSM tag barrier=*)
| barrier | Описание | Действие |
|---|---|---|
gate |
Ворота, шлагбаум | ❌ Исключить |
lift_gate |
Шлагбаум с подъёмником | ❌ Исключить |
bollard |
Столбик / боллард | ❌ Исключить |
chain |
Цепь | ❌ Исключить |
cycle_barrier |
Велобарьер | ❌ Исключить |
motorcycle_barrier |
Мотобарьер | ❌ Исключить |
border_control |
Блокпост | ❌ Исключить |
cattle_grid |
Коровья решётка | ⚠️ Оставить (проезжая) |
ford |
Брод | ⚠️ Оставить (отдельная фича) |
block |
Блок | ❌ Исключить |
Реализация
В enduro.lua → process_node: заменить result.barrier = true на result.barrier = false + result.forward_mode = mode.inaccessible (полная блокировка ноды).
function process_node(profile, node, result)
local barrier = node:get_value_by_key("barrier")
if barrier == "gate" or barrier == "bollard" or barrier == "lift_gate"
or barrier == "chain" or barrier == "cycle_barrier"
or barrier == "motorcycle_barrier" or barrier == "border_control"
or barrier == "block" then
result.barrier = false -- НЕ penalty, а полный запрет
result.forward_mode = mode.inaccessible
result.backward_mode = mode.inaccessible
end
end
⚠️ Требуется пересборка OSRM графа (~40 мин). Это разовая операция.
F-08: Исключить тротуары из роутинга
Описание
Дороги с highway=footway, highway=pedestrian, highway=steps исключаются из графа OSRM. Маршрут не пойдёт по тротуару или пешеходной улице.
Зачем
Тротуар — не дорога для мотоцикла. В городе OSRM может провести маршрут по тротуару (rate=60 — довольно привлекательный). Это незаконно, опасно для пешеходов, и эндуристу не нужно.
Use Cases
UC-08.1 — Маршрут без тротуаров
Слава строит маршрут в черте города. Раньше OSRM мог провести по тротуару вдоль дороги. Теперь маршрут идёт только по проезжей части.
UC-08.2 — Пешеходная зона
Точка B находится на пешеходной улице. OSRM не может доехать прямо до точки — строит маршрут до ближайшей проезжей дороги.
Исключаемые типы дорог
| highway | Описание | Действие |
|---|---|---|
footway |
Тротуар / пешеходная дорожка | ❌ Исключить из роутинга |
pedestrian |
Пешеходная зона / улица | ❌ Исключить |
steps |
Лестница | ❌ Исключить |
corridor |
Крытый переход | ❌ Исключить |
Реализация
В enduro.lua → process_way: убрать footway из highway_rate и добавить проверку:
-- Дороги, исключаемые из роутинга (тротуары и пешеходные зоны)
local excluded_highways = {
footway = true,
pedestrian = true,
steps = true,
corridor = true,
}
function process_way(profile, way, result)
local highway = way:get_value_by_key("highway")
if not highway then return end
-- Исключаем тротуары и пешеходные зоны
if excluded_highways[highway] then return end -- пропускаем эту дорогу
local rate = highway_rate[highway]
if not rate then return end
...
⚠️ Требуется пересборка OSRM графа (~40 мин). Вместе с F-07 — одна пересборка.
F-09: Больше альтернативных маршрутов
Описание
Предложить пользователю до 5 существенно разных маршрутов, не только варианты от OSRM.
Зачем
OSRM alternatives даёт маршруты, которые расходятся на ~5–10% пути. Они визуально почти одинаковые. Пользователь хочет видеть принципиально разные пути: через лес А vs через лес Б vs через поля.
Подход
Шаг 1: Максимизировать OSRM-альтернативы
- Запросить
alternatives=5сradiusesдля лучшего снэппинга - При
TooBig— fallback на 3→1 (уже реализовано)
Шаг 2: Дополнительно — штрафование уже найдённых путей После получения первого маршрута — запросить OSRM повторно, но «заштрафить» дороги, через которые прошёл первый маршрут. Для этого:
- Увеличить вес дорог на маршруте (concept: «penalized re-query»)
- OSRM
annotations=trueвозвращает список way-узлов маршрута
Реализация (упрощённая):
- Запрос 1:
alternatives=5— получаем N маршрутов от OSRM - Если N < 3 — сделать повторный запрос с другим
snappingилиradiuses - Дедупликация: убрать маршруты, которые отличаются менее чем на 10% от уже найденных (по дистанции)
Критерий «существенно разный маршрут»:
- Отличается по дистанции на ≥10%
- Или проходит через разные ключевые точки (определяется по перекрытию геометрии: Jaccard similarity < 0.7)
Use Cases
UC-09.1 — Выбор из 3+ маршрутов
Слава строит маршрут 200 км. Получает 3 варианта: через лес (180 км, 92% грунт), через поля (210 км, 95% грунт), комбинированный (195 км, 85% грунт). Каждый визуально отличается на карте.
UC-09.2 — Только один путь
Точки A и B в одном лесу — один разумный путь. Система показывает 1 маршрут, подпись «Альтернативных маршрутов не найдено».
F-10: Слой препятствий на карте
Описание
На карте отображаются шлагбаумы, броды, блокпосты как отдельный слой с иконками. Пользователь видит препятствия ДО построения маршрута.
Зачем
Даже если маршрут обходит шлагбаум — полезно видеть где они. «Ага, тут шлагбаум, значит объехать можно через ту грунтовку». Без слоя — пользователь не знает о препятствиях пока не упрётся.
Use Cases
UC-10.1 — Просмотр препятствий
Слава включает слой «Препятствия». На карте появляются иконки: 🚧 шлагбаумы, 🌊 броды, ⛔ блокпосты. Видит что на интересной грунтовке стоит шлагбаум — решает построить маршрут через другую дорогу.
UC-10.2 — Препятствие на маршруте
Маршрут построен. Слава видит брод на маршруте. Кликает — попап: «Брод. Возможен проезд только в сухое время года». Решает выбрать другой маршрут.
Источники данных (OSM теги)
| Тип | OSM тег | Иконка | Цвет |
|---|---|---|---|
| Шлагбаум | barrier=gate/lift_gate |
🚧 | 🟠 оранжевый |
| Столбик | barrier=bollard/block |
⛔ | 🔴 красный |
| Брод | ford=yes или highway=ford |
🌊 | 🔵 голубой |
| Блокпост | barrier=border_control |
🛂 | 🔴 красный |
| Частная территория | access=private/no |
🔒 | 🟡 жёлтый |
Реализация
Бэкенд:
- Добавить парсинг препятствий в
scripts/parse.py— таблицаobstacles:
CREATE TABLE obstacles (
id INTEGER PRIMARY KEY,
osm_id INTEGER,
obstacle_type TEXT, -- gate, bollard, ford, border_control, private
name TEXT,
lon REAL,
lat REAL
);
CREATE INDEX idx_obstacles_bbox ON obstacles(lon, lat);
- Добавить POI-слой
obstaclesвbuild_mvt()— точки сobstacle_typeв props.
Фронт:
- Слой в style.json:
obstacles-circles— цветные круги по типу - Кнопка в хедере: 🚧 Препятствия (toggle on/off)
- Попап при клике: тип, название, предупреждение
⚠️ Требует перепарсинга PBF — добавить extract точек barrier из OSM данных.
3. Приоритет реализации
| # | Фича | Приоритет | Сложность | Зависимости |
|---|---|---|---|---|
| F-07 | Исключить шлагбаумы | 🔴 Высокий | Низкая (lua) + средняя (пересборка графа ~40 мин) | Пересборка OSRM |
| F-08 | Исключить тротуары | 🔴 Высокий | Низкая (lua) + средняя (пересборка) | Пересборка OSRM |
| F-09 | Больше альтернатив | 🟡 Средний | Высокая (алгоритм) | — |
| F-10 | Слой препятствий | 🟡 Средний | Средняя (parse + style + UI) | Перепарсинг PBF |
Рекомендуемый порядок:
- F-07 + F-08 вместе — одна правка
enduro.lua, одна пересборка графа - F-09 — улучшение альтернативных маршрутов (на уже исправленном графе)
- F-10 — слой препятствий (перепарсинг + UI)
4. Пересборка OSRM графа
F-07 и F-08 требуют пересборки — это ~40 минут на сервере mva154.
Порядок:
- Обновить
enduro.lua(убрать footway из rate + заблокировать barrier nodes) - Запустить пересборку:
cd /home/slin/enduro-trails/osrm
docker compose run --rm osrm-prepare
- Перезапустить роутер:
docker compose restart osrm-routed
- Проверить: маршрут не идёт через шлагбаумы и тротуары
5. Открытые вопросы для Славы
-
Шлагбаумы — всегда блокировать? Некоторые шлагбаумы открыты всегда (например, на въезде в дачный посёлок). Полная блокировка означает что маршрут НИКОГДА не пойдёт через шлагбаум. Ок, или хочешь опцию «показывать предупреждение но не блокировать»?
-
Тротуары vs тропы —
footwayв лесу это тропа (можно проехать),footwayв городе это тротуар (нельзя). Различать по контексту (город/лес) сложно. Предлагаю: исключить всеfootway, а тропы оставить какpath/bridleway(rate=85/90). Норм? -
Слой препятствий — стоит ли перепарсить PBF сейчас, или отложить на потом? Перепарсинг ~30 мин + пересборка OSRM ещё ~40 мин. Итого ~70 мин работы сервера.
-
Альтернативы — алгоритм — проще всего оставить OSRM alternatives как есть, но добавить дедупликацию (убрать визуально одинаковые). Или хочешь чтобы я исследовала «penalized re-query» подход для принципиально разных маршрутов? Это сложнее и дольше.
Документ готов к согласованию. После ответов — обновлю и передам Dev-агенту.