Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/tools/import/vissim/tls_vissimXML2SUMOnet_update.py
169679 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) 2009-2025 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 tls_vissimXML2SUMOnet_update.py
16
# @author Lukas Grohmann <[email protected]>
17
# @author Gerald Richter <[email protected]>
18
# @date Jun 11 2015
19
20
"""
21
Converts a VISSIM-tls-description into a SUMO-tls-description and writes
22
the appended information to a copy of the given sumo.net file
23
"""
24
# TODO: usage doc.ref
25
26
from __future__ import print_function
27
from __future__ import absolute_import
28
29
import os
30
import sys
31
from xml.dom import minidom
32
from copy import deepcopy
33
34
import numpy as np
35
if 'SUMO_HOME' in os.environ:
36
sys.path.append(os.path.join(os.environ['SUMO_HOME'], 'tools'))
37
import sumolib # noqa
38
39
40
def dict_from_node_attributes(node):
41
"""takes a xml node and returns a dictionary with its attributes"""
42
return dict((attn, node.getAttribute(attn)) for attn in
43
node.attributes.keys())
44
45
46
def nparr_from_dict_list(dicl_tab, col_ns, col_ts):
47
"""converts a dictionary into an np array table structure"""
48
return np.array([tuple(rd.get(cn, '0') for cn in col_ns) for rd in
49
dicl_tab], dtype=np.dtype(list(zip(col_ns, col_ts))))
50
51
52
def get_conn_verb_rel(conn_tab, from_to_tab):
53
"""
54
returns a dictionary to get the connection id for a
55
given verbinder id and vice versa
56
"""
57
conn_link_d = {} # key = verbinder.id, value = list<connection.id>
58
for conn in conn_tab:
59
if ':' not in conn['from']:
60
link = from_to_tab[
61
(from_to_tab['f_link'] == conn['from'].split("[")[0]) &
62
(from_to_tab['t_link'] == conn['to'].split("[")[0])]
63
if len(link) > 0:
64
if link["_link"][0] in conn_link_d:
65
conn_link_d[link["_link"][0]].append(conn['via'])
66
else:
67
conn_link_d[link["_link"][0]] = [conn['via']]
68
else:
69
print("from: " + conn['from'] + "to: " + conn['to'])
70
return conn_link_d
71
72
73
def parse_vissim_net_data(inpxdoc):
74
link_tab = []
75
from_to_tab = []
76
for lin in inpxdoc.getElementsByTagName('link'):
77
link_d = dict_from_node_attributes(lin)
78
link_tab.append(link_d)
79
if lin.hasChildNodes():
80
lep_d = {} # link end point dict
81
for ept in ('fromLinkEndPt', 'toLinkEndPt'):
82
lep_nd = lin.getElementsByTagName(ept)
83
ch0 = ept[0] # identifier 'f'rom / 't'o
84
if len(lep_nd) > 0:
85
dic = dict_from_node_attributes(lep_nd.item(0))
86
dic['link'], dic['lane'] = dic['lane'].split(' ')
87
lep_d.update(dict((ch0 + '_' + key, value)
88
for key, value in dic.items()))
89
lep_d.update({'_link': link_d['no'], })
90
from_to_tab.append(lep_d)
91
# which columns to pick ?
92
link_tab = nparr_from_dict_list(link_tab, 'no name'.split(), ('O',) * 2)
93
# lane_tab = just the number of lanes and width
94
from_to_tab = nparr_from_dict_list(
95
from_to_tab,
96
'_link f_link f_lane t_link t_lane'.split(),
97
'O O i O i'.split())
98
return link_tab, from_to_tab
99
100
101
def parse_sumo_net_data(sumodoc):
102
junc_tab = []
103
conn_tab = []
104
junc_tab = [dict_from_node_attributes(nd) for
105
nd in sumodoc.getElementsByTagName('junction')]
106
col_n = ('id', 'type', 'x', 'y', 'incLanes', 'intLanes')
107
col_t = ('O', ) * 6
108
junc_tab = nparr_from_dict_list(junc_tab, col_n, col_t)
109
conn_tab = [dict_from_node_attributes(nd) for
110
nd in sumodoc.getElementsByTagName('connection')]
111
col_n = ('from', 'to', 'fromLane', 'toLane', 'via')
112
col_t = ('O', ) * 5
113
conn_tab = nparr_from_dict_list(conn_tab, col_n, col_t)
114
return junc_tab, conn_tab
115
116
117
def compute_signal_tables(disp_name_id_d, signal_state_d, prog_list):
118
"""
119
completes the signal tables with all duration and beginning times
120
(in the VISSIm .sig files are only the beginning times of the red and
121
green phases as well as the durations of the other phases given )
122
"""
123
for key, program in signal_state_d.items():
124
cycletime = int([prog for prog in prog_list
125
if prog["id"] == key][0]["cycletime"])
126
for sig_group in program.values():
127
sig_seq = sig_group["signal_sequence"]
128
sig_tab = deepcopy(disp_name_id_d[sig_seq])
129
# durations füllen
130
for state in sig_group["durations"]:
131
itemindex = np.where(sig_tab == int(state["display"]))
132
sig_tab[itemindex[0][0]][itemindex[1][0] + 2] \
133
= int(state["duration"])
134
# begins füllen
135
for cmd in sig_group["begins"]:
136
itemindex = np.where(sig_tab == int(cmd["display"]))
137
sig_tab[itemindex[0][0]][itemindex[1][0] + 1] \
138
= int(cmd["begin"])
139
# begin Zeiten berechnen
140
# bei zufälligem begin Eintrag starten
141
i = itemindex[0][0]
142
check = 0
143
while check != len(sig_tab):
144
if sig_tab[i - 1][1] == -1: # duration bekannt
145
# überlauf cycletime
146
if (sig_tab[i][1] - sig_tab[i - 1][2]) < 0:
147
sig_tab[i - 1][1] = cycletime - \
148
(sig_tab[i - 1][2] - sig_tab[i][1])
149
else:
150
sig_tab[i - 1][1] = sig_tab[i][1] - sig_tab[i - 1][2]
151
elif sig_tab[i - 1][2] == -1: # begin bekannt
152
if sig_tab[i - 1][1] > sig_tab[i][1]: # überlauf cycletime
153
sig_tab[i - 1][2] = \
154
(cycletime - sig_tab[i - 1][1]) + sig_tab[i][1]
155
else:
156
sig_tab[i - 1][2] = sig_tab[i][1] - sig_tab[i - 1][1]
157
i -= 1
158
check += 1
159
i = 0
160
while i < len(sig_tab):
161
if (sig_tab[i][1] + sig_tab[i][2]) > cycletime:
162
diff = cycletime - sig_tab[i][1]
163
dur = sig_tab[i][2]
164
sig_tab[i][2] = diff
165
sig_tab = np.insert(
166
sig_tab, i, np.array(
167
(sig_tab[i][0], 0, dur - diff)), 0)
168
break
169
i += 1
170
sig_tab = sig_tab[np.argsort(sig_tab[:, 1])]
171
sig_group["signal_table"] = sig_tab
172
173
174
def sigtable_split_time(signal_state_d, prog_list):
175
# FIXME: doc
176
reference_time_d = {}
177
for key, program in signal_state_d.items():
178
cycletime = int([prog for prog in prog_list
179
if prog["id"] == key][0]["cycletime"])
180
reference_time = np.array([], dtype="int")
181
reference_duration = np.array([], dtype="int")
182
for sg in program.values():
183
reference_time = np.append(
184
reference_time, sg["signal_table"][:, 1])
185
reference_time = np.unique(reference_time)
186
i = 0
187
while i < len(reference_time):
188
if i == len(reference_time) - 1:
189
ele = cycletime - reference_time[i]
190
else:
191
ele = reference_time[i + 1] - reference_time[i]
192
reference_duration = np.append(reference_duration, ele)
193
i += 1
194
reference_time_d[key] = {}
195
reference_time_d[key]["begin"] = reference_time
196
reference_time_d[key]["duration"] = reference_duration
197
return reference_time_d
198
199
200
def compute_sumo_signal_tables(reference_time_d,
201
signal_state_d,
202
sig_disp_list,
203
tls_state_vissim2SUMO):
204
# FIXME: doc
205
for key, program in signal_state_d.items():
206
for sg in program.values():
207
state = sg["signal_table"]
208
ref_time = reference_time_d[key]["begin"]
209
sumo_tab = ""
210
for time in ref_time:
211
i = 0
212
while i < len(state):
213
if state[i][1] <= time < state[i][1] + state[i][2]:
214
sumo_state = tls_state_vissim2SUMO[
215
[sig for sig in sig_disp_list if
216
sig["id"] == str(state[i][0])][0]["state"]]
217
sumo_tab = "".join([sumo_tab, sumo_state])
218
break
219
i += 1
220
sg["sumo_signal_table"] = sumo_tab
221
222
223
def get_sigcon_junc_relation(sig_con_tab, sig_group_conn_d, junc_tab):
224
"""
225
allocates the VISSIM signalcontrollers to SUMO junctions
226
"""
227
sigCon_junc_d = {}
228
for sig_con in sig_con_tab:
229
conn_l = []
230
for sg in sig_con["_sgs"]:
231
if sg["_sg"] in sig_group_conn_d:
232
conn_l += sig_group_conn_d[sg["_sg"]]
233
else:
234
continue
235
# intersection
236
junction = [
237
junc for junc in junc_tab if len(
238
set(conn_l).intersection(
239
junc['intLanes'].split(" "))) > 0]
240
if len(junction) > 0:
241
junction = junction[0]
242
else:
243
continue
244
sigCon_junc_d[sig_con["no"]] = junction["id"]
245
return sigCon_junc_d
246
247
248
def get_sigseq_id_list(sig_seq_tab, sig_disp_list):
249
# FIXME: doc
250
disp_name_id_d = {}
251
for seq in sig_seq_tab:
252
id_list = []
253
names = seq["name"].split("-")
254
for name in names:
255
id_list.append([[disp for disp in sig_disp_list
256
if disp["name"] == name][0]["id"], -1, -1])
257
disp_name_id_d[seq["id"]] = np.array(id_list, dtype="int")
258
return disp_name_id_d
259
260
261
def get_sg_connection_data(
262
conn_tab,
263
sig_con_tab,
264
sig_head_d,
265
edge_list,
266
conn_link_d):
267
# FIXME: doc
268
sig_group_conn_d = {} # dic [sigCon ID] = List <[conn via]>
269
for con in sig_con_tab:
270
for sg in con['_sgs']:
271
# check if a signalHead exists for the given signalGroup
272
if sg['_sg'] in sig_head_d:
273
for signal in sig_head_d[sg['_sg']]:
274
link = signal['link']
275
lane = str(int(signal['lane']) - 1)
276
# tls on normal edge or verbinder?
277
if is_verbinder_d[link] is False:
278
if link in edge_list:
279
connection = conn_tab[
280
(conn_tab["from"] == link) & (
281
conn_tab["fromLane"] == lane)]
282
else:
283
check = True
284
split_len = 0
285
while check:
286
if "".join(
287
[link, "[", str(split_len), "]"]) \
288
in edge_list:
289
split_len += 1
290
else:
291
check = False
292
print("".join([link, "[", str(split_len), "]"]))
293
connection = conn_tab[(conn_tab["from"] == "".join(
294
[link, "[", str(split_len), "]"])) &
295
(conn_tab["fromLane"] == lane)][0]
296
else:
297
connection = conn_tab[
298
(conn_tab["via"] ==
299
[conn for conn in
300
conn_link_d[link] if conn[-1] == lane])]
301
if sg['_sg'] in sig_group_conn_d:
302
for conn in connection:
303
sig_group_conn_d[sg['_sg']].append(conn["via"])
304
else:
305
sig_group_conn_d[sg['_sg']] = []
306
for conn in connection:
307
sig_group_conn_d[sg['_sg']].append(conn["via"])
308
else:
309
print(sg['_sg'])
310
return sig_group_conn_d
311
312
313
def parse_sig_file(sig_file):
314
xmldoc = minidom.parse(sig_file)
315
print('\n---\n\n* loading signal file:\n\t', sig_file)
316
317
# just getting single head node
318
sc_node = xmldoc.getElementsByTagName('sc').item(0)
319
sc_id = sc_node.getAttribute('id')
320
321
# get the signal displays; should be just 1 node
322
sig_disp_nodes = sc_node.getElementsByTagName('signaldisplays')
323
display_nodes = sig_disp_nodes.item(0).getElementsByTagName('display')
324
# build for single current signal
325
sig_disp_list = [dict_from_node_attributes(disp) for disp in display_nodes]
326
[sd.update({'_sc_id': sc_id}) for sd in sig_disp_list]
327
328
# signalsequences
329
sig_seq_tab = []
330
# sigStat_tab needed for default program
331
sigStat_tab = []
332
for sig_seq in sc_node.getElementsByTagName('signalsequence'):
333
sig_seq_d = dict_from_node_attributes(sig_seq)
334
sig_seq_tab.append(sig_seq_d)
335
sig_state_l = [dict_from_node_attributes(sst) for
336
sst in sig_seq.getElementsByTagName('state')]
337
[sst.update({'_sigSeq_id': sig_seq_d['id']}) for sst in sig_state_l]
338
sigStat_tab.extend(sig_state_l)
339
sgroup_list = []
340
# holds defaultDurations, fixedstates, cmds
341
prog_list = []
342
# dict[prog_id][signal_id]
343
# <signal_sequence>
344
# <begins>
345
# <durations>
346
signal_state_d = {}
347
348
# reading default program; should be just 1 node
349
sgs_list = sc_node.getElementsByTagName('sgs')
350
prog_id = '0' # unsaved
351
prog_d = dict((('id', prog_id), ))
352
prog_list.append(prog_d)
353
354
# default sg einlesen
355
for sg in sgs_list.item(0).getElementsByTagName('sg'):
356
sg_d = dict_from_node_attributes(sg)
357
sg_d.update({'_prog_id': prog_id, })
358
sgroup_list.append(sg_d)
359
360
# other sg reading
361
progs_node = sc_node.getElementsByTagName('progs').item(0)
362
for prog_node in progs_node.getElementsByTagName('prog'):
363
prog_d = dict_from_node_attributes(prog_node)
364
prog_list.append(prog_d)
365
prog_id = prog_d['id']
366
signal_state_d[prog_id] = {}
367
sg_nl = prog_node.getElementsByTagName(
368
'sgs').item(0).getElementsByTagName('sg')
369
for sg in sg_nl:
370
sg_d = dict_from_node_attributes(sg)
371
signal_state_d[prog_id][sg_d["sg_id"]] = {}
372
signal_state_d[prog_id][sg_d["sg_id"]][
373
"signal_sequence"] = sg_d["signal_sequence"]
374
signal_state_d[prog_id][sg_d["sg_id"]]["begins"] = []
375
signal_state_d[prog_id][sg_d["sg_id"]]["durations"] = []
376
sg_d.update({'_prog_id': prog_id, })
377
sgroup_list.append(sg_d)
378
# fixedstates
379
for fixStat in sg.getElementsByTagName('fixedstates').item(0).\
380
getElementsByTagName('fixedstate'):
381
fixst = dict_from_node_attributes(fixStat)
382
signal_state_d[prog_id][sg_d["sg_id"]][
383
"durations"].append(fixst)
384
# cmds
385
for cmd_node in sg.getElementsByTagName('cmds').item(0).\
386
getElementsByTagName('cmd'):
387
cmd_d = dict_from_node_attributes(cmd_node)
388
signal_state_d[prog_id][sg_d["sg_id"]]["begins"].append(cmd_d)
389
390
return sig_seq_tab, signal_state_d, sig_disp_list, prog_list
391
392
393
def parse_inpx_sig_data(xmldoc):
394
"""parses the signal data from the .inpx file"""
395
sig_controller_tab = []
396
sig_head_d = dict()
397
398
for controller in xmldoc.getElementsByTagName('signalController'):
399
controller_d = dict_from_node_attributes(controller)
400
sgs_l = [dict_from_node_attributes(sgn) for
401
sgn in controller.getElementsByTagName('signalGroup')]
402
for sg in sgs_l:
403
sg['_sg'] = " ".join([controller.getAttribute('no'), sg['no']])
404
controller_d['_sgs'] = sgs_l
405
sig_controller_tab.append(controller_d)
406
407
# parse signalHeads
408
for s_head_item in xmldoc.getElementsByTagName('signalHead'):
409
sig_head = dict_from_node_attributes(s_head_item)
410
sig_head['link'], sig_head['lane'] = sig_head['lane'].split(" ")
411
# temp = sHead.getAttribute('lane').split(" ") # "link lane"
412
if sig_head['sg'] in sig_head_d:
413
sig_head_d[sig_head['sg']].append(sig_head)
414
else:
415
sig_head_d[sig_head['sg']] = [sig_head]
416
return sig_controller_tab, sig_head_d
417
418
419
def edit_connections(conn_l, sumodoc, junc_id):
420
i = 0
421
while i < len(conn_l):
422
for via in conn_l[i]:
423
connection = [conn for conn in
424
sumodoc.getElementsByTagName("connection")
425
if conn.getAttribute("via") == via][0]
426
connection.setAttribute("state", "o") # CHECK
427
connection.setAttribute("linkIndex", str(i))
428
connection.setAttribute("tl", junc_id)
429
i += 1
430
431
432
def is_verbinder(xmldoc):
433
"""checks if a given link is a verbinder"""
434
is_verbinder_d = dict()
435
for link in xmldoc.getElementsByTagName("link"):
436
if len(link.getElementsByTagName("fromLinkEndPt")) > 0:
437
is_verbinder_d[link.getAttribute("no")] = True
438
else:
439
is_verbinder_d[link.getAttribute("no")] = False
440
return is_verbinder_d
441
442
443
def generate_xml_doc(
444
sumo_tls_d, sigCon_junc_d,
445
sig_con_tab, reference_time_d,
446
sumodoc, prog_list_d, sig_group_conn_d):
447
for tls_id, programs in sumo_tls_d.items():
448
junc_id = sigCon_junc_d[tls_id]
449
default_prog_id = [
450
sig for sig in sig_con_tab if sig["no"] == tls_id][0]["progNo"]
451
for prog_id, program in programs.items():
452
signal_table = []
453
for sg_id, sg in program.items():
454
if " ".join([tls_id, sg_id]) in sig_group_conn_d:
455
signal_table.append([sg_id, sg["sumo_signal_table"]])
456
signal_table = np.array(signal_table)
457
signal_table = signal_table[
458
signal_table[:, 0].astype("int").argsort()]
459
sg_id_l = signal_table[:, 0]
460
conn_l = []
461
for s_id in sg_id_l:
462
conn_l.append(sig_group_conn_d[" ".join([tls_id, s_id])])
463
signal_table = np.delete(signal_table, 0, 1)
464
signal_table = np.ravel(signal_table)
465
state_l = []
466
i = 0
467
while i < len(signal_table[0]):
468
j = 0
469
duration = []
470
while j < len(signal_table):
471
duration.append(signal_table[j][i])
472
j += 1
473
state_l.append("".join(duration))
474
i += 1
475
duration_l = reference_time_d[tls_id][
476
prog_id]["duration"]
477
# edit net file
478
junction = [junc for junc in sumodoc.getElementsByTagName(
479
"junction") if junc.getAttribute("id") == junc_id][0]
480
junction.setAttribute("type", "traffic_light")
481
net = sumodoc.getElementsByTagName("net")[0]
482
483
edit_connections(conn_l, sumodoc, junc_id)
484
tl_logic = sumodoc.createElement("tlLogic")
485
tl_logic.setAttribute("id", junc_id)
486
tl_logic.setAttribute("type", "static")
487
tl_logic.setAttribute("programID",
488
[prog for prog in prog_list_d[tls_id]
489
if prog["id"] == prog_id][0]["name"])
490
tl_logic.setAttribute("offset", "0.00")
491
net.insertBefore(tl_logic, junction)
492
for state, duration in zip(state_l, duration_l):
493
phase = sumodoc.createElement("phase")
494
phase.setAttribute("duration", str(duration / 1000))
495
phase.setAttribute("state", state)
496
tl_logic.appendChild(phase)
497
498
# create WAUT
499
waut = sumodoc.createElement("WAUT")
500
waut.setAttribute("startProg",
501
[prog for prog in prog_list_d[tls_id]
502
if prog["id"] == default_prog_id][0]["name"])
503
waut.setAttribute("refTime", "100")
504
waut.setAttribute("id", "".join(["w", tls_id]))
505
# root.appendChild(WAUT)
506
net.insertBefore(waut, junction)
507
508
# create waut junction
509
waut_junc = sumodoc.createElement("wautJunction")
510
waut_junc.setAttribute("junctionID", junc_id)
511
waut_junc.setAttribute("wautID", "".join(["w", tls_id]))
512
# root.appendChild(wautJunction)
513
net.insertBefore(waut_junc, junction)
514
515
516
# global signal color translation definition
517
tls_state_vissim2SUMO = {'RED': 'r',
518
'REDAMBER': 'u',
519
'GREEN': 'g',
520
'AMBER': 'y',
521
# this should be different: like in SUMO 'o', 'O'
522
'FLASHING_GREEN': 'g',
523
'OFF': 'O'}
524
525
# MAIN
526
if __name__ == '__main__':
527
op = sumolib.options.ArgumentParser(
528
description='TLS conversion utility (VISSIM.inpx to SUMO)')
529
op.add_argument('--vissim-input', '-V',
530
category="input", required=True, type=op.file,
531
help='VISSIM inpx file path')
532
op.add_argument('--SUMO-net', '-S',
533
category="input", required=True, type=op.net_file,
534
help='SUMO net file path')
535
op.add_argument('--output-file', '-o',
536
category="output", required=True, type=op.file,
537
help='output file name')
538
args = op.parse_args()
539
print("\n", args, "\n")
540
print('\n---\n\n* loading VISSIM net:\n\t', args.vissim_input)
541
xmldoc = minidom.parse(args.vissim_input)
542
print('\n---\n\n* loading SUMO net:\n\t', args.SUMO_net,)
543
sumodoc = minidom.parse(args.SUMO_net)
544
545
edge_list = []
546
for edge in sumodoc.getElementsByTagName('edge'):
547
# is it a normal edge ?
548
if not edge.hasAttribute("function"):
549
edge_list.append(edge.getAttribute("id"))
550
551
# INPX read
552
sig_con_tab, sig_head_d = parse_inpx_sig_data(xmldoc)
553
link_tab, from_to_tab = parse_vissim_net_data(xmldoc)
554
is_verbinder_d = is_verbinder(xmldoc)
555
556
# SUMO NET read
557
junc_tab, conn_tab = parse_sumo_net_data(sumodoc)
558
conn_link_d = get_conn_verb_rel(conn_tab, from_to_tab)
559
560
# get the connections for every signal group
561
sig_group_conn_d = get_sg_connection_data(conn_tab,
562
sig_con_tab,
563
sig_head_d,
564
edge_list,
565
conn_link_d)
566
# related junction id for a given Signal Controller
567
sigCon_junc_d = get_sigcon_junc_relation(sig_con_tab,
568
sig_group_conn_d,
569
junc_tab)
570
571
# pick all the .sig files from the signalControllers
572
sig_files = set(sc[att] for sc in sig_con_tab for att in
573
sc.keys() if 'supplyFile' in att and '.sig' in sc[att])
574
# sig_files = ['TestsiteGraz_v01301.sig'] # DEBUG, just 1 file
575
576
reference_time_d = {}
577
sumo_tls_d = {}
578
prog_list_d = {}
579
580
for sig_file in sig_files:
581
sig_file = os.path.join(os.path.dirname(args.vissim_input), sig_file)
582
sig_seq_tab = []
583
signal_state_d = {}
584
sig_disp_list = []
585
disp_name_id_d = {}
586
587
# parse .sig files
588
sig_seq_tab, signal_state_d, sig_disp_list, \
589
prog_list_d[sig_disp_list[0]["_sc_id"]] = parse_sig_file(sig_file)
590
tls_id = sig_disp_list[0]["_sc_id"]
591
# returns a numpy array with the reference signal Sequence table
592
# format: display_id || begin_time || duration
593
disp_name_id_d = get_sigseq_id_list(sig_seq_tab, sig_disp_list)
594
595
compute_signal_tables(
596
disp_name_id_d, signal_state_d, prog_list_d[tls_id])
597
598
# reference time and duration for every signal program
599
# times need to be split, to convert the sig table from VISSIM to SUMO
600
reference_time_d[tls_id] = sigtable_split_time(
601
signal_state_d, prog_list_d[tls_id])
602
603
compute_sumo_signal_tables(reference_time_d[tls_id],
604
signal_state_d,
605
sig_disp_list,
606
tls_state_vissim2SUMO)
607
608
# Format: [tls id][signal program id][signal group index]
609
sumo_tls_d[tls_id] = signal_state_d
610
611
generate_xml_doc(
612
sumo_tls_d, sigCon_junc_d, sig_con_tab,
613
reference_time_d, sumodoc, prog_list_d, sig_group_conn_d)
614
615
with open("%s.net.xml" % args.output_file, "w") as ofh:
616
sumodoc.writexml(ofh, addindent=' ', newl='\n')
617
ofh.close()
618
619