Skip to content

Commit

Permalink
Merge e4713bb into f7e1d78
Browse files Browse the repository at this point in the history
  • Loading branch information
AboudyKreidieh committed Jul 10, 2020
2 parents f7e1d78 + e4713bb commit befe777
Show file tree
Hide file tree
Showing 36 changed files with 860 additions and 460 deletions.
2 changes: 1 addition & 1 deletion environment.yml
Expand Up @@ -9,7 +9,7 @@ dependencies:
- path.py
- python-dateutil==2.7.3
- pip>=18.0
- tensorflow==1.14.0
- tensorflow==1.15.2
- setuptools==41.0.0
- plotly==2.4.0
- gym==0.14.0
Expand Down
7 changes: 2 additions & 5 deletions examples/exp_configs/non_rl/highway_single.py
Expand Up @@ -11,7 +11,7 @@
from flow.core.params import VehicleParams
from flow.core.params import SumoParams
from flow.core.params import SumoLaneChangeParams
from flow.core.rewards import miles_per_gallon, miles_per_megajoule
from flow.core.rewards import instantaneous_mpg
from flow.core.params import SumoCarFollowingParams
from flow.networks import HighwayNetwork
from flow.envs import TestEnv
Expand Down Expand Up @@ -147,10 +147,7 @@
env.k.vehicle.get_speed(env.k.vehicle.get_ids()))),
"avg_outflow": lambda env: np.nan_to_num(
env.k.vehicle.get_outflow_rate(120)),
"miles_per_megajoule": lambda env: np.nan_to_num(
miles_per_megajoule(env, env.k.vehicle.get_ids(), gain=1.0)
),
"miles_per_gallon": lambda env: np.nan_to_num(
miles_per_gallon(env, env.k.vehicle.get_ids(), gain=1.0)
instantaneous_mpg(env, env.k.vehicle.get_ids(), gain=1.0)
)
}
7 changes: 2 additions & 5 deletions examples/exp_configs/non_rl/i210_subnetwork.py
Expand Up @@ -12,8 +12,7 @@
from flow.core.params import VehicleParams
from flow.core.params import InitialConfig
from flow.core.params import InFlows
from flow.core.rewards import miles_per_gallon
from flow.core.rewards import miles_per_megajoule
from flow.core.rewards import instantaneous_mpg
from flow.networks import I210SubNetwork
from flow.networks.i210_subnetwork import EDGES_DISTRIBUTION
from flow.envs import TestEnv
Expand Down Expand Up @@ -211,8 +210,6 @@ def valid_ids(env, veh_ids):
env.k.vehicle.get_speed(valid_ids(env, env.k.vehicle.get_ids())))),
"avg_outflow": lambda env: np.nan_to_num(
env.k.vehicle.get_outflow_rate(120)),
"mpg": lambda env: miles_per_gallon(
"mpg": lambda env: instantaneous_mpg(
env, valid_ids(env, env.k.vehicle.get_ids()), gain=1.0),
"mpj": lambda env: miles_per_megajoule(
env, valid_ids(env, env.k.vehicle.get_ids()), gain=1.0),
}
3 changes: 2 additions & 1 deletion examples/exp_configs/rl/multiagent/multiagent_i210.py
Expand Up @@ -29,7 +29,8 @@
# Specify some configurable constants. #
# =========================================================================== #

# whether to include the downstream slow-down edge in the network as well as a ghost cell at the upstream edge
# whether to include the downstream slow-down edge in the network as well as a
# ghost cell at the upstream edge
WANT_BOUNDARY_CONDITIONS = True
# whether to include vehicles on the on-ramp
ON_RAMP = False
Expand Down
29 changes: 13 additions & 16 deletions examples/train.py
Expand Up @@ -17,7 +17,7 @@
import pytz

from flow.core.util import ensure_dir
from flow.core.rewards import miles_per_gallon, miles_per_megajoule
from flow.core.rewards import instantaneous_mpg
from flow.utils.registry import env_constructor
from flow.utils.rllib import FlowParamsEncoder, get_flow_params
from flow.utils.registry import make_create_env
Expand All @@ -42,10 +42,6 @@ def parse_args(args):
help='Name of the experiment configuration file, as located in '
'exp_configs/rl/singleagent or exp_configs/rl/multiagent.')

parser.add_argument(
'exp_title', type=str,
help='Name of experiment that results will be stored in')

# optional input parameters
parser.add_argument(
'--rl_trainer', type=str, default="rllib",
Expand Down Expand Up @@ -76,14 +72,18 @@ def parse_args(args):
parser.add_argument(
'--rollout_size', type=int, default=1000,
help='How many steps are in a training batch.')
parser.add_argument('--use_s3', action='store_true', help='If true, upload results to s3')
parser.add_argument('--use_s3', action='store_true', default=False,
help='If true, upload results to s3')
parser.add_argument('--local_mode', action='store_true', default=False,
help='If true only 1 CPU will be used')
parser.add_argument('--render', action='store_true', default=False,
help='If true, we render the display')
parser.add_argument(
'--checkpoint_path', type=str, default=None,
help='Directory with checkpoint to restore training from.')
parser.add_argument(
'--exp_title', type=str, default=None,
help='Name of experiment that results will be stored in')
parser.add_argument('--multi_node', action='store_true',
help='Set to true if this will be run in cluster mode.'
'Relevant for rllib')
Expand Down Expand Up @@ -147,7 +147,7 @@ def setup_exps_rllib(flow_params,
number of CPUs to run the experiment over
n_rollouts : int
number of rollouts per training iteration
flags:
flags : TODO
custom arguments
policy_graphs : dict, optional
TODO
Expand Down Expand Up @@ -243,8 +243,7 @@ def on_episode_start(info):
episode.user_data["avg_speed"] = []
episode.user_data["avg_speed_avs"] = []
episode.user_data["avg_energy"] = []
episode.user_data["avg_mpg"] = []
episode.user_data["avg_mpj"] = []
episode.user_data["inst_mpg"] = []
episode.user_data["num_cars"] = []
episode.user_data["avg_accel_human"] = []
episode.user_data["avg_accel_avs"] = []
Expand Down Expand Up @@ -275,8 +274,7 @@ def on_episode_step(info):
av_speed = np.mean([speed for speed in env.k.vehicle.get_speed(rl_ids) if speed >= 0])
if not np.isnan(av_speed):
episode.user_data["avg_speed_avs"].append(av_speed)
episode.user_data["avg_mpg"].append(miles_per_gallon(env, veh_ids, gain=1.0))
episode.user_data["avg_mpj"].append(miles_per_megajoule(env, veh_ids, gain=1.0))
episode.user_data["inst_mpg"].append(instantaneous_mpg(env, veh_ids, gain=1.0))
episode.user_data["num_cars"].append(len(env.k.vehicle.get_ids()))
episode.user_data["avg_accel_human"].append(np.nan_to_num(np.mean(
[np.abs((env.k.vehicle.get_speed(veh_id) - env.k.vehicle.get_previous_speed(veh_id))/env.sim_step) for
Expand All @@ -295,8 +293,7 @@ def on_episode_end(info):
episode.custom_metrics["avg_speed_avs"] = avg_speed_avs
episode.custom_metrics["avg_accel_avs"] = np.mean(episode.user_data["avg_accel_avs"])
episode.custom_metrics["avg_energy_per_veh"] = np.mean(episode.user_data["avg_energy"])
episode.custom_metrics["avg_mpg_per_veh"] = np.mean(episode.user_data["avg_mpg"])
episode.custom_metrics["avg_mpj_per_veh"] = np.mean(episode.user_data["avg_mpj"])
episode.custom_metrics["avg_mpg_per_veh"] = np.mean(episode.user_data["inst_mpg"])
episode.custom_metrics["num_cars"] = np.mean(episode.user_data["num_cars"])

def on_train_result(info):
Expand Down Expand Up @@ -361,7 +358,7 @@ def trial_str_creator(trial):
ray.init()
exp_dict = {
"run_or_experiment": alg_run,
"name": flags.exp_title,
"name": flags.exp_title or flow_params['exp_tag'],
"config": config,
"checkpoint_freq": flags.checkpoint_freq,
"checkpoint_at_end": True,
Expand All @@ -373,9 +370,9 @@ def trial_str_creator(trial):
}
date = datetime.now(tz=pytz.utc)
date = date.astimezone(pytz.timezone('US/Pacific')).strftime("%m-%d-%Y")
s3_string = "s3://i210.experiments/i210/" \
+ date + '/' + flags.exp_title
if flags.use_s3:
s3_string = "s3://i210.experiments/i210/" \
+ date + '/' + flags.exp_title
exp_dict['upload_dir'] = s3_string
tune.run(**exp_dict, queue_trials=False, raise_on_failed_trial=False)

Expand Down
137 changes: 67 additions & 70 deletions flow/controllers/base_controller.py
Expand Up @@ -38,6 +38,8 @@ class BaseController(metaclass=ABCMeta):
List of failsafes which can be "instantaneous", "safe_velocity",
"feasible_accel", or "obey_speed_limit". The order of applying the
falsafes will be based on the order in the list.
display_warnings : bool
Flag for toggling on/off printing failsafe warnings to screen.
noise : double
variance of the gaussian from which to sample a noisy acceleration
"""
Expand All @@ -47,6 +49,7 @@ def __init__(self,
car_following_params,
delay=0,
fail_safe=None,
display_warnings=False,
noise=0):
"""Instantiate the base class for acceleration behavior."""
self.veh_id = veh_id
Expand All @@ -59,17 +62,27 @@ def __init__(self,

# longitudinal failsafe used by the vehicle
if isinstance(fail_safe, str):
self.fail_safe = [fail_safe]
failsafe_list = [fail_safe]
elif isinstance(fail_safe, list) or fail_safe is None:
self.fail_safe = fail_safe
failsafe_list = fail_safe
else:
print(
"==========================================================\n"
"WARNING: fail_safe should be string or list of strings. \n"
"Set fal_safe to None\n"
"==========================================================\n"
)
self.fail_safe = None
raise ValueError("fail_safe should be string or list of strings. Setting fail_safe to None\n")

failsafe_map = {
'instantaneous': self.get_safe_action_instantaneous,
'safe_velocity': self.get_safe_velocity_action,
'feasible_accel': lambda _, accel: self.get_feasible_action(accel),
'obey_speed_limit': self.get_obey_speed_limit_action
}
self.failsafes = []
if failsafe_list:
for check in failsafe_list:
if check in failsafe_map:
self.failsafes.append(failsafe_map.get(check))
else:
raise ValueError('Skipping {}, as it is not a valid failsafe.'.format(check))

self.display_warnings = display_warnings

self.max_accel = car_following_params.controller_params['accel']
# max deaccel should always be a positive
Expand Down Expand Up @@ -103,11 +116,11 @@ def get_action(self, env):
float
the modified form of the acceleration
"""
# clear the current stored accel_no_noise_no_failsafe of this vehicle None
env.k.vehicle.update_accel_no_noise_no_failsafe(self.veh_id, None)
env.k.vehicle.update_accel_no_noise_with_failsafe(self.veh_id, None)
env.k.vehicle.update_accel_with_noise_no_failsafe(self.veh_id, None)
env.k.vehicle.update_accel_with_noise_with_failsafe(self.veh_id, None)
# clear the current stored accels of this vehicle to None
env.k.vehicle.update_accel(self.veh_id, None, noise=False, failsafe=False)
env.k.vehicle.update_accel(self.veh_id, None, noise=False, failsafe=True)
env.k.vehicle.update_accel(self.veh_id, None, noise=True, failsafe=False)
env.k.vehicle.update_accel(self.veh_id, None, noise=True, failsafe=True)

# this is to avoid abrupt decelerations when a vehicle has just entered
# a network and it's data is still not subscribed
Expand All @@ -128,45 +141,24 @@ def get_action(self, env):

# store the acceleration without noise to each vehicle
# run fail safe if requested
env.k.vehicle.update_accel_no_noise_no_failsafe(self.veh_id, accel)
env.k.vehicle.update_accel(self.veh_id, accel, noise=False, failsafe=False)
accel_no_noise_with_failsafe = accel

if self.fail_safe is not None:
for check in self.fail_safe:
if check == 'instantaneous':
accel_no_noise_with_failsafe = self.get_safe_action_instantaneous(
env, accel_no_noise_with_failsafe)
elif check == 'safe_velocity':
accel_no_noise_with_failsafe = self.get_safe_velocity_action(
env, accel_no_noise_with_failsafe)
elif check == 'feasible_accel':
accel_no_noise_with_failsafe = self.get_feasible_action(
accel_no_noise_with_failsafe)
elif check == 'obey_speed_limit':
accel_no_noise_with_failsafe = self.get_obey_speed_limit_action(
env, accel_no_noise_with_failsafe)

env.k.vehicle.update_accel_no_noise_with_failsafe(
self.veh_id, accel_no_noise_with_failsafe)
for failsafe in self.failsafes:
accel_no_noise_with_failsafe = failsafe(env, accel_no_noise_with_failsafe)

env.k.vehicle.update_accel(self.veh_id, accel_no_noise_with_failsafe, noise=False, failsafe=True)

# add noise to the accelerations, if requested
if self.accel_noise > 0:
accel += np.sqrt(env.sim_step) * np.random.normal(0, self.accel_noise)
env.k.vehicle.update_accel_with_noise_no_failsafe(self.veh_id, accel)
env.k.vehicle.update_accel(self.veh_id, accel, noise=True, failsafe=False)

# run the fail-safes, if requested
if self.fail_safe is not None:
for check in self.fail_safe:
if check == 'instantaneous':
accel = self.get_safe_action_instantaneous(env, accel)
elif check == 'safe_velocity':
accel = self.get_safe_velocity_action(env, accel)
elif check == 'feasible_accel':
accel = self.get_feasible_action(accel)
elif check == 'obey_speed_limit':
accel = self.get_obey_speed_limit_action(env, accel)

env.k.vehicle.update_accel_with_noise_with_failsafe(self.veh_id, accel)
for failsafe in self.failsafes:
accel = failsafe(env, accel)

env.k.vehicle.update_accel(self.veh_id, accel, noise=True, failsafe=True)
return accel

def get_safe_action_instantaneous(self, env, action):
Expand Down Expand Up @@ -212,11 +204,12 @@ def get_safe_action_instantaneous(self, env, action):
# if the vehicle will crash into the vehicle ahead of it in the
# next time step (assuming the vehicle ahead of it is not
# moving), then stop immediately
print(
"=====================================\n"
"Vehicle {} is about to crash. Instantaneous acceleration "
"clipping applied.\n"
"=====================================".format(self.veh_id))
if self.display_warnings:
print(
"=====================================\n"
"Vehicle {} is about to crash. Instantaneous acceleration "
"clipping applied.\n"
"=====================================".format(self.veh_id))

return -this_vel / sim_step
else:
Expand Down Expand Up @@ -296,11 +289,12 @@ def safe_velocity(self, env):
# edge_speed_limit = env.k.network.speed_limit(this_edge)

if this_vel > v_safe:
print(
"=====================================\n"
"Speed of vehicle {} is greater than safe speed. Safe velocity "
"clipping applied.\n"
"=====================================".format(self.veh_id))
if self.display_warnings:
print(
"=====================================\n"
"Speed of vehicle {} is greater than safe speed. Safe velocity "
"clipping applied.\n"
"=====================================".format(self.veh_id))

return v_safe

Expand Down Expand Up @@ -333,11 +327,12 @@ def get_obey_speed_limit_action(self, env, action):

if this_vel + action * sim_step > edge_speed_limit:
if edge_speed_limit > 0:
print(
"=====================================\n"
"Speed of vehicle {} is greater than speed limit. Obey "
"speed limit clipping applied.\n"
"=====================================".format(self.veh_id))
if self.display_warnings:
print(
"=====================================\n"
"Speed of vehicle {} is greater than speed limit. Obey "
"speed limit clipping applied.\n"
"=====================================".format(self.veh_id))
return (edge_speed_limit - this_vel) / sim_step
else:
return -this_vel / sim_step
Expand Down Expand Up @@ -365,19 +360,21 @@ def get_feasible_action(self, action):
if action > self.max_accel:
action = self.max_accel

print(
"=====================================\n"
"Acceleration of vehicle {} is greater than the max "
"acceleration. Feasible acceleration clipping applied.\n"
"=====================================".format(self.veh_id))
if self.display_warnings:
print(
"=====================================\n"
"Acceleration of vehicle {} is greater than the max "
"acceleration. Feasible acceleration clipping applied.\n"
"=====================================".format(self.veh_id))

if action < -self.max_deaccel:
action = -self.max_deaccel

print(
"=====================================\n"
"Deceleration of vehicle {} is greater than the max "
"deceleration. Feasible acceleration clipping applied.\n"
"=====================================".format(self.veh_id))
if self.display_warnings:
print(
"=====================================\n"
"Deceleration of vehicle {} is greater than the max "
"deceleration. Feasible acceleration clipping applied.\n"
"=====================================".format(self.veh_id))

return action

0 comments on commit befe777

Please sign in to comment.