集成控制系统的异常行为及解决方法

43 阅读4分钟

昨天,我发表了一个问题:ValueError 和 odepack.error using integrate.odeint(),我认为这个问题已成功得到解答。然而,此后我注意到了一些情况。

运行此程序时,它不会趋向于期望的速度 vr 在运行程序时,随着时间变化而改变角度(代表道路的坡度),它并不总能返回期望的速度 vr,甚至返回到以前.

该程序旨在模拟积分控制系统(特别是巡航控制)。它目前从速度 v0 开始,以该速度运行一段时间,然后接合巡航控制。在这一点上,我们应该看到速度发生变化(我们确实看到了),最终稳定在期望速度 vr上。然而,它并没有达到。它达到了其他一些未知原因的值,并且该值根据道路的坡度而不同。无论初始速度如何,它仍然无法达到期望的速度。

我尝试过不同的参数和变量,但都无济于事。我认为问题在于控制器没有传递正确的当前速度,但我不知道如何解决这个问题。

如果您需要更多信息,请告诉我。如果我应该编辑之前的问题,请告诉我,我会这么做的,提前抱歉。

以下是我的代码:

import matplotlib.pylab as plt
import numpy as np
import scipy.integrate as integrate

##Parameters
kp = .5 #proportional gain
ki = .1 #integral gain
vr = 25 #desired velocity in m/s
Tm = 190 #Max Torque in Nm
wm = 420 #engine speed
B = 0.4 #Beta
an = 12 #at gear 4
p = 1.3 #air density
Cd = 0.32 #Drag coefficient
Cr = .01 #Coefficient of rolling friction
A = 2.4 #frontal area

##Variables
m = 18000.0 #weight
v0 = 20. #starting velocity
t = np.linspace(61, 500, 5000) #time
theta = np.radians(4) #Theta

def torque(v):    
    return Tm * (1 - B*(an*v/wm - 1)**2)  

def vderivs(v, t):
    v1 = an * controller(v, t) * torque(v)
    v2 = m*Cr*np.sign(v)
    v3 = 0.5*p*Cd*A*v**2
    v4 = m*np.sin(theta)
    vtot = v1-v2-v3-v4*(t>=200)
    return vtot/m

def uderivs(v, t):
    return vr - v

def controller(currentV, time):
    z = integrate.odeint(uderivs, currentV, time)
    return kp*(vr-currentV) + ki*z.squeeze()

def velocity(desired, theta, time):
    return integrate.odeint(vderivs, desired, time)

t0l = [i for i in range(61)]
vf=[v0 for i in range(61)]+[v for v in velocity(v0,theta,t)]
tf=t0l+[time for time in t]

plt.plot(tf, vf, 'k-', label=('V(0) = '+str(v0)))

v0=35.
vf=[v0 for i in range(61)]+[v for v in velocity(v0,theta,t)]
plt.plot(tf, vf, 'b-', label=('V(0) = '+str(v0)))

v0=vr
vf=[v0 for i in range(61)]+[v for v in velocity(v0,theta,t)]
plt.plot(tf, vf, 'g-', label=('V(0) = Vr'))

plt.axhline(y=vr, xmin=0, xmax=1000, color='r', label='Desired Velocity')
plt.legend(loc = "upper right")
plt.axis([0,500,18,36])
plt.show()

This is what is plotted running the program as is, using a range of initial velocities

The first sharp change in velocity is when the cruise control is initiated, and the second is when the gradient of the rode changes

2、解决方案

您的猜测是正确的。目标系统和 PI 控制器是集成的,您不能将其分成两个 odeint。我修改了您的代码,使该系统有两个状态变量:一个用于系统的速度,另一个用于控制误差的积分:

import matplotlib.pylab as plt
import numpy as np
import scipy.integrate as integrate

##Parameters
kp = .5 #proportional gain
ki = .1 #integral gain
vr = 25 #desired velocity in m/s
Tm = 190 #Max Torque in Nm
wm = 420 #engine speed
B = 0.4 #Beta
an = 12 #at gear 4
p = 1.3 #air density
Cd = 0.32 #Drag coefficient
Cr = .01 #Coefficient of rolling friction
A = 2.4 #frontal area

##Variables
m = 18000.0 #weight
v0 = 20. #starting velocity
t = np.linspace(61, 500, 5000) #time
theta = np.radians(4) #Theta

def torque(v):    
    return Tm * (1 - B*(an*v/wm - 1)**2)  

def vderivs(status, t):
    v, int_err = status

    err = vr - v
    control = kp * err + ki * int_err

    v1 = an * control * torque(v)
    v2 = m*Cr*np.sign(v)
    v3 = 0.5*p*Cd*A*v**2
    v4 = m*np.sin(theta)
    vtot = v1-v2-v3-v4*(t>=200)
    return vtot/m, err

def velocity(desired, theta, time):
    return integrate.odeint(vderivs, [desired, 0], time)[:, 0]

t0l = [i for i in range(61)]
vf=[v0 for i in range(61)]+[v for v in velocity(v0,theta,t)]
tf=t0l+[time for time in t]

plt.plot(tf, vf, 'k-', label=('V(0) = '+str(v0)))

v0=35.
vf=[v0 for i in range(61)]+[v for v in velocity(v0,theta,t)]
plt.plot(tf, vf, 'b-', label=('V(0) = '+str(v0)))

v0=vr
vf=[v0 for i in range(61)]+[v for v in velocity(v0,theta,t)]
plt.plot(tf, vf, 'g-', label=('V(0) = Vr'))

plt.axhline(y=vr, xmin=0, xmax=1000, color='r', label='Desired Velocity')
plt.legend(loc = "upper right")
plt.axis([0,500,18,36])
plt.show()

输出:

[图片]

通过修改代码,该系统现在能够按预期工作。它追踪期望速度并最终达到稳定状态。

我希望这个解决方案对您有帮助。如果您有任何其他问题,请随时提出。