diff --git a/flow/core/kernel/network/aimsun.py b/flow/core/kernel/network/aimsun.py index 0378d45a9..ea302ce5a 100644 --- a/flow/core/kernel/network/aimsun.py +++ b/flow/core/kernel/network/aimsun.py @@ -212,7 +212,7 @@ def generate_network(self, network): self.edgestarts = self.network.edge_starts # if no edge_starts are specified, generate default values to be used - # by the "get_x" method + # by the "get_edge" method if self.edgestarts is None: length = 0 self.edgestarts = [] @@ -222,6 +222,7 @@ def generate_network(self, network): # increment the total length of the network with the length of # the current edge length += self._edges[edge_id]['length'] + self.edgestarts.sort(key=lambda tup: tup[1]) # these optional parameters need only be used if "no-internal-links" # is set to "false" while calling sumo's netconvert function @@ -315,9 +316,9 @@ def get_junction_list(self): """See parent class.""" return self._junction_list - def get_edge(self, x): # TODO: maybe remove + def _get_edge(self, x): # TODO: maybe remove """See parent class.""" - for (edge, start_pos) in reversed(self.total_edgestarts): + for (edge, start_pos) in reversed(self.edgestarts): if x >= start_pos: return edge, x - start_pos diff --git a/flow/core/kernel/network/base.py b/flow/core/kernel/network/base.py index 3ec58d3c6..2479734b9 100644 --- a/flow/core/kernel/network/base.py +++ b/flow/core/kernel/network/base.py @@ -154,9 +154,11 @@ def get_junction_list(self): """Return the names of all junctions in the network.""" raise NotImplementedError - def get_edge(self, x): # TODO: maybe remove + def _get_edge(self, x): # TODO: maybe remove """Compute an edge and relative position from an absolute position. + The edges do not include internal edges. + Parameters ---------- x : float @@ -203,6 +205,10 @@ def prev_edge(self, edge, lane): """ raise NotImplementedError + def non_internal_length(self): + """Return the length of the network, no including internal edges.""" + raise NotImplementedError + ########################################################################### # Methods for generating initial vehicle positions. # ########################################################################### @@ -322,30 +328,12 @@ def gen_even_start_pos(self, initial_config, num_vehicles): # generate uniform starting positions while car_count < num_vehicles: # collect the position and lane number of each new vehicle - pos = self.get_edge(x) - - # ensures that vehicles are not placed in an internal junction - while pos[0] in dict(self.internal_edgestarts).keys(): - # find the location of the internal edge in total_edgestarts, - # which has the edges ordered by position - edges = [tup[0] for tup in self.total_edgestarts] - indx_edge = next( - i for i, edge in enumerate(edges) if edge == pos[0]) - - # take the next edge in the list, and place the car at the - # beginning of this edge - if indx_edge == len(edges) - 1: - next_edge_pos = self.total_edgestarts[0] - else: - next_edge_pos = self.total_edgestarts[indx_edge + 1] - - x = next_edge_pos[1] - pos = (next_edge_pos[0], 0) + pos = self._get_edge(x) # ensures that you are in an acceptable edge while pos[0] not in available_edges: x = (x + self.edge_length(pos[0])) % self.non_internal_length() - pos = self.get_edge(x) + pos = self._get_edge(x) # ensure that in variable lane settings vehicles always start a # vehicle's length away from the start of the edge. This, however, @@ -358,7 +346,7 @@ def gen_even_start_pos(self, initial_config, num_vehicles): (num_vehicles - car_count) # place vehicles side-by-side in all available lanes on this edge - for lane in range(min([self.num_lanes(pos[0]), lanes_distr])): + for lane in range(min(self.num_lanes(pos[0]), lanes_distr)): car_count += 1 startpositions.append(pos) startlanes.append(lane) @@ -366,7 +354,8 @@ def gen_even_start_pos(self, initial_config, num_vehicles): if car_count == num_vehicles: break - x = (x + increment + VEHICLE_LENGTH + min_gap) % self.non_internal_length() + x = (x + increment + VEHICLE_LENGTH + min_gap) \ + % self.non_internal_length() # add a perturbation to each vehicle, while not letting the vehicle # leave its current edge diff --git a/flow/core/kernel/network/traci.py b/flow/core/kernel/network/traci.py index c9ac80772..e7c659e7b 100644 --- a/flow/core/kernel/network/traci.py +++ b/flow/core/kernel/network/traci.py @@ -168,7 +168,7 @@ def generate_network(self, network): self.edgestarts = self.network.edge_starts # if no edge_starts are specified, generate default values to be used - # by the "get_x" method + # by the "get_edge" method if self.edgestarts is None: length = 0 self.edgestarts = [] @@ -178,17 +178,12 @@ def generate_network(self, network): # increment the total length of the network with the length of # the current edge length += self._edges[edge_id]['length'] + # sort the edgestarts by position + self.edgestarts.sort(key=lambda tup: tup[1]) - # these optional parameters need only be used if "no-internal-links" - # is set to "false" while calling sumo's netconvert function - self.internal_edgestarts = self.network.internal_edge_starts - self.internal_edgestarts_dict = dict(self.internal_edgestarts) - - # total_edgestarts and total_edgestarts_dict contain all of the above - # edges, with the former being ordered by position - self.total_edgestarts = self.edgestarts + self.internal_edgestarts - self.total_edgestarts.sort(key=lambda tup: tup[1]) - + # total_edgestarts and total_edgestarts_dict contain all main and + # internal edges, with the former being ordered by position + self.total_edgestarts = self._gen_internal_edgestarts() self.total_edgestarts_dict = dict(self.total_edgestarts) self.__length = sum( @@ -247,9 +242,9 @@ def close(self): except OSError: pass - def get_edge(self, x): + def _get_edge(self, x): """See parent class.""" - for (edge, start_pos) in reversed(self.total_edgestarts): + for (edge, start_pos) in reversed(self.edgestarts): if x >= start_pos: return edge, x - start_pos @@ -262,7 +257,7 @@ def get_x(self, edge, position): if edge[0] == ':': try: - return self.internal_edgestarts_dict[edge] + position + return self.total_edgestarts_dict[edge] + position except KeyError: # in case several internal links are being generalized for # by a single element (for backwards compatibility) @@ -891,8 +886,11 @@ def _import_edges_from_net(self, net_params): net_data[edge_id]['lanes'] = 0 for i, lane in enumerate(edge): net_data[edge_id]['lanes'] += 1 + # choose the largest length across lanes as the edge length + net_data[edge_id]['length'] = max( + net_data[edge_id].get('length', 0), + float(lane.attrib['length'])) if i == 0: - net_data[edge_id]['length'] = float(lane.attrib['length']) if net_data[edge_id]['speed'] is None \ and 'speed' in lane.attrib: net_data[edge_id]['speed'] = float( @@ -935,3 +933,60 @@ def _import_edges_from_net(self, net_params): connection_data = {'next': next_conn_data, 'prev': prev_conn_data} return net_data, connection_data + + def _gen_internal_edgestarts(self): + """Create a list of internal edgestarts. + + This method also increments the regular edgestarts so that they do not + overlap with the internal edgestarts. + + Returns + ------- + list of (str, float) + list of all edge names and starting positions, + ex: [(internal0, pos0), (internal1, pos1), ...] + """ + edgestarts = deepcopy(self.edgestarts) + + # the length that needs to be added to all next edges in the list of + # sorted edges + prev_junction_lengths = 0 + + internal_edgestarts = [] + for i in range(len(edgestarts)): + edge, pos = edgestarts[i] + + # increment the position with the junction length increment, and + # add it back to the edgestarts + pos += prev_junction_lengths + edgestarts[i] = (edge, pos) + + # collect the names of all next junctions from the current edge + all_next_edges = [] + for lane in range(self.num_lanes(edge)): + next_edge = self.next_edge(edge, lane) + for edge_i, _ in next_edge: + if edge_i not in all_next_edges: + all_next_edges.append(edge_i) + + # In the case there are no next edges from the current edge (e.g. + # end of a highway), stop. + if len(all_next_edges) == 0: + continue + + # get the maximum length of the edges, and add it to the junction + # increment length + max_length = max(self.edge_length(e) for e in all_next_edges) + prev_junction_lengths += max_length + + # add the junctions with the position being immediately after the + # current edge + next_pos = pos + self.edge_length(edge) + for next_edge in all_next_edges: + internal_edgestarts.append((next_edge, next_pos)) + + # combine and sort the edgestarts and internal edgestarts + total_edgestarts = edgestarts + internal_edgestarts + total_edgestarts.sort(key=lambda tup: tup[1]) + + return total_edgestarts diff --git a/flow/networks/base.py b/flow/networks/base.py index 58964348f..9043e8156 100644 --- a/flow/networks/base.py +++ b/flow/networks/base.py @@ -136,7 +136,7 @@ class file If the type variable is None, then no types are available within the network. Furthermore, a proper example of this variable being used can - be found under `specify_types` in flow/networks/loop.py. + be found under `specify_types` in flow/networks/ring.py. Note that, if the network is meant to generate the network from an OpenStreetMap or template file, this variable is set to None @@ -161,13 +161,6 @@ class file the edge/intersection/internal_link, and the second value is the distance of the link from some global reference, i.e. [(link_0, pos_0), (link_1, pos_1), ...] - internal_edge_starts : list of (str, float) - A variable similar to `edge_starts` but for junctions within the - network. If no junctions are available, this variable will return the - default variable: `[(':', -1)]` needed by sumo simulations. - intersection_edge_starts : list of (str, float) - A variable similar to `edge_starts` but for intersections within - the network. This variable will be deprecated in future releases. Example ------- @@ -293,17 +286,6 @@ class file >>> print(network.edge_starts) >>> [('bottom', 0), ('right', 57.5), ('top', 115.0), ('left', 172.5)] - - Finally, the ring network does not contain any junctions or intersections, - and as a result the `internal_edge_starts` and `intersection_edge_starts` - attributes are both set to None. For an example of a network with junctions - and intersections, please refer to: flow/networks/figure_eight.py. - - >>> print(network.internal_edge_starts) - >>> [(':', -1)] - - >>> print(network.intersection_edge_starts) - >>> [] """ def __init__(self, @@ -385,7 +367,7 @@ def __init__(self, # optional parameters, used to get positions from some global reference self.edge_starts = self.specify_edge_starts() - self.internal_edge_starts = self.specify_internal_edge_starts() + self.internal_edge_starts = [] # this will be deprecated self.intersection_edge_starts = [] # this will be deprecated # TODO: convert to property @@ -408,29 +390,6 @@ def specify_edge_starts(self): """ return None - # TODO: convert to property - def specify_internal_edge_starts(self): - """Define the edge starts for internal edge nodes. - - This is meant to provide some global reference frame for the internal - edges in the network. - - These edges are the result of finite-length connections between road - sections. This methods does not need to be specified if "no-internal- - links" is set to True in net_params. - - By default, all internal edge starts are given a position of -1. This - may be overridden; however, in general we do not worry about internal - edges and junctions in large networks. - - Returns - ------- - list of (str, float) - list of internal junction names and starting positions, - ex: [(internal0, pos0), (internal1, pos1), ...] - """ - return [(':', -1)] - # TODO: convert to property def specify_nodes(self, net_params): """Specify the attributes of nodes in the network. diff --git a/flow/networks/figure_eight.py b/flow/networks/figure_eight.py index 8306254b6..f95b65dad 100755 --- a/flow/networks/figure_eight.py +++ b/flow/networks/figure_eight.py @@ -70,13 +70,6 @@ def __init__(self, ring_radius = net_params.additional_params["radius_ring"] self.ring_edgelen = ring_radius * np.pi / 2. self.intersection_len = 2 * ring_radius - self.junction_len = 2.9 + 3.3 * net_params.additional_params["lanes"] - self.inner_space_len = 0.28 - - # # instantiate "length" in net params - # net_params.additional_params["length"] = \ - # 6 * self.ring_edgelen + 2 * self.intersection_len + \ - # 2 * self.junction_len + 10 * self.inner_space_len super().__init__(name, vehicles, net_params, initial_config, traffic_lights) @@ -225,39 +218,11 @@ def specify_connections(self, net_params): def specify_edge_starts(self): """See base class.""" edgestarts = [ - ("bottom", self.inner_space_len), - ("top", self.intersection_len / 2 + self.junction_len + - self.inner_space_len), - ("upper_ring", self.intersection_len + self.junction_len + - 2 * self.inner_space_len), - ("right", self.intersection_len + 3 * self.ring_edgelen - + self.junction_len + 3 * self.inner_space_len), - ("left", 3 / 2 * self.intersection_len + 3 * self.ring_edgelen - + 2 * self.junction_len + 3 * self.inner_space_len), - ("lower_ring", 2 * self.intersection_len + 3 * self.ring_edgelen - + 2 * self.junction_len + 4 * self.inner_space_len)] + ("bottom", 0), + ("top", self.intersection_len / 2), + ("upper_ring", self.intersection_len), + ("right", self.intersection_len + 3 * self.ring_edgelen), + ("left", 3 / 2 * self.intersection_len + 3 * self.ring_edgelen), + ("lower_ring", 2 * self.intersection_len + 3 * self.ring_edgelen)] return edgestarts - - def specify_internal_edge_starts(self): - """See base class.""" - internal_edgestarts = [ - (":bottom", 0), - (":center_{}".format(self.net_params.additional_params['lanes']), - self.intersection_len / 2 + self.inner_space_len), - (":top", self.intersection_len + self.junction_len + - self.inner_space_len), - (":right", self.intersection_len + 3 * self.ring_edgelen - + self.junction_len + 2 * self.inner_space_len), - (":center_0", 3 / 2 * self.intersection_len + 3 * self.ring_edgelen - + self.junction_len + 3 * self.inner_space_len), - (":left", 2 * self.intersection_len + 3 * self.ring_edgelen - + 2 * self.junction_len + 3 * self.inner_space_len), - # for aimsun - ('bottom_to_top', - self.intersection_len / 2 + self.inner_space_len), - ('right_to_left', - + self.junction_len + 3 * self.inner_space_len), - ] - - return internal_edgestarts diff --git a/flow/networks/merge.py b/flow/networks/merge.py index 74d71422f..bef9841e2 100644 --- a/flow/networks/merge.py +++ b/flow/networks/merge.py @@ -195,24 +195,11 @@ def specify_edge_starts(self): premerge = self.net_params.additional_params["pre_merge_length"] postmerge = self.net_params.additional_params["post_merge_length"] - edgestarts = [("inflow_highway", 0), ("left", INFLOW_EDGE_LEN + 0.1), - ("center", INFLOW_EDGE_LEN + premerge + 22.6), - ("inflow_merge", - INFLOW_EDGE_LEN + premerge + postmerge + 22.6), - ("bottom", - 2 * INFLOW_EDGE_LEN + premerge + postmerge + 22.7)] + edgestarts = [ + ("inflow_highway", 0), + ("left", INFLOW_EDGE_LEN), + ("center", INFLOW_EDGE_LEN + premerge), + ("inflow_merge", INFLOW_EDGE_LEN + premerge + postmerge), + ("bottom", 2 * INFLOW_EDGE_LEN + premerge + postmerge)] return edgestarts - - def specify_internal_edge_starts(self): - """See parent class.""" - premerge = self.net_params.additional_params["pre_merge_length"] - postmerge = self.net_params.additional_params["post_merge_length"] - - internal_edgestarts = [ - (":left", INFLOW_EDGE_LEN), (":center", - INFLOW_EDGE_LEN + premerge + 0.1), - (":bottom", 2 * INFLOW_EDGE_LEN + premerge + postmerge + 22.6) - ] - - return internal_edgestarts diff --git a/flow/networks/multi_ring.py b/flow/networks/multi_ring.py index 9e5e65a53..9eae111a7 100644 --- a/flow/networks/multi_ring.py +++ b/flow/networks/multi_ring.py @@ -115,7 +115,7 @@ def gen_custom_start_pos(cls, net_params, initial_config, num_vehicles): # generate uniform starting positions while car_count < num_vehicles: # collect the position and lane number of each new vehicle - pos = cls.get_edge(x) + pos = cls._get_edge(x) # place vehicles side-by-side in all available lanes on this edge for lane in range(min(cls.num_lanes(pos[0]), lanes_distr)): diff --git a/flow/networks/ring.py b/flow/networks/ring.py index de4d17503..9529a2fe9 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', @@ -59,7 +59,7 @@ def __init__(self, net_params, initial_config=InitialConfig(), traffic_lights=TrafficLightParams()): - """Initialize a ring scenario.""" + """Initialize a ring network.""" for p in ADDITIONAL_NET_PARAMS.keys(): if p not in net_params.additional_params: raise KeyError('Network parameter "{}" not supplied'.format(p)) @@ -194,23 +194,10 @@ def specify_routes(self, net_params): def specify_edge_starts(self): """See parent class.""" ring_length = self.net_params.additional_params["length"] - junction_length = 0.1 # length of inter-edge junctions edgestarts = [("bottom", 0), - ("right", 0.25 * ring_length + junction_length), - ("top", 0.5 * ring_length + 2 * junction_length), - ("left", 0.75 * ring_length + 3 * junction_length)] - - return edgestarts - - def specify_internal_edge_starts(self): - """See parent class.""" - ring_length = self.net_params.additional_params["length"] - junction_length = 0.1 # length of inter-edge junctions - - edgestarts = [(":right_0", 0.25 * ring_length), - (":top_0", 0.5 * ring_length + junction_length), - (":left_0", 0.75 * ring_length + 2 * junction_length), - (":bottom_0", ring_length + 3 * junction_length)] + ("right", 0.25 * ring_length), + ("top", 0.5 * ring_length), + ("left", 0.75 * ring_length)] return edgestarts diff --git a/tests/fast_tests/test_controllers.py b/tests/fast_tests/test_controllers.py index 1e5c6057d..f09befe1d 100644 --- a/tests/fast_tests/test_controllers.py +++ b/tests/fast_tests/test_controllers.py @@ -523,7 +523,7 @@ def test_find_intersection_dist(self): for veh_id in ids ] - expected = [-10, 0, 23.1, 34.7, 46.3] + expected = [-10, 0, 23., 34.5, 46.] np.testing.assert_array_almost_equal(requested, expected) diff --git a/tests/fast_tests/test_scenario_base_class.py b/tests/fast_tests/test_scenario_base_class.py index e563c07ab..2b18f59be 100644 --- a/tests/fast_tests/test_scenario_base_class.py +++ b/tests/fast_tests/test_scenario_base_class.py @@ -22,6 +22,8 @@ os.environ["TEST_FLAG"] = "True" +JUNCTION_LENGTH = 0.6 + class NoRouteNetwork(RingNetwork): """A network with no routes. @@ -52,12 +54,12 @@ def test_getx(self): # test for an edge in the lanes edge_1 = "bottom" pos_1 = 4.72 - self.assertAlmostEqual(self.env.k.network.get_x(edge_1, pos_1), 5) + self.assertAlmostEqual(self.env.k.network.get_x(edge_1, pos_1), 4.72) # test for an edge in the internal links - edge_2 = ":bottom" + edge_2 = ":top_0" pos_2 = 0.1 - self.assertAlmostEqual(self.env.k.network.get_x(edge_2, pos_2), 0.1) + self.assertAlmostEqual(self.env.k.network.get_x(edge_2, pos_2), 69.5) def test_error(self): edge = '' @@ -85,12 +87,7 @@ def test_get_edge(self): # test for a position in the lanes x1 = 5 self.assertTupleEqual( - self.env.k.network.get_edge(x1), ("bottom", 4.72)) - - # test for a position in the internal links - x2 = 0.1 - self.assertTupleEqual( - self.env.k.network.get_edge(x2), (":bottom", 0.1)) + self.env.k.network._get_edge(x1), ("bottom", 5)) class TestEvenStartPos(unittest.TestCase): @@ -157,6 +154,11 @@ def test_base(self): veh_pos = np.array([self.env.k.vehicle.get_x_by_id(veh_id) for veh_id in ids]) + # to account for the additions to the positions by the junctions + veh_pos[veh_pos > (230/4)] -= JUNCTION_LENGTH + veh_pos[veh_pos > (230/2)] -= JUNCTION_LENGTH + veh_pos[veh_pos > (230*3/4)] -= JUNCTION_LENGTH + # difference in position between the nth vehicle and the vehicle ahead # of it nth_headway = np.mod( @@ -190,6 +192,11 @@ def test_x0(self): veh_pos = np.array([self.env.k.vehicle.get_x_by_id(veh_id) for veh_id in ids]) + # to account for the additions to the positions by the junctions + veh_pos[veh_pos > (230/4)] -= JUNCTION_LENGTH + veh_pos[veh_pos > (230/2)] -= JUNCTION_LENGTH + veh_pos[veh_pos > (230*3/4)] -= JUNCTION_LENGTH + # difference in position between the nth vehicle and the vehicle ahead # of it nth_headway = np.mod( @@ -221,6 +228,11 @@ def test_bunching(self): veh_pos = np.array([self.env.k.vehicle.get_x_by_id(veh_id) for veh_id in ids]) + # to account for the additions to the positions by the junctions + veh_pos[veh_pos > (230/4)] -= JUNCTION_LENGTH + veh_pos[veh_pos > (230/2)] -= JUNCTION_LENGTH + veh_pos[veh_pos > (230*3/4)] -= JUNCTION_LENGTH + # difference in position between the nth vehicle and the vehicle ahead # of it nth_headway = np.mod( @@ -256,6 +268,11 @@ def test_bunching_too_small(self): veh_pos = np.array([self.env.k.network.get_x(pos[0], pos[1]) for pos in startpos]) + # to account for the additions to the positions by the junctions + veh_pos[veh_pos > (230/4)] -= JUNCTION_LENGTH + veh_pos[veh_pos > (230/2)] -= JUNCTION_LENGTH + veh_pos[veh_pos > (230*3/4)] -= JUNCTION_LENGTH + # difference in position between the nth vehicle and the vehicle ahead # of it nth_headway = np.mod( @@ -288,10 +305,15 @@ def test_lanes_distribution(self): ids = self.env.k.vehicle.get_ids() veh_pos = [] for i in range(lanes): - veh_pos.append([ + veh_pos.append(np.array([ self.env.k.vehicle.get_x_by_id(veh_id) for veh_id in ids if self.env.k.vehicle.get_lane(veh_id) == i - ]) + ])) + + # to account for the additions to the positions by the junctions + veh_pos[-1][veh_pos[-1] > (230 / 4)] -= JUNCTION_LENGTH + veh_pos[-1][veh_pos[-1] > (230 / 2)] -= JUNCTION_LENGTH + veh_pos[-1][veh_pos[-1] > (230 * 3 / 4)] -= JUNCTION_LENGTH # check that the vehicles are uniformly distributed in the number of # requested lanes @@ -430,73 +452,6 @@ def test_num_vehicles(self): self.assertEqual(len(lanes), 10) -class TestEvenStartPosInternalLinks(unittest.TestCase): - """ - Tests the function gen_even_start_pos when internal links are being used. - Ensures that all vehicles are evenly spaced except when a vehicle is - supposed to be placed at an internal link, in which case the vehicle is - placed right outside the internal link. - """ - - def setUp(self): - # place 15 vehicles in the network (we need at least more than 1) - vehicles = VehicleParams() - vehicles.add( - veh_id="test", - acceleration_controller=(IDMController, {}), - routing_controller=(ContinuousRouter, {}), - car_following_params=SumoCarFollowingParams( - min_gap=0 - ), - num_vehicles=15) - - initial_config = InitialConfig(x0=150) - - # create the environment and network classes for a ring road - self.env, _, _ = figure_eight_exp_setup( - initial_config=initial_config, vehicles=vehicles) - - def tearDown(self): - # terminate the traci instance - self.env.terminate() - - # free data used by the class - self.env = None - - def test_even_start_pos_internal(self): - # get the positions of all vehicles - ids = self.env.k.vehicle.get_ids() - veh_pos = np.array([self.env.k.vehicle.get_x_by_id(veh_id) - for veh_id in ids]) - - # difference in position between the nth vehicle and the vehicle ahead - # of it - nth_headway = np.mod( - np.append(veh_pos[1:], veh_pos[0]) - veh_pos, - self.env.k.network.non_internal_length()) - - try: - # if all element are equal, there should only be one unique value - self.assertEqual(np.unique(np.around(nth_headway, 2)).size, 1) - except AssertionError: - # check that, if not all vehicles are equally spaced, that the - # vehicle that is not equally spaced is right after an internal - # link, and at position 0 - for i in range(len(nth_headway) - 1): - if nth_headway[i] - np.mean(nth_headway) > 0.001: - # if not, check that the last or first vehicle is right - # after an internal link, on position 0 - pos = [ - self.env.k.vehicle.get_x_by_id(veh_id) - for veh_id in [ids[i + 1], ids[i]] - ] - rel_pos = [ - self.env.k.network.get_edge(pos_i)[1] for pos_i in pos - ] - - self.assertTrue(np.any(np.array(rel_pos) == 0)) - - class TestRandomStartPos(unittest.TestCase): """ Tests the function gen_random_start_pos in networks/base.py. diff --git a/tests/fast_tests/test_vehicles.py b/tests/fast_tests/test_vehicles.py index 485a6a072..df87fecbd 100644 --- a/tests/fast_tests/test_vehicles.py +++ b/tests/fast_tests/test_vehicles.py @@ -248,7 +248,7 @@ def test_no_junctions_ring(self): # check the lane tailways is outputting the right values actual_lane_tail = env.k.vehicle.get_lane_tailways("test_0") - expected_lane_tail = [28.577143] * 3 + expected_lane_tail = [28.277143] * 3 np.testing.assert_array_almost_equal(actual_lane_tail, expected_lane_tail) diff --git a/tutorials/tutorial05_networks.ipynb b/tutorials/tutorial05_networks.ipynb index 653ee099d..cd8a188dc 100644 --- a/tutorials/tutorial05_networks.ipynb +++ b/tutorials/tutorial05_networks.ipynb @@ -330,15 +330,13 @@ "\n", "Other optional abstract methods within the base network class include:\n", "\n", - "* **specify_internal_edge_starts**: defines the edge starts for internal edge nodes caused by finite length connections between road section\n", - "* **specify_intersection_edge_starts**: defines edge starts for intersections with respect to some global reference frame. Only needed by environments with intersections.\n", "* **gen_custom_start_pos**: used to generate a user defined set of starting positions for vehicles in the network\n", "\n", "### 2.2 Specifying the Starting Position of Edges\n", "\n", "All of the above functions starting with \"specify\" receive no inputs, and return a list of tuples in which the first element of the tuple is the name of the edge/intersection/internal_link, and the second value is the distance of the link from some global reference, i.e. [(link_0, pos_0), (link_1, pos_1), ...].\n", "\n", - "The data specified in `specify_edge_starts` is used to provide a \"global\" sense of the location of vehicles, in one dimension. This is done either through the `get_x_by_id` method within an environment, or the `get_absolute_position` method in the `Vehicles` object within an environment. The `specify_internal_edge_starts` allows us to do the same to junctions/internal links when they are also located within the network (this is not the case for the ring road).\n", + "The data specified in `specify_edge_starts` is used to provide a \"global\" sense of the location of vehicles, in one dimension. This is done through the `get_x_by_id` method within an environment. The positions of the junctions are then added internally by the framework.\n", "\n", "In section 1, we created a network with 4 edges named: \"edge0\", \"edge1\", \"edge2\", and \"edge3\". We assume that the edge titled \"edge0\" is the origin, and accordingly the position of the edge start of \"edge0\" is 0. The next edge, \"edge1\", begins a quarter of the length of the network from the starting point of edge \"edge0\", and accordingly the position of its edge start is radius * pi/2. This process continues for each of the edges. We can then define the starting position of the edges as follows:" ] @@ -501,7 +499,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.7" + "version": "3.6.8" } }, "nbformat": 4,