李雨松 徐野 哈樂
(1.沈陽理工大學(xué)自動化與電氣工程學(xué)院 遼寧沈陽 110159;2.北部戰(zhàn)區(qū)總醫(yī)院醫(yī)學(xué)工程科 遼寧沈陽 110000)
強(qiáng)化學(xué)習(xí)已經(jīng)在游戲、機(jī)器人領(lǐng)域中開花結(jié)果,可 以說強(qiáng)化學(xué)習(xí)算法正在改變和影響著世界,掌握了這門技術(shù)就掌握了改變世界和影響世界的工具。Deep-Mind(AlphaGo 的創(chuàng)造者)提出了一種結(jié)合深度學(xué)習(xí)和強(qiáng)化學(xué)習(xí)的方式,就是DQN(Deep Q Network)[1]。
與人工駕駛相比,機(jī)器駕駛車輛的重復(fù)性較好、駕駛精度較高。目前,駕駛機(jī)器人已經(jīng)成功地應(yīng)用于汽車排放耐久性試驗(yàn)。無人駕駛機(jī)器人進(jìn)行轉(zhuǎn)向操縱具有精度高、重復(fù)性好的特點(diǎn),而人類駕駛員則具有平穩(wěn)轉(zhuǎn)向的特點(diǎn)。在要求無人駕駛機(jī)器人能進(jìn)行高精度和高重復(fù)性的車輛駕駛的同時(shí),對駕駛員駕駛行為的研究必不可少[2-4]。
該文創(chuàng)新之處在于仿真環(huán)境的構(gòu)建,仿真環(huán)境的構(gòu)建對于駕駛行為機(jī)器人的訓(xùn)練十分的重要,一個(gè)好的仿真環(huán)境,可以讓算法來訓(xùn)練駕駛行為機(jī)器人,讓其更加真實(shí)。該文的思路是創(chuàng)造一個(gè)虛擬駕駛環(huán)境,隨機(jī)生成一條路,并設(shè)置好擁堵的各種情況讓機(jī)器人不斷地去學(xué)習(xí),最后實(shí)現(xiàn)更快、更安全地到達(dá)終點(diǎn)[5]。
包含的環(huán)境有:天氣、道路等級、道路類型、路況、汽車數(shù)據(jù)、行駛環(huán)境。
環(huán)境分類:晴/陰/多云、霧、雨、雪、高速(>60 km/h,<120 km/h)、城市大路(<70 km/h)、城市小路(<40 km/h)、省道(<80 km/h)、國道(<90 km/h)、環(huán)島(<30 km/h)、路口(<30 km/h)、橋梁(<30 km/h)、隧道(<70 km/h)、紅燈/擁堵、行駛里程Sall、總駕駛時(shí)長、位置、速度v、白天、夜間。
踩油門(加速)、剎車(減速)、急踩油門(急加速)、急剎車(急減速)、勻速。
采取的動作:急剎車、急加速、踩油門、剎車、勻速。
對應(yīng)的獎勵(lì):-3,-2,0,0,0。
動作導(dǎo)致狀態(tài)改變:車與目的地的距離>0,到達(dá)目的地(Sall-S0≤0),發(fā)生事故(車輛碰撞與其他物體距離≤0),晴/陰/多云超速20%以內(nèi),晴/陰/多云超速(超速百分比20%/50%/100%),速度在上限速度的90%以內(nèi),速度在上限速度的90%以上但未超速,駕駛時(shí)間t≤4,駕駛時(shí) 間t≥4,雨天超速(超速百分20%/50%/100%)×0.8,雪天超速(超速百分20%/50%/100%)×0.5,霧天超速(超速百分20%/50%/100%)×0.5,雨天超速20%以內(nèi)×(0.8),雪天超速20%以內(nèi)×(0.8),霧天超速20%以內(nèi)×(0.8),高速小于最低限速。
獎勵(lì):-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。
導(dǎo)入gym 庫,通過make()函數(shù)得到環(huán)境對象,每一個(gè)環(huán)境都有一個(gè)ID,格式“Xxxx-vd”。
env=gym.make('UBI_Robot-v0',randomRouteOr-RealworldRoute='RandomRoute',staticOrRandom='random')
env.step(env.action_space.sample()) 隨機(jī)選擇加減速或者勻速
在configs 文件中設(shè)置好相應(yīng)的動作獎勵(lì)、狀態(tài)獎勵(lì)、天氣和道路類型和道路等級的概率,產(chǎn)生紅燈和擁堵的概率,消失一個(gè)擁堵產(chǎn)生一個(gè)新的擁堵的概率、設(shè)置擁堵時(shí)長、紅綠燈轉(zhuǎn)換時(shí)間、白天夜間的時(shí)間,設(shè)置疲勞駕駛的時(shí)間以及疲勞駕駛恢復(fù)時(shí)間。
在RandomRoute 里創(chuàng)建一個(gè)類,其中包含[(產(chǎn)生鏈路//包含所有內(nèi)容)、(產(chǎn)生隨機(jī)鏈路)、(產(chǎn)生靜態(tài)鏈路)、(根據(jù)路長返回天氣list)、(隨機(jī)產(chǎn)生系列紅燈/擁堵)、(每次動作后更新self.jam)、(疲勞駕駛:如果速度為0 且剎車,則停車一秒,按比率-12)、(根據(jù)生成路、紅燈、天氣等信息,更新state)、(獲取總的狀態(tài))、(獲取jam 離車的距離)、(獲取當(dāng)前天氣ID)(獲取小車當(dāng)前相對位置)、(未歸一化的最高限速)、(未歸一化的最低限速)、(獲取當(dāng)前未歸一化的速度,單位:m/s)、(獲取當(dāng)前路類型ID)、(獲取當(dāng)前的加速度,考慮了天氣原因的變化)、(更新基于當(dāng)前位置pos 的路段ID 天氣ID道路類型ID)、(執(zhí)行相應(yīng)動作,更新所有參數(shù),返回:更新后的state)]方法。
每次測試后都生成一個(gè)日志,日志級別包括debug、info、warning、error、critical。在每一次運(yùn)行時(shí),日志開頭輸出開始運(yùn)行游戲環(huán)境,當(dāng)前世界路類型,當(dāng)前路的產(chǎn)生類型。將總級別設(shè)置成info、路總長度、擁堵返回值、道路類型、天氣、當(dāng)前處于第幾段路、運(yùn)行時(shí)間、路長、歸一化位置、速度、疲勞駕駛時(shí)間、動作ID、19 個(gè)狀態(tài)()、終點(diǎn)獎勵(lì)、碰撞獎勵(lì)、超速獎勵(lì)、疲勞駕駛獎勵(lì)、每秒總獎勵(lì)、游戲提示結(jié)束等設(shè)置為info 級別。其余的(擁堵統(tǒng)計(jì)情況、總共擁堵、最近擁堵、當(dāng)前總共擁堵情況、疲勞駕駛折扣時(shí)間)設(shè)置為debug 級別。這樣保證了當(dāng)總級別設(shè)置為info時(shí),debug級別不顯示在日志上,當(dāng)總級別為debug 時(shí),全部顯示在日志中。
該研究在擁堵這一方面設(shè)置為產(chǎn)生車輛擁堵和紅燈擁堵兩種擁堵情況。其中高速和隧道沒有紅燈,只有車輛擁堵。其中,產(chǎn)生紅燈擁堵概率為0.7,產(chǎn)生車輛擁堵的概率為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],](前者為車輛擁堵產(chǎn)生的概率,后者為紅燈擁堵產(chǎn)生的概率)在不同道路類型和道路等級[高速0、國道1、省道2、城市大路3、城市小路4、環(huán)島5、路口6、橋梁7、隧道8]的情況下產(chǎn)生車輛擁堵和紅燈擁堵的概率,每200 m隨機(jī)一次[6]。
擁堵算法總體構(gòu)架:按照概率隨機(jī)產(chǎn)生擁堵—返回當(dāng)前最近擁堵—(當(dāng)前小車位置大于擁堵位置—游戲結(jié)束/當(dāng)前小車位置小于擁堵位置—游戲繼續(xù)進(jìn)行)。
擁堵算法流程設(shè)計(jì):按照概率隨機(jī)產(chǎn)生擁堵—(紅燈(當(dāng)綠燈時(shí)間變?yōu)?)—(當(dāng)紅燈時(shí)間變?yōu)?)綠燈/車輛擁堵—(當(dāng)小車未經(jīng)過車輛擁堵時(shí)車輛擁堵時(shí)間為0)按照概率產(chǎn)生一個(gè),兩個(gè),或者不產(chǎn)生車輛擁堵)。
在generateJams 中,首先,按照概率判斷是產(chǎn)生紅燈擁堵還是車輛擁堵,紅燈擁堵車輛擁堵概率分別為(0.7,0.3);其次,按照在不同的道路等級和道路類型上產(chǎn)生紅燈和車輛擁堵的概率,按照概率隨機(jī)產(chǎn)生擁堵,(每200 m 隨機(jī)一次)。紅燈的起始時(shí)間為1~90 s 隨機(jī),車輛擁堵的起始時(shí)間為90~300 s 隨機(jī)。最后用append 累計(jì)輸出總的擁堵情況(擁堵位置,是否擁堵,擁堵類型,擁堵時(shí)間)。
產(chǎn)生擁堵設(shè)計(jì):
{先按照概率隨機(jī)選出擁堵類型jamtype為紅燈擁堵還是車輛擁堵。
If(jamtype==’車輛擁堵’)
If(當(dāng)前單路類型或者道路等級產(chǎn)生車輛擁堵的概率<cofigs.py 中不同道路類型道路等級產(chǎn)生車輛擁堵的概率)
jamSituation='擁堵'
else:
jamSituation='無擁堵'
If(jamtype==’紅燈’)
If(當(dāng)前單路類型或者道路等級產(chǎn)生紅燈擁堵的概率<cofigs.py 中不同道路類型道路等級產(chǎn)生紅燈的概率)
jamSituation='擁堵'
else:
jamSituation='無擁堵'
紅燈(signalTime)和車輛擁堵(jamTime)起始時(shí)間為configs.py中規(guī)定的起始時(shí)間中隨機(jī)選擇一個(gè)值。
if(jamSituation=='擁堵'and jamType=='紅燈'):
jamSummary=[當(dāng)前位置,到當(dāng)前位置+configs.py中每多少米隨機(jī)可能產(chǎn)生一個(gè)擁堵的距離,是否有擁堵,擁堵類型,信號燈時(shí)間]
self.jam.append(jamSummary)(把所有擁堵情況放到self.jam中)
lastPosition=lastPosition+ConfigRandomRoute.congestionDistance(下一次可能產(chǎn)生擁堵的位置)
allJams=allJams+1(擁堵數(shù)量+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
在日志中輸出總的擁堵情況統(tǒng)計(jì)self.jam 及總共擁堵數(shù)量allJams
return self.jam}
在updateJams 中,當(dāng)紅燈時(shí)間歸零后,變?yōu)榫G燈,此時(shí)為不擁堵的情況,綠燈時(shí)間為90 s,如果綠燈時(shí)間未到0小車通過當(dāng)前的綠燈,那么不算碰撞游戲繼續(xù),刪除這個(gè)擁堵情況;如果綠燈時(shí)間歸零小車還未到此綠燈,那么綠燈變?yōu)榧t燈,此時(shí)為擁堵的情況,時(shí)間為90 s(紅綠燈轉(zhuǎn)換時(shí)間為90 s),如果當(dāng)車輛擁堵時(shí)間未到0,而小車通過了此處車輛擁堵,那么即小車發(fā)生了碰撞,游戲結(jié)束了;如果當(dāng)前車輛擁堵時(shí)間到0,而小車還未到達(dá)此處車輛擁堵,那么按照概率,70%的概率在小車當(dāng)前位置到終點(diǎn)產(chǎn)生新?lián)矶拢?0%的概率在小車當(dāng)前位置到終點(diǎn)不產(chǎn)生新的擁堵。如果產(chǎn)生了新的擁堵,那么有50%的概率在小車當(dāng)前位置到終點(diǎn)產(chǎn)生兩個(gè)新?lián)矶?,?0%的概率在小車當(dāng)前位置到終點(diǎn)產(chǎn)生一個(gè)新?lián)矶隆N覀兪紫纫_定一下是否在當(dāng)前位置到終點(diǎn)處有擁堵的情況,如果有則返回最近的擁堵位置,沒有則返回-1。如果前方有擁堵情況,創(chuàng)建一個(gè)realJams=[],realJams.append(當(dāng)前的擁堵情況),如果沒擁堵則返回10,如果有擁堵,判斷,該擁堵如果距離小車1 000 m以外則返回-1,如果該擁堵在離小車1 000 m之內(nèi)則返回當(dāng)前擁堵歸一化位置減去小車歸一化位置值為(0,1)之間,如果當(dāng)前小車超過了擁堵位置即發(fā)生了碰撞,則返回-10,游戲結(jié)束。最后如果游戲繼續(xù),則按照擁堵位置大小,一次排序進(jìn)行下一次秒的更新。
擁堵更新算法設(shè)計(jì):
if 前方無擁堵:
jamDistance=-1
return jamDistance
else:
realJams=[]
for語句找到當(dāng)前所有的擁堵
realJams.append(self.jam[i])都放在realJams中
if len(realJams)==0:前方無擁堵
minDistanceJamFront=10
else:
minDistanceJamFront=realJams[0][0](最近的擁堵值的位置)
if 當(dāng)前位置<=(minDistanceJamFront -1000/ (路總長)):
jamDistance=-1
elif 當(dāng)前位置>(minDistanceJamFront -1000/ (路總長))and 當(dāng)前位置<minDistanceJamFront:
jamDistance=(minDistanceJamFront -當(dāng)前位置)/(1000/(路總長))
else:#當(dāng)前位置==minDistanceJam
if(realJams[0][2]=='紅燈')or(realJams[0][2]=='車輛擁堵'):
jamDistance=-10
else:
jamDistance=-1
日志中輸出當(dāng)前共有的擁堵數(shù)量
碰撞檢測即為判斷駕駛機(jī)器人位置是否超過了擁堵位置。
檢測判斷:駕駛機(jī)器人當(dāng)前位置<最近擁堵,駕駛機(jī)器人當(dāng)前位置>=最近擁堵;
判斷結(jié)果:沒發(fā)生碰撞,游戲繼續(xù)進(jìn)行。發(fā)生了碰撞,游戲結(jié)束。
用DDQN 算法訓(xùn)練駕駛機(jī)器人,隨著訓(xùn)練次數(shù)增加獎勵(lì)穩(wěn)步也在穩(wěn)定地提升,剛開始時(shí)波動比較大,隨著學(xué)習(xí)次數(shù)增加獎勵(lì)越來越高波動越來越小。
仿真環(huán)境的構(gòu)建對于機(jī)器人訓(xùn)練順利進(jìn)行起著重要的作用,擁堵算法的設(shè)計(jì)要切合實(shí)際,要聯(lián)想到生活當(dāng)中,在駕駛時(shí)可能遇到的擁堵情況,一個(gè)好的虛擬鏈路仿真環(huán)境,可以讓游戲更加地切合實(shí)際,以便于之后用算法來訓(xùn)練機(jī)器人,讓機(jī)器人不斷地去學(xué)習(xí),最后實(shí)現(xiàn)更快、更安全地到達(dá)終點(diǎn)的目的。