Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/tests/complex/netconvert/osm_sidewalk_access/runner.py
428379 views
1
#!/usr/bin/env python
2
# -*- coding: utf-8 -*-
3
# Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
4
# Copyright (C) 2008-2026 German Aerospace Center (DLR) and others.
5
# This program and the accompanying materials are made available under the
6
# terms of the Eclipse Public License 2.0 which is available at
7
# https://www.eclipse.org/legal/epl-2.0/
8
# This Source Code may also be made available under the following Secondary
9
# Licenses when the conditions for such availability set forth in the Eclipse
10
# Public License 2.0 are satisfied: GNU General Public License, version 2
11
# or later which is available at
12
# https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
13
# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
14
15
# @file runner.py
16
# @author Michael Behrisch
17
# @date 2026-03-25
18
19
"""
20
Test netconvert OSM import for correct pedestrian access handling under
21
various sidewalk tag combinations. Refs https://github.com/eclipse-sumo/sumo/issues/17758
22
23
Rules under test:
24
- sidewalk=separate/separated -> pedestrians must NOT be on the road
25
(unless foot=yes explicitly overrides)
26
- foot=no / foot=use_sidepath -> pedestrians excluded from road
27
- foot=yes -> pedestrians explicitly allowed on road
28
- sidewalk=both/left/right -> separate sidewalk lane added under
29
--osm.sidewalks; pedestrians off road lanes
30
- No sidewalk tags -> pedestrians follow typemap defaults
31
"""
32
33
from __future__ import print_function
34
import os
35
import subprocess
36
import sys
37
38
if "SUMO_HOME" in os.environ:
39
sys.path.append(os.path.join(os.environ["SUMO_HOME"], "tools"))
40
import sumolib # noqa
41
42
OSM_TEMPLATE = """\
43
<?xml version="1.0" encoding="UTF-8"?>
44
<osm version="0.6">
45
<node id="1" lat="51.500" lon="0.000"/>
46
<node id="2" lat="51.501" lon="0.000"/>
47
<way id="101">
48
<nd ref="1"/>
49
<nd ref="2"/>
50
<tag k="highway" v="secondary"/>
51
<tag k="lanes" v="2"/>
52
<tag k="maxspeed" v="50"/>
53
<tag k="name" v="Test Road"/>
54
{tags}
55
</way>
56
</osm>
57
"""
58
59
60
def _is_sidewalk_lane(lane):
61
"""True if the lane is a dedicated sidewalk (pedestrian-only lane)."""
62
return lane.getPermissions().issubset({"pedestrian", "wheelchair"})
63
64
65
def run_case(extra_tags, use_osm_sidewalks, guess_sidewalks, typemap):
66
# Build OSM XML
67
tag_lines = "\n".join(' <tag k="{}" v="{}"/>'.format(k, v) for k, v in extra_tags)
68
osm_text = OSM_TEMPLATE.format(tags=tag_lines)
69
with open("osm.xml", "w") as fh:
70
fh.write(osm_text)
71
72
# Run netconvert
73
cmd = [sumolib.checkBinary("netconvert"), "--osm-files", "osm.xml", "--output-file", "test.net.xml"]
74
if typemap:
75
cmd += ["--type-files", typemap]
76
if use_osm_sidewalks:
77
cmd.append("--osm.sidewalks")
78
if guess_sidewalks:
79
cmd.append("--sidewalks.guess")
80
subprocess.check_call(cmd, stdout=subprocess.DEVNULL)
81
82
# Inspect the network
83
net = sumolib.net.readNet("test.net.xml")
84
any_sidewalk = False
85
any_ped_on_road = False
86
for edge in net.getEdges():
87
lanes = edge.getLanes()
88
sidewalk_lanes = [la for la in lanes if _is_sidewalk_lane(la)]
89
road_lanes = [la for la in lanes if not _is_sidewalk_lane(la)]
90
if sidewalk_lanes:
91
any_sidewalk = True
92
if any(la.allows("pedestrian") for la in road_lanes):
93
any_ped_on_road = True
94
print("tags:", extra_tags, " ".join(["netconvert"] + cmd[5:]).replace(os.environ["SUMO_HOME"], ""))
95
print(" sidewalk:", any_sidewalk, "peds_on_road:", any_ped_on_road)
96
97
98
if __name__ == "__main__":
99
pedmap = os.path.join(os.environ["SUMO_HOME"], "data", "typemap", "osmNetconvertPedestrians.typ.xml")
100
for osm in (False, True):
101
for guess in (False, True):
102
for typemap in (None, pedmap):
103
for sidewalk in (None, "yes", "no", "both", "left", "right", "separate", "none"):
104
sidewalk_tag = [("sidewalk", sidewalk)] if sidewalk else []
105
for foot in (None, "yes", "no", "designated", "use_sidepath"):
106
foot_tag = [("foot", foot)] if foot else []
107
run_case(sidewalk_tag + foot_tag, osm, guess, typemap)
108
109