<p>把这个单独贴出来,因为我有你的代码。好吧,运行并产生产出:P</p>
<p>实际上,一个很大的问题是一些我没有注意到的秘密广播,但我改变了很多其他的事情。在</p>
<p>首先,隐形广播是,如果你把一个一维函数与一个参数集成,<code>odeint</code>返回一个列向量,然后当你用这个结果填充行向量时,你就得到了一个2d数组(矩阵)。例如:</p>
<pre><code>In [704]: a
Out[704]: array([0, 1, 2, 3, 4])
In [705]: b
Out[705]:
array([[0],
[1],
[2]])
In [706]: a+b
Out[706]:
array([[0, 1, 2, 3, 4],
[1, 2, 3, 4, 5],
[2, 3, 4, 5, 6]])
</code></pre>
<p>我们得到了速度的输出,它是一个列向量,比如<code>b</code>,然后把它加到其他时间函数中,得到一个矩阵。在</p>
<hr/>
<p>关于递归,我想我解决了这个问题。这两个导数函数应该取一个标量<code>t</code>,此时它们计算导数。要做到这一点,<code>vderivs</code>需要做积分,它应该一直做到<code>t</code>。所以我重新定义了它们:</p>
^{pr2}$
<p>当然<code>uderivs</code>也可以,但可以写得更简单:</p>
<pre><code>def uderivs(v, t):
return vr - v
</code></pre>
<p>然后,确保<code>velocity</code>和<code>controller</code>传递正确的值(使用<code>v0</code>而不是{<cd10>}作为起始速度):</p>
<pre><code>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)
</code></pre>
<p>谁知道物理原理是否正确,但这给出了:</p>
<p><img src="https://i.stack.imgur.com/OTRcA.png" alt="short time"/></p>
<p>注意,它还没有达到期望的速度,所以我增加了求解的时间</p>
<pre><code>time = np.linspace(0,50,50) #time
</code></pre>
<p>{2美元^</p>
<p>以下是我运行的所有代码:</p>
<pre><code>import matplotlib.pylab as plt
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.0 #weight
v0 = 20. #starting velocity
t = np.linspace(0, 20, 50) #time
dt = .1
theta = np.radians(4) #Theta
def torque(v):
return Tm * (1 - B*(an*v/wm - 1)**2)
def vderivs(v, t):
ts = np.arange(0, t, dt)
v1 = an * controller(v, ts) * 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*(ts>=10)
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)
plt.plot(t, velocity(v0, theta, t), 'k-', lw=2, label='velocity')
plt.plot(t, controller(v0, t), 'r', lw=2, label='controller')
plt.legend()
plt.show()
</code></pre>