從0開始的智慧車程式碼(6)
阿新 • • 發佈:2020-08-03
桶形失真是由鏡頭引起的成像畫面呈桶形膨脹狀的失真現象。會將一些明顯的跳變點誤判成普通的弧線。
攝像頭的舵機控制與環島處理可以處理絕大多數的賽道狀況,美中不足的是攝像頭對於小圓環的處理不太理想,特別是彎道後的小圓環,會因嚴重的桶形失真影響判斷。另外,相比於攝像頭判斷,電磁判斷是一種更為簡單且穩妥的方案。
電磁杆上有4個電感,分別是左側水平電感、左側斜45°電感、右側斜45°電感、右側水平電感。
處理普通路段時,使用簡單的差比和演算法。斜45°電感的作用是判斷環島的方向。根據法拉第電磁感應定律,垂直於環島電磁線的電感的電壓值會明顯大於平行於環島電磁線的電感的電壓值。在入環和過環時,通過增大相應方向電感的電壓值的比例控制小車走向正確的方向。
void ADProcess(void){ uint16 AD1,AD2,AD3,AD4; AD1=adc_mean_filter(ADC_1,ADC1_CH3_B14,10); AD2=adc_mean_filter(ADC_1,ADC1_CH4_B15,10); AD3=adc_mean_filter(ADC_1,ADC1_CH10_B21,10); AD4=adc_mean_filter(ADC_1,ADC1_CH12_B23,10); lcd_showuint16(0,4,AD1); lcd_showuint16(0,5,AD2); lcd_showuint16(0,6,AD3); lcd_showuint16(0,7,AD4); if(AD1<40&&AD4<40){//出界停車 pit_close(PIT_CH0); pit_close(PIT_CH1); pwm_duty(PWM1_MODULE3_CHA_D0,0); pwm_duty(PWM1_MODULE3_CHB_D1,0); } /*====環島處理在這裡開始====*/ //AD1-4從右至左 static uint8 ringFlag=0; static uint8 ringSide=0; static uint32 ringCount=0; lcd_showuint8(0,2,ringFlag); if(ringFlag==0){ if((AD1+AD4>6000)&&(AD1-AD4<1500)&&(AD4-AD1<1500)&&(AD1>2000)&&(AD4>2000)){ ringFlag=1; } } else if(ringFlag==1){//已遇到環島未開始入環 if(ringSide==0){//已遇到環島未判斷方向 ringSide=AD2>AD3?1:2;//1:右環,2:左環 } else if((ringSide==1)&&(AD2<AD3)){ ringFlag=11;//開始入右環 } else if((ringSide==2)&&(AD2>AD3)){ ringFlag=12;//開始入左環 } } else if(ringFlag==11){ ringCount++; if(ringCount<80){ offset=-(int16)(80*((float)(4*AD2-AD3))/((float)(4*AD2+AD3))); return; } else if(ringCount>80){ if((AD1+AD4>6000)&&(AD1-AD4<1500)&&(AD4-AD1<1500)&&(AD1>2000)&&(AD4>2000)){ ringFlag=21;//開始出左環 ringCount=0; } } } else if(ringFlag==12){ ringCount++; if(ringCount<80){ offset=-(int16)(80*((float)(AD2-4*AD3))/((float)(AD2+4*AD3))); return; } else if(ringCount>80){ if((AD1+AD4>6000)&&(AD1-AD4<1500)&&(AD4-AD1<1500)&&(AD1>2000)&&(AD4>2000)){ ringFlag=22;//開始出右環 ringCount=0; } } } else if(ringFlag==21){ ringCount++; if(ringCount<80){ offset=-(int16)(80*((float)(AD2-4*AD3))/((float)(AD2+4*AD3))); return; } else if(ringCount>80){ ringFlag=0; ringSide=0; ringCount=0; } } else if(ringFlag==22){ ringCount++; if(ringCount<80){ offset=-(int16)(80*((float)(4*AD2-AD3))/((float)(4*AD2+AD3))); return; } else if(ringCount>80){ ringFlag=0; ringSide=0; ringCount=0; } } /*====環島處理在這裡結束====*/ offset=-(int16)(80*((float)(AD1-AD4))/((float)(AD1+AD4))); }