元胞自动机交通流模型c++_MATLAB——含出入匝道的交织区快速路元胞自动机模型...

这是一个使用C++和MATLAB实现的交通流模型,模拟了包含一条变速车道和出入匝道的快速路交织区。模型区分了自由换道和强制换道,并详细描述了车辆在不同区域的换道行为。车辆状态(出匝道或直行)影响其换道规则,如出匝道车辆在特定车道强制换道。模型遵循周期边界条件,但存在一些不足,例如未考虑车辆强制换道的位置限制、混合车种和非恒定密度情况。作者期待能与他人合作改进模型。
摘要由CSDN通过智能技术生成

03d287b988d809d6f6d98ffb41e7f96d.png

e2b9e50ee754ab0be2f39f30ff0abe35.gif
输出效果

本模型为包含一条变速车道和出入匝道的快速路交织区仿真模型。

ab9dcf4fa1b5b3c8f16a4af6c66cae89.png
车道编号

换道规则和不含出入匝道的路段的区别在于换道分为自由换道和强制换道。车辆在不同区域有不同换道状态,而车辆本身又有出匝道和直行(入匝道车辆归为直行车辆)两种状态,共同决定车辆换道行为。在自由换道区域(1,2,3,7,8,10,11,12车道)内按照普通路段换道规则换道,且不区分出匝道和直行车辆,即,若前车阻碍车辆对速度的追求则必定换道,且优先左换道,若前车无影响则概率左换道,而为了编程方便,规定两车道交界处,即,下一时间步将会驶出所在车道的车辆不允许换道。而强制换道区域(4,5,6,9,15)内换道规则因车辆状态的不同而不同,直行状态车辆任然按自由换道区域内车辆换道规则换道,出匝道车辆换道规则为,4车道中出匝道车辆强制向5车道换道,5车道车辆强制向6车道换道,6车道出匝道车辆不允许换道,这符合现实生活中车辆提前驶入靠变速车道车道的情况。其中,15车道车辆中为直行状态车辆(入匝道车辆)换道规则与出匝道车辆换道规则相反。

跟驰规则和NaSch模型基本规则相同,区分是驶出所在车道会驶入下一车道。

边界条件依然是周期边界条件,四个驶出车道,四个驶入车道,一一对应。

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


脚本

%%  交织区仿真
clc;
clear;
%%  参数设置
lane_length = 100; %车道长度
car_rate = 0.2;%车道占有率
time_span = 0.1;%图片输出时间间隔
p_out = 0.5;%车辆出匝道概率
v_max = 5;%最大速度
time_max = 1000;%仿真步长
p_changelane = 0.3;%车辆换道概率
p_slowdown = 0.3;%随机慢化概率
%%  调用函数
main(v_max,lane_length,time_span,p_out,car_rate,time_max,p_changelane,p_slowdown);

跟驰函数

