這兩天圍觀了一場比較激烈的討論(《最優控制理論是什麼?》),親自回答了另一場比較激烈的討論(《如何看待知名網紅攝影師傑克兔在航拍過程中追尾前機導致Inspire 2墜崖並不願意賠償?》),頗有些感慨。有關於知乎社區的,有關於我自己求學經歷的,有關於一些陳年往事的。

這些討論中各方互相辯論,言辭難免激烈。撇開辯論的觀點,撇開我的一些感慨,就關於控制理論的那場討論,倒是勾起了我的一些回憶。當年人人網還火的時候,我曾經在人人網上寫過兩篇系列文章《自動化都在幹什麼》,一方面作為我自己求學過程中的總結,一方面也是作為臨畢業的前輩給學弟學妹們一點指引。現在正好搬運過來,比爛在人人網那個墓地要強,也正好求證於大方之家,請知乎上控制理論方面的大牛指導批評。這兩篇文章寫完距今也快 5 年了,回看以前的文章,遣詞造句相比現在更為輕鬆愉快,也是一件趣事。

我沒有開設控制方面話題的專欄,所以這兩篇就單獨發布了。以下開始正文。


1:1 起初神創造天地。

1:2 地是空虛混沌。淵面黑暗。神的靈運行在水面上。

1:3 神說,引入負反饋吧。於是世界穩定了下來。

1:4 神看負反饋是好的,就創造了一門學科,叫自動化。——自動控制理論第一章第一節 · 創世紀 Automation(大霧)

說起來,本學渣在堂堂大洗衣機系讀了快7年了,時常問自己,以及也時常被人問到,自動化都在幹什麼?

自動化都在幹什麼

咳咳,不對不對,我想說什麼來著……啊,控制!既然把「控制論」作為咱大洗衣機系的三大基石之一(其他兩個不記得了這種事情我纔不會亂說呢!)那就先從控制說一說。

說到控制理論,其精髓在於引入反饋(絕大多數情況是負反饋),引入反饋形成閉環系統,相對的,沒有反饋的系統就是開環系統。

但是,為什麼要引入反饋呢?

引入反饋能使系統穩定下來。為什麼引入反饋就能使系統穩定下來呢?不引入反饋就不能使系統穩定了嗎?

是啊,為什麼呢?

本學渣有個優點,問題想不通了就不想了。所以我要拿一個實際的例子來看看,舉個什麼栗子呢?想當年我們舉辦第一屆自動控制大賽,題目就是蹺蹺板,那就看看蹺蹺板吧。啊,說起這個自動控制比賽,我記得當年我們組什麼控制理論什麼零極點配置什麼狀態方程啥都沒用,就用最土的方法直接把誤差信號接入負反饋再加上一個微分控制,然後刷了一個晚上參數,居然也混進決賽圈了……不過學渣到底是學渣,混進決賽圈果然還是墊底。對比人家學霸組那各種眼花繚亂的模塊還有自己寫的模糊控制單元神經網路優化,簡直無地自容。

咳咳,扯遠了。回到蹺蹺板。比如說,我有這麼個蹺蹺板,假設杆子質量可以忽略不計,右邊這個重物是可以沿著杆子滑動的,我想要通過移動右邊的重物來讓這個蹺蹺板回到水平的狀態,可以怎麼做呢?

蹺蹺板

當然第一步還是要建立模型,根據剛體運動學的知識,我們可以寫出下面這個方程

(m_1 L_1^2 + m_2 L_2^2)ddot{	heta} = (m_1 L_1 - m_2 L_2)gcos	heta

唔……等等,這個方程!如果我們設計好了角度隨時間變化的關係(也就是確定了上面隨時間變化的函數關係)那麼每一個時刻的 L2 都是可以算出來的!

L_2 = frac{sqrt{m_2left(-4ddot{	heta}^2 L_1^2 m_1 +      4ddot{	heta}g L_1 m_1 cos	heta +     g^2 m_2 cos^2	heta
ight)} - g m_2 cos	heta}{2ddot{	heta} m_2}

