基于元胞自动机NaSch模型的多车道手动-自动混合驾驶仿真模型的Matlab实现
模型的建立基本来自于:http://www.doc88.com/p-2078634086043.html
花了一天半的时间用新学会的matlab实现了一下。
───────────────────────────────────────────────────────────────────────────────────────
2018-1-31更新:
居然真的有人会看我的博文诶,那我不能就这么不负责任的直接甩代码跑路了,稍微评价一下我自己的代码吧……
1、首先是优点,就是能用(囧),调调参数,几个车道,多少元胞,多少辆车,自动驾驶车手动驾驶车比例,基本都能改。
2、缺点一:各种规则十分不清晰明确,正确性有待商榷……
特别是变道规则,又臭又长,我自己写完之后都不想看第二遍,而且我怀疑跟论文里写的规则有出入(虽然我说实话,论文里的变道规则也说的不是很清晰)
3、缺点二:速度贼慢,慢的跟爬一样。因为这个代码是为了数学建模敲的,所以也多考虑优化速度什么的,直接就简单粗暴地写了。
这导致了,我在出结果的时候,车道数不敢设大于3,元胞数不敢设大于200,循环时常不敢超过300,;
即使这样,初始放入车辆的时候,元胞占用率大于0.3的时候,程序跑的就肉眼可见的慢,如果想跑个几十上百组的数据求平均的话,估计可以打局王者荣耀再来看看结果……
4、稳定性贼差,我算结果的时候,几百组几百组求平均(元胞占用率0.0几的情况下,跑的还是挺快的),结果都稳定不下来……导致我们敏感性分析基本等于瞎扯。
感觉自己是真鸡儿的菜,写了这么久的代码,敲个稍微大点的程序,还是敲得跟坨shit一样
───────────────────────────────────────────────────────────────────────────────────────
2018-5-7更新:
emmm发现居然少贴了一个函数的代码,补上了calc_Vave()函数;
然后关于这个模型怎么用……
最简单的用法是:
更改global变量的值(车辆数、车道数、自动驾驶车辆占比等等等等),更改模拟时长T,然后运行NaSch()这个函数,返回的ans答案是整个时长T内所有车辆的平均速度
───────────────────────────────────────────────────────────────────────────────────────
NaSch模型主函数:
function [ret_Vave] = NaSch()
rng('shuffle'); global CellsNum; CellsNum = 200; %The number of cells in each lane
global LanesNum; LanesNum = 3; %The number of Lanes
global D; D = 0.02; %The cell occupancy rate
global L; L = 5; %The length of one cell
global CarsNum; CarsNum = round( LanesNum .* CellsNum .* D ); %The number of cars
global SelfRatio; SelfRatio = 0.5; %Self-driving vehicle rate
global Vmin; Vmin = 1; %Minimum speed limit
global Vmax; Vmax = 6; %Maximum speed limit %Meet the lane changing conditions...
global ChangeRightP; ChangeRightP = 0.5; %The probability of changing into the right lane
global ChangeLeftP; ChangeLeftP = 0.8; %The probability of changing into the left lane [z,cars] = RoadInit();
cells = z;
cars = CarInit(cars); T = 1000; %The duration of simulation
Vave = zeros(1,T); %Average velocity per unit time global loopCars; loopCars = [];
%Start the simulation
for t = 1:1:T [cells,cars] = EntryControl(cells,cars); %Calculate each distance
[d,d_safe,d_l_for,d_l_bac,d_r_for,d_r_bac] = calcDist(cells,cars); %Get the next state
for i = 1:1:CarsNum
if(cars(i).M==1) %Leftmost lane
[cells,cars] = L_NextState(i,cells,cars,d,d_safe,d_l_for,d_l_bac,d_r_for,d_r_bac);
elseif(cars(i).M==LanesNum) %Rightmost lane
[cells,cars] = R_NextState(i,cells,cars,d,d_safe,d_l_for,d_l_bac,d_r_for,d_r_bac);
else %Middle lane
[cells,cars] = M_NextState(i,cells,cars,d,d_safe,d_l_for,d_l_bac,d_r_for,d_r_bac);
end
end cars = RandSlow(cars);
[cells,cars] = Update(cells,cars);
cells = cells(1:LanesNum,1:CellsNum); %Control the size of Cells Matrix
Vave(t) = calc_Vave(cars); %Calculate current average velocity
end ret_Vave = mean(Vave); %Calculate average velocity
end
初始化函数:
function [cell_mat,car_mat] = RoadInit()
global LanesNum;
global CellsNum;
global CarsNum; mat = zeros(LanesNum,CellsNum); Car(1,CarsNum) = struct('ID',[],'V',[],'M',[],'N',[],'Self',[]);
%Vehicle Information: ID, Speed, Position, Whether self driving or not for i = 1:1:CarsNum
m=round( 1 + ( LanesNum - 1 ) * rand(1) );
n=round( 1 + ( CellsNum - 1 ) * rand(1) );
while( mat(m,n) ~= 0 )
m = round( 1 + ( LanesNum - 1 ) * rand(1) );
n = round( 1 + ( CellsNum - 1 ) * rand(1) );
end
mat(m,n) = i; Car(i).ID = i;
Car(i).M = m;
Car(i).N = n;
end cell_mat = mat;
car_mat = Car;
end
function car_mat = CarInit(Car)
global CarsNum;
global Vmin;
global Vmax;
global SelfRatio; for i = 1:1:CarsNum
Car(i).V = round( Vmin + ( Vmax - Vmin ) * rand(1) );
if(rand(1)<=SelfRatio) Car(i).Self = 1;
else Car(i).Self = 0;
end
end car_mat = Car;
end
入口控制:
function [new_cells,new_cars] = EntryControl(cells,cars)
global loopCars;
global LanesNum;
global Vmin; while(StackSize(loopCars) > 0) if( all( cells(:,1) ~= 0 ) == 1 )
break
end for i = 1:1:LanesNum
if(cells(i,1) == 0)
id = topStack(loopCars); popStack(loopCars);
cells(i,1) = id;
cars(id).V = Vmin;
cars(id).M = i;
cars(id).N = 1;
break
end
end end new_cells = cells;
new_cars = cars;
end
计算各种车距:
function [Ret_d,Ret_d_safe,Ret_d_l_for,Ret_d_l_bac,Ret_d_r_for,Ret_d_r_bac] = calcDist(cells,cars)
global LanesNum;
global CellsNum;
global CarsNum; d = linspace(-1,-1,CarsNum);
d_safe = linspace(-1,-1,CarsNum);
d_l_for = linspace(-1,-1,CarsNum);
d_l_bac = linspace(-1,-1,CarsNum);
d_r_for = linspace(-1,-1,CarsNum);
d_r_bac = linspace(-1,-1,CarsNum); for i = 1:1:CarsNum m = cars(i).M; %The m_th lane
n = cars(i).N; %The n_th cell %Calculate the distance to front car
d(i) = inf;
for f = n+1:1:CellsNum
if(cells(m,f) ~= 0)
d(i) = f - n;
break
end
end %If the left lane exist
if( m-1 >= 1 )
%Forward
d_l_for(i) = inf;
for p = n:1:CellsNum
if( cells( m-1 , p ) ~= 0 )
d_l_for(i) = p - n;
break
end
end
%Backward
for p = n:-1:1
d_l_bac(i) = inf;
if( cells( m-1 , p ) ~= 0 )
d_l_bac(i) = n - p;
break
end
end
end %If the right lane exist
if( m+1 <= LanesNum )
%Forward
d_r_for(i) = inf;
for p = n:1:CellsNum
if( cells( m+1 , p ) ~= 0 )
d_r_for(i) = p - n;
break
end
end
%Backward
d_r_bac(i) = inf;
for p = n:-1:1
if( cells( m+1 , p ) ~= 0 )
d_r_bac(i) = n - p;
break
end
end
end %The d_safe of two kinds of cars is different
if(cars(i).Self == 1)
d_safe(i) = cars(i).V;
else
d_safe(i) = 2 .* cars(i).V;
end end Ret_d = d;
Ret_d_safe = d_safe;
Ret_d_l_for = d_l_for;
Ret_d_l_bac = d_l_bac;
Ret_d_r_for = d_r_for;
Ret_d_r_bac = d_r_bac;
end
加减速规则实现:
function new_cars = Accelerate(id,cars,d,d_Safe)
global Vmax;
global Pa;
Pa = 0.8; %Acceleration probability if( d(id) > d_Safe(id) && cars(id).V < Vmax )
if(rand(1) <= Pa)
cars(id).V = cars(id).V + 1;
end
end new_cars = cars;
end
function new_cars = Decelerate(id,cars,d,d_safe)
global Vmax;
global Vmin; if( d(id) < d_safe(id) && d(id) >= Vmax - Vmin )
cars(id).V = max( cars(id).V - 1 , Vmin );
elseif( d(id) < Vmax - Vmin )
cars(id).V = Vmin;
end new_cars = cars;
end
关于变道的状态更新:
function [new_cells,new_cars] = L_NextState(i,cells,cars,d,d_safe,d_l_for,d_l_bac,d_r_for,d_r_bac)
global Vmax;
global LanesNum;
global loopCars; if( d_r_for(i) > d_safe(i) ) %与右前方车辆距离大于安全距离
ok1 = 1;
else
ok1 = 0;
end if( d_r_bac(i) > 1 + Vmax - min(cars(i).V+1,Vmax) ) %与右后方车辆安全
ok2 = 1;
else
ok2 = 0;
end if( cars(i).M+2 <= LanesNum && cells(cars(i).M+2,cars(i).N) ~= 0 ) %右边相隔一个车道平行位置有车
id = cells(cars(i).M+2,cars(i).N); %获取该车编号
if( min( d_l_for(id) , d_l_bac(id) ) < d_safe(id) ) %判断该车不能向左变道
ok3 = 1;
else
ok3 = 0;
end
else
ok3 = 1;
end ChangeLaneOK = ok1 && ok2 && ok3; %得到是否有变道条件 if( d(i) < d_safe(i) ) %与前车距离小于安全距离,能变道则必须变道
if(ChangeLaneOK) cells(cars(i).M,cars(i).N) = 0;
cars(i).M = cars(i).M + 1;
if( cells( cars(i).M , cars(i).N ) ~= 0 ) %撞车控制
loopCars = pushStack(loopCars,cars(i).ID);
else
cells(cars(i).M,cars(i).N) = cars(i).ID; %变道
end cars = Accelerate(i,cars,d,d_safe); %加速
else
cars = Decelerate(i,cars,d,d_safe); %减速
end
else %与前车距离大于等于安全距离
ChangeLaneDesire = getCLD(i,cars,'R'); %计算变道欲望
if(ChangeLaneOK && ChangeLaneDesire) cells(cars(i).M,cars(i).N) = 0;
cars(i).M = cars(i).M + 1;
if( cells( cars(i).M , cars(i).N ) ~= 0 ) %撞车控制
loopCars = pushStack(loopCars,cars(i).ID);
else
cells(cars(i).M,cars(i).N) = cars(i).ID; %变道
end cars = Accelerate(i,cars,d,d_safe); %加速
else
cars = Accelerate(i,cars,d,d_safe); %加速
cars = Decelerate(i,cars,d,d_safe); %减速
end
end new_cells = cells;
new_cars = cars;
end
function [new_cells,new_cars] = M_NextState(i,cells,cars,d,d_safe,d_l_for,d_l_bac,d_r_for,d_r_bac)
global Vmax;
global LanesNum;
global loopCars;
%计算中间车道上车辆的下一时刻状态 if( d_l_for(i) > d_safe(i) ) %与左前方车辆距离大于安全距离
ok1 = 1;
else
ok1 = 0;
end if( d_l_bac(i) > 1 + Vmax - min(cars(i).V+1,Vmax) ) %与左后方车辆安全
ok2 = 1;
else
ok2 = 0;
end if( cars(i).M-2 >= 1 && cells(cars(i).M-2,cars(i).N) ~= 0 ) %左边相隔一个车道平行位置有车
id = cells(cars(i).M-2,cars(i).N); %获取该车编号
if( min( d_r_for(id) , d_r_bac(id) ) < d_safe(id) ) %判断该车不能向右变道
ok3 = 1;
else
ok3 = 0;
end
else
ok3 = 1;
end ChangeLeftLaneOK = ok1 && ok2 && ok3; %得到是否有向左变道条件 if( d_r_for(i) > d_safe(i) ) %与右前方车辆距离大于安全距离
ok1 = 1;
else
ok1 = 0;
end if( d_r_bac(i) ~= inf && d_r_bac(i) ~= -1 && cells( cars(i).M + 1 , cars(i).N - d_r_bac(i) ) > 0 ) %右后方有车
id = cells( cars(i).M + 1 , cars(i).N - d_r_bac(i) ); %得到该车的编号
if( d_r_bac(i) > d_safe(id) ) %与右后方车辆安全
ok2 = 1;
else
ok2 = 0;
end
else
ok2 = 1;
end if( cars(i).M+2 <= LanesNum && cells(cars(i).M+2,cars(i).N) ~= 0 ) %右边相隔一个车道平行位置有车
id = cells(cars(i).M+2,cars(i).N); %获取该车编号
if( min( d_l_for(id) , d_l_bac(id) ) < d_safe(id) ) %判断该车不能向左变道
ok3 = 1;
else
ok3 = 0;
end
else
ok3 = 1;
end ChangeRightLaneOK = ok1 && ok2 && ok3; %得到是否有向右变道条件 if( d(i) < d_safe(i) ) %与前车距离小于安全距离 if(ChangeRightLaneOK) %能够向右变道则向右变道 cells(cars(i).M,cars(i).N) = 0;
cars(i).M = cars(i).M + 1;
if( cells( cars(i).M , cars(i).N ) ~= 0 ) %撞车控制
loopCars = pushStack(loopCars,cars(i).ID);
else
cells(cars(i).M,cars(i).N) = cars(i).ID; %变道
end cars = Accelerate(i,cars,d,d_safe); %加速 else %不能向右变道则尝试向左变道 if(ChangeLeftLaneOK == 1) %能向左变道则向左变道 cells(cars(i).M,cars(i).N) = 0;
cars(i).M = cars(i).M - 1;
if( cells( cars(i).M , cars(i).N ) ~= 0 ) %撞车控制
loopCars = pushStack(loopCars,cars(i).ID);
else
cells(cars(i).M,cars(i).N) = cars(i).ID; %变道
end else %两边都不允许变道
cars = Decelerate(i,cars,d,d_safe); %减速
end end else %与前车距离大于等于安全距离 ChangeLaneDesire = getCLD(i,cars,'R'); %计算变道欲望 if(ChangeRightLaneOK && ChangeLaneDesire) %能够向右变道,且有变道欲望 cells(cars(i).M,cars(i).N) = 0;
cars(i).M = cars(i).M + 1;
if( cells( cars(i).M , cars(i).N ) ~= 0 ) %撞车控制
loopCars = pushStack(loopCars,cars(i).ID);
else
cells(cars(i).M,cars(i).N) = cars(i).ID; %变道
end cars = Accelerate(i,cars,d,d_safe); %加速
else
cars = Accelerate(i,cars,d,d_safe); %加速
cars = Decelerate(i,cars,d,d_safe); %减速
end end new_cells = cells;
new_cars = cars;
end
function [new_cells,new_cars] = R_NextState(i,cells,cars,d,d_safe,d_l_for,d_l_bac,d_r_for,d_r_bac)
global Vmax;
global loopCars;
%计算最右侧车道上车辆的下一时刻状态 if( d_l_for(i) > d_safe(i) ) %与左前方车辆距离大于安全距离
ok1 = 1;
else
ok1 = 0;
end if( d_l_bac(i) > 1 + Vmax - min(cars(i).V+1,Vmax) ) %与左后方车辆安全
ok2 = 1;
else
ok2 = 0;
end if( cars(i).M-2 >= 1 && cells(cars(i).M-2,cars(i).N) ~= 0 ) %左边相隔一个车道平行位置有车
id = cells(cars(i).M-2,cars(i).N); %获取该车编号
if( min( d_r_for(id) , d_r_bac(id) ) < d_safe(id) ) %判断该车不能向右变道
ok3 = 1;
else
ok3 = 0;
end
else
ok3 = 1;
end ChangeLaneOK = ok1 && ok2 && ok3; %得到是否有变道条件 if( d(i) < d_safe(i) ) %与前车距离小于安全距离
ChangeLaneDesire = getCLD(i,cars,'L'); %计算变道欲望
if(ChangeLaneOK && ChangeLaneDesire)
cells(cars(i).M,cars(i).N) = 0;
cars(i).M = cars(i).M - 1;
if( cells( cars(i).M , cars(i).N ) ~= 0 ) %撞车控制
loopCars = pushStack(loopCars,cars(i).ID);
else
cells(cars(i).M,cars(i).N) = cars(i).ID; %变道
end
else
cars = Decelerate(i,cars,d,d_safe); %减速
end
else %与前车距离大于等于安全距离
cars = Accelerate(i,cars,d,d_safe); %加速
cars = Decelerate(i,cars,d,d_safe); %减速
end new_cells = cells;
new_cars = cars;
end
计算变道欲望:
function ret = getCLD(id,cars,Type)
%Calculate the desire to change the lane
global ChangeRightP;
global ChangeLeftP; if(Type == 'R') %To right
if(cars(id).Self == 1) %Self driving
ret = 1;
else %Manual driving
if(rand(1) <= ChangeRightP)
ret = 1;
else
ret = 0;
end
end;
else %To left
if(cars(id).Self == 1) %Self driving
ret = 1;
else %Manual driving
if(rand(1) <= ChangeLeftP)
ret = 1;
else
ret = 0;
end
end;
end end
随机慢化:
function new_cars = RandSlow(cars)
global CarsNum;
global Vmin; p=0.1; %手动车慢化概率
q=0.03; %自动驾驶车慢化概率 for i = 1:1:CarsNum
if(cars(i).Self==1)
if(rand(1) <= q)
cars(i).V = max( cars(i).V - 1 , Vmin );
end
else
if(rand(1) <= p)
cars(i).V = max( cars(i).V - 1 , Vmin );
end
end
end new_cars = cars;
end
状态更新:
function [new_cells,new_cars] = Update(cells,cars)
global CarsNum;
global CellsNum;
global loopCars; for i = 1:1:CarsNum
cells( cars(i).M , cars(i).N ) = 0;
if( cars(i).N + cars(i).V > CellsNum ) %Drive out of the road
loopCars = pushStack(loopCars,cars(i).ID);
else
cells( cars(i).M , cars(i).N ) = cars(i).ID;
end;
end new_cells = cells;
new_cars = cars;
end
计算某一时刻的平均车速:
function Ret = calc_Vave(cars)
global CarsNum; sum = 0;
for i = 1:1:CarsNum
sum = sum+cars(i).V;
end Ret = sum./CarsNum;
end
栈模拟:
function newStack = pushStack(Stack,val)
newStack = [val,Stack];
end
function newStack = popStack(Stack)
newStack = Stack(2:end);
end
function ret = StackSize(Stack)
ret = size(Stack,2);
end
function Val = topStack(Stack)
Val = Stack(1);
end
基于元胞自动机NaSch模型的多车道手动-自动混合驾驶仿真模型的Matlab实现的更多相关文章
- 简单二维元胞自动机 MATLAB实现
20世纪50年代,乌尔姆和冯·诺依曼(对此人真是崇拜的五体投地)为了研究机器人自我复制的可能性,提出了一种叫做元胞自动机(Cellular Automaton,CA)的算法.该算法采用局相互作用规则, ...
- 用C++实现的元胞自动机
我是一个C++初学者,控制台实现了一个元胞自动机. 代码如下: //"生命游戏"V1.0 //李国良于2017年1月1日编写完成 #include <iostream> ...
- 美国康奈尔大学BioNB441元胞自动机MATLAB应用
美国康奈尔大学BioNB441在Matlab中的元胞自动机 介绍 元胞自动机(CA)是用于计算计划利用当地的规则和本地通信.普遍CA定义一个网格,网格上的每个点代表一个有限数量的状态中的细胞.过渡规则 ...
- 游戏中的过程生成——元胞自动机 Celluar Automata 生成洞穴地形
最近在学习过程生成技术,在这里写一些心得. 对于元胞自动机,我们这里只讨论输入是一副二维bool数组的情况,即大多数游戏中的情况. 一个元胞自动机,对于一个输入,给出一个同样格式的输出.输出中的每个点 ...
- 《 .NET并发编程实战》扩展阅读 - 元胞自动机 - 1 - 为什么要学元胞自动机
先发表生成URL以印在书里面.等书籍正式出版销售后会公开内容.
- 【AI】Exponential Stochastic Cellular Automata for Massively Parallel Inference - 大规模并行推理的指数随机元胞自动机
[论文标题]Exponential Stochastic Cellular Automata for Massively Parallel Inference (19th-ICAIS,PMLR ...
- matlab学习笔记12_3串联结构体,按属性创建含有元胞数组的结构体,filenames,isfield,isstruct,orderfields
一起来学matlab-matlab学习笔记12 12_3 结构体 串联结构体,按属性创建含有元胞数组的结构体,filenames,isfield,isstruct,orderfields 觉得有用的话 ...
- 基于git的源代码管理模型——git flow
基于git的源代码管理模型--git flow A successful Git branching model
- MATLAB元胞数组
MATLAB元胞数组 元胞数组: 元胞数组是MATLAB的一种特殊数据类型,可以将元胞数组看做一种无所不包的通用矩阵,或者叫做广义矩阵.组成元胞数组的元素可以是任何一种数据类型的常数或者常量,每一个元 ...
随机推荐
- 8 -- 深入使用Spring -- 1...1Bean后处理器
8.1.1 Bean后处理器(BeanPostProcessor) Bean后处理器主要负责对容器中其他Bean执行后处理,例如为容器中的目标Bean生成代理等. Bean后处理器会在Bean实例创建 ...
- 初试WebSocket构建聊天程序
上一篇文章中使用了Ajax long polling实现了一个简单的聊天程序,对于web实时通信,今天就来试用一下基于WebSocket的长连接方式. WebSocket简介 为了增强web通信的功能 ...
- mysql强制使用索引
在公司后台某模块功能记录日志中有一个搜索功能,通过前段时间的产品使用时间区间进行搜索反馈有些卡顿,我发现这个搜索功能比较慢,要3秒左右才能出来,就决定对这里做一下优化. 通过分析代码和SQL发现最核心 ...
- mysql 行转列 (case when的使用)
现有 table1 如下 table2 如下 需要统计:各个部门每个月的绩效总和 实现如下:
- 3ds Max导出FBX动画模型在OSG中使用
3ds Max做好动画模型 导出选项:包含-动画-附加选项-勾选使用场景名(这样动画名就是场景名)高级选项-单位-勾选自动(否则导出的模型很小) 导出文件名假设a.fbx使用osgconv工具旋转坐标 ...
- Theme.AppCompat.Light的解决方法
style name=”AppBaseTheme” parent=”Theme.AppCompat.Light” 改为 改为 style name=”AppBaseTheme” parent=”and ...
- linux下getsockopt和setsockopt详解及测试
linux下getsockopt和setsockopt详解及测试 NAME 名字 getsockopt, setsockopt - get and set options on sockets 获取或 ...
- 《C++ Primer Plus》第16章 string类和标准模板库 学习笔记
C++提供了一组功能强大的库,这些库提供了很多常见编程问题的解决方案以及简化其他问题的工具string类为将字符串作为对象来处理提供了一种方便的方法.string类提供了自动内存管理动能以及众多处理字 ...
- springbatch---->springbatch的使用(一)
这里我们通过一个简单的实例来对springbatch做一个入门的体会.刚刚好,看见你幸福的样子,于是幸福着你的幸福. springbatch的入门案例 简单项目的结构如下: 一.引入maven的spr ...
- 行逻辑链接的顺序表实现稀疏矩阵的相乘(Java语言描述)
行逻辑链接,带行链接信息.程序有空指针BUG,至今未解决.还是C/C++适合描述算法数据结构.以后复杂的算法还是改用C/C++吧. 有BUG的代码,总有一天会换成没有BUG的. package 行逻辑 ...