![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5iN4gjMzUTZkRWZwcTNkRzYjFzMyIzM2gTZ4IWM2UGZj9CX0JXZ252bj91Ztl2Lc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
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)<p_changelane %滿足換道條件時車輛以機率換道
map1(num2str(car_rate)) = map1(num2str(car_rate))+1; %計數器
space(car.m(id),car.n(id)) =0;
car.m(id) = car.m(id)+2*direction-1;
space(car.m(id),car.n(id)) =1;
end
end
最後,不管是plot () 和scatter () 都有包括線性(scatter的氣泡類型),顔色等屬性設定,具體檢視幫助文檔。