基于元胞自动机的传染病模型代码_MATLAB——汽车卡车混合车流元胞自动机模型...

该博客介绍了一种基于元胞自动机的混合车流交通流仿真模型,主要区分了汽车和卡车两种车型。模型在原有单向三车道模型基础上扩展,通过引入flag参数区分车辆类型。尽管存在车辆类型有限、行为差异未深入研究、换道冲突处理不完善以及可视化效果不佳等问题,博主提供了相关函数代码,并表达了希望与他人交流学习的愿望。
摘要由CSDN通过智能技术生成

9973e27c0c92488b67699cdc4e8f01e0.png

45293ca5f6a35e1b34db7306df9e4296.gif
输出效果

以往的大部分交通流仿真模型都是建立在交通流中只有一种车型的前提下,这显然与现实不符,所以本模型旨在建立基于元胞自动机的混合车流的交通流仿真模型。不过由于这两周课程有点紧,只在交通流中区分了汽车和卡车两种车辆类型,且两者只有车长和最大速度不同的区别。

本模型是在之前单向三车道模型的基础上更改形成。原理很简单且省事。简单说就是建立一个与汽车结构体内容完全相同的卡车结构体,引入flag参数,值可取1,0,分别代表汽车,卡车,这样做的好处是可以直接在原来为只有汽车写的函数稍作改动就可以直接用于卡车。需要做的一些改动比如,计算卡车后方车距要从卡车尾部算起,卡车换道还需要判断目标车道与尾部同列的位置是否有车以及卡车换道需要头部尾部都位置改变等,而还有很多是不需要改动的,比如换取与前车距离,车辆跟驰等。除此以外,卡车也采取了用固定车辆数和周期边界。

还是先贴代码,再说缺点哈。


脚本

%%  混合流模型
%%  此模型车辆从左向右运动,左右车道是以车辆前进方向的左右
clc;
clear;
%%  参数设置
lane_length = 200; %车道长度
car_rate = 0.1;  %车辆占有率
truck_rate = 0.1; %卡车占有率
v_max = 5; %最大车速
v_max_truck = 3;%卡车最大速度
time_max = 1000; %仿真步长
time_span = 0.1; %仿真图片输出间隔
p_slowdown = 0.3; %随机慢化概率
p_changelane = 0.3; %驾驶员换道欲望
%%  开始仿真
main(lane_length,car_rate,v_max,time_max,time_span,p_slowdown,p_changelane,truck_rate,v_max_truck);

跟驰函数

function [space,car] = NaSch(space,car,v_max,lane_length,p_slowdown,car_number,flag)
for id = 1:car_number
             %%  加速
              car.v(id) = min(car.v(id)+1,v_max);
             %%  获取车辆前空元胞数以及是否符合满足周期循环
              [cycle,empty]=get_empty_front(id,car,v_max,lane_length,space);
             %%  判断车辆是否满足周期边界条件
         if  cycle
             %%  减速
              car.v(id) = min( car.v(id) , empty );
             %%  概率慢化
              if  rand(1) <= p_slowdown
                  car.v(id) = max( car.v(id)-1,0 );
              end
             %%  位置更新
              if  flag
                  space ( car.m(id),car.n(id) ) = 0;                
                  car.n(id) = car.n(id) +car.v(id);
                  space ( car.m(id),car.n(id) ) = 1;
              else
                  space ( car.m(id),car.n(id) ) = 0;
                  space ( car.m(id),car.n(id)-1 ) = 0;
                  car.n(id) = car.n(id) +car.v(id);
                  space ( car.m(id),car.n(id) ) = 1;
                  space ( car.m(id),car.n(id)-1 ) = 1;
              end
         else
        %%  周期边界条件将头车以原速度道路最左边
              if flag
                 space ( car.m(id),car.n(id) ) = 0;
                 car.n(id) = 1;
                 space ( car.m(id),car.n(id) ) = 1;
              else
                 space ( car.m(id),car.n(id) ) = 0;
                 space ( car.m(id),car.n(id)-1 ) = 0;
                 car.n(id) = 2;
                 space ( car.m(id),car.n(id) ) = 1;
                 space ( car.m(id),car.n(id)-1 ) = 1;
              end
         end
