李雨松 徐野 哈乐
(1.沈阳理工大学自动化与电气工程学院 辽宁沈阳 110159;2.北部战区总医院医学工程科 辽宁沈阳 110000)
强化学习已经在游戏、机器人领域中开花结果,可 以说强化学习算法正在改变和影响着世界,掌握了这门技术就掌握了改变世界和影响世界的工具。Deep-Mind(AlphaGo 的创造者)提出了一种结合深度学习和强化学习的方式,就是DQN(Deep Q Network)[1]。
与人工驾驶相比,机器驾驶车辆的重复性较好、驾驶精度较高。目前,驾驶机器人已经成功地应用于汽车排放耐久性试验。无人驾驶机器人进行转向操纵具有精度高、重复性好的特点,而人类驾驶员则具有平稳转向的特点。在要求无人驾驶机器人能进行高精度和高重复性的车辆驾驶的同时,对驾驶员驾驶行为的研究必不可少[2-4]。
该文创新之处在于仿真环境的构建,仿真环境的构建对于驾驶行为机器人的训练十分的重要,一个好的仿真环境,可以让算法来训练驾驶行为机器人,让其更加真实。该文的思路是创造一个虚拟驾驶环境,随机生成一条路,并设置好拥堵的各种情况让机器人不断地去学习,最后实现更快、更安全地到达终点[5]。
包含的环境有:天气、道路等级、道路类型、路况、汽车数据、行驶环境。
环境分类:晴/阴/多云、雾、雨、雪、高速(>60 km/h,<120 km/h)、城市大路(<70 km/h)、城市小路(<40 km/h)、省道(<80 km/h)、国道(<90 km/h)、环岛(<30 km/h)、路口(<30 km/h)、桥梁(<30 km/h)、隧道(<70 km/h)、红灯/拥堵、行驶里程Sall、总驾驶时长、位置、速度v、白天、夜间。
踩油门(加速)、刹车(减速)、急踩油门(急加速)、急刹车(急减速)、匀速。
采取的动作:急刹车、急加速、踩油门、刹车、匀速。
对应的奖励:-3,-2,0,0,0。
动作导致状态改变:车与目的地的距离>0,到达目的地(Sall-S0≤0),发生事故(车辆碰撞与其他物体距离≤0),晴/阴/多云超速20%以内,晴/阴/多云超速(超速百分比20%/50%/100%),速度在上限速度的90%以内,速度在上限速度的90%以上但未超速,驾驶时间t≤4,驾驶时 间t≥4,雨天超速(超速百分20%/50%/100%)×0.8,雪天超速(超速百分20%/50%/100%)×0.5,雾天超速(超速百分20%/50%/100%)×0.5,雨天超速20%以内×(0.8),雪天超速20%以内×(0.8),雾天超速20%以内×(0.8),高速小于最低限速。
奖励:-0.05,100,-100,-10,-20(-50/-100),0,0.1,0,-50,-20(-50/-100),-20(-50/-100),-20(-50/-100),-10,-10,-10,-10。
导入gym 库,通过make()函数得到环境对象,每一个环境都有一个ID,格式“Xxxx-vd”。
env=gym.make('UBI_Robot-v0',randomRouteOr-RealworldRoute='RandomRoute',staticOrRandom='random')
env.step(env.action_space.sample()) 随机选择加减速或者匀速
在configs 文件中设置好相应的动作奖励、状态奖励、天气和道路类型和道路等级的概率,产生红灯和拥堵的概率,消失一个拥堵产生一个新的拥堵的概率、设置拥堵时长、红绿灯转换时间、白天夜间的时间,设置疲劳驾驶的时间以及疲劳驾驶恢复时间。
在RandomRoute 里创建一个类,其中包含[(产生链路//包含所有内容)、(产生随机链路)、(产生静态链路)、(根据路长返回天气list)、(随机产生系列红灯/拥堵)、(每次动作后更新self.jam)、(疲劳驾驶:如果速度为0 且刹车,则停车一秒,按比率-12)、(根据生成路、红灯、天气等信息,更新state)、(获取总的状态)、(获取jam 离车的距离)、(获取当前天气ID)(获取小车当前相对位置)、(未归一化的最高限速)、(未归一化的最低限速)、(获取当前未归一化的速度,单位:m/s)、(获取当前路类型ID)、(获取当前的加速度,考虑了天气原因的变化)、(更新基于当前位置pos 的路段ID 天气ID道路类型ID)、(执行相应动作,更新所有参数,返回:更新后的state)]方法。
每次测试后都生成一个日志,日志级别包括debug、info、warning、error、critical。在每一次运行时,日志开头输出开始运行游戏环境,当前世界路类型,当前路的产生类型。将总级别设置成info、路总长度、拥堵返回值、道路类型、天气、当前处于第几段路、运行时间、路长、归一化位置、速度、疲劳驾驶时间、动作ID、19 个状态()、终点奖励、碰撞奖励、超速奖励、疲劳驾驶奖励、每秒总奖励、游戏提示结束等设置为info 级别。其余的(拥堵统计情况、总共拥堵、最近拥堵、当前总共拥堵情况、疲劳驾驶折扣时间)设置为debug 级别。这样保证了当总级别设置为info时,debug级别不显示在日志上,当总级别为debug 时,全部显示在日志中。
该研究在拥堵这一方面设置为产生车辆拥堵和红灯拥堵两种拥堵情况。其中高速和隧道没有红灯,只有车辆拥堵。其中,产生红灯拥堵概率为0.7,产生车辆拥堵的概率为0.3。[[0.05,0.05,0.05,0.15,0.20,0.20,0.20,0.20,0.10],[0.00,0.10,0.10,0.20,0.20,0.30,0.30,0.05,0.00],](前者为车辆拥堵产生的概率,后者为红灯拥堵产生的概率)在不同道路类型和道路等级[高速0、国道1、省道2、城市大路3、城市小路4、环岛5、路口6、桥梁7、隧道8]的情况下产生车辆拥堵和红灯拥堵的概率,每200 m随机一次[6]。
拥堵算法总体构架:按照概率随机产生拥堵—返回当前最近拥堵—(当前小车位置大于拥堵位置—游戏结束/当前小车位置小于拥堵位置—游戏继续进行)。
拥堵算法流程设计:按照概率随机产生拥堵—(红灯(当绿灯时间变为0)—(当红灯时间变为0)绿灯/车辆拥堵—(当小车未经过车辆拥堵时车辆拥堵时间为0)按照概率产生一个,两个,或者不产生车辆拥堵)。
在generateJams 中,首先,按照概率判断是产生红灯拥堵还是车辆拥堵,红灯拥堵车辆拥堵概率分别为(0.7,0.3);其次,按照在不同的道路等级和道路类型上产生红灯和车辆拥堵的概率,按照概率随机产生拥堵,(每200 m 随机一次)。红灯的起始时间为1~90 s 随机,车辆拥堵的起始时间为90~300 s 随机。最后用append 累计输出总的拥堵情况(拥堵位置,是否拥堵,拥堵类型,拥堵时间)。
产生拥堵设计:
{先按照概率随机选出拥堵类型jamtype为红灯拥堵还是车辆拥堵。
If(jamtype==’车辆拥堵’)
If(当前单路类型或者道路等级产生车辆拥堵的概率<cofigs.py 中不同道路类型道路等级产生车辆拥堵的概率)
jamSituation='拥堵'
else:
jamSituation='无拥堵'
If(jamtype==’红灯’)
If(当前单路类型或者道路等级产生红灯拥堵的概率<cofigs.py 中不同道路类型道路等级产生红灯的概率)
jamSituation='拥堵'
else:
jamSituation='无拥堵'
红灯(signalTime)和车辆拥堵(jamTime)起始时间为configs.py中规定的起始时间中随机选择一个值。
if(jamSituation=='拥堵'and jamType=='红灯'):
jamSummary=[当前位置,到当前位置+configs.py中每多少米随机可能产生一个拥堵的距离,是否有拥堵,拥堵类型,信号灯时间]
self.jam.append(jamSummary)(把所有拥堵情况放到self.jam中)
lastPosition=lastPosition+ConfigRandomRoute.congestionDistance(下一次可能产生拥堵的位置)
allJams=allJams+1(拥堵数量+1)
elif(jamSituation=='拥堵'and jamType=='车辆拥堵'):
jamSummary=[random.randint(lastPosition+1,last-Position+ConfigRandomRoute.congestionDistance)/ (self.roadLength),jamSituation,jamType,jamTime]
self.jam.append(jamSummary)
lastPosition=lastPosition+ConfigRandomRoute.congestionDistance
allJams=allJams+1
else:
lastPosition=lastPosition+ConfigRandomRoute.congestionDistance
在日志中输出总的拥堵情况统计self.jam 及总共拥堵数量allJams
return self.jam}
在updateJams 中,当红灯时间归零后,变为绿灯,此时为不拥堵的情况,绿灯时间为90 s,如果绿灯时间未到0小车通过当前的绿灯,那么不算碰撞游戏继续,删除这个拥堵情况;如果绿灯时间归零小车还未到此绿灯,那么绿灯变为红灯,此时为拥堵的情况,时间为90 s(红绿灯转换时间为90 s),如果当车辆拥堵时间未到0,而小车通过了此处车辆拥堵,那么即小车发生了碰撞,游戏结束了;如果当前车辆拥堵时间到0,而小车还未到达此处车辆拥堵,那么按照概率,70%的概率在小车当前位置到终点产生新拥堵,30%的概率在小车当前位置到终点不产生新的拥堵。如果产生了新的拥堵,那么有50%的概率在小车当前位置到终点产生两个新拥堵,有50%的概率在小车当前位置到终点产生一个新拥堵。我们首先要确定一下是否在当前位置到终点处有拥堵的情况,如果有则返回最近的拥堵位置,没有则返回-1。如果前方有拥堵情况,创建一个realJams=[],realJams.append(当前的拥堵情况),如果没拥堵则返回10,如果有拥堵,判断,该拥堵如果距离小车1 000 m以外则返回-1,如果该拥堵在离小车1 000 m之内则返回当前拥堵归一化位置减去小车归一化位置值为(0,1)之间,如果当前小车超过了拥堵位置即发生了碰撞,则返回-10,游戏结束。最后如果游戏继续,则按照拥堵位置大小,一次排序进行下一次秒的更新。
拥堵更新算法设计:
if 前方无拥堵:
jamDistance=-1
return jamDistance
else:
realJams=[]
for语句找到当前所有的拥堵
realJams.append(self.jam[i])都放在realJams中
if len(realJams)==0:前方无拥堵
minDistanceJamFront=10
else:
minDistanceJamFront=realJams[0][0](最近的拥堵值的位置)
if 当前位置<=(minDistanceJamFront -1000/ (路总长)):
jamDistance=-1
elif 当前位置>(minDistanceJamFront -1000/ (路总长))and 当前位置<minDistanceJamFront:
jamDistance=(minDistanceJamFront -当前位置)/(1000/(路总长))
else:#当前位置==minDistanceJam
if(realJams[0][2]=='红灯')or(realJams[0][2]=='车辆拥堵'):
jamDistance=-10
else:
jamDistance=-1
日志中输出当前共有的拥堵数量
碰撞检测即为判断驾驶机器人位置是否超过了拥堵位置。
检测判断:驾驶机器人当前位置<最近拥堵,驾驶机器人当前位置>=最近拥堵;
判断结果:没发生碰撞,游戏继续进行。发生了碰撞,游戏结束。
用DDQN 算法训练驾驶机器人,随着训练次数增加奖励稳步也在稳定地提升,刚开始时波动比较大,随着学习次数增加奖励越来越高波动越来越小。
仿真环境的构建对于机器人训练顺利进行起着重要的作用,拥堵算法的设计要切合实际,要联想到生活当中,在驾驶时可能遇到的拥堵情况,一个好的虚拟链路仿真环境,可以让游戏更加地切合实际,以便于之后用算法来训练机器人,让机器人不断地去学习,最后实现更快、更安全地到达终点的目的。