模型预测控制MPC(单输入单输出例子)

模型预测控制MPC(单输入单输出例子)

作为初学者,这篇主要记录自己学习MPC,并用python简单实现个单输入单输出的例子。
有什么不对的地方欢迎留言讨论。

模型预测控制

这一节不会讲模型预测控制的公式推导,都是默认理解模型预测控制理论的。

单输入单输出模型

单输入单输出的系统结构图如下图所示:
单输入单输出系统结构图
其中,
r ( t ) r(t) r(t)是给定值;
e ( t ) e(t) e(t)是误差,其公式为: e = r ( t ) − y ( t ) e=r(t)-y(t) e=r(t)y(t),这个误差也是系统的状态;
u ( t ) u(t) u(t)是系统的输入。

我们假设动态系统的行为由下面的微分方程所描述:
x ˙ ( t ) = a x ( t ) + b u ( t ) \dot{x}(t)=ax(t)+bu(t) x˙(t)=ax(t)+bu(t)
其中,
x ( t ) x(t) x(t)是系统状态;
u ( t ) u(t) u(t)是控制输入;
a a a b b b是系统的常数。
代价函数可以写成如下:
J = ∫ 0 T q e t 2 + p u t 2 d t J=\int^{T}_{0}qe^2_t+pu^2_t{dt} J=0Tqet2+put2dt
其中,
q q q p p p是权重因子,分别平衡状态和控制输入的成本;
T T T是终端时间。
因为计算机无法处理连续的函数,所以我们需要将积分写成累加形式:
x k + 1 = a x k + b u k x_{k+1}=ax_k+bu_k xk+1=axk+buk
J = ∑ k N − 1 [ q e k 2 + p u k 2 ] + h e N 2 J=\sum_{k}^{N-1}[qe_k^2+pu_k^2]+he^2_{N} J=kN1[qek2+puk2]+heN2
其中, N N N是预测的步数, h h h是终端状态的权重。

代码实现

导入的库函数

import casadi as ca
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
from matplotlib.offsetbox import OffsetImage, AnnotationBbox
import matplotlib.patches as patches
from matplotlib.ticker import MultipleLocator

建立模型

下面的函数是用于画图:

def draw(y_nums, y_ref, x_min=0, x_max=100, x_num=100):
    # 8 * 6 英寸的画布大小,每英寸有 80 个点
    fig  = plt.figure(figsize=(8,6), dpi=80)
    y1 = np.full(x_num, y_ref)
    # 设置一维坐标系
    ## 获取当前的轴对象
    ax = plt.gca()
    ## 设置x、y轴的上下限
    ax.set_xlim(-5, x_max+int(x_max/10))
    #ax.set_ylim(-8, 8)
    ## 框的上、右、左设置无颜色
    # ax.spines['right'].set_color('none')
    # ax.spines['top'].set_color('none')
    # ## 框的下原点坐标。这样就成一维坐标系
    # ax.xaxis.set_ticks_position('bottom')
    # ax.spines['bottom'].set_position(('data',0))
    # ax.yaxis.set_ticks_position('left')
    # ax.spines['left'].set_position(('data',0))
    # ## 隐藏y轴刻度
    # ax.yaxis.set_visible(False) 
    x = np.linspace(x_min, x_max, x_num, endpoint=True)    
    plt.plot(x, y_nums, color="blue", linewidth=2.0, linestyle="-")
    plt.plot(x, y1, color='red', linestyle='-', linewidth=1)
    #plt.plot(ax, x_ref, color="green", linewidth=1.0, linestyle="-")

    plt.show()    

下面的函数就是单输入单输出的建模:

def MPC_SISO():
    '''
    x_next = a * x(now) + b * u(now)
    偏差: e = x(now) - x(ref)
    预测步数: N
    J(N) = J(0) + J(1) + ... + J(N-1)
    J(0) = 0
    J(1) = J(0) + q * (e**2) + p * (u**2)
    .
    .
    .
    J(N-1) = J(N-2) + q * (e**2) + p * (u**2)
    J(N) = J(N-1) + q * (e**2) + p * (u**2)
    J = J(N) + h * (e**2)
    最终的

    假设起点到终点有 100 步,每一步都要做模型预测控制计算,每一步计算出来只取第一个数据
    '''
    # 定义系统系数 a、b
    a = 1
    b = 1
    # 定义系统最终状态 x_ref
    x_ref = 1
    # 定义预测区间 N
    N = 5
    # 定义系统的状态和输入,状态要比输入多一个
    X = ca.SX.sym("X", N+1)
    U = ca.SX.sym("U", N)
    # 定义 q(状态比重)、r(输入比重)
    q = 0.01
    p = 0.9
    h = 0.01
    # 定义初始状态 X_0
    X_0 = ca.SX.sym("X_0")
    # 定义约束,也是我认为的偏差,这是一个集合,表示预测的每一个点的偏差
    constraints = []
    constraints.append(X[0]-X_0)

    # 定义和计算 代价函数 
    J = 0
    for k in range(N):
        e = X[k] - x_ref
        J = J + q * (e**2) + p * (U[k]**2)
        x_next = a * X[k] + b * U[k]
        constraints.append(x_next - X[k+1])
    J = J + h * ((X[N] - x_ref)**2)

    # 以上步骤就完成了数学建模,接下来是求解最优
    # 创建NLP求解器
    ## 'x' 是代价函数里面需要求解的参数;'f' 是代价函数;'g' 是约束函数;'p' 是定义的初始值
    nlp = {'x': ca.vertcat(X, U), 'f': J, 'g': ca.vertcat(*constraints), 'p':X_0}
    solver = ca.nlpsol('solver', 'ipopt', nlp)
    # 初始猜测和边界
    ## x0 是初始猜测值:初始猜测值为优化求解器提供了一个起点,即从哪里开始搜索解空间。对于非线性问题,不同的起点可能导致求解器收敛到不同的局部最优解。
    ## 系统状态 X 有 N+1 个,输入 U 有 N 个,所以 共有 N+N+1 个初始猜测值
    x0 = np.zeros(N + N + 1)
    ## 约束的下界和上界都设置为0:表示预测的每个点的偏差都为 0
    ## 为什么是 N+1 ? 因为有 N+1 个预测的系统状态
    lbg = np.zeros(N + 1)
    ubg = np.zeros(N + 1)
    ## 变量的上下界设置为 无穷 
    lbx = [-ca.inf] * (N + N + 1)
    ubx = [ca.inf] * (N + N + 1)

    # 定义步数,以及每一步的模型预测控制的数据
    k_step = 100
    X_step = np.zeros((N, k_step), dtype=float)
    init_value = -3.0
    for k_i in range(k_step):
        # 解决NLP
        ## 初始值设置为 -3.0
        sol = solver(x0=x0, lbg=lbg, ubg=ubg, lbx=lbx, ubx=ubx, p=[init_value])
        # 提取解
        optimal_values = sol['x'].full().flatten()
        optimal_states = optimal_values[:N+1]
        optimal_controls = optimal_values[N+1:]

        print("Optimized State Trajectory:\n", optimal_states[1:6])
        print("Optimized Control Inputs:\n", optimal_controls)
        
        init_value = optimal_states[1]
        X_step[:,k_i] = optimal_states[1:6]
    y = X_step[0,:]
    draw(y_nums=y,y_ref = x_ref, x_min=0,x_max=100,x_num=k_step)

调用函数

if __name__ == "__main__":
    MPC_SISO()

输出图片

下图是以上代码所实现的,红色的直线代表设定值,蓝色曲线代表系统的状态走势。可以通过更改 q q q p p p h h h来观察曲线的走势。若 q ≫ p q \gg p qp则该模型控制比较看重系统的状态,曲线比较陡峭;若 p ≫ q p \gg q pq,则相反,曲线比较平滑。
单输入单输出曲线图

总结

以上就是模型预测控制的单输入单输出的例子,可能还存在诸多不足,欢迎各位留言讨论。

  • 12
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
模型预测控制(MPC)是一种先进的控制算法,它能有效地处理输入输出系统。MPC算法基于系统的数学模型,通过预测系统未来的行为来生成控制策略。在输入输出系统中,MPC会对系统的动态特性进行建模,包括系统输入输出和各种约束条件。 MPC算法需要一个系统的数学模型作为输入,这个模型可以是离散时间模型或连续时间模型。然后,MPC算法会预测系统的未来行为,并生成一个优化问题来求解最优的控制策略。在输入输出系统中,MPC算法可以根据系统的数学模型和性能指标来调整控制输入,使系统输出能够在约束条件下实现最优性能。 MPC算法对于输入输出系统的控制具有很多优点。首先,MPC算法可以很容易地处理系统的约束条件,例如输入输出的限制,这使得MPC算法在实际工程应用中很有用。其次,MPC算法可以通过对系统的未来行为进行预测,来减小系统的过渡过程,实现更加平稳的控制效果。此外,MPC算法还可以通过对系统的模型进行更新,来适应系统的实际动态特性,提高了控制的鲁棒性和适应性。 总之,MPC算法输入输出系统的控制中具有很大的应用潜力,它通过对系统动态特性的建模和预测,能够实现更加高效和稳定的控制效果。MPC算法的不断发展和完善,将为输入输出系统的控制带来更多的机遇和挑战。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值