Skip to content

Commit

Permalink
Merge pull request #14 from nextmv-io/merschformann/fix-osrm-no-route
Browse files Browse the repository at this point in the history
Adds fallback for OSRM "NoRoute" errors
  • Loading branch information
merschformann authored Oct 24, 2024
2 parents a20bc78 + a9676fe commit 21dde0c
Showing 1 changed file with 27 additions and 5 deletions.
32 changes: 27 additions & 5 deletions nextplot/osrm.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,18 @@ class OsrmRouteRequest:


@dataclasses.dataclass
class OsrRouteResponse:
class OsrmRouteResponse:
paths: list[list[types.Position]]
distances: list[float]
durations: list[float]
zero_distance: bool = False
no_route: bool = False


def query_route(
endpoint: str,
route: OsrmRouteRequest,
) -> OsrRouteResponse:
) -> OsrmRouteResponse:
"""
Queries a route from the OSRM server.
"""
Expand All @@ -40,9 +41,26 @@ def query_route(
# Query OSRM
try:
response = requests.get(url)
# If no route was found, use as-the-crow-flies fallback
if response.status_code == 400 and response.json()["code"] == "NoRoute":
print(
f"Warning: OSRM was unable to find a route for {[(p.lat, p.lon) for p in route.positions]}"
+ "(lat,lon ordering), using as-the-crow-flies fallback"
)
paths, distances, durations = [], [], []
for f, t in zip(route.positions, route.positions[1:], strict=False):
paths.append(
[types.Position(lon=f.lon, lat=f.lat, desc=None), types.Position(lon=t.lon, lat=t.lat, desc=None)]
)
distances.append(common.haversine(f, t))
durations.append(common.haversine(f, t) / TRAVEL_SPEED)
return OsrmRouteResponse(paths=paths, distances=distances, durations=durations, no_route=True)
# Make sure we are not getting an error
response.raise_for_status()
except requests.exceptions.RequestException as e:
print(f"Error querying OSRM at {url_base}:", e)
if response:
print(response.text)
sys.exit(1)
result = response.json()
if result["code"] != "Ok":
Expand Down Expand Up @@ -85,13 +103,13 @@ def query_route(
print(f"Warning: number of legs ({len(legs)}) does not match number of positions ({len(route.positions)} - 1)")

# Extract route
return OsrRouteResponse(paths=legs, distances=distances, durations=durations, zero_distance=all_zero_distances)
return OsrmRouteResponse(paths=legs, distances=distances, durations=durations, zero_distance=all_zero_distances)


def query_routes(
endpoint: str,
routes: list[types.Route],
) -> list[OsrRouteResponse]:
) -> list[OsrmRouteResponse]:
"""
Queries multiple routes from the OSRM server.
Expand All @@ -103,13 +121,17 @@ def query_routes(

# Query all routes
reqs = [OsrmRouteRequest(positions=route.points) for route in routes]
zero_distance_routes = 0
zero_distance_routes, no_route_routes = 0, 0
for r, req in enumerate(reqs):
result = query_route(endpoint, req)
routes[r].legs = result.paths
routes[r].leg_distances = result.distances
routes[r].leg_durations = result.durations
if result.zero_distance:
zero_distance_routes += 1
if result.no_route:
no_route_routes += 1
if zero_distance_routes > 0:
print(f"Warning: {zero_distance_routes} / {len(routes)} routes have zero distance according to OSRM")
if no_route_routes > 0:
print(f"Warning: {no_route_routes} / {len(routes)} routes could not be found by OSRM")

0 comments on commit 21dde0c

Please sign in to comment.