飛思卡爾智能車之舵機算法

 

恍恍惚惚,將近一年的智能車生涯終於結束了,雖然到目前爲止我們的車子還是比不上學長的神車,但是也還算是對的起我們組一年的辛勤與努力了,爲了給自己慘敗的智能車比賽和還算完整的智能車學習生涯留下點東西。我打算慢慢的把我們做車子的一些感悟等記錄下來,供新手參考,希望新手入門智能車的時候能夠少燒幾塊k60(畢竟那種價格/哭死)。再表達一下我這一年下來對智能車的感悟吧:鐵打的飛思卡爾,流水的參賽隊員/手動滑稽。

這篇文章,我將會從舵機的控制策略來向介紹我的調試經歷,供新手進行參考,儘量詳細的記錄我們調試一步一步變化的過程,坦白的說我們的車子最終跑的不是很好,原因是各個方面的。但是我認爲我們遇到的問題對新手應該還是有些用處的,時間原因,我將會不定期更新,望諒解。(已完結)

 

前言:

想要控制舵機,就需要先了解舵機的工作原理,這一點前輩們的資料相當的豐富,大家可以先行學習一下。

然後因爲我們組做的是光電組,所以就引入一些攝像頭的一些名詞,其他的組別也可以根據這個思路進行舵機調節,不影響學習(僅限賽道組,無賽道組例外)

階段一:

剛剛入手舵機首要目標當然是理解它是如何工作的,控制原理很簡單,這個瞭解了以後我們就開始想辦法讓他工作了。那剛開始該怎麼辦呢?先想一下我現在有什麼呢?攝像頭傳來的中線信息和有效行信息。那第一步就是利用這些數據,怎麼用呢?

自然而然的我們就該想到,如果圖像上面的中線是偏左的,說明我的車子是在中線的右邊,那我就該讓舵機往左邊打角;如果中線是偏右的,說明我的車子是在中線的左邊,那我們就該讓舵機往右邊打角。

那麼問題來了,我怎麼讓單片機根據現在的中線數組知道我的車子是往左還是往右的呢?我們人看到圖像的時候一眼就能夠看到這個中線到底是往左還是往右、、、哎,等等,你怎麼能夠一眼看出來?你是不是經過了某種魔術的計算啊?啊啊啊,我沒有啊,你看這圖不是很明顯中線在圖像的左邊嗎?Emmm有道理,我們讓這個中線數組和圖片最中間的那個數組做差不就得到了嗎?那該選那些行進行計算呢?管他那麼多呢,先選上中間行再說吧。於是我們得到:

Deltax=Center_line[Image_H/2]-Image_L/2;

 

如果deltax>0說明中線在圖像的右側,否則就在左側,那麼打多少呢?當然是直接打到Limit了,肯定不會不夠用。好了知道車子相對於賽道的位置,我們就可以控制舵機向對應的方向打角就好了。那我們不如給這個方法起個名字吧,那不如就叫棒棒算法吧(嗯,這個名字好像有那麼點難聽,但前輩們就是這樣起的啊,我也很絕望啊)。

 

階段二:

拿着棒棒算法弄出來的程序到賽道上面跑一跑,怎麼回事,車子走個直線都走不穩,怎麼一會這邊一會那邊,雖然整體在中間跑的,但是這也太難看了吧。只有一點點偏差舵機就會打角非常的大,怎麼解決呢?當然是讓車子距離中線近的時候讓舵機打角小一點;當車子距離中線遠的時候讓舵機的打角大一點。那麼這個距離中線的遠近是?對,就是上一個階段計算出來的deltax。

if(abs(Deltax)<Image_L/6)
    Control=Limit/3;
else if(abs(Deltax)>=Image_L/6&&abs(Deltax)<=Image_L/3)
        Control=Limit*2/3;
     else
        Control=Limit;

當然啦大家想分多少段多可以了,我在這裏只是拿三段舉個例子。

我們就有了第二個階段的東西,分段式棒棒算法,快整理一下代碼燒進去試試效果。

階段三:

棒棒算法對這個打角分了階段,但是好像又發現了新的問題,當計算得到的deltax處在臨界點附近的時候,舵機的 打角會在一個較大範圍內進行擺動,這樣看到車子的效果就是猛地一下在這邊,然後就又變到了另一邊,好像和第一階段的棒棒算法差別不是很大,那該如何將它變得順滑一點點呢?對,讓對應範圍內的打角變成線性的打角,隨着這個線性係數的增加而逐漸變化的舵機打角值,這個東西其實就是一個純p的pid算法,用代碼表示就是:

 Control=S3010_kp*deltax+Contorl_median;

接下來的問題就是該如何調參數了,終於算是進入到舵機調試的核心部分了,那這個參數該如何進行調試呢?首先是進行計算,我需要算出來這個S3010_kp到底處於一個什麼樣的數量級範圍內怎麼算呢?左右極值的差除以我所要計算的delatx的範圍好像就行;

