traci.connection
1# -*- coding: utf-8 -*- 2# Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo 3# Copyright (C) 2008-2026 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 connection.py 15# @author Michael Behrisch 16# @author Lena Kalleske 17# @author Mario Krumnow 18# @author Daniel Krajzewicz 19# @author Jakob Erdmann 20# @date 2008-10-09 21 22from __future__ import print_function 23from __future__ import absolute_import 24import socket 25import struct 26import sys 27import warnings 28import threading 29 30from . import constants as tc 31from .exceptions import TraCIException, FatalTraCIError 32from .domain import DOMAINS 33from .storage import Storage 34from .step import StepManager 35 36_DEBUG = False 37_RESULTS = {0x00: "OK", 0x01: "Not implemented", 0xFF: "Error"} 38 39_connections = {} 40_connectHook = None 41 42 43def check(): 44 if "" not in _connections: 45 raise FatalTraCIError("Not connected.") 46 return _connections[""] 47 48 49def has(label): 50 return label in _connections 51 52 53def get(label="default"): 54 if label not in _connections: 55 raise TraCIException("Connection '%s' is not known." % label) 56 return _connections[label] 57 58 59def switch(label): 60 con = get(label) 61 _connections[""] = con 62 for domain in DOMAINS: 63 domain._setConnection(con) 64 65 66class Connection(StepManager): 67 68 """Contains the socket, the composed message string 69 together with a list of TraCI commands which are inside. 70 """ 71 72 def __init__(self, host, port, process, traceFile, traceGetters, label=None): 73 StepManager.__init__(self) 74 if label in _connections: 75 raise TraCIException("Connection '%s' is already active." % label) 76 if sys.platform.startswith('java'): 77 # working around jython 2.7.0 bug #2273 78 self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_TCP) 79 else: 80 self._socket = socket.socket() 81 self._socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) 82 try: 83 self._socket.connect((host, port)) 84 except socket.error: 85 self._socket.close() 86 raise 87 self._process = process 88 self._string = bytes() 89 self._queue = [] 90 self._subscriptionMapping = {} 91 self._lock = threading.Lock() 92 if traceFile is not None: 93 self.startTracing(traceFile, traceGetters, DOMAINS) 94 for domain in DOMAINS: 95 domain._register(self, self._subscriptionMapping) 96 self._label = label 97 if _connectHook is not None: 98 _connectHook(self) 99 if label is not None: 100 _connections[label] = self 101 102 def getLabel(self): 103 return self._label 104 105 def _recvExact(self): 106 try: 107 result = bytes() 108 while len(result) < 4: 109 t = self._socket.recv(4 - len(result)) 110 if not t: 111 return None 112 result += t 113 length = struct.unpack("!i", result)[0] - 4 114 result = bytes() 115 while len(result) < length: 116 t = self._socket.recv(length - len(result)) 117 if not t: 118 return None 119 result += t 120 return Storage(result) 121 except socket.error: 122 return None 123 124 def _sendExact(self): 125 if self._socket is None: 126 raise FatalTraCIError("Connection already closed.") 127 length = struct.pack("!i", len(self._string) + 4) 128 if _DEBUG: 129 print("sending", Storage(length + self._string).getDebugString()) 130 self._socket.send(length + self._string) 131 result = self._recvExact() 132 if _DEBUG: 133 print("receiving", result.getDebugString()) 134 if not result: 135 self._socket.close() 136 self._socket = None 137 raise FatalTraCIError("Connection closed by SUMO.") 138 for command in self._queue: 139 prefix = result.read("!BBB") 140 err = result.readString() 141 if prefix[2] or err: 142 self._string = bytes() 143 self._queue = [] 144 raise TraCIException(err, prefix[1], _RESULTS[prefix[2]]) 145 elif prefix[1] != command: 146 raise FatalTraCIError("Received answer %s for command %s." % (prefix[1], command)) 147 elif prefix[1] == tc.CMD_STOP: 148 length = result.read("!B")[0] - 1 149 result.read("!%sx" % length) 150 self._string = bytes() 151 self._queue = [] 152 return result 153 154 def _pack(self, format, *values): 155 packed = bytes() 156 for f, v in zip(format, values): 157 if f == "i": 158 packed += struct.pack("!Bi", tc.TYPE_INTEGER, int(v)) 159 elif f == "I": # raw int for setOrder 160 packed += struct.pack("!i", int(v)) 161 elif f == "d": 162 packed += struct.pack("!Bd", tc.TYPE_DOUBLE, float(v)) 163 elif f == "D": # raw double for some base commands like simstep 164 packed += struct.pack("!d", float(v)) 165 elif f == "b": 166 packed += struct.pack("!Bb", tc.TYPE_BYTE, int(v)) 167 elif f == "B": 168 packed += struct.pack("!BB", tc.TYPE_UBYTE, int(v)) 169 elif f == "u": # raw unsigned byte needed for distance command and subscribe 170 packed += struct.pack("!B", int(v)) 171 elif f == "s": 172 if sys.version_info[0] > 2 or not isinstance(v, str): 173 v = str(v).encode("utf8") 174 packed += struct.pack("!Bi", tc.TYPE_STRING, len(v)) + v 175 elif f == "p": # polygon 176 if len(v) <= 255: 177 packed += struct.pack("!BB", tc.TYPE_POLYGON, len(v)) 178 else: 179 packed += struct.pack("!BBi", tc.TYPE_POLYGON, 0, len(v)) 180 for p in v: 181 packed += struct.pack("!dd", *p) 182 elif f == "t": # tuple aka compound 183 packed += struct.pack("!Bi", tc.TYPE_COMPOUND, v) 184 elif f == "c": # color 185 packed += struct.pack("!BBBBB", tc.TYPE_COLOR, int(v[0]), int(v[1]), int(v[2]), 186 int(v[3]) if len(v) > 3 else 255) 187 elif f == "l": # string list 188 packed += struct.pack("!Bi", tc.TYPE_STRINGLIST, len(v)) 189 for s in v: 190 s = str(s).encode("utf8") 191 packed += struct.pack("!i", len(s)) + s 192 elif f == "f": # float list 193 packed += struct.pack("!Bi", tc.TYPE_DOUBLELIST, len(v)) 194 for x in v: 195 packed += struct.pack("!d", x) 196 elif f == "o": 197 packed += struct.pack("!Bdd", tc.POSITION_2D, *v) 198 elif f == "O": 199 packed += struct.pack("!Bddd", tc.POSITION_3D, *v) 200 elif f == "g": 201 packed += struct.pack("!Bdd", tc.POSITION_LON_LAT, *v) 202 elif f == "G": 203 packed += struct.pack("!Bddd", tc.POSITION_LON_LAT_ALT, *v) 204 elif f == "r": 205 s = str(v[0]).encode("utf8") 206 packed += struct.pack("!Bi", tc.POSITION_ROADMAP, len(s)) + s 207 packed += struct.pack("!dB", v[1], v[2]) 208 return packed 209 210 def _sendCmd(self, cmdID, varID, objID, format="", *values): 211 with self._lock: 212 self._queue.append(cmdID) 213 packed = self._pack(format, *values) 214 objID = str(objID).encode("utf8") 215 length = len(packed) + 1 + 1 # length and command 216 if varID is not None: 217 if isinstance(varID, tuple): # begin and end of a subscription 218 length += 8 + 8 + 4 + len(objID) 219 else: 220 length += 1 + 4 + len(objID) 221 if length <= 255: 222 self._string += struct.pack("!BB", length, cmdID) 223 else: 224 self._string += struct.pack("!BiB", 0, length + 4, cmdID) 225 if varID is not None: 226 if isinstance(varID, tuple): 227 self._string += struct.pack("!dd", *varID) 228 else: 229 self._string += struct.pack("!B", varID) 230 self._string += struct.pack("!i", len(objID)) + objID 231 self._string += packed 232 return self._sendExact() 233 234 def _readSubscription(self, result): 235 if _DEBUG: 236 print("reading subscription", result.getDebugString()) 237 result.readLength() 238 response = result.read("!B")[0] 239 isVariableSubscription = ((response >= tc.RESPONSE_SUBSCRIBE_INDUCTIONLOOP_VARIABLE and 240 response <= tc.RESPONSE_SUBSCRIBE_BUSSTOP_VARIABLE) or 241 (response >= tc.RESPONSE_SUBSCRIBE_PARKINGAREA_VARIABLE and 242 response <= tc.RESPONSE_SUBSCRIBE_OVERHEADWIRE_VARIABLE)) 243 objectID = result.readString() 244 contextDomain = 0 if isVariableSubscription else result.read("!B")[0] 245 numVars = result.read("!B")[0] 246 if isVariableSubscription: 247 while numVars > 0: 248 varID, status = result.read("!BB") 249 if status: 250 print("Error!", result.readTypedString()) 251 elif response in self._subscriptionMapping: 252 self._subscriptionMapping[response].add(objectID, varID, result) 253 else: 254 raise FatalTraCIError( 255 "Cannot handle subscription response %02x for %s." % (response, objectID)) 256 numVars -= 1 257 else: 258 objectNo = result.read("!i")[0] 259 subsMap = self._subscriptionMapping[response] 260 subsMap.addContext(objectID) 261 for _ in range(objectNo): 262 oid = result.readString() 263 if numVars == 0: 264 subsMap.addContext(objectID, oid) 265 for __ in range(numVars): 266 varID, status = result.read("!BB") 267 if status: 268 print("Error!", result.readTypedString()) 269 elif contextDomain in self._subscriptionMapping: 270 subsMap.addContext(objectID, oid, varID, 271 self._subscriptionMapping[contextDomain].parse(varID, result)) 272 else: 273 raise FatalTraCIError( 274 "Cannot handle subscription response %02x for %s." % (response, objectID)) 275 return objectID, response 276 277 def _subscribe(self, cmdID, begin, end, objID, varIDs, parameters): 278 format = "u" 279 args = [len(varIDs)] 280 for v in varIDs: 281 format += "u" 282 args.append(v) 283 if parameters is not None and v in parameters: 284 if isinstance(parameters[v], tuple): 285 format += parameters[v][0] 286 for a in parameters[v][1:]: 287 args.append(a) 288 elif isinstance(parameters[v], int): 289 format += "i" 290 args.append(parameters[v]) 291 elif isinstance(parameters[v], float): 292 format += "d" 293 args.append(parameters[v]) 294 else: 295 format += "s" 296 args.append(parameters[v]) 297 result = self._sendCmd(cmdID, (begin, end), objID, format, *args) 298 if varIDs: 299 objectID, response = self._readSubscription(result) 300 if response - cmdID != 16 or objectID != objID: 301 raise FatalTraCIError("Received answer %02x,%s for subscription command %02x,%s." % ( 302 response, objectID, cmdID, objID)) 303 304 def _getSubscriptionResults(self, cmdID): 305 return self._subscriptionMapping[cmdID] 306 307 def _subscribeContext(self, cmdID, begin, end, objID, domain, dist, varIDs, parameters=None): 308 result = self._sendCmd(cmdID, (begin, end), objID, "uDu" + (len(varIDs) * "u"), 309 domain, dist, len(varIDs), *varIDs) 310 if varIDs: 311 objectID, response = self._readSubscription(result) 312 if response - cmdID != 16 or objectID != objID: 313 raise FatalTraCIError("Received answer %02x,%s for context subscription command %02x,%s." % ( 314 response, objectID, cmdID, objID)) 315 316 def _addSubscriptionFilter(self, filterType, params=None): 317 if filterType in (tc.FILTER_TYPE_NONE, tc.FILTER_TYPE_NOOPPOSITE, 318 tc.FILTER_TYPE_LEAD_FOLLOW): 319 # filter without parameter 320 assert params is None 321 self._sendCmd(tc.CMD_ADD_SUBSCRIPTION_FILTER, None, None, "u", filterType) 322 elif filterType in (tc.FILTER_TYPE_DOWNSTREAM_DIST, tc.FILTER_TYPE_UPSTREAM_DIST, 323 tc.FILTER_TYPE_TURN, tc.FILTER_TYPE_FIELD_OF_VISION, 324 tc.FILTER_TYPE_LATERAL_DIST): 325 # filter with float parameter 326 self._sendCmd(tc.CMD_ADD_SUBSCRIPTION_FILTER, None, None, "ud", filterType, params) 327 elif filterType in (tc.FILTER_TYPE_VCLASS, tc.FILTER_TYPE_VTYPE): 328 # filter with list(string) parameter 329 self._sendCmd(tc.CMD_ADD_SUBSCRIPTION_FILTER, None, None, "ul", filterType, params) 330 elif filterType == tc.FILTER_TYPE_LANES: 331 # filter with list(byte) parameter 332 # check uniqueness of given lanes in list 333 lanes = set() 334 for i in params: 335 lane = int(i) 336 if lane < 0: 337 lane += 256 338 lanes.add(lane) 339 if len(lanes) < len(list(params)): 340 warnings.warn("Ignoring duplicate lane specification for subscription filter.") 341 self._sendCmd(tc.CMD_ADD_SUBSCRIPTION_FILTER, None, None, 342 (len(lanes) + 2) * "u", filterType, len(lanes), *lanes) 343 344 def hasGUI(self): 345 try: 346 self.gui.getIDList() 347 return True 348 except TraCIException: 349 return False 350 351 def load(self, args): 352 """ 353 Load a simulation from the given arguments. 354 """ 355 if self._traceFile: 356 self._traceFile.write("traci.load(%s)\n" % repr(args)) 357 self._sendCmd(tc.CMD_LOAD, None, None, "l", args) 358 359 def simulationStep(self, step=0.): 360 """ 361 Make a simulation step and simulate up to the given second in sim time. 362 If the given value is 0 or absent, exactly one step is performed. 363 Values smaller than or equal to the current sim time result in no action. 364 """ 365 if self._traceFile: 366 args = "" if step == 0 else str(step) 367 self._traceFile.write("traci.simulationStep(%s)\n" % args) 368 if type(step) is int and step >= 1000: 369 warnings.warn("API change now handles step as floating point seconds", stacklevel=2) 370 result = self._sendCmd(tc.CMD_SIMSTEP, None, None, "D", step) 371 for subscriptionResults in self._subscriptionMapping.values(): 372 subscriptionResults.reset() 373 numSubs = result.readInt() 374 responses = [] 375 while numSubs > 0: 376 responses.append(self._readSubscription(result)) 377 numSubs -= 1 378 self.manageStepListeners(step) 379 return responses 380 381 def getVersion(self): 382 command = tc.CMD_GETVERSION 383 result = self._sendCmd(command, None, None) 384 result.readLength() 385 response = result.read("!B")[0] 386 if response != command: 387 raise FatalTraCIError("Received answer %s for command %s." % (response, command)) 388 return result.readInt(), result.readString() 389 390 def setOrder(self, order): 391 self._sendCmd(tc.CMD_SETORDER, None, None, "I", order) 392 393 def close(self, wait=True): 394 StepManager.close(self, True) 395 for listenerID in list(self._stepListeners.keys()): 396 self.removeStepListener(listenerID) 397 if self._socket is not None: 398 self._sendCmd(tc.CMD_CLOSE, None, None) 399 self._socket.close() 400 self._socket = None 401 if wait and self._process is not None: 402 self._process.wait() 403 self.simulation._setConnection(None) 404 if self._label is not None: 405 if _connections.get("") == self: 406 del _connections[""] 407 del _connections[self._label]
def
check():
def
has(label):
def
get(label='default'):
def
switch(label):
class
Connection(traci.step.StepManager):
67class Connection(StepManager): 68 69 """Contains the socket, the composed message string 70 together with a list of TraCI commands which are inside. 71 """ 72 73 def __init__(self, host, port, process, traceFile, traceGetters, label=None): 74 StepManager.__init__(self) 75 if label in _connections: 76 raise TraCIException("Connection '%s' is already active." % label) 77 if sys.platform.startswith('java'): 78 # working around jython 2.7.0 bug #2273 79 self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_TCP) 80 else: 81 self._socket = socket.socket() 82 self._socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) 83 try: 84 self._socket.connect((host, port)) 85 except socket.error: 86 self._socket.close() 87 raise 88 self._process = process 89 self._string = bytes() 90 self._queue = [] 91 self._subscriptionMapping = {} 92 self._lock = threading.Lock() 93 if traceFile is not None: 94 self.startTracing(traceFile, traceGetters, DOMAINS) 95 for domain in DOMAINS: 96 domain._register(self, self._subscriptionMapping) 97 self._label = label 98 if _connectHook is not None: 99 _connectHook(self) 100 if label is not None: 101 _connections[label] = self 102 103 def getLabel(self): 104 return self._label 105 106 def _recvExact(self): 107 try: 108 result = bytes() 109 while len(result) < 4: 110 t = self._socket.recv(4 - len(result)) 111 if not t: 112 return None 113 result += t 114 length = struct.unpack("!i", result)[0] - 4 115 result = bytes() 116 while len(result) < length: 117 t = self._socket.recv(length - len(result)) 118 if not t: 119 return None 120 result += t 121 return Storage(result) 122 except socket.error: 123 return None 124 125 def _sendExact(self): 126 if self._socket is None: 127 raise FatalTraCIError("Connection already closed.") 128 length = struct.pack("!i", len(self._string) + 4) 129 if _DEBUG: 130 print("sending", Storage(length + self._string).getDebugString()) 131 self._socket.send(length + self._string) 132 result = self._recvExact() 133 if _DEBUG: 134 print("receiving", result.getDebugString()) 135 if not result: 136 self._socket.close() 137 self._socket = None 138 raise FatalTraCIError("Connection closed by SUMO.") 139 for command in self._queue: 140 prefix = result.read("!BBB") 141 err = result.readString() 142 if prefix[2] or err: 143 self._string = bytes() 144 self._queue = [] 145 raise TraCIException(err, prefix[1], _RESULTS[prefix[2]]) 146 elif prefix[1] != command: 147 raise FatalTraCIError("Received answer %s for command %s." % (prefix[1], command)) 148 elif prefix[1] == tc.CMD_STOP: 149 length = result.read("!B")[0] - 1 150 result.read("!%sx" % length) 151 self._string = bytes() 152 self._queue = [] 153 return result 154 155 def _pack(self, format, *values): 156 packed = bytes() 157 for f, v in zip(format, values): 158 if f == "i": 159 packed += struct.pack("!Bi", tc.TYPE_INTEGER, int(v)) 160 elif f == "I": # raw int for setOrder 161 packed += struct.pack("!i", int(v)) 162 elif f == "d": 163 packed += struct.pack("!Bd", tc.TYPE_DOUBLE, float(v)) 164 elif f == "D": # raw double for some base commands like simstep 165 packed += struct.pack("!d", float(v)) 166 elif f == "b": 167 packed += struct.pack("!Bb", tc.TYPE_BYTE, int(v)) 168 elif f == "B": 169 packed += struct.pack("!BB", tc.TYPE_UBYTE, int(v)) 170 elif f == "u": # raw unsigned byte needed for distance command and subscribe 171 packed += struct.pack("!B", int(v)) 172 elif f == "s": 173 if sys.version_info[0] > 2 or not isinstance(v, str): 174 v = str(v).encode("utf8") 175 packed += struct.pack("!Bi", tc.TYPE_STRING, len(v)) + v 176 elif f == "p": # polygon 177 if len(v) <= 255: 178 packed += struct.pack("!BB", tc.TYPE_POLYGON, len(v)) 179 else: 180 packed += struct.pack("!BBi", tc.TYPE_POLYGON, 0, len(v)) 181 for p in v: 182 packed += struct.pack("!dd", *p) 183 elif f == "t": # tuple aka compound 184 packed += struct.pack("!Bi", tc.TYPE_COMPOUND, v) 185 elif f == "c": # color 186 packed += struct.pack("!BBBBB", tc.TYPE_COLOR, int(v[0]), int(v[1]), int(v[2]), 187 int(v[3]) if len(v) > 3 else 255) 188 elif f == "l": # string list 189 packed += struct.pack("!Bi", tc.TYPE_STRINGLIST, len(v)) 190 for s in v: 191 s = str(s).encode("utf8") 192 packed += struct.pack("!i", len(s)) + s 193 elif f == "f": # float list 194 packed += struct.pack("!Bi", tc.TYPE_DOUBLELIST, len(v)) 195 for x in v: 196 packed += struct.pack("!d", x) 197 elif f == "o": 198 packed += struct.pack("!Bdd", tc.POSITION_2D, *v) 199 elif f == "O": 200 packed += struct.pack("!Bddd", tc.POSITION_3D, *v) 201 elif f == "g": 202 packed += struct.pack("!Bdd", tc.POSITION_LON_LAT, *v) 203 elif f == "G": 204 packed += struct.pack("!Bddd", tc.POSITION_LON_LAT_ALT, *v) 205 elif f == "r": 206 s = str(v[0]).encode("utf8") 207 packed += struct.pack("!Bi", tc.POSITION_ROADMAP, len(s)) + s 208 packed += struct.pack("!dB", v[1], v[2]) 209 return packed 210 211 def _sendCmd(self, cmdID, varID, objID, format="", *values): 212 with self._lock: 213 self._queue.append(cmdID) 214 packed = self._pack(format, *values) 215 objID = str(objID).encode("utf8") 216 length = len(packed) + 1 + 1 # length and command 217 if varID is not None: 218 if isinstance(varID, tuple): # begin and end of a subscription 219 length += 8 + 8 + 4 + len(objID) 220 else: 221 length += 1 + 4 + len(objID) 222 if length <= 255: 223 self._string += struct.pack("!BB", length, cmdID) 224 else: 225 self._string += struct.pack("!BiB", 0, length + 4, cmdID) 226 if varID is not None: 227 if isinstance(varID, tuple): 228 self._string += struct.pack("!dd", *varID) 229 else: 230 self._string += struct.pack("!B", varID) 231 self._string += struct.pack("!i", len(objID)) + objID 232 self._string += packed 233 return self._sendExact() 234 235 def _readSubscription(self, result): 236 if _DEBUG: 237 print("reading subscription", result.getDebugString()) 238 result.readLength() 239 response = result.read("!B")[0] 240 isVariableSubscription = ((response >= tc.RESPONSE_SUBSCRIBE_INDUCTIONLOOP_VARIABLE and 241 response <= tc.RESPONSE_SUBSCRIBE_BUSSTOP_VARIABLE) or 242 (response >= tc.RESPONSE_SUBSCRIBE_PARKINGAREA_VARIABLE and 243 response <= tc.RESPONSE_SUBSCRIBE_OVERHEADWIRE_VARIABLE)) 244 objectID = result.readString() 245 contextDomain = 0 if isVariableSubscription else result.read("!B")[0] 246 numVars = result.read("!B")[0] 247 if isVariableSubscription: 248 while numVars > 0: 249 varID, status = result.read("!BB") 250 if status: 251 print("Error!", result.readTypedString()) 252 elif response in self._subscriptionMapping: 253 self._subscriptionMapping[response].add(objectID, varID, result) 254 else: 255 raise FatalTraCIError( 256 "Cannot handle subscription response %02x for %s." % (response, objectID)) 257 numVars -= 1 258 else: 259 objectNo = result.read("!i")[0] 260 subsMap = self._subscriptionMapping[response] 261 subsMap.addContext(objectID) 262 for _ in range(objectNo): 263 oid = result.readString() 264 if numVars == 0: 265 subsMap.addContext(objectID, oid) 266 for __ in range(numVars): 267 varID, status = result.read("!BB") 268 if status: 269 print("Error!", result.readTypedString()) 270 elif contextDomain in self._subscriptionMapping: 271 subsMap.addContext(objectID, oid, varID, 272 self._subscriptionMapping[contextDomain].parse(varID, result)) 273 else: 274 raise FatalTraCIError( 275 "Cannot handle subscription response %02x for %s." % (response, objectID)) 276 return objectID, response 277 278 def _subscribe(self, cmdID, begin, end, objID, varIDs, parameters): 279 format = "u" 280 args = [len(varIDs)] 281 for v in varIDs: 282 format += "u" 283 args.append(v) 284 if parameters is not None and v in parameters: 285 if isinstance(parameters[v], tuple): 286 format += parameters[v][0] 287 for a in parameters[v][1:]: 288 args.append(a) 289 elif isinstance(parameters[v], int): 290 format += "i" 291 args.append(parameters[v]) 292 elif isinstance(parameters[v], float): 293 format += "d" 294 args.append(parameters[v]) 295 else: 296 format += "s" 297 args.append(parameters[v]) 298 result = self._sendCmd(cmdID, (begin, end), objID, format, *args) 299 if varIDs: 300 objectID, response = self._readSubscription(result) 301 if response - cmdID != 16 or objectID != objID: 302 raise FatalTraCIError("Received answer %02x,%s for subscription command %02x,%s." % ( 303 response, objectID, cmdID, objID)) 304 305 def _getSubscriptionResults(self, cmdID): 306 return self._subscriptionMapping[cmdID] 307 308 def _subscribeContext(self, cmdID, begin, end, objID, domain, dist, varIDs, parameters=None): 309 result = self._sendCmd(cmdID, (begin, end), objID, "uDu" + (len(varIDs) * "u"), 310 domain, dist, len(varIDs), *varIDs) 311 if varIDs: 312 objectID, response = self._readSubscription(result) 313 if response - cmdID != 16 or objectID != objID: 314 raise FatalTraCIError("Received answer %02x,%s for context subscription command %02x,%s." % ( 315 response, objectID, cmdID, objID)) 316 317 def _addSubscriptionFilter(self, filterType, params=None): 318 if filterType in (tc.FILTER_TYPE_NONE, tc.FILTER_TYPE_NOOPPOSITE, 319 tc.FILTER_TYPE_LEAD_FOLLOW): 320 # filter without parameter 321 assert params is None 322 self._sendCmd(tc.CMD_ADD_SUBSCRIPTION_FILTER, None, None, "u", filterType) 323 elif filterType in (tc.FILTER_TYPE_DOWNSTREAM_DIST, tc.FILTER_TYPE_UPSTREAM_DIST, 324 tc.FILTER_TYPE_TURN, tc.FILTER_TYPE_FIELD_OF_VISION, 325 tc.FILTER_TYPE_LATERAL_DIST): 326 # filter with float parameter 327 self._sendCmd(tc.CMD_ADD_SUBSCRIPTION_FILTER, None, None, "ud", filterType, params) 328 elif filterType in (tc.FILTER_TYPE_VCLASS, tc.FILTER_TYPE_VTYPE): 329 # filter with list(string) parameter 330 self._sendCmd(tc.CMD_ADD_SUBSCRIPTION_FILTER, None, None, "ul", filterType, params) 331 elif filterType == tc.FILTER_TYPE_LANES: 332 # filter with list(byte) parameter 333 # check uniqueness of given lanes in list 334 lanes = set() 335 for i in params: 336 lane = int(i) 337 if lane < 0: 338 lane += 256 339 lanes.add(lane) 340 if len(lanes) < len(list(params)): 341 warnings.warn("Ignoring duplicate lane specification for subscription filter.") 342 self._sendCmd(tc.CMD_ADD_SUBSCRIPTION_FILTER, None, None, 343 (len(lanes) + 2) * "u", filterType, len(lanes), *lanes) 344 345 def hasGUI(self): 346 try: 347 self.gui.getIDList() 348 return True 349 except TraCIException: 350 return False 351 352 def load(self, args): 353 """ 354 Load a simulation from the given arguments. 355 """ 356 if self._traceFile: 357 self._traceFile.write("traci.load(%s)\n" % repr(args)) 358 self._sendCmd(tc.CMD_LOAD, None, None, "l", args) 359 360 def simulationStep(self, step=0.): 361 """ 362 Make a simulation step and simulate up to the given second in sim time. 363 If the given value is 0 or absent, exactly one step is performed. 364 Values smaller than or equal to the current sim time result in no action. 365 """ 366 if self._traceFile: 367 args = "" if step == 0 else str(step) 368 self._traceFile.write("traci.simulationStep(%s)\n" % args) 369 if type(step) is int and step >= 1000: 370 warnings.warn("API change now handles step as floating point seconds", stacklevel=2) 371 result = self._sendCmd(tc.CMD_SIMSTEP, None, None, "D", step) 372 for subscriptionResults in self._subscriptionMapping.values(): 373 subscriptionResults.reset() 374 numSubs = result.readInt() 375 responses = [] 376 while numSubs > 0: 377 responses.append(self._readSubscription(result)) 378 numSubs -= 1 379 self.manageStepListeners(step) 380 return responses 381 382 def getVersion(self): 383 command = tc.CMD_GETVERSION 384 result = self._sendCmd(command, None, None) 385 result.readLength() 386 response = result.read("!B")[0] 387 if response != command: 388 raise FatalTraCIError("Received answer %s for command %s." % (response, command)) 389 return result.readInt(), result.readString() 390 391 def setOrder(self, order): 392 self._sendCmd(tc.CMD_SETORDER, None, None, "I", order) 393 394 def close(self, wait=True): 395 StepManager.close(self, True) 396 for listenerID in list(self._stepListeners.keys()): 397 self.removeStepListener(listenerID) 398 if self._socket is not None: 399 self._sendCmd(tc.CMD_CLOSE, None, None) 400 self._socket.close() 401 self._socket = None 402 if wait and self._process is not None: 403 self._process.wait() 404 self.simulation._setConnection(None) 405 if self._label is not None: 406 if _connections.get("") == self: 407 del _connections[""] 408 del _connections[self._label]
Contains the socket, the composed message string together with a list of TraCI commands which are inside.
Connection(host, port, process, traceFile, traceGetters, label=None)
73 def __init__(self, host, port, process, traceFile, traceGetters, label=None): 74 StepManager.__init__(self) 75 if label in _connections: 76 raise TraCIException("Connection '%s' is already active." % label) 77 if sys.platform.startswith('java'): 78 # working around jython 2.7.0 bug #2273 79 self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_TCP) 80 else: 81 self._socket = socket.socket() 82 self._socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) 83 try: 84 self._socket.connect((host, port)) 85 except socket.error: 86 self._socket.close() 87 raise 88 self._process = process 89 self._string = bytes() 90 self._queue = [] 91 self._subscriptionMapping = {} 92 self._lock = threading.Lock() 93 if traceFile is not None: 94 self.startTracing(traceFile, traceGetters, DOMAINS) 95 for domain in DOMAINS: 96 domain._register(self, self._subscriptionMapping) 97 self._label = label 98 if _connectHook is not None: 99 _connectHook(self) 100 if label is not None: 101 _connections[label] = self
def
load(self, args):
352 def load(self, args): 353 """ 354 Load a simulation from the given arguments. 355 """ 356 if self._traceFile: 357 self._traceFile.write("traci.load(%s)\n" % repr(args)) 358 self._sendCmd(tc.CMD_LOAD, None, None, "l", args)
Load a simulation from the given arguments.
def
simulationStep(self, step=0.0):
360 def simulationStep(self, step=0.): 361 """ 362 Make a simulation step and simulate up to the given second in sim time. 363 If the given value is 0 or absent, exactly one step is performed. 364 Values smaller than or equal to the current sim time result in no action. 365 """ 366 if self._traceFile: 367 args = "" if step == 0 else str(step) 368 self._traceFile.write("traci.simulationStep(%s)\n" % args) 369 if type(step) is int and step >= 1000: 370 warnings.warn("API change now handles step as floating point seconds", stacklevel=2) 371 result = self._sendCmd(tc.CMD_SIMSTEP, None, None, "D", step) 372 for subscriptionResults in self._subscriptionMapping.values(): 373 subscriptionResults.reset() 374 numSubs = result.readInt() 375 responses = [] 376 while numSubs > 0: 377 responses.append(self._readSubscription(result)) 378 numSubs -= 1 379 self.manageStepListeners(step) 380 return responses
Make a simulation step and simulate up to the given second in sim time. If the given value is 0 or absent, exactly one step is performed. Values smaller than or equal to the current sim time result in no action.
def
getVersion(self):
382 def getVersion(self): 383 command = tc.CMD_GETVERSION 384 result = self._sendCmd(command, None, None) 385 result.readLength() 386 response = result.read("!B")[0] 387 if response != command: 388 raise FatalTraCIError("Received answer %s for command %s." % (response, command)) 389 return result.readInt(), result.readString()
def
close(self, wait=True):
394 def close(self, wait=True): 395 StepManager.close(self, True) 396 for listenerID in list(self._stepListeners.keys()): 397 self.removeStepListener(listenerID) 398 if self._socket is not None: 399 self._sendCmd(tc.CMD_CLOSE, None, None) 400 self._socket.close() 401 self._socket = None 402 if wait and self._process is not None: 403 self._process.wait() 404 self.simulation._setConnection(None) 405 if self._label is not None: 406 if _connections.get("") == self: 407 del _connections[""] 408 del _connections[self._label]