diff --git a/sumo_edge_vsl_environment.py b/sumo_edge_vsl_environment.py index 4ec91cd..51efb59 100644 --- a/sumo_edge_vsl_environment.py +++ b/sumo_edge_vsl_environment.py @@ -76,14 +76,18 @@ class SUMOEdgeVSLEnvironment: net_file=self.net_file, ) - # 为每条边构建检测器映射(只用第一个检测器获取边级数据) - self.edge_detector_map: Dict[str, str] = {} + # 为每条边构建第一组检测器映射(所有车道) + self.edge_detector_map: Dict[str, List[str]] = {} for edge_id in self.control_edges: ei = self.parser.edge_info.get(edge_id) if ei and ei.detectors: - # 取第一个检测器作为该边的代表 - first_det = list(ei.detectors.values())[0] - self.edge_detector_map[edge_id] = first_det + # 获取第一组检测器(pos_index=0)的所有交通车道 + first_group_dets = [] + for lane_idx in ei.traffic_lane_indices: + det_id = ei.detectors.get((lane_idx, 0)) + if det_id: + first_group_dets.append(det_id) + self.edge_detector_map[edge_id] = first_group_dets # 动作空间: 每条边独立选速度 self.action_dims = [self.num_speed_actions] * self.num_edges @@ -181,8 +185,10 @@ class SUMOEdgeVSLEnvironment: self._interval_arrived += traci.simulation.getArrivedNumber() self._interval_departed += traci.simulation.getDepartedNumber() - state = self._collect_state() - info = self._collect_metrics() + # 只读取一次检测器数据 + detector_data = self._get_edge_detector_data() + state = self._collect_state(detector_data) + info = self._collect_metrics(detector_data) reward = self._calculate_reward(info) self._last_reward = reward @@ -209,32 +215,54 @@ class SUMOEdgeVSLEnvironment: for i, edge_id in enumerate(self.control_edges): traci.edge.setMaxSpeed(edge_id, float(edge_speeds[i])) - def _collect_state(self) -> np.ndarray: - """收集状态:每条边的平均速度/占有率/流量""" - state_parts = [] + def _get_edge_detector_data(self) -> Tuple[List[float], List[float], List[int], List[float]]: + """获取所有控制边的检测器数据(速度、占有率、车辆数、有效速度)""" + speeds, occs, counts, valid_speeds = [], [], [], [] for edge_id in self.control_edges: - det_id = self.edge_detector_map.get(edge_id) - if det_id: + det_ids = self.edge_detector_map.get(edge_id, []) + if not det_ids: + speeds.append(self.free_flow_speed) + occs.append(0.0) + counts.append(0) + continue + + # 获取所有车道的数据 + lane_speeds, lane_occs, lane_counts = [], [], [] + for det_id in det_ids: try: spd = traci.inductionloop.getLastIntervalMeanSpeed(det_id) occ = traci.inductionloop.getLastIntervalOccupancy(det_id) cnt = traci.inductionloop.getLastIntervalVehicleNumber(det_id) - if spd <= 0: - spd = traci.lane.getMaxSpeed(traci.inductionloop.getLaneID(det_id)) + if spd > 0: + lane_speeds.append(spd) + lane_occs.append(occ) + lane_counts.append(cnt) except Exception: - spd = self.free_flow_speed - occ = 0.0 - cnt = 0 - else: - spd = self.free_flow_speed - occ = 0.0 - cnt = 0 + pass + # 聚合 + speeds.append(np.mean(lane_speeds) if lane_speeds else self.free_flow_speed) + occs.append(np.mean(lane_occs) if lane_occs else 0.0) + counts.append(sum(lane_counts)) + if lane_speeds: + valid_speeds.append(np.mean(lane_speeds)) + + return speeds, occs, counts, valid_speeds + + def _collect_state(self, detector_data: Optional[Tuple[List[float], List[float], List[int], List[float]]] = None) -> np.ndarray: + """收集状态:每条边的平均速度/占有率/流量""" + state_parts = [] + + if detector_data is None: + speeds, occs, counts, _ = self._get_edge_detector_data() + else: + speeds, occs, counts, _ = detector_data + + for spd, occ, cnt in zip(speeds, occs, counts): mean_speed_norm = np.clip(spd / self.free_flow_speed, 0.0, 1.5) mean_occ = np.clip(occ / 100.0, 0.0, 1.0) flow_norm = min(cnt / 50.0, 1.0) - state_parts.extend([mean_speed_norm, mean_occ, flow_norm]) # 边限速 @@ -252,7 +280,7 @@ class SUMOEdgeVSLEnvironment: return np.array(state_parts, dtype=np.float32) - def _collect_metrics(self) -> Dict: + def _collect_metrics(self, detector_data: Tuple[List[float], List[float], List[int], List[float]]) -> Dict: """收集交通指标""" info = {} @@ -263,34 +291,14 @@ class SUMOEdgeVSLEnvironment: info["departed_count"] = self._interval_departed # 每条边的速度和占有率 - edge_speeds = [] - edge_occs = [] - all_speeds = [] - - for edge_id in self.control_edges: - det_id = self.edge_detector_map.get(edge_id) - if det_id: - try: - spd = traci.inductionloop.getLastIntervalMeanSpeed(det_id) - occ = traci.inductionloop.getLastIntervalOccupancy(det_id) - if spd <= 0: - spd = traci.lane.getMaxSpeed(traci.inductionloop.getLaneID(det_id)) - edge_speeds.append(spd) - edge_occs.append(occ) - all_speeds.append(spd) - except Exception: - edge_speeds.append(self.free_flow_speed) - edge_occs.append(0.0) - else: - edge_speeds.append(self.free_flow_speed) - edge_occs.append(0.0) + edge_speeds, edge_occs, _, valid_speeds = detector_data info["edge_speeds_ms"] = edge_speeds info["edge_occupancies"] = edge_occs - info["mean_speed"] = np.mean(all_speeds) if all_speeds else 0.0 + info["mean_speed"] = np.mean(valid_speeds) if valid_speeds else 0.0 info["mean_speed_kmh"] = info["mean_speed"] * 3.6 info["mean_occupancy"] = np.mean(edge_occs) if edge_occs else 0.0 - info["speed_std"] = np.std(all_speeds) if len(all_speeds) > 1 else 0.0 + info["speed_std"] = np.std(valid_speeds) if len(valid_speeds) > 1 else 0.0 # 车辆数和密度 try: