Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions examples/sumo/highway.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,13 @@ def highway_example(sumo_binary=None):
inflow = InFlows()
inflow.add(
veh_type="human",
edge="highway",
edge="highway_0",
probability=0.25,
departLane="free",
departSpeed=20)
inflow.add(
veh_type="human2",
edge="highway",
edge="highway_0",
probability=0.25,
departLane="free",
departSpeed=20)
Expand Down
34 changes: 18 additions & 16 deletions flow/core/vehicles.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,25 +190,25 @@ def add(self,

self.initial.append({
"veh_id":
veh_id,
veh_id,
"acceleration_controller":
acceleration_controller,
acceleration_controller,
"lane_change_controller":
lane_change_controller,
lane_change_controller,
"routing_controller":
routing_controller,
routing_controller,
"initial_speed":
initial_speed,
initial_speed,
"num_vehicles":
num_vehicles,
num_vehicles,
"speed_mode":
speed_mode,
speed_mode,
"lane_change_mode":
lane_change_mode,
lane_change_mode,
"sumo_car_following_params":
sumo_car_following_params,
sumo_car_following_params,
"sumo_lc_params":
sumo_lc_params
sumo_lc_params
})

# this is used to return the actual headways from the vehicles class
Expand Down Expand Up @@ -1119,7 +1119,7 @@ def _multi_lane_headways_util(self, veh_id, edge_dict, num_edges, env):
edge_dict : dict < list<tuple> >
Key = Edge name
Index = lane index
Element = sorted list of (vehicle id, position)
Element = list sorted by position of (vehicle id, position)

Returns
-------
Expand All @@ -1138,6 +1138,7 @@ def _multi_lane_headways_util(self, veh_id, edge_dict, num_edges, env):
"""
this_pos = self.get_position(veh_id)
this_edge = self.get_edge(veh_id)
this_lane = self.get_lane(veh_id)
num_lanes = env.scenario.num_lanes(this_edge)

# set default values for all output values
Expand All @@ -1156,7 +1157,8 @@ def _multi_lane_headways_util(self, veh_id, edge_dict, num_edges, env):

# if you are at the end or the front of the edge, the lane
# leader is in the edges in front of you
if index < len(positions) - 1:
if (lane == this_lane and index < len(positions) - 1) \
or (lane != this_lane and index < len(positions)):
# check if the index does not correspond to the current
# vehicle
if ids[index] == veh_id:
Expand All @@ -1165,15 +1167,15 @@ def _multi_lane_headways_util(self, veh_id, edge_dict, num_edges, env):
self.get_length(leader[lane]))
else:
leader[lane] = ids[index]
headway[lane] = positions[index] - this_pos \
- self.get_length(leader[lane])
headway[lane] = (positions[index] - this_pos
- self.get_length(leader[lane]))

# you are in the back of the queue, the lane follower is in the
# edges behind you
if index > 0:
follower[lane] = ids[index - 1]
tailway[lane] = this_pos - positions[index - 1] \
- self.get_length(veh_id)
tailway[lane] = (this_pos - positions[index - 1]
- self.get_length(veh_id))

# if lane leader not found, check next edges
if leader[lane] == "":
Expand Down
12 changes: 8 additions & 4 deletions flow/scenarios/base_scenario.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,11 @@ def __init__(self,
])

# generate starting position for vehicles in the network
positions, lanes = self.generate_starting_positions()
kwargs = initial_config.additional_params
positions, lanes = self.generate_starting_positions(
num_vehicles=vehicles.num_vehicles,
**kwargs
)

# create the sumo configuration files using the generator class
cfg_name = self.generator.generate_cfg(self.net_params,
Expand Down Expand Up @@ -403,7 +407,7 @@ def gen_random_start_pos(self, initial_config, num_vehicles, **kwargs):
"""
(x0, min_gap, bunching, lanes_distr, available_length,
available_edges, initial_config) = self._get_start_pos_util(
initial_config, num_vehicles, **kwargs)
initial_config, num_vehicles, **kwargs)

# extra space a vehicle needs to cover from the start of an edge to be
# fully in the edge and not risk having a gap with a vehicle behind it
Expand Down Expand Up @@ -433,7 +437,7 @@ def gen_random_start_pos(self, initial_config, num_vehicles, **kwargs):
for i in range(num_vehicles):
edge_i = available_edges[edge_indx]
pos_i = (init_absolute_pos[i] - decrement) % (
self.edge_length(edge_i) - efs)
self.edge_length(edge_i) - efs)
lane_i = int(((init_absolute_pos[i] - decrement) - pos_i) /
(self.edge_length(edge_i) - efs))

