Python交通流仿真【含源码】

article/2025/10/6 8:12:24

虽然交通并不总是畅通无阻,但汽车无缝穿越交叉路口,在交通信号灯处转弯和停车看起来相当壮观。这种沉思让我思考交通流对人类文明的重要性。

在此之后,内心的书呆子特质让我忍不住思考一种模拟交通流的方法。我在一个涉及交通流量的本科项目上投入了几个星期的时间,深入到不同的模拟技术,最终选择了一个。

在本文中,我将解释为什么交通流模拟很重要,比较不同的方法来模拟交通流,并呈现仿真结果(以及源代码)。

1、为什么要模拟交通流?

模拟交通流的主要原因是在没有真实世界的情况下生成数据。你可以使用软件运行模型来预测交通流,而不需要在现实世界中安装传感器来测试新的管理思路如何影响现实世界。这有助于加速交通流系统的优化和数据收集。仿真是实际测试更便宜、更快捷的替代方案。

训练机器学习模型需要巨大的数据集,这些数据集的收集和处理成本可能很高。通过模拟交通流在程序上生成数据可以很容易地适应所需的数据类型。

2、建 模

要分析和优化交通系统,我们首先必须对交通系统进行数学建模。这种模型应根据输入参数(路网几何、每分钟车辆、车速等)真实地表示交通流量。

在这里插入图片描述

交通流系统模型通常分为三类,具体取决于它们在哪个级别上运行:

  • 微型模型:分别代表每辆车,并尝试复现驾驶员行为。
  • 宏观模型:从交通密度(每公里车辆)和交通流量(车辆每分钟)的角度描述车辆的整体移动。它们通常类似于流体的流动。
  • 中观模型:是结合微观和宏观模型特点的混合模型,将流量建模为车辆的"包"。
    在本文中,我将使用微观模型。

3、微观模型

在微观模型中使用驾驶员模型描述单个驾驶员/车辆的行为。因此,它必须是一个多代理系统,即每辆车都使用来自其环境的输入自行运行。
在这里插入图片描述

在微观模型中,每辆车都编号为i。第i辆车跟随第(i-1)辆车。对于第i辆车,我们将用xi表示其沿路的位置,用vi表示其速度,以及li表示其长度。每辆车都是如此。
在这里插入图片描述

我们将用si表示保险杠到保险杠的距离,用Δvᵢ 表示第i辆车和前面的第i-1辆车之间的速度差异。

4、智能驾驶员模型 (IDM)

2000年,Treiber, Hennecke 和 Helbing开发了智能驾驶员模型,它描述第i辆车的加速度是其变量和前面车辆的变量的函数。动态方程的定义为:

在这里插入图片描述

在我解释这个模型背后的直觉之前,我应该先解释下这些符号代表什么。

我们已经谈到了sᵢ, vᵢ, andΔvᵢ。其他参数包括:

  • s0i:是第i辆车和第i-1辆车之间的最小期望距离。
  • v0i :是第i辆车的最大期望速度.
  • δ:是加速度指数,它控制着加速度的"平滑度"。
  • Ti:是第i辆车的驾驶员的反应时间。
  • ai :是第i辆车的最大加速度。
  • bi :是第i辆车的舒适减速度.
  • s* : 是第i辆车和第i-1辆车之间的实际期望距离。

首先,我们将看看s*,这是一个距离,它由三部分组成。

在这里插入图片描述

  • s0i:如前所言,是所需的最小距离。

  • viTi:是反应时间的安全距离。这是车辆在驾驶员反应(刹车)前行驶的距离。由于速度是随着时间推移而保持的距离,距离是速度乘以时间。
    在这里插入图片描述

  • (vᵢ Δvᵢ)/√(2aᵢ bᵢ):这个有点复杂,这是一个基于速度差的安全距离。它表示车辆在非紧急刹车时(减速度应小于bi),不撞到前面的车辆的前提下所需的距离。

5、智能驾驶员模型的工作原理

车辆假定沿着一条直道行驶,并假定遵守以下方程:
在这里插入图片描述

为了更好地了解这个等式,我们可以将其一分为二。我们有一个自由道路加速度和交互加速度。
在这里插入图片描述

