2020年6月8日更新双车道模型及流量密度图模板。
之前的模板都是无实物操作,所以,这次贴完整代码,是在双车道模型基础上出流量密度图。
%% 单向 2 车道模型——先更新换道完的位置,换道阶段和跟驰阶段位置更新分两步
%% 跟驰位置随机顺序更新
%% 此模型车辆从左向右运动,左右车道是以车辆前进方向的左右
clc;
clear;
dbstop if error;
%% 参数设置
lane_length = 100; %车道长度
car_rate = 0.3; %车辆占有率
v_max = 5; %最大车速
time_max = 1000; %仿真步长
time_span = 0.1; %仿真图片输出间隔
p_slowdown = 0.3; %随机慢化概率
empty_safe = 2; %安全车距
v_mid = zeros(1,time_max);
n_mid = 20;
v_mean = zeros(1,n_mid);
for rate = 1:n_mid
car_rate = (rate-1)/(n_mid);
car_number = fix(1+(2*lane_length-1)*car_rate); %按车辆占有率算出的车辆数
%% 创建空间
space = zeros(2,lane_length);%元胞空间
car = struct('v',zeros(1,car_number),'m',zeros(1,car_number),'n',zeros(1,car_number));% 车辆信息结构体从左到右为速度,车道,列
%% 随机生成初始车辆信息
for time = 1:car_number
%% 位置信息初始化
if time <= fix(car_number/2)
%% 向 1 车道随机投放车辆
car.m(time) = 1;
car.n(time) = fix( 1+rand(1)*(lane_length-1) );
while space(car.m(time),car.n(time))==1
car.n(time) = fix( 1+rand(1)*(lane_length-1) );
end
else
%% 向 2 车道随机投放车辆
car.m(time) = 2;
car.n(time) = fix( 1+rand(1)*(lane_length-1) );
while space(car.m(time),car.n(time))==1
car.n(time) = fix( 1+rand(1)*(lane_length-1) );
end
end
car.v(time) = fix( 1+rand(1)*(v_max-1) );
space(car.m(time) , car.n(time) ) = 1;
end
% %% 显示初始仿真图
% space = -1*space;
% H = imshow(space,[]);
% title('虚拟车道','color','red');
% space = -1*space;
%% 开始仿真
for time=1:time_max
if length(find(space == 1)) ~= car_number
keyboard;
end
%% 换道阶段
for id = 1:car_number
%% 车距获取
[empty_front,~] = get_empty(car.m(id),car.n(id),space,lane_length,v_max); %当前车道前车距
if car.m(id) == 1
m = 2;
else
m = 1;
end
[empty_front_aims,empty_back_aims] = get_empty(m,car.n(id),space,lane_length,v_max); %目标车道前后车距
if empty_front < min(car.v(id)+1,v_max)
%% 前车阻碍对速度的追求
if empty_front_aims >= empty_safe && empty_back_aims >= empty_safe && space(m,car.n(id) ) == 0 %目标车道前后及旁边均安全
%% 满足安全条件换道
space (car.m(id),car.n(id)) =0;
car.m(id) = m;
space (car.m(id),car.n(id)) =1;
end
end
end
%% 跟驰阶段
for id = 1:car_number
%% 加速
car.v(id) = min(car.v(id)+1,v_max);
%% 减速
[empty_front,~] = get_empty(car.m(id),car.n(id),space,lane_length,v_max); %当前车道前车距
car.v(id) = min( car.v(id) , empty_front );
%% 概率慢化
if rand(1) <= p_slowdown
car.v(id) = max( car.v(id)-1,0 );
end
%% 位置更新
space(car.m(id) , car.n(id)) = 0;
car.n(id) = car.n(id) + car.v(id);
if car.n(id) > lane_length %执行周期边界条件
car.n(id) = car.n(id) - lane_length;
end
space(car.m(id) , car.n(id)) = 1;
end
v_mid(time) = mean(car.v);
%% 显示仿真图
% space = -1*space;
% set(H,'CData',space);
% pause(time_span);
% space = -1*space;
end
v_mean(rate) = mean(v_mid);
end
disp(v_mean);
plot(1/(n_mid)*[0:n_mid-1]/0.005 , 1/(n_mid)*[0:n_mid-1]/0.005 .* v_mean*12);
xlabel('密度');
ylabel('流量');
%% 求距离函数
function [empty_front,empty_back] = get_empty(m,n,space,lane_length,v_max)
%用于求m车道n列的前车距,周期边界条件:头车的前车是尾车,尾车的后车是前车
space_mid = [space,space];
for mid = [1 , -1]
empty = 1;
while space_mid(m , n+mid*empty) == 0
empty = empty + 1;
if empty > v_max
break; %减少运算次数
end
end
if mid == 1
empty_front = empty - 1;
n = n + lane_length;
else
empty_back = empty - 1;
end
end
end
学matlab之后一直写模型,而没有对所得数据进行处理,之后更多做数据处理,但受制于专业知识及matlab水平,尤其对matlab出图这块实在菜的扣脚,暂时只想到以下三个类型的图,会不定时更新,希望看到的小伙伴能批评指正,相互学习。
以下内容以MATLAB——考虑驾驶员特性及前车速度的快速路模型为基础,建议先看完MATLAB——考虑驾驶员特性及前车速度的快速路模型,再看本篇文章。
在周边边界条件下,车辆数目固定,车道总长度固定,即,平均密度固定,平均速度可以算出,用平均密度*平均速度 = 平均流量。
空间占有率和密度的换算取决于单个元胞对应的实际长度。
ρ = rate / len
其中ρ是平均密度,rate是空间占有率,len是单个元胞对应的实际长度,单位:km。
①空间占有率-平均速度图
%% 数据储存矩阵的初始化
v = zeros(1,time_max);
v_mean = zeros(1,9);
for rate = 1:9 %获取不同车道占有率下的平均速度
car_rate = rate * 0.1; %车辆占有率
%% 随机生成初始车辆信息
car_number = fix(1+(3*lane_length-1)*car_rate); %按车辆占有率算出的车辆数
% 调用初始化函数
for time = 1:time_max
%% 仿真阶段
v(time) = mean(car.v); %每个时间步的平均速度
end
v_mean(rate) = mean(v); %总的平均速度
end
plot(0.1*[1:9] , v_mean);
xlabel('空间占有率');
ylabel('平均速度');
②时空图
出图的基本思路是,在每个时间步结束处,将space的值赋值给中间变量mid,并将mid中的1全部替换为time,以1:lane_length为横轴,再利用hold on,使每个时间步的空间分布图(一个时间步的空间分布图就是y = time这条散点线)出现在同一个图形界面(figure)上。
for time = 1:time_max
%%
%%仿真阶段
%%
mid= space(1,:)
mid(mid == 1) = time;
scatter(1:lane_length , mid,1); %第三个输入参数可以调节气泡大小
hold on;
end
xlabel('空间');
ylabel('时间');
③换道次数-空间占有率
利用containers.Map类型作为函数输入可以直接更改键对值的特点。containers.Map不了解可看这篇文章。
map1 = containers.Map;
for rate = 1:9
car_rate = 0.1*rate; %车辆占有率
map1(num2str(car_rate)) = 0;
%%
%%其他过程
%%
if car.m(id) == 1
[space,car] = change_lane(space,car,lane_length,id,empty_front,v_front,p_changelane,1,car_rate,map1);
elseif car.m(id) == 2
[space,car] = change_lane(space,car,lane_length,id,empty_front,v_front,p_changelane,2,car_rate,map1);
elseif car.m(id) == 3
[space,car] = change_lane(space,car,lane_length,id,empty_front,v_front,p_changelane,0,car_rate,map1);
end
%%
%%跟驰阶段
%%
end
plot(0.1*[1:9] , cell2mat(map1.values)); %注意,map.values返回类型为元胞
xlabel('空间占有率');
ylabel('换道次数');
%% 换道函数
%%
%% 中间过程
%% 换道决策
if a && b && c
if rand(1)
最后,不管是plot () 和scatter () 都有包括线性(scatter的气泡类型),颜色等属性设置,具体查看帮助文档。