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

Separated data loading and simulation run

This commit is contained in:
Ahp06 2019-01-20 15:56:05 +01:00
parent a1196612d4
commit 2f20a9c2b5
7 changed files with 87 additions and 88 deletions

View File

@ -79,7 +79,7 @@ class Config:
f'RF = {self.trafficLights_duration_rf * 100}%\n' f'RF = {self.trafficLights_duration_rf * 100}%\n'
) )
def init_traci(self): def init_traci(self, simulation_dir):
""" """
Init the Traci API Init the Traci API
:return: :return:
@ -90,6 +90,7 @@ class Config:
else: else:
sys.exit("please declare environment variable 'SUMO_HOME'") sys.exit("please declare environment variable 'SUMO_HOME'")
self._SUMOCFG = f'files/simulations/{simulation_dir}/osm.sumocfg'
sumo_binary = os.path.join(os.environ['SUMO_HOME'], 'bin', self._SUMOCMD) sumo_binary = os.path.join(os.environ['SUMO_HOME'], 'bin', self._SUMOCMD)
self.sumo_cmd = [sumo_binary, "-c", self._SUMOCFG] self.sumo_cmd = [sumo_binary, "-c", self._SUMOCFG]

View File

@ -25,30 +25,25 @@ from parse import search
from shapely.geometry import LineString from shapely.geometry import LineString
import actions import actions
from config import Config
from model import Area, Vehicle, Lane, TrafficLight, Phase, Logic, Emission from model import Area, Vehicle, Lane, TrafficLight, Phase, Logic, Emission
class Data: class Data:
def __init__(self, map_bounds, config : Config): def __init__(self, map_bounds, areas_number,simulation_dir):
""" """
Data constructor Data constructor
""" """
self.map_bounds = map_bounds self.map_bounds = map_bounds
self.config = config self.areas_number = areas_number
self.dir = simulation_dir
def init_grid(self): def init_grid(self):
""" """
Initialize the grid of the loaded map from the configuration Initialize the grid of the loaded map from the cfg file with areas_number x areas_number areas
:param self.map_bounds: The map bounds
:param areas_number: The number of areas
:param window_size: The size of the acquisition window
:return: A list of areas
""" """
self.grid = list() self.grid = list()
areas_number = self.config.areas_number areas_number = self.areas_number
window_size = self.config.window_size
width = self.map_bounds[1][0] / areas_number width = self.map_bounds[1][0] / areas_number
height = self.map_bounds[1][1] / areas_number height = self.map_bounds[1][1] / areas_number
@ -58,7 +53,7 @@ class Data:
ar_bounds = ((i * width, j * height), (i * width, (j + 1) * height), ar_bounds = ((i * width, j * height), (i * width, (j + 1) * height),
((i + 1) * width, (j + 1) * height), ((i + 1) * width, j * height)) ((i + 1) * width, (j + 1) * height), ((i + 1) * width, j * height))
name = 'Area ({},{})'.format(i, j) name = 'Area ({},{})'.format(i, j)
area = Area(ar_bounds, name, window_size) area = Area(ar_bounds, name)
self.grid.append(area) self.grid.append(area)
return self.grid return self.grid

View File

