diff --git a/sumo_project/actions.py b/sumo_project/actions.py index 69705db..527a5c6 100644 --- a/sumo_project/actions.py +++ b/sumo_project/actions.py @@ -3,13 +3,14 @@ Created on 17 oct. 2018 @author: Axel Huynh-Phuc, Thibaud Gasser """ +import traci +from traci._trafficlight import Logic from typing import Iterable -import traci from shapely.geometry.linestring import LineString from model import Area, Vehicle -from traci._trafficlight import Logic + def compute_edge_weight(edge_id): return (traci.edge.getCOEmission(edge_id) diff --git a/sumo_project/config.py b/sumo_project/config.py index decf4d5..c92c7ec 100644 --- a/sumo_project/config.py +++ b/sumo_project/config.py @@ -2,15 +2,15 @@ Global configuration for the simulation """ -import os -import sys import datetime import logging +import os +import sys + ############################################################################### ############################# SIMULATION FILE ################################# ############################################################################### - if 'SUMO_HOME' in os.environ: tools = os.path.join(os.environ['SUMO_HOME'], 'tools') sys.path.append(tools) @@ -28,13 +28,13 @@ sumo_cmd = [sumo_binary, "-c", _SUMOCFG] now = datetime.datetime.now() current_date = now.strftime("%Y_%m_%d_%H_%M_%S") -LOG_FILENAME = f'sumo_logs_{current_date}.log' +log_filename = f'sumo_logs_{current_date}.log' # create logger logger = logging.getLogger("sumo_logger") logger.setLevel(logging.INFO) -# create console handler and set level to info -handler = logging.FileHandler(LOG_FILENAME) +# create handler and set level to info +handler = logging.FileHandler(log_filename) # create formatter formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s") # add formatter to handler @@ -46,9 +46,10 @@ logger.addHandler(handler) ########################## SIMULATION CONFIGURATION ########################### ############################################################################### -CELLS_NUMBER = 10 -EMISSIONS_THRESHOLD = 500000 +areas_number = 10 # Simulation boundary will be divided into areas_number x areas_number areas +emissions_threshold = 500000 n_steps = 200 +window_size = 100 ############################################################################### ########################## ACTIONS CONFIGURATION ############################## @@ -88,28 +89,27 @@ if without_actions_mode: ############################################################################### # Total of emissions of all pollutants in mg for n steps of simulation without locking areas -total_emissions200 = 43970763.15084749 -total_emissions300 = 87382632.08217141 -total_emissions400 = 140757491.8489904 -total_emissions500 = 202817535.43856794 +# These constants are simulation dependant, you must change them according to your simulation +total_emissions100 = 13615949.148296086 +total_emissions200 = 43970763.15084738 +total_emissions300 = 87382632.0821697 ############################################################################### ########################## CONFIGURATION METHODS ############################## ############################################################################### def get_basics_emissions(): + if n_steps == 100: + return total_emissions100 if n_steps == 200: return total_emissions200 if n_steps == 300: return total_emissions300 - if n_steps == 400: - return total_emissions400 - if n_steps == 500: - return total_emissions500 def show_config(): - return (str(f'Grid : {CELLS_NUMBER}x{CELLS_NUMBER}\n') + return (str(f'Grid : {areas_number}x{areas_number}\n') + str(f'step number = {n_steps}\n') + + str(f'window size = {window_size}\n') + str(f'weight routing mode = {weight_routing_mode}\n') + str(f'lock area mode = {lock_area_mode}\n') + str(f'limit speed mode = {limit_speed_mode}, RF = {speed_rf*100}%\n') diff --git a/sumo_project/emissions.py b/sumo_project/emissions.py index 21d4cb3..4fe9194 100644 --- a/sumo_project/emissions.py +++ b/sumo_project/emissions.py @@ -14,12 +14,15 @@ from traci import trafficlight logger = config.logger -def init_grid(simulation_bounds, cells_number): +def init_grid(simulation_bounds, areas_number): + """ + Create all areas according to simulation bounds and the areas number choosen + """ grid = list() - width = simulation_bounds[1][0] / cells_number - height = simulation_bounds[1][1] / cells_number - for i in range(cells_number): - for j in range(cells_number): + width = simulation_bounds[1][0] / areas_number + height = simulation_bounds[1][1] / areas_number + for i in range(areas_number): + for j in range(areas_number): # bounds coordinates for the area : (xmin, ymin, xmax, ymax) ar_bounds = ((i * width, j * height), (i * width, (j + 1) * height), ((i + 1) * width, (j + 1) * height), ((i + 1) * width, j * height)) @@ -81,13 +84,17 @@ def get_all_vehicles() -> List[Vehicle]: vehicles.append(vehicle) return vehicles -def get_emissions(grid: List[Area], vehicles: List[Vehicle]): +def get_emissions(grid: List[Area], vehicles: List[Vehicle], current_step): for area in grid: + vehicle_emissions = 0 for vehicle in vehicles: if vehicle.pos in area: - area.emissions += vehicle.emissions - if area.emissions > config.EMISSIONS_THRESHOLD: - + vehicle_emissions += vehicle.emissions + + area.emissions_by_step.append(vehicle_emissions) + + if area.sum_emissions_by_step(current_step, config.window_size) > config.emissions_threshold: + if config.limit_speed_mode and not area.limited_speed: logger.info(f'Action - Decreased max speed into {area.name} by {config.speed_rf*100}%') actions.limit_speed_into_area(area, vehicles, config.speed_rf) @@ -96,21 +103,22 @@ def get_emissions(grid: List[Area], vehicles: List[Vehicle]): if config.adjust_traffic_light_mode and not area.tls_adjusted: logger.info(f'Action - Decreased traffic lights duration by {config.trafficLights_duration_rf*100}%') actions.adjust_traffic_light_phase_duration(area, config.trafficLights_duration_rf) - + if config.lock_area_mode and not area.locked: if actions.count_vehicles_in_area(area): logger.info(f'Action - {area.name} blocked') actions.lock_area(area) + def main(): grid = list() try: traci.start(config.sumo_cmd) - + logger.info(f'Loaded simulation file : {config._SUMOCFG}') logger.info('Loading data for the simulation') start = time.perf_counter() - grid = init_grid(traci.simulation.getNetBoundary(), config.CELLS_NUMBER) + grid = init_grid(traci.simulation.getNetBoundary(), config.areas_number) add_data_to_areas(grid) loading_time = round(time.perf_counter() - start,2) @@ -122,7 +130,7 @@ def main(): traci.simulationStep() vehicles = get_all_vehicles() - get_emissions(grid, vehicles) + get_emissions(grid, vehicles,step) if config.weight_routing_mode: logger.info('Action - Lane weights adjusted') @@ -137,14 +145,15 @@ def main(): total_emissions = 0 for area in grid: - total_emissions += area.emissions - + total_emissions += area.sum_all_emissions() + logger.info(f'Total emissions = {total_emissions} mg') - if not config.without_actions_mode: + if not config.without_actions_mode : ref = config.get_basics_emissions() - diff_with_actions = (ref - total_emissions)/ref - logger.info(f'Reduction percentage of emissions = {diff_with_actions*100} %') + if not (ref is None): + diff_with_actions = (ref - total_emissions)/ref + logger.info(f'Reduction percentage of emissions = {diff_with_actions*100} %') logger.info('With the configuration : \n' + str(config.show_config())) logger.info('Logs END') diff --git a/sumo_project/model.py b/sumo_project/model.py index 888cef7..e5d288c 100644 --- a/sumo_project/model.py +++ b/sumo_project/model.py @@ -1,9 +1,9 @@ +from traci._trafficlight import Logic as SUMO_Logic from typing import Tuple, Set from shapely.geometry import Point, LineString from shapely.geometry import Polygon from shapely.geometry.base import BaseGeometry -from traci._trafficlight import Logic as SUMO_Logic class Lane: @@ -51,7 +51,7 @@ class Area: self.tls_adjusted = False self.rectangle = Polygon(coords) self.name = name - self.emissions = 0.0 + self.emissions_by_step = [] self._lanes: Set[Lane] = set() self._tls: Set[TrafficLight] = set() @@ -76,6 +76,19 @@ class Area: def remove_lane(self, lane: Lane): self._lanes.remove(lane) + + def sum_all_emissions(self): + sum = 0 + for emission in self.emissions_by_step: + sum += emission + return sum + + def sum_emissions_by_step(self, current_step, window_size): + sum = 0 + q = current_step // window_size #Returns the integral part of the quotient + for i in range(q*window_size, current_step): + sum += self.emissions_by_step[i] + return sum @classmethod def from_bounds(cls, xmin, ymin, xmax, ymax):