diff --git a/examples/exp_configs/non_rl/aimsun_template.py b/examples/exp_configs/non_rl/aimsun_template.py index 7ab4fd13b..69181ac28 100644 --- a/examples/exp_configs/non_rl/aimsun_template.py +++ b/examples/exp_configs/non_rl/aimsun_template.py @@ -33,7 +33,6 @@ sim=AimsunParams( sim_step=0.1, render=True, - emission_path='data', replication_name="Replication 930", centroid_config_name="Centroid Configuration 910" ), diff --git a/examples/exp_configs/non_rl/figure_eight.py b/examples/exp_configs/non_rl/figure_eight.py index 13444261a..37c155cff 100755 --- a/examples/exp_configs/non_rl/figure_eight.py +++ b/examples/exp_configs/non_rl/figure_eight.py @@ -15,7 +15,9 @@ vehicles = VehicleParams() vehicles.add( veh_id="idm", - acceleration_controller=(IDMController, {}), + acceleration_controller=(IDMController, { + "noise": 0.1, + }), lane_change_controller=(StaticLaneChanger, {}), routing_controller=(ContinuousRouter, {}), car_following_params=SumoCarFollowingParams( diff --git a/examples/exp_configs/non_rl/i210_subnetwork.py b/examples/exp_configs/non_rl/i210_subnetwork.py new file mode 100644 index 000000000..873028304 --- /dev/null +++ b/examples/exp_configs/non_rl/i210_subnetwork.py @@ -0,0 +1,55 @@ +"""Runs a simulation of the I-210 subnetwork.""" +from flow.core.params import AimsunParams, EnvParams, NetParams +from flow.core.params import VehicleParams +from flow.core.params import InFlows +import flow.config as config +from flow.envs import TestEnv +from flow.networks import Network +import os + + +# no vehicles in the network +vehicles = VehicleParams() + +# path to the imported Aimsun template +template_path = os.path.join( + config.PROJECT_PATH, "examples/prebuilt/aimsun/i_210_sub_merge_020620.ang") + + +flow_params = dict( + # name of the experiment + exp_tag='I-210_subnetwork', + + # name of the flow environment the experiment is running on + env_name=TestEnv, + + # name of the network class the experiment is running on + network=Network, + + # simulator that is used by the experiment + simulator='aimsun', + + # Aimsun-related parameters + sim=AimsunParams( + sim_step=0.1, # FIXME: 0.8? + render=True, + replication_name="Replication 930", # FIXME + centroid_config_name="Centroid Configuration 910" # FIXME + ), + + # environment related parameters (see flow.core.params.EnvParams) + env=EnvParams( + horizon=3000, # FIXME + ), + + # network-related parameters (see flow.core.params.NetParams and the + # network's documentation or ADDITIONAL_NET_PARAMS component) + net=NetParams( + inflows=InFlows(), + template=template_path + ), + + # vehicles to be placed in the network at the start of a rollout (see + # flow.core.params.VehicleParams) + veh=vehicles, +) diff --git a/examples/exp_configs/non_rl/merge.py b/examples/exp_configs/non_rl/merge.py index 2a1ff0455..5d37b44fc 100644 --- a/examples/exp_configs/non_rl/merge.py +++ b/examples/exp_configs/non_rl/merge.py @@ -57,7 +57,6 @@ # sumo-related parameters (see flow.core.params.SumoParams) sim=SumoParams( render=True, - emission_path="./data/", sim_step=0.2, restart_instance=False, ), diff --git a/examples/exp_configs/non_rl/ring.py b/examples/exp_configs/non_rl/ring.py index bffbdf3ba..1dfd28e99 100755 --- a/examples/exp_configs/non_rl/ring.py +++ b/examples/exp_configs/non_rl/ring.py @@ -6,6 +6,7 @@ from flow.controllers import IDMController, ContinuousRouter from flow.core.params import SumoParams, EnvParams, InitialConfig, NetParams from flow.core.params import VehicleParams +from flow.core.params import SumoCarFollowingParams from flow.envs.ring.accel import AccelEnv, ADDITIONAL_ENV_PARAMS from flow.networks.ring import RingNetwork, ADDITIONAL_NET_PARAMS @@ -15,6 +16,9 @@ veh_id="idm", acceleration_controller=(IDMController, {}), routing_controller=(ContinuousRouter, {}), + car_following_params=SumoCarFollowingParams( + min_gap=0, + ), num_vehicles=22) diff --git a/examples/exp_configs/rl/multiagent/multiagent_ring.py b/examples/exp_configs/rl/multiagent/multiagent_ring.py index e7688c87d..8e33cc444 100644 --- a/examples/exp_configs/rl/multiagent/multiagent_ring.py +++ b/examples/exp_configs/rl/multiagent/multiagent_ring.py @@ -12,6 +12,7 @@ from flow.core.params import NetParams from flow.core.params import SumoParams from flow.core.params import VehicleParams +from flow.core.params import SumoCarFollowingParams from flow.envs.multiagent import MultiWaveAttenuationPOEnv from flow.networks import MultiRingNetwork from flow.utils.registry import make_create_env @@ -35,6 +36,9 @@ acceleration_controller=(IDMController, { 'noise': 0.2 }), + car_following_params=SumoCarFollowingParams( + min_gap=0 + ), routing_controller=(ContinuousRouter, {}), num_vehicles=21) vehicles.add( diff --git a/examples/prebuilt/aimsun/i_210_sub_merge_020620.ang b/examples/prebuilt/aimsun/i_210_sub_merge_020620.ang new file mode 100644 index 000000000..0b0135d5f Binary files /dev/null and b/examples/prebuilt/aimsun/i_210_sub_merge_020620.ang differ diff --git a/examples/simulate.py b/examples/simulate.py index 04967b830..a46466bde 100644 --- a/examples/simulate.py +++ b/examples/simulate.py @@ -6,6 +6,7 @@ import argparse import sys from flow.core.experiment import Experiment +from flow.core.params import AimsunParams def parse_args(args): @@ -60,6 +61,12 @@ def parse_args(args): flow_params['sim'].render = not flags.no_render flow_params['simulator'] = 'aimsun' if flags.aimsun else 'traci' + # If Aimsun is being called, replace SumoParams with AimsunParams. + if flags.aimsun: + sim_params = AimsunParams() + sim_params.__dict__.update(flow_params['sim'].__dict__) + flow_params['sim'] = sim_params + # specify an emission path if they are meant to be generated if flags.gen_emission: flow_params['sim'].emission_path = "./data" diff --git a/flow/core/kernel/network/aimsun.py b/flow/core/kernel/network/aimsun.py index 0378d45a9..f5d9b599b 100644 --- a/flow/core/kernel/network/aimsun.py +++ b/flow/core/kernel/network/aimsun.py @@ -258,11 +258,13 @@ def update(self, reset): def close(self): """See parent class.""" - # delete the json file that was used to read the network data - cur_dir = os.path.join(config.PROJECT_PATH, - 'flow/core/kernel/network') - os.remove(os.path.join(cur_dir, 'data_%s.json' % self.sim_params.port)) - os.remove('%s_%s' % (self.network.net_params.template, self.sim_params.port)) + try: + # delete the json file that was used to read the network data + cur_dir = os.path.join(config.PROJECT_PATH, 'flow/core/kernel/network') + os.remove(os.path.join(cur_dir, 'data_%s.json' % self.sim_params.port)) + os.remove('%s_%s' % (self.network.net_params.template, self.sim_params.port)) + except FileNotFoundError: + pass ########################################################################### # State acquisition methods # diff --git a/flow/core/kernel/simulation/aimsun.py b/flow/core/kernel/simulation/aimsun.py index 91b4c4abd..f24428290 100644 --- a/flow/core/kernel/simulation/aimsun.py +++ b/flow/core/kernel/simulation/aimsun.py @@ -1,8 +1,11 @@ """Script containing the base simulation kernel class.""" -from flow.core.kernel.simulation.base import KernelSimulation -from flow.utils.aimsun.api import FlowAimsunAPI +import os +import signal import os.path as osp import csv + +from flow.core.kernel.simulation.base import KernelSimulation +from flow.utils.aimsun.api import FlowAimsunAPI from flow.core.util import ensure_dir @@ -126,6 +129,10 @@ def close(self): try: self.kernel_api.stop_simulation() self.master_kernel.network.aimsun_proc.kill() + + # Weird bug that I don't understand. This closes Aimsun's window. + pid = self.master_kernel.network.aimsun_proc.pid + 1 + os.kill(pid, signal.SIGTERM) except OSError: # in case no simulation originally existed (used by the visualizer) pass diff --git a/flow/core/kernel/vehicle/aimsun.py b/flow/core/kernel/vehicle/aimsun.py index 9e791a10d..5529225dc 100644 --- a/flow/core/kernel/vehicle/aimsun.py +++ b/flow/core/kernel/vehicle/aimsun.py @@ -47,11 +47,6 @@ def __init__(self, # Ordered dictionary used to keep neural net inputs in order self.__vehicles = collections.OrderedDict() - # total number of vehicles in the network - self.num_vehicles = 0 - # number of rl vehicles in the network - self.num_rl_vehicles = 0 - # contains the parameters associated with each type of vehicle self.type_parameters = {} @@ -110,8 +105,6 @@ def initialize(self, vehicles): individual vehicles and their initial speeds """ self.type_parameters = vehicles.type_parameters - self.num_vehicles = 0 - self.num_rl_vehicles = 0 self.__vehicles.clear() for typ in vehicles.initial: @@ -121,9 +114,6 @@ def initialize(self, vehicles): self.__vehicles[veh_id]['type'] = typ['veh_id'] self.__vehicles[veh_id]['type_name'] = typ['veh_id'] # FIXME self.__vehicles[veh_id]['initial_speed'] = typ['initial_speed'] - self.num_vehicles += 1 - if typ['acceleration_controller'][0] == RLController: - self.num_rl_vehicles += 1 # for tracked_type in self.tracked_vehicle_types: # self.num_type[tracked_type] = 0 @@ -174,6 +164,12 @@ def update(self, reset): added_vehicles = self.kernel_api.get_entered_ids() exited_vehicles = self.kernel_api.get_exited_ids() + # updated the list of departed and arrived vehicles + self._num_departed.append(len(added_vehicles)) + self._num_arrived.append(len(exited_vehicles)) + self._departed_ids.append(added_vehicles) + self._arrived_ids.append(exited_vehicles) + # add the new vehicles if they should be tracked for aimsun_id in added_vehicles: veh_type = self.kernel_api.get_vehicle_type_name(aimsun_id) @@ -351,7 +347,6 @@ def _add_departed(self, aimsun_id): # add the vehicle's id to the list of vehicle ids if accel_controller[0] == RLController: self.__rl_ids.append(veh_id) - self.num_rl_vehicles += 1 else: self.__human_ids.append(veh_id) if accel_controller[0] != SimCarFollowingController: @@ -369,7 +364,6 @@ def _add_departed(self, aimsun_id): def add(self, veh_id, type_id, edge, pos, lane, speed): """See parent class.""" - self.num_vehicles += 1 self.__ids.append(veh_id) self.__vehicles[veh_id] = {} self.__vehicles[veh_id]["type_name"] = type_id @@ -414,7 +408,6 @@ def remove(self, aimsun_id): del self._id_aimsun2flow[aimsun_id] del self._id_flow2aimsun[veh_id] self.__ids.remove(veh_id) - self.num_vehicles -= 1 # remove it from all other ids (if it is there) if veh_id in self.__human_ids: @@ -426,7 +419,6 @@ def remove(self, aimsun_id): elif veh_id in self.__rl_ids: # FIXME should be else self.__rl_ids.remove(veh_id) - self.num_rl_vehicles -= 1 # make sure that the rl ids remain sorted self.__rl_ids.sort() @@ -802,3 +794,11 @@ def get_lane_followers_speed(self, veh_id, error=None): def get_lane_leaders_speed(self, veh_id, error=None): """See parent class.""" raise NotImplementedError + + @property + def num_vehicles(self): + return len(self.__ids) + + @property + def num_rl_vehicles(self): + return len(self.__rl_ids) diff --git a/flow/envs/base.py b/flow/envs/base.py index 7749ffea5..0166b6ff7 100644 --- a/flow/envs/base.py +++ b/flow/envs/base.py @@ -392,8 +392,10 @@ def step(self, rl_actions): # test if the environment should terminate due to a collision or the # time horizon being met - done = (self.time_counter >= self.env_params.warmup_steps + - self.env_params.horizon) # or crash + current_time = self.time_counter / self.env_params.sims_per_step + max_time = self.env_params.warmup_steps + self.env_params.horizon + + done = (current_time >= max_time) # or crash # compute the info for each agent infos = {} @@ -478,8 +480,7 @@ def reset(self): # reintroduce the initial vehicles to the network for veh_id in self.initial_ids: - type_id, edge, lane_index, pos, speed = \ - self.initial_state[veh_id] + type_id, edge, lane_index, pos, speed = self.initial_state[veh_id] try: self.k.vehicle.add( diff --git a/flow/networks/ring.py b/flow/networks/ring.py index de4d17503..ceef22a78 100755 --- a/flow/networks/ring.py +++ b/flow/networks/ring.py @@ -37,7 +37,7 @@ class RingNetwork(Network): >>> from flow.core.params import NetParams >>> from flow.core.params import VehicleParams >>> from flow.core.params import InitialConfig - >>> from flow.scenarios import RingNetwork + >>> from flow.networks import RingNetwork >>> >>> network = RingNetwork( >>> name='ring_road', diff --git a/flow/utils/aimsun/generate.py b/flow/utils/aimsun/generate.py index 25ed213b0..b8f3cd379 100644 --- a/flow/utils/aimsun/generate.py +++ b/flow/utils/aimsun/generate.py @@ -33,6 +33,7 @@ port_string = sys.argv[1] model.setAuthor(port_string) + def generate_net(nodes, edges, connections,