|
6 | 6 | from valhalla.config import _sanitize_config, default_config |
7 | 7 | from typing import Union |
8 | 8 | 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()} |
10 | 69 |
|
11 | 70 | def get_config_fixed( |
12 | 71 | 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) -> |
79 | 138 | valhalla_conf["service_limits"]["isochrone"]["max_locations"] = 5000 |
80 | 139 | # --------------------------------------------------------- |
81 | 140 |
|
| 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 | + |
82 | 183 | with open(config_path, "w") as f: |
83 | 184 | json.dump(valhalla_conf, f, indent=4) |
84 | 185 |
|
|
0 commit comments