10 KiB
План: точность высот/уклона в предпросмотре + безопасность маршрутов (brouter)
Context
Пять замечаний по предпросмотру маршрута и маршрутизации (baldav):
- Режим «уклон» врёт: рисует крутой подъём там, где его нет (и наоборот). Высоты из DEM квантуются по ячейкам 30м, точки внутри ячейки имеют одну высоту, на границе - скачок, и вся Δ падает на один короткий сегмент = ложный крутой уклон. (Второе - «не рисует где есть» - предел разрешения SRTM 30м, не чинится без более точного DEM.)
- Спуски красить иначе: сейчас уклон красится по МОДУЛЮ (вверх и вниз одинаково). Спуски по направлению движения должны уходить из зелёного в голубой -> navy.
- brouter трижды завёл к бродам/ледяной воде (ford - теги OSM в данных brouter, не SRTM). Нужно: избегать бродов/сложных троп/крутых спусков по умолчанию, ПОКАЗЫВАТЬ оставшиеся опасные участки на предпросмотре заранее, и дать опцию «разрешить (испытать удачу)». Полный объём.
- Кнопка объезда ↪ на записи срабатывает всегда и ведёт «к первому вейпоинту»: нет проверки, что впереди реально есть затык, а цель выбирается по глобально ближайшей точке маршрута (ломается на петлях и вдали от маршрута).
- Уточнять высоты по многим проездам. Решение пользователя: база - SRTM, медиана высот из треков берётся ТОЛЬКО как поправка вверх/вниз к SRTM (не замена), там где катал.
Общее: раскраска уклон/высота и расчёт уклона - в ОДНИХ функциях, используются в предпросмотре маршрута, детали записанного трека, редакторе и на экране записи. Правка общих функций чинит везде; проверить надо каждое место (WT4: починил A - проверь B и C в той же области).
Критичные файлы и функции
frontend/js/gps.js:GPS.routeElevStats(расчётgrades[]/smoothed[]),GPS.filterAndSmoothAlt(сглаживание высот - сейчас по ТОЧКАМ, окно 5),GPS.fillGaps/get_ride_graph(сетка ~20м - база для п.5).frontend/js/main.js:routeSlopeColor+ROUTE_SLOPE_BANDS+slopeLegendHtml(п.2),drawRoutePolyline/showRouteDetail(предпросмотр),rejoinReroute(п.4),fetchElevations(п.5).src-tauri/gen/android/app/src/main/assets/brouter/profiles2/trekking.brf(п.3, избегание) + копия вtools/brouter-web-staging/profiles2/trekking.brf(единый источник - править обе).MainActivity.ktrouteBrouter(п.3, вытащить теги путей изOsmTrack.messageListрядом с GPX).src-tauri/src/lib.rsget_ride_graph/новый агрегат высот (п.5).
Подход по пунктам
П.1 - уклон по дистанционному окну (вместо ступенек ячейки)
В GPS.routeElevStats считать grades[i] как центральную разность высоты по РАССТОЯНИЮ окном
~30м (одна ячейка DEM), а не между соседними точками: для точки i найти вперёд j и назад k так,
чтобы суммарная дистанция >= W (конфиг gradeWindowM, дефолт 30), grade = (smoothed[j]-smoothed[k])/dist.
Так одиночная ступенька ячейки размазывается по всей ячейке. maxGrade и профиль - по тем же
сглаженным. «Не рисует где есть» - записать как предел разрешения SRTM; реально улучшает п.5.
П.2 - направленная раскраска спусков
routeSlopeColor(gradePct) сделать знакочувствительной: подъём (>=0) - тёплый веер (как сейчас
green->yellow->red->brown->black), спуск (<0) - холодный веер green->cyan->blue->navy по модулю.
Два массива полос + обновить slopeLegendHtml (две шкалы: подъём/спуск). Направление = порядок
точек (он же направление движения в треке/маршруте).
П.3 - brouter: избегать + показывать + опция
- Профиль
trekking.brf: добавить штрафы (черезassignв---context:way) наford=yes, пересечение waterway без моста,tracktype=grade4|grade5,trail_visibility=bad|horrible, высокийsac_scale/mtb:scale; крутой спуск уже есть черезdownhillcost. Параметр%allow_adventure%(дефолт false) - при true штрафы снимаются («испытать удачу»). - Показ опасного: в
routeBrouterрядом с GPX вернуть JSON тегов сегментов изOsmTrack.messageList(btools даёт теги путей); нужен короткий спайк - проверить, что messageList заполняется и какие поля. На превью (drawRoutePolyline/showRouteDetail) пометить участки ford/вода/крутой спуск отдельным стилем + счётчик «броды: N, крутые спуски: M». Тумблер «разрешить броды/сложные тропы» (localStorage +%allow_adventure%в вызов BRouter). - Если messageList тегов не отдаёт - запасной путь: крутые спуски берём из уклона (уже есть), броды - пометить честно как «не выяснено без тегов» и решить отдельно. Спайк решает.
П.4 - объезд ↪ только при реальном затыке впереди
В rejoinReroute: (а) спроецировать текущую позицию на маршрут -> индекс прогресса (не глобально
ближайший - ломается на петлях), учитывать направление движения; (б) объезд строить ТОЛЬКО если
есть nogo на маршруте ВПЕРЕДИ в пределах окна (напр. до +1.5км по маршруту); иначе toast «впереди
затыка нет» и ничего не строить. Цель rejoin - первая точка маршрута за nogo + запас.
П.5 - поправка высот по проездам (база SRTM + медиана как сдвиг)
- Rust (
lib.rs, рядом сget_ride_graph): агрегат по сетке ~20-30м изgps_points.altitude: на ячейку median(alt) и count. Новый command, напр.get_elev_correction. - JS (
fetchElevations/routeElevStats): после получения SRTM-высот, где у ячейки count>=порога, скорректировать:elev = SRTM + smooth(median_ridden - SRTM). SRTM остаётся базой и формой; треки только двигают вверх/вниз где катал. Порог проездов и сглаживание сдвига - в конфиг. - GPS-высота шумная -> median по многим точкам/проездам + отбрасывание выбросов; барометр DJI (отдельный TODO) улучшит позже.
Порядок и коммиты
Пункты независимы. Делать по одному, коммит на каждый (commit-before-test), сборка через
./build.sh -d -i android, проверка на телефоне; follow-up фиксы - отдельными коммитами.
Рекомендуемый порядок: 2 (быстрый, визуальный) -> 1 -> 4 -> 5 -> 3 (самый большой, со спайком).
Проверка (на устройстве + где можно на ПК)
- П.1/П.2: открыть предпросмотр реального маршрута с известным рельефом; переключить уклон/высота; убедиться, что крутой цвет только на реально крутом, спуски холодные. Вёрстку/цвета можно глянуть на ПК в dev (reference_verify_record_screen). Проверить ВСЕ места раскраски: превью маршрута, деталь записанного трека, редактор, экран записи.
- П.3: построить маршрут через известный брод/грунтовку -> по умолчанию объезжает; включить «разрешить» -> ведёт через, но помечено на превью. Спайк messageList - логом из routeBrouter.
- П.4: на записи вдали от затыка нажать ↪ -> «впереди затыка нет»; поставить nogo на маршруте впереди -> объезд строится за него, не к старту.
- П.5: взять ячейки, где много проездов, сравнить профиль до/после коррекции; где не катал - SRTM.