end
end

主函数

%%  单向3车道主函数
%%  注意:在本模型中车辆位置信息由车道和列两个维度唯一确定
function  []= main(lane_length,car_rate,v_max,time_max,time_span,p_slowdown,p_changelane,truck_rate,v_max_truck)

car_number = fix(1+(3*lane_length-1)*car_rate); %按车辆占有率算出的车辆数
truck_number =  fix(1+(3*lane_length-1)*truck_rate);
%%  创建空间
space = zeros(3,lane_length);%元胞空间
car = struct('v',zeros(1,car_number),'m',zeros(1,car_number),'n',zeros(1,car_number));% 汽车车辆信息结构体从左到右为速度,车道,列
truck = struct('v',zeros(1,truck_number),'m',zeros(1,truck_number),'n',zeros(1,truck_number));% 卡车车辆车头信息结构体从左到右为速度,车道,列
%%  随机生成初始车辆信息
[space,car,truck] = initialize(space,car,truck,car_number,lane_length,v_max,truck_number,v_max_truck);

%%  显示初始仿真图
figure('name','汽车卡车混合车流','position',[241 132 560 420],'doublebuffer','on');%窗口名称,位置,双缓存)
space = -1*space;
H = imshow(space,[]);
title('汽车卡车混合车流','color','red');
space = -1*space;
%%  开始仿真
for time=1:time_max
    %%  换道阶段
    [car,space] = change_lane(space,car,car_number,p_changelane,v_max,lane_length,1);
    [truck,space] = change_lane(space,truck,truck_number,p_changelane,v_max_truck,lane_length,0);   %最后一位数字用于区分卡车换道还是汽车换道
    %%  跟驰阶段
    [space,car] = NaSch(space,car,v_max,lane_length,p_slowdown,car_number,1);
    [space,truck] = NaSch(space,truck,v_max_truck,lane_length,p_slowdown,truck_number,0);
    %%  显示仿真图
    space = -1*space;
    set(H,'CData',space);
    pause(time_span);
    space = -1*space;
end
end

初始化函数

function [space,car,truck] = initialize(space,car,truck,car_number,lane_length,v_max,truck_number,v_max_truck)
%%  随机生成初始汽车车辆信息
for id=1:car_number
    %%  位置信息初始化
    if  id<=fix(car_number/3)
        %%  最左边车道随机投放车辆
        car.m(id) = 1;
        car.n(id) = fix( 1+rand(1)*(lane_length-1) );
        while space(car.m(id),car.n(id))==1
              car.n(id) = fix( 1+rand(1)*(lane_length-1) );
        end
        space( 1,car.n(id) ) = 1;
    elseif  id<fix( (car_number*2)/3 )
        %%  中间车道随机投放车辆
        car.m(id) = 2;
        car.n(id) = fix( 1+rand(1)*(lane_length-1) );
        while space(car.m(id),car.n(id))==1
              car.n(id) = fix( 1+rand(1)*(lane_length-1) );
        end
        space( 2,car.n(id) ) = 1;
    else
        %%  最右边车道投放车辆   
        car.m(id) = 3;
        car.n(id) = fix( 1+rand(1)*(lane_length-1) );
        while space(car.m(id),car.n(id))==1
              car.n(id) = fix( 1+rand(1)*(lane_length-1) );
        end
        space( 3,car.n(id) ) = 1;
    end
    %%  速度信息初始化
    car.v(id) = fix( 1+rand(1)*(v_max-1) );
    
end

