No description
  • JavaScript 96.9%
  • CSS 2.9%
  • HTML 0.2%
Find a file
malice 2efc5fa52e
MVUM Layer 3c: surface-change transition candidates (#27)
Extract surface-category boundaries along the winning single-mode polyline as
additional multi-modal-Auto transition candidates, so Auto can suggest "pull off
where the pavement turns to dirt and switch vehicles" trips even with no MVUM
trailhead nearby. Candidates share the trailhead record shape, so _try_hybrid_auto
consumes them with no restructuring.

Backend-only:
- mvum_surface_change.py: get_surface_change_candidates(coords, valhalla_url) walks
  the polyline through Valhalla trace_attributes (action=include, costing=auto,
  edge.surface/road_class/use/begin_shape_index/end_shape_index). classify_surface
  buckets each edge into PAVED/UNPAVED/TRACK/TRAIL; adjacent edges are grouped into
  runs, runs shorter than MIN_STRETCH_M (100 m, measured by haversine along the input
  coords) are collapsed to suppress noise, and each surviving category boundary emits
  {lat, lon, name: "Surface change: <from>-><to>", road_class}. Capped at 10. Adds an
  encode_polyline6 helper (the inverse of the router _decode_polyline method).
- router.py: _try_hybrid_auto concatenates trailheads + surface-change candidates,
  then re-sorts by distance to the route and applies the existing
  HYBRID_MAX_TRAILHEADS cap. Probing logic unchanged.

Verified trace_attributes on the live Valhalla before coding (returns the requested
edge fields). Two empirically-driven deviations from the spec, flagged:
1. This Valhalla normalizes OSM surface tags into its own enum (paved_smooth/paved/
   paved_rough/compacted/dirt/gravel/path/impassable); classify_surface keys on that
   enum AND the raw OSM names for robustness.
2. Urban alleys come back as road_class=service_other with surface=paved_smooth, so
   the service_other->TRACK rule is gated on a non-paved surface to avoid classifying
   paved alleys as tracks.

Tests: test_mvum_surface_change.py (6) -- classify spot-check, paved->unpaved boundary,
sub-100 m noise suppression, uniform-surface empty, encoder round-trip vs the router
decoder, and hybrid integration (both trailhead + surface candidates probed). Full
offroute suite: 77 passed.

Co-authored-by: Matt <mj@k7zvx.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 23:52:08 -06:00
backend MVUM Layer 3c: surface-change transition candidates (#27) 2026-05-25 23:52:08 -06:00
frontend MVUM Layer 3a: multi-modal Auto via MVUM trailhead transitions (#26) 2026-05-25 22:49:13 -06:00