那我們來試試看咯~首先這裡出現了角度的二階導數,那這個函數至少要二階連續,然後作為初始狀態比如我們假設 θ(0)=π/6 也就是 30 度,誒,有了,我們用右半個高斯函數來作為這個軌跡怎麼樣?

	heta(t) = frac{pi}{6} e^{-frac{t^2}{16}}

剩下的再來點實際的數字比如 m1=1,m2=1,L1=1 為了畫圖和演示的方便這裡設g=0.98(比月球的重力加速度還小很多啊……)走一個!

開環控制效果

你看,搞定了!——這麼說起來,根本沒有自動控制什麼事情嘛(吶,這就是個開環系統)~ 只要事先設計好角度的函數,那麼滑塊的位置就能相應地確定了。嘿,這不是拉普拉斯同學的論調嘛!

我們可以把宇宙現在的狀態視為其過去的果以及未來的因。如果一個智能知道某一刻所有自然運動的力和所有自然構成的物件的位置,假如他也能夠對這些數據進行分析,那宇宙裡最大的物體到最小的粒子的運動都會包含在一條簡單公式中。對於這智者來說沒有事物會是含糊的,而未來只會像過去般出現在他面前。 (Laplace, Essai philosophique des probabilités)

不過很可惜,我們的世界到現在也並沒有按照小拉同學設想的來發展,巴西蝴蝶與美洲颶風之間,雖然有著由決定性方程所描述的關係,但畢竟隱藏著名為混沌的妖精。

又扯遠了。不過有了小拉同學的前車之鑒,我們不得不謹慎一點。這裡真的不需要閉環控制嗎?如果我們測量的參數有一點點誤差,如果我們建立的模型有一點點誤差,如果我們控制的滑塊位置有一點點誤差,這個蹺蹺板還能回到水平位置嗎?

比如我們的模型有一點點誤差,我們建模的時候忽略了軸上的摩擦。假如軸上存在一個摩擦力矩呢?

L_f = k_f dot{	heta}

把這個加到模型裏去。

ddot{	heta}(m_1 L_1^2 + m_2 L_2^2) = (m_1 L_1 - m_2 L_2) g cos	heta - k_f dot{	heta}

由於我們計算滑塊位置的時候按照理想的模型(無摩擦),而實際的蹺蹺板是有上面這個摩擦力矩的,那麼蹺蹺板會回到水平位置嗎?

開環控制,有摩擦

完蛋!

如果測量的參數有一點點誤差呢?比如左邊的滑塊位置有 1% 的誤差,我們測量得到 L1=1,但是實際上 L1=1.01,結果會是怎麼樣呢?

開環控制,左側滑塊位置測量不準

完蛋!

如果我們控制的滑塊位置有一點點誤差呢?比如控制的滑塊總比預計的偏左 0.02(約 2% 的誤差),會怎麼樣呢?

開環控制,右側滑塊控制不準

完蛋!

好了,上面玩了三個蛋(咦?),我們看到即使是 1%,2% 這樣小的誤差,帶來的結果也是致命的,與我們預先設計的軌跡大相徑庭。那隻好換一個思路。我不管你這個物理模型是怎麼樣的,我只看結果。角度大了就把滑塊往右推,角度小了就把滑塊往左推——這就是反饋,引入反饋之後系統就閉環了。比如這麼著:

L_2 = 1 + k	heta

這裡 1 就是我們預計的平衡位置,滑塊的相對位置就和角度誤差直接成正比——這就是比例控制,控制量和誤差直接成比例。不過這有個問題,憑經驗我們知道,這樣簡單的策略一般比較不靠譜,很容易來回震蕩,所以我們不僅要看角度,還要看角度的變化。如果角度是正的,但是不斷在變小,那麼我們滑塊就可以不要往右推了,應該要準備往左或者直接就往左了。這角度的變化怎麼衡量呢?就用微分,比如這麼著:

L_2 = 1 + k	heta + k_ddot{	heta}

