考虑以下系统:
Fig.1 - Mass, spring, damper and Coulomb frction (image courtesy of Wikimedia).
具有的动态方程:
其中Ff
是Amontons-Columb摩擦定义为:
,因此no-slip
条件定义为
在this example之后,我有一个模糊的代码,我不知道该如何完成:
from scipy.integrate import odeint
import numpy as np
m = 1.0
k = 2.0
c = 0.1
mus = 0.3
muk = 0.2
g = 9.8
vf = 0.01
def eq(X, t, Xi):
Ff = k * (Xi[0] - X[0]) + c * (Xi[1] - X[1]) # - m * dydt
if np.abs(X[1]) < vf and np.abs(Ff) < mus * m * g :
Ff = k * (Xi[0] - X[0]) + c * (Xi[1] - X[1]) # - m * dydt
else:
Ff = -np.sign(X[1]) * muk * m * g
pass
dxdt = X[1]
dydt = (k * (Xi[0] - X[0]) + c * (Xi[1] - X[1]) - Ff) / m
return [dxdt, dydt]
t = np.linspace(0, 10, 1000)
Xi0 = np.piecewise(t, [t < 1, t >= 1], [0, 1])
X0 = [0, 0]
sol = odeint(eq, X0, t)
其中Xi0
是一个步进函数。我的主要问题是,当我想定义Ff
时,它取决于dydt
,后者将在该范围的后面定义!
如果您能帮助我知道用数字方法求解此系统的最典型方法,我将不胜感激。预先感谢。
答案 0 :(得分:0)
我要在这里提出一个简化/临时的解决方案,直到有人提出更好的解决方案为止:
from scipy.integrate import odeint
import numpy as np
import matplotlib.pyplot as plt
m = 0.2
k = 2.0
c = 0.1
mus = 0.3
muk = 0.2
g = 9.8
vf = 0.01
v0 = 0.0
t1 = 10
sign = lambda x: np.tanh(100*x)
def Xi(t):
if t < 1 :
return 0
else:
return 1
vXi = np.vectorize(Xi)
def eq(X, t, Xi):
Ff = k * (Xi(t) - X[0])
if np.abs(X[1]) < vf and np.abs(Ff) < mus * m * g :
Ff = k * (Xi(t) - X[0])
else:
Ff = sign(X[1]) * muk * m * g
d2x = (k * (Xi(t) - X[0]) - Ff) / m
return [X[1], d2x]
t = np.linspace(0, t1, 1000)
X0 = [v0, 0]
sol = odeint(func = eq, y0 = X0, t = t, args = (Xi, ), mxstep = 50000, atol = 1e-5)
plt.plot(t, sol[:, 0], 'r-', label = 'Output (x(t))')
plt.plot(t, vXi(t), 'b-', label = 'Input (xi(t))')
plt.ylabel('values')
plt.xlabel('time')
plt.legend(loc='best')
plt.show()
结果是:
答案 1 :(得分:0)
另一种方法是使用for循环并按顺序计算步骤:
Y = np.piecewise(t, [t < t2, t >= t2], [0, 1])
dY = np.insert(np.diff(Y) / np.diff(t), 0 , v0, axis = 0)
X = np.zeros((steps,))
dX = np.zeros((steps,))
dX[0] = v0
ddX = np.zeros((steps,))
Ff = np.zeros((steps,))
# FS = np.zeros((steps,))
dt = t1 / (steps - 1)
for ii in range(1, steps):
X[ii] = X[ii - 1] + dt * dX[ii - 1]
dX[ii] = dX[ii - 1] + dt * ddX[ii - 1]
Ff[ii] = k * (Y[ii] - X[ii]) #+ c * (dY[ii] - dX[ii])
if not (np.abs(dX[ii]) < vf and np.abs(Ff[ii]) < mus * m * g) :
Ff[ii] = np.sign(dX[ii]) * muk * m * g
ddX[ii] = (k * (Y[ii] - X[ii]) - Ff[ii]) / m
结果在下图中显示为绿色:
我也将vf
更改为0.001
。由于某些原因,结果与odeint
不同!
答案 2 :(得分:0)
写出这样一个系统的方程并不明显。而且解决起来也不容易。
如果可以解除Python约束,我建议使用OpenModelica来解决这个问题。在modelica 组件库中,您有元素
.Modelica.Mechanics.Translational.Components.MassWithStopAndFriction
可用于模拟干摩擦。