function [lanes,car] = NaSch(lanes,car,v_max,lane_length,p_slowdown,car_number,p_out)
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,lanes);
             %%  判断车辆是否满足周期边界条件
         if  cycle %0是头车,1非头车
             %%  减速
              car.v(id) = min( car.v(id) , empty );
             %%  概率慢化
              if  rand(1) <= p_slowdown
                  car.v(id) = max( car.v(id)-1,0 );
              end
             %%  位置更新
              lanes ( car.lane(id),car.n(id) ) = 0;                 %位置更新前元胞变为无车
              car.n(id) = car.n(id) +car.v(id);
              lanes ( car.lane(id),car.n(id) ) = 1;   
         else
              if  car.lane(id)==10||car.lane(id)==11||car.lane(id)==12||car.lane(id)==13
                  %%  10,11,12,13执行周期边界条件
                  switch  car.lane(id)
                      case 10
                          lanes(car.lane(id),car.n(id)) =0;
                          car.lane(id) = 1;
                          car.n(id) = 1;
                          lanes(car.lane(id),car.n(id)) = 1;
                          if rand(1)<p_out
                             car.state(id) = 1;%概率驶出匝道 
                          end
                      case 11
                          lanes(car.lane(id),car.n(id)) =0;
                          car.lane(id) = 2;
                          car.n(id) = 1;
                          lanes(car.lane(id),car.n(id)) = 1;
                          if rand(1)<p_out
                             car.state(id) = 1;%概率驶出匝道 
                          end
                      case 12
                          lanes(car.lane(id),car.n(id)) =0;
                          car.lane(id) = 3;
                          car.n(id) = 1;
                          lanes(car.lane(id),car.n(id)) = 1;
                          if rand(1)<p_out
                             car.state(id) = 1;%概率驶出匝道
                          end
                      case 13
                          lanes(car.lane(id),car.n(id)) =0;
                          car.lane(id) = 14;
                          car.n(id) = 1;
                          lanes(car.lane(id),car.n(id)) = 1;
                          car.state(id) = 0;%状态更改为直行
                  end
                  
              elseif car.lane(id)==1||car.lane(id)==2||car.lane(id)==3||car.lane(id)==4||car.lane(id)==5||car.lane(id)==6||car.lane(id)==7||car.lane(id)==8||car.lane(id)==9
                  %%  1,2,3,4,5,6,7,8,9驶入另一条车道
                     [~,empty_next] = get_empty(car.lane(id)+3,1,v_max,lanes,lane_length);%获得与驶入车道前车的距离
                  %%  减速
                     car.v(id) = min( car.v(id) , empty+empty_next );
                  %%  概率慢化
                     if  rand(1) <= p_slowdown
                         car.v(id) = max( car.v(id)-1,0 );
                     end
                  %%  位置更新
                     if  car.v(id)<=empty
                         %%  仍在当前车道
                         lanes(car.lane(id),car.n(id)) = 0;
                         car.n(id) = car.n(id)+car.v(id) ;
                         lanes(car.lane(id),car.n(id)) = 1;
                     else
                         %%  驶入下一车道
                         lanes(car.lane(id),car.n(id)) = 0;
                         car.lane(id) = car.lane(id)+3;
                         car.n(id) = 1+car.v(id)-empty;
                         lanes(car.lane(id),car.n(id)) = 1;
                     end
              else
                  if car.lane(id) ==14
                      %15车道首个元胞无车则驶入,否则在入口等待
                      if  lanes(15,1)==0
                          lanes(car.lane(id),car.n(id))=0;
                          car.lane(id)=15;
                          car.n(id)=1;
                          lanes(car.lane(id),car.n(id))=1;
                      else
                          lanes(14,car.n(id))=0;
                          car.n(id)=lane_length;
                          lanes(car.lane(id),car.n(id))=1;
                      end
                  else
                      %15车道头车在11车道首个元胞无车则驶入,否则在出口等待
                      if  lanes(13,1)==0
                          lanes(car.lane(id),car.n(id))=0;
                          car.lane(id)=13;
                          car.n(id)=1;
                          lanes(car.lane(id),car.n(id))=1;
                      else
                          lanes(car.lane(id),car.n(id))=0;
                          car.n(id)=lane_length;
                          lanes(car.lane(id),car.n(id))=1;
                      end
                  end
              end 
        end
end
end

主函数

function  main(v_max,lane_length,time_span,p_out,car_rate,time_max,p_changelane,p_slowdown)
%%  空间,车道,车辆状态初始化
car_number = fix(14*lane_length*car_rate); %车辆数
[space,lanes,car]=initialiaze (v_max,lane_length,p_out,car_number);
%%  显示初始图像
H = imshow (space,[-1,0]);
%%  开始仿真
for time = 1:time_max
%%  换道
[car,lanes] = change_lane(lanes,car,car_number,p_changelane,v_max,lane_length);
%%  跟驰
[lanes,car] = NaSch(lanes,car,v_max,lane_length,p_slowdown,car_number,p_out);
%%  车道状态更新
space(1,1:lane_length) = lanes(1,:);
space(2,1:lane_length) = lanes(2,:);
space(3,1:lane_length) = lanes(3,:);
space(1,lane_length+1:2*lane_length) = lanes(4,:);
space(2,lane_length+1:2*lane_length) = lanes(5,:);
space(3,lane_length+1:2*lane_length) = lanes(6,:);
space(1,2*lane_length+1:3*lane_length) = lanes(7,:);
space(2,2*lane_length+1:3*lane_length) = lanes(8,:);
space(3,2*lane_length+1:3*lane_length) = lanes(9,:);
space(1,3*lane_length+1:4*lane_length) = lanes(10,:);
space(2,3*lane_length+1:4*lane_length) = lanes(11,:);
space(2,3*lane_length+1:4*lane_length) = lanes(12,:);
space(5:end,3*lane_length) = lanes(13,:)';
space(end:-1:5,2*lane_length+1) = lanes(14,:)';%注意此处的转置和元素反取
space(4,2*lane_length+1:3*lane_length) = lanes(15,:);
%%  输出图像
space = -1*space;
set(H,'CData',space);
pause(time_span);
space = -1*space;
end
end

