第五章 模式應用與情境分析
6.2 建議
1、由於研究時間與人力不足,本研究著重在事故模擬功能,在程式設計過程中作 了若干的簡化設定,以便程式可以順利執行。模式中考慮前方車隊停等車輛 數,然而事故發生之瞬間,接近事故地點的車子皆為強制煞車,應該以預設之 停等長度取代之。
2、在一般車道的跟車行為,乃採用車間距在小於 Dmin時表示車間距太小,所以 採取減速;車間距大於 Dmax時表示車間距太大,所以採用加速;在 Dmin跟 Dmax 之間則加速度等於 0。由於採用加減速皆以最大加減速度來執行,用意為考慮 安全的因素下,越快保持在安全車間距內對行車安全越好。但建議可以考慮 乘客舒適度下,可以加入衝度(jerk)的問題,讓加減速度在舒適的環境下執行 跟車,但仍在考慮安全狀態下加速度變化率的數值大小,也是提供後續研究 作為參考。
3、在模擬時間過後之無法順利變換車道而停等在自動控制車道之殘餘車輛停等 長度,會對事故更上游之車隊到達造成影響,然而建議考慮的是更上游的車 隊可能會因為殘餘的停等長度而需要作一些反應,如事故上游車隊的大小規 模不相同、車隊與車隊出現之間隔時間(headway)等問題,供作為後續作相關 研究之參考。
4、建議可以考慮第三個車道(最外側車道)變換進入中間車道,對於 AC 車輛變換 車道時的影響。
5、本研究所採用鄰近車道的跟車行為,乃用 Dmin與 Dmax的方式,則 Dmin與 Dmax 的數值直接影響跟車行為,故建議可以模擬測試出較佳或最適的數值。另外,
跟車行為也有其他的模式,如通用汽車第一代至第五代的跟車模式,建議可 以納入模擬。
6、建議 Dmin與 Dmax的跟車方式,可以考慮加入前後車為不同車種,或者相同車 種,有不同的 Dmin與 Dmax值,可參考蔡孟釗(2005)之相關研究。
7、本研究之程式撰寫部分乃以 Turbo C V2.01 開發,由於 Turbo C V2.01 版有繪 圖之功能,但鑑於 Turbo C 開發已有一段時間,更多功能及介面的程式語言也 已推出(如:C++),像是用 thread 可以撰寫一輛車子的演算法(algorithm)來代 替所有車子的演算,故建議以更合時宜且功能強大的程式語言進行開發。
8、未來如果可以取得自動公路系統測試之相關資料,可以針對未發生事故前之車 隊前進做模式之實例驗證。
參考文獻
1. Adolf D. May, “Traffic Flow Fundamentals”, University of California, Berkeley, Prentice Hall, p.296~p.301, 1990.
2. AHSRA Japan, http://www.ahsra.or.jp/
3. Alexander Kanaris,“Strategies and Spacing Requirements for Lane Changing and Merging in Automated Highway Systems”, IEEE Conference, 2001
4. Cem Hatipoglu, Ümit Özgüne, Keith A. Redmill, “Automated Lane Change Controller Design”, IEEE Transactions on Intelligent Transportation System, Vol.
4, No.1, March 2003.
5. Cem Ünsal, “Intelligent Navigation of Autonomous Vehicles in an Automated Highway System: Learning Methods and Interacting Vehicles Approach”, Virginia Polytechnic Institute and State University, Ph.D Thesis pp2-6, 1997.
6. Datta N. Godbole, Raja Sengupta, Veit Hagenmeyer, “Distributed Hybrid Controls for Automated Vehicle Lane Changes”, Proceedings of the 37th IEEE Conference on Decision & Control Tampa, Florida USA, December 1998.
7. ITS-America, http://www.itsa.org/
8. J.B. Sheu, “Microscopic Control Logic for Incident-Responsive Automatic Vehicle Control in Single-Automated-Lane Highway Systems”, Paper submitted to Transportation Science, 2004.
9. Junji Kaneko, Akihide Shimamura, “A design of Lane change Maneuver for Automated Vehicles”, The IEEE 37th Conference on Decision & Control Tampa, 1998.
10. Lingxi Li, Fei-Yue Wang, “The Automated Lane-Changing Model of Intelligent Vehicle Highway Systems”, The IEEE 5th International Conference on Intelligent Transportation Systems, 2002.
11. M.Broucke, P.Varaiya, “A Theory of Traffic Flow in Automated Highway Systems”, Transportation Research Part C. Vol. 4, pp. 181-210, 1996.
12. Quadstone Limited Co., Paramics traffic simulation, Modeller V4.0, User Guide, 2003.
13. R. Rajamani, S.E. Shladover, “An experimental comparative study of autonomous and co-operative vehicle-follower control systems”, Transportation Research Part C, Vol.9, no.1, pp.15-31, 2001.
14. Wonshik Chee, Masayoshi Tomizuka, “Lane Change Maneuver of Automobiles for The Intelligent Vehicle and Highway System (IVHS)”, American Control Conference, June 1994.
15. Yoji Seto, Hideaki Inoue, “Development of platoon driving in AHS”, JSAE Review, Vol.20, 1999.
16. 王敏聰,「自動跟車模式之研究及其在車流上的位階」,淡江大學運輸科學 研究所,碩士論文,1999。
17. 交通部運輸研究所,台灣地區智慧型運輸系統發展綱要計畫,2001。
18. 交通部運輸研究所,2001 年台灣地區公路容量手冊,2001。
19. 李月仙,「微觀車流模擬模式與適應性交通控制策略之整合研究」,國立成 功大學交通管理科學研究所,碩士論文,1989。
20. 張鈞華,「模擬一般市區道路事故發生之微觀車流行為」,國立台灣大學土 木工程系研究所,碩士論文,2001。
附錄 A Turbo C 程式碼
第一部份 變數及函式說明:
1. 變數說明:
TOTALSECONDS : 系統總時間(sec)
TIMESLICE : 時階單位時間(sec)
TOTALSTEPS : 系統總步驟
INCIDENT_X : 事故地點(m)
ROADLEN : 道路長度(m)
CAR_TYPE_1 “Q” : 車輛種類(自動車)
CAR_TYPE_2 “P” : 車輛種類(手動車)
MAX_ACC : 車輛最大加速度(m/s2)
MAX_DEACC : 車輛最大減速度(m/s)
MAX_SPEED : 車輛最大速率(m)
PLATOON_TOTAL_SECONDS : 車隊產生間距時間(sec)
D_MAX : 最大車間距(m)
D_MIN : 最小車間距(m)
D_EXT : 車間距極值(m)
DEC_DX : 自動車產生所保持之車時間距(sec)
TRANS_SECONDS : 變換車道所需時間(sec)
struct node : 車輛資料結構
x : 車輛 x 座標(m)
y : 車輛 y 座標(m)
car_type : 車輛種類
car_seq : 車輛個別獨有之 I D
v : 速度(m/s)
a : 加速度(m/s2)
國立交通大學交通運輸研究所碩士班 指導教授:許 鉅 秉
研 究 生:許 智 詠
程式名稱:因應事故自動控制車隊變換車道模擬程式 日 期:2005 年 6 月
d : 車隊拆解區門檻值(m)
f : 跟車緩衝區門檻值(m)
b : 強制煞車區門檻值(m)
transflag : 變換車道顯示
translock : 變換車道鎖定
STEPS : 系統步驟
platoon_size : 自動車隊規模大小
v0 : 自動車隊初始速率(m/s)
flow : 鄰近車道車流量(veh/plph)
next_car_time : 產生下一台車輛間隔時間(sec)
2. 函式說明:
main( ) : 主函式
P_laneGenerator( ) : 自動車輛產生器函式
Q_laneGenerator( ) : 手動車輛產生器函式
P_laneTransition( ) : 自動車道上之車輛運行函式
Q_laneTransition( ) : 手動車道上之車輛運行函式
v_acc_car( ) : 呼叫車速函式
x_acc_car( ) : 呼叫位置函式
watchtime( ) : 觀看系統時間函式
brakelength( ) : 計算最大煞車距離函式
hittime( ) : 呼叫與對照系統時間函式
search_insert( ) : 變換車道控制函式
check_trans( ) : 確認變換車道位置函式
car_can_reach( ) : 呼叫變換車道可能的加速度函式
cal_safe( ) : 保持安全車間距函式
collision( ) : 系統碰撞偵測函式
normal( ) : 常態分配函式
drawRoad( ) : 繪製道路函式
drawlane( ) : 繪製車輛函式
showpq( ) : 輸出結果資料函式
第二部分 程式碼:
#include <graphics.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#define TOTALSECONDS 100
#define TIMESLICE 0.1
#define TOTALSTEPS (int)(TOTALSECONDS/TIMESLICE)
#define INCIDENT_X 600.0
#define ROADLEN 640.0
#define CAR_TYPE_MANUAL 'P'
#define CAR_TYPE_AUTO 'Q'
#define MAX_ACC 3.6
#define MAX_DEACC 7.2
#define MAX_SPEED 32
#define PLATOON_TOTAL_SECONDS 30
#define D_MAX 50
#define D_MIN 20
#define D_EXT 150
#define DEC_DX 30
#define TRANS_SECONDS 4
FILE *o;
struct node {
float x;
float y;
int car_type;
int car_seq;
float v;
float a;
float d;
float f;
float b;
int transflag;
int translock;
float transtime;
struct node *trans;
struct node *head;
struct node *tail;
};
float normal(float ave,float dev);
struct node *p=NULL;
struct node *q=NULL;
struct node *headp=NULL;
struct node *headq=NULL;
int P_laneGenerator(float,int);
int Q_laneGenerator(float);
int P_laneTransition();
int Q_laneTransition();
float v_acc_car(float v0,float a,float t);
float x_acc_car(float x0,float v0,float a,float t);
float watchtime();
float brakelength(float v0);
int hittime(float);
int search_insert();
int collision();
int STEPS;
int check_trans(struct node *car);
int car_can_reach(struct node *car,float x1,float x2);
int cal_safe(struct node *car,float DMIN,float DMAX,float DEXT);
int headqtranslock=0;
void drawlane() {
int x;
struct node *current;
current = headp;
while(current!=NULL){
if(current->transflag) setfillstyle(1,60);
else
setfillstyle(1,current->car_type-21);
x=(int)current->x/ROADLEN*640;
current = current->tail;
}
current = headq;
while(current!=NULL){
setfillstyle(1,current->car_type-21);
x=(int)current->x/ROADLEN*640;
bar(x,35,x+1,37);
current = current->tail;
} }
void drawRoad(void) {
float x;
setlinestyle(0,0,1);
line(0,24,640,24);
line(0,48,640,48);
setlinestyle(3,0,1);
line(0,32,640,32);
line(0,40,640,40);
setfillstyle(4,63);
x=INCIDENT_X/ROADLEN*640;
bar(x,24,x+10,32);
}
void showpq() {
struct node* temp;
int i;
for(i=0;i<2;i++){
if(i){
temp=headq;
fprintf(o,"Q-lane:\n");
} else{
temp=headp;
fprintf(o,"P-lane:\n");
}
fprintf(o,"CAR\tx\tv\ta\ttrans\n");
while(temp){
fprintf(o,"%c%03d: %.3f %.3f %.3f\t",\
temp->car_type,temp->car_seq,temp->x,temp->v,temp->a);
if(temp->transflag) fprintf(o,"*:%.3f",temp->transtime);
fprintf(o,"\n");
temp=temp->tail;
} }
fprintf(o,"---\n");
}
int main() {
float v0,flow;
int platoon_size;
struct node* temp;
int k,l;
int graphdriver=DETECT,graphmode=DETECT;
initgraph(&graphdriver,&graphmode,"");
if((o=fopen("file01.xls","w")) == NULL){
fprintf(o,"Open file file01.xls for writing error\n");
return -1;
}
printf("Platoon size(2-15):");
scanf("%d",&platoon_size);
printf("Initial speed of platoon(in kph)");
scanf("%f",&v0);
printf("Flow of adjacent lane is (100-2300):");
scanf("%f",&flow);
v0=v0*10/36;
flow/=60;
for(STEPS=0;((STEPS<TOTALSTEPS)&&(!collision()));STEPS++) {
drawRoad();
P_laneGenerator(v0,platoon_size);
Q_laneGenerator(flow);
drawlane();
P_laneTransition();
Q_laneTransition();
fprintf(o,"\t\t\t\t\t\t%.2f\n",watchtime());
showpq();
for(k=0;k<30000;k++) for(l=0;l<1000;l++);
cleardevice();
}
closegraph();
getchar();
return 0;
}
int Q_laneGenerator(float flow) {
static float next_car_time=0;
static int carseq=0;
struct node *temp;
if(q&&(q->x<5) )return 1;
if(hittime(next_car_time)){
temp=(struct node *)malloc(sizeof(struct node));
temp->head=q;
temp->tail=NULL;
if(q!=NULL) q->tail=temp;
else headq=temp;
q=temp;
temp->x=0;
temp->y=35;
temp->v=normal(15,5);
temp->a=0;
temp->transflag=0;
temp->translock=0;
temp->car_type=CAR_TYPE_1;
temp->car_seq=++carseq;
next_car_time+=normal(60/flow,1);
fprintf(o,"Q:%03d is born\n",carseq);
}
}
int P_laneGenerator(float v0,int platoon_size) {
static float next_car_time=0;
static int carseq=0;
struct node *temp;
float b,f,d;
if((p)&&(p->x<20)){
next_car_time+=.1;
return 1;
}
if(hittime(next_car_time)){
temp=(struct node *)malloc(sizeof(struct node));
temp->head=p;
temp->tail=NULL;
if(p!=NULL) p->tail=temp;
else headp=temp;
p=temp;
temp->x=0;
temp->y=27;
temp->v=v0;
temp->a=0;
temp->transflag=0;
temp->translock=0;
temp->car_type=CAR_TYPE_2;
temp->car_seq=++carseq;
b= 4+8*(carseq-1)+v0*v0/(2*MAX_DEACC) ; f= DEC_DX+carseq*(15-v0)*(15-v0)/(2*MAX_DEACC);
d=4+(carseq-1)*(4+8)+v0*10;
temp->b=INCIDENT_X-b;
temp->f=(INCIDENT_X-b-f>0)? (INCIDENT_X-b-f):0;
temp->d=(INCIDENT_X-b-f-d>0)? (INCIDENT_X-b-f-d):0;
if((carseq%platoon_size)==0)
next_car_time =PLATOON_TOTAL_SECONDS*carseq/platoon_size;
else
next_car_time +=25/v0;
temp->b);
} }
int P_laneTransition() {
struct node *current,*tailtemp;
current=headp;
while(current!=NULL){
if(current->transflag){
if(current->transtime<watchtime()){
tailtemp=current->tail;
search_insert(current);
current->transflag=0;
current->a=0;
fprintf(o,"P:%03d is changed to Q",current->car_seq);
if(current->trans) fprintf(o,"%03d",current->trans->car_seq);
fprintf(o,"\n");
current=tailtemp;
} else{
current->x=x_acc_car(current->x,current->v,current->a,TIMESLICE);
current->v=v_acc_car(current->v,current->a,TIMESLICE);
current=current->tail;
} }
else{
if(current->x<current->d) current->a=0;
else if((current->x>=current->d)&&(current->x<current->f)) cal_safe(current,DEC_DX,DEC_DX,D_EXT);
else if((current->x>=current->f)&&(current->x<current->b)){
/* cal_safe(current,DEC_DX,DEC_DX,D_EXT); */
if(current->v>15)
current->a=-MAX_DEACC;
check_trans(current);
} }
else{
if(!check_trans(current))
current->a=-MAX_DEACC;
}
current->x=x_acc_car(current->x,current->v,current->a,TIMESLICE);
current->v=v_acc_car(current->v,current->a,TIMESLICE);
current=current->tail;
}
}
}
int Q_laneTransition() {
struct node *current;
current=headq;
while(current!=NULL){
cal_safe(current,D_MIN,D_MAX,D_EXT);
current->x=x_acc_car(current->x,current->v,current->a,TIMESLICE);
current->v=v_acc_car(current->v,current->a,TIMESLICE);
current=current->tail;
} }
int hittime(float i) {
float j;
j=watchtime();
if ((i>(j-TIMESLICE/2))&&(i<=(j+TIMESLICE/2))) return 1;
return 0;
}
float watchtime() {
return STEPS*TIMESLICE;
}
float x_acc_car(float x0,float v0,float a,float t)
float x=0.0,v,t1;
v=v0+a*t;
x=v0*t+0.5*a*t*t;
if(v0>(MAX_SPEED-0.2)) x=v0*t;
else if (v>MAX_SPEED){
t1=(MAX_SPEED-v0)/a;
x= 0.5*(2*t-t1)*(MAX_SPEED-v0)+v0*t;
}
else if (v<0)
x= v0*v0/(2*a);
return x+x0;
}
float v_acc_car(float v0,float a,float t) {
float v;
v=v0+a*t;
if (v>MAX_SPEED) return MAX_SPEED;
else if (v<0) return 0.0;
return v;
}
int collision() {
struct node * temp;
struct node * tempt;
int i;
temp=headq;
for(i=0;i<2;i++){
if(i){
tempt=q;
temp=headq;
} else{
tempt=p;
temp=headp;
}
while(temp!=tempt){
if((temp->x<temp->tail->x)&&(temp->transflag==0)){
if(temp->tail->transflag==0){
fprintf(o,"Err!+++Collision at %c%03d,%c%03d ++++\n",\
temp->car_type,temp->car_seq,\
temp->tail->car_type,temp->tail->car_seq);
return 1;
int check_trans(struct node *car) {
x2=x_acc_car(headq->x,headq->v,MAX_ACC,TRANS_SECONDS);
v2=v_acc_car(headq->v,MAX_ACC,TRANS_SECONDS);
x2+=brakelength(v2);
if((car_can_reach(car,ROADLEN,x2))&&(headqtranslock==0)){
car->trans=NULL;
car->transtime=watchtime()+TRANS_SECONDS;
car->transflag=1;
headqtranslock=1;
return 1;
} else
car->a=a0;
while(temp!=NULL){
x1=x_acc_car(temp->x,temp->v,-MAX_DEACC,TRANS_SECONDS);
if(temp!=q) {
x2=x_acc_car(temp->tail->x,temp->tail->v,MAX_ACC,TRANS_SECONDS);
v2=v_acc_car(temp->tail->v,MAX_ACC,TRANS_SECONDS);
x2+=brakelength(v2);
} else
x2=0;
if((car_can_reach(car,x1,x2))&&(temp->translock==0)){
car->trans=temp;
car->transflag=1;
temp->translock=1;
car->transtime=watchtime()+TRANS_SECONDS;
return 1;
} else
car->a=a0;
temp=temp->tail;
}
return 0;
}
float v_car_reach(struct node *car,float x1,float x2) {
if(((a1<=MAX_ACC)&&(a1>0))||((a1>=-MAX_DEACC)&&(a1<0))) return v_acc_car(car->v,a1,TRANS_SECONDS);
if(((a2<=MAX_ACC) &&(a2>0))||((a2>=-MAX_DEACC)&&(a2<0))) return v_acc_car(car->v,a2,TRANS_SECONDS);
return -1;
}
int car_can_reach(struct node *car,float x1,float x2) {
float x0,a0=0,a1,a2;
float blength;
x1-=brakelength(v_car_reach(car,x1,x2));
if((x1-x2)<6) return 0;
a1=((x1-car->x)-car->v*TRANS_SECONDS)/(0.5*TRANS_SECONDS*TRANS_SEC ONDS);
a2=((x2-car->x)-car->v*TRANS_SECONDS)/(0.5*TRANS_SECONDS*TRANS_SEC ONDS);
if((a2>MAX_ACC)||(a1<-MAX_DEACC)) return 0;
if(((a1<=MAX_ACC)&&(a1>0))||((a1>=-MAX_DEACC)&&(a1<0)))
a0=a1;
else if(((a2<=MAX_ACC) &&(a2>0))||((a2>=-MAX_DEACC)&&(a2<0))) a0=a2;
int search_insert(struct node *car) {
if((car==headp)&&(car==p)){
headp=NULL;
p=NULL;
}
else if(car==headp){
car->tail->head=NULL;
headp=car->tail;
}
else if(car==p){
car->head->tail=NULL;
p=car->head;
}
else{
car->head->tail=car->tail;
car->tail->head=car->head;
car->head=car->trans;
if(car->trans==NULL) { car->tail=headq;
headq->head=car;
headq=car;
headqtranslock=0;
}
else if(car->trans==q){
car->tail=car->trans->tail;
car->trans->tail=car;
car->trans->translock=0;
q=car;
int cal_safe(struct node *car,float DMIN,float DMAX,float DEXT) {
float dmin ; struct node* temp;
if(car->head==NULL) return 0;
temp=car->head;
while((temp!=NULL)&&(temp->transflag)) temp=temp->head;
if(temp==NULL) return 0;
dmin=(-temp->v*temp->v+car->v*car->v)/2*7.2;
if(dmin>DMIN) DMIN=dmin;
if((temp->x-car->x)<=DMIN){
if(DMIN==DMAX) car->a=0;
else car->a=-7.2;
}
else if ((temp->x-car->x)>DEXT)
car->a=0;
else if((temp->x-car->x)>DMAX){
if(DMIN==DMAX) car->a=0;
else car->a=3.6;
} else
car->a=0;
return 0;
}
float brakelength(float v0) {
if(v0<0) return 0;
return (v0*v0/(2*MAX_DEACC));
}
float normal(float mean,float stddev) {
static double V2, fac;
static int phase = 0;
double S, Z, U1, U2, V1;
if (phase) Z = V2 * fac;
else{
do{
U1 = (double)rand() / RAND_MAX;
U2 = (double)rand() / RAND_MAX;
V1 = 2 * U1 - 1;
V2 = 2 * U2 - 1;
S = V1 * V1 + V2 * V2;
}while(S >= 1);
fac = sqrt (-2 * log(S) / S);
Z = V1 * fac;
}
phase = 1 - phase;
return ((float)Z)*stddev+mean;
}
附錄 B 模擬結果
表 B-2 情境 4~6 模擬結果
表 B-3 情境 7~9 模擬結果
表 B-4 情境 10~12 模擬結果
滯時間 39.4066667 平均停滯
時間 60.9857143 平均停滯
時間 0
表 B-5 情境 13~15 模擬結果
表 B-6 情境 16~18 模擬結果
表 B-7 情境 19~21 模擬結果
滯時間 34.2454545 平均停滯
時間 72.3538462 平均停
滯時間 0
表 B-8 情境 22~24 模擬結果
滯時間 26.2777778 平均停
滯時間 52.0454545 平均停
滯時間 15.8
表 B-9 情境 25~27 模擬結果
滯時間 32.8615385 平均停
滯時間 41.4153846 平均停滯
時間 23.58571
簡 歷
姓 名:許智詠 籍 貫:高雄市 生 日:69.10.08 學 歷:
92.9-94.6 國立交通大學交通運輸研究所碩士班 87.9-92.6 國立中山大學應用數學系
84.9-87.6 高雄市立瑞祥高級中學 81.9-84.6 高雄市立新興國民中學 Email :[email protected]