有没有办法告诉GEKKO求解器从非零值开始

问题描述 投票:0回答:1

我正在尝试在 gekko 中实现实时 MPC。这意味着我需要这个模拟无限期地实时运行。类似于do-MPC的实时MPC。一般代码循环是在每个时间步调用求解器,根据当前状态重新评估问题,然后将 m.time 数组移动 1(即,如果它以 [0-20] 开始,则下一个时间步将是 [ 1-21]等)。

当我像这样定义 m.time 数组时,问题就出现了:

m.time = np.linspace(current_time, current_time+prediction_horizon, prediction_horizon+1) current_time += 1

应该会达到预期的效果。相反,求解器给了我这个警告消息:

Warning: shifting time horizon to start at zero Current starting time value:  18.

这意味着现在模拟窗口不会移动。这只是解算器的限制还是我可以改变?

我尝试动态延长时间范围,这有效:

m.time = np.linspace(0, current_time+prediction_horizon, prediction_horizon+1) current_time += 1
这意味着我需要向所有数组附加新值,以便所有求解参数的数组具有相同的长度。然而,这显着减慢了计算时间 60 秒。移动设定的范围可以克服这个问题,但我似乎无法实现它。

如有任何帮助,我们将不胜感激。谢谢。

gekko
1个回答
0
投票

MPC应用时间范围是相对于零开始时间而言的。时间通常不在模型中,因此不需要从非零值开始。 Gekko 自动对先前的解决方案进行时间平移,并接受对任何干扰、设定点、状态变量初始条件和测量反馈的更新,以创建新的 MPC 解决方案。下面是一个演示该方法的简单应用程序

MPC Application

import numpy as np
from gekko import GEKKO
import matplotlib.pyplot as plt
from PIL import Image

# Initialize the GEKKO model
m = GEKKO(remote=False)
m.time = np.linspace(0, 20, 21)  # Time grid
mass = 500
b = m.Param(value=50)
K = m.Param(value=0.8)
p = m.MV(value=0, lb=0, ub=100)  # Manipulated Variable (gas pedal)
v = m.CV(value=0)  # Controlled Variable (velocity)

# Define the dynamic equation
m.Equation(mass * v.dt() == -v * b + K * b * p)

# Set optimization mode for control
m.options.IMODE = 6  # Control mode

# Tuning parameters for MV (gas pedal)
p.STATUS = 1  # Allow optimizer to change
p.FSTATUS = 0
p.DCOST = 0.1  # Smooth out gas pedal movement
p.DMAX = 20  # Limit rate of change

# Tuning parameters for CV (velocity)
v.STATUS = 1  # Include set point in the objective
m.options.CV_TYPE = 2  # L2 norm
v.SP = 40  # Set point for velocity
v.TR_INIT = 1  # Enable set point trajectory
v.TAU = 5  # Time constant of trajectory

# List to store frames for GIF
frames = []

# Run the optimization in a loop and save plots
for i in range(25):
    if i==15:
        v.SP = 20
    
    print(f'MPC cycle: {i} of 25')
    m.solve(disp=False)  # Solve the optimization problem

    # Create a plot for each iteration
    fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(6, 8))
    
    ax1.plot(m.time+i, p.value, 'b-', lw=2)
    ax1.set_ylabel('Gas Pedal (%)')
    ax1.set_title(f'MPC Cycle {i+1}')
    ax1.set_ylim([0,100])

    ax2.plot(m.time+i, v.value, 'r--', lw=2)
    ax2.plot(m.time+i,np.ones_like(m.time)*v.SP,'k:',lw=2)
    ax2.set_ylim([0,50])
    ax2.set_ylabel('Velocity (m/s)')
    ax2.set_xlabel('Time (s)')
    fig.tight_layout()

    # Save the plot as an image frame
    fig.canvas.draw()
    frame = np.frombuffer(fig.canvas.tostring_rgb(), dtype='uint8')
    frame = frame.reshape(fig.canvas.get_width_height()[::-1] + (3,))
    frames.append(Image.fromarray(frame))

    plt.close(fig)  # Close the figure to save memory

# Save the frames as a GIF
frames[0].save('control_simulation.gif', format='GIF',
               append_images=frames[1:], save_all=True, duration=500, loop=0)

print("GIF saved as 'control_simulation.gif'")

我在图中添加了

m.time+i
以显示时间的进展。

ax2.plot(m.time+i, v.value, 'r--', lw=2)

Gekko 应用程序不需要相同的进程,可以在解决方案完成后添加到任何可视化中。

© www.soinside.com 2019 - 2024. All rights reserved.