Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/tests/complex/simpla/config/test.py
169686 views
1
#!/usr/bin/env python
2
# Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3
# Copyright (C) 2017-2025 German Aerospace Center (DLR) and others.
4
# This program and the accompanying materials are made available under the
5
# terms of the Eclipse Public License 2.0 which is available at
6
# https://www.eclipse.org/legal/epl-2.0/
7
# This Source Code may also be made available under the following Secondary
8
# Licenses when the conditions for such availability set forth in the Eclipse
9
# Public License 2.0 are satisfied: GNU General Public License, version 2
10
# or later which is available at
11
# https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12
# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13
14
# @file test.py
15
# @author Leonhard Luecken
16
# @author Mirko Barthauer
17
# @date 2017
18
19
import unittest as ut
20
import os
21
import sys
22
23
# Put tools into PYTHONPATH
24
sumoHome = os.environ.get("SUMO_HOME", os.path.abspath(
25
os.path.join(os.path.dirname(sys.argv[0]), '..', '..', '..', '..')))
26
sys.path.append(os.path.join(sumoHome, "tools"))
27
28
import traci # noqa
29
import sumolib # noqa
30
import simpla # noqa
31
import simpla._config as cfg # noqa
32
import simpla._reporting as rp # noqa
33
from simpla import SimplaException # noqa
34
from simpla._platoonmode import PlatoonMode # noqa
35
36
37
class TestConfig(ut.TestCase):
38
39
def setUp(self):
40
ut.TestCase.setUp(self)
41
self.testDir = os.path.dirname(os.path.realpath(__file__))
42
# set config filenames
43
self.CFG0 = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'simpla.cfg.xml')
44
self.CFG1 = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'simpla_test.cfg.xml')
45
46
# define config contents
47
self.cfg_body0 =\
48
"""
49
<vTypeMapFile value="vtype.map" />
50
<controlRate value="10." />
51
<vehicleSelectors value="pkwFern1,pkwFern2" />
52
<maxPlatoonGap value="15.0" />
53
<catchupDist value="50.0" />
54
<switchImpatienceFactor value="0.1" />
55
<platoonSplitTime value="3.0" />
56
<lcMode original="597" leader="597" follower="514" catchup="514" catchupFollower="514" />
57
<speedFactor original="1.01" leader="1.01" follower="1.11" catchup="1.21" catchupFollower="1.31" >\
58
</speedFactor>
59
<verbosity value="2" />
60
<vTypeMap original="origVTypeID" leader="leaderVTypeID" follower="followerVTypeID" \
61
catchup="catchupVTypeID" catchupFollower="catchupFollowerVTypeID" />
62
"""
63
self.cfg_body1 =\
64
"""
65
<controlRate value="0" />
66
<vehicleSelectors>empty</vehicleSelectors>
67
<maxPlatoonGap value="-1" />
68
<catchupDist value="-1" />
69
<switchImpatienceFactor value="-1" />
70
<platoonSplitTime value="-1" ></platoonSplitTime>
71
<lcMode leader="100000" follower="-1" catchupFollower="0" />
72
<speedFactor original="-1" leader="0" follower="0.5" catchup="-4"/>
73
<vTypeMap leader="leaderVTypeID" follower="followerVTypeID" catchup="catchupVTypeID" \
74
catchupFollower="catchupFollowerVTypeID" /><verbosity value="200" ></verbosity>
75
<UnknownConfigParam></UnknownConfigParam>
76
"""
77
self.cfg_body2 = '<vTypeMapFile file="vtype2.map"></vTypeMapFile>'
78
self.cfg_body3 = '<vTypeMapFile file="vtype3.map"></vTypeMapFile>'
79
self.cfg_body4 = '<vTypeMapFile file="FileThatDoesntExist"></vTypeMapFile>'
80
self.cfg_body5 = '<vTypeMap original="original_type1" leader="leader_type1" follower="follower_type1" ' + \
81
'catchup ="catchup_type1" catchupFollower ="catchupFollower_type1"/>'
82
self.cfg_body6 =\
83
"""
84
<catchupDist value="50.0" />
85
<vTypeMap original="origVTypeID" leader="leaderVTypeID" follower="followerVTypeID" \
86
catchup="catchupVTypeID" catchupFollower="catchupFollowerVTypeID" />
87
"""
88
self.cfg_body7 = '<edgeLookAhead value="2"/><distLookAhead value="300.0"/>'
89
90
# start a sumo instance
91
self.sumocfg = os.path.join(self.testDir, "sumo.sumocfg")
92
self.connectToSumo(self.sumocfg)
93
94
def connectToSumo(self, sumo_cfg):
95
traci.start([sumolib.checkBinary('sumo'), "-c", sumo_cfg, "-S"])
96
97
def tearDown(self):
98
ut.TestCase.tearDown(self)
99
# clear loaded variables
100
cfg.initDefaults()
101
rp.initDefaults()
102
os.remove(self.CFG1)
103
traci.close()
104
105
def patchConfigFile(self, cfg_body):
106
with open(self.CFG0, "r") as empty_cfg, open(self.CFG1, "w") as target_cfg:
107
s = empty_cfg.read()
108
target_cfg.write(s.format(body=cfg_body))
109
110
def test_empty_config(self):
111
print("Testing empty config...")
112
self.patchConfigFile("")
113
cfg.load(self.CFG1)
114
self.assertEqual(rp.VERBOSITY, 1.)
115
self.assertEqual(cfg.CONTROL_RATE, 1.)
116
self.assertEqual(cfg.VEH_SELECTORS, [''])
117
self.assertEqual(cfg.MAX_PLATOON_GAP, 15.)
118
self.assertEqual(cfg.CATCHUP_DIST, 50.)
119
self.assertEqual(cfg.PLATOON_SPLIT_TIME, 3.)
120
self.assertEqual(cfg.SWITCH_IMPATIENCE_FACTOR, 0.1)
121
self.assertEqual(cfg.VTYPE_FILE, '')
122
for mode in PlatoonMode:
123
self.assertTrue(mode in cfg.LC_MODE)
124
self.assertTrue(mode in cfg.SPEEDFACTOR)
125
self.assertEqual(cfg.LC_MODE[PlatoonMode.NONE], 0b1001010101)
126
self.assertEqual(cfg.LC_MODE[PlatoonMode.LEADER], 0b1001010101)
127
self.assertEqual(cfg.LC_MODE[PlatoonMode.FOLLOWER], 0b1000000010)
128
self.assertEqual(cfg.LC_MODE[PlatoonMode.CATCHUP], 0b1000000010)
129
self.assertEqual(cfg.LC_MODE[PlatoonMode.CATCHUP_FOLLOWER], 0b1000000010)
130
for tp in cfg.PLATOON_VTYPES:
131
for mode in PlatoonMode:
132
self.assertTrue(mode in cfg.PLATOON_VTYPES[tp])
133
self.assertListEqual(list(rp.WARNING_LOG), [])
134
135
def test_example_config(self):
136
print("Testing standard config...")
137
self.patchConfigFile(self.cfg_body0)
138
cfg.load(self.CFG1)
139
self.assertEqual(rp.VERBOSITY, 2.)
140
self.assertEqual(cfg.CONTROL_RATE, 10.)
141
self.assertEqual(cfg.VEH_SELECTORS, ['pkwFern1', 'pkwFern2'])
142
self.assertEqual(cfg.MAX_PLATOON_GAP, 15.)
143
self.assertEqual(cfg.CATCHUP_DIST, 50.)
144
self.assertEqual(cfg.PLATOON_SPLIT_TIME, 3.)
145
self.assertEqual(cfg.SWITCH_IMPATIENCE_FACTOR, 0.1)
146
self.assertTrue(cfg.VTYPE_FILE.endswith('vtype.map'))
147
for mode in PlatoonMode:
148
self.assertTrue(mode in cfg.LC_MODE)
149
self.assertTrue(mode in cfg.SPEEDFACTOR)
150
self.assertEqual(cfg.LC_MODE[PlatoonMode.NONE], 0b1001010101)
151
self.assertEqual(cfg.LC_MODE[PlatoonMode.LEADER], 0b1001010101)
152
self.assertEqual(cfg.LC_MODE[PlatoonMode.FOLLOWER], 0b1000000010)
153
self.assertEqual(cfg.LC_MODE[PlatoonMode.CATCHUP], 0b1000000010)
154
self.assertEqual(cfg.LC_MODE[PlatoonMode.CATCHUP_FOLLOWER], 0b1000000010)
155
for tp in cfg.PLATOON_VTYPES:
156
for mode in PlatoonMode:
157
self.assertTrue(mode in cfg.PLATOON_VTYPES[tp])
158
self.assertListEqual(list(rp.WARNING_LOG), [])
159
160
def test_partial_config(self):
161
print("Testing partial config...")
162
self.patchConfigFile(self.cfg_body6)
163
cfg.load(self.CFG1)
164
self.assertEqual(cfg.CATCHUP_DIST, 50.)
165
166
def test_config_warnings(self):
167
print("Testing config warnings...")
168
self.patchConfigFile(self.cfg_body1)
169
cfg.load(self.CFG1)
170
# cfg.load(TestConfig.CFG2)
171
expected_warnings = [
172
"WARNING: No attributes found for tag 'vehicleSelectors'. (Config)",
173
"WARNING: Encountered unknown configuration parameter 'UnknownConfigParam'! (Config)",
174
"WARNING: Verbosity must be one of [0, 1, 2, 3, 4]! Ignoring given value: 200 (Config)",
175
"WARNING: Parameter controlRate must be positive. Ignoring given value: 0.0 (Config)",
176
"WARNING: Parameter maxPlatoonGap must be positive. Ignoring given value: -1.0 (Config)",
177
"WARNING: Parameter catchupDist must be positive. Ignoring given value: -1.0 (Config)",
178
"WARNING: Parameter switchImpatienceFactor must be non-negative. Ignoring given value: -1.0 (Config)",
179
"WARNING: Parameter platoonSplitTime must be non-negative. Ignoring given value: -1.0 (Config)",
180
"WARNING: Given lane change mode '100000' lies out of admissible range [0,255]. " +
181
"Using default mode instead. (Config)",
182
"WARNING: Given lane change mode '-1' lies out of admissible range [0,255]. " +
183
"Using default mode instead. (Config)",
184
"WARNING: vTypeMap must specify original type. Ignoring malformed vTypeMap element. (Config)",
185
"WARNING: Given speedFactor 0.0 is invalid. Using default value. (Config)",
186
"WARNING: Given speedFactor -4.0 is invalid. Using default value. (Config)",
187
"WARNING: Given speedFactor -1.0 is invalid. Using default value. (Config)"
188
]
189
warning_list = [w[1] for w in rp.WARNING_LOG]
190
for w in expected_warnings:
191
self.assertIn(w, warning_list)
192
self.assertListEqual([], list(set(warning_list).difference(expected_warnings)))
193
194
def test_corrupted_vTypeMapFile_raises_exception(self):
195
print("Testing malformed vtype map file causing exception...")
196
self.patchConfigFile(self.cfg_body2)
197
with self.assertRaises(SimplaException):
198
cfg.load(self.CFG1)
199
200
self.patchConfigFile(self.cfg_body3)
201
with self.assertRaises(SimplaException):
202
cfg.load(self.CFG1)
203
204
self.patchConfigFile(self.cfg_body4)
205
with self.assertRaises(SimplaException):
206
cfg.load(self.CFG1)
207
208
def test_corrupted_vTypeMapFile_exception_text(self):
209
print("Testing exception messages...")
210
self.patchConfigFile(self.cfg_body4)
211
try:
212
cfg.load(self.CFG1)
213
except SimplaException as e:
214
# print (str(e))
215
self.assertTrue(str(e).startswith("Given vTypeMapFile"))
216
217
self.patchConfigFile(self.cfg_body3)
218
try:
219
cfg.load(self.CFG1)
220
except SimplaException as e:
221
self.assertTrue(str(e).startswith("Platoon leader vType must be specified"))
222
223
self.patchConfigFile(self.cfg_body2)
224
try:
225
cfg.load(self.CFG1)
226
except SimplaException as e:
227
self.assertTrue(str(e).startswith("Original vType must be specified"))
228
229
def test_only_vTypeMap_given(self):
230
print("Testing specification of vTypeMap only...")
231
self.patchConfigFile(self.cfg_body5)
232
simpla.load(self.CFG1)
233
# print ("controlInterval: %s"%simpla._mgr._controlInterval)
234
for i in range(10):
235
# print ("Time: %s"%traci.simulation.getCurrentTime())
236
# print ("Vehicles: %s"%traci.vehicle.getIDList())
237
traci.simulationStep()
238
239
def test_lookAhead(self):
240
print("Testing lookAhead settings only...")
241
self.patchConfigFile(self.cfg_body7)
242
simpla.load(self.CFG1)
243
self.assertEqual(cfg.EDGE_LOOKAHEAD, 2)
244
self.assertEqual(cfg.DIST_LOOKAHEAD, 300.0)
245
246
# ~ # restrict run to specific tests
247
# ~ selected_test = 5
248
# ~ tests = [a for a in dir(TestConfig) if a.startswith("test")]
249
# ~ print (tests, len(tests))
250
# ~ for i,t in enumerate(tests):
251
# ~ if i != selected_test:
252
# ~ print("Removing test %s (%s)"%(i, t))
253
# ~ delattr(TestConfig, t)
254
# ~ else:
255
# ~ print("Keeping test %s (%s)"%(i, t))
256
257
258
if __name__ == "__main__":
259
ut.main()
260
261