【发布时间】:2019-11-12 00:35:38
【问题描述】:
我正在处理一个家庭作业问题。我正在尝试使用 Scipy 的 integrate.solve_ivp() 函数在 Python 中模拟 PID 控制。
我的方法是在函数的右侧运行 PID 代码,使用全局变量并在每个时间步的末尾将它们附加到全局矩阵中,如下所示:
solution = integrate.solve_ivp(rhs, tspan, init, t_eval=teval)
这是我的代码:
def rhs(dt, init):
global old_time, omega0dot, rhs_t, omega0dotmat
timestep = dt - old_time
old_time = dt
# UNPACK INITIAL
x = init[0]
y = init[1]
z = init[2]
xdot = init[3]
ydot = init[4]
zdot = init[5]
alpha = init[6]
beta = init[7]
gamma = init[8]
alphadot = init[9]
betadot = init[10]
gammadot = init[11]
# SOLVE EQUATIONS
(xddot, yddot, zddot, alphaddot, betaddot, gammaddot) = dynamics(k_d, k_m, x, y, z, xdot, ydot, zdot, alpha, beta, gamma, alphadot, betadot, gammadot, omega0dot)
# CONTROL SYSTEMS
z_des = 10
err_z = z_des - z
zPID = (1*err_z) + hover
omega0dot = zPID
rhs_t.append(dt)
omega0dotmat.append(omega0dot)
return [xdot, ydot, zdot, xddot, yddot, zddot, alphadot, betadot, gammadot, alphaddot, betaddot, gammaddot]
全局变量在这个函数之外初始化。您可能会注意到我专门尝试模拟四旋翼飞行器,其中四旋翼的线性和角运动取决于omega0dot,它代表转子速度,我试图用 PID 控制它。
我的困难在于integrate.solve_ivp() 的时间步长。 PID 控制的积分和微分部分都依赖于时间步长,但solve_ivp() 函数具有可变时间步长,有时甚至会在时间上倒退,有时甚至没有时间步长(即 dt
我想知道是否有更好的方法来进行此 PID 控制,或者我是否将 solve_ivp() 中的 dt 术语解释错了。
【问题讨论】:
-
顺便说一句,我尝试根据此线程 (stackoverflow.com/questions/54494770/…) 中的答案修复时间步,但我仍然偶尔会得到 0 个时间步。
-
这是个坏主意。
solve_ivp的方法都具有自适应时间步长,并且每一步都包含在接近但不在解曲线上的点处对导函数的多次评估。最好只求解没有任何全局变量的方程,然后从解样本中构造所需的数组。 -
不幸的是,我无法在事后求解方程,因为转子速度,以及四轴飞行器的高度和姿态,都取决于前一个时间步长的计算。在这方面我错了吗?这就像模拟一个没有 PID 的系统,然后在事后计算 PID - 但模拟显然必须在首次运行时考虑 PID,因为 PID 会改变系统
-
这在代码中是不可见的,多余的值是用来填充一些数组的,但不用来影响动态的。
标签: python scipy ode runge-kutta