快速上手¶
车辆¶
新建一辆车辆:
from eins import road
car = road.Car()
需用户定义的车辆属性:
属性名 | 含义 | 初始值 | 单位 |
---|---|---|---|
length | 车辆长度 | 1.0 | m |
safedistance | 最小安全车距 | 0.0 | m |
acc | 加速度 | 1.0 | m/s^2 |
slowacc | 慢加速度 | 0.5 | m/s^2 |
negacc | 减速度 | 1.0 | m/s^2 |
view | 视野距离 | 0.0 | m |
speed | 速度 | 0.0 | m/s |
注解
- 不一定需要定义全部属性,根据要使用数学模型的需求来定义即可
- 速度定义的含义是车辆的初始速度
- 车辆在道路上运行时会具有许多其他的属性,详情请往后阅读
以NaSch模型为例,模拟现实生活中普通车辆时,可以定义如下:
car.length = 3.5
car.acc = 3.2
car.negacc = 3.0
car.safedistance = 50.0
小技巧
合适的值可以查询国家的相关规定来得到
道路¶
class ExecRoad(Road):
def __init__(self, carbox, vmax, length, lanes=1,
entercars=0, enterflag=False, connectroad=None, exitflag=False, roadname='default'):
super(ExecRoad, self).__init__(carbox, vmax, length, lanes, \
entercars, enterflag, connectroad, exitflag, roadname)
ExecRoad Parameters¶
- carbox :
- 车辆集合
- vmax :
- 车速上限
- length :
- 道路长度
- lanes :
- 道路车道数目
- entercars :
- 已通过的车辆数目
- connectroad :
- 连接的道路
- enterflag :
- 入口标记
- exitflag :
- 出口标记
- roadname :
- 道路名称
道路具有非常多的属性和方法,我们慢慢道来
得到一条道路¶
为了初始化一条道路,有3个参数是必不可少的:
- 初始化的车辆 — carbox
- 道路长度 — length
- 道路的最大限定速度 — vmax
其中carbox必须要符合特定的格式,由两层嵌套的list构成:
[
[car_1, car_2, ..., car_n],
[car_1, car_2, ..., car_n],
...
[car_1, car_2, ..., car_n]
]
可以想象为第一层这个整体就是整条道路,而道路中有N条车道即第一层里面的各个元素(list),各个元素(list)里面的元素(Car)就是车辆
- 同时,有如下规定:
在一条车道中,第n+1辆车一定位于第n辆车前方
车道号从小到大对应着从左到右,比如 lane_0 对于 lane_1 是在左方, lane_2 对于 lane_1 是在右方
同一条道路上的所有车道行驶方向相同
carbox第一层内的元素个数必须严格等于初始化时规定的车道数。比如车道数为3的道路,其carbox必须这样构成:
[ [...], [...], [...] ]
注解
第二层中的元素可以为空,即那条车道上没有任何车辆
下面来举个简单的例子,初始化一条长度为500m,最大速度60km/h,车道为2,每条车道上有2辆车的道路:
from eins import road
vmax = 16.7 # 这里的单位为 m/s
length = 500
car1 = road.Car()
car1.locate = 100.0 # 这里定义locate实际上是定义车辆的初始化所在的位置
car1.lane = 0 # 定义车道标号
car2 = road.Car()
car2.locate = 300.0
car2.lane = 0
car3 = road.Car()
car3.locate = 150.0
car3.lane = 1
car4 = road.Car()
car4.locate = 250.0
car4.lane = 1
carbox = [[car1, car2], [car3, car4]]
rd = road.ExecRoad(carbox=carbox, length=length, vmax=vmax) # 得到一条道路
虽然的确得到了要的道路,但是过于繁琐,而且车辆数一多肯定不能这样手动的一辆一辆去创建
这里提供2个帮助新建用于初始化carbox的函数:
- init_empty_road(lanes)
- —— 用于初始化空的道路,需要的参数只有道路的车道数量
- init_cars_distributed(length, carTemplateBox, carsNum=None, lanes=1, dis=’normal’, pers=None)
- —— 可以按预定的格式初始化道路,必须的参数为分布长度、车辆模板
示例:
from eins import road
import copy
lanes = 3
length = 1000
vmax = 20
carbox1 = road.init_empty_road(lanes)
rd = road.ExecRoad(carbox=carbox1, length=length, vmax=vmax) # 空的道路
rd1 = road.ExecRoad(carbox=copy.deepcopy(carbox1), length=length, vmax=vmax) # 一定要记得使用deepcopy!!!不要直接重复使用!!!
car = road.Car() # 使用提供的初始化函数时不需要指定初始车道编号
car.speed = vmax # 定义车辆初始速度
car.safedistance = 50
car.length = 4
car.acc = 3.2
car.negacc = 3
carbox2 = road.init_cars_distributed(length=length, carTemplateBox=[car], lanes=lanes)
rd2 = road.ExecRoad(carbox=carbox2, length=length, vmax=vmax) # 有初始车辆的道路
注解
如果想让道路上有多种车型,只需提前定义好车辆模板,然后加入carTemplateBox中,提供它们的pers(比例)即可(pers之和必须为1.0),如:
carbox = road.init_cars_distributed(length=length, carTemplateBox=[car1, car2], pers=[0.7, 0.3], lanes=lanes)
开始仿真¶
得到初始好的道路后,设定运行规则便可以进行仿真了
设rd为一条初始化完毕的道路,使用NaSch规则仿真 100s:
...
exectime = 100
rd.set_exec_rule('NS')
for t in xrange(exectime):
rd.reflush_status()
ExecRoad.reflush_status()
—— 刷新道路上所有车辆的状态,timestep为1s
注意
运行规则一定要记得设定,如果不设定的话默认值为 NS
Key的可选值为
- NS
- CD
- MCD
可以用 print rd 来获取道路的当前信息。输出的一个例子:
+===================+
- 运行规则及道路HashValue:<bound method ExecRoad.NS of <road.ExecRoad object at 0x7f108147e5d0>>
- 车道数:3 - 道路长度(m):2000 - 运行时间(s):0 - 是否为入口:False - 是否为出口:False
--------------------
- 车道_0 - 车辆数目:12 - 平均车速:14.167 - 已通过车辆数:0
- 车道_1 - 车辆数目:12 - 平均车速:15.833 - 已通过车辆数:0
- 车道_2 - 车辆数目:12 - 平均车速:14.167 - 已通过车辆数:0
- 整体 - 车辆数目:36 - 平均车速:14.722 - 已通过车辆数:0
--------------------
- 连接道路:None - 时间边界条件:False - 循环边界条件:False
+===================+
道路自身也有许多方法获取当前的信息,下面介绍几个常用的:
ExecRoad.get_cars_locate()
—— 可以得到目前时刻车辆的位置信息,返回值的形式为 list 中嵌套 numpy.array
ExecRoad.get_cars_v()
—— 可以得到目前时刻车辆的速度信息,返回值的形式为 list 中嵌套 numpy.array
ExecRoad.get_mean_speed()
—— 可以得到目前时刻各车道的平均速度和整体的平均速度,第一个返回值的形式为为 numpy.array ,第二个返回值的形式为 float
一个简单的例子:
...
rd = road.ExecRoad(carbox=carbox, length=length, vmax=vmax)
lane_v, whole = rd.get_mean_speed()
注意
当车道上没有车时,车道的平均速度被 -1 所标记。当所有车道上都无车时,整体平均速度为 None
当然,也可以直接得到整个carbox,从而直接得到车辆操纵权:
ExecRoad.get_cars()
警告
事实上,在没有特殊的要求时,十分不推荐直接从外部影响车辆的状态。但是可能本库在某些方面并不能满足您的需求,所以还是开放了车辆对象的直接获取。希望您在做出行动时一定要清楚自己在干什么。 (更推荐研究reflush_status这个方法后,直接在源码上进行扩充或修改。)
车辆自动循环¶
一般只有初始的车辆是不够的,大多都需要持续观察道路一定时间。所以在仿真过程中需要持续的添加车辆。
如果您阅读了之前的数学模型中的通用规则,就会知道这里提供两种边界更新方式,具体的规则前面有提到过,这里不再赘述。
循环边界条件¶
ExecRoad.cycle_boundary_condition(switch, carTemplateBox, pers=None)
循环边界相对简单,switch 为开关,设定为True便开启了,carTemplateBox 与 pers 的定义同前面的默认初始化函数
时间边界条件¶
ExecRoad.time_boundary_condition(switch, carTemplateBox, pers=None, timeStep=1, nums=1)
—— timeStep 添加车辆的时间间隔,必须为整数
—— nums 添加时添加的车辆数目
注解
- 无论是哪种边界条件,都不需要给模板设置车道号
- 更新时,如果道路入口处没有车身长度的空位时,不会添加车辆,使用循环边界条件时请特别注意这一点
统计¶
def road_runner(roadbox, exectime, savepath, timestep='sec',
st=True, sm=True, bar=True, ownfun=None):
road_runner Parameters¶
- roadbox :
- 道路集合
- exectime :
- 仿真时间
- savepath :
- 保存路径(无需加后缀)
- timestep :
- SummmaryData 统计的间隔,Key可为 sec min hour
- st :
- 是否统计SummaryData
- sm :
- 是否统计SpaceTimeData
- bar :
- 是否开启进度条
- ownfun :
- 自定义函数,可以在统计过程中输出自己想要的其他信息(返回值必须为str)
统计功能统计数据一览(.xlsx形式)
Sheet:SummaryData
属性名 | 含义 |
---|---|
ROAD_HASH_ID | 道路Hash值 |
LANE_ID | 车道号 |
TIME_STAMP | 时间戳 |
AVR_SPEED | 平均速度 |
FLUX | 车流量 |
DENSITY | 密度 |
CARS_NUM | 车辆数目 |
LEAVE_CARS | 累计通车数目 |
注解
- 当ROAD_ID为 -1 时,指整条道路
- 如果有值为空,则说明那条道路或那条车道上无任何车辆,为空和为0的含义是不同的
Sheet:SpaceTimeData
属性名 | 含义 |
---|---|
ROAD_HASH_ID | 道路Hash值 |
LANE_ID | 车道号 |
TIME_STAMP | 时间戳 |
LOCATE | 坐标集 |
如未能满足您的需求,则需要自行开发函数
使用十分简单,只需设定 仿真时间 与预先设定好的 道路box 即可,一个简单的例子:
from eins import statistics as st
from eins import road
savepath = './data' # 不需要加后缀名
car = Car()
exectime = 600
length = 1000
vmax = 5
lanes = 3
carbox = road.init_cars_distributed(length, [car], lanes = lanes)
emptybox = road.init_empty_road(lanes)
rd = road.ExecRoad(carbox, length, vmax)
rd1 = road.ExecRoad(emptybox, length, vmax)
rd.set_connect_to(rd1) # 连接rd rd1
rd.cycle_boundary_condition(True, [car]) # 设定循环边界条件
st.road_runner([rd, rd1], exectime, savepath)
时空图¶
时空图的数据不是特别好读取,所以提供了一个辅助绘制时空图的功能,其他的图形需要自行根据采集数据绘制。 接上面统计代码的示例:
...
from eins import plot
plot.read_data('./data', 0, '0x7f7b07ac3d50')
动态测试图¶
如果想查看某条道路的动态可视化情况,这里提供了简易的函数来帮助您
testplot.addRoad(roadbox)
testplot.plot()
这个仅是为您测试提供的函数,所以只能显示一条道路的情况(roadbox中的第一个元素)
eg:
from eins import testplot as tp
from eins import road
import copy
length = 2000
vmax = 5
lanes = 3
carTemp = road.Car()
carTemp.safedistance = 0
carTemp.length = 1
carTemp.speed = vmax
InitCar = road.init_cars_distributed(length, [carTemp], lanes = lanes)
EmptyCar = road.init_empty_road(lanes = lanes)
rd = road.ExecRoad(InitCar, vmax, length, lanes=lanes)
rd1 = road.ExecRoad(EmptyCar, vmax, length, lanes=lanes)
rd.set_connect_to(rd1)
rd.cycle_boundary_condition(True, [carTemp])
tp.addRoad([rd, rd1]) # 绘制rd的运行情况,所以将rd放在第一个元素
tp.plot() # 显示
注解
显示的图中的车道从上到下对应着规则中的从左至右
车辆颜色代表的含义:
红: 速度 <= vmax*0.2
黄: vmax*0.2< 速度 <= vmax*0.6
绿: 速度 > vmax*0.6