Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/tools/jtcrouter.py
169659 views
1
#!/usr/bin/env python
2
# Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3
# Copyright (C) 2012-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 jtcrouter.py
15
# @author Jakob Erdmann
16
# @date 2019-11-07
17
18
"""
19
Generate routes like jtrrouter but bas on count parameters at connections
20
The counts are used to derive the turn file and flow file for calling jtrrouter
21
"""
22
from __future__ import absolute_import
23
from __future__ import print_function
24
25
import os
26
import sys
27
from collections import defaultdict
28
import subprocess
29
30
if 'SUMO_HOME' in os.environ:
31
sys.path.append(os.path.join(os.environ['SUMO_HOME'], 'tools'))
32
sys.path.append(os.path.join(os.environ['SUMO_HOME'], 'tools/turn-defs'))
33
else:
34
THIS_DIR = os.path.abspath(os.path.dirname(__file__))
35
sys.path.append(os.path.join(THIS_DIR, 'turn-defs'))
36
37
import sumolib # noqa
38
from sumolib.options import ArgumentParser
39
from turnCount2EdgeCount import parseEdgeCounts # noqa
40
41
42
def get_options(args=None):
43
parser = ArgumentParser(description="Route by turn counts")
44
parser.add_argument("-n", "--net-file", dest="net", help="Input net file")
45
parser.add_argument("-t", "--turn-file", dest="turnFile", help="Input turn-count file")
46
parser.add_argument("--additional-files", dest="addFiles", help="Input additional files to pass to jtrrouter")
47
parser.add_argument("-o", "--output-file", dest="out", default="out.rou.xml",
48
help="Output route file")
49
parser.add_argument("--turn-output", dest="turnOutput", default="turns.tmp.xml",
50
help="Intermediate turn-ratio-file")
51
parser.add_argument("--flow-output", dest="flowOutput", default="flows.tmp.xml",
52
help="Intermediate flow file")
53
parser.add_argument("--turn-attribute", dest="turnAttr", default="count",
54
help="Read turning counts from the given attribute")
55
parser.add_argument("-b", "--begin", default=0, help="begin time")
56
parser.add_argument("-e", "--end", default=3600, help="end time (default 3600)")
57
parser.add_argument("-p", "--count-param", dest="countParam", default="count",
58
help="the connection parameter to use as count")
59
parser.add_argument("--fringe-flows", action="store_true", default=False, dest="fringe_flows",
60
help="Avoid overlapping flows (start only on the outside of the network)")
61
parser.add_argument("--discount-sources", "-D", action="store_true", default=False, dest="discountSources",
62
help="passes option --discount-sources to jtrrouter")
63
parser.add_argument("--prefix", dest="prefix", default="",
64
help="prefix for the flow ids")
65
parser.add_argument("-a", "--attributes", dest="flowattrs", default="",
66
help="additional flow attributes")
67
options = parser.parse_args(args=args)
68
if options.net is None:
69
parser.print_help()
70
sys.exit()
71
if options.flowattrs and options.flowattrs[0] != ' ':
72
options.flowattrs = ' ' + options.flowattrs
73
return options
74
75
76
def findFringe(edge, countParam, intermediateCounts=None):
77
if intermediateCounts:
78
# do not backtrack past edges that define turning counts (to avoid duplicate flows)
79
return None
80
if edge.is_fringe(edge._incoming):
81
return edge
82
elif len(edge.getIncoming()) == 1:
83
prev = edge.getIncoming().keys()[0]
84
return findFringe(prev, countParam, getCounts(prev, countParam))
85
return None
86
87
88
def getCounts(edge, countParam):
89
counts = defaultdict(lambda: 0)
90
for toEdge, cons in edge.getOutgoing().items():
91
for con in cons:
92
value = con.getParam(countParam)
93
if value is not None:
94
counts[con.getTo().getID()] += float(value)
95
return counts
96
97
98
def main(options):
99
if options.turnFile is None:
100
# read data from connection params
101
net = sumolib.net.readNet(options.net)
102
with open(options.turnOutput, 'w') as tf, open(options.flowOutput, 'w') as ff:
103
sumolib.writeXMLHeader(tf, "$Id$", "turns") # noqa
104
sumolib.writeXMLHeader(ff, "$Id$", "routes") # noqa
105
tf.write(' <interval begin="%s" end="%s">\n' % (options.begin, options.end))
106
for edge in net.getEdges():
107
counts = getCounts(edge, options.countParam)
108
if counts:
109
tf.write(' <fromEdge id="%s">\n' % (edge.getID()))
110
for toEdge, count in counts.items():
111
tf.write(' <toEdge id="%s" probability="%s"/>\n' % (toEdge, count))
112
tf.write(' </fromEdge>\n')
113
114
totalCount = int(sum(counts.values()))
115
fromEdge = edge
116
if options.fringe_flows:
117
fromEdge = findFringe(edge, options.countParam)
118
if fromEdge:
119
ff.write(' <flow id="%s%s" from="%s" begin="%s" end="%s" number="%s"%s/>\n' % (
120
options.prefix, edge.getID(), fromEdge.getID(),
121
options.begin, options.end,
122
totalCount, options.flowattrs))
123
tf.write(' </interval>\n')
124
tf.write('</turns>\n')
125
ff.write('</routes>\n')
126
else:
127
# read turn-count file
128
options.turnOutput = options.turnFile
129
with open(options.flowOutput, 'w') as ff:
130
ff.write('<routes>\n')
131
for i, interval in enumerate(parseEdgeCounts(options.turnFile, options.turnAttr)):
132
interval_id, interval_begin, interval_end, counts = interval
133
for edge in sorted(counts.keys()):
134
count = counts[edge]
135
if count > 0:
136
flowID = edge
137
if i > 0:
138
flowID += "#%s" % i
139
ff.write(' <flow id="%s%s" from="%s" begin="%s" end="%s" number="%s"%s/>\n' % (
140
options.prefix,
141
flowID, edge, interval_begin, interval_end,
142
int(count),
143
options.flowattrs))
144
ff.write('</routes>\n')
145
146
JTRROUTER = sumolib.checkBinary('jtrrouter')
147
args = [JTRROUTER,
148
'-n', options.net,
149
'--turn-ratio-files', options.turnOutput,
150
'--route-files', options.flowOutput,
151
'--accept-all-destinations',
152
'-o', options.out]
153
if options.addFiles:
154
args += ['--additional-files', options.addFiles,
155
'--vtype-output', 'NUL']
156
if not options.fringe_flows:
157
args += ['-S']
158
if options.discountSources:
159
args += ['-D']
160
subprocess.call(args)
161
162
163
if __name__ == "__main__":
164
main(get_options())
165
166