用ode45做控制系统仿真
本文是reddit r/ControlTheory一篇帖子的总结。这篇帖子以倒立摆为例,介绍如何在MATLAB中用解微分方程的方式做控制系统仿真,并与常规仿真方法做比较。
所用模型是倒立摆在平衡点附近的近似线性模型,这个模型很常见,从代码中也能很容易看出来,所以我就不列出。采用反馈控制方式,将测量输出\(y\)(本例中就是系统的状态,\(y=Cx\),\(C\)矩阵为单位阵)与参考输入\(r\)做比较,得到差值,将差值乘以反馈矩阵\(K\)后,作为倒立摆模型的输入,即 \[ u = K(r-y) \]
控制本质上要求解微分方程,MATLAB解微分方程最常用的是ode45
函数,它求解的微分方程的标准形式为\(y'=f(t,y)\),右边的表达式是时间\(t\)和变量\(y\)的函数。我以前被这个表达式迷惑了,以为它只能求解没有外部输入的非强迫系统(unforced
system)。其实不然,右边的表达式可以非常灵活,能够求解有外部输入信号的控制系统。全部代码如下:
1 | % 倒立摆近似线性模型的参数 |
最后几行代码是倒立摆微分方程模型的描述,将输入信号u
作为model
函数的参数。第18行调用ode45
函数求解微分方程,在这里将输入信号的计算式u = K*(r-y)
传递给model
函数。
MATLAB中对这样的系统做仿真一般用lsim
函数,因为它可以自定义输入信号,还可以包含初始条件。由于该模型是平衡点附近的近似线性模型,控制目标是将系统输出(或系统状态)保持在参考输入\(r\)附近,它不是零点,因此模型变成如下形式:
\[
\dot{x} = A(x-r) + Bu
\]
将\(u = K(r-y)=K(r-Cx)\)代入得: \[ \dot{x} = (A-BKC)x+(BK-A)r \]
本文使用lsim
函数的如下接口:
1 | [y, tOut, x] = lsim(sys, u, t, x0) |
\(r\)即为lsim
的参数u
,\(BK-A\)是模型中与输入信号相乘的\(B\)矩阵。因此,得到如下仿真代码:
1 | % 倒立摆近似线性模型的参数 |
可以验证,用ode45
和lsim
得到的结果完全一样,系统状态随时间变化的曲线如下图所示,达到了控制目标。
对比来看,lsim
是MATLAB中专门用于控制系统仿真的函数,使用更方便,ode45
则更通用,可以做更复杂更灵活的仿真,如事件触发控制(event-triggered
control)。