Chacha-Chen / MPLight

56 stars 18 forks source link

Pressure Calculations #4

Closed oroojlooy closed 4 years ago

oroojlooy commented 4 years ago

In anon_env.py, to get the coming_vehicle and leaving_vehicle, in functions _get_coming_vehicles and _get_leaving_vehicles, two lists self.list_entering_lanes and self.list_exiting_lanes are used which for a 1*1 grid with two lanes (dic_traffic_env_conf["LANE_NUM"] = { "LEFT": 1, "STRAIGHT": 1 } , they are:

self.list_entering_lanes = ['road_0_1_0_0', 'road_0_1_0_1', 'road_2_1_2_0', 'road_2_1_2_1', 'road_1_2_3_0', 'road_1_2_3_1', 'road_1_0_1_0', 'road_1_0_1_1']
self.list_exiting_lanes = ['road_1_1_0_0', 'road_1_1_0_1', 'road_1_1_2_0', 'road_1_1_2_1', 'road_1_1_3_0', 'road_1_1_3_1', 'road_1_1_1_0', 'road_1_1_1_1']

In order to get the pressure of each movement, we need to get |coming_vehicle - leaving_vehicle| of all possible allowed traffic-movement of that phase. For example, for phase=WE-Left, we need the traffic of road_0_1_0_0 (coming traffic ) to road_1_1_2_0 (leaving traffic) and road_2_1_2_0 (coming traffic) to road_1_1_3_0. Having this information, one can easily get the pressure.

Although, in the _get_pressure function:

    def _get_pressure(self):
        return [self.dic_lane_waiting_vehicle_count_current_step[lane] for lane in self.list_entering_lanes] + [-self.dic_lane_waiting_vehicle_count_current_step[lane] for lane in self.list_exiting_lanes]

it deducts the two vectors from each other, and it does not care about the Left-turns. For example, for the to-East movement, it only deducts road_0_1_0_0 from road_1_1_0_0 and road_0_1_0_1 from road_1_1_0_1, so it does not obtain the pressure for the left turns. Same happens with the other movements. So, basically, it only considers straight-traffic-movement. Am I missing something?

oroojlooy commented 4 years ago

One more question, I assume the index oflane is based on dic_traffic_env_conf["LANE_NUM"]. For example, if dic_traffic_env_conf["LANE_NUM"] = { "LEFT": 2, "STRAIGHT": 1, i.e., 0 = Left, , 1=Left, 2=Straight. Although, I see that when the list of the lanes is created:

        self.list_entering_lanes = []
        for approach in self.list_approachs:
            self.list_entering_lanes += [self.dic_entering_approach_to_edge[approach] + '_' + str(i) for i in
                                         range(sum(list(dic_traffic_env_conf["LANE_NUM"].values())))]

it does not consider that dictionary, and only use that to count the number of the lanes, and it is not known which lane is Left or Straight.

So, the question is, how do you know which lane index is for Left and Straight?

Chacha-Chen commented 4 years ago

Lane number is defined from inner to outer. So 0 means the left lane, 1 means the straight lane and 2 means the right turn lane. We did not consider right turn lane. But we considered both straight and left-turn lane. (If there are 3 lanes in each road)

oroojlooy commented 4 years ago

Can you also please explain the pressure?

Chacha-Chen commented 4 years ago
  1. left turn and straight are both considered.
  2. There should be a sum operation later on the dic_feature[‘pressure"]
oroojlooy commented 4 years ago

Yes, there is dic_reward['pressure'] = np.absolute(np.sum(self.dic_feature["pressure"])) later in the code which obtains the sum of pressure, but that is not my point at all. It is not clear how the pressure for each traffic movement is calculated.

Consider the _get_pressure function:

    def _get_pressure(self):
        return [self.dic_lane_waiting_vehicle_count_current_step[lane] for lane in self.list_entering_lanes] + [-self.dic_lane_waiting_vehicle_count_current_step[lane] for lane in self.list_exiting_lanes]

it deducts the two vectors from each other, which each value of that is the number of waiting cars in that lane. The lanes in the list_entering_lanes list and the lanes in the list_exiting_lanes list are:

self.list_entering_lanes = ['road_0_1_0_0', 'road_0_1_0_1', 'road_2_1_2_0', 'road_2_1_2_1', 'road_1_2_3_0', 'road_1_2_3_1', 'road_1_0_1_0', 'road_1_0_1_1']
self.list_exiting_lanes = ['road_1_1_0_0', 'road_1_1_0_1', 'road_1_1_2_0', 'road_1_1_2_1', 'road_1_1_3_0', 'road_1_1_3_1', 'road_1_1_1_0', 'road_1_1_1_1']

So, self.dic_lane_waiting_vehicle_count_current_step[road_0_1_0_0] - self.dic_lane_waiting_vehicle_count_current_step[road_1_1_0_0] is the first pressure, self.dic_lane_waiting_vehicle_count_current_step[road_0_1_0_1] - self.dic_lane_waiting_vehicle_count_current_step[road_1_1_0_1] is the second pressure, and so forth.

Considering this, it shows that the traffic of the entering left-lane road_0_1_0_0 is compared to the traffic of the exiting left-lane road_1_1_0_0, which looks not a valid traffic movement for the left lane. But, the entering left-lane has to be compared to exiting left-lane road_1_1_1_0. One question here is, is the mentioned traffic movement valid? If not, why is it considered? If so, it how do it consider the left-turn movement?

As another example for more clarification on a phase level, for phase=WE-Left (Figure 3 of the Presslight paper), we need the traffic of road_0_1_0_0 (entering from-west left-lane) be compared to the traffic of road_1_1_1_0 (exiting to-north left-lane) and the traffic of road_2_1_2_0 (entering from east left-lane) be compared to the traffic of road_1_1_3_0 (exiting to-south left-lane). But, the current formula compares the traffic of road_0_1_0_0 compared to road_1_1_0_0 and the traffic of road_2_1_2_0 compared to the traffic of road_1_1_2_0.

Chacha-Chen commented 4 years ago

That is a valid point. Thanks, Afshin. We've tried 3 kinds of state implementations: 1) Feed dic_feature['lane_num_features'] and dic_feature['lane_num_features_downstream'] together by concatenation. 2) dic_feature['delta_lane_num_features']. As you said, the orders didn't make sense here. 3) for phase=WE-Left, we consider the discrepancy between number of vehicles on road_0_1_0_0 - average(road_1_1_1_0, road_1_1_1_1, road_1_1_1_2), which are the average of all the downstream vechicle numbers.

All of them work similarly to the final results. So I guess the pressure reward definition, as well as integration of FRAP base model (transfer_dqn.py) are more important.

Chacha-Chen commented 4 years ago

Thanks for pointing out, I shall take notes and update the codes afterwards.

oroojlooy commented 4 years ago

Thanks for the update.