@ -1,8 +1,6 @@
{ {
"_SUMOCMD": "sumo", "_SUMOCMD": "sumo",
"_SUMOCFG": "files/simulations/mulhouse_simulation/osm.sumocfg",
"areas_number": 10,
"emissions_threshold": 500000, "emissions_threshold": 500000,
"n_steps": 200, "n_steps": 200,
"window_size":100, "window_size":100,

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

View File

@ -153,13 +153,12 @@ class Area:
The Area class defines a grid area of the simulation map The Area class defines a grid area of the simulation map
""" """
def __init__(self, coords, name, window_size): def __init__(self, coords, name):
""" """
Area constructor Area constructor
:param coords: The coordinates of the zone, :param coords: The coordinates of the zone,
defined by the bounds coordinates of this area : (xmin, ymin, xmax, ymax) defined by the bounds coordinates of this area : (xmin, ymin, xmax, ymax)
:param name: The Area name :param name: The Area name
:param window_size: The size of the acquisition window
""" """
self.limited_speed = False self.limited_speed = False
self.locked = False self.locked = False
@ -168,10 +167,12 @@ class Area:
self.rectangle = Polygon(coords) self.rectangle = Polygon(coords)
self.name = name self.name = name
self.emissions_by_step = [] self.emissions_by_step = []
self.window = collections.deque(maxlen=window_size)
self._lanes: Set[Lane] = set() self._lanes: Set[Lane] = set()
self._tls: Set[TrafficLight] = set() self._tls: Set[TrafficLight] = set()
def set_window_size(self, window_size):
self.window = collections.deque(maxlen=window_size)
def __eq__(self, other): def __eq__(self, other):
""" """
Overrides the equal definition Overrides the equal definition

View File

@ -1,7 +1,7 @@
''' '''
Created on 19 janv. 2019 Created on 19 janv. 2019
@author: Admin @author: Axel Huynh-Phuc
''' '''
import argparse import argparse
@ -17,6 +17,15 @@ from data import Data
import emissions import emissions
from model import Emission from model import Emission
"""
Init the Traci API
"""
if 'SUMO_HOME' in os.environ:
tools = os.path.join(os.environ['SUMO_HOME'], 'tools')
sys.path.append(tools)
else:
sys.exit("please declare environment variable 'SUMO_HOME'")
def add_options(parser): def add_options(parser):
""" """
@ -24,43 +33,42 @@ def add_options(parser):
:param parser: The command line parser :param parser: The command line parser
:return: :return:
""" """
parser.add_argument("-new_dump", "--new_dump", metavar=('config_file', 'dump_name'), nargs=2, type=str,
required=False, help='Load and create a new data dump with the configuration file chosen')
parser.add_argument("-run", "--run", type=str, required=False,
help='Run a simulation with the dump chosen')
# TODO: Faire que -areas & -simulation_dir soit requis si -new_dump
# Faire que -c soit requis si -run
parser.add_argument("-new_dump", "--new_dump", type=str,
required=False, help='Load and create a new data dump with the configuration file chosen')
parser.add_argument("-areas", "--areas", type=int, required=False,
help='Will create a grid with "areas x areas" areas')
parser.add_argument("-simulation_dir", "--simulation_dir", type=str, required=False,
help='Choose the simulation directory')
parser.add_argument("-run", "--run", type=str,
help='Run a simulation with the dump chosen')
parser.add_argument("-c", "--c", type=str,
help='Choose your configuration file from your working directory')
parser.add_argument("-save", "--save", action="store_true", parser.add_argument("-save", "--save", action="store_true",
help='Save the logs into the logs folder') help='Save the logs into the logs folder')
parser.add_argument("-csv", "--csv", action="store_true", parser.add_argument("-csv", "--csv", action="store_true",
help="Export all data emissions into a CSV file") help="Export all data emissions into a CSV file")
parser.add_argument("-steps", "--steps", type=int, default=200, required=False,
help='Choose the simulated time (in seconds)')
parser.add_argument("-ref", "--ref", action="store_true",
help='Launch a reference simulation (without acting on areas)')
parser.add_argument("-gui", "--gui", action="store_true",
help="Set GUI mode")
def create_dump(dump_name, simulation_dir, areas_number):
def create_dump(config_file, dump_name):
""" """
Create a new dump with config file and dump_name chosen Create a new dump with config file and dump_name chosen
:param config_file: The configuration file :param cfg_file: The simulation file
:param dump_name: The dump name :param areas_number: The number of areas in grid
:return: :return:
""" """
config = Config()
config.import_config_file(config_file)
config.check_config()
config.init_traci()
sumo_binary = os.path.join(os.environ['SUMO_HOME'], 'bin', 'sumo') sumo_binary = os.path.join(os.environ['SUMO_HOME'], 'bin', 'sumo')
sumo_cmd = [sumo_binary, "-c", config._SUMOCFG] sumo_cmd = [sumo_binary, "-c", f'files/simulations/{simulation_dir}/osm.sumocfg']
traci.start(sumo_cmd) traci.start(sumo_cmd)
if not os.path.isfile(f'files/dump/{dump_name}.json'): if not os.path.isfile(f'files/dump/{dump_name}.json'):
start = time.perf_counter() start = time.perf_counter()
data = Data(traci.simulation.getNetBoundary(), config) data = Data(traci.simulation.getNetBoundary(), areas_number, simulation_dir)
data.init_grid() data.init_grid()
data.add_data_to_areas() data.add_data_to_areas()
data.save(dump_name) data.save(dump_name)
@ -74,32 +82,33 @@ def create_dump(config_file, dump_name):
traci.close(False) traci.close(False)
def run(data : Data, logger): def run(data : Data, config : Config, logger):
""" """
Run a data set Run a data set
:param data: The data instance :param data: The data instance
:param logger: The logger instance :param logger: The logger instance
""" """
try: try:
traci.start(data.config.sumo_cmd) traci.start(config.sumo_cmd)
for area in data.grid: for area in data.grid: # Set acquisition window size
area.set_window_size(config.window_size)
traci.polygon.add(area.name, area.rectangle.exterior.coords, (255, 0, 0)) # Add polygon for UI traci.polygon.add(area.name, area.rectangle.exterior.coords, (255, 0, 0)) # Add polygon for UI
logger.info(f'Loaded simulation file : {data.config._SUMOCFG}') logger.info(f'Loaded simulation file : {config._SUMOCFG}')
logger.info('Loading data for the simulation') logger.info('Loading data for the simulation')
start = time.perf_counter() start = time.perf_counter()
logger.info('Simulation started...') logger.info('Simulation started...')
step = 0 step = 0
while step < data.config.n_steps: while step < config.n_steps:
traci.simulationStep() traci.simulationStep()
vehicles = emissions.get_all_vehicles() vehicles = emissions.get_all_vehicles()
emissions.get_emissions(data.grid, vehicles, step, data.config, logger) emissions.get_emissions(data.grid, vehicles, step, config, logger)
step += 1 step += 1
print(f'step = {step}/{data.config.n_steps}', end='\r') print(f'step = {step}/{config.n_steps}', end='\r')
finally: finally:
traci.close(False) traci.close(False)
@ -116,7 +125,8 @@ def main(args):
args = parser.parse_args(args) args = parser.parse_args(args)
if args.new_dump is not None: if args.new_dump is not None:
create_dump(args.new_dump[0], args.new_dump[1]) # (config_file, dump_name) if (args.simulation_dir is not None) and (args.areas is not None):
create_dump(args.new_dump, args.simulation_dir, args.areas)
if args.run is not None: if args.run is not None:
dump_path = f'files/dump/{args.run}.json' dump_path = f'files/dump/{args.run}.json'
@ -124,51 +134,45 @@ def main(args):
with open(dump_path, 'r') as f: with open(dump_path, 'r') as f:
data = jsonpickle.decode(f.read()) data = jsonpickle.decode(f.read())
data.config.init_traci() config = Config()
logger = data.config.init_logger(dump_name=args.run, save_logs=args.save) if args.c is not None:
config.import_config_file(args.c)
if args.gui: config.init_traci(data.dir)
data.config._SUMOCMD = "sumo-gui" logger = config.init_logger(dump_name=args.run, save_logs=args.save)
config.check_config()
if args.ref:
data.config.without_actions_mode = True
logger.info(f'Reference simulation')
if args.steps:
data.config.n_steps = args.steps
data.config.check_config()
logger.info(f'Running simulation dump {args.run}...') logger.info(f'Running simulation dump {args.run}...')
start = time.perf_counter() start = time.perf_counter()
run(data, logger)
run(data, config, logger)
simulation_time = round(time.perf_counter() - start, 2) simulation_time = round(time.perf_counter() - start, 2)
logger.info(f'End of the simulation ({simulation_time}s)') logger.info(f'End of the simulation ({simulation_time}s)')
if args.csv: if args.csv:
emissions.export_data_to_csv(data.config, data.grid, dump_name=args.run) emissions.export_data_to_csv(config, data.grid, dump_name=args.run)
logger.info(f'Exported data into the csv folder') logger.info(f'Exported data into the csv folder')
# 1 step is equal to one second simulated # 1 step is equal to one second simulated
logger.info(f'Real-time factor : {data.config.n_steps / simulation_time}') logger.info(f'Real-time factor : {config.n_steps / simulation_time}')
total_emissions = Emission() total_emissions = Emission()
for area in data.grid: for area in data.grid:
total_emissions += area.sum_all_emissions() total_emissions += area.sum_all_emissions()
logger.info(f'Total emissions = {total_emissions.value()} mg') logger.info(f'Total emissions = {total_emissions.value()} mg')
if not data.config.without_actions_mode: # If it's not a simulation without actions if not config.without_actions_mode: # If it's not a simulation without actions
ref = data.config.get_ref_emissions() ref = config.get_ref_emissions()
if not (ref is None): # If a reference value exist (add yours into config.py) if not (ref is None): # If a reference value exist (add yours into config.py)
global_diff = (ref.value() - total_emissions.value()) / ref.value() global_diff = (ref.value() - total_emissions.value()) / ref.value()
logger.info(f'Global reduction percentage of emissions = {global_diff * 100} %') logger.info(f'Global reduction percentage of emissions = {global_diff * 100} %')
logger.info(f'-> CO2 emissions = {emissions.get_reduction_percentage(ref.co2, total_emissions.co2)} %') logger.info(f'-> CO2 emissions = {emissions.get_reduction_percentage(ref.co2, total_emissions.co2)} %')
logger.info(f'-> CO emissions = {emissions.get_reduction_percentage(ref.co, total_emissions.co)} %') logger.info(f'-> CO emissions = {emissions.get_reduction_percentage(ref.co, total_emissions.co)} %')
logger.info(f'-> Nox emissions = {emissions.get_reduction_percentage(ref.nox, total_emissions.nox)} %') logger.info(f'-> Nox emissions = {emissions.get_reduction_percentage(ref.nox, total_emissions.nox)} %')
logger.info(f'-> HC emissions = {emissions.get_reduction_percentage(ref.hc, total_emissions.hc)} %') logger.info(f'-> HC emissions = {emissions.get_reduction_percentage(ref.hc, total_emissions.hc)} %')
logger.info(f'-> PMx emissions = {emissions.get_reduction_percentage(ref.pmx, total_emissions.pmx)} %') logger.info(f'-> PMx emissions = {emissions.get_reduction_percentage(ref.pmx, total_emissions.pmx)} %')
if __name__ == '__main__': if __name__ == '__main__':