sumolib.net.generator.network
1# Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo 2# Copyright (C) 2013-2026 German Aerospace Center (DLR) and others. 3# This program and the accompanying materials are made available under the 4# terms of the Eclipse Public License 2.0 which is available at 5# https://www.eclipse.org/legal/epl-2.0/ 6# This Source Code may also be made available under the following Secondary 7# Licenses when the conditions for such availability set forth in the Eclipse 8# Public License 2.0 are satisfied: GNU General Public License, version 2 9# or later which is available at 10# https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html 11# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later 12 13# @file network.py 14# @author Daniel Krajzewicz 15# @date 2013-10-10 16 17from __future__ import absolute_import 18from __future__ import print_function 19import os 20import sys 21import subprocess 22import tempfile 23 24if 'SUMO_HOME' in os.environ: 25 tools = os.path.join(os.environ['SUMO_HOME'], 'tools') 26 sys.path.append(os.path.join(tools)) 27import sumolib # noqa 28 29 30class Node: 31 32 def __init__(self, nid, x, y, nodeType): 33 self.nid = nid 34 self.x = x 35 self.y = y 36 self.nodeType = nodeType 37 self.crossings = [] 38 39 def getNetworkCoordinates(self): 40 t = self.nid.split("/") 41 return [int(t[0]), int(t[1])] 42 43 def addCrossing(self, fromEdge, toEdge): 44 self.crossings.append([fromEdge, toEdge]) 45 46 47class Lane: 48 49 def __init__(self, dirs=None, allowed=None, disallowed=None): 50 self.dirs = dirs 51 self.allowed = allowed 52 self.disallowed = disallowed 53 if self.dirs is None: 54 self.dirs = [] 55 56 57class Split: 58 59 def __init__(self, distance, lanes): 60 self.distance = distance 61 self.lanes = lanes 62 63 64class Edge: 65 66 def __init__(self, eid=None, fromNode=None, toNode=None, numLanes=None, maxSpeed=None, lanes=None, splits=None): 67 self.eid = eid 68 self.fromNode = fromNode 69 self.toNode = toNode 70 self.numLanes = numLanes 71 self.maxSpeed = maxSpeed 72 self.lanes = lanes 73 if self.lanes is None: 74 self.lanes = [Lane() for _ in range(numLanes)] 75 self.splits = splits 76 if self.splits is None: 77 self.splits = [] 78 if numLanes is None: 79 numLanes = len(self.lanes) 80 81 def addSplit(self, distance, lanesToRight=None, lanesToLeft=None): 82 if len(self.splits) == 0: 83 if lanesToRight is None: 84 lanesToRight = 0 85 if lanesToLeft is None: 86 lanesToLeft = 0 87 lanes = range(lanesToRight, self.numLanes + lanesToRight) 88 self.splits.append(Split(0, lanes)) 89 lanes = range(0, self.numLanes + lanesToRight + lanesToLeft) 90 self.splits.append(Split(distance, lanes)) 91 self.lanes = [Lane() for _ in range(lanesToRight)] + self.lanes 92 self.lanes += [Lane() for _ in range(lanesToLeft)] 93 94 def getConnections(self, net): 95 ret = [] 96 97 seen = {} 98 for i, l in enumerate(self.lanes): 99 for d in l.dirs: 100 if d not in seen: 101 seen[d] = 0 102 c = net.dir2connection(d, self, i, seen[d]) 103 if c is not None: 104 ret.append(c) 105 seen[d] = seen[d] + 1 106 return ret 107 108 def getDirection(self): 109 n1c = self.fromNode.getNetworkCoordinates() 110 n2c = self.toNode.getNetworkCoordinates() 111 return [n2c[0] - n1c[0], n2c[1] - n1c[1]] 112 113 114class Connection: 115 116 def __init__(self, fromEdge, fromLane, toEdge, toLane): 117 self.fromEdge = fromEdge 118 self.fromLane = fromLane 119 self.toEdge = toEdge 120 self.toLane = toLane 121 122 123class E1: 124 125 def __init__(self, id, laneID, pos, freq, outputFile): 126 self.id = id 127 self.laneID = laneID 128 self.pos = pos 129 self.freq = freq 130 self.outputFile = outputFile 131 132 133class Net: 134 135 def __init__(self, defaultNode, defaultEdge): 136 self._nodes = {} 137 self._edges = {} 138 self._defaultEdge = defaultEdge 139 if self._defaultEdge is None: 140 self._defaultEdge = Edge(None, None, None, 2, 13.89) 141 self._defaultNode = defaultNode 142 if self._defaultNode is None: 143 self._defaultNode = Node(None, None, None, "traffic_light") 144 self._e1 = {} 145 self.netName = None 146 147 def addNode(self, n): 148 self._nodes[n.nid] = n 149 150 def getNode(self, id): 151 if id in self._nodes: 152 return self._nodes[id] 153 return None 154 155 def addEdge(self, e): 156 self._edges[e.eid] = e 157 158 def addE1Detectors(self, id, laneID, pos, freq, outputFile): 159 e1 = E1(id, laneID, pos, freq, outputFile) 160 self._e1[e1.id] = e1 161 return e1 162 163 def getEdge(self, id): 164 if id in self._edges: 165 return self._edges[id] 166 return None 167 168 def getDefaultEdge(self, n1, n2): 169 return self._defaultEdge 170 171 def buildEdge(self, n1, n2): 172 defEdge = self.getDefaultEdge(n1, n2) 173 splits = [] 174 for s in defEdge.splits: 175 splits.append(s) 176 lanes = list(defEdge.lanes) 177 numLanes = defEdge.numLanes 178 maxSpeed = defEdge.maxSpeed 179 e = Edge(n1.nid + "_to_" + n2.nid, n1, n2, numLanes=numLanes, 180 maxSpeed=maxSpeed, lanes=lanes, splits=splits) 181 return e 182 183 def connectNodes(self, node1, node2, bidi, centralReservation): 184 n1 = self._nodes[node1] 185 n2 = self._nodes[node2] 186 self.addEdge(self.buildEdge(n1, n2)) 187 if bidi: 188 self.addEdge(self.buildEdge(n2, n1)) 189 190 def getDirectionFromNode(self, n, dir): 191 nc = n.getNetworkCoordinates() 192 eid = n.nid + "_to_" + str(nc[0] + dir[0]) + "/" + str(nc[1] + dir[1]) 193 if eid in self._edges: 194 return self._edges[eid] 195 return None 196 197 def getMatchingOutgoing(self, edge, direction): 198 edir = edge.getDirection() 199 if direction == "s": 200 return self.getDirectionFromNode(edge.toNode, edir) 201 elif direction == "t": 202 return self.getDirectionFromNode(edge.toNode, [-1 * edir[0], -1 * edir[1]]) 203 elif direction == "r": 204 # look, the following is because SUMO's coordinates don't match: 205 # the y-direction starts at the bottom, while x on right 206 if edir[0] == 0: 207 return self.getDirectionFromNode(edge.toNode, [1 * edir[1], 1 * edir[0]]) 208 else: 209 return self.getDirectionFromNode(edge.toNode, [-1 * edir[1], -1 * edir[0]]) 210 elif direction == "l": 211 # the same as above 212 if edir[0] != 0: 213 return self.getDirectionFromNode(edge.toNode, [1 * edir[1], 1 * edir[0]]) 214 else: 215 return self.getDirectionFromNode(edge.toNode, [-1 * edir[1], -1 * edir[0]]) 216 else: 217 raise RuntimeError("Unrecognized direction '%s'" % direction) 218 219 def dir2connection(self, direction, edge, lane, seen): 220 toEdge = self.getMatchingOutgoing(edge, direction) 221 if toEdge is not None: 222 if toEdge.lanes[seen].allowed != edge.lanes[lane].allowed: 223 seen = seen + 1 224 return Connection(edge, lane, toEdge, seen) 225 return None 226 227 def build(self, netName="net.net.xml"): 228 connections = [] 229 nodesFile = tempfile.NamedTemporaryFile(mode="w", delete=False) 230 print("<nodes>", file=nodesFile) 231 for nid in self._nodes: 232 n = self._nodes[nid] 233 print(' <node id="%s" x="%s" y="%s" type="%s"/>' % ( 234 n.nid, n.x, n.y, n.nodeType), file=nodesFile) 235 print("</nodes>", file=nodesFile) 236 nodesFile.close() 237 238 edgesFile = tempfile.NamedTemporaryFile(mode="w", delete=False) 239 print("<edges>", file=edgesFile) 240 for eid in self._edges: 241 e = self._edges[eid] 242 print(' <edge id="%s" from="%s" to="%s" numLanes="%s" speed="%s">' % ( 243 e.eid, e.fromNode.nid, e.toNode.nid, e.numLanes, e.maxSpeed), file=edgesFile) 244 for s in e.splits: 245 print(' <split pos="%s" lanes="%s"/>' % 246 (-s.distance, " ".join(map(str, s.lanes))), file=edgesFile) 247 248 """ 249 for i,l in enumerate(e.lanes): 250 if l.allowed==None and l.disallowed==None: 251 continue 252 ls = ' <lane index="%s" ' % (i) 253 if l.allowed!=None: 254 ls = ls + 'allow="%s"' % l.allowed 255 if l.disallowed!=None: 256 ls = ls + 'disallow="%s"' % l.disallowed 257 print >> edgesFile, ls+'/>' 258 """ 259 260 connections.extend(e.getConnections(self)) 261 print(' </edge>', file=edgesFile) 262 263 hadConstraints = False 264 for i, l in enumerate(e.lanes): 265 if l.allowed is None and l.disallowed is None: 266 continue 267 hadConstraints = True 268 if hadConstraints: 269 for s in e.splits: 270 eid = e.eid 271 if s.distance != 0: 272 eid = eid + ".%s" % -s.distance 273 print(' <edge id="%s">' % (eid), file=edgesFile) 274 for i, l in enumerate(e.lanes): 275 # if i not in s.lanes: 276 # continue 277 if l.allowed is None and l.disallowed is None: 278 continue 279 ls = ' <lane index="%s" ' % (i) 280 if l.allowed is not None: 281 ls = ls + 'allow="%s"' % l.allowed 282 if l.disallowed is not None: 283 ls = ls + 'disallow="%s"' % l.disallowed 284 print(ls + '/>', file=edgesFile) 285 print(' </edge>', file=edgesFile) 286 287 print("</edges>", file=edgesFile) 288 edgesFile.close() 289 290 connectionsFile = tempfile.NamedTemporaryFile(mode="w", delete=False) 291 print("<connections>", file=connectionsFile) 292 for c in connections: 293 eid = c.fromEdge.eid 294 if len(c.fromEdge.splits) > 1: 295 eid = eid + ".-" + str(c.fromEdge.splits[-1].distance) 296 print(' <connection from="%s" to="%s" fromLane="%s" toLane="%s"/>' % ( 297 eid, c.toEdge.eid, c.fromLane, c.toLane), file=connectionsFile) 298 for n in self._nodes: 299 if len(self._nodes[n].crossings) == 0: 300 continue 301 for c in self._nodes[n].crossings: 302 print(' <crossing node="%s" edges="%s"/>' % ( 303 n, " ".join(c)), file=connectionsFile) 304 print("</connections>", file=connectionsFile) 305 connectionsFile.close() 306 307 netconvert = sumolib.checkBinary("netconvert") 308 309 subprocess.call([netconvert, "-v", "-n", nodesFile.name, "-e", edgesFile.name, "-x", connectionsFile.name, 310 "-o", netName]) 311 os.remove(nodesFile.name) 312 os.remove(edgesFile.name) 313 os.remove(connectionsFile.name) 314 self.netName = netName 315 return netName 316 317 def buildDetectors(self, filename): 318 e1File = filename 319 fdo = open(e1File, "w") 320 print("<additional>", file=fdo) 321 for e1id in self._e1: 322 e1 = self._e1[e1id] 323 print(' <e1Detector id="%s" lane="%s" pos="%s" freq="%s" file="%s"/>' % ( 324 e1.id, e1.laneID, e1.pos, e1.freq, e1.outputFile), file=fdo) 325 print("</additional>", file=fdo) 326 fdo.close()
class
Node:
31class Node: 32 33 def __init__(self, nid, x, y, nodeType): 34 self.nid = nid 35 self.x = x 36 self.y = y 37 self.nodeType = nodeType 38 self.crossings = [] 39 40 def getNetworkCoordinates(self): 41 t = self.nid.split("/") 42 return [int(t[0]), int(t[1])] 43 44 def addCrossing(self, fromEdge, toEdge): 45 self.crossings.append([fromEdge, toEdge])
class
Lane:
48class Lane: 49 50 def __init__(self, dirs=None, allowed=None, disallowed=None): 51 self.dirs = dirs 52 self.allowed = allowed 53 self.disallowed = disallowed 54 if self.dirs is None: 55 self.dirs = []
class
Split:
58class Split: 59 60 def __init__(self, distance, lanes): 61 self.distance = distance 62 self.lanes = lanes
class
Edge:
65class Edge: 66 67 def __init__(self, eid=None, fromNode=None, toNode=None, numLanes=None, maxSpeed=None, lanes=None, splits=None): 68 self.eid = eid 69 self.fromNode = fromNode 70 self.toNode = toNode 71 self.numLanes = numLanes 72 self.maxSpeed = maxSpeed 73 self.lanes = lanes 74 if self.lanes is None: 75 self.lanes = [Lane() for _ in range(numLanes)] 76 self.splits = splits 77 if self.splits is None: 78 self.splits = [] 79 if numLanes is None: 80 numLanes = len(self.lanes) 81 82 def addSplit(self, distance, lanesToRight=None, lanesToLeft=None): 83 if len(self.splits) == 0: 84 if lanesToRight is None: 85 lanesToRight = 0 86 if lanesToLeft is None: 87 lanesToLeft = 0 88 lanes = range(lanesToRight, self.numLanes + lanesToRight) 89 self.splits.append(Split(0, lanes)) 90 lanes = range(0, self.numLanes + lanesToRight + lanesToLeft) 91 self.splits.append(Split(distance, lanes)) 92 self.lanes = [Lane() for _ in range(lanesToRight)] + self.lanes 93 self.lanes += [Lane() for _ in range(lanesToLeft)] 94 95 def getConnections(self, net): 96 ret = [] 97 98 seen = {} 99 for i, l in enumerate(self.lanes): 100 for d in l.dirs: 101 if d not in seen: 102 seen[d] = 0 103 c = net.dir2connection(d, self, i, seen[d]) 104 if c is not None: 105 ret.append(c) 106 seen[d] = seen[d] + 1 107 return ret 108 109 def getDirection(self): 110 n1c = self.fromNode.getNetworkCoordinates() 111 n2c = self.toNode.getNetworkCoordinates() 112 return [n2c[0] - n1c[0], n2c[1] - n1c[1]]
Edge( eid=None, fromNode=None, toNode=None, numLanes=None, maxSpeed=None, lanes=None, splits=None)
67 def __init__(self, eid=None, fromNode=None, toNode=None, numLanes=None, maxSpeed=None, lanes=None, splits=None): 68 self.eid = eid 69 self.fromNode = fromNode 70 self.toNode = toNode 71 self.numLanes = numLanes 72 self.maxSpeed = maxSpeed 73 self.lanes = lanes 74 if self.lanes is None: 75 self.lanes = [Lane() for _ in range(numLanes)] 76 self.splits = splits 77 if self.splits is None: 78 self.splits = [] 79 if numLanes is None: 80 numLanes = len(self.lanes)
def
addSplit(self, distance, lanesToRight=None, lanesToLeft=None):
82 def addSplit(self, distance, lanesToRight=None, lanesToLeft=None): 83 if len(self.splits) == 0: 84 if lanesToRight is None: 85 lanesToRight = 0 86 if lanesToLeft is None: 87 lanesToLeft = 0 88 lanes = range(lanesToRight, self.numLanes + lanesToRight) 89 self.splits.append(Split(0, lanes)) 90 lanes = range(0, self.numLanes + lanesToRight + lanesToLeft) 91 self.splits.append(Split(distance, lanes)) 92 self.lanes = [Lane() for _ in range(lanesToRight)] + self.lanes 93 self.lanes += [Lane() for _ in range(lanesToLeft)]
class
Connection:
115class Connection: 116 117 def __init__(self, fromEdge, fromLane, toEdge, toLane): 118 self.fromEdge = fromEdge 119 self.fromLane = fromLane 120 self.toEdge = toEdge 121 self.toLane = toLane
class
E1:
124class E1: 125 126 def __init__(self, id, laneID, pos, freq, outputFile): 127 self.id = id 128 self.laneID = laneID 129 self.pos = pos 130 self.freq = freq 131 self.outputFile = outputFile
class
Net:
134class Net: 135 136 def __init__(self, defaultNode, defaultEdge): 137 self._nodes = {} 138 self._edges = {} 139 self._defaultEdge = defaultEdge 140 if self._defaultEdge is None: 141 self._defaultEdge = Edge(None, None, None, 2, 13.89) 142 self._defaultNode = defaultNode 143 if self._defaultNode is None: 144 self._defaultNode = Node(None, None, None, "traffic_light") 145 self._e1 = {} 146 self.netName = None 147 148 def addNode(self, n): 149 self._nodes[n.nid] = n 150 151 def getNode(self, id): 152 if id in self._nodes: 153 return self._nodes[id] 154 return None 155 156 def addEdge(self, e): 157 self._edges[e.eid] = e 158 159 def addE1Detectors(self, id, laneID, pos, freq, outputFile): 160 e1 = E1(id, laneID, pos, freq, outputFile) 161 self._e1[e1.id] = e1 162 return e1 163 164 def getEdge(self, id): 165 if id in self._edges: 166 return self._edges[id] 167 return None 168 169 def getDefaultEdge(self, n1, n2): 170 return self._defaultEdge 171 172 def buildEdge(self, n1, n2): 173 defEdge = self.getDefaultEdge(n1, n2) 174 splits = [] 175 for s in defEdge.splits: 176 splits.append(s) 177 lanes = list(defEdge.lanes) 178 numLanes = defEdge.numLanes 179 maxSpeed = defEdge.maxSpeed 180 e = Edge(n1.nid + "_to_" + n2.nid, n1, n2, numLanes=numLanes, 181 maxSpeed=maxSpeed, lanes=lanes, splits=splits) 182 return e 183 184 def connectNodes(self, node1, node2, bidi, centralReservation): 185 n1 = self._nodes[node1] 186 n2 = self._nodes[node2] 187 self.addEdge(self.buildEdge(n1, n2)) 188 if bidi: 189 self.addEdge(self.buildEdge(n2, n1)) 190 191 def getDirectionFromNode(self, n, dir): 192 nc = n.getNetworkCoordinates() 193 eid = n.nid + "_to_" + str(nc[0] + dir[0]) + "/" + str(nc[1] + dir[1]) 194 if eid in self._edges: 195 return self._edges[eid] 196 return None 197 198 def getMatchingOutgoing(self, edge, direction): 199 edir = edge.getDirection() 200 if direction == "s": 201 return self.getDirectionFromNode(edge.toNode, edir) 202 elif direction == "t": 203 return self.getDirectionFromNode(edge.toNode, [-1 * edir[0], -1 * edir[1]]) 204 elif direction == "r": 205 # look, the following is because SUMO's coordinates don't match: 206 # the y-direction starts at the bottom, while x on right 207 if edir[0] == 0: 208 return self.getDirectionFromNode(edge.toNode, [1 * edir[1], 1 * edir[0]]) 209 else: 210 return self.getDirectionFromNode(edge.toNode, [-1 * edir[1], -1 * edir[0]]) 211 elif direction == "l": 212 # the same as above 213 if edir[0] != 0: 214 return self.getDirectionFromNode(edge.toNode, [1 * edir[1], 1 * edir[0]]) 215 else: 216 return self.getDirectionFromNode(edge.toNode, [-1 * edir[1], -1 * edir[0]]) 217 else: 218 raise RuntimeError("Unrecognized direction '%s'" % direction) 219 220 def dir2connection(self, direction, edge, lane, seen): 221 toEdge = self.getMatchingOutgoing(edge, direction) 222 if toEdge is not None: 223 if toEdge.lanes[seen].allowed != edge.lanes[lane].allowed: 224 seen = seen + 1 225 return Connection(edge, lane, toEdge, seen) 226 return None 227 228 def build(self, netName="net.net.xml"): 229 connections = [] 230 nodesFile = tempfile.NamedTemporaryFile(mode="w", delete=False) 231 print("<nodes>", file=nodesFile) 232 for nid in self._nodes: 233 n = self._nodes[nid] 234 print(' <node id="%s" x="%s" y="%s" type="%s"/>' % ( 235 n.nid, n.x, n.y, n.nodeType), file=nodesFile) 236 print("</nodes>", file=nodesFile) 237 nodesFile.close() 238 239 edgesFile = tempfile.NamedTemporaryFile(mode="w", delete=False) 240 print("<edges>", file=edgesFile) 241 for eid in self._edges: 242 e = self._edges[eid] 243 print(' <edge id="%s" from="%s" to="%s" numLanes="%s" speed="%s">' % ( 244 e.eid, e.fromNode.nid, e.toNode.nid, e.numLanes, e.maxSpeed), file=edgesFile) 245 for s in e.splits: 246 print(' <split pos="%s" lanes="%s"/>' % 247 (-s.distance, " ".join(map(str, s.lanes))), file=edgesFile) 248 249 """ 250 for i,l in enumerate(e.lanes): 251 if l.allowed==None and l.disallowed==None: 252 continue 253 ls = ' <lane index="%s" ' % (i) 254 if l.allowed!=None: 255 ls = ls + 'allow="%s"' % l.allowed 256 if l.disallowed!=None: 257 ls = ls + 'disallow="%s"' % l.disallowed 258 print >> edgesFile, ls+'/>' 259 """ 260 261 connections.extend(e.getConnections(self)) 262 print(' </edge>', file=edgesFile) 263 264 hadConstraints = False 265 for i, l in enumerate(e.lanes): 266 if l.allowed is None and l.disallowed is None: 267 continue 268 hadConstraints = True 269 if hadConstraints: 270 for s in e.splits: 271 eid = e.eid 272 if s.distance != 0: 273 eid = eid + ".%s" % -s.distance 274 print(' <edge id="%s">' % (eid), file=edgesFile) 275 for i, l in enumerate(e.lanes): 276 # if i not in s.lanes: 277 # continue 278 if l.allowed is None and l.disallowed is None: 279 continue 280 ls = ' <lane index="%s" ' % (i) 281 if l.allowed is not None: 282 ls = ls + 'allow="%s"' % l.allowed 283 if l.disallowed is not None: 284 ls = ls + 'disallow="%s"' % l.disallowed 285 print(ls + '/>', file=edgesFile) 286 print(' </edge>', file=edgesFile) 287 288 print("</edges>", file=edgesFile) 289 edgesFile.close() 290 291 connectionsFile = tempfile.NamedTemporaryFile(mode="w", delete=False) 292 print("<connections>", file=connectionsFile) 293 for c in connections: 294 eid = c.fromEdge.eid 295 if len(c.fromEdge.splits) > 1: 296 eid = eid + ".-" + str(c.fromEdge.splits[-1].distance) 297 print(' <connection from="%s" to="%s" fromLane="%s" toLane="%s"/>' % ( 298 eid, c.toEdge.eid, c.fromLane, c.toLane), file=connectionsFile) 299 for n in self._nodes: 300 if len(self._nodes[n].crossings) == 0: 301 continue 302 for c in self._nodes[n].crossings: 303 print(' <crossing node="%s" edges="%s"/>' % ( 304 n, " ".join(c)), file=connectionsFile) 305 print("</connections>", file=connectionsFile) 306 connectionsFile.close() 307 308 netconvert = sumolib.checkBinary("netconvert") 309 310 subprocess.call([netconvert, "-v", "-n", nodesFile.name, "-e", edgesFile.name, "-x", connectionsFile.name, 311 "-o", netName]) 312 os.remove(nodesFile.name) 313 os.remove(edgesFile.name) 314 os.remove(connectionsFile.name) 315 self.netName = netName 316 return netName 317 318 def buildDetectors(self, filename): 319 e1File = filename 320 fdo = open(e1File, "w") 321 print("<additional>", file=fdo) 322 for e1id in self._e1: 323 e1 = self._e1[e1id] 324 print(' <e1Detector id="%s" lane="%s" pos="%s" freq="%s" file="%s"/>' % ( 325 e1.id, e1.laneID, e1.pos, e1.freq, e1.outputFile), file=fdo) 326 print("</additional>", file=fdo) 327 fdo.close()
Net(defaultNode, defaultEdge)
136 def __init__(self, defaultNode, defaultEdge): 137 self._nodes = {} 138 self._edges = {} 139 self._defaultEdge = defaultEdge 140 if self._defaultEdge is None: 141 self._defaultEdge = Edge(None, None, None, 2, 13.89) 142 self._defaultNode = defaultNode 143 if self._defaultNode is None: 144 self._defaultNode = Node(None, None, None, "traffic_light") 145 self._e1 = {} 146 self.netName = None
def
buildEdge(self, n1, n2):
172 def buildEdge(self, n1, n2): 173 defEdge = self.getDefaultEdge(n1, n2) 174 splits = [] 175 for s in defEdge.splits: 176 splits.append(s) 177 lanes = list(defEdge.lanes) 178 numLanes = defEdge.numLanes 179 maxSpeed = defEdge.maxSpeed 180 e = Edge(n1.nid + "_to_" + n2.nid, n1, n2, numLanes=numLanes, 181 maxSpeed=maxSpeed, lanes=lanes, splits=splits) 182 return e
def
getMatchingOutgoing(self, edge, direction):
198 def getMatchingOutgoing(self, edge, direction): 199 edir = edge.getDirection() 200 if direction == "s": 201 return self.getDirectionFromNode(edge.toNode, edir) 202 elif direction == "t": 203 return self.getDirectionFromNode(edge.toNode, [-1 * edir[0], -1 * edir[1]]) 204 elif direction == "r": 205 # look, the following is because SUMO's coordinates don't match: 206 # the y-direction starts at the bottom, while x on right 207 if edir[0] == 0: 208 return self.getDirectionFromNode(edge.toNode, [1 * edir[1], 1 * edir[0]]) 209 else: 210 return self.getDirectionFromNode(edge.toNode, [-1 * edir[1], -1 * edir[0]]) 211 elif direction == "l": 212 # the same as above 213 if edir[0] != 0: 214 return self.getDirectionFromNode(edge.toNode, [1 * edir[1], 1 * edir[0]]) 215 else: 216 return self.getDirectionFromNode(edge.toNode, [-1 * edir[1], -1 * edir[0]]) 217 else: 218 raise RuntimeError("Unrecognized direction '%s'" % direction)
def
build(self, netName='net.net.xml'):
228 def build(self, netName="net.net.xml"): 229 connections = [] 230 nodesFile = tempfile.NamedTemporaryFile(mode="w", delete=False) 231 print("<nodes>", file=nodesFile) 232 for nid in self._nodes: 233 n = self._nodes[nid] 234 print(' <node id="%s" x="%s" y="%s" type="%s"/>' % ( 235 n.nid, n.x, n.y, n.nodeType), file=nodesFile) 236 print("</nodes>", file=nodesFile) 237 nodesFile.close() 238 239 edgesFile = tempfile.NamedTemporaryFile(mode="w", delete=False) 240 print("<edges>", file=edgesFile) 241 for eid in self._edges: 242 e = self._edges[eid] 243 print(' <edge id="%s" from="%s" to="%s" numLanes="%s" speed="%s">' % ( 244 e.eid, e.fromNode.nid, e.toNode.nid, e.numLanes, e.maxSpeed), file=edgesFile) 245 for s in e.splits: 246 print(' <split pos="%s" lanes="%s"/>' % 247 (-s.distance, " ".join(map(str, s.lanes))), file=edgesFile) 248 249 """ 250 for i,l in enumerate(e.lanes): 251 if l.allowed==None and l.disallowed==None: 252 continue 253 ls = ' <lane index="%s" ' % (i) 254 if l.allowed!=None: 255 ls = ls + 'allow="%s"' % l.allowed 256 if l.disallowed!=None: 257 ls = ls + 'disallow="%s"' % l.disallowed 258 print >> edgesFile, ls+'/>' 259 """ 260 261 connections.extend(e.getConnections(self)) 262 print(' </edge>', file=edgesFile) 263 264 hadConstraints = False 265 for i, l in enumerate(e.lanes): 266 if l.allowed is None and l.disallowed is None: 267 continue 268 hadConstraints = True 269 if hadConstraints: 270 for s in e.splits: 271 eid = e.eid 272 if s.distance != 0: 273 eid = eid + ".%s" % -s.distance 274 print(' <edge id="%s">' % (eid), file=edgesFile) 275 for i, l in enumerate(e.lanes): 276 # if i not in s.lanes: 277 # continue 278 if l.allowed is None and l.disallowed is None: 279 continue 280 ls = ' <lane index="%s" ' % (i) 281 if l.allowed is not None: 282 ls = ls + 'allow="%s"' % l.allowed 283 if l.disallowed is not None: 284 ls = ls + 'disallow="%s"' % l.disallowed 285 print(ls + '/>', file=edgesFile) 286 print(' </edge>', file=edgesFile) 287 288 print("</edges>", file=edgesFile) 289 edgesFile.close() 290 291 connectionsFile = tempfile.NamedTemporaryFile(mode="w", delete=False) 292 print("<connections>", file=connectionsFile) 293 for c in connections: 294 eid = c.fromEdge.eid 295 if len(c.fromEdge.splits) > 1: 296 eid = eid + ".-" + str(c.fromEdge.splits[-1].distance) 297 print(' <connection from="%s" to="%s" fromLane="%s" toLane="%s"/>' % ( 298 eid, c.toEdge.eid, c.fromLane, c.toLane), file=connectionsFile) 299 for n in self._nodes: 300 if len(self._nodes[n].crossings) == 0: 301 continue 302 for c in self._nodes[n].crossings: 303 print(' <crossing node="%s" edges="%s"/>' % ( 304 n, " ".join(c)), file=connectionsFile) 305 print("</connections>", file=connectionsFile) 306 connectionsFile.close() 307 308 netconvert = sumolib.checkBinary("netconvert") 309 310 subprocess.call([netconvert, "-v", "-n", nodesFile.name, "-e", edgesFile.name, "-x", connectionsFile.name, 311 "-o", netName]) 312 os.remove(nodesFile.name) 313 os.remove(edgesFile.name) 314 os.remove(connectionsFile.name) 315 self.netName = netName 316 return netName
def
buildDetectors(self, filename):
318 def buildDetectors(self, filename): 319 e1File = filename 320 fdo = open(e1File, "w") 321 print("<additional>", file=fdo) 322 for e1id in self._e1: 323 e1 = self._e1[e1id] 324 print(' <e1Detector id="%s" lane="%s" pos="%s" freq="%s" file="%s"/>' % ( 325 e1.id, e1.laneID, e1.pos, e1.freq, e1.outputFile), file=fdo) 326 print("</additional>", file=fdo) 327 fdo.close()