我正在尝试编写一个方程来建模,然后绘制一个积分控制系统(特别是关于巡航控制) . 但是每当我运行它时,我都会收到两个错误:
ValueError:对象太深,无法使用所需的数组odepack.error:函数调用的结果不是正确的浮点数组 .
我读过这些问题:
看起来他们应该有所帮助,但是我不确定如何将这些应用到我的问题中 . 我是python的新手,所以如果我错过了一些明显的东西或做了一些特别愚蠢的事情,请耐心等待 . 我没有绘制它的问题,所以一旦我弄清楚如何实际工作,我想我已经设定好了 .
import numpy as np
import scipy.integrate as integrate
##Parameters
kp=.5 #proportional gain
ki=.1 #integral gain
vr=30 #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 #weight
v=20 #starting velocity
time=np.linspace(0,10,50) #time
theta=np.radians(4) #Theta
def vderivs(state,t):
v = state
vel=[]
ti=0
while ti < t:
v1 = an*controller(ti,vr,v)*torque(v)
v2 = m*Cr*np.sign(v)
v3 = 0.5*p*Cd*A*v**2
v4 = m*np.sin(theta)
if t < 10:
vtot = v1+v2+v3
vfin = np.divide(vtot,m)
else:
vtot = v1+v2+v3+v4
vfin = np.divide(vtot,m)
vel.append(vfin)
ti+=1
trueVel = np.array(vel, float)
return trueVel
def uderivs(state,t):
v = state
deltax = vr - v
return deltax
def controller(time,desired,currentV):
z = integrate.odeint(uderivs, currentV, time)
u = kp*(vr-currentV)+ki*z
return u.flatten()
def torque(v):
return Tm*(1-B*(np.divide(an*v,wm)-1)**2)
def velocity(mass,desired,theta,t):
v = integrate.odeint(vderivs, desired, t)
return v.flatten()
test = velocity(m,vr,theta,time)
print(test)
如果您还有其他需要,请告诉我!
3 回答
将此作为单独发布,因为我让您的代码工作 . 好吧,运行并产生输出:P
实际上一个大问题是我没有注意到的一些隐形广播,但是我一路上改变了很多其他的东西 .
首先隐身广播是如果你将1d函数与一个参数集成,
odeint
返回一个列向量,然后当你用这个结果作为行向量的东西时,你得到一个二维数组(矩阵) . 例如:您获得的速度输出是
b
之类的列向量,并将其添加到其他时间函数中,并获得矩阵 .关于递归,我想我已经解决了这个问题 . 两个导数函数应采用单个标量
t
,此时它们计算导数 . 要做到这一点,vderivs
需要做积分,它应该一直做到t
. 所以我重新定义了它们:当然
uderivs
很好,但可以写得更简单:然后,确保
velocity
和controller
传递正确的值(使用v0
而不是v
作为起始速度):谁知道物理学是否正确,但这给出了:
请注意,它没有达到所需的速度,因此我增加了解决它的时间
这是我运行的所有代码:
这不是一个真正的答案,而是我注意到的一些关于你的代码的评论 .
正如@qmorgan指出的那样,你已经在
controller
函数中命名了一个与另一个函数相同的参数:velocity
尝试在变量名中保持一致以避免这种情况 . 例如,所有常量都是简写缩写 . 所以,当你在函数中命名参数时,也许会使用单词,这样你就可以使用'll have a habit of knowing where you' .你've made a few similar mistakes where you have a parameter for something in your function but you ignore it in the body of the function, and instead use a constant. For example, you'已经定义了
velocity
来取(mass, desired, theta, t)
但你传递了(m, v, theta, time)
,其中v
是你的起始速度 . 小心!你没有注意到这个错误,因为事实上,velocity
忽略desired
而只是使用vr
全局常量 . 相反,这整个应该有类似的东西要将列表转换为numpy数组,您可以使用
np.array(vel, float)
而不是np.array([x for x in vel], float)
,因为[x for x in vel]
与vel
本身相同 .在
vderivs
中,通过t
的循环可能已完全消除,但至少我认为它应该更像是:哪个不会忽略输入
t
.就目前而言,
uderivs
采用当前速度和全局定义的所需速度并返回它们的差异:但是你总是传递它
vr
(参见controller
的定义),所以每次集成它时,它只会返回一个长度为t.size
且值为vr
的扁平数组 .而不是
theta = 4
你可能想要theta = np.radians(4)
numpy中已存在函数
np.sign
,无需实现自己的 .我看到的一个错误是函数
controller
;您试图从整数(vr
)中减去一个函数(velocity
),这可能是某些问题的根源 ."object too deep for desired array"错误可能来自一个单独的问题,其中函数
controller
和velocity
的返回形状错误;它们需要是一维的numpy数组 . 您可以使用flatten()
方法解决此问题:但是为了完全调试,您需要在控制器功能中修复上述错误 .