• MPC入门与Matlab实现


    本文为B站视频《你还在用PID?MPC模型预测控制,从公式到代码!》的学习笔记,强烈推荐去看这位大佬的视频,链接放在了最后,别忘了给大佬一键三连哈


    前言

       模型预测控制(MPC)是一类特殊的控制。它的当前控制动作是在每一个采样瞬间通过求解一个有限时域开环最优控制问题而获得。过程的当前状态作为最优控制问题的初始状态,解得的最优控制序列只实施第一个控制作用。这是它与那些使用预先计算控制律的算法的最大不同。本质上模型预测控制求解一个开环最优控制问题。它的思想与具体的模型无关,但是实现则与模型有关。 (百度百科)模型预测控制的结构图如下(来源论文[1]):
    在这里插入图片描述
      因此,模型预测控制一共包括了以下四个部分:模型,预测,滚动优化以及误差补偿。
      模型顾名思义指的是被控系统的模型,预测指的是根据系统输出以及当前状态预测之后的状态,优化指使用常见的优化方法找到满足约束条件的最优值,之所称为滚动优化,是因为每run一步,需要将下一时刻的预测值作为当前时刻的预测值,依次类推,就好比“滚动一样”。误差补偿是因为系统是存在静态误差的,即当进入下一步时会发现,预测值并不等于下一次的实际值,这是就需要对这个误差进行补偿。下面详细介绍各个部分的含义。
    首先需要定义两个变量:
    P:预测步长,即每次要预测多少步, y ( k + 1 ) , y ( k + 2 ) , . . . , y ( k + P − 1 ) y(k+1),y(k+2),...,y(k+P-1) y(k+1),y(k+2),...,y(k+P1)
    M:控制步长,即之后M步的控制量, Δ u ( k ) , Δ u ( k + 1 ) , . . . , Δ u ( k + M − 1 ) \Delta{u}(k),\Delta{u}(k+1),...,\Delta{u}(k+M-1) Δu(k),Δu(k+1),...,Δu(k+M1)

    1. 模型

      参考视频的内容,这里也以线性系统为例,即一个单位阶跃响应:
    来源于论文[1]
      根据叠加原理我们可以得到k时刻的系统可以表示为(论文[1]):
    y ( k ) = ∑ i = 1 P − 1 a i Δ u ( k − i ) + a p Δ u ( k − p ) ( j = 1 , 2 , ⋯   , n )

    y(k)=i=1P1aiΔu(ki)+apΔu(kp)(j=1,2,,n)" role="presentation" style="position: relative;">y(k)=i=1P1aiΔu(ki)+apΔu(kp)(j=1,2,,n)
    y(k)=i=1P1aiΔu(ki)+apΔu(kp)(j=1,2,,n)
    用matlab程序表示如下:

    %1.1获取阶跃响应模型
    [stepresponse,t]=step(sys1,ts:ts:(P)*ts);
    %1.2创建动态矩阵A,矩阵大小为P*M
    A(:,1)=stepresponse(1:P);
    for i=1:P
        for j=2:M
            if i>=j
                A(i,j)=A(i-1,j-1);
            end
        end
    end
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    2. 预测

      之后的P步预测估计可以写成(论文[1]):
    y ^ ( k + j ) = ∑ i = 1 P − 1 a i Δ u ( k + j − i ) + a p Δ u ( k + j − p ) ( j = \hat{y}(k+j)=\sum_{i=1}^{P-1} a_{i} \Delta u(k+j-i)+a_{p} \Delta u(k+j-p)(j= y^(k+j)=i=1P1aiΔu(k+ji)+apΔu(k+jp)(j=
    1 , 2 , ⋯   , n ) 1,2, \cdots, n) 1,2,,n)
      为了方便计算,写成矩阵的形式如下(论文[1]):
    [ y ^ ( k + 1 ) y ^ ( k + 2 ) ⋮ y ^ ( k + n ) ] = [ a 1 0 a 2 a 1 ⋮ ⋱ a n a n − 1 ⋯ a 1 ] [ Δ u ( k ) Δ u ( k + 1 ) ⋮ Δ u ( k + m − 1 ) ] + {\left[

    y^(k+1)y^(k+2)y^(k+n)" role="presentation" style="position: relative;">y^(k+1)y^(k+2)y^(k+n)
    \right]=\left[
    a10a2a1anan1a1" role="presentation" style="position: relative;">a10a2a1anan1a1
    \right]\left[
    Δu(k)Δu(k+1)Δu(k+m1)" role="presentation" style="position: relative;">Δu(k)Δu(k+1)Δu(k+m1)
    \right]+} y^(k+1)y^(k+2)y^(k+n) = a1a2ana1an10a1 Δu(k)Δu(k+1)Δu(k+m1) +
    [ y 0 ( k + 1 ) y 0 ( k + 2 ) ⋮ y 0 ( k + n ) ] {\left[
    y0(k+1)y0(k+2)y0(k+n)" role="presentation" style="position: relative;">y0(k+1)y0(k+2)y0(k+n)
    \right] }
    y0(k+1)y0(k+2)y0(k+n)

    进而可以写成:
    Y ^ 0 = A ⋅ Δ u + Y 0
    Y^0=AΔu+Y0" role="presentation" style="position: relative;">Y^0=AΔu+Y0
    Y^0=AΔu+Y0

    即:新的预测输出=控制变化量+原预测输出
    matlab:

    %计算增量化控制
    Y0 = Y0 + A * DU;
    
    • 1
    • 2

    3. 滚动优化

    参考轨迹

    首先需要确定参考轨迹(期望)
    使用一阶低通滤波得到期望的轨迹为:
    w ( k + i ) = α i y ( k ) + ( 1 − α i ) y t a r g e t w(k+i)=\alpha^iy(k)+(1-\alpha^i)y_{target} w(k+i)=αiy(k)+(1αi)ytarget
    α \alpha α越大,预测的轨迹月缓慢。
    用matlab程序表示如下:

    %参考轨迹
    for i=1:P
        W(i,1) = alpha^i * y(k) + (1 - alpha^i) * target;
    end
    
    • 1
    • 2
    • 3
    • 4

    优化目标

    这里使用二次规划,matlab可以使用quadprog()函数求解,也可以通过对目标函数求导等于0得到最优值。

    目标一:离目标越近越好
    J 1 = ∑ i = 1 P − 1 [ y ( k + i ) − w ( k + i ) ] 2

    J1=i=1P1[y(k+i)w(k+i)]2" role="presentation" style="position: relative;">J1=i=1P1[y(k+i)w(k+i)]2
    J1=i=1P1[y(k+i)w(k+i)]2
    目标二:能量越小越好(耗费能量直接与控制量u相关,因此要最小化控制量u)
    J 2 = ∑ j = 1 M − 1 [ Δ u ( k + j − 1 ) ] 2
    J2=j=1M1[Δu(k+j1)]2" role="presentation" style="position: relative;">J2=j=1M1[Δu(k+j1)]2
    J2=j=1M1[Δu(k+j1)]2

    所以优化的目标函数可以写成:
    J = ∑ i = 1 P − 1 [ y ( k + i ) − w ( k + i ) ] 2 ⋅ q + ∑ j = 1 M − 1 [ Δ u ( k + j − 1 ) ] 2 ⋅ r
    J=i=1P1[y(k+i)w(k+i)]2q+j=1M1[Δu(k+j1)]2r" role="presentation" style="position: relative;">J=i=1P1[y(k+i)w(k+i)]2q+j=1M1[Δu(k+j1)]2r
    J=i=1P1[y(k+i)w(k+i)]2q+j=1M1[Δu(k+j1)]2r

    其中q和r为对应的权重系数,如果更关注与到达目标点就让q大一点,如果关注与节能,就让r大一点。
    表示成二次规划的形式为:
    J = ( Y − W ) T ⋅ Q ⋅ ( Y − W ) + Δ U T ⋅ R ⋅ Δ U
    J=(YW)TQ(YW)+ΔUTRΔU" role="presentation" style="position: relative;">J=(YW)TQ(YW)+ΔUTRΔU
    J=(YW)TQ(YW)+ΔUTRΔU

    根据 Δ J Δ U = 0 \frac{\Delta{J}}{\Delta{U}}=0 ΔUΔJ=0可得:
    Δ U = ( A T Q A + R ) − 1 ⋅ A T ⋅ ( W − Y 0 )

    ΔU=(ATQA+R)1AT(WY0)" role="presentation" style="position: relative;">ΔU=(ATQA+R)1AT(WY0)
    ΔU=(ATQA+R)1AT(WY0)
    Δ U = [ Δ u ( k ) Δ u ( k + 2 ) ⋮ Δ u ( k + m − 1 ) ] \Delta{U}=\left[
    Δu(k)Δu(k+2)Δu(k+m1)" role="presentation" style="position: relative;">Δu(k)Δu(k+2)Δu(k+m1)
    \right]
    ΔU= Δu(k)Δu(k+2)Δu(k+m1)
    ,选取第一行 Δ u ( k ) \Delta{u}(k) Δu(k)作为系统的输入。
    matlab:

    %求解最优值
    DU = (A'*Q*A+R)^-1*A'*Q*(W-Y0);
    u(k) = u(k-1) + DU(1,1);
    
    • 1
    • 2
    • 3

    4. 误差补偿

      在k时刻,我们预测到了P个输出: y ( k + 1 ) , y ( k + 2 ) , . . . , y ( k + P − 1 ) y(k+1),y(k+2),...,y(k+P-1) y(k+1),y(k+2),...,y(k+P1)
    假设现在位于k+1时刻,则预测的误差可以表示为:
    e ( k + 1 ) = y ( k + 1 ) − y ^ ( k + 1 ) e(k+1)=y(k+1)-\hat{y}(k+1) e(k+1)=y(k+1)y^(k+1)
    由于在k+1时刻实际的测量值仅为该时刻的值,而后面时间序列的测量值无法测得,因此需要引入加权的方法来预测未来误差,以此补偿模型预测出现的误差,可以得到校正后的预测向量:
    y c o r ( k + 1 ) = y ^ p ( k + 1 ) + H e ( k + 1 ) \boldsymbol{y}_{c o r}(k+1)=\hat{\boldsymbol{y}}_{p}(k+1)+\boldsymbol{H} \boldsymbol{e}(k+1) ycor(k+1)=y^p(k+1)+He(k+1)
    其中 H 为误差校正矩阵:
    H = [ h ( 1 ) h ( 2 ) ⋮ h ( p ) ] H={\left[

    h(1)h(2)h(p)" role="presentation" style="position: relative;">h(1)h(2)h(p)
    \right] } H= h(1)h(2)h(p)
      在k+1时刻,由于时间基点的变动,预测的未来时间点移到k+2,…,k+p+1。初始预测值也相应移位,其初始预测值:
    Y ^ 0 ( k + 1 ) = S ⋅ Y ^ c o r ( k + 1 ) \hat{Y}_0(k+1)=S\cdot\hat{Y}_{cor}(k+1) Y^0(k+1)=SY^cor(k+1)
    其中S为移位矩阵:
    S = [ 0 1 ⋯ 0 0 ⋱ ⋱ ⋮ ⋮ ⋱ 0 1 0 ⋯ 0 1 ] \boldsymbol{S}=\left[
    010001001" role="presentation" style="position: relative;">010001001
    \right]
    S= 000100011

    matlab:

    %误差补偿,修正轨迹
    Y_cor = Y0 + H * (y(k) - Y0(1,1));
    %移位
    Y0 = S * Y_cor;
    
    • 1
    • 2
    • 3
    • 4

    matlab实现

    最后附上作者的完整matlab程序(若有侵权,请联系删除):

    clc;clear;
    %%
    %创建系统,初始化部分参数
    steps=100; % 仿真步数
    ts=0.01; % 采样周期
    ad = [1.00027180509492,0.00625101658363726,-0.000298104527325984,-0.000592137149727941,-0.000195218555764740;-0.00625101658365004,0.879670596217866,0.0123995907573806,0.00942892684037583,-0.00775386215642799;-0.000298104527325549,-0.0123995907573839,0.999169855139624,-0.0148759276100900,0.000129671924415677;0.000592137149728420,0.00942892684037156,0.0148759276100894,0.998913472148301,0.0286900249744246;-0.000195218555764543,0.00775386215643324,0.000129671924425366,-0.0286900249744255,0.999703452784522];
    bd = [-0.023307871208778;-0.314731276263951;-0.008803109981206;0.016810972019614;0.005019051193557];
    cs = [0.023307871208772,-0.314731276263952,0.008803109981209,0.016810972019614,-0.005019051193548];
    ds = 0;
    sys1 = ss(ad,bd,cs,ds,ts);
    xs0=[0,0,0,0,0]';
    
    %%
    %MPC关键参数
    P = 10;%预测步长
    M = 5;%控制步长
    q = 1;%Q矩阵权重
    r = 10;%R矩阵权重
    h = 0.5;%H矩阵权重
    alpha = 0.2;%期望轨迹的平滑度(范围为0~1),越小,响应越快
    target = 1;%目标值
    %矩阵初始化
    A=zeros(P,M);%动态矩阵
    Q=eye(P,P)*q;%Q矩阵
    R=eye(M,M)*r;%R矩阵
    H=ones(P,1)*h;%H矩阵
    S=zeros(P,M);%移位矩阵
    DU=zeros(M,1);
        for i=1:P-1
            S(i,i+1)=1;
        end
        S(P,P)=1;
    W=zeros(P,1);%期望轨迹
    Y0=zeros(P,1);%预测输出轨迹
    Y_cor=zeros(P,1);%预测输出轨迹修正值
    %% 1.模型
    %1.1获取阶跃响应模型
    [stepresponse,t]=step(sys1,ts:ts:(P)*ts);
    %1.2创建动态矩阵A,矩阵大小为P*M
    A(:,1)=stepresponse(1:P);
    for i=1:P
        for j=2:M
            if i>=j
                A(i,j)=A(i-1,j-1);
            end
        end
    end
    
    %% 2.预测
    xs1=ad*xs0;
    y(1)=cs*xs0;
    u(1) = 0;
    for k=2:3*steps
        xs1=ad*xs0+bd*u(k-1);
        y(k)=cs*xs0+ds*u(k-1);
        xs0=xs1;
        
        
        if k < steps
            target = 1;
        elseif (k-steps)*Q*A+R)^-1*A'*Q*(W-Y0);
        u(k) = u(k-1) + DU(1,1);
                %使用quadprog()的办法
                %Z1 = A'*Q*A+R;
                %Z2 = A'*Q*(-W);
                %[x,fval,exitflag,output,lambda] = quadprog(Z1,Z2);
                %u(k)=u(k-1)+x(1,1);  
    end
    
    %%
    % 绘制图形
    figure(1);
    subplot(211);
    plot(y,'linewidth',2);
    hold on;plot(ref,'linewidth',2);
    title('系统输出');
    xlabel('t');
    ylabel('y');
    ylim([-1.5 1.5])
    
    grid on;
    subplot(212);
    plot(u,'linewidth',2);
    title('控制输入');
    xlabel('t');
    ylabel('u');
    grid on;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105

    参考:
    [1]仝小龙,张立广,王娜丹.模型预测控制在纯滞后对象中的研究[J].电子测量技术,2018,41(23):12-17.DOI:10.19651/j.cnki.emt.1801892.
    [2] 你还在用PID?MPC模型预测控制,从公式到代码!

  • 相关阅读:
    Siamese Neural Network (SNN: 孪生神经网络)
    ExoPlayer架构详解与源码分析(8)——Loader
    FISCOBCOS 控制台全部命令
    电子企业MES管理系统实施的功能和流程有哪些
    网络学习(十) | 深入学习HTTPS与安全传输
    windows上安装和启动Elasticseach
    目标检测算法改进系列之Backbone替换为EfficientFormerV2
    Java 热更新 Groovy 实践及踩坑指南
    【JavaWeb】JSP系列——EL表达式
    第十章 时序与延迟
  • 原文地址:https://blog.csdn.net/qq_46304090/article/details/126572639