1
0
mirror of https://github.com/Ahp06/SUMO_Emissions.git synced 2024-11-22 03:26:30 +00:00

Merge pull request #4 from Ahp06/Axel

Axel
This commit is contained in:
Axel HUYNH-PHUC 2018-12-07 22:18:10 +01:00 committed by GitHub
commit b012c4c4a8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 445 additions and 246 deletions

View File

@ -9,36 +9,70 @@ import traci
from shapely.geometry.linestring import LineString
from model import Area, Vehicle
def remove_vehicle(veh_id):
traci.vehicle.remove(veh_id, traci.constants.REMOVE_PARKING)
def lanes_in_area(area):
for lane_id in traci.lane.getIDList():
polygon_lane = LineString(traci.lane.getShape(lane_id))
if area.rectangle.intersects(polygon_lane):
yield lane_id
from traci._trafficlight import Logic
def compute_edge_weight(edge_id):
return (traci.edge.getCOEmission(edge_id)
+ traci.edge.getNOxEmission(edge_id)
+ traci.edge.getHCEmission(edge_id)
+ traci.edge.getPMxEmission(edge_id)
+ traci.edge.getCO2Emission(edge_id))
+ traci.edge.getCO2Emission(edge_id))/(traci.edge.getLaneNumber(edge_id))
def adjust_edges_weights():
for edge_id in traci.edge.getIDList():
weight = compute_edge_weight(edge_id) # by default edges weight = length/mean speed
traci.edge.adaptTraveltime(edge_id, weight)
traci.edge.setEffort(edge_id, weight)
for veh_id in traci.vehicle.getIDList():
traci.vehicle.rerouteEffort(veh_id)
def lock_area(area: Area):
max_speed = 30
print(f'Setting max speed into {area.name} to {max_speed} km/h')
def limit_speed_into_area(area: Area, vehicles: Iterable[Vehicle], speed_rf):
area.limited_speed = True
for lane in area._lanes:
traci.lane.setMaxSpeed(lane.lane_id, speed_rf * lane.initial_max_speed)
def modifyLogic(logic, rf): #rf for "reduction factor"
new_phases = []
for phase in logic._phases:
new_phase = traci.trafficlight.Phase(phase.duration*rf,phase.minDuration*rf,phase.maxDuration*rf,phase.phaseDef)
new_phases.append(new_phase)
return traci.trafficlight.Logic("new-program", 0 , 0 , 0 , new_phases)
def adjust_traffic_light_phase_duration(area, reduction_factor):
area.tls_adjusted = True
for tl in area._tls:
for logic in tl._logics:
traci.trafficlights.setCompleteRedYellowGreenDefinition(tl.tl_id, modifyLogic(logic,reduction_factor))
def count_vehicles_in_area(area):
vehicles_in_area = 0
for lane in area._lanes:
vehicles_in_area += traci.lane.getLastStepVehicleNumber(lane.lane_id)
return vehicles_in_area
def lock_area(area):
area.locked = True
for lane in area._lanes:
traci.lane.setMaxSpeed(lane.lane_id, max_speed / 3.6)
traci.lane.setDisallowed(lane.lane_id, 'passenger')
def reverse_actions(area):
#Reset max speed to original
if not area.limited_speed:
area.limited_speed = False
for lane in area.lanes:
traci.lane.setMaxSpeed(lane.lane_id, lane.initial_max_speed / 3.6)
#Reset traffic lights initial duration
if not area.tls_adjusted:
area.tls_adjusted = False
for initial_logic in tl._logics:
traci.trafficlights.setCompleteRedYellowGreenDefinition(tl.tl_id, initial_logic)
#Unlock the area
if not area.locked:
area.locked = False
for lane in area._lanes:
traci.lane.setAllowed(lane.lane_id, '') #empty means all classes are allowed

View File