%%  随机生成初始卡车车辆信息
for id=1:truck_number
    %%  位置信息初始化
    if  id<=fix(truck_number/3)
        %%  最左边车道随机投放车辆
        truck.m(id) = 1;
        truck.n(id) = fix( 1+rand(1)*(lane_length-1) );
        while ( space(truck.m(id),truck.n(id))==1 || space(truck.m(id),max(truck.n(id)-1,1))==1) || truck.n(id)==1
              truck.n(id) = fix( 1+rand(1)*(lane_length-1) );
        end
        space( 1,truck.n(id) ) = 1;
        space(truck.m(id),truck.n(id)-1)=1;
    elseif  id<fix( (truck_number*2)/3 )
        %%  中间车道随机投放车辆
        truck.m(id) = 2;
        truck.n(id) = fix( 1+rand(1)*(lane_length-1) );
        while  ( space(truck.m(id),truck.n(id))==1 || space(truck.m(id),max(truck.n(id)-1,1))==1) || truck.n(id)==1
              truck.n(id) = fix( 1+rand(1)*(lane_length-1) );
        end
        space( 2,truck.n(id) ) = 1;
        space(truck.m(id),truck.n(id)-1)=1;
    else
        %%  最右边车道投放车辆   
        truck.m(id) = 3;
        truck.n(id) = fix( 1+rand(1)*(lane_length-1) );
        while  ( space(truck.m(id),truck.n(id))==1 || space(truck.m(id),max(truck.n(id)-1,1))==1) || truck.n(id)==1
              truck.n(id) = fix( 1+rand(1)*(lane_length-1) );
        end
        space( 3,truck.n(id) ) = 1;
        space(truck.m(id),max(truck.n(id)-1,1))=1;
    end
    %%  速度信息初始化
    truck.v(id) = fix( 1+rand(1)*(v_max_truck-1) );
    
end
end

获取前车距函数

%用于求出cell_i与前方元胞空元胞数并判断是否需要执行周期边界条件,cycle返回值为1不需要,0需要
%  输出EmptyFront为输入车辆处元胞前方空元胞数(超过v_max按v_max算)
function [cycle,empty_front] = get_empty_front(id,car,v_max,lane_length,space)
empty_front = 0;
cycle=1;
if  car.n(id)+v_max < lane_length-v_max       %判断是否到边界(lane_length-v_max)
    
    %%  求出车辆前方空元胞数
    for front= ( car.n(id) + 1 ) : ( car.n(id) + v_max )
        if space( car.m(id),front )==1
            empty_front = front- (car.n(id)+1);
            break;
        end
        empty_front = v_max;
    end
    
else
    %% 判断是否是头车
    first = 1;
    for front= min( ( car.n(id) + 1 ),lane_length ) :lane_length
        if  space( car.m(id),front )==1
            empty_front = front- (car.n(id)+1);    %不是头车就输出空格数
            first =0;
            break;
        end
    end
    if first
     %%  判断头车下一时间步是否可能移动到lane_length-1处
        if  car.n(id)+car.v(id)+1 >= lane_length-1
            cycle = 0;
        else
            empty_front =v_max;  %只要头车下一秒不到达lane_length前方空元胞数按v_max记
        end
    end
end
end

获取指定位置前后车距函数

%%  本函数用于求输入车辆前后车距
%%  输入参数m,n为一辆车的位置信息,输出该车所在车道前后车距,车距超过安全车距按安全车距算
function [empty_back,empty_front] = get_empty(m,n,v_max,space,lane_length,flag)
empty_back = 0;
empty_front = 0;
if flag %判断车辆类型  
    %%  求出汽车后方空元胞数
    for back=  n :-1: max(n-v_max ,1)
        if space( m,back )==1
            empty_back =n-back;
            break;
        end
        empty_back = v_max;
    end
    
else
    %%  求出卡车后方空元胞数
    for back=  n-1 :-1: max(n-v_max ,1)
        if space( m,back )==1
            empty_back =n-1-back;
            break;
        end
        empty_back = v_max;
    end
end
    %%  获取车辆前方空元宝数
    for front=  n: min(n+ v_max,lane_length) 
        if space( m,front )==1
            empty_front = n-front;
            break;
        end
        empty_front = v_max;
    end
end

换道函数

