Skip to content

Commit 6d02db9

Browse files
authored
Feat/valhalls custom speed (#513)
* speed override * rm unused import * fix broken apt sources * fix broken apt sources
1 parent 6ede1f4 commit 6d02db9

2 files changed

Lines changed: 106 additions & 3 deletions

File tree

Dockerfile

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ ENV UV_LINK_MODE=copy
1616
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
1717

1818
# Install heavy C++ compilers required for building python wheels
19-
RUN apt-get update && \
19+
RUN grep -lr 'apache.jfrog.io' /etc/apt/sources.list.d/ | xargs -r rm -f && \
20+
apt-get update && \
2021
apt-get install -y --no-install-recommends \
2122
python3-pip python3-dev gcc g++ git cmake libgeos-dev
2223

@@ -61,7 +62,8 @@ COPY --from=python-builder --chown=1000:1000 /rapida/.venv /rapida/.venv
6162

6263
# Install ONLY runtime dependencies (Playwright needs system UI libraries for Chromium)
6364
# We do this in one layer and immediately purge the apt cache
64-
RUN apt-get update && \
65+
RUN grep -lr 'apache.jfrog.io' /etc/apt/sources.list.d/ | xargs -r rm -f && \
66+
apt-get update && \
6567
playwright install chromium --with-deps && \
6668
apt-get autoremove -y && apt-get clean && rm -rf /var/lib/apt/lists/*
6769

rapida/connectivity/graph.py

Lines changed: 102 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,66 @@
66
from valhalla.config import _sanitize_config, default_config
77
from typing import Union
88
from pathlib import Path
9-
9+
import re
10+
import logging
11+
import sys
12+
import valhalla
13+
logger = logging.getLogger(__name__)
14+
15+
DEFAULT_SPEEDS = {
16+
"motorway": 105,
17+
"trunk": 90,
18+
"primary": 75,
19+
"secondary": 60,
20+
"tertiary": 50,
21+
"unclassified": 40,
22+
"residential": 35,
23+
"service": 25
24+
}
25+
# by CB guys
26+
# SPEED_OVERRIDES = \
27+
# {
28+
# "motorway": 60,
29+
# "trunk": 50,
30+
# "primary": 35,
31+
# "secondary": 25,
32+
# "tertiary": 20,
33+
# "unclassified": 15,
34+
# "residential": 12,
35+
# "service": 8
36+
# }
37+
38+
39+
40+
def fetch_default_lua():
41+
import urllib.request
42+
url = "https://raw.githubusercontent.com/valhalla/valhalla/refs/heads/master/lua/graph.lua"
43+
with urllib.request.urlopen(url) as response:
44+
return response.read().decode('utf-8')
45+
46+
def get_speed_overrides() -> dict:
47+
"""
48+
Returns a dictionary of {valhalla_index: final_speed}
49+
merging defaults with any os.environ MJOLNIR_*_SPEED overrides.
50+
"""
51+
# Since Python 3.7, dicts maintain insertion order.
52+
# roads.index("motorway") will correctly yield 0.
53+
roads = list(DEFAULT_SPEEDS.keys())
54+
final_speeds = {}
55+
56+
for env_key, env_val in os.environ.items():
57+
if env_key.startswith("MJOLNIR_") and env_key.endswith("_SPEED"):
58+
try:
59+
_, road_class, _ = env_key.lower().split('_')
60+
if road_class in roads and env_val.isdigit():
61+
default_speed = DEFAULT_SPEEDS[road_class]
62+
final_speeds[road_class] = int(env_val)
63+
logger.warning(f'Overriding default speed for {road_class} road type from {default_speed} to {env_val}')
64+
except ValueError:
65+
# Safely ignore env vars that don't match the exact 3-part split
66+
continue
67+
# Convert the text tags back to Valhalla's expected integer indices
68+
return {roads.index(road): speed for road, speed in final_speeds.items()}
1069

1170
def get_config_fixed(
1271
tile_extract: Union[str, Path] = "valhalla_tiles.tar",
@@ -79,6 +138,48 @@ async def compile_valhalla_graph(pbf_path: str, dst_dir: str, progress=None) ->
79138
valhalla_conf["service_limits"]["isochrone"]["max_locations"] = 5000
80139
# ---------------------------------------------------------
81140

141+
# ---------------------------------------------------------
142+
# APPLY AUTOMATED JSON SPEED OVERRIDES
143+
# ---------------------------------------------------------
144+
overrides = get_speed_overrides()
145+
146+
if overrides:
147+
# Merge overrides with the defined default_speed fallback
148+
default_vals = list(DEFAULT_SPEEDS.values())
149+
way_speeds = [overrides.get(i, default_vals[i]) for i in range(8)]
150+
151+
# Valhalla's C++ parser strictly requires ALL schema keys to exist.
152+
# Python 'None' outputs as JSON 'null', which tells Valhalla to safely ignore
153+
# these fields and fall back to its internal heuristics.
154+
null_array_5 = [None] * 5
155+
null_array_8 = [None] * 8
156+
157+
speed_profile = {
158+
"way": way_speeds,
159+
"link_exiting": null_array_5,
160+
"link_turning": null_array_5,
161+
"roundabout": null_array_8,
162+
"driveway": None,
163+
"alley": None,
164+
"parking_aisle": None,
165+
"drive-through": None
166+
}
167+
168+
speeds_config_path = os.path.join(dst_dir, "default_speeds.json")
169+
speed_schema = [
170+
{
171+
"rural": speed_profile,
172+
"suburban": speed_profile,
173+
"urban": speed_profile
174+
}
175+
]
176+
177+
with open(speeds_config_path, "w") as f:
178+
json.dump(speed_schema, f, indent=4)
179+
180+
valhalla_conf["mjolnir"]["default_speeds_config"] = speeds_config_path
181+
# ---------------------------------------------------------
182+
82183
with open(config_path, "w") as f:
83184
json.dump(valhalla_conf, f, indent=4)
84185

0 commit comments

Comments
 (0)