Advertisement

python元胞自动机模拟三车道自动驾驶车辆与人驾驶车辆混合通行

阅读量:

模型摘要
该模型模拟了自动驾驶和人驾驶车辆在公路上的行驶行为,重点研究了车辆进入、移动、车道变更以及离开路口的规则。通过设置不同比例的自动驾驶车辆,观察其对通过路口车辆数的影响。结果表明,自动驾驶车辆的比例对通过车辆数呈现显著的线性关系,自动驾驶车辆的比例越高,通过的车辆数也越多。该研究为理解车辆行为对交通流量的影响提供了新的视角。

一、 任意车道离开

  1. 公路模型创建:初始化两个二维数组,分别用于保存当前状态和更新后的状态。当前状态数组中,0表示该位置无车辆,1表示有人驾驶车辆,2表示有自动驾驶车辆。
  2. 模拟车辆的进入:由于规定一般条件下前方三个车位的空间内有车辆,此车会在此步时处于静止状态以模拟减速。因此,若每步时会随机生成车辆,道路覆盖率的控制难度较大。为了解决这一问题,我们每隔四步时进行一次车辆的随机生成模拟。
  3. 模拟车辆的前进:遍历所有公路元素,若当前元素为自动驾驶车辆且满足正常行驶条件,则将车辆状态传递给右侧元素。若当前元素为人驾驶车辆且前方三个车位为空,则有20%的概率前进两步以模拟加速操作。此外,为了模拟人驾驶车辆的不稳定性,我们设定人驾驶车辆有5%的概率前进、5%概率后退,以模拟非匀速运动。
  4. 模拟车辆的离开:若车辆到达模拟公路末端,计数器增加一,并将该位置元素置为0以完成车辆离开状态的模拟。同时,可以统计通过的车辆数目。
  5. 模拟更改车道:根据问题一的结论,人驾驶车辆具有根据路况更换车道的能力。因此,若在移动过程中该车辆为人驾驶车辆,则会在一定约束条件下完成车道更改,即将其值赋给目标车道的相同位置的下一位置。