這就是比例微分控制(PD 控制),這就是工業上最最最最最最……最最最常用的控制器了。 (這裡有誤,經蘇老師指出,工業上最最最最常用的還是 PI 控制,比例積分控制。哎,果然學渣就是學渣,閉門造車不接地氣啊……><)

有效果嗎?我設置 k=0.5,kd=1.2(隨手設的……),看看理想情況下和其他三個蛋的情況下這個蹺蹺板會怎麼樣。

理想情況:

閉環控制效果

第一個蛋,有摩擦:

閉環控制,有摩擦

第二個蛋,左邊滑塊位置有誤差:

閉環控制,左側滑塊位置測量不準

第三個蛋,右邊滑塊控制位置不準:

閉環控制,右側滑塊控制不準

除了第三個蛋玩的不太好,其他都很圓滿地解決了之前的問題。

第三個蛋呢,這種情況,蹺蹺板最終停是停了,不過沒有停在水平位置上,還有一點點差距。這就叫「靜差」,正因為有這個靜差所以才抵消了控制變數的誤差而最終讓系統穩定了下來。為了消除靜差,就需要引入「積分控制」。和前面的比例微分控制 PD 合起來,就是比例積分微分控制 PID(唔以後可以專門寫一篇)

我想,到這裡本學渣終於可以對開頭的問題說一兩句話了。為什麼要閉環控制?因為我們對世界的瞭解是很有限的,對一個系統,我們可能寫不出他的方程來(蹺蹺板是個非常簡單的系統了),就算寫出了方程我們可能也做出了很多的假設和近似,就算沒有假設和近似,那我們對參數的測量,我們對被控物體的控制,這一系列環節都可能出現誤差。更關鍵的一點,這個可愛的世界,大部分系統都是非線性的,非線性系統裏就住著名為混沌的妖精,即使是一點點很小的誤差,也足以讓結果變得面目全非。這當然是很危險的。而引入反饋之後呢,我們從結果出發,隨時調整控制量,這就保證了系統不至於變得面目全非。

寫到這裡,本學渣突然想到了數值分析裡面解微分方程的前向歐拉法和後向歐拉法,前向歐拉法就像是開環系統,數值誤差是積累的,數值穩定性不好;而後向歐拉法就像是閉環系統,數值穩定性就好得多了。異曲同工,妙不可言。

寫完了。

說是寫完了,不過本學渣有個缺點就是愛胡思亂想。我就突然又想啊,如果哪一天我們發展了天頂星科技,對真實世界的建模精確無比,對參數的測量精確無比,對變數的控制也精確無比,那是不是就可以不用閉環控制了呢?我想大概還是要用的。因為開環控制是針對每一個系統「特別定製」的,必須根據具體系統的動態方程來計算,是特異性(Specific)的解決方案,適用範圍小;而閉環控制呢,只要確定比例係數和微分係數,就能搞定一大堆一大堆的系統,是通用(General)的解決方案,適用範圍廣。

哎呀本學渣思維真是停不下來了,突然又想到軟體工程了。軟體工程裡面呢,讓人焦頭爛額的一個詞就是「需求」。一個著名的段子說,讓程序猿發瘋只要改三次需求就行,可見改需求這種事情是多麼的喪盡天良。為什麼呢?因為程序這個東西,現在還沒辦法做得很通用化,一般都是針對每個需求特異化實現的。所以一改需求,往往就要相當於重寫一遍整個項目。為了應付這樣的狀況,很多聰明的大牛們發明瞭各種方法,從早先的設計模式,到單元測試、代碼重構,到控制反轉、依賴注入……其實說白了,就是想從這些千變萬化的模式裡面,找出一些不變的東西,這樣每次改需求的時候就能夠少改動一些代碼——把變化的和不變的部分分離開,這是軟體工程裏最核心的問題了,也是一個資深架構師和本學渣的最大區別所在了。

以不變應萬變,看來古人的智慧總能給人啟迪,路還遠著呢。

下一篇:《章佳傑:自動化都在幹什麼(2):果殼中的王》

推薦閱讀:

相關文章