Expand All @@ -446,7 +450,7 @@ def gen_random_start_pos(self, initial_config, num_vehicles, **kwargs):

edge_i = available_edges[edge_indx]
pos_i = (init_absolute_pos[i] - decrement) % (
self.edge_length(edge_i) - efs)
self.edge_length(edge_i) - efs)

lane_i = int(((init_absolute_pos[i] - decrement) - pos_i) /
(self.edge_length(edge_i) - efs))
Expand Down
45 changes: 27 additions & 18 deletions flow/scenarios/highway/gen.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""Contains the highway scenario class."""

from flow.core.generator import Generator
import numpy as np


class HighwayGenerator(Generator):
Expand All @@ -20,30 +21,34 @@ def __init__(self, net_params, base):
def specify_nodes(self, net_params):
"""See parent class."""
length = net_params.additional_params["length"]
num_edges = net_params.additional_params.get("num_edges", 1)
segment_lengths = np.linspace(0, length, num_edges+1)

nodes = [{
"id": "begin",
"x": repr(0),
"y": repr(0)
}, {
"id": "end",
"x": repr(length),
"y": repr(0)
}]
nodes = []
for i in range(num_edges+1):
nodes += [{
"id": "edge_{}".format(i),
"x": repr(segment_lengths[i]),
"y": repr(0)
}]

return nodes

def specify_edges(self, net_params):
"""See parent class."""
length = net_params.additional_params["length"]

edges = [{
"id": "highway",
"type": "highwayType",
"from": "begin",
"to": "end",
"length": repr(length)
}]
num_edges = net_params.additional_params.get("num_edges", 1)
segment_length = length/float(num_edges)

edges = []
for i in range(num_edges):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sort of at a high level, why do we want to cut the highway into sections?

Copy link
Member Author

@eugenevinitsky eugenevinitsky Sep 17, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This lets me write tests for the methods that get leaders for subsequent edges; doing this to highways seemed like the cleanest way to test the non-junction version of this

edges += [{
"id": "highway_{}".format(i),
"type": "highwayType",
"from": "edge_{}".format(i),
"to": "edge_{}".format(i+1),
"length": repr(segment_length)
}]

return edges

Expand All @@ -62,6 +67,10 @@ def specify_types(self, net_params):

def specify_routes(self, net_params):
"""See parent class."""
rts = {"highway": ["highway"]}
num_edges = net_params.additional_params.get("num_edges", 1)
rts = {}
for i in range(num_edges):
rts["highway_{}".format(i)] = ["highway_{}".format(j) for
j in range(i, num_edges)]

return rts
29 changes: 28 additions & 1 deletion flow/scenarios/highway/scenario.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
"lanes": 4,
# speed limit for all edges
"speed_limit": 30,
# number of edges to divide the highway into
"num_edges": 1
}


Expand Down Expand Up @@ -39,11 +41,36 @@ def __init__(self,

self.length = net_params.additional_params["length"]
self.lanes = net_params.additional_params["lanes"]
self.num_edges = net_params.additional_params.get("num_edges", 1)

super().__init__(name, generator_class, vehicles, net_params,
initial_config, traffic_lights)

def specify_edge_starts(self):
"""See parent class."""
edgestarts = [("highway", 0)]
edgestarts = [("highway_{}".format(i), 0)
for i in range(self.num_edges)]
return edgestarts

def gen_custom_start_pos(self, initial_config, num_vehicles, **kwargs):
"""Generate a user defined set of starting positions.
This method is just used for testing.

Parameters
----------
initial_config : InitialConfig type
see flow/core/params.py
num_vehicles : int
number of vehicles to be placed on the network
kwargs : dict
extra components, usually defined during reset to overwrite initial
config parameters

Returns
-------
startpositions : list of tuple (float, float)
list of start positions [(edge0, pos0), (edge1, pos1), ...]
startlanes : list of int
list of start lanes
"""
return kwargs["start_positions"], kwargs["start_lanes"]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we want this for all scenarios? if so, would be a good idea to create an issue about this

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like a one-off at the moment? I don't see a compelling case for carefully specifying the initial position of vehicles but happy to be convinced otherwise

Loading