复制代码
    import numpy as np
    import random
    import copy
    import matplotlib.pyplot as plt
    plt.rcParams['font.sans-serif'] = ['SimHei']
    plt.rcParams['axes.unicode_minus'] = False
    
    
    def make_car(way, auto_p, car_p):
    if cell_temp[way][0] == 0:
        leng[way] = leng[way] + 1
        if random.randint(1, 100) <= car_p *(1- auto_p) * 100:
            cell_temp[way][0] = 1  # people's car
        elif random.randint(1, 100) <= car_p *auto_p * 100:
            cell_temp[way][0] = 2  # auto car
    
    
    def move(way):
    for j in range(0, width-1):
        if j==0 and cell[way][0]!=0:
            x = 0
            for i in range(j+1,j+4):
                if cell[way][i]!=0:
                    x=1
            if x==0:
                cell_temp[way][1]=cell_temp[way][0]
                cell_temp[way][0]=0
        elif cell[way][j]!=0:
            if change_way(way, j) == 1:
                continue
            x = 0
            for i in range(j+1,min(j+3,width-1)):
                if cell[way][i]!=0:
                    x=1
            if x==0:
                if  j+3<width-4 and cell[way][j+3]== 0 and cell_temp[way][j]==1 and random.randint(1,100)<=20:
                        cell_temp[way][j+2]=cell_temp[way][j]
                        cell_temp[way][j] = 0
                        k = j+2
                else:
                    cell_temp[way][j+1]=cell_temp[way][j]
                    cell_temp[way][j]=0
                    k=min(j+1,width-2)
                if cell_temp[way][k]==1:
                    if random.randint(1,100)<=5 and cell_temp[way][k-1]==0:
                        cell_temp[way][k-1]=1
                        cell_temp[way][k]=0
                    elif random.randint(1,100)<=5 and cell_temp[way][k+1]==0:
                        cell_temp[way][k + 1] = 1
                        cell_temp[way][k] = 0
    
    
    def remove(way):
    if cell_temp[way][width-1]!=0:
        leng[3] = leng[3]+1
        leng[way] = leng[way] -1
        cell_temp[way][width-1]=0
    
    
    def change_way(way,local):
    m = 0
    n = 0
    if way ==1:
        if leng[way]*2/3 > leng[way+1] and leng[way]>10:
            for i in range(local-3,local+4):
                if cell[way+1][i] != 0:
                    m = 1
            if m == 0:
                cell_temp[way+1][local+1]=cell_temp[way][local]
                cell_temp[way][local] = 0
                leng[way]=leng[way]-1
                leng[way+1] = leng[way]+1
        if leng[way] * 2 / 3 > leng[way - 1]:
            for i in range(local - 3, local + 4):
                if cell[way - 1][i] != 0:
                    n = 1
            if n == 0:
                cell_temp[way - 1][local + 1] = cell_temp[way][local]
                cell_temp[way][local] = 0
                leng[way] = leng[way] - 1
                leng[way - 1] = leng[way] + 1
        if m + n < 2:
            return 0
        else:
            return 1
    if way == 0:
        if leng[way]*2/3 > leng[way+1]:
            for i in range(local-3,local+4):
                if cell[way+1][i] != 0:
                    m = 1
            if m == 0:
                cell_temp[way+1][local+1]=cell_temp[way][local]
                cell_temp[way][local] = 0
                leng[way]=leng[way]-1
                leng[way+1] = leng[way+1]+1
        if m == 0:
            return 0
        else:
            return 1
    if way == 2:
        if leng[way] * 2 / 3 > leng[way - 1]:
            for i in range(local - 3, local + 4):
                if cell[way - 1][i] != 0:
                    n = 1
            if n == 0:
                cell_temp[way - 1][local + 1] = cell_temp[way][local]
                cell_temp[way][local] = 0
                leng[way] = leng[way] - 1
                leng[way - 1] = leng[way] + 1
        if n == 0:
            return 0
        else:
            return 1
    
    
    if __name__ == '__main__':
    length = 3
    width = 200
    d = 0
    cell = np.zeros((length,width),int)
    cell_temp = copy.deepcopy(cell)
    for i in range(0, length):
        for j in range(0,width):
            cell_temp[i][j] = 0
    #cell_temp[i][1] = 1
    #cell_temp[i][2] = 1
    global leng
    leng = {0: 0, 1: 0, 2: 0, 3: 0}
    list1 = []
    for i in range(0, 100):
        while True:
            if d % 4 == 0:
                make_car(0, i/100, 0.8)
            if d % 3 == 0:
                make_car(1, i/100, 0.8)
            if d % 5 == 0:
                make_car(2, i/100, 0.8)
            cell = copy.deepcopy(cell_temp)
            # 显示每一轮的图像
            plt.imshow(cell)
            plt.pause(0.000000001)
            move(0)
            move(1)
            move(2)
            remove(0)
            remove(1)
            remove(2)
            d = d + 1
            if leng[3] >= 2000:
                list1.append(d)
                d=0
                leng[3]=0
                break
            print(len(list1))
            print(leng[3])
    
    print(list1)
    
    x=np.arange(0,1,0.01)
    ax = plt.subplot()
    ax.set_xlabel('自动驾驶车辆比例')
    ax.set_ylabel('通过2000辆车步时')
    plt.text(x=-0.1,  # 文本x轴坐标
             y=0,  # 文本y轴坐标
             s='p = 0.3',  # 文本内容
    
             fontdict=dict(fontsize=12, color='r', family='monospace', ),  # 字体属性字典
    
             # 添加文字背景色
             bbox={'facecolor': '#74C476',  # 填充色
                   'edgecolor': 'b',  # 外框色
                   'alpha': 0.5,  # 框透明度
                   'pad': 0.8,  # 本文与框周围距离
                   'boxstyle': 'sawtooth'
                   }
    
             )
    
    plt.plot(x, list1)
    plt.show()

