智能交通红绿灯系统(Python)
这是一个模拟单个路口的红绿灯自适应程序,可以作为智能交通系统的原型,展示了如何根据实时数据调整交通信号灯,提高道路通行效率。主要功能:
1. 人流量模拟:
- 基于时间段的人流量模型(早高峰、午间、晚高峰等)
- 随机波动和周期性变化
- 实时人流量图表显示
2. 红绿灯控制:
- 根据人流量自动调节红绿灯时长
- 包含红、黄、绿三种状态
- 显示倒计时
3. 可视化界面:
- 动态红绿灯显示
- 实时人流量曲线图
- 时间和时段显示
- 模拟速度控制
以下是具体代码说明:
1. 人流量模型 (PedestrianModel类):
class PedestrianModel:def __init__(self):# 初始化历史数据self.flow_history = []self.max_history = 100# 不同时段的人流量基础值配置self.time_patterns = {"morning_rush": (80, 20), # (基础人流量, 波动范围)"midday": (40, 15),"afternoon_rush": (90, 25),"evening": (30, 10),"night": (10, 5),"normal": (25, 10)}
首先定义了人流量模型的基础配置,包括不同时段的基础人流量和波动范围。
def update_flow(self):# 获取当前时段的基础人流量pattern = self.get_time_pattern(self.current_time)base_flow, variation = self.time_patterns[pattern]# 添加随机波动flow = base_flow + random.uniform(-variation, variation)# 添加突发情况if random.random() < 0.1: # 10%概率flow *= random.uniform(1.2, 1.5)# 添加周期性波动cycle_effect = 10 * math.sin(self.current_time.minute / 10 * math.pi)flow += cycle_effect
以上代码实现了人流量的动态计算,包括随机波动、突发情况和周期性变化。
2. 红绿灯控制器 (TrafficLightController类)
class TrafficLightController:def __init__(self):# 红绿灯状态: 0=红灯, 1=绿灯, 2=黄灯self.state = 0# 基础时长设置self.base_durations = {0: 30, # 红灯1: 20, # 绿灯2: 5 # 黄灯}
定义了红绿灯的基本状态和时长配置。
def adjust_durations(self, pedestrian_flow):# 根据人流量调整系数if pedestrian_flow < 20:self.adjustment_factor = 0.8elif pedestrian_flow < 40:self.adjustment_factor = 0.9elif pedestrian_flow < 60:self.adjustment_factor = 1.0elif pedestrian_flow < 80:self.adjustment_factor = 1.1else:self.adjustment_factor = 1.2# 调整红绿灯时长self.current_durations[0] = int(self.base_durations[0] / self.adjustment_factor)self.current_durations[1] = int(self.base_durations[1] * self.adjustment_factor)
这段代码实现了根据人流量动态调整红绿灯时长的核心算法。
3. 红绿灯显示组件 (TrafficLightWidget类)
def paintEvent(self, event):painter = QPainter(self)painter.setRenderHint(QPainter.Antialiasing)# 绘制红绿灯外框painter.setPen(QPen(Qt.black, 2))painter.setBrush(QBrush(QColor(50, 50, 50)))painter.drawRect(10, 10, 80, 240)# 绘制三个灯colors = [QColor(80, 0, 0), QColor(0, 80, 0), QColor(80, 80, 0)]# 点亮当前状态的灯if self.state == 0:colors[0] = QColor(255, 0, 0) # 红灯亮elif self.state == 1:colors[1] = QColor(0, 255, 0) # 绿灯亮else:colors[2] = QColor(255, 255, 0) # 黄灯亮
使用PyQt5的绘图功能实现红绿灯的可视化显示。
4. 人流量图表组件 (FlowChartWidget类)
def paintEvent(self, event):painter = QPainter(self)# 绘制坐标轴painter.drawLine(40, self.height() - 30, self.width() - 20, self.height() - 30)painter.drawLine(40, 20, 40, self.height() - 30)# 绘制当前人流量柱状图flow_height = int((self.flow / self.max_flow) * (self.height() - 50))painter.drawRect(60, self.height() - 30 - flow_height, 40, flow_height)# 绘制历史人流量曲线if len(self.flow_history) > 1:x_step = (self.width() - 120) / max(1, len(self.flow_history) - 1)for i in range(len(self.flow_history) - 1):x1 = int(120 + i * x_step)y1 = int(self.height() - 30 - (self.flow_history[i] / self.max_flow) * (self.height() - 50))x2 = int(120 + (i + 1) * x_step)y2 = int(self.height() - 30 - (self.flow_history[i + 1] / self.max_flow) * (self.height() - 50))painter.drawLine(x1, y1, x2, y2)
以上代码实现了人流量的实时显示,包括柱状图和历史趋势曲线。
5. 主窗口和更新逻辑 (MainWindow类)
def update_simulation(self):# 推进时间for _ in range(self.simulation_speed):self.pedestrian_model.advance_time(1)# 获取当前人流量并更新红绿灯current_flow = self.pedestrian_model.get_current_flow()state, timer = self.traffic_light.update(current_flow)# 更新UI显示self.traffic_light_widget.set_state(state, timer)self.flow_widget.set_flow(current_flow, self.pedestrian_model.flow_history)# 更新标签信息self.time_label.setText(f"当前时间: {self.pedestrian_model.get_formatted_time()}")self.pattern_label.setText(f"当前时段: {self.pedestrian_model.get_time_pattern_name()}")
实现了整个系统的主要更新逻辑,包括时间推进、状态更新和UI刷新。
6. 模拟速度控制
def change_simulation_speed(self, value):self.simulation_speed = valueself.speed_label.setText(f"{value}x")
实现了模拟速度的调节功能,允许加快或减慢模拟过程。
以下是程序完整代码:
import sys
import random
import math
from datetime import datetime, timedelta
from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, QLabel, QPushButton, QSlider)
from PyQt5.QtGui import QPainter, QColor, QFont, QPen, QBrush
from PyQt5.QtCore import Qt, QTimer, QRectclass PedestrianModel:"""人流量模型类"""def __init__(self):# 初始化历史数据self.flow_history = []self.max_history = 100# 一天中不同时段的人流量基础值self.time_patterns = {# 时间段: (基础人流量, 波动范围)"morning_rush": (80, 20), # 早高峰 (7:00-9:00)"midday": (40, 15), # 中午时段 (11:00-13:00)"afternoon_rush": (90, 25), # 晚高峰 (17:00-19:00)"evening": (30, 10), # 晚间 (19:00-22:00)"night": (10, 5), # 夜间 (22:00-6:00)"normal": (25, 10) # 其他时段}# 初始化当前时间和人流量self.current_time = datetime.now()self.current_flow = 0# 更新初始人流量self.update_flow()def get_time_pattern(self, time_obj):"""根据时间确定当前时段"""hour = time_obj.hourif 7 <= hour < 9:return "morning_rush"elif 11 <= hour < 13:return "midday"elif 17 <= hour < 19:return "afternoon_rush"elif 19 <= hour < 22:return "evening"elif hour >= 22 or hour < 6:return "night"else:return "normal"def update_flow(self):"""更新当前人流量"""# 获取当前时段pattern = self.get_time_pattern(self.current_time)base_flow, variation = self.time_patterns[pattern]# 添加随机波动flow = base_flow + random.uniform(-variation, variation)# 添加一些随机波峰波谷if random.random() < 0.1: # 10%的概率出现突发情况flow *= random.uniform(1.2, 1.5) # 突然增加20%-50%# 添加周期性波动 (模拟行人到达的波动性)cycle_effect = 10 * math.sin(self.current_time.minute / 10 * math.pi)flow += cycle_effect# 确保人流量不为负self.current_flow = max(5, int(flow))# 记录历史数据self.flow_history.append(self.current_flow)if len(self.flow_history) > self.max_history:self.flow_history.pop(0)def advance_time(self, seconds=10):"""推进时间"""self.current_time += timedelta(seconds=seconds)self.update_flow()def get_current_flow(self):"""获取当前人流量"""return self.current_flowdef get_formatted_time(self):"""获取格式化的当前时间"""return self.current_time.strftime("%H:%M:%S")def get_time_pattern_name(self):"""获取当前时段名称"""pattern = self.get_time_pattern(self.current_time)pattern_names = {"morning_rush": "早高峰","midday": "午间","afternoon_rush": "晚高峰","evening": "晚间","night": "夜间","normal": "平常时段"}return pattern_names.get(pattern, "未知时段")class TrafficLightController:"""红绿灯控制器类"""def __init__(self):# 红绿灯状态: 0=红灯, 1=绿灯, 2=黄灯self.state = 0# 基础时长设置 (秒)self.base_durations = {0: 30, # 红灯基础时长1: 20, # 绿灯基础时长2: 5 # 黄灯基础时长}# 当前时长self.current_durations = self.base_durations.copy()# 计时器self.timer = 30 # 初始为红灯时长# 调整系数self.adjustment_factor = 1.0def update(self, pedestrian_flow):"""更新红绿灯状态"""# 递减计时器self.timer -= 1# 如果计时结束,切换状态if self.timer <= 0:self.switch_state()# 根据人流量调整红绿灯时长self.adjust_durations(pedestrian_flow)# 重置计时器self.timer = self.current_durations[self.state]return self.state, self.timerdef switch_state(self):"""切换红绿灯状态"""# 红灯 -> 绿灯, 绿灯 -> 黄灯, 黄灯 -> 红灯self.state = (self.state + 1) % 3def adjust_durations(self, pedestrian_flow):"""根据人流量调整红绿灯时长"""# 基于人流量的调整系数# 人流量越大,绿灯时间越长,红灯时间越短if pedestrian_flow < 20:self.adjustment_factor = 0.8 # 人流量小,缩短绿灯时间elif pedestrian_flow < 40:self.adjustment_factor = 0.9elif pedestrian_flow < 60:self.adjustment_factor = 1.0 # 正常人流量,使用基础时长elif pedestrian_flow < 80:self.adjustment_factor = 1.1else:self.adjustment_factor = 1.2 # 人流量大,延长绿灯时间# 调整红灯时长 (人流量大时缩短)self.current_durations[0] = int(self.base_durations[0] / self.adjustment_factor)# 调整绿灯时长 (人流量大时延长)self.current_durations[1] = int(self.base_durations[1] * self.adjustment_factor)# 黄灯时长保持不变self.current_durations[2] = self.base_durations[2]# 确保时长在合理范围内self.current_durations[0] = max(15, min(self.current_durations[0], 60))self.current_durations[1] = max(10, min(self.current_durations[1], 45))def get_state_name(self):"""获取当前状态名称"""state_names = {0: "红灯", 1: "绿灯", 2: "黄灯"}return state_names.get(self.state, "未知")def get_state_color(self):"""获取当前状态颜色"""state_colors = {0: QColor(255, 0, 0), 1: QColor(0, 255, 0), 2: QColor(255, 255, 0)}return state_colors.get(self.state, QColor(128, 128, 128))class TrafficLightWidget(QWidget):"""红绿灯显示组件"""def __init__(self, parent=None):super().__init__(parent)self.state = 0 # 0=红灯, 1=绿灯, 2=黄灯self.timer = 30def set_state(self, state, timer):"""设置红绿灯状态"""self.state = stateself.timer = timerself.update() # 触发重绘def paintEvent(self, event):"""绘制红绿灯"""painter = QPainter(self)painter.setRenderHint(QPainter.Antialiasing)# 绘制红绿灯外框painter.setPen(QPen(Qt.black, 2))painter.setBrush(QBrush(QColor(50, 50, 50)))painter.drawRect(10, 10, 80, 240)# 绘制三个灯colors = [QColor(80, 0, 0), QColor(0, 80, 0), QColor(80, 80, 0)] # 暗色# 点亮当前状态的灯if self.state == 0:colors[0] = QColor(255, 0, 0) # 红灯亮elif self.state == 1:colors[1] = QColor(0, 255, 0) # 绿灯亮else:colors[2] = QColor(255, 255, 0) # 黄灯亮# 绘制红灯painter.setBrush(QBrush(colors[0]))painter.drawEllipse(30, 30, 40, 40)# 绘制黄灯painter.setBrush(QBrush(colors[2]))painter.drawEllipse(30, 110, 40, 40)# 绘制绿灯painter.setBrush(QBrush(colors[1]))painter.drawEllipse(30, 190, 40, 40)# 绘制倒计时painter.setPen(QPen(Qt.white, 2))painter.setFont(QFont("Arial", 12, QFont.Bold))painter.drawText(QRect(10, 250, 80, 30), Qt.AlignCenter, str(self.timer))class FlowChartWidget(QWidget):"""人流量图表组件"""def __init__(self, parent=None):super().__init__(parent)self.flow = 0self.flow_history = []self.max_flow = 100def set_flow(self, flow, flow_history):"""设置当前人流量"""self.flow = flowself.flow_history = flow_historyself.update() # 触发重绘def paintEvent(self, event):"""绘制人流量图表"""painter = QPainter(self)painter.setRenderHint(QPainter.Antialiasing)# 绘制背景painter.setPen(QPen(Qt.black, 1))painter.setBrush(QBrush(QColor(240, 240, 240)))painter.drawRect(0, 0, self.width(), self.height())# 绘制坐标轴painter.setPen(QPen(Qt.black, 2))painter.drawLine(40, self.height() - 30, self.width() - 20, self.height() - 30) # X轴painter.drawLine(40, 20, 40, self.height() - 30) # Y轴# 绘制Y轴刻度painter.setPen(QPen(Qt.black, 1))painter.setFont(QFont("Arial", 8))for i in range(0, 101, 20):y = self.height() - 30 - int((i / 100) * (self.height() - 50))painter.drawLine(35, y, 45, y)painter.drawText(5, y + 5, str(i))# 绘制当前人流量柱状图painter.setPen(QPen(Qt.NoPen))painter.setBrush(QBrush(QColor(0, 0, 255, 100)))flow_height = int((self.flow / self.max_flow) * (self.height() - 50))painter.drawRect(60, self.height() - 30 - flow_height, 40, flow_height)# 绘制人流量数值painter.setPen(QPen(Qt.black, 1))painter.setFont(QFont("Arial", 10, QFont.Bold))painter.drawText(QRect(60, self.height() - 30 - flow_height - 20, 40, 20), Qt.AlignCenter, str(self.flow))# 绘制历史人流量曲线if len(self.flow_history) > 1:painter.setPen(QPen(QColor(255, 0, 0), 2))# 计算点之间的间距x_step = (self.width() - 120) / max(1, len(self.flow_history) - 1)# 绘制折线for i in range(len(self.flow_history) - 1):x1 = int(120 + i * x_step)y1 = int(self.height() - 30 - (self.flow_history[i] / self.max_flow) * (self.height() - 50))x2 = int(120 + (i + 1) * x_step)y2 = int(self.height() - 30 - (self.flow_history[i + 1] / self.max_flow) * (self.height() - 50))painter.drawLine(x1, y1, x2, y2)class MainWindow(QMainWindow):"""主窗口类"""def __init__(self):super().__init__()self.initUI()# 创建人流模型和红绿灯控制器self.pedestrian_model = PedestrianModel()self.traffic_light = TrafficLightController()# 设置定时器self.timer = QTimer(self)self.timer.timeout.connect(self.update_simulation)self.timer.start(100) # 每100毫秒更新一次# 模拟速度 (默认为1倍速)self.simulation_speed = 1def initUI(self):"""初始化UI"""self.setWindowTitle('自适应红绿灯系统')self.setGeometry(100, 100, 800, 600)# 创建中央部件central_widget = QWidget()self.setCentralWidget(central_widget)# 创建主布局main_layout = QHBoxLayout(central_widget)# 左侧布局 - 红绿灯显示left_layout = QVBoxLayout()# 红绿灯组件self.traffic_light_widget = TrafficLightWidget()self.traffic_light_widget.setFixedSize(100, 300)left_layout.addWidget(self.traffic_light_widget)# 红绿灯状态标签self.state_label = QLabel("当前状态: 红灯")self.state_label.setAlignment(Qt.AlignCenter)self.state_label.setFont(QFont("Arial", 12, QFont.Bold))left_layout.addWidget(self.state_label)# 添加到主布局main_layout.addLayout(left_layout)# 右侧布局 - 人流量和控制right_layout = QVBoxLayout()# 时间和时段显示time_layout = QHBoxLayout()self.time_label = QLabel("当前时间: 00:00:00")self.time_label.setFont(QFont("Arial", 12))time_layout.addWidget(self.time_label)self.pattern_label = QLabel("当前时段: 平常时段")self.pattern_label.setFont(QFont("Arial", 12))time_layout.addWidget(self.pattern_label)right_layout.addLayout(time_layout)# 人流量图表self.flow_widget = FlowChartWidget()self.flow_widget.setMinimumSize(500, 300)right_layout.addWidget(self.flow_widget)# 人流量信息self.flow_label = QLabel("当前人流量: 0")self.flow_label.setFont(QFont("Arial", 12, QFont.Bold))right_layout.addWidget(self.flow_label)# 红绿灯时长信息durations_layout = QHBoxLayout()self.red_duration_label = QLabel("红灯时长: 30s")durations_layout.addWidget(self.red_duration_label)self.green_duration_label = QLabel("绿灯时长: 20s")durations_layout.addWidget(self.green_duration_label)self.yellow_duration_label = QLabel("黄灯时长: 5s")durations_layout.addWidget(self.yellow_duration_label)right_layout.addLayout(durations_layout)# 模拟速度控制speed_layout = QHBoxLayout()speed_layout.addWidget(QLabel("模拟速度:"))self.speed_slider = QSlider(Qt.Horizontal)self.speed_slider.setMinimum(1)self.speed_slider.setMaximum(10)self.speed_slider.setValue(1)self.speed_slider.setTickPosition(QSlider.TicksBelow)self.speed_slider.setTickInterval(1)self.speed_slider.valueChanged.connect(self.change_simulation_speed)speed_layout.addWidget(self.speed_slider)self.speed_label = QLabel("1x")speed_layout.addWidget(self.speed_label)right_layout.addLayout(speed_layout)# 添加到主布局main_layout.addLayout(right_layout)def update_simulation(self):"""更新模拟"""# 推进时间for _ in range(self.simulation_speed):self.pedestrian_model.advance_time(1)# 获取当前人流量current_flow = self.pedestrian_model.get_current_flow()# 更新红绿灯状态state, timer = self.traffic_light.update(current_flow)# 更新UIself.traffic_light_widget.set_state(state, timer)self.state_label.setText(f"当前状态: {self.traffic_light.get_state_name()}")# 更新人流量显示self.flow_widget.set_flow(current_flow, self.pedestrian_model.flow_history)self.flow_label.setText(f"当前人流量: {current_flow}")# 更新时间和时段显示self.time_label.setText(f"当前时间: {self.pedestrian_model.get_formatted_time()}")self.pattern_label.setText(f"当前时段: {self.pedestrian_model.get_time_pattern_name()}")# 更新红绿灯时长信息self.red_duration_label.setText(f"红灯时长: {self.traffic_light.current_durations[0]}s")self.green_duration_label.setText(f"绿灯时长: {self.traffic_light.current_durations[1]}s")self.yellow_duration_label.setText(f"黄灯时长: {self.traffic_light.current_durations[2]}s")def change_simulation_speed(self, value):"""改变模拟速度"""self.simulation_speed = valueself.speed_label.setText(f"{value}x")def main():app = QApplication(sys.argv)window = MainWindow()window.show()sys.exit(app.exec_())if __name__ == '__main__':main()