从pid的角度出发,根据原始参数,计算性能指标,然后通过优化方法(Nelder-Mead法)来调节参数实现性能的提升
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import minimize
import control as ctl # note: pip install control
import matplotlib.font_manager as fm
plt.rcParams['font.sans-serif'] = ['SimHei'] # 黑体
plt.rcParams['axes.unicode_minus'] = False # 正常显示负号
# 系统的开环传递函数
def create_system():
num = [1.151, 0.1774]
den = [1, 0.739, 0.921, 0]
return ctl.TransferFunction(num, den)
# 计算性能指标的函数
def calculate_performance(params, sys, target=0.2):
Kp, Ki, Kd = params
if Kp >= 20 or Ki >= 20 or Kd >= 20:
return 9999999999
C = ctl.TransferFunction([Kd, Kp, Ki], [1, 0])
T = ctl.feedback(C * sys, 1)
t = np.linspace(0, 20, 1000)
_, y = ctl.step_response(0.2 * T, t)
theta = y
max_theta = np.max(theta)
overshoot = (max_theta - target) / target * 100
ninety_percent_index = np.where(theta >= 0.9 * target)[0]
rise_time = t[ninety_percent_index[0]] - t[0] if len(ninety_percent_index) > 0 else 999999
steady_state_indices = np.where(np.abs(theta - target) <= target * 0.02)[0]
steady_state_time = 999999
if len(steady_state_indices) > 0:
for idx in steady_state_indices:
if np.all(np.abs(theta[idx:] - target) <= target * 0.02):
steady_state_time = t[idx]
if steady_state_time >= 15:
steady_state_time = 999999
break
return overshoot + rise_time + steady_state_time
# 原始PID参数及相关操作
def original_pid_analysis(sys):
Kp_original = 10
Ki_original = 5
Kd_original = 5
print(f"原始PID参数: Kp={Kp_original}, Ki={Ki_original}, Kd={Kd_original}")
C_original = ctl.TransferFunction([Kd_original, Kp_original, Ki_original], [1, 0])
T_original = ctl.feedback(C_original * sys, 1)
# 仿真原始系统响应
t_original = np.linspace(0, 20, 1000)
t_original, y_original = ctl.step_response(0.2 * T_original, t_original)
# 计算原始PID的性能指标
overshoot_original = (np.max(y_original) - 0.2) / 0.2 * 100
ninety_percent_index_original = np.where(y_original >= 0.9 * 0.2)[0]
rise_time_original = t_original[ninety_percent_index_original[0]] - t_original[0] if len(
ninety_percent_index_original) > 0 else np.nan
steady_state_indices_original = np.where(np.abs(y_original - 0.2) <= 0.2 * 0.02)[0]
steady_state_time_original = np.nan
if len(steady_state_indices_original) > 0:
for idx in steady_state_indices_original:
if np.all(np.abs(y_original[idx:] - 0.2) <= 0.2 * 0.02):
steady_state_time_original = t_original[idx]
break
steady_state_error_original = np.abs(y_original[-1] - 0.2) / 0.2 * 100
print("原始PID参数性能指标:")
print(f"超调量: {overshoot_original:.2f}%")
print(f"上升时间: {rise_time_original:.2f}秒")
print(f"稳态时间: {steady_state_time_original:.2f}秒")
print(f"稳态误差: {steady_state_error_original:.2f}%")
return t_original, y_original
# 优化PID参数及相关操作
def optimized_pid_analysis(sys):
initial_guess = [10, 1, 1]
# Nelder-Mead法 优化pid参数
result = minimize(calculate_performance, initial_guess, args=(sys,), method='Nelder-Mead')
Kp_opt, Ki_opt, Kd_opt = result.x
print(f'优化后的PID参数: Kp={Kp_opt:.2f}, Ki={Ki_opt:.2f}, Kd={Kd_opt:.2f}')
C_opt = ctl.TransferFunction([Kd_opt, Kp_opt, Ki_opt], [1, 0])
T_opt = ctl.feedback(C_opt * sys, 1)
t_opt = np.linspace(0, 40, 1000)
t_opt, y_opt = ctl.step_response(0.2 * T_opt, t_opt)
# 计算优化后PID的性能指标
overshoot_opt = (np.max(y_opt) - 0.2) / 0.2 * 100
ninety_percent_index_opt = np.where(y_opt >= 0.9 * 0.2)[0]
rise_time_opt = t_opt[ninety_percent_index_opt[0]] - t_opt[0] if len(ninety_percent_index_opt) > 0 else np.nan
steady_state_indices_opt = np.where(np.abs(y_opt - 0.2) <= 0.2 * 0.02)[0]
steady_state_time_opt = np.nan
if len(steady_state_indices_opt) > 0:
for idx in steady_state_indices_opt:
if np.all(np.abs(y_opt[idx:] - 0.2) <= 0.2 * 0.02):
steady_state_time_opt = t_opt[idx]
break
steady_state_error_opt = np.abs(y_opt[-1] - 0.2) / 0.2 * 100
print("优化后PID参数性能指标:")
print(f"超调量: {overshoot_opt:.2f}%")
print(f"上升时间: {rise_time_opt:.2f}秒")
print(f"稳态时间: {steady_state_time_opt:.2f}秒")
print(f"稳态误差: {steady_state_error_opt:.2f}%")
return t_opt, y_opt
if __name__ == "__main__":
sys = create_system()
t_original, y_original = original_pid_analysis(sys)
t_opt, y_opt = optimized_pid_analysis(sys)
plt.plot(t_original, y_original, label='原始PID')
plt.plot(t_opt, y_opt, label='优化后PID')
plt.title('原始PID与优化后PID的闭环系统阶跃响应对比')
plt.xlabel('时间 (秒)')
plt.ylabel('输出 (弧度)')
plt.grid()
plt.legend()
plt.show()
指标参数
原始PID参数: Kp=10, Ki=5, Kd=5
原始PID参数性能指标:
超调量: 10.02%
上升时间: 0.28秒
稳态时间: 1.26秒
稳态误差: 0.14%
优化后的PID参数: Kp=20.00, Ki=11.79, Kd=13.20
优化后PID参数性能指标:
超调量: 3.94%
上升时间: 0.16秒
稳态时间: 0.80秒
稳态误差: 0.00%