-
Notifications
You must be signed in to change notification settings - Fork 375
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Default num_vehicles to 0 when adding vehicle type * add color_vehicles param if we don't want auto vehicle coloration * Add color_vehicles param in docstring * More params and docstring for InFlows * Consider new inflow params period and number when adding them in sumo * Complete wrt changes and add examples to inflows tutorial * Add images for new inflow tutorial * Fix allowed value for 'begin' param * Add precisions for kwargs * Fix docstyle * Make attribute SimParams.color_vehicles back-compatible for tests * Fix test_environments that expects one vehicle of each type to be added by default * Fix bug in case inflow generates vehicles into several routes * Made new highway example with on and off ramps * Add angle for on and off ramps * Modify network parameters * Fix docstring * Fix docstring * Fix pep8 * Fix pep8 * Fix bug of vehicles colliding * test highway ramps * Fix vehicles collision * Add ramps angle in additional params * updated python version * updated rllib pkl data to match new python * added channel to conda * added different channels
- Loading branch information
1 parent
fd0ad46
commit 0b8503f
Showing
10 changed files
with
390 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
name: flow | ||
|
||
dependencies: | ||
- python==3.5.2 | ||
- python==3.6.8 | ||
- numpy==1.14.0 | ||
- scipy==1.1.0 | ||
- lxml==4.2.4 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
"""Example of a highway section network with on/off ramps.""" | ||
|
||
from flow.core.params import SumoParams, EnvParams, \ | ||
NetParams, InitialConfig, InFlows, SumoCarFollowingParams, \ | ||
SumoLaneChangeParams | ||
from flow.core.params import VehicleParams | ||
from flow.core.experiment import Experiment | ||
from flow.scenarios.highway_ramps import HighwayRampsScenario, \ | ||
ADDITIONAL_NET_PARAMS | ||
from flow.controllers import IDMController | ||
from flow.envs.loop.loop_accel import AccelEnv, ADDITIONAL_ENV_PARAMS | ||
|
||
|
||
additional_net_params = ADDITIONAL_NET_PARAMS.copy() | ||
|
||
# lengths | ||
additional_net_params["highway_length"] = 600 | ||
additional_net_params["on_ramps_length"] = 65 | ||
additional_net_params["off_ramps_length"] = 65 | ||
|
||
# number of lanes | ||
additional_net_params["highway_lanes"] = 4 | ||
additional_net_params["on_ramps_lanes"] = 1 | ||
additional_net_params["off_ramps_lanes"] = 1 | ||
|
||
# speed limits | ||
additional_net_params["highway_speed"] = 15 | ||
additional_net_params["on_ramps_speed"] = 10 | ||
additional_net_params["off_ramps_speed"] = 10 | ||
|
||
# ramps | ||
additional_net_params["on_ramps_pos"] = [200, 400] | ||
additional_net_params["off_ramps_pos"] = [300, 500] | ||
|
||
# probability of exiting at the next off-ramp | ||
additional_net_params["next_off_ramp_proba"] = 0.05 | ||
|
||
# inflow rates in vehs/hour | ||
HIGHWAY_INFLOW_RATE = 1000 | ||
ON_RAMPS_INFLOW_RATE = 200 | ||
|
||
|
||
def highway_ramps_example(render=None): | ||
""" | ||
Perform a simulation of vehicles on a highway section with ramps. | ||
Parameters | ||
---------- | ||
render: bool, optional | ||
Specifies whether or not to use the GUI during the simulation. | ||
Returns | ||
------- | ||
exp: flow.core.experiment.Experiment | ||
A non-RL experiment demonstrating the performance of human-driven | ||
vehicles on a highway section with on and off ramps. | ||
""" | ||
sim_params = SumoParams( | ||
render=True, | ||
emission_path="./data/", | ||
sim_step=0.2, | ||
restart_instance=True) | ||
|
||
if render is not None: | ||
sim_params.render = render | ||
|
||
vehicles = VehicleParams() | ||
vehicles.add( | ||
veh_id="human", | ||
acceleration_controller=(IDMController, { | ||
"noise": 0.2 | ||
}), | ||
car_following_params=SumoCarFollowingParams( | ||
speed_mode="obey_safe_speed", | ||
), | ||
lane_change_params=SumoLaneChangeParams(lane_change_mode=1621)) | ||
|
||
env_params = EnvParams( | ||
additional_params=ADDITIONAL_ENV_PARAMS, | ||
sims_per_step=5, | ||
warmup_steps=0) | ||
|
||
inflows = InFlows() | ||
inflows.add( | ||
veh_type="human", | ||
edge="highway_0", | ||
vehs_per_hour=HIGHWAY_INFLOW_RATE, | ||
depart_lane="free", | ||
depart_speed="max", | ||
name="highway_flow") | ||
for i in range(len(additional_net_params["on_ramps_pos"])): | ||
inflows.add( | ||
veh_type="human", | ||
edge="on_ramp_{}".format(i), | ||
vehs_per_hour=ON_RAMPS_INFLOW_RATE, | ||
depart_lane="first", | ||
depart_speed="max", | ||
name="on_ramp_flow") | ||
|
||
net_params = NetParams( | ||
inflows=inflows, | ||
additional_params=additional_net_params) | ||
|
||
initial_config = InitialConfig(spacing="uniform", perturbation=5.0) | ||
|
||
scenario = HighwayRampsScenario( | ||
name="highway-ramp", | ||
vehicles=vehicles, | ||
net_params=net_params, | ||
initial_config=initial_config) | ||
|
||
env = AccelEnv(env_params, sim_params, scenario) | ||
|
||
return Experiment(env) | ||
|
||
|
||
if __name__ == "__main__": | ||
exp = highway_ramps_example() | ||
exp.run(1, 3600, convert_to_csv=True) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,238 @@ | ||
"""Contains the highway with ramps scenario class.""" | ||
|
||
from flow.scenarios.base_scenario import Scenario | ||
from flow.core.params import InitialConfig, TrafficLightParams | ||
from collections import defaultdict | ||
from numpy import pi, sin, cos | ||
|
||
|
||
ADDITIONAL_NET_PARAMS = { | ||
# lengths of highway, on-ramps and off-ramps respectively | ||
"highway_length": 300, | ||
"on_ramps_length": 100, | ||
"off_ramps_length": 100, | ||
# number of lanes on highway, on-ramps and off-ramps respectively | ||
"highway_lanes": 1, | ||
"on_ramps_lanes": 1, | ||
"off_ramps_lanes": 1, | ||
# speed limit on highway, on-ramps and off-ramps respectively | ||
"highway_speed": 10, | ||
"on_ramps_speed": 10, | ||
"off_ramps_speed": 10, | ||
# positions of the on-ramps | ||
"on_ramps_pos": [], | ||
# positions of the off-ramps | ||
"off_ramps_pos": [], | ||
# probability for a vehicle to exit the highway at the next off-ramp | ||
"next_off_ramp_proba": 0.2, | ||
# ramps angles | ||
"angle_on_ramps": - 3 * pi / 4, | ||
"angle_off_ramps": - pi / 4 | ||
} | ||
|
||
|
||
class HighwayRampsScenario(Scenario): | ||
"""Scenario class for a highway section with on and off ramps. | ||
This scenario consists of a single or multi-lane highway network with a | ||
variable number of on-ramps and off-ramps at arbitrary positions, | ||
with arbitrary numbers of lanes. It can be used to generate periodic | ||
perturbation on a more realistic highway. | ||
Parameters in net_params: | ||
* **highway_length** : total length of the highway | ||
* **on_ramps_length** : length of each on-ramp | ||
* **off_ramps_length** : length of each off-ramp | ||
* **highway_lanes** : number of lanes on the highway | ||
* **on_ramps_lanes** : number of lanes on each on-ramp | ||
* **off_ramps_lanes** : number of lanes on each off-ramp | ||
* **highway_speed** : speed limit on the highway | ||
* **on_ramps_speed** : speed limit on each on-ramp | ||
* **off_ramps_speed** : speed limit on each off-ramp | ||
* **on_ramps_pos** : positions of the in-ramps on the highway (int list) | ||
* **off_ramps_pos** : positions of the off-ramps on the highway (int list) | ||
* **next_off_ramp_proba** : probability for a vehicle to exit the highway | ||
at the next off-ramp | ||
""" | ||
|
||
def __init__(self, | ||
name, | ||
vehicles, | ||
net_params, | ||
initial_config=InitialConfig(), | ||
traffic_lights=TrafficLightParams()): | ||
"""Initialize a highway with on and off ramps scenario.""" | ||
for p in ADDITIONAL_NET_PARAMS.keys(): | ||
if p not in net_params.additional_params: | ||
raise KeyError('Network parameter "{}" not supplied'.format(p)) | ||
|
||
# load parameters into class | ||
params = net_params.additional_params | ||
|
||
self.highway_length = params['highway_length'] | ||
self.on_ramps_length = params['on_ramps_length'] | ||
self.off_ramps_length = params['off_ramps_length'] | ||
|
||
self.highway_lanes = params['highway_lanes'] | ||
self.on_ramps_lanes = params['on_ramps_lanes'] | ||
self.off_ramps_lanes = params['off_ramps_lanes'] | ||
|
||
self.highway_speed = params['highway_speed'] | ||
self.on_ramps_speed = params['on_ramps_speed'] | ||
self.off_ramps_speed = params['off_ramps_speed'] | ||
|
||
self.on_ramps_pos = params['on_ramps_pos'] | ||
self.off_ramps_pos = params['off_ramps_pos'] | ||
|
||
self.p = params['next_off_ramp_proba'] | ||
|
||
self.angle_on_ramps = params['angle_on_ramps'] | ||
self.angle_off_ramps = params['angle_off_ramps'] | ||
|
||
# generate position of all network nodes | ||
self.ramps_pos = sorted(self.on_ramps_pos + self.off_ramps_pos) | ||
self.nodes_pos = sorted(list(set([0] + self.ramps_pos + | ||
[self.highway_length]))) | ||
|
||
# highway_pos[x] = id of the highway node whose starting position is x | ||
self.highway_pos = {x: i for i, x in enumerate(self.nodes_pos)} | ||
# ramp_pos[x] = id of the ramp node whose intersection with the highway | ||
# is at position x | ||
self.ramp_pos = {x: "on_ramp_{}".format(i) | ||
for i, x in enumerate(self.on_ramps_pos)} | ||
self.ramp_pos.update({x: "off_ramp_{}".format(i) | ||
for i, x in enumerate(self.off_ramps_pos)}) | ||
|
||
# make sure scenario is constructible | ||
if (len(self.ramps_pos) > 0 and | ||
(min(self.ramps_pos) <= 0 or | ||
max(self.ramps_pos) >= self.highway_length)): | ||
raise ValueError('All ramps positions should be positive and less ' | ||
'than highway length. Current ramps positions: {}' | ||
'. Current highway length: {}.'.format( | ||
self.ramps_pos, self.highway_length)) | ||
if len(self.ramps_pos) != len(list(set(self.ramps_pos))): | ||
raise ValueError('Two ramps positions cannot be equal.') | ||
|
||
super().__init__(name, vehicles, net_params, initial_config, | ||
traffic_lights) | ||
|
||
def specify_nodes(self, net_params): | ||
"""See parent class.""" | ||
nodes_highway = [{ | ||
"id": "highway_{}".format(i), | ||
"x": self.nodes_pos[i], | ||
"y": 0, | ||
"radius": 10 | ||
} for i in range(len(self.nodes_pos))] | ||
|
||
nodes_on_ramps = [{ | ||
"id": "on_ramp_{}".format(i), | ||
"x": x + self.on_ramps_length * cos(self.angle_on_ramps), | ||
"y": self.on_ramps_length * sin(self.angle_on_ramps) | ||
} for i, x in enumerate(self.on_ramps_pos)] | ||
|
||
nodes_off_ramps = [{ | ||
"id": "off_ramp_{}".format(i), | ||
"x": x + self.off_ramps_length * cos(self.angle_off_ramps), | ||
"y": self.off_ramps_length * sin(self.angle_off_ramps) | ||
} for i, x in enumerate(self.off_ramps_pos)] | ||
|
||
return nodes_highway + nodes_on_ramps + nodes_off_ramps | ||
|
||
def specify_edges(self, net_params): | ||
"""See parent class.""" | ||
highway_edges = [{ | ||
"id": "highway_{}".format(i), | ||
"type": "highway", | ||
"from": "highway_{}".format(i), | ||
"to": "highway_{}".format(i + 1), | ||
"length": self.nodes_pos[i + 1] - self.nodes_pos[i] | ||
} for i in range(len(self.nodes_pos) - 1)] | ||
|
||
on_ramps_edges = [{ | ||
"id": "on_ramp_{}".format(i), | ||
"type": "on_ramp", | ||
"from": "on_ramp_{}".format(i), | ||
"to": "highway_{}".format(self.highway_pos[x]), | ||
"length": self.on_ramps_length | ||
} for i, x in enumerate(self.on_ramps_pos)] | ||
|
||
off_ramps_edges = [{ | ||
"id": "off_ramp_{}".format(i), | ||
"type": "off_ramp", | ||
"from": "highway_{}".format(self.highway_pos[x]), | ||
"to": "off_ramp_{}".format(i), | ||
"length": self.off_ramps_length | ||
} for i, x in enumerate(self.off_ramps_pos)] | ||
|
||
return highway_edges + on_ramps_edges + off_ramps_edges | ||
|
||
def specify_routes(self, net_params): | ||
"""See parent class.""" | ||
def get_routes(start_node_pos): | ||
"""Compute the routes recursively.""" | ||
if start_node_pos not in self.nodes_pos: | ||
raise ValueError('{} is not a node position.'.format( | ||
start_node_pos)) | ||
|
||
id_highway_node = self.highway_pos[start_node_pos] | ||
|
||
if id_highway_node + 1 >= len(self.nodes_pos): | ||
return [(["highway_{}".format(id_highway_node - 1)], 1)] | ||
|
||
id_ramp_node = self.ramp_pos[start_node_pos] | ||
|
||
routes = get_routes(self.nodes_pos[id_highway_node + 1]) | ||
|
||
if id_ramp_node.startswith("on"): | ||
return ([ | ||
(["highway_{}".format(id_highway_node - 1)] + route, prob) | ||
for route, prob in routes if not route[0].startswith("on") | ||
] + [ | ||
([id_ramp_node] + route, prob) | ||
for route, prob in routes if not route[0].startswith("on") | ||
] + [ | ||
(route, prob) | ||
for route, prob in routes if route[0].startswith("on") | ||
]) | ||
else: | ||
return ([ | ||
(["highway_{}".format(id_highway_node - 1)] + route, | ||
(1 - self.p) * prob) | ||
for route, prob in routes if not route[0].startswith("on") | ||
] + [ | ||
(["highway_{}".format(id_highway_node - 1), id_ramp_node], | ||
self.p * prob) | ||
for route, prob in routes if not route[0].startswith("on") | ||
] + [ | ||
(route, prob) | ||
for route, prob in routes if route[0].startswith("on") | ||
]) | ||
|
||
routes = get_routes(self.nodes_pos[1]) | ||
|
||
rts = defaultdict(list) | ||
for route, prob in routes: | ||
rts[route[0]].append((route, prob)) | ||
|
||
return rts | ||
|
||
def specify_types(self, net_params): | ||
"""See parent class.""" | ||
types = [{ | ||
"id": "highway", | ||
"numLanes": self.highway_lanes, | ||
"speed": self.highway_speed | ||
}, { | ||
"id": "on_ramp", | ||
"numLanes": self.on_ramps_lanes, | ||
"speed": self.on_ramps_speed | ||
}, { | ||
"id": "off_ramp", | ||
"numLanes": self.off_ramps_lanes, | ||
"speed": self.off_ramps_speed | ||
}] | ||
|
||
return types |
Binary file modified
BIN
+0 Bytes
(100%)
tests/data/rllib_data/multi_agent/checkpoint_1/checkpoint-1
Binary file not shown.
Binary file modified
BIN
+0 Bytes
(100%)
tests/data/rllib_data/multi_agent/checkpoint_1/checkpoint-1.tune_metadata
Binary file not shown.
Oops, something went wrong.