@ -4,6 +4,12 @@ Global configuration for the simulation
import os
import sys
import datetime
import logging
###############################################################################
############################# SIMULATION FILE #################################
###############################################################################
if 'SUMO_HOME' in os.environ:
tools = os.path.join(os.environ['SUMO_HOME'], 'tools')
@ -13,14 +19,99 @@ else:
_SUMOCMD = 'sumo' # use 'sumo-gui' cmd for UI
_SUMOCFG = "mulhouse_simulation/osm.sumocfg"
sumo_binary = os.path.join(os.environ['SUMO_HOME'], 'bin', _SUMOCMD)
sumo_cmd = [sumo_binary, "-c", _SUMOCFG]
###############################################################################
################################## LOGS #######################################
###############################################################################
now = datetime.datetime.now()
current_date = now.strftime("%Y_%m_%d_%H_%M_%S")
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 formatter
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
# add formatter to handler
handler.setFormatter(formatter)
# add handler to logger
logger.addHandler(handler)
###############################################################################
########################## SIMULATION CONFIGURATION ###########################
###############################################################################
CELLS_NUMBER = 10
EMISSIONS_THRESHOLD = 500000
n_steps = 200
lock_mode = True
routing_mode = False
###############################################################################
########################## ACTIONS CONFIGURATION ##############################
###############################################################################
sumo_binary = os.path.join(os.environ['SUMO_HOME'], 'bin', _SUMOCMD)
sumo_cmd = [sumo_binary, "-c", _SUMOCFG]
#Set this mode to True if you want running a basic simulation without actions
without_actions_mode = False
#Limit the speed into areas when the threshold is exceeded
speed_rf = 0.1
limit_speed_mode = True
#Decrease all traffic lights duration into the area when the threshold is exceeded
trafficLights_duration_rf = 0.2
adjust_traffic_light_mode = True
#Vehicles are routed according to the less polluted route (HEAVY)
weight_routing_mode = False
#Lock the area when the threshold is exceeded (NOT FIXED)
lock_area_mode = False
#Weight routing mode cannot be combinated with other actions
if weight_routing_mode:
limit_speed_mode = False
adjust_traffic_light_mode = False
#If without_actions_mode is choosen
if without_actions_mode:
limit_speed_mode = False
adjust_traffic_light_mode = False
weight_routing_mode = False
lock_area_mode = False
###############################################################################
########################## SIMULATION REFERENCES ##############################
###############################################################################
# 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
###############################################################################
########################## CONFIGURATION METHODS ##############################
###############################################################################
def get_basics_emissions():
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')
+ str(f'step number = {n_steps}\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')
+ str(f'adjust traffic light mode = {adjust_traffic_light_mode} , RF = {trafficLights_duration_rf*100}%\n'))

View File

@ -1,13 +1,18 @@
from typing import List
import traci
import time
from shapely.geometry import LineString
from parse import search
import actions
import config
import sys
from model import Area, Vehicle, Lane
from model import Area, Vehicle, Lane , TrafficLight , Phase , Logic
from traci import trafficlight
logger = config.logger
def init_grid(simulation_bounds, cells_number):
grid = list()
@ -19,18 +24,52 @@ def init_grid(simulation_bounds, cells_number):
ar_bounds = ((i * width, j * height), (i * width, (j + 1) * height),
((i + 1) * width, (j + 1) * height), ((i + 1) * width, j * height))
area = Area(ar_bounds)
area.name = 'area ({},{})'.format(i, j)
area.name = 'Area ({},{})'.format(i, j)
grid.append(area)
traci.polygon.add(area.name, ar_bounds, (0, 255, 0))
return grid
def get_all_lanes() -> List[Lane]:
lanes = []
for lane_id in traci.lane.getIDList():
polygon_lane = LineString(traci.lane.getShape(lane_id))
initial_max_speed = traci.lane.getMaxSpeed(lane_id)
lanes.append(Lane(lane_id, polygon_lane, initial_max_speed))
return lanes
def parse_phase(phase_repr):
duration = search('duration: {:f}', phase_repr)
minDuration = search('minDuration: {:f}', phase_repr)
maxDuration = search('maxDuration: {:f}', phase_repr)
phaseDef = search('phaseDef: {}\n', phase_repr)
if phaseDef is None: phaseDef = ''
else : phaseDef = phaseDef[0]
return Phase(duration[0], minDuration[0], maxDuration[0], phaseDef)
def add_data_to_areas(areas: List[Area]):
lanes = get_all_lanes()
for area in areas:
for lane in lanes: # add lanes
if area.rectangle.intersects(lane.polygon):
area.add_lane(lane)
for tl_id in traci.trafficlight.getIDList(): # add traffic lights
if lane.lane_id in traci.trafficlight.getControlledLanes(tl_id):
logics = []
for l in traci.trafficlight.getCompleteRedYellowGreenDefinition(tl_id): #add logics
phases = []
for phase in traci.trafficlight.Logic.getPhases(l): #add phases to logics
phases.append(parse_phase(phase.__repr__()))
logics.append(Logic(l,phases))
area.add_tl(TrafficLight(tl_id,logics))
def compute_vehicle_emissions(veh_id):
return (traci.vehicle.getCOEmission(veh_id)
+ traci.vehicle.getNOxEmission(veh_id)
+ traci.vehicle.getHCEmission(veh_id)
+ traci.vehicle.getPMxEmission(veh_id)
+ traci.vehicle.getCO2Emission(veh_id))
+traci.vehicle.getNOxEmission(veh_id)
+traci.vehicle.getHCEmission(veh_id)
+traci.vehicle.getPMxEmission(veh_id)
+traci.vehicle.getCO2Emission(veh_id))
def get_all_vehicles() -> List[Vehicle]:
@ -39,73 +78,76 @@ def get_all_vehicles() -> List[Vehicle]:
veh_pos = traci.vehicle.getPosition(veh_id)
vehicle = Vehicle(veh_id, veh_pos)
vehicle.emissions = compute_vehicle_emissions(veh_id)
traci.vehicle.setRoutingMode(veh_id, traci.constants.ROUTING_MODE_AGGREGATED)
vehicles.append(vehicle)
return vehicles
def get_all_lanes() -> List[Lane]:
lanes = []
for lane_id in traci.lane.getIDList():
polygon_lane = LineString(traci.lane.getShape(lane_id))
lanes.append(Lane(lane_id, polygon_lane))
return lanes
def get_emissions(grid: List[Area], vehicles: List[Vehicle]):
for area in grid:
for vehicle in vehicles:
if vehicle.pos in area:
area.emissions += vehicle.emissions
if config.lock_mode and area.emissions > config.EMISSIONS_THRESHOLD and not area.locked:
actions.lock_area(area)
traci.polygon.setColor(area.name, (255, 0, 0))
traci.polygon.setFilled(area.name, True)
if area.emissions > 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)
traci.polygon.setColor(area.name, (255, 0, 0))
traci.polygon.setFilled(area.name, True)
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)
def add_lanes_to_areas(areas: List[Area]):
lanes = get_all_lanes()
for area in areas:
for lane in lanes:
if area.rectangle.intersects(lane.polygon):
area.add_lane(lane)
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)
grid = init_grid(traci.simulation.getNetBoundary(), config.CELLS_NUMBER)
add_lanes_to_areas(grid)
logger.info('Loading data for the simulation')
start = time.perf_counter()
grid = init_grid(traci.simulation.getNetBoundary(), config.CELLS_NUMBER)
add_data_to_areas(grid)
loading_time = round(time.perf_counter() - start,2)
logger.info(f'Data loaded ({loading_time}s)')
logger.info('Start of the simulation')
step = 0
while step < config.n_steps: # traci.simulation.getMinExpectedNumber() > 0:
while step < config.n_steps : #traci.simulation.getMinExpectedNumber() > 0:
traci.simulationStep()
vehicles = get_all_vehicles()
get_emissions(grid, vehicles)
if config.routing_mode:
if config.weight_routing_mode:
logger.info('Action - Lane weights adjusted')
actions.adjust_edges_weights()
# actions.rerouteAllVehicles()
step += 1
sys.stdout.write(f'Simulation step = {step}/{config.n_steps}' + '\r')
sys.stdout.flush()
finally:
traci.close(False)
simulation_time = round(time.perf_counter() - start,2)
logger.info(f'End of the simulation ({simulation_time}s)')
total_emissions = 0
for area in grid:
total_emissions += area.emissions
# Total of emissions of all pollutants in mg for 200 steps of simulation without locking areas
total_emissions200 = 43970763.15084749
logger.info(f'Total emissions = {total_emissions} mg')
print(f'\n**** Total emissions = {total_emissions} mg ****')
diff_with_lock = (total_emissions200 - total_emissions) / total_emissions200
print(f'**** Reduction percentage of emissions = {diff_with_lock*100} % ****\n')
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} %')
logger.info('With the configuration : \n' + str(config.show_config()))
logger.info('Logs END')
if __name__ == '__main__':