%%  换道函数
function [car,space] = change_lane(space,car,car_number,p_changelane,v_max,lane_length,flag)

   empty_safe = v_max; %安全车距

   for  id = 1:car_number
       [cycle,empty]=get_empty_front(id,car,v_max,lane_length,space);%卡车与汽车前方空格数求取方法相同,不予区分
       if  cycle   %执行周期边界条件车辆不换道
           
           if  car.m(id) == 1
           %%  最左侧车道换道
               %%  获取周边车距
               [empty_right_back,empty_right_front] = get_empty(car.m(id)+1,car.n(id),v_max,space,lane_length,flag);%flag用于区分车辆类型,1为汽车
               if  car.v(id)<= empty
                   %%  前车阻碍对速度的追求
                   if  empty_right_front>=empty_safe && empty_right_back>=empty_safe && space( car.m(id)+1,car.n(id) )==0 %右前,右后,旁边均安全
                       %%  满足安全条件换道
                       if flag
                          space (car.m(id),car.n(id)) =0;
                          car.m(id) = car.m(id)+1;
                          space (car.m(id),car.n(id)) =1;
                       else
                           if  space( car.m(id)+1,max(car.n(id)-1,1) )==0  %卡车还有判断尾部目标车道位置是否有车
                               space (car.m(id),car.n(id)) =0;
                               space (car.m(id),car.n(id)-1) =0;
                               car.m(id) = car.m(id)+1;
                               space (car.m(id),car.n(id)) =1;
                               space (car.m(id),car.n(id)-1) =1;
                           end
                       end
                   end
                   
           
               else
                   %%  前车无影响
                   if  rand(1)<p_changelane %概率换道
                       
                       if  empty_right_front>empty_safe && empty_right_back>empty_safe &&  space( car.m(id)+1,car.n(id) )==0 %右前,右后,旁边均安全
                           %%  满足安全条件换道
                           if flag
                               space (car.m(id),car.n(id)) =0;
                               car.m(id) = car.m(id)+1;
                               space (car.m(id),car.n(id)) =1;
                           else
                               if  space( car.m(id)+1,max(car.n(id)-1,1) )==0  %卡车还有判断尾部目标车道位置是否有车
                                   space (car.m(id),car.n(id)) =0;
                                   space (car.m(id),car.n(id)-1) =0;
                                   car.m(id) = car.m(id)+1;
                                   space (car.m(id),car.n(id)) =1;
                                   space (car.m(id),car.n(id)-1) =1;
                               end
                           end
                       end
                       
                   end
           
               end
       
       
           elseif  car.m(id) ==2
               %%  中间车道换道
               %%  获取周边车距
               [empty_right_back,empty_right_front] = get_empty(car.m(id)+1,car.n(id),v_max,space,lane_length,flag);
               [empty_left_back,empty_left_front] = get_empty(car.m(id)-1,car.n(id),v_max,space,lane_length,flag);
               if  car.v(id)<= empty
                   %%  前车阻碍对速度的追求
                   %%  向右换道
                   if  empty_right_front>=empty_safe && empty_right_back>=empty_safe && space( car.m(id)+1,car.n(id) )==0 %右前,右后,旁边均安全
                       %%  右边满足安全条件换道
                       if flag
                          space (car.m(id),car.n(id)) =0;
                          car.m(id) = car.m(id)+1;
                          space (car.m(id),car.n(id)) =1;
                       else
                           if  space( car.m(id)+1,max(car.n(id)-1,1) )==0  %卡车还有判断尾部目标车道位置是否有车
                               space (car.m(id),car.n(id)) =0;
                               space (car.m(id),car.n(id)-1) =0;
                               car.m(id) = car.m(id)+1;
                               space (car.m(id),car.n(id)) =1;
                               space (car.m(id),car.n(id)-1) =1;
                           end
                       end
                       %%  向左换道
                   elseif  empty_left_front>=empty_safe && empty_left_back>=empty_safe && space( car.m(id)-1,car.n(id) )==0
                         %%  满足安全条件换道
                       if flag
                          space (car.m(id),car.n(id)) =0;
                          car.m(id) = car.m(id)-1;
                          space (car.m(id),car.n(id)) =1;
                       else
                           if  space( car.m(id)-1,max(car.n(id)-1,1) )==0  %卡车还有判断尾部目标车道位置是否有车
                               space (car.m(id),car.n(id)) =0;
                               space (car.m(id),car.n(id)-1) =0;
                               car.m(id) = car.m(id)-1;
                               space (car.m(id),car.n(id)) =1;
                               space (car.m(id),car.n(id)-1) =1;
                           end
                       end
                   end
                   %%  前车不阻碍速度追求
               else
                   %%  以一定几率向右换道
                   if  rand(1)<p_changelane
                       
                       if  empty_right_front>empty_safe && empty_right_back>empty_safe &&  space( car.m(id)+1,car.n(id) )==0 %右前,右后,旁边均安全
                           %%  满足安全条件换道
                           if flag
                               space (car.m(id),car.n(id)) =0;
                               car.m(id) = car.m(id)+1;
                               space (car.m(id),car.n(id)) =1;
                           else
                               if  space( car.m(id)+1,max(car.n(id)-1,1) )==0  %卡车还有判断尾部目标车道位置是否有车
                                   space (car.m(id),car.n(id)) =0;
                                   space (car.m(id),car.n(id)-1) =0;
                                   car.m(id) = car.m(id)+1;
                                   space (car.m(id),car.n(id)) =1;
                                   space (car.m(id),car.n(id)-1) =1;
                               end
                           end
                       end
               
                   end
               end
        
        
           else
               %%  最右侧车辆换道
               %%  获取周边车距
               [empty_left_back,empty_left_front] = get_empty(car.m(id)-1,car.n(id),v_max,space,lane_length,flag);
               if  car.v(id)<= empty
                   %%  前车阻碍对速度的追求
                   if  empty_left_front>=empty_safe && empty_left_back>=empty_safe && space( car.m(id)-1,car.n(id) )==0 %右前,右后,旁边均安全
                       %%  满足安全条件换道
                       if flag
                          space (car.m(id),car.n(id)) =0;
                          car.m(id) = car.m(id)-1;
                          space (car.m(id),car.n(id)) =1;
                       else
                           if  space( car.m(id)-1,max(car.n(id)-1,1) )==0  %卡车还有判断尾部目标车道位置是否有车
                               space (car.m(id),car.n(id)) =0;
                               space (car.m(id),car.n(id)-1) =0;
                               car.m(id) = car.m(id)-1;
                               space (car.m(id),car.n(id)) =1;
                               space (car.m(id),car.n(id)-1) =1;
                           end
                       end
                   end
           
               else
                   %%  前车无影响
                   if  rand(1)<p_changelane
                       
                       if  empty_left_front>empty_safe && empty_left_back>empty_safe &&  space( car.m(id)-1,car.n(id) )==0 %右前,右后,旁边均安全
                           %%  满足安全条件换道
                           if flag
                               space (car.m(id),car.n(id)) =0;
                               car.m(id) = car.m(id)-1;
                               space (car.m(id),car.n(id)) =1;
                           else
                               if  space( car.m(id)-1,max(car.n(id)-1,1) )==0  %卡车还有判断尾部目标车道位置是否有车
                                   space (car.m(id),car.n(id)) =0;
                                   space (car.m(id),car.n(id)-1) =0;
                                   car.m(id) = car.m(id)-1;
                                   space (car.m(id),car.n(id)) =1;
                                   space (car.m(id),car.n(id)-1) =1;
                               end
                           end
                       end
               
                   end
           
               end
       
           end
       end
   end
end

说一下缺点,其实很多。

1.车辆类型依然只有两种。

2.汽车与卡车的行为差别没有查阅相关文章进行很好的区分。

3.目前函数中汽车结构体先作为参数运行换道函数,这样造成汽车与卡车有换道冲突点(比如,汽车,卡车一左一右均向中间车道同一位置换道)时,总是汽车拥有优先占有权利,与现实不符。

4.目前的可视化运用在混合车流效果很不好,需要学习别的可视化方法以及做GUI。

最后还是希望有想法的小伙伴可以加我一起讨论学习哈。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值