这两天围观了一场比较激烈的讨论(《最优控制理论是什么?》),亲自回答了另一场比较激烈的讨论(《如何看待知名网红摄影师杰克兔在航拍过程中追尾前机导致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):果壳中的王》

推荐阅读:

相关文章