View File

@ -3,27 +3,57 @@ 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:
def __init__(self, lane_id: str, polygon: LineString):
def __init__(self, lane_id: str, polygon: LineString, initial_max_speed: float):
self.polygon = polygon
self.lane_id = lane_id
self.initial_max_speed = initial_max_speed
def __hash__(self):
"""Overrides the default implementation"""
return hash(self.lane_id)
class Phase:
def __init__(self, duration: float, minDuration: float, maxDuration : float, phaseDef: str):
self.duration = duration
self.minDuration = minDuration
self.maxDuration = maxDuration
self.phaseDef = phaseDef
def __repr__(self) -> str:
repr = f'Phase(duration:{self.duration},minDuration:{self.minDuration},maxDuration:{self.maxDuration},phaseDef:{self.phaseDef})'
return str(repr)
class Logic:
def __init__(self, logic: SUMO_Logic, phases: Set[Phase]):
self._logic = logic
self._phases: Set[Phase] = phases
class TrafficLight:
def __init__(self, tl_id: str, logics: Set[Logic]):
self.tl_id = tl_id
self._logics: Set[Logic] = logics
def __hash__(self):
"""Overrides the default implementation"""
return hash(self.tl_id)
class Area:
def __init__(self, coords, name=''):
self.limited_speed = False
self.locked = False
self.tls_adjusted = False
self.rectangle = Polygon(coords)
self.name = name
self.emissions = 0.0
self._lanes: Set[Lane] = set()
self._tls: Set[TrafficLight] = set()
def __eq__(self, other):
return self.rectangle.__eq__(other)
@ -41,6 +71,9 @@ class Area:
def add_lane(self, lane: Lane):
self._lanes.add(lane)
def add_tl(self, tl: TrafficLight):
self._tls.add(tl)
def remove_lane(self, lane: Lane):
self._lanes.remove(lane)
@ -52,7 +85,6 @@ class Area:
(xmax, ymax),
(xmax, ymin)))
class Vehicle:
def __init__(self, veh_id: int, pos: Tuple[float, float]):