运行结果

不同颜色代表不同小车
结束后画出图像

二、每辆小车出现时随机获得一个离开路口

针对问题分析中提出的问题,我们在问题二模型的基础上做出如下改变:

  1. 目的车道信息的保存:我们引入了一个新的二维数组来保存目的车道并跟随表示公路的二维数组同等变化,车辆到达目的车道后新二位数组的值赋为-1,作为标识不再变化
  2. 更换车位规则变化:若车辆处在目的车道,则新二位数组值赋为-1,否则,若为自动驾驶则会在即将到达道路尽头位置开始改变车道,若为人驾驶车辆,则会在第一次遇到符合变道条件的时候进行改变车道
  3. 模拟车辆离开规则变化:新增判断条件,只有新二维数组标识为-1才可以离开。
复制代码
    import numpy as np
    import random
    import copy
    import matplotlib.pyplot as plt
    plt.rcParams['font.sans-serif'] = ['SimHei']
    plt.rcParams['axes.unicode_minus'] = False
    
    
    def make_car(way, auto_p, car_p):
    if cell_temp[way][0] == 0:
        leng[way] = leng[way] + 1
        if random.randint(1, 100) <= car_p *(1- auto_p) * 100:
            cell_temp[way][0] = 1  # people's car
        elif random.randint(1, 100) <= car_p *auto_p * 100:
            cell_temp[way][0] = 2  # auto car
    cell2[way][0] = random.randint(0, 2)
    
    
    def move(way):
    for j in range(0, width-1):
        if j==0 and cell[way][0]!=0:
            x = 0
            for i in range(j+1,j+4):
                if cell[way][i]!=0:
                    x=1
            if x==0:
                cell_temp[way][1]=cell_temp[way][0]
                cell_temp[way][0]=0
                cell2[way][1] = cell2[way][0]
                cell2[way][0] = -1
        elif cell[way][j]!=0:
            if cell2[way][j] == way:
                cell2[way][j] = -1
            if cell2[way][j] != -1 and cell_temp[way][j] == 1:
                a = change_way(way, j)
                if a ==0:
                    continue
            elif cell2[way][j] != -1 and cell_temp[way][j] == 2 and j+5+way>width:
                a = change_way(way, j)
                if a == 0:
                    continue
            x = 0
            for i in range(j+1,min(j+3,width-1)):
                if cell[way][i]!=0:
                    x=1
            if x==0:
                if  j+3<width-4 and cell[way][j+3]== 0 and cell_temp[way][j]==1 and random.randint(1,100)<=20:
                        cell_temp[way][j+2]=cell_temp[way][j]
                        cell_temp[way][j] = 0
                        cell2[way][j + 2] = cell2[way][j]
                        cell2[way][j] = 0
                        k = j+2
                else:
                    cell_temp[way][j+1]=cell_temp[way][j]
                    cell_temp[way][j]=0
                    cell2[way][j + 1] = cell2[way][j]
                    cell2[way][j] = 0
                    k=min(j+1,width-2)
                if cell_temp[way][k]==1:
                    if random.randint(1,100)<=5 and cell_temp[way][k-1]==0:
                        cell_temp[way][k-1]=1
                        cell_temp[way][k]=0
                        cell2[way][k - 1] = cell2[way][k]
                        cell2[way][k] = -1
                    elif random.randint(1,100)<=5 and cell_temp[way][k+1]==0:
                        cell_temp[way][k + 1] = 1
                        cell_temp[way][k] = 0
                        cell2[way][k + 1] = cell2[way][k]
                        cell2[way][k] = -1
    
    
    def remove(way):
    if cell_temp[way][width-1] != 0 and cell2[way][width-1]==-1:
        leng[3] = leng[3]+1
        leng[way] = leng[way] -1
        cell_temp[way][width-1]=0
    
    
    def change_way(way, local):
    m = 0
    n = 0
    if way ==1:
        if cell2[way][local] != way:
            for i in range(local-3,min(local+4,width-1)):
                if cell[cell2[way][local]][i] != 0:
                    m = 1
            if m == 0:
                cell_temp[cell2[way][local]][local+1]=cell_temp[way][local]
                cell_temp[way][local] = 0
                leng[way]=leng[way]-1
                leng[cell2[way][local]] = leng[cell2[way][local]]+1
                cell2[cell2[way][local]][local+1] = -1
                cell2[cell2[way][local]][local] = 0
        if m == 0:
            return 0
        else:
            return 1
    if way == 0:
        if cell2[way][local] != way:
            for i in range(local-3,min(local+4,width-1)):
                if cell[1][i] != 0:
                    m = 1
            if m == 0:
                cell_temp[1][local+1]=cell_temp[way][local]
                cell_temp[way][local] = 0
                leng[way]=leng[way]-1
                leng[1] = leng[1]+1
                cell2[1][local + 1] = cell2[way][local]
                cell2[way][local] = 0
        if m == 0:
            return 0
        else:
            return 1
    if way == 2:
        if cell2[way][local] != way:
            for i in range(local - 3, min(local + 4,width-1)):
                if cell[1][i] != 0:
                    m = 1
            if m == 0:
                cell_temp[1][local + 1] = cell_temp[way][local]
                cell_temp[way][local] = 0
                leng[way] = leng[way] - 1
                leng[1] = leng[1] + 1
                cell2[1][local + 1] = cell2[way][local]
                cell2[way][local] = 0
        if m == 0:
            return 0
        else:
            return 1
    
    
    if __name__ == '__main__':
    length = 3
    width = 200
    d = 0
    cell = np.zeros((length,width),int)
    cell_temp = copy.deepcopy(cell)
    cell2 = copy.deepcopy(cell)
    for i in range(0, length):
        for j in range(0,width):
            cell_temp[i][j] = 0
    for i in range(0, length):
        for j in range(0,width):
            cell2[i][j] = -1
    #cell_temp[i][1] = 1
    #cell_temp[i][2] = 1
    global leng
    leng = {0: 0, 1: 0, 2: 0, 3: 0}
    list1 = []
    for i in range(0, 100):
        while True:
            if d % 4 == 0:
                make_car(0, i/100, 0.3)
            if d % 3 == 0:
                make_car(1, i/100, 0.3)
            if d % 5 == 0:
                make_car(2, i/100, 0.3)
            cell = copy.deepcopy(cell_temp)
            # 显示每一轮的图像
            plt.imshow(cell)
            plt.pause(0.000000001)
            move(0)
            move(1)
            move(2)
            remove(0)
            remove(1)
            remove(2)
            d = d + 1
            if leng[3] >= 2000:
                list1.append(d)
                d=0
                leng[3]=0
                break
            print(len(list1))
            print(leng[3])
    
    print(list1)
    
    x = np.arange(0, 1, 0.01)
    ax = plt.subplot()
    ax.set_xlabel('自动驾驶车辆比例')
    ax.set_ylabel('通过2000辆车步时')
    plt.text(x=-0.1,  # 文本x轴坐标
             y=0,  # 文本y轴坐标
             s='p = 0.3',  # 文本内容
    
             fontdict=dict(fontsize=12, color='r', family='monospace', ),  # 字体属性字典
    
             # 添加文字背景色
             bbox={'facecolor': '#74C476',  # 填充色
                   'edgecolor': 'b',  # 外框色
                   'alpha': 0.5,  # 框透明度
                   'pad': 0.8,  # 本文与框周围距离
                   'boxstyle': 'sawtooth'
                   }
    
             )
    
    plt.plot(x, list1)
    plt.show()
在这里插入图片描述

由于设定自动驾驶小车过于呆所以结果就差不多线性了。。。

全部评论 (0)

还没有任何评论哟~