自由道路加速度是自由道路上的加速,即没有车辆的空路。如果我们绘制加速度作为速度vi的函数,可以得到:
在这里插入图片描述

我们注意到,当车辆静止(vi=0)时,加速是最大的。当车速接近最高速度时,加速变为 0。这表明,自由道路加速度将加速车辆到最高速度。

如果我们绘制不同值的δ的 v-a 图,我们会注意到它控制驾驶员在接近最大速度时减速的速度。这反过来又控制了加速度/减速度的平滑度。

在这里插入图片描述
在这里插入图片描述

交互加速度与与前方车辆的交互有关。为了更好地了解它是如何工作的,让我们考虑以下情况:

  • 在自由路上(si >>s*):
    当前面的车辆很远时,即si远远大于车辆之间所需的安全距离s*,交互加速度几乎为0。这意味着车辆将受到自由道路加速的制约。
    在这里插入图片描述

  • 在高接近速率((Δvᵢ):
    当速度差很大时,交互加速度试图通过分子中的(vᵢΔvᵢ)²项进行制动补偿,但过于困难。这是通过分母中4bᵢsᵢ²实现的(老实说,我不知道它如何精确限制减速到bᵢ)。
    在这里插入图片描述

  • 在小距离差(si <<1和Δvᵢ≈0):
    加速度成为一个简单的排斥力。
    在这里插入图片描述

6、交通道路网络模型

我们需要模拟道路网络。为此,我们将使用有向图 G =(V、E),其中:

  • V是一组顶点(或节点)。
  • E是代表道路的边的几何。

每辆车将沿着一条由多个路段(边)组成的路径形式。我们将在同一路段(边)上的车辆应用智能驾驶员模型。当车辆到达路的尽头时,我们会将其从该路段移开并附加到下一路段上。

在仿真中,我们不会保留一组节点(阵列),相反,每条道路都将由其开始和结束节点的值明确定义。

7、随机车辆发生器

为了将车辆添加到我们的模拟中,我们有两个选项:

  • 通过创建新的Vehicle类实例并将其添加到车辆列表中,手动将每辆车添加到模拟中。
  • 根据预先定义的概率,随机添加车辆。

对于第二个选项,我们必须定义一个随机车辆发生器。

随机车辆发生器由两个约束定义:

  • 车辆生成速率(τ): 平均每分钟应添加到仿真中的车辆数。
  • 车辆配置列表 (L):车辆配置和生成概率的元组列表。

L = [(p1,V1),(p2,V2),(p3,V3]),…
随机车辆发生器以概率pi生成车辆Vi。

8、交通信号灯

红绿灯位于路段端点上,其特点是包含以下两个区域:

  • 减速区:以减速距离和减速系数为特征,是车辆使用减速系数减速的区域。
    在这里插入图片描述

  • 停车区:以停车距离为特征,是车辆停车的区域。这是通过此动态方程使用阻尼力实现的:
    在这里插入图片描述

9、仿真

我们将采用面向对象的方法。每辆车和道路将被定义为一个类。

我们将反复使用以下的__init__函数。它通过一个函数set_default_config设置当前类的默认配置,并将一个字典中的属性设置为当前类实例的属性。这样,我们不必担心更新不同类别的__init__函数或将来的变化。

def __init__(self, config={}):# Set default configurationself.set_default_config()# Update configurationfor attr, val in config.items():setattr(self, attr, val)

我们将为路段创建一个Road类:

from scipy.spatial import distanceclass Road:def __init__(self, start, end):self.start = startself.end = endself.init_porperties()def init_properties(self):self.length = distance.euclidean(self.start, self.end)self.angle_sin = (self.end[1]-self.start[1]) / self.lengthself.angle_cos = (self.end[0]-self.start[0]) / self.length

当在屏幕上绘制道路及其角度的正弦和余弦时,我们需要道路的长度length。

还有一个Simulation类,让我们添加了一些方法来将道路添加到仿真里。

from .road import Roadclass Simulation:def __init__(self, config={}):# Set default configurationself.set_default_config()# Update configurationfor attr, val in config.items():setattr(self, attr, val)def set_default_config(self):self.t = 0.0            # Time keepingself.frame_count = 0    # Frame count keepingself.dt = 1/60          # Simulation time stepself.roads = []         # Array to store roadsdef create_road(self, start, end):road = Road(start, end)self.roads.append(road)return roaddef create_roads(self, road_list):for road in road_list:self.create_road(*road)

我们必须在屏幕上实时显示我们的仿真。为此,我们将使用pygame。我将创建一个Window类,以类Simulation作为参数。

我定义了多个绘图函数,有助于绘制基本形状。

该loop方法创建一个pygame窗口,并在每一帧调用draw方法和loop参数。当我们的仿真需要逐帧更新时,这将变得有用。

import pygame
from pygame import gfxdraw
import numpy as npclass Window:def __init__(self, sim, config={}):# Simulation to drawself.sim = sim# Set default configurationsself.set_default_config()# Update configurationsfor attr, val in config.items():setattr(self, attr, val)def set_default_config(self):"""Set default configuration"""self.width = 1400self.height = 1000self.bg_color = (250, 250, 250)self.fps = 60self.zoom = 5self.offset = (0, 0)self.mouse_last = (0, 0)self.mouse_down = Falsedef loop(self, loop=None):"""Shows a window visualizing the simulation and runs the loop function."""# Create a pygame windowself.screen = pygame.display.set_mode((self.width, self.height))pygame.display.flip()# Fixed fpsclock = pygame.time.Clock()# To draw textpygame.font.init()self.text_font = pygame.font.SysFont('Lucida Console', 16)# Draw looprunning = Truewhile not self.sim.stop_condition(self.sim) and running:# Update simulationif loop: loop(self.sim)# Draw simulationself.draw()# Update windowpygame.display.update()clock.tick(self.fps)# Handle all eventsfor event in pygame.event.get():# Handle mouse drag and wheel events...def convert(self, x, y=None):"""Converts simulation coordinates to screen coordinates"""...def inverse_convert(self, x, y=None):"""Converts screen coordinates to simulation coordinates"""...def background(self, r, g, b):"""Fills screen with one color."""...def line(self, start_pos, end_pos, color):"""Draws a line."""...def rect(self, pos, size, color):"""Draws a rectangle."""...def box(self, pos, size, color):"""Draws a rectangle."""...def circle(self, pos, radius, color, filled=True):"""Draws a circle"""...def polygon(self, vertices, color, filled=True):"""Draws a polygon"""def rotated_box(self, pos, size, angle=None, cos=None, sin=None, centered=True, color=(0, 0, 255), filled=True):"""Draws a filled rectangle centered at *pos* with size *size* rotated anti-clockwise by *angle*."""def rotated_rect(self, pos, size, angle=None, cos=None, sin=None, centered=True, color=(0, 0, 255)):"""Draws a rectangle centered at *pos* with size *size* rotated anti-clockwise by *angle*."""def draw_axes(self, color=(100, 100, 100)):"""Draw x and y axis"""def draw_grid(self, unit=50, color=(150,150,150)):"""Draws a grid"""def draw_roads(self):"""Draws every road"""def draw_status(self):"""Draws status text"""def draw(self):# Fill backgroundself.background(*self.bg_color)# Major and minor grid and axesself.draw_grid(10, (220,220,220))self.draw_grid(100, (200,200,200))self.draw_axes()# Draw roadsself.draw_roads()# Draw status infoself.draw_status()

我将trafficSimulator文件夹中的每一个文件使用__init__.py组合在一起。

from .road import *
from .simulation import *
from .window import *

每当定义新类时,应在此文件中导入该类。

将trafficSimulator文件夹放置在我们的项目文件夹中将以便使用仿真模块。

from trafficSimulator import *# Create simulation
sim = Simulation()# Add one road
sim.create_road((300, 98), (0, 98))# Add multiple roads
sim.create_roads([((300, 98), (0, 98)),((0, 102), (300, 102)),((180, 60), (0, 60)),((220, 55), (180, 60)),((300, 30), (220, 55)),((180, 60), (160, 98)),((158, 130), (300, 130)),((0, 178), (300, 178)),((300, 182), (0, 182)),((160, 102), (155, 180))])# Start simulation
win = Window(sim)
win.loop()

在这里插入图片描述

10、车辆

现在,我们必须增加车辆。

我们将使用Taylor级数来近似求解本文建模部分所讨论的动态方程。

一个微分方程f的泰勒级数展开是:

在这里插入图片描述

使用▲x替换a,使用x+▲x替换x, 我们得到:
在这里插入图片描述

使用位置x替换f:
在这里插入图片描述

作为一个近似,对位置我们将在2阶截止,因为加速度是最高阶导数。我们得到方程(2):
在这里插入图片描述

对于速度,我们将用v代替x:
在这里插入图片描述

我们将在1阶 停止,因为速度是1阶导数。方程(2):
在这里插入图片描述

在每个迭代(或帧)中,使用 IDM 公式计算加速度后,我们将使用以下两个方程更新位置和速度:

在这里插入图片描述

在代码中看起来像这样:

self.a = ...      # IDM formula 
self.v += self.a*dt
self.x += self.v*dt + self.a*dt*dt/2

由于这只是一个近似值,速度有时可能会变为负值(但模型不允许这样)。当速度为负时,会产生不稳定性,位置和速度会分化为负无穷大。

为了克服这个问题,每当我们预测负速度时,我们就会将其设定为零,并从那里找出方法:

在这里插入图片描述

在代码中,此实现如下:

if self.v + self.a*dt < 0:self.x -= 1/2*self.v*self.v/self.aself.v = 0
else:self.v += self.a*dtself.x += self.v*dt + self.a*dt*dt/2

要计算 IDM 加速度,我们将引导车辆表示为lead,并当lead不是None时,计算一个交互项(用alpha表示)。

alpha = 0
if lead:delta_x = lead.x - self.x - lead.ldelta_v = self.v - lead.valpha = (self.s0 + max(0, self.T*self.v + delta_v*self.v/self.sqrt_ab)) / delta_x
self.a = self.a_max * (1-(self.v/self.v_max)**4 - alpha**2)

如果车辆停止(例如在红绿灯处),我们将使用阻尼方程:

if self.stopped: self.a = -self.b_max*self.v/self.v_max

然后,我们将所有内容整合在Vehicle类的update方法中:

import numpy as npclass Vehicle:def __init__(self, config={}):# Set default configurationself.set_default_config()# Update configurationfor attr, val in config.items():setattr(self, attr, val)# Calculate propertiesself.init_properties()def set_default_config(self):    self.l = 4self.s0 = 4self.T = 1self.v_max = 16.6self.a_max = 1.44self.b_max = 4.61self.path = []self.current_road_index = 0self.x = 0self.v = self.v_maxself.a = 0self.stopped = Falsedef init_properties(self):self.sqrt_ab = 2*np.sqrt(self.a_max*self.b_max)self._v_max = self.v_maxdef update(self, lead, dt):# Update position and velocityif self.v + self.a*dt < 0:self.x -= 1/2*self.v*self.v/self.aself.v = 0else:self.v += self.a*dtself.x += self.v*dt + self.a*dt*dt/2# Update accelerationalpha = 0if lead:delta_x = lead.x - self.x - lead.ldelta_v = self.v - lead.valpha = (self.s0 + max(0, self.T*self.v + delta_v*self.v/self.sqrt_ab)) / delta_xself.a = self.a_max * (1-(self.v/self.v_max)**4 - alpha**2)if self.stopped: self.a = -self.b_max*self.v/self.v_maxdef stop(self):self.stopped = Truedef unstop(self):self.stopped = Falsedef slow(self, v):self.v_max = vdef unslow(self):self.v_max = self._v_max

在Road类中,我们将添加一个deque(双端队列)来跟踪车辆。队列是存储车辆的较好的数据结构,因为队列中的第一辆车是路上最远的车辆,它是第一个可以从队列中删除的车辆。要从deque 中删除第一个车辆,我们可以使用self.vehicles.popleft() 。

我们将在Road类中添加一个update方法:

def update(self, dt):n = len(self.vehicles)if n > 0:# Update first vehicleself.vehicles[0].update(None, dt)# Update other vehiclesfor i in range(1, n):lead = self.vehicles[i-1]self.vehicles[i].update(lead, dt
在Simulation类中添加一个update方法:def update(self):# Update every roadfor road in self.roads:road.update(self.dt)# Check roads for out of bounds vehiclefor road in self.roads:# If road has no vehicles, continueif len(road.vehicles) == 0: continue# If notvehicle = road.vehicles[0]# If first vehicle is out of road boundsif vehicle.x >= road.length:# If vehicle has a next roadif vehicle.current_road_index + 1 < len(vehicle.path):# Update current road to next roadvehicle.current_road_index += 1# Create a copy and reset some vehicle propertiesnew_vehicle = deepcopy(vehicle)new_vehicle.x = 0# Add it to the next roadnext_road_index = vehicle.path[vehicle.current_road_index]self.roads[next_road_index].vehicles.append(new_vehicle)# In all cases, remove it from its roadroad.vehicles.popleft() 

回到Window类,添加了一个run方法来实时更新仿真:

def run(self, steps_per_update=1):"""Runs the simulation by updating in every loop."""def loop(sim):sim.run(steps_per_update)self.loop(loop)

现在我们将手动添加车辆:

sim.roads[4].vehicles.append(Vehicle({"path": [4, 3, 2]})
)sim.roads[0].vehicles.append(Vehicle())
sim.roads[1].vehicles.append(Vehicle())
sim.roads[6].vehicles.append(Vehicle())
sim.roads[7].vehicles.append(Vehicle())

在这里插入图片描述

车辆生成器代码如下:

from .vehicle import Vehicle
from numpy.random import randintclass VehicleGenerator:def __init__(self, sim, config={}):...def set_default_config(self):self.vehicle_rate = 20self.vehicles = [(1, {})]def init_properties(self):self.upcoming_vehicle = self.generate_vehicle()def generate_vehicle(self):"""Returns a random vehicle from self.vehicles with random proportions"""...def update(self):"""Add vehicles"""...

VehicleGenerator包含(odds, vehicle) 元组的列表。

元组第一个元素是在同一元组中生成车辆的权重(不是概率)。我使用权重, 因为它们更容易工作, 因为我们可以只使用整数。

例如,如果我们有3辆车权重分别为132,这相当于生成概率分别为1/6 , 3/6 ,2/66 。

为了实现这一点,我们使用以下算法

  • 生成1到权重和之间的数字r。
  • 当r是非负数:循环所有可能的车辆,并在每次迭代时减去其权重。
  • 返回最后使用的车辆。

如果我们有权重:W1,W2,W3。 此算法将在1和W 3之间的数字分配到第一辆车,将W₁ 到 W₁+W₂ 之间的数字分配给第二辆车,将W₁+W₂+W₃到结束的数字分配给第三辆车。

def generate_vehicle(self):"""Returns a random vehicle from self.vehicles with random proportions"""total = sum(pair[0] for pair in self.vehicles)r = randint(1, total+1)for (weight, config) in self.vehicles:r -= weightif r <= 0:return Vehicle(config)

每次生成器添加车辆时,last_added_time属性都会更新到当前时间。当当前时间和last_added_time之差值大于车辆生成周期时,添加车辆。

添加车辆的周期是60/vehicle_rate,因为vehicle_rate 的单位是车辆/每分钟,60表示1分钟或60秒。

我们还必须检查道路是否还有空间来添加即将行驶的车辆。我们通过检查道路上最后一辆车之间的距离和即将行驶的车辆的长度和安全距离的总和来做到这一点。

def update(self):"""Add vehicles"""if self.sim.t - self.last_added_time >= 60 / self.vehicle_rate:# If time elasped after last added vehicle is# greater than vehicle_period; generate a vehicleroad = self.sim.roads[self.upcoming_vehicle.path[0]]      if len(road.vehicles) == 0\or road.vehicles[-1].x > self.upcoming_vehicle.s0 + self.upcoming_vehicle.l:# If there is space for the generated vehicle; add itself.upcoming_vehicle.time_added = self.sim.troad.vehicles.append(self.upcoming_vehicle)# Reset last_added_time and upcoming_vehicleself.last_added_time = self.sim.tself.upcoming_vehicle = self.generate_vehicle()

最后,我们应该通过调用Simulation 的update方法来更新车辆生成。

sim.create_gen({'vehicle_rate': 60,'vehicles': [[1, {"path": [4, 3, 2]}],[1, {"path": [0]}],[1, {"path": [1]}],[1, {"path": [6]}],[1, {"path": [7]}]]
})

在这里插入图片描述

11、红绿灯

交通信号灯的默认属性是:

class TrafficSignal:def __init__(self, roads, config={}):# Initialize roadsself.roads = roads# Set default configurationself.set_default_config()# Update configurationfor attr, val in config.items():setattr(self, attr, val)# Calculate propertiesself.init_properties()def set_default_config(self):self.cycle = [(False, True), (True, False)]self.slow_distance = 40self.slow_factor = 10self.stop_distance = 15self.current_cycle_index = 0self.last_t = 0

self.cycle是self.roads 的一个数组,每个元组包含道路的状态(True绿色,False红色)。

在默认配置中,(False, True)表示第一组道路为红色,第二组道路为绿色。 (True, False) 则恰恰相反。

所以使用此方法之,是因为它易于扩展。我们创建红绿灯,包括超过 2 条道路、带有左右转弯单独信号的红绿灯,甚至用于多个交叉路口的同步交通信号灯。

交通信号灯的update函数应该是可定制的。其默认行为是对称的固定时间循环。

def init_properties(self):for i in range(len(self.roads)):for road in self.roads[i]:road.set_traffic_signal(self, i)@property
def current_cycle(self):return self.cycle[self.current_cycle_index]def update(self, sim):# Goes through all cycles every cycle_length and repeatscycle_length = 30k = (sim.t // cycle_length) % 2self.current_cycle_index = int(k)

我们需要在Road类添加以下方法:

def set_traffic_signal(self, signal, group):self.traffic_signal = signalself.traffic_signal_group = groupself.has_traffic_signal = True@property
def traffic_signal_state(self):if self.has_traffic_signal:i = self.traffic_signal_groupreturn self.traffic_signal.current_cycle[i]return True

而这个,在Road的update方法。

# Check for traffic signal
if self.traffic_signal_state:# If traffic signal is green or doesn't exist# Then let vehicles passself.vehicles[0].unstop()for vehicle in self.vehicles:vehicle.unslow()
else:# If traffic signal is redif self.vehicles[0].x >= self.length - self.traffic_signal.slow_distance:# Slow vehicles in slowing zoneself.vehicles[0].slow(self.traffic_signal.slow_speed)if self.vehicles[0].x >= self.length - self.traffic_signal.stop_distance and\self.vehicles[0].x <= self.length - self.traffic_signal.stop_distance / 2:# Stop vehicles in the stop zoneself.vehicles[0].stop()

在Simulation 的update 方法中检查交通灯状态:

for signal in self.traffic_signals:signal.update(self)

在这里插入图片描述

12、曲线

在现实世界中,道路有曲线。虽然从技术上讲,我们可以通过手写很多道路的坐标来接近曲线来创建此模拟中的曲线,但我们可以在程序上实现同样的事情。

我们将使用贝赛尔曲线来达到这个效果。

我创建了一个curve.py文件,其中包含有助于创建曲线并按其道路序号引用曲线的功能。

def curve_points(start, end, control, resolution=5):# If curve is a straight lineif (start[0] - end[0])*(start[1] - end[1]) == 0:return [start, end]# If not return a curvepath = []for i in range(resolution+1):t = i/resolutionx = (1-t)**2 * start[0] + 2*(1-t)*t * control[0] + t**2 *end[0]y = (1-t)**2 * start[1] + 2*(1-t)*t * control[1] + t**2 *end[1]path.append((x, y))return pathdef curve_road(start, end, turn_direction, resolution=15):points = curve_points(start, end, turn_direction, resolution)return [(points[i-1], points[i]) for i in range(1, len(points))]

测试:

from trafficSimulator import *# Create simulation
sim = Simulation()# Add multiple roads
sim.create_roads([((0, 100), (140, 100)),((150, 110), (150, 200)),*curve_road((140, 100), (150, 110), (150, 100))
])sim.create_gen({'vehicle_rate': 20,'vehicles': [[1, {"path": [0, *range(2, 17), 1]}]]
})# Start simulation
win = Window(sim)
win.run(steps_per_update=5)

在这里插入图片描述

13、示例

这些示例的代码可在 Github 中找到。

公路匝道入口
在这里插入图片描述

双向交叉路口
在这里插入图片描述

环形交叉路口
在这里插入图片描述

钻石型分流交叉路口
在这里插入图片描述

14、局限性

虽然我们可以修改Simulation类来存储有关我们以后可以使用的模拟数据,但如果数据收集过程更加简化,则更好。

这种模拟仍然缺乏很多。曲线的实现是糟糕和低效的,并导致车辆和交通信号之间的相互作用的问题。

虽然有些人可能认为智能驱动模型有点过头了,但重要的是要有一个模型,可以复制现实世界的现象,如交通波(又名幽灵交通蛇)和司机的反应时间的影响。因此,我选择使用智能驱动模型。但对于精度和极端现实主义不重要的仿真,就像在视频游戏中一样,IDM可以被一个更简单的基于逻辑的模型所取代。

完全依赖基于仿真的数据会增加过度拟合的风险。你的 ML 模型可以优化用于仅存在于仿真中的处理,并且在现实世界中不存在。

15、结论

仿真是数据科学和机器学习的重要组成部分。有时,从现实世界中收集数据是不可能的,或者成本很高。生成数据有助于以更好的价格构建巨大的数据集。仿真还有助于填补真实数据中的空白。在某些情况下,现实世界数据集缺少对开发模型至关重要的边缘案例。

这个仿真是我参与的本科学校项目的一部分。目的是优化城市交叉路口的交通信号。我制作了此仿真来测试和验证我的优化方法。

我从来没有想过发表这篇文章,直到我看到特斯拉的AI展示日,其中他们谈到他们如何使用仿真来生成数据的边缘样本。


原文链接:Python交通流仿真 - BimAnt


http://chatgpt.dhexx.cn/article/RhO2hHX8.shtml

相关文章

基于深度学习的短时交通流预测与优化

TOC 第二章 数据预处理与短时交通流量特性分析 2.1 数据来源 数据记录了明尼苏达州双子城19条高速环城公路一整年的交通流量&#xff0c;交通流量数据采样间隔为30秒(采用2018年6月1日至8月31日期间&#xff0c;采集间隔为5分钟&#xff0c;选取公路上的5个车辆检测站点的交…

基于Spatial-Temporal Transformer的城市交通流预测

文章信息 本周阅读的论文是题目为《Spatial-Temporal Transformer Networks for Traffic Flow Forecasting》的一篇2021年发布在arXiv网站上的使用时空Transformer网络&#xff08;STTNs&#xff09;预测交通流的文章。 摘要 交通预测已成为智能交通系统的核心组成部分。然而&a…

基于推特数据挖掘交通事件的城市交通流深度学习预测模型

文章信息 本周阅读的论文是题目为《A deep-learning model for urban traffic flow prediction with traffic events mined from twitter》的一篇2021年发表在《World Wide Web》涉及交通事故下的城市交通客流预测的文章。 摘要 短期交通预测是现代城市交通管理和控制系统的关键…

交通流优化:一种强化学习方法

1. 文章信息 《Traffic flow optimization: A reinforcement learning approach》是2016年发表在Engineering Applications of Artificial Intelligence的一篇文章。 2. 摘要 交通拥堵会导致诸如延误、燃油消耗增加和额外污染等重要问题。本文提出了一种新的基于强化学习的交通…

SUMO交通流仿真实战

理解、预测并最终减少城市路网中的交通拥堵是一个复杂的问题。即使了解最简单的单车道情况下出现的交通拥堵&#xff0c; 也是具有挑战性的。SUMO是一个开源平台&#xff0c;可模拟复杂环境中的交通流。在这个教程里&#xff0c;我们将学习如何从零创建复杂的交通流模拟&#x…

python交通流预测算法_一种高速公路交通流预测方法与流程

本发明涉及智能交通领域,更具体地,涉及一种高速公路交通流预测方法。 背景技术: 随着社会经济的不断增长,国内汽车的拥有量越来越多,高速公路车流量急剧上升,从而导致高速公路上车辆拥堵愈发严重。现有方法采用径向基函数神经网络训练网络参数的算法,在粗略搜索过程中容…

交通流特征工程小技巧与思考

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、交通流是什么&#xff1f;二、特征工程是什么&#xff1f;三、处理数据时的一些小技巧四、一些常用的机器学习python库总结 前言 小编最近参与了一些工程方…

初等模型---交通流和道路通行能力

交通流的基本参数及其特性 为明确和简单起见&#xff0c;这里的交通流均指由标准长度的小型汽车在单方向的。 道路上行驶而形成的车流,没有外界因素如岔路、信号灯等的影响。 借用物理学的概念&#xff0c;将交通流近似看作一辆辆汽车组成的连续的流体&#xff0c;可以 用流量、…

交通流理论 第一章 绪论

第一章 绪论 1.1 交通流理论研究的内容和意义 交通流理论是运用物理学和数学的定律描述交通特性的交通工程学基础理论之一&#xff1b;道路设施可以分为两类&#xff1a;连续流和间断流设施。连续流设施为机动车流提供了相对连续的运行环境&#xff0c;几乎没有强制性阻断干扰…

数学小游戏:原创字谜几则

昨天晚上躺在床上发呆&#xff0c;想了几则数学字谜。下面每个式子都对应一个英文单词&#xff0c;例如的意思就是tank。 你能猜出多少个来呢&#xff1f; 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.

纵横字谜的答案

1.问题描述 输入一个r行c列(1<r,c<10)的网格&#xff0c;黑格用”*”表示&#xff0c;每个白格都填有一个字母&#xff0c;如果一个白格的左边相邻的位置或者边上相邻的位置没有白格&#xff08;可能是黑格&#xff0c;也可能除了网格边界&#xff09;&#xff0c; 则称…

猜字谜 C++

解析&#xff1a; 1.由于五位数*一位数等于六位数 而且万位等于第二位数各位所以A>3 2.D为1-9 3.整式变形为 DDDDDD/AABCAB 我们需判断一个每位数都一样的六位数除以一个3-9中的某个数A 结果需满足 万位等于十位等于A 千位等于个位 且没有余数 answer: #include<iostr…

猜字小游戏

文章目录 猜字小游戏猜字游戏升级版 猜字小游戏 编写程序 运行程序 猜字游戏升级版 编写程序 运行程序

纵横字谜的答案 (UVa232)

纵横字谜的答案 Time Limit:3000MS Memory Limit:0KB 64bit IO Format:%lld & %llu Submit Status Description Crossword Answers A crossword puzzle consists of a rectangular grid of black and white squares and two lists of definitions (or descriptio…

Scratch 教程《元宵猜灯谜》

程序演示 元宵节到了&#xff0c;用Scratch给小朋友做一个猜灯谜游戏&#xff01; 课程引入 青玉案元夕 【宋】辛弃疾 东风夜放花千树&#xff0c;更吹落、星如雨。宝马雕车香满路。凤箫声动&#xff0c;玉壶光转&#xff0c;一夜鱼龙舞。 蛾儿雪柳黄金缕&#xff0c;笑语盈盈暗…

Python 猜字谜游戏

import random WORDS ("python","import","hello","difficult","easy") print("欢迎来到猜单词游戏&#xff0c;请将乱序后的单词组成正确的单词") iscontinue "y" while iscontinue"y" or…

c语言猜字谜(详解)(后附完整源码)

c语言猜字谜 一.游戏前置二.游戏实现1.让电脑生成随机数2.让玩家重复输入3.输赢判断 一.游戏前置 向其他游戏一样&#xff0c;在游戏开始前&#xff0c;我们需要一个菜单让玩家进行选择 所以我们需要以下功能 1.一个能让玩家进行选择的函数&#xff08;switch&#xff09; 2.玩…

猜字谜小游戏

猜字谜小游戏 思路 : 先写一个菜单函数,打印一个菜单,获取用户输入 从菜单函数中调用Game函数 写Game函数里面的内容 从主函数中调用菜单函数 #include<stdio.h> #include<stdlib.h>//里面包含rand函数,system函数 #include<time.h> void Game(void);//声明…

猜字谜游戏

一个非常简单的猜数字游戏&#xff0c;在一个限定的范围内&#xff0c;系统会给出一个随机的未知数&#xff0c;让玩家自己去猜&#xff0c;并且还会根据玩家输入的数给出相应的提示。如下图&#xff1a; 原理很简单&#xff0c;主要通过Random函数构建循环方法&#xff0c;再用…