初始化函数

function  [space,lanes,car]=initialiaze (v_max,lane_length,p_out,car_number)
%%  创建空间
space = zeros(4+lane_length,4*lane_length);
%非车道空间状态为0.1
space(4:end,1:2*lane_length)=0.1;
space(5:end,2*lane_length+1:3*lane_length-1)=0.1;
space(4:end,3*lane_length+1:4*lane_length)=0.1;
%创建车道矩阵
lanes = zeros(15,lane_length);%每行储存对应编号车道位置信息
%%  车辆结构体的创建
car = struct('v',zeros(1,car_number),'lane',zeros(1,car_number),'n',zeros(1,car_number),'state',zeros(1,car_number));
%依次为速度,所在车道编号,所在车道元胞位置,行驶状态
%%  车辆状态初始化
for a =1:14
    %向 a 车道随机投放车辆
    for  id = fix(car_number/14)*(a-1)+1 : fix(car_number/14)*a
          car.lane(id) = a;
          car.n(id) = fix( 1+rand(1)* (fix(lane_length-1) ) );
          lanes( car.lane(id),car.n(id) ) = 1; %有车状态为1
          car.v(id) = fix( 1+rand(1)*(v_max-1) );%随机生成速度
          if  rand(1)<p_out
              car.state(id) = 1;%出匝道车辆state值为1
          end
    end
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,lanes)
empty_front = 0;
cycle=1;
if  car.n(id) < lane_length-v_max       %判断是否到边界(lane_length-v_max)
    %%  求出车辆前方空元胞数
    front = car.n(id) + 1;
    while front~=car.n(id) + v_max 
          if lanes( car.lane(id),front )==1
             empty_front = front- (car.n(id)+1);
             break;
          end
          front = front +1;
    end
    if  front == car.n(id) + v_max 
        empty_front = v_max;
    end
else
    %% 判断是否是头车,非头车必定无法驶出车道
    front= min( ( car.n(id) + 1 ),lane_length );
    while front ~=lane_length
           if  lanes( car.lane(id),front )==1
               empty_front = front- min( ( car.n(id) + 1 ),lane_length );    %不是头车就输出空格数
               break;
           end
           front = front +1;
    end
    if  front == lane_length %前方无车则可能驶出车道
         empty_front = lane_length-car.n(id);
         cycle = 0;
    end
end
end

获取指定位置与前后首车距离

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

右侧车辆换道函数

function [lanes,car] = change_lane_right(id,lanes,car,v_max,lane_length,p_changelane,empty_safe)
%右侧车道车辆换道函数
 [~,empty]=get_empty_front(id,car,v_max,lane_length,lanes);%获取前方车距
 [empty_left_back,empty_left_front] = get_empty(car.lane(id)-1,car.n(id),v_max,lanes,lane_length);
 if  empty<min(car.v(id)+1,v_max)
     %%  前车阻碍车辆对速度的追求
     if  empty_left_front>=empty && empty_left_back>=empty_safe && lanes( car.lane(id)-1,car.n(id) )==0 %旁边车道距离更大,左后,旁边均安全
         %%  满足安全条件换道
         lanes(car.lane(id),car.n(id)) =0;
         car.lane(id) = car.lane(id)-1;
         lanes(car.lane(id),car.n(id)) =1;
     end
 else
     %%  前车无影响则概率换道
     if  rand(1)<p_changelane
         if  empty_left_front>=empty && empty_left_back>=empty_safe && lanes( car.lane(id)-1,car.n(id) )==0 %旁边车道距离更大,左后,旁边均安全
             %%  满足安全条件换道
             lanes(car.lane(id),car.n(id)) =0;
             car.lane(id) = car.lane(id)-1;
             lanes(car.lane(id),car.n(id)) =1;
         end
     end
     
 end
end

中间车辆换道函数

function [lanes,car] = change_lane_middle(id,lanes,car,v_max,lane_length,p_changelane,empty_safe)
 %中间车道换道
