Skip to content

feat(backend,web): tuned bike custom model on GraphHopper 12#72

Merged
cafca merged 1 commit into
mainfrom
claude/competent-tereshkova-c8be04
Apr 26, 2026
Merged

feat(backend,web): tuned bike custom model on GraphHopper 12#72
cafca merged 1 commit into
mainfrom
claude/competent-tereshkova-c8be04

Conversation

@cafca
Copy link
Copy Markdown
Owner

@cafca cafca commented Apr 26, 2026

Summary

  • Replace the legacy vehicle: bike, weighting: custom profile with a single Add Fathom analytics via configurable build-time env var #12-style custom-model bike profile mounted from backend/custom_models/beebeebike.json.
  • Migrate the GraphHopper config to the GH 12 schema: drop vehicle: / weighting:, nest turn_costs: { vehicle_types: [bicycle], u_turn_costs: 20 }, register custom models via custom_models.directory: /custom_models.
  • Lower the web "Route directness" default from 70 → 60 to match the model's distance_influence so first-load behavior is consistent (the slider can still override per request).

What the custom model does

Layered on top of GH's built-in bike_priority baseline, it applies these multipliers:

Priority

  • Wrong-way oneway enforcement: !bike_access && (!backward_bike_access || roundabout) → 0, with the asymmetric oneway:bicycle=no case allowed at 0.2.
  • Access penalties: bike_road_access == PRIVATE → 0.2; road_access FORESTRY/AGRICULTURAL → 0.6, MILITARY → 0.1.
  • road_environment FERRY → 0.3, FORD → 0.2.
  • Hard block: mtb_rating > 2 → 0 (no T2+ MTB segments).
  • Cycle infra boost: cycleway == TRACK → 1.3, cycleway == LANE → 1.1.
  • Comfort: get_off_bike → 0.6; surface COBBLESTONE → 0.5, loose surfaces SAND/GROUND/DIRT → 0.7.

Speed (km/h)

  • Base: limit_to: bike_average_speed.
  • Wrong-way contraflow: limit_to: 6.
  • Surface slowdowns: cobblestone × 0.75, paving stones / gravel × 0.9.
  • Slope shaping: >6° × 0.7, >12° × 0.5, <−6° × 1.2.

Other

  • distance_influence: 60 (slightly more willing to detour than the GH default of 70).
  • u_turn_costs: 20 (vs. GH default 10) to discourage tight reroutes.

Notably not in this model: no road_class tuning (TRUNK/PRIMARY/SECONDARY/etc. all use bike_priority as-is), no bike_network boost, no smoothness rules. Those can be added later if needed.

Notes for reviewers

  • profiles_ch: []: CH preparation cannot bake custom weighting with dynamic per-request priority rules (rated-area injection, optional distance_influence override). The per-request "ch.disable": true in routing.rs is now redundant but harmless.
  • compose.yml gains one bind mount: ./backend/custom_models:/custom_models:ro.
  • Mobile API surface unchanged — mobile clients keep sending rating_weight + optional distance_influence, no profile field.
  • Any future edit to a profile's priority/speed/distance_influence rules or to turn_costs/u_turn_costs requires wiping the GH cache (data/osm/berlin/graphhopper/) and reimporting; otherwise GH refuses to start with Profile 'bike' does not match.

Test plan

  • cargo test --lib (backend, 69 tests)
  • cargo clippy --all-targets -- -D warnings
  • npm test -- --run (web, 71 tests)
  • GraphHopper boots cleanly with the new config and serves /route for the bike profile
  • Manual smoke: a route in central Berlin returns geometry and respects oneway directionality

Replace the legacy single-vehicle bike profile with a custom-model bike
profile tuned for our use case (cycle infra preference, calm-street boost,
strong avoidance of trunk/primary, surface penalties). The image now ships
GraphHopper 12, which removed `vehicle:`/`weighting:` from profiles and
requires custom models to enforce per-direction access themselves; the
new config matches that schema and explicitly blocks wrong-way oneway
traversal via `bike_access` / `backward_bike_access`. The custom model
JSON is mounted into the GH container from `backend/custom_models/`.

CH preparation is disabled (`profiles_ch: []`) because custom weighting
with dynamic per-request priority rules (rated areas, distance_influence)
cannot be baked.

Web: lower the default route-directness from 70 to 60 to match the
custom model's distance_influence so first-load behavior is consistent.
@cafca cafca merged commit a921234 into main Apr 26, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant