李雨松 徐野 哈樂
(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 算法訓練駕駛機器人,隨著訓練次數增加獎勵穩步也在穩定地提升,剛開始時波動比較大,隨著學習次數增加獎勵越來越高波動越來越小。
仿真環境的構建對于機器人訓練順利進行起著重要的作用,擁堵算法的設計要切合實際,要聯想到生活當中,在駕駛時可能遇到的擁堵情況,一個好的虛擬鏈路仿真環境,可以讓游戲更加地切合實際,以便于之后用算法來訓練機器人,讓機器人不斷地去學習,最后實現更快、更安全地到達終點的目的。