S3010_kp=(Control_left_limit-Control_right_limit)/deltax_scale;

通過這個公式,我們就可以得到一個最爲基礎的打角kp值然後代入進去,發現效果好像還行,多跑幾圈,感覺還不是很理想,那該怎麼辦呢?我的kp調節是不是還有點問題這樣粗暴的算出一個kp好像不是太合適,那該怎麼調節呢?這個時候就真的沒有什麼辦法了,只能一點一點嘗試,一個參數一個的實驗,最開始的時候每次增加十,直到看到的效果不好,然後一點一點往下面減,直到車子跑起來還算順暢的時候。在這個過程之前,一定要記得加上舵機打角的限幅代碼,要不然我得到的舵機打角過大或者過小而機械結構達不到然後就大概率可以考慮換舵機了/無奈。限幅的方法呢,也很簡單,這樣就可以了

if(Control>Control_left_limit)Control=Control_left_limit;
if(Control<Control_right_limit)Control=Control_right_limit;//Control_left_limit>Control_right_limit

到這,純p調節的舵機打角就算完成了,下一步就是繼續深化了,要求不高的話這樣子得到的kp值也是可以使用的,整體而言看不到太大的問題,如果想要繼續優化,那就要再往下進行調節了。

階段四:

純p調節得到的舵機打角雖然能夠工作,但是如果想要提速,就會參數的問題就會大範圍的暴露出來,速度一高,跑出來的效果還是很差,總能感覺到我們的舵機打角不夠或者太多的問題,我們還是應該對p進行精細化調節,那到底該怎麼精細呢?查表法,怎麼查表呢?我們的每一個deltax都會對應着一個Control值,我們把這個關係列出來,當得到這個deltax的時候查詢一下此時的kp然後算出對應的Control,我們不就得到了相對應的關係。那麼問題來了,我們該如何得到這個表呢?

這個時候,就該進行一些數據測量了,我們需要從賽道上得到幾組數據,怎麼測量呢,讓舵機固定打角,然後推着他走彎道,直到它能夠完美的過來這個彎道,然後記錄此時的舵機打角值和得到的deltax值,再測試不同的彎道得到至少三組數據,正走反走都需要那樣就是至少六組數據得到數據以後該怎麼辦呢?這麼點數據肯定不夠查表,那我們就需要對數據進行一下處理了,最有用的辦法就是對所需要的數據進行一下擬合,一般上擬合成二次函數曲線就可以了,太高次數會更加接近我們所需要的結果,但是因爲數據有限,我們也只能得到這個值。那麼數據擬合該怎麼做呢?當然是強大的MATLAB了,參考代碼如下:

name='6.2.2';
jpg=strcat(name,'.jpg');
txt=strcat(name,'.txt');
x=[59 43 19 51];y=[530 390 255 400];%參考數據,這是一邊的數據
p=polyfit(x,y,3);
x1=1:80;
y1=polyval(p,x1);
h=plot(x,y,'r',x1,y1,'b');
k1=zeros(80,1);
fid=fopen(txt,'w');%將生成的數據寫到txt文件裏面方便複製
for i=1:length(y1)
    k1(i)=y1(i);
    fprintf(fid,'%3.2f,',k1(i));
end
fclose(fid);

這樣我們就得到了一個表,有了這個表,我們再進行查表,舵機的打角就變得更加圓滑了,這個階段的任務也就完成了。

階段五:

做過上面的這些步驟以後,車子已經能夠滿足大多數情況的轉彎打角等,似乎是沒有什麼再改變的空間了,但是在不斷地加速以後,我們還是發現了問題,車子轉彎的時候有點緩慢,容易衝出去,那該怎樣進行調整呢?當車子快到轉彎的地方的時候,我們希望他就提前打角,舵機自身的響應延遲加上此時的高車速,提前打角顯得非常有必要,那該如何提前呢?加大我算出來的值,讓deltax開始變大的時候我們就加上一個微分d進行校正,讓得到的舵機打角更加偏向我所期待的值;當要出彎的時候,我期待車子響應不要那麼快,解決方式也是對這個偏差的差值乘以某個係數加到我們的舵機打角上面。這些,其實就是我們pid調節中的微分調節過程。

Control=Control_median+S3010_kp*deltax+S3010_kd*(deltax_last-deltax_now);

那麼下一個問題就是,這個kd的參數該如何確定呢?首先我們要確定都有哪些因素影響了kd,首先是偏差的差值,這個是我們主要要進行校正的部分,其次是速度,我們的速度不一樣得到的kd值也應該是有那麼一點點差別的,所以主要根據這兩個之間的關係,確定出一個比較好的值。其實如果kp的值能夠調好,kd調節作用不會太明顯,除非你能到達一種超高速。不過車速那麼快,必定老司機。老司機就不用在乎這些了。

至此,我們組在調試舵機的時候所用到的調試方法大致講述完了,希望你看完這篇文章以後能加快調車進程,然後開始爲其他的問題頭疼吧(哈哈哈哈哈哈哈)。

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章