循線算法原理與實踐在機(jī)器人上的應(yīng)用
出處:互聯(lián)網(wǎng) 發(fā)布于:2011-06-06 18:43:05
前言
現(xiàn)在,國際上對機(jī)器人的概念已經(jīng)逐漸趨近一致。一般說來,人們都可以接受這種說法,即機(jī)器人是靠自身動力和控制能力來實現(xiàn)各種功能的一種機(jī)器。聯(lián)合國標(biāo)準(zhǔn)化組織采納了美國機(jī)器人協(xié)會給機(jī)器人下的定義:“一種可編程和多功能的,用來搬運材料、零件、工具的操作機(jī);或是為了執(zhí)行不同的任務(wù)而具有可用電腦改變和可編程動作的專門系統(tǒng)。”現(xiàn)在機(jī)器人也在逐漸走向普及,在各方面得到了應(yīng)用。本文介紹的是機(jī)器人的循線算法原理及其實踐應(yīng)用。
硬件基本構(gòu)架
對于機(jī)器人的循線,為了獲得場地上白線(黑線)的信息,硬件結(jié)構(gòu)一般有如下幾種種類。
1、紅外對管陣列。采取這種方式的機(jī)器人比較多,尤其在各種機(jī)器人競賽中,幾乎是標(biāo)準(zhǔn)配置。但是這種技術(shù)有一個致命的弱點,就是對于場地光線的干擾特別敏感,而且也很難把紅色和白線區(qū)別開來,所以使用受到一定的限制。一般解決這類問題的方法是在紅外光上加載一個調(diào)制波,通過檢測這個調(diào)制波來消除場地光線的干擾,至于如何解決紅色和白色的區(qū)別問題,那就幾乎是五花八門了。
2、光纖傳感器陣列。采用這種傳感器陣列的原因是,光纖非常細(xì),在單位面積內(nèi)可以安裝更多的傳感器,從而獲得更地場地信息。當(dāng)然,錢也也花得更多。
3、線性CCD。這種硬件方法幾乎是一種對場地信息分辨率的BT追求,如果說紅外對管陣列還是離散信息的話,那么線性CCD就是線性的連續(xù)數(shù)據(jù)。當(dāng)然驅(qū)動它也不是一件容易的事情,對于單片機(jī)也有更高的速度要求。
4、視覺。視覺技術(shù)相對復(fù)雜,對硬件設(shè)備的要求對我們來說就好比是 平民要迎娶公主一樣 天價……沒有個10萬8萬不要過問——當(dāng)然,大款斗不過公_款,在實驗室耍的各位不在以上說明之列。
OurRobotV1是一款面向廣大初學(xué)者的DIY類機(jī)器人系統(tǒng),肯定從基礎(chǔ)“原理”的部分入手了哈——成本也是考慮因素之一。硬件系統(tǒng)使用4051驅(qū)動 5個紅外管,通過AD來采集,在程序中需要使用以下的配置來驅(qū)動該硬件系統(tǒng):
/*-----------紅外循線模塊初始化--------------*/
# define IRSB_A _PB2 //3個4051通道
# define IRSB_B _PB1
# define IRSB_C _PB0
# define IRSB_COM 0 //使用AD0通道
# define IRSB_SENSOR_COUNT 5 //說明管子的數(shù)目,默認(rèn)為8個
# define IRSB_SENSOR_SENSITIVITY 50 //對外界環(huán)境的靈敏度
# define IRSB_SENSOR_BLACK_LINE //白底黑線,默認(rèn)黑底白線
# include <RD_UseInfraredScanBoard.h> //頭文件
基本原理
所謂循線,就是通過一定的傳感器探測地面色調(diào)迥異的兩種色彩從而獲得引導(dǎo)線位置,修正機(jī)器人運動路徑的一種技術(shù)。就紅外傳感器來說,就是通過對主動發(fā)射的紅外線進(jìn)行接受,檢測反射光的強(qiáng)度來獲取地面色彩信息的。常識告訴我們,黑色幾乎不反射,所以回來的光強(qiáng)弱,白色反射很強(qiáng),所以很容易被從黑色的背景中檢測到——說的太拗口了。不說太多理論的東西,我們就從基于紅外對管陣列的循線技術(shù)來說起。
假設(shè),我們使用的是黑底白線的場地。紅外對管陣列由3個紅外對管1字?jǐn)[開組成。白線的寬度略小于或等于紅外對管陣列的寬度。
1 數(shù)據(jù)的采集
對于機(jī)器人來說,通過傳感器感知周圍事物的信息,利用這些信息并不作太多智能上的計算而直接通過一定的轉(zhuǎn)換,指導(dǎo)機(jī)器人的運動——這種形式在人工智能(AI)上叫做機(jī)器人的“反應(yīng)范式”。我們要想讓我們的機(jī)器人能夠?qū)ぶ覀兘o定的軌跡線運動,步就必須讓他感知到軌跡線的存在。一般的做法就是通過AD采樣,獲得紅外對管(傳感器)反饋回來的電壓信息。然而,這樣獲得的電壓值信息是無法直接指導(dǎo)運動的,必須把他們轉(zhuǎn)化為二值(也就是二進(jìn)制信息,1表示線存在,0表示線不存在)信息,然后掃描每一個管子反饋回來的二值信息來判斷白線的位置。
》技術(shù)點A
AD信號的閥值化。(你可以參考其它的算法,獲得比較詳盡的技術(shù),我這里只是舉例一二)
所謂閥值化,就是通過一定的“范圍把握”,把線性數(shù)據(jù)轉(zhuǎn)化為離散數(shù)據(jù)的一種變換。簡單的說,就是通過分段函數(shù)的方法,將數(shù)據(jù)分類。我們這個應(yīng)用中,需要使AD采集回來的電壓信息陣列變換為一個恰恰能夠較為準(zhǔn)確表示白線位置信息的二進(jìn)制信息陣列;假定1代表白線存在,0代表白線不存在。由于白色和黑色在電壓差異上非常之巨大,所以可以簡單的通過一個標(biāo)志線來區(qū)分它們,當(dāng)電壓值高于這個標(biāo)志線了,就把他標(biāo)志為1,否則就標(biāo)志為0,算法描述為:
if (AdValue[i] > MarkLing)
{
LineInfor[i] = 1;
}
else
{
LineInfor[i] = 0;
}
這樣做非常簡單,適合于比較標(biāo)準(zhǔn)的場地,然而對于那些模糊了的場地或者是非標(biāo)準(zhǔn)場地,即便人的肉眼能夠看出來,對于機(jī)器人來說,看到的就是花白的一片或者是黑色的夜幕——當(dāng)標(biāo)志線值過高時,機(jī)器人能看到的只是那些特別明顯的白線,其他則是黑色的夜幕,很容易丟失軌跡線;當(dāng)標(biāo)志線值過低時,機(jī)器人眼中就是白茫茫的一片毛刺??偠灾?,這種方法對場地的適應(yīng)性非常差。解決方法是,利用斯密特觸發(fā)特性,通過設(shè)定兩個標(biāo)志線來標(biāo)定軌跡線信息,當(dāng)AD值高于某一值且原本狀態(tài)位標(biāo)志該位置為0時,標(biāo)志1;當(dāng)AD值低于另外某一值且原本狀態(tài)位顯示該位置為1時,標(biāo)定0。算法描述為:
/***********************************************************
* 函數(shù)說明:白線狀態(tài)計算函數(shù) *
* 輸入: 結(jié)果變量的地址 *
* 輸出: 探測到白線的傳感器數(shù)量 *
***********************************************************/
char IRSBgetLineState(char *LastState)
{
char n = 0;
char Start = 0;
char TGTCounter = 0;
#ifdef IRSB_SENSOR_COUNT_EVEN //傳感器為偶數(shù)時的情形
Start = (8 - IRSB_SENSOR_COUNT)》1;
#else //傳感器為奇數(shù)時的情形
Start = (7 - IRSB_SENSOR_COUNT)》1;
#endif
for (n = 0;n<IRSB_SENSOR_COUNT;n++)
{
#ifndef IRSB_SENSOR_BLACK_LINE
if ((*LastState) 《 (7 - Start - n)》7) //從上向下跳變
{
if (IRSB_SENSOR(n) < IRSBJudgeLine[0])
{
?。?LastState) &= ~(1 《 (Start + n));
}
else
{
TGTCounter ++;
}
}
else //從下向上跳變
{
if (IRSB_SENSOR(n) > IRSBJudgeLine[1])
{
?。?LastState) |= 1 《 (Start + n);
TGTCounter ++;
}
}
#else
if ((*LastState) 《 (7 - Start - n)》7) //從上向下跳變
{
if (IRSB_SENSOR(n) > IRSBJudgeLine[1])
{
(*LastState) &= ~(1 《 (Start + n));
}
else
{
TGTCounter ++;
}
}
else //從下向上跳變
{
if (IRSB_SENSOR(n) < IRSBJudgeLine[0])
{
?。?LastState) |= 1 《 (Start + n);
TGTCounter ++;
}
}
#endif
}
return TGTCounter;
}
很顯然,通過調(diào)節(jié)兩條線之間的距離就可以控制算法的靈敏度,一種極限的情況,當(dāng)該值為0時就是前面提到過的那種簡單算法了。
》技術(shù)點 B 動態(tài)預(yù)值
當(dāng)然,這種算法在簡單的機(jī)器人循線中不是很常用。比較常見,適應(yīng)性強(qiáng)的方法是,首先從AD值中找到一個中間值作為MarkLine,然后從MarkLine稍小的值開始向上或向下搜索,(或者可以從AD值中找那些比較接近值和值之差的0.618倍的數(shù)值),然后再標(biāo)記,尋找一個合理的值,比方說恰好在這種狀態(tài)下找到的白線數(shù)量少于4個。這樣的算法叫做動態(tài)預(yù)值。
/***********************************************************
* 函數(shù)說明:傳感結(jié)果處理函數(shù) *
***********************************************************/
char IRSBproccessAdsValue(char TempLineState)
{
unsigned int MaxValue = 0;
unsigned int MinValue = 0xffff;
unsigned int TempValue = 0;
char n = 0;
if (!IfGetAllSensorADCValue) //采樣是否完成
{
return TempLineState;
}
for (n = 0;n<IRSB_SENSOR_COUNT;n++) //獲取采樣跨度
{
TempValue = IRSB_SENSOR(n);
if (MaxValue < TempValue)
{
MaxValue = TempValue;
}
if (MinValue > TempValue)
{
MinValue = TempValue;
}
}
if (MaxValue - MinValue > 200) //開始動態(tài)設(shè)定閥值
{
if (((MaxValue + MinValue) 》 1) > (IRSB_SENSOR_SENSITIVITY 》 1))
{
TempValue = ((MaxValue + MinValue) 》 1) - (IRSB_SENSOR_SENSITIVITY 》 1);
}
else
{
TempValue = 0;
}
while(TempValue < 650) //測試循環(huán)體
{
IRSBJudgeLine[0] = TempValue;
IRSBJudgeLine[1] = TempValue + IRSB_SENSOR_SENSITIVITY;
if (IRSBgetLineState(&TempLineState) < 4)
{
break;
}
TempValue += 20;
}
}
else
{
#ifndef IRSB_SENSOR_BLACK_LINE
if (MaxValue > 700) //上限
{
TempLineState = 0xff;
}
else
{
TempLineState = 0x00;
}
#else
if (MaxValue > 700) //上限
{
TempLineState = 0x00;
}
else
{
TempLineState = 0xff;
}
#endif
}
IfGetAllSensorADCValue = False; //設(shè)定操作標(biāo)志位False
return TempLineState;
}
2 數(shù)據(jù)的簡單加工——個循線程序
到目前為止,我們已經(jīng)把AD的值的數(shù)組轉(zhuǎn)變?yōu)榱艘粋€表示白線位置的二進(jìn)制位的數(shù)組——我們不妨直接把他用一個字節(jié)表示哈。那么,這個字節(jié)的狀態(tài)就表示了當(dāng)前白線的位置信息。再假設(shè),我們已經(jīng)寫好了幾個函數(shù)用來分別控制小車的左右運動。那么我們就可以通過以下的簡單方式來實現(xiàn)循線了。
//用字節(jié)的高三位表示三個管子檢測到的白線信息。
switch (LineInforByte)
{
case 0b11100000: //全部在白線上
Motor_Left_GoFront(FullSpeed);
Motor_Right_GoFront(FullSpeed);
break;
case 0b01100000: //明顯車子向左偏了哈
Motor_Left_GoFront(FullSpeed);
Motor_Right_GoFront(NormalSpeed);
break;
case 0b00100000:
Motor_Left_GoFront(FullSpeed);
Motor_Right_GoFront(LowSpeed);
break;
……
//其他情況仿照上面自己寫了哈。
default:
Motor_Left_GoFront(StopNow);
Motor_Right_GoFront(StopNow);
break
}
呵呵,這樣就完成了一個循線小車的程序了哈。簡單吧。
順便說明一下下,Motor_Left_GoFront()函數(shù)是一個控制電機(jī)PWM輸出的函數(shù)。
FullSpeed NormalSpeed LowSpeed StopNow StopFree 是一些控制PWM的宏定義,你可以修改這些宏定義的值來實現(xiàn)以上的功能。我想,你看了這個程序應(yīng)該已經(jīng)對循線的基本原理了然于胸了吧。哈哈哈哈哈哈哈哈。
3 數(shù)據(jù)的加工——復(fù)雜地面情況的模糊識別算法
以上的算法的確可以應(yīng)付規(guī)范場地下的情況了,但是由于其類似查表式的數(shù)據(jù)處理方式,一旦出現(xiàn)真值表中沒有的情況——哪怕是很明顯的直線存在——機(jī)器人都沒有辦法處理了。典型的就是在地上有大塊的白色斑點,導(dǎo)致機(jī)器人對白線視而不見。
解決以上問題的方法還要從人眼識別白線的原理上說起。在破壞嚴(yán)重的場地上,人類的眼睛仍然可以識別出原先的白線,這是為什么呢?通過重心。人類的眼睛通過捕捉白線的重心確立白線的大體軌跡,從而辨認(rèn)出白線的位置。從概率的角度上說,在破壞嚴(yán)重的場地上,出現(xiàn)在白線兩邊的淺色干擾的概率是一樣的,即使不同,由于白線本身的存在,其重心至少是不會偏離白線很遠(yuǎn)的,所以,只要簡單的獲得地面淺色標(biāo)志的重心,就可以大體確立白線的所在。我們可以利用物理學(xué)上質(zhì)心的算法獲得這一信息。忘了說一點,要想機(jī)器人增強(qiáng)對環(huán)境的適應(yīng)力,就需要增加傳感器的數(shù)目。我們不妨用8個紅外管作為傳感器。這樣通過處理后獲得的場地信息就整整1個字節(jié)了。假設(shè)1個光電管的1擁有1單位的重量,八個光電管的坐標(biāo)分別為 -7 -5 -3 -1 1 3 5 7,其間距都是2個單位,通過置信公式很容易計算出質(zhì)心的坐標(biāo),通過這個坐標(biāo)和0的,就可以知道當(dāng)前機(jī)器人偏離白線的多少,而這個偏離值則可以通過簡單的比例直接指導(dǎo)運動函數(shù)。典型實例如下:
/********************************************************
* 函數(shù)說明:電機(jī)動作調(diào)速函數(shù) *
* 說明: 該函數(shù)放在定時器或者主循環(huán)里面用于產(chǎn)生軟PWM*
********************************************************/
void SpeedPWM(char PWMLine)
{
char PWMLine_L = PWMLine;
char PWMLine_R = PWMLine;
static char PWMCount_L = 0;
static char PWMCount_R = 0;
char Temp = 0;
if (FollowLineEnable == True)
{
Temp = (char)fabs((float)CG_X);
if (AdcValueFlag == 0)
{
Temp = 0;
}
else
{
if (CG_X <0)
{
if ((Temp《4) <= PWMLine_R)
{
PWMLine_R -= ((Temp《5)+Temp《2);
}
else
{
PWMLine_R = 0;
}
}
else
{
if ((Temp《4) <= PWMLine_L)
{
PWMLine_L -= (Temp《5);
}
else
{
PWMLine_L = 0;
}
}
}
}
PWMCount_L ++;
PWMCount_R ++;
if (PWMCount_L > Fastest)
{
PWMCount_L = Stop;
}
if (PWMCount_R > Fastest)
{
PWMCount_R = Stop;
}
if (PWMCount_L < PWMLine_L)
{
switch (GoDirection)
{
case Front:
Motor_Left_GoFront;
break;
case Back:
Motor_Left_GoBack;
break;
case Left:
Motor_Left_GoFront;
break;
case Right:
Motor_Left_GoBack;
break;
case Stop:
Motor_Left_Stop_Free;
break;
}
}
else
{
Motor_Left_Stop_Free;
}
if (PWMCount_R < PWMLine_R)
{
switch (GoDirection)
{
case Front:
Motor_Right_GoFront;
break;
case Back:
Motor_Right_GoBack;
break;
case Left:
Motor_Right_GoBack;
break;
case Right:
Motor_Right_GoFront;
break;
case Stop:
Motor_Right_Stop_Free;
break;
}
}
else
{
Motor_Right_Stop_Free;
}
}
/********************************************************
* 函數(shù)說明:獲取偏離軌跡線的數(shù)值 *
* 輸入: 表明尋線狀態(tài)的字節(jié) *
* [說明] *
* 通過類質(zhì)心算法獲取當(dāng)前機(jī)器人偏離軌跡線的量 *
* - 表示偏左 + 表示偏右 *
********************************************************/
signed char GetCG_X(unsigned char AdcValues)
{
signed char a = 0;
signed char Temp = 0;
signed char Totals = 0;
for (a = 0;a<8;a++)
{
if ((AdcValues 《a)》7)
{
Temp += ((-7)+ (a《1));
Totals++;
}
}
if (Totals ==0)
{
return 0;
}
return (Temp / Totals);
}
函數(shù)調(diào)用GetCG_X函數(shù),用來獲取CG_X,CG_X直接在PWM輸出函數(shù)里面指導(dǎo)機(jī)器人的運動。
以上方法的好處是,提供了一個比例調(diào)節(jié)循線動作的可能。支持多傳感器的情況,尤其適合線性CCD類的線性數(shù)據(jù)的處理。為機(jī)器人提供了一個相對完整的視覺,不可能出現(xiàn)無法識別的情況,而且,這種情況可以使機(jī)器人在不加修改程序的情況下直接在在白線循線和黑線循線狀態(tài)下切換。
4 循線位置閉環(huán)控制中的PD算法
從前文,我們已經(jīng)初步掌握了獲取機(jī)器人位置信息的方法,并且通過質(zhì)心公式擁有了利用簡單的P調(diào)解來指導(dǎo)機(jī)器人運動的可能——不知不覺間,我們已經(jīng)進(jìn)入了控制學(xué)中關(guān)于位置環(huán)的閉環(huán)控制的問題了。
我們通過傳感器獲得白線的位置信息,并且通過計算獲得了白線的質(zhì)心距離車體中心的偏移量??刂栖圀w中心位于白線的質(zhì)心——這就是循線中位置環(huán)所要控制的東西。
首先,我們來說說如果不用PD算法,我們會如何控制這一位置環(huán)。我們可以簡單的利用如果質(zhì)心偏左就向左邊全速運動,質(zhì)心偏右就向右邊全速運動來實現(xiàn)。這樣的確可以完成循線的操作,但是效果顯而易見,車子就像喝醉了酒一樣,走著蛇形的路線。如果我們通過偏移量的多少乘上一個比例K來指導(dǎo)向左或者向右運動的幅度,那么我們的s形運動的幅度就會越來越小,終到達(dá)水平運動。
這就是P算法。在P算法中k值的確立非常關(guān)鍵,如果K值過大,仍然會出現(xiàn)明顯的S形運動——這個被稱為超調(diào);如果K值過小,那么就不能有效地指導(dǎo)循線,機(jī)器人就像對白線沒有反應(yīng)一樣,很容易就超出了合理的運動范圍;如果K值不合適,那么至少也會導(dǎo)致機(jī)器人不能以快的速度到達(dá)位置環(huán)的平衡位置甚至是震蕩。如何獲得一個合適的K值理論上是可以通過計算獲得的,但往往經(jīng)驗值和測試得來的數(shù)值會比較有效。
當(dāng)使用P算法時,到達(dá)平衡位置中心后由于場地的原因,機(jī)器人出現(xiàn)頻繁的調(diào)節(jié)位置的動作,就會大大限制住機(jī)器人移動的平均速度。這個時候,就需要一個和回復(fù)位置環(huán)速度有關(guān)系的量,這個就是我們通常稱之為D的量,通常這個也稱之為和動量有關(guān)的修正量——大家可以查閱相關(guān)的書籍獲得D調(diào)節(jié)的詳細(xì)內(nèi)容。一般情況下,循線中僅僅是P調(diào)節(jié)就已經(jīng)足夠了滿足一般要求了。
版權(quán)與免責(zé)聲明
凡本網(wǎng)注明“出處:維庫電子市場網(wǎng)”的所有作品,版權(quán)均屬于維庫電子市場網(wǎng),轉(zhuǎn)載請必須注明維庫電子市場網(wǎng),http://m.58mhw.cn,違反者本網(wǎng)將追究相關(guān)法律責(zé)任。
本網(wǎng)轉(zhuǎn)載并注明自其它出處的作品,目的在于傳遞更多信息,并不代表本網(wǎng)贊同其觀點或證實其內(nèi)容的真實性,不承擔(dān)此類作品侵權(quán)行為的直接責(zé)任及連帶責(zé)任。其他媒體、網(wǎng)站或個人從本網(wǎng)轉(zhuǎn)載時,必須保留本網(wǎng)注明的作品出處,并自負(fù)版權(quán)等法律責(zé)任。
如涉及作品內(nèi)容、版權(quán)等問題,請在作品發(fā)表之日起一周內(nèi)與本網(wǎng)聯(lián)系,否則視為放棄相關(guān)權(quán)利。
- 掌握 DSP:原理剖析與應(yīng)用實踐2025/5/8 14:03:24
- 模糊邏輯在 DSP 上實時執(zhí)行2023/7/25 17:13:30
- 多速率DSP及其在數(shù)模轉(zhuǎn)換中的應(yīng)用2023/6/12 15:28:52
- 使用 DSP 加速 CORDIC 算法2023/3/29 15:46:30
- 高速DSP系統(tǒng)的信號完整性2022/9/26 16:45:38