%%  获取周边车距
[~,empty]=get_empty_front(id,car,v_max,lane_length,lanes);%获取前方车距
[empty_right_back,empty_right_front] = get_empty(car.lane(id)+1,car.n(id),v_max,lanes,lane_length);
[empty_left_back,empty_left_front] = get_empty(car.lane(id)-1,car.n(id),v_max,lanes,lane_length);
if  empty<min(car.v(id)+1,v_max)
    %%  前车阻碍车辆对速度的追求
    %%  优先左换道
    if  empty_left_front>=empty && empty_left_back>=empty_safe && lanes( car.lane(id)-1,car.n(id) )==0 %旁边车道距离更大,左后,旁边均安全
        %%  满足左换道安全条件换道
        lanes(car.lane(id),car.n(id)) =0;
        car.lane(id) = car.lane(id)-1;
        lanes(car.lane(id),car.n(id)) =1;
    elseif  empty_right_front>=empty && empty_right_back>=empty_safe && lanes( car.lane(id)+1,car.n(id) )==0 %旁边车道距离更大,右后,旁边均安全
        %%  满足右换道安全条件换道
        lanes(car.lane(id),car.n(id)) =0;
        car.lane(id) = car.lane(id)+1;
        lanes(car.lane(id),car.n(id)) =1;
    end
else
    %%  前车无影响则概率向左换道
    if  rand(1)<p_changelane
        if  empty_left_front>=empty && empty_left_back>=empty_safe && lanes( car.lane(id)-1,car.n(id) )==0 %旁边车道距离更大,左后,旁边均安全
            %%  满足安全条件换道
            lanes(car.lane(id),car.n(id)) =0;
            car.lane(id) = car.lane(id)-1;
            lanes(car.lane(id),car.n(id)) =1;
        end
    end
    
end
end

左侧车辆换道函数

function [lanes,car] = change_lane_left(lanes,car,id,v_max,lane_length,p_changelane,empty_safe)
     %%  获取周边车距
     [~,empty]=get_empty_front(id,car,v_max,lane_length,lanes);%获取前方车距
     [empty_right_back,empty_right_front] = get_empty(car.lane(id)+1,car.n(id),v_max,lanes,lane_length);
     if  empty<min(car.v(id)+1,v_max)
         %%  前车阻碍车辆对速度的追求
         if  empty_right_front>=empty && empty_right_back>=empty_safe && lanes( car.lane(id)+1,car.n(id) )==0 %旁边车道距离更大,右后,旁边均安全
             %%  满足安全条件换道
             lanes(car.lane(id),car.n(id)) =0;
             car.lane(id) = car.lane(id)+1;
             lanes(car.lane(id),car.n(id)) =1;
         end
     else
         %%  前车无影响则概率换道
         if  rand(1)<p_changelane
             if  empty_right_front>=empty && empty_right_back>=empty_safe && lanes( car.lane(id)+1,car.n(id) )==0 %旁边车道距离更大,右后,旁边均安全
                 %%  满足安全条件换道
                 lanes(car.lane(id),car.n(id)) =0;
                 car.lane(id) = car.lane(id)+1;
                 lanes(car.lane(id),car.n(id)) =1;
             end
         end
         
     end
end

换道函数

function [car,lanes] = change_lane(lanes,car,car_number,p_changelane,v_max,lane_length)

empty_safe = v_max; %安全车距

for id=1:car_number
    
    if  car.lane(id)==1||car.lane(id)==2||car.lane(id)==3||car.lane(id)==7||car.lane(id)==8||car.lane(id)==10||car.lane(id)==11||car.lane(id)==12
        %%  自由换道区域:1,2,3,7,8,10,11,12
        [cycle,~]=get_empty_front(id,car,v_max,lane_length,lanes);%判断是否驶出所在车道
        if  cycle  %驶出车道车辆不允许换道
            %%  非驶出所在车道车辆
               if  car.lane(id) == 1||car.lane(id) ==7||car.lane(id) ==10
                    %%  左侧车道换道
                    [lanes,car] = change_lane_left(lanes,car,id,v_max,lane_length,p_changelane,empty_safe);
               elseif  car.lane(id)==2||car.lane(id)==8||car.lane(id)==11
                   %%  中间车道换道
                    [lanes,car] = change_lane_middle(id,lanes,car,v_max,lane_length,p_changelane,empty_safe);
               else
                   %%  右侧车道换道
                    [lanes,car] = change_lane_right(id,lanes,car,v_max,lane_length,p_changelane,empty_safe);
               end          
        end
        
    elseif  car.lane(id)==4||car.lane(id)==5||car.lane(id)==6||car.lane(id)==9||car.lane(id)==15
           %%  强制换道区域
           switch  car.lane(id)
              %%  6,9车道直行车辆只能向左变道,出匝道车辆不变道
               case 6
                   if car.state(id)==0%1是出匝道车辆,0是直行车辆
                      [lanes,car] = change_lane_right(id,lanes,car,v_max,lane_length,p_changelane,empty_safe);
                   end
               case 9
                   if car.state(id)==0%1是出匝道车辆,0是直行车辆
                      [lanes,car] = change_lane_right(id,lanes,car,v_max,lane_length,p_changelane,empty_safe);
                   else
                       %%  9中出匝道车辆强制向15换道
                       [empty_right_back,empty_right_front] = get_empty(15,car.n(id),v_max,lanes,lane_length);
                       if  empty_right_front>=1 && empty_right_back>=fix(v_max/2) && lanes(15,car.n(id))==0%15车道前方有距离且后方距离大于等于最大车速一半且旁边无车即可换道
                           %%  强制换道
                           lanes(9,car.n(id)) = 0;
                           car.lane(id) = 15;
                           lanes(9,car.n(id)) = 1;
                       end
                   end
               case 4
                   if car.state(id)==0%1是出匝道车辆,0是直行车辆
                     %%  4车道直行车辆只能向右变道
                      [lanes,car] = change_lane_left(lanes,car,id,v_max,lane_length,p_changelane,empty_safe);
                   else
                      %%  强制向5换道
                        [empty_right_back,empty_right_front] = get_empty(5,car.n(id),v_max,lanes,lane_length);
                        if  empty_right_front>=1 && empty_right_back>=fix(v_max/2) && lanes(5,car.n(id))==0%5车道前方有距离且后方距离大于等于最大车速一半且旁边无车即可换道
                            %%  强制换道
                            lanes(4,car.n(id)) = 0;
                            car.lane(id) = 5;
                            lanes(5,car.n(id)) = 1;
                        end
                   end
               case 5
                   if  car.state(id)==0
                       [lanes,car] = change_lane_middle(id,lanes,car,v_max,lane_length,p_changelane,empty_safe);
                   else
                     %%  强制向6换道
                       [empty_right_back,empty_right_front] = get_empty(6,car.n(id),v_max,lanes,lane_length);
                       if  empty_right_front>=1 && empty_right_back>=fix(v_max/2) && lanes(6,car.n(id))==0%6车道前方有距离且后方距离大于等于最大车速一半且旁边无车即可换道
                           %%  强制换道
                           lanes(5,car.n(id)) = 0;
                           car.lane(id) = 6;
                           lanes(6,car.n(id)) = 1;
                       end
                   end
               case 15
                   %%  15车道入匝道车辆强制向9换道,出匝道车辆不换道
                   if  car.state(id)==0%此处0为入匝道车辆
                       [empty_right_back,empty_right_front] = get_empty(9,car.n(id),v_max,lanes,lane_length);
                       if  empty_right_front>=1 && empty_right_back>=fix(v_max/2) && lanes(9,car.n(id))==0%9车道前方有距离且后方距离大于等于最大车速一半且旁边无车即可换道
                           %%  强制换道
                           lanes(15,car.n(id)) = 0;
                           car.lane(id) = 9;
                           lanes(9,car.n(id)) = 1;
                       end
                   end
           end
    end
    
end
end

目前缺点其实很多,只说几个,因为本人专业知识也很短缺。

1.没有设定车辆必须在到达某个位置前完成强制换道,同时,也没有考虑车辆无法完成强制换道的情况。

2.没有考虑混合车种,且只能模拟恒定密度情况的交通流。

3.强制换道规则合理性可能比较差,只参考了一篇论文中的强制换道规则,以及为了编程方便,先采取的强制换道规则是目标车道与前车距离大于等于一个元胞,与目标车道后车距离大于等于最大车速一半且目标车道旁边无车既可强制换道。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值