def make_routes(self, scenario, initial_config): """Generates .rou.xml files using net files and netconvert. This file specifies the sumo-specific properties of vehicles with similar types, and well as the starting positions of vehicles. The starting positions, however, may be modified in real-time (e.g. during an environment reset). Parameters ---------- scenario: Scenario type scenario class calling this method. This contains information on the properties and initial states of vehicles in the network. initial_config: InitialConfig type see flow/core/params.py """ vehicles = scenario.vehicles routes = makexml("routes", "http://sumo.dlr.de/xsd/routes_file.xsd") # add the types of vehicles to the xml file for vtype, type_params in vehicles.types: type_params_str = { key: str(type_params[key]) for key in type_params } routes.append(E("vType", id=vtype, **type_params_str)) self.vehicle_ids = vehicles.get_ids() if initial_config.shuffle: random.shuffle(self.vehicle_ids) # add the initial positions of vehicles to the xml file positions = initial_config.positions lanes = initial_config.lanes for i, veh_id in enumerate(self.vehicle_ids): veh_type = vehicles.get_state(veh_id, "type") edge, pos = positions[i] lane = lanes[i] type_depart_speed = vehicles.get_initial_speed(veh_id) routes.append( self._vehicle(veh_type, "route" + edge, depart="0", id=veh_id, color="1,1,1", departSpeed=str(type_depart_speed), departPos=str(pos), departLane=str(lane))) # add the in-flows from various edges to the xml file if self.net_params.in_flows is not None: total_inflows = self.net_params.in_flows.get() for inflow in total_inflows: for key in inflow: if not isinstance(inflow[key], str): inflow[key] = repr(inflow[key]) routes.append(self._flow(**inflow)) printxml(routes, self.cfg_path + self.roufn)
def make_routes(self): """Generate .rou.xml files using net files and netconvert. This file specifies the sumo-specific properties of vehicles with similar types, and well as the inflows of vehicles. """ vehicles = self.network.vehicles routes = makexml('routes', 'http://sumo.dlr.de/xsd/routes_file.xsd') # add the types of vehicles to the xml file for params in vehicles.types: type_params_str = { key: str(params['type_params'][key]) for key in params['type_params'] } routes.append(E('vType', id=params['veh_id'], **type_params_str)) # add the inflows from various edges to the xml file if self.network.net_params.inflows is not None: total_inflows = self.network.net_params.inflows.get() for inflow in total_inflows: for key in inflow: if not isinstance(inflow[key], str): inflow[key] = repr(inflow[key]) if key == 'edge': inflow['route'] = 'route{}'.format(inflow['edge']) del inflow['edge'] routes.append(_flow(**inflow)) printxml(routes, self.cfg_path + self.roufn)
def make_routes(self, scenario, initial_config): vehicles = scenario.vehicles type_list = vehicles.types if vehicles.num_vehicles > 0: routes = makexml("routes", "http://sumo.dlr.de/xsd/routes_file.xsd") # add the types of vehicles to the xml file for veh_type in vehicles.types: routes.append(E("vType", id=veh_type, minGap="0", accel="100", decel="100")) self.vehicle_ids = vehicles.get_ids() if initial_config.shuffle: random.shuffle(self.vehicle_ids) # add the initial positions of vehicles to the xml file positions = initial_config.positions lanes = initial_config.lanes for i, id in enumerate(self.vehicle_ids): veh_type = vehicles.get_state(id, "type") edge, pos = positions[i] lane = lanes[i] indx_type = [i for i in range(len(type_list)) if type_list[i] == veh_type][0] type_depart_speed = vehicles.get_initial_speed(id) routes.append(self._vehicle( veh_type, "route" + edge, depart="0", id=id, color="1,0.0,0.0", departSpeed=str(type_depart_speed), departPos=str(pos), departLane=str(lane))) printxml(routes, self.cfg_path + self.roufn)
def GenerateXMLs(filepath="/home/mesto/flow/MyTests/flows.xml"): flows = makexml('routes', 'http://sumo.dlr.de/xsd/routes_file.xsd') flows.append( CreateVTypeElem('human', '2.6', '4.5', '0.5', '70', '2.5', '0.0')) flows.append( CreateFlowElem('121304377#0', 'flow_0', '1', '900', '2156', 'human', '28.3')) flows.append( CreateFlowElem('121304377#0', 'flow_1', '900', '1200', '2100', 'human', '29.5')) flows.append( CreateFlowElem('121304377#0', 'flow_2', '1200', '1500', '2016', 'human', '28.3')) flows.append( CreateFlowElem('121304377#0', 'flow_3', '1500', '1800', '2100', 'human', '27.1')) flows.append( CreateFlowElem('121304377#0', 'flow_4', '1800', '2100', '2212', 'human', '21.5')) flows.append( CreateFlowElem('121304377#0', 'flow_5', '2100', '2400', '2156', 'human', '8.3')) flows.append( CreateFlowElem('121304377#0', 'flow_6', '2400', '2700', '3360', 'human', '14.1')) flows.append( CreateFlowElem('121304377#0', 'flow_7', '2700', '3000', '2548', 'human', '16.9')) flows.append( CreateFlowElem('121304377#0', 'flow_8', '3000', '3300', '2324', 'human', '8.3')) flows.append( CreateFlowElem('121304377#0', 'flow_9', '3300', '3600', '2716', 'human', '9.1')) flows.append( CreateFlowElem('121304377#0', 'flow_10', '3600', '3900', '2548', 'human', '10.2')) flows.append( CreateFlowElem('121304377#0', 'flow_11', '3900', '4200', '2716', 'human', '9.3')) printxml(flows, filepath)
def make_routes(self, scenario, initial_config): type_list = scenario.vehicles.types num_cars = scenario.vehicles.num_vehicles if num_cars > 0: routes = makexml("routes", "http://sumo.dlr.de/xsd/routes_file.xsd") for veh_type in scenario.vehicles.types: routes.append(E("vType", id=veh_type, minGap="0")) vehicle_ids = scenario.vehicles.get_ids() if initial_config.shuffle: random.shuffle(vehicle_ids) positions = initial_config.positions ring_positions = positions[:scenario.vehicles.num_vehicles - scenario.num_merge_vehicles] merge_positions = positions[scenario.vehicles.num_vehicles - scenario.num_merge_vehicles:] i_merge = 0 i_ring = 0 for i, id in enumerate(vehicle_ids): if "merge" in scenario.vehicles.get_state(id, "type"): route, pos = merge_positions[i_merge] i_merge += 1 else: route, pos = ring_positions[i_ring] i_ring += 1 veh_type = scenario.vehicles.get_state(id, "type") type_depart_speed = scenario.vehicles.get_initial_speed(id) routes.append( self._vehicle(veh_type, "route" + route, depart="0", departSpeed=str(type_depart_speed), departPos=str(pos), id=id, color="1,0.0,0.0") ) printxml(routes, self.cfg_path + self.roufn)
def generate_cfg(self, net_params): """Generates .sumo.cfg files using net files and netconvert. This includes files such as the routes vehicles can traverse and the view settings of the gui (whether the gui is used or not). The background of the gui is set here to be grey, with RGB values: (100, 100, 100). Parameters ---------- net_params: NetParams type see flow/core/params.py """ start_time = 0 end_time = None self.roufn = "%s.rou.xml" % self.name addfn = "%s.add.xml" % self.name cfgfn = "%s.sumo.cfg" % self.name guifn = "%s.gui.cfg" % self.name # specify routes vehicles can take self.rts = self.specify_routes(net_params) add = makexml("additional", "http://sumo.dlr.de/xsd/additional_file.xsd") for (edge, route) in self.rts.items(): add.append(E("route", id="route%s" % edge, edges=" ".join(route))) printxml(add, self.cfg_path + addfn) gui = E("viewsettings") gui.append(E("scheme", name="real world")) gui.append( E("background", backgroundColor="100,100,100", showGrid="0", gridXSize="100.00", gridYSize="100.00")) printxml(gui, self.cfg_path + guifn) cfg = makexml("configuration", "http://sumo.dlr.de/xsd/sumoConfiguration.xsd") logging.debug(self.netfn) cfg.append( self._inputs(self.name, net=self.netfn, add=addfn, rou=self.roufn, gui=guifn)) t = E("time") t.append(E("begin", value=repr(start_time))) if end_time: t.append(E("end", value=repr(end_time))) cfg.append(t) printxml(cfg, self.cfg_path + cfgfn) return cfgfn
def generate_cfg(self, net_params): """ Generates .sumo.cfg files using net files and netconvert. Requires: num_cars: Number of cars to seed the simulation with max_speed: max speed of cars OR type_list: List of types of cars to seed the simulation with start_time: time to start the simulation end_time: time to end the simulation """ start_time = 0 end_time = None self.roufn = "%s.rou.xml" % self.name addfn = "%s.add.xml" % self.name cfgfn = "%s.sumo.cfg" % self.name guifn = "%s.gui.cfg" % self.name # specify routes vehicles can take self.rts = self.specify_routes(net_params) # TODO: add functionality for multiple routes (such as Braess) add = makexml("additional", "http://sumo.dlr.de/xsd/additional_file.xsd") for (edge, route) in self.rts.items(): add.append(E("route", id="route%s" % edge, edges=" ".join(route))) # specify (optional) rerouting actions rerouting = self.specify_rerouters(net_params) if rerouting is not None: for rerouting_params in rerouting: add.append(self._rerouter(rerouting_params["name"], rerouting_params["from"], rerouting_params["route"])) printxml(add, self.cfg_path + addfn) gui = E("viewsettings") gui.append(E("scheme", name="real world")) printxml(gui, self.cfg_path +guifn) cfg = makexml("configuration", "http://sumo.dlr.de/xsd/sumoConfiguration.xsd") logging.debug(self.netfn) cfg.append(self._inputs(self.name, net=self.netfn, add=addfn, rou=self.roufn, gui=guifn)) t = E("time") t.append(E("begin", value=repr(start_time))) if end_time: t.append(E("end", value=repr(end_time))) cfg.append(t) printxml(cfg, self.cfg_path + cfgfn) return cfgfn
def generate_net(self, net_params, traffic_lights, nodes, edges, types=None, connections=None): """Generate Net files for the transportation network. Returns ------- edges : dict <dict> Key = name of the edge Elements = length, lanes, speed connection_data : dict < dict < list < (edge, pos) > > > Key = name of the arriving edge Key = lane index Element = list of edge/lane pairs that a vehicle can traverse from the arriving edge/lane pairs """ # add traffic lights to the nodes tl_ids = list(traffic_lights.get_properties().keys()) for n_id in tl_ids: indx = next(i for i, nd in enumerate(nodes) if nd['id'] == n_id) nodes[indx]['type'] = 'traffic_light' node_id_map = {} # for nodes that have traffic lights that haven't been added for nid, node in enumerate(nodes): if node['id'] not in tl_ids \ and node.get('type', None) == 'traffic_light': traffic_lights.add(node['id']) node_id_map[node['id']] = str(nid) node['id'] = str(nid) # modify the x and y values to be strings node['x'] = str(node['x']) node['y'] = str(node['y']) # xml file for nodes; contains nodes for the boundary points with # respect to the x and y axes scenario = etree.Element('scenario', {'xmlns': 'opentrafficmodels'}) network = etree.SubElement(scenario, 'network') for node_attributes in nodes: if 'radius' in node_attributes: del node_attributes['radius'] network.append(E('node', **node_attributes)) # modify the length, shape, numLanes, and speed values # xml file for edges links = etree.SubElement(network, 'links') edge_dict = {} for eid, edge in enumerate(edges): edge['length'] = str(edge['length']) if 'shape' in edge: if not isinstance(edge['shape'], str): edge['shape'] = ' '.join('%.2f,%.2f' % (x, y) for x, y in edge['shape']) if 'numLanes' in edge: edge['numLanes'] = str(edge['numLanes']) else: edge['numLanes'] = str(1) if 'speed' in edge: edge['speed'] = str(edge['speed']) edge_attrib = { 'end_node_id': node_id_map[edge['to']], 'start_node_id': node_id_map[edge['from']], 'lanes': edge['numLanes'], 'id': str(eid), 'roadparams': '1', 'length': edge['length'] } edge_dict[edge['id']] = edge_attrib link = etree.SubElement(links, 'link', attrib=edge_attrib) if 'shape' in edge: points = etree.SubElement(link, 'points') for x, y in edge['shape']: points.append(E('point'), attrib={'x': x, 'y': y}) roadparams = etree.SubElement(network, 'roadparams') roadparams.append( E('roadparam', attrib={ 'id': '1', 'capacity': '1000', 'jam_density': '200', 'speed': '20' })) printxml(scenario, self.net_path + self.nodfn) # Gabriel put xml dummy here (TODO FIX THIS LATER) self.cfg = self.net_path + "line.xml" # self.nodfn return edge_dict
def generate_cfg(self, net_params, traffic_lights, routes): """Generate .sumo.cfg files using net files and netconvert. This method is responsible for creating the following config files: - *.add.xml: This file contains the sumo-specific properties of vehicles with similar types, and properties of the traffic lights. - *.rou.xml: This file contains the routes vehicles can traverse, either from a specific starting edge, or by vehicle name, and well as the inflows of vehicles. - *.gui.cfg: This file contains the view settings of the gui (whether the gui is used or not). The background of the gui is set here to be grey, with RGB values: (100, 100, 100). - *.sumo.cfg: This is the file that is used by the simulator to identify the location of the various network, vehicle, and traffic light properties that are used when instantiating the simulation. Parameters ---------- net_params : flow.core.params.NetParams see flow/core/params.py traffic_lights : flow.core.params.TrafficLightParams traffic light information, used to determine which nodes are treated as traffic lights routes : dict Key = name of the starting edge Element = list of edges a vehicle starting from this edge must traverse. """ # this is the data that we will pass to the *.add.xml file add = makexml('additional', 'http://sumo.dlr.de/xsd/additional_file.xsd') # add the types of vehicles to the xml file for params in self.network.vehicles.types: type_params_str = { key: str(params['type_params'][key]) for key in params['type_params'] } add.append(E('vType', id=params['veh_id'], **type_params_str)) # add (optionally) the traffic light properties to the .add.xml file num_traffic_lights = len(list(traffic_lights.get_properties().keys())) if num_traffic_lights > 0: if traffic_lights.baseline: tl_params = traffic_lights.actuated_default() tl_type = str(tl_params['tl_type']) program_id = str(tl_params['program_id']) phases = tl_params['phases'] max_gap = str(tl_params['max_gap']) detector_gap = str(tl_params['detector_gap']) show_detector = tl_params['show_detectors'] detectors = {'key': 'detector-gap', 'value': detector_gap} gap = {'key': 'max-gap', 'value': max_gap} if show_detector: show_detector = {'key': 'show-detectors', 'value': 'true'} else: show_detector = {'key': 'show-detectors', 'value': 'false'} nodes = self._inner_nodes # nodes where there's traffic lights tll = [] for node in nodes: tll.append({ 'id': node['id'], 'type': tl_type, 'programID': program_id }) for elem in tll: e = E('tlLogic', **elem) e.append(E('param', **show_detector)) e.append(E('param', **gap)) e.append(E('param', **detectors)) for phase in phases: e.append(E('phase', **phase)) add.append(e) else: tl_properties = traffic_lights.get_properties() for node in tl_properties.values(): # At this point, we assume that traffic lights are properly # formed. If there are no phases for a static traffic # light, ignore and use default if node['type'] == 'static' and not node.get('phases'): continue elem = { 'id': str(node['id']), 'type': str(node['type']), 'programID': str(node['programID']) } if node.get('offset'): elem['offset'] = str(node.get('offset')) e = E('tlLogic', **elem) for key, value in node.items(): if key == 'phases': for phase in node.get('phases'): e.append(E('phase', **phase)) else: e.append( E('param', **{ 'key': key, 'value': str(value) })) add.append(e) printxml(add, self.cfg_path + self.addfn) # this is the data that we will pass to the *.gui.cfg file gui = E('viewsettings') gui.append(E('scheme', name='real world')) gui.append( E('background', backgroundColor='100,100,100', showGrid='0', gridXSize='100.00', gridYSize='100.00')) printxml(gui, self.cfg_path + self.guifn) # this is the data that we will pass to the *.rou.xml file routes_data = makexml('routes', 'http://sumo.dlr.de/xsd/routes_file.xsd') # add the routes to the .add.xml file for route_id in routes.keys(): # in this case, we only have one route, convert into into a # list of routes with one element if isinstance(routes[route_id][0], str): routes[route_id] = [(routes[route_id], 1)] # add each route incrementally, and add a second term to denote # the route number of the given route at the given edge for i in range(len(routes[route_id])): r, _ = routes[route_id][i] routes_data.append( E('route', id='route{}_{}'.format(route_id, i), edges=' '.join(r))) # add the inflows from various edges to the xml file if self.network.net_params.inflows is not None: total_inflows = self.network.net_params.inflows.get() for inflow in total_inflows: # do not want to affect the original values sumo_inflow = deepcopy(inflow) # convert any non-string element in the inflow dict to a string for key in sumo_inflow: if not isinstance(sumo_inflow[key], str): sumo_inflow[key] = repr(sumo_inflow[key]) # distribute the inflow rates across all routes from a given # edge on the basis of the provided fractions for each route edge = sumo_inflow['edge'] del sumo_inflow['edge'] for i, (_, frac) in enumerate(routes[edge]): sumo_inflow['name'] += str(i) sumo_inflow['route'] = 'route{}_{}'.format(edge, i) for key in ['vehsPerHour', 'probability', 'period']: if key in sumo_inflow: sumo_inflow[key] = str(float(inflow[key]) * frac) if 'number' in sumo_inflow: sumo_inflow['number'] = str( int(float(inflow['number']) * frac)) routes_data.append(_flow(**sumo_inflow)) printxml(routes_data, self.cfg_path + self.roufn) # this is the data that we will pass to the *.sumo.cfg file cfg = makexml('configuration', 'http://sumo.dlr.de/xsd/sumoConfiguration.xsd') cfg.append( _inputs(net=self.netfn, add=self.addfn, rou=self.roufn, gui=self.guifn)) t = E('time') t.append(E('begin', value=repr(0))) cfg.append(t) printxml(cfg, self.cfg_path + self.sumfn) return self.sumfn
def generate_net(self, net_params, traffic_lights, nodes, edges, types=None, connections=None): """Generate Net files for the transportation network. Creates different network configuration files for: * nodes: x,y position of points which are connected together to form links. The nodes may also be fitted with traffic lights, or can be treated as priority or zipper merge regions if they combines several lanes or edges together. * edges: directed edges combining nodes together. These constitute the lanes vehicles will be allowed to drive on. * types (optional): parameters used to describe common features amount several edges of similar types. If edges are not defined with common types, this is not needed. * connections (optional): describes how incoming and outgoing edge/lane pairs on a specific node as connected. If none is specified, SUMO handles these connections by default. The above files are then combined to form a .net.xml file describing the shape of the traffic network in a form compatible with SUMO. Parameters ---------- net_params : flow.core.params.NetParams network-specific parameters. Different networks require different net_params; see the separate sub-classes for more information. traffic_lights : flow.core.params.TrafficLightParams traffic light information, used to determine which nodes are treated as traffic lights nodes : list of dict A list of node attributes (a separate dict for each node). Nodes attributes must include: * id {string} -- name of the node * x {float} -- x coordinate of the node * y {float} -- y coordinate of the node edges : list of dict A list of edges attributes (a separate dict for each edge). Edge attributes must include: * id {string} -- name of the edge * from {string} -- name of node the directed edge starts from * to {string} -- name of the node the directed edge ends at In addition, the attributes must contain at least one of the following: * "numLanes" {int} and "speed" {float} -- the number of lanes and speed limit of the edge, respectively * type {string} -- a type identifier for the edge, which can be used if several edges are supposed to possess the same number of lanes, speed limits, etc... types : list of dict A list of type attributes for specific groups of edges. If none are specified, no .typ.xml file is created. connections : list of dict A list of connection attributes. If none are specified, no .con.xml file is created. Returns ------- edges : dict <dict> Key = name of the edge Elements = length, lanes, speed connection_data : dict < dict < list < (edge, pos) > > > Key = name of the arriving edge Key = lane index Element = list of edge/lane pairs that a vehicle can traverse from the arriving edge/lane pairs """ # add traffic lights to the nodes tl_ids = list(traffic_lights.get_properties().keys()) for n_id in tl_ids: indx = next(i for i, nd in enumerate(nodes) if nd['id'] == n_id) nodes[indx]['type'] = 'traffic_light' # for nodes that have traffic lights that haven't been added for node in nodes: if node['id'] not in tl_ids \ and node.get('type', None) == 'traffic_light': traffic_lights.add(node['id']) # modify the x and y values to be strings node['x'] = str(node['x']) node['y'] = str(node['y']) if 'radius' in node: node['radius'] = str(node['radius']) # xml file for nodes; contains nodes for the boundary points with # respect to the x and y axes x = makexml('nodes', 'http://sumo.dlr.de/xsd/nodes_file.xsd') for node_attributes in nodes: x.append(E('node', **node_attributes)) printxml(x, self.net_path + self.nodfn) # modify the length, shape, numLanes, and speed values for edge in edges: edge['length'] = str(edge['length']) if 'priority' in edge: edge['priority'] = str(edge['priority']) if 'shape' in edge: if not isinstance(edge['shape'], str): edge['shape'] = ' '.join('%.2f,%.2f' % (x, y) for x, y in edge['shape']) if 'numLanes' in edge: edge['numLanes'] = str(edge['numLanes']) if 'speed' in edge: edge['speed'] = str(edge['speed']) # xml file for edges x = makexml('edges', 'http://sumo.dlr.de/xsd/edges_file.xsd') for edge_attributes in edges: x.append(E('edge', attrib=edge_attributes)) printxml(x, self.net_path + self.edgfn) # xml file for types: contains the the number of lanes and the speed # limit for the lanes if types is not None: # modify the numLanes and speed values for typ in types: if 'numLanes' in typ: typ['numLanes'] = str(typ['numLanes']) if 'speed' in typ: typ['speed'] = str(typ['speed']) x = makexml('types', 'http://sumo.dlr.de/xsd/types_file.xsd') for type_attributes in types: x.append(E('type', **type_attributes)) printxml(x, self.net_path + self.typfn) # xml for connections: specifies which lanes connect to which in the # edges if connections is not None: # modify the fromLane and toLane values for connection in connections: if 'fromLane' in connection: connection['fromLane'] = str(connection['fromLane']) if 'toLane' in connection: connection['toLane'] = str(connection['toLane']) x = makexml('connections', 'http://sumo.dlr.de/xsd/connections_file.xsd') for connection_attributes in connections: if 'signal_group' in connection_attributes: del connection_attributes['signal_group'] x.append(E('connection', **connection_attributes)) printxml(x, self.net_path + self.confn) # xml file for configuration, which specifies: # - the location of all files of interest for sumo # - output net file # - processing parameters for no internal links and no turnarounds x = makexml('configuration', 'http://sumo.dlr.de/xsd/netconvertConfiguration.xsd') t = E('input') t.append(E('node-files', value=self.nodfn)) t.append(E('edge-files', value=self.edgfn)) if types is not None: t.append(E('type-files', value=self.typfn)) if connections is not None: t.append(E('connection-files', value=self.confn)) x.append(t) t = E('output') t.append(E('output-file', value=self.netfn)) x.append(t) t = E('processing') t.append(E('no-internal-links', value='false')) t.append(E('no-turnarounds', value='true')) x.append(t) printxml(x, self.net_path + self.cfgfn) subprocess.call([ 'netconvert -c ' + self.net_path + self.cfgfn + ' --output-file=' + self.cfg_path + self.netfn + ' --no-internal-links="false"' ], shell=True) # collect data from the generated network configuration file error = None for _ in range(RETRIES_ON_ERROR): try: edges_dict, conn_dict = self._import_edges_from_net(net_params) return edges_dict, conn_dict except Exception as e: print('Error during start: {}'.format(e)) print('Retrying in {} seconds...'.format(WAIT_ON_ERROR)) time.sleep(WAIT_ON_ERROR) raise error
def generate_cfg(self, net_params, traffic_lights, routes): """Generate .sumo.cfg files using net files and netconvert. This includes files such as the routes vehicles can traverse, properties of the traffic lights, and the view settings of the gui (whether the gui is used or not). The background of the gui is set here to be grey, with RGB values: (100, 100, 100). Parameters ---------- net_params : NetParams type see flow/core/params.py traffic_lights : flow.core.traffic_lights.TrafficLights type traffic light information, used to determine which nodes are treated as traffic lights routes : dict Key = name of the starting edge Element = list of edges a vehicle starting from this edge must traverse. """ # specify routes vehicles can take self.rts = routes add = makexml('additional', 'http://sumo.dlr.de/xsd/additional_file.xsd') # add the routes to the .add.xml file for (edge, route) in self.rts.items(): add.append(E('route', id='route%s' % edge, edges=' '.join(route))) # add (optionally) the traffic light properties to the .add.xml file num_traffic_lights = len(list(traffic_lights.get_properties().keys())) if num_traffic_lights > 0: if traffic_lights.baseline: tl_params = traffic_lights.actuated_default() tl_type = str(tl_params['tl_type']) program_id = str(tl_params['program_id']) phases = tl_params['phases'] max_gap = str(tl_params['max_gap']) detector_gap = str(tl_params['detector_gap']) show_detector = tl_params['show_detectors'] detectors = {'key': 'detector-gap', 'value': detector_gap} gap = {'key': 'max-gap', 'value': max_gap} if show_detector: show_detector = {'key': 'show-detectors', 'value': 'true'} else: show_detector = {'key': 'show-detectors', 'value': 'false'} # FIXME(ak): add abstract method nodes = self.specify_tll(net_params) tll = [] for node in nodes: tll.append({ 'id': node['id'], 'type': tl_type, 'programID': program_id }) for elem in tll: e = E('tlLogic', **elem) e.append(E('param', **show_detector)) e.append(E('param', **gap)) e.append(E('param', **detectors)) for phase in phases: e.append(E('phase', **phase)) add.append(e) else: tl_properties = traffic_lights.get_properties() for node in tl_properties.values(): # At this point, we assume that traffic lights are properly # formed. If there are no phases for a static traffic # light, ignore and use default if node['type'] == 'static' and not node.get('phases'): continue elem = { 'id': str(node['id']), 'type': str(node['type']), 'programID': str(node['programID']) } if node.get('offset'): elem['offset'] = str(node.get('offset')) e = E('tlLogic', **elem) for key, value in node.items(): if key == 'phases': for phase in node.get('phases'): e.append(E('phase', **phase)) else: e.append( E('param', **{ 'key': key, 'value': str(value) })) add.append(e) printxml(add, self.cfg_path + self.addfn) gui = E('viewsettings') gui.append(E('scheme', name='real world')) gui.append( E('background', backgroundColor='100,100,100', showGrid='0', gridXSize='100.00', gridYSize='100.00')) printxml(gui, self.cfg_path + self.guifn) cfg = makexml('configuration', 'http://sumo.dlr.de/xsd/sumoConfiguration.xsd') cfg.append( _inputs(net=self.netfn, add=self.addfn, rou=self.roufn, gui=self.guifn)) t = E('time') t.append(E('begin', value=repr(0))) cfg.append(t) printxml(cfg, self.cfg_path + self.sumfn) return self.sumfn
def generate_net(self, net_params, traffic_lights): """Generates Net files for the transportation network. Creates different network configuration files for: * nodes: x,y position of points which are connected together to form links. The nodes may also be fitted with traffic lights, or can be treated as priority or zipper merge regions if they combines several lanes or edges together. * edges: directed edges combining nodes together. These constitute the lanes vehicles will be allowed to drive on. * types (optional): parameters used to describe common features amount several edges of similar types. If edges are not defined with common types, this is not needed. * connections (optional): describes how incoming and outgoing edge/lane pairs on a specific node as connected. If none is specified, SUMO handles these connections by default. The above files are then combined to form a .net.xml file describing the shape of the traffic network in a form compatible with SUMO. Parameters ---------- net_params : flow.core.params.NetParams type network-specific parameters. Different networks require different net_params; see the separate sub-classes for more information. traffic_lights : flow.core.traffic_lights.TrafficLights type traffic light information, used to determine which nodes are treated as traffic lights Returns ------- edges : dict <dict> Key = name of the edge Elements = length, lanes, speed connection_data : dict < dict < list<tup> > > Key = name of the arriving edge Key = lane index Element = list of edge/lane pairs that a vehicle can traverse from the arriving edge/lane pairs """ nodfn = "%s.nod.xml" % self.name edgfn = "%s.edg.xml" % self.name typfn = "%s.typ.xml" % self.name cfgfn = "%s.netccfg" % self.name netfn = "%s.net.xml" % self.name confn = "%s.con.xml" % self.name # specify the attributes of the nodes nodes = self.specify_nodes(net_params) # add traffic lights to the nodes for n_id in traffic_lights.get_ids(): indx = next(i for i, nd in enumerate(nodes) if nd["id"] == n_id) nodes[indx]["type"] = "traffic_light" # xml file for nodes; contains nodes for the boundary points with # respect to the x and y axes x = makexml("nodes", "http://sumo.dlr.de/xsd/nodes_file.xsd") for node_attributes in nodes: x.append(E("node", **node_attributes)) printxml(x, self.net_path + nodfn) # collect the attributes of each edge edges = self.specify_edges(net_params) # xml file for edges x = makexml("edges", "http://sumo.dlr.de/xsd/edges_file.xsd") for edge_attributes in edges: x.append(E("edge", attrib=edge_attributes)) printxml(x, self.net_path + edgfn) # specify the types attributes (default is None) types = self.specify_types(net_params) # xml file for types: contains the the number of lanes and the speed # limit for the lanes if types is not None: x = makexml("types", "http://sumo.dlr.de/xsd/types_file.xsd") for type_attributes in types: x.append(E("type", **type_attributes)) printxml(x, self.net_path + typfn) # specify the connection attributes (default is None) connections = self.specify_connections(net_params) # xml for connections: specifies which lanes connect to which in the # edges if connections is not None: x = makexml("connections", "http://sumo.dlr.de/xsd/connections_file.xsd") for connection_attributes in connections: x.append(E("connection", **connection_attributes)) printxml(x, self.net_path + confn) # check whether the user requested no-internal-links (default="true") if net_params.no_internal_links: no_internal_links = "true" else: no_internal_links = "false" # xml file for configuration, which specifies: # - the location of all files of interest for sumo # - output net file # - processing parameters for no internal links and no turnarounds x = makexml("configuration", "http://sumo.dlr.de/xsd/netconvertConfiguration.xsd") t = E("input") t.append(E("node-files", value=nodfn)) t.append(E("edge-files", value=edgfn)) if types is not None: t.append(E("type-files", value=typfn)) if connections is not None: t.append(E("connection-files", value=confn)) x.append(t) t = E("output") t.append(E("output-file", value=netfn)) x.append(t) t = E("processing") t.append(E("no-internal-links", value="%s" % no_internal_links)) t.append(E("no-turnarounds", value="true")) x.append(t) printxml(x, self.net_path + cfgfn) subprocess.call([ "netconvert -c " + self.net_path + cfgfn + " --output-file=" + self.cfg_path + netfn + ' --no-internal-links="%s"' % no_internal_links ], shell=True) # location of the .net.xml file self.netfn = netfn # collect data from the generated network configuration file error = None for _ in range(RETRIES_ON_ERROR): try: edges_dict, conn_dict = self._import_edges_from_net() return edges_dict, conn_dict except Exception as error: print("Error during start: {}".format(traceback.format_exc())) print("Retrying in {} seconds...".format(WAIT_ON_ERROR)) time.sleep(WAIT_ON_ERROR) raise error
def generate_cfg(self, net_params, traffic_lights): """Generates .sumo.cfg files using net files and netconvert. This includes files such as the routes vehicles can traverse, properties of the traffic lights, and the view settings of the gui (whether the gui is used or not). The background of the gui is set here to be grey, with RGB values: (100, 100, 100). Parameters ---------- net_params: NetParams type see flow/core/params.py traffic_lights : flow.core.traffic_lights.TrafficLights type traffic light information, used to determine which nodes are treated as traffic lights """ start_time = 0 end_time = None self.roufn = "%s.rou.xml" % self.name addfn = "%s.add.xml" % self.name cfgfn = "%s.sumo.cfg" % self.name guifn = "%s.gui.cfg" % self.name # specify routes vehicles can take self.rts = self.specify_routes(net_params) add = makexml("additional", "http://sumo.dlr.de/xsd/additional_file.xsd") # add the routes to the .add.xml file for (edge, route) in self.rts.items(): add.append(E("route", id="route%s" % edge, edges=" ".join(route))) # add (optionally) the traffic light properties to the .add.xml file if traffic_lights.num_traffic_lights > 0: if traffic_lights.baseline: tl_type = str(traffic_lights["tl_type"]) program_id = str(traffic_lights["program_id"]) phases = traffic_lights["phases"] max_gap = str(traffic_lights["max_gap"]) detector_gap = str(traffic_lights["detector_gap"]) show_detector = traffic_lights["show_detectors"] detectors = {"key": "detector-gap", "value": detector_gap} gap = {"key": "max-gap", "value": max_gap} if show_detector: show_detector = {"key": "show-detectors", "value": "true"} else: show_detector = {"key": "show-detectors", "value": "false"} # FIXME(ak): add abstract method nodes = self.specify_tll(net_params) tll = [] for node in nodes: tll.append({ "id": node['id'], "type": tl_type, "programID": program_id }) for elem in tll: e = E("tlLogic", **elem) e.append(E("param", **show_detector)) e.append(E("param", **gap)) e.append(E("param", **detectors)) for phase in phases: e.append(E("phase", **phase)) add.append(e) else: tl_properties = traffic_lights.get_properties() for node in tl_properties.values(): # at this point, the generator assumes that traffic lights # are properly formed. If there are no phases for a static # traffic light, ignore and use default if node["type"] == "static" and not node.get("phases"): continue elem = { "id": str(node["id"]), "type": str(node["type"]), "programID": str(node["programID"]) } if node.get("offset"): elem["offset"] = str(node.get("offset")) e = E("tlLogic", **elem) for key, value in node.items(): if key == "phases": for phase in node.get("phases"): e.append(E("phase", **phase)) else: e.append( E("param", **{ "key": key, "value": str(value) })) add.append(e) printxml(add, self.cfg_path + addfn) gui = E("viewsettings") gui.append(E("scheme", name="real world")) gui.append( E("background", backgroundColor="100,100,100", showGrid="0", gridXSize="100.00", gridYSize="100.00")) printxml(gui, self.cfg_path + guifn) cfg = makexml("configuration", "http://sumo.dlr.de/xsd/sumoConfiguration.xsd") logging.debug(self.netfn) cfg.append( self._inputs(self.name, net=self.netfn, add=addfn, rou=self.roufn, gui=guifn)) t = E("time") t.append(E("begin", value=repr(start_time))) if end_time: t.append(E("end", value=repr(end_time))) cfg.append(t) printxml(cfg, self.cfg_path + cfgfn) return cfgfn
from lxml import etree E = etree #.Element import xml.etree.ElementTree as ET from flow.core.util import makexml, printxml, ensure_dir file = "/home/mesto/flow/MyTests/I24-62.add.xml" tree = E.parse(file) if __name__ == "__main__": root = tree.getroot() #tree.append(file) add = makexml('additional', 'http://sumo.dlr.de/xsd/additional_file.xsd') for child in root: add.append(child) #add.append(E('flow', id = 'Test')) printxml(add, "/home/mesto/flow/MyTests/test.xml")
def make_routes(self, scenario, positions, lanes, shuffle): """Generates .rou.xml files using net files and netconvert. This file specifies the sumo-specific properties of vehicles with similar types, and well as the starting positions of vehicles. The starting positions, however, may be modified in real-time (e.g. during an environment reset). Parameters ---------- scenario : Scenario type scenario class calling this method. This contains information on the properties and initial states of vehicles in the network. positions : list of tuple (float, float) list of start positions [(edge0, pos0), (edge1, pos1), ...] lanes : list of float list of start lanes shuffle : bool specifies whether the vehicle IDs should be shuffled before the vehicles are assigned starting positions """ vehicles = scenario.vehicles routes = makexml("routes", "http://sumo.dlr.de/xsd/routes_file.xsd") # add the types of vehicles to the xml file for params in vehicles.types: type_params_str = { key: str(params["type_params"][key]) for key in params["type_params"] } routes.append(E("vType", id=params["veh_id"], **type_params_str)) self.vehicle_ids = vehicles.get_ids() if shuffle: random.shuffle(self.vehicle_ids) # add the initial positions of vehicles to the xml file for i, veh_id in enumerate(self.vehicle_ids): veh_type = vehicles.get_state(veh_id, "type") edge, pos = positions[i] lane = lanes[i] type_depart_speed = vehicles.get_initial_speed(veh_id) routes.append( self._vehicle(veh_type, "route" + edge, depart="0", id=veh_id, color="1,1,1", departSpeed=str(type_depart_speed), departPos=str(pos), departLane=str(lane))) # add the in-flows from various edges to the xml file if self.net_params.in_flows is not None: total_inflows = self.net_params.in_flows.get() for inflow in total_inflows: for key in inflow: if not isinstance(inflow[key], str): inflow[key] = repr(inflow[key]) routes.append(self._flow(**inflow)) printxml(routes, self.cfg_path + self.roufn)
def generate_net(self, net_params): """ Generates Net files for the transportation network. Different networks require different net_params; see the separate sub-classes for more information. """ nodfn = "%s.nod.xml" % self.name edgfn = "%s.edg.xml" % self.name typfn = "%s.typ.xml" % self.name cfgfn = "%s.netccfg" % self.name netfn = "%s.net.xml" % self.name confn = "%s.con.xml" % self.name # specify the attributes of the nodes nodes = self.specify_nodes(net_params) # xml file for nodes; contains nodes for the boundary points with # respect to the x and y axes x = makexml("nodes", "http://sumo.dlr.de/xsd/nodes_file.xsd") for node_attributes in nodes: x.append(E("node", **node_attributes)) printxml(x, self.net_path + nodfn) # collect the attributes of each edge edges = self.specify_edges(net_params) # xml file for edges x = makexml("edges", "http://sumo.dlr.de/xsd/edges_file.xsd") for edge_attributes in edges: x.append(E("edge", attrib=edge_attributes)) printxml(x, self.net_path + edgfn) # specify the types attributes (default is None) types = self.specify_types(net_params) # xml file for types: contains the the number of lanes and the speed # limit for the lanes if types is not None: x = makexml("types", "http://sumo.dlr.de/xsd/types_file.xsd") for type_attributes in types: x.append(E("type", **type_attributes)) printxml(x, self.net_path + typfn) # specify the connection attributes (default is None) connections = self.specify_connections(net_params) # xml for connections: specifies which lanes connect to which in the # edges if connections is not None: x = makexml("connections", "http://sumo.dlr.de/xsd/connections_file.xsd") for connection_attributes in connections: x.append(E("connection", **connection_attributes)) printxml(x, self.net_path + confn) # check whether the user requested no-internal-links (default="true") if net_params.no_internal_links: no_internal_links = "true" else: no_internal_links = "false" # xml file for configuration, which specifies: # - the location of all files of interest for sumo # - output net file # - processing parameters for no internal links and no turnarounds x = makexml("configuration", "http://sumo.dlr.de/xsd/netconvertConfiguration.xsd") t = E("input") t.append(E("node-files", value=nodfn)) t.append(E("edge-files", value=edgfn)) if types is not None: t.append(E("type-files", value=typfn)) if connections is not None: t.append(E("connection-files", value=confn)) x.append(t) t = E("output") t.append(E("output-file", value=netfn)) x.append(t) t = E("processing") t.append(E("no-internal-links", value="%s" % no_internal_links)) t.append(E("no-turnarounds", value="true")) x.append(t) printxml(x, self.net_path + cfgfn) retcode = subprocess.call( ["netconvert -c " + self.net_path + cfgfn + " --output-file=" + self.cfg_path + netfn + ' --no-internal-links="%s"' % no_internal_links], stdout=sys.stdout, stderr=sys.stderr, shell=True) self.netfn = netfn return self.net_path + netfn