我正在使用二阶拉格朗日方程组进行多重自由度动力学问题。我用sympy来了解运动方程。现在,这些方程在计算导数之后变得相当长,尽管sympy简化无法进一步简化。我的问题实际上是从这里如何解决这个三阶ode系统。我不知道如何转换这些方程式,因此它们可以与scipy.odeint()一起使用。我想到了替代,但是有很多符号。因此,Im寻找phi0,phi1和phi2以及它们的一阶和二阶导数。初始条件均为phi [0] = 0和所有dphi [0] = 0。 我希望有一种方法可以解决此问题,而不会从头开始。提前致谢。
def derivativeLagranga(Lagrange,n):
"""left side of lagrange"""
f0 = sym.Function('f0')(t)
f1 = sym.Function('f1')(t)
f2 = sym.Function('f2')(t)
f3 = sym.Function('f3')(t)
L_i = []
L_it = []
L_j =[]
L_leva = []
x=0
y=0
for i in range(0,n-1):
x = Lagrange.diff(kot[i].diff(t))
L_i.append(x)
for i in range(0,n-1):
x = L_i[i].diff(t)
x = x.replace(sym.sin(kot[i]),kot[i])
L_it.append(x)
for i in range(0,n-1):
x = L.diff(kot[i])
L_j.append(x)
for i in range(0,n-1):
x = L_it[i]+L_j[i]
L_leva.append(x)
return L_left
left_side_L = derivativeLagranga(Lagrange, n)
f0 = sym.simplify(left_side_L[0].subs(values))
f1 = leva_stran_L[1].subs(values)
f2 = leva_stran_L[2].subs(values)
f0
所以我的f0是方程式之一,我无法复制输出,所以我将发布图片。
54.51345(−(????0(?)+????1(?)−????2(?))sin(?0(?)+?1(?)−?2(?))+2.0?0(?)????0(?))(0.5(????0(?)+????1(?)−????2(?))cos(?0(?)+?1(?)−?2(?))−1.0cos(?0(?))????0(?)−1.0cos(?1(?))????1(?)+1.0cos(?2(?))????2(?))+54.51345((????0(?)+????1(?)−????2(?))cos(?0(?)+?1(?)−?2(?))+cos(?0(?))????0(?))(0.5(????0(?)+????1(?)−????2(?))sin(?0(?)+?1(?)−?2(?))+0.5?0(?)????0(?)+0.5sin(?1(?))????1(?)+1.0sin(?2(?))????2(?))+54.51345(2.0(????0(?)+????1(?)−????2(?))cos(?0(?)+?1(?)−?2(?))+cos(?0(?))????0(?))(1.0(????0(?)+????1(?)−????2(?))sin(?0(?)+?1(?)−?2(?))+0.5?0(?)????0(?)+0.5sin(?1(?))????1(?)+1.0sin(?2(?))????2(?)+0.5sin(?4(?))????4(?))−54.51345(2.0cos(?0(?))????0(?)+1.0cos(?1(?))????1(?))?0(?)????0(?)+54.51345(?0(?)+sin(?0(?)+?1(?)−?2(?)))((0.5????0(?)+0.5????1(?)−0.5????2(?))(????0(?)+????1(?)−????2(?))cos(?0(?)+?1(?)−?2(?))+(0.5?2??2?0(?)+0.5?2??2?1(?)−0.5?2??2?2(?))sin(?0(?)+?1(?)−?2(?))+0.5?0(?)?2??2?0(?)+0.5sin(?1(?))?2??2?1(?)+1.0sin(?2(?))?2??2?2(?)+0.5cos(?0(?))(????0(?))2+0.5cos(?1(?))(????1(?))2+1.0cos(?2(?))(????2(?))2)+54.51345(?0(?)+2.0sin(?0(?)+?1(?)−?2(?)))((????0(?)+????1(?)−????2(?))(1.0????0(?)+1.0????1(?)−1.0????2(?))cos(?0(?)+?1(?)−?2(?))+(1.0?2??2?0(?)+1.0?2??2?1(?)−1.0?2??2?2(?))sin(?0(?)+?1(?)−?2(?))+0.5?0(?)?2??2?0(?)+0.5sin(?1(?))?2??2?1(?)+1.0sin(?2(?))?2??2?2(?)+0.5sin(?4(?))?2??2?4(?)+0.5cos(?0(?))(????0(?))2+0.5cos(?1(?))(????1(?))2+1.0cos(?2(?))(????2(?))2+0.5cos(?4(?))(????4(?))2)+54.51345(cos(?0(?)+?1(?)−?2(?))−2.0cos(?0(?)))(−(0.5????0(?)+0.5????1(?)−0.5????2(?))(????0(?)+????1(?)−????2(?))sin(?0(?)+?1(?)−?2(?))+(0.5?2??2?0(?)+0.5?2??2?1(?)−0.5?2??2?2(?))cos(?0(?)+?1(?)−?2(?))+1.0?0(?)(????0(?))2+1.0sin(?1(?))(????1(?))2−1.0sin(?2(?))(????2(?))2−1.0cos(?0(?))?2??2?0(?)−1.0cos(?1(?))?2??2?1(?)+1.0cos(?2(?))?2??2?2(?))+54.51345(0.5?0(?)????0(?)+0.5sin(?1(?))????1(?)+0.5sin(?2(?))????2(?))cos(?0(?))????0(?)−54.51345(2.0cos(?0(?))????0(?)+2.0cos(?1(?))????1(?)−1.0cos(?2(?))????2(?))?0(?)????0(?)+54.51345(−2.0?0(?)(????0(?))2−1.0sin(?1(?))(????1(?))2+2.0cos(?0(?))?2??2?0(?)+1.0cos(?1(?))?2??2?1(?))cos(?0(?))+54.51345(−2.0?0(?)(????0(?))2−2.0sin(?1(?))(????1(?))2+1.0sin(?2(?))(????2(?))2+2.0cos(?0(?))?2??2?0(?)+2.0cos(?1(?))?2??2?1(?)−1.0cos(?2(?))?2??2?2(?))cos(?0(?))+54.51345(0.5?0(?)?2??2?0(?)+0.5sin(?1(?))?2??2?1(?)+0.5sin(?2(?))?2??2?2(?)+0.5cos(?0(?))(????0(?))2+0.5cos(?1(?))(????1(?))2+0.5cos(?2(?))(????2(?))2)?0(?)−2123.406????0(?)+45.427875?2??2?0(?)−2123.406????1(?)+9.085575?2??2?1(?)−9.085575?2??2?2(?)
然后lambdify输出:
NameError Traceback (most recent call last)
<ipython-input-14-ee077b324a2e> in <module>
2 en2 = sym.lambdify([kot_0,kot_1,kot_2],f1)
3 en3 = sym.lambdify([kot_0,kot_1,kot_2],f2)
----> 4 en1(kot_0,kot_1,kot_2)
5
6
<lambdifygenerated-4> in _lambdifygenerated(_Dummy_227, _Dummy_226, _Dummy_225)
9 # Derivative
10 # Derivative
---> 11 22.722525*_Dummy_227**2*Derivative(_Dummy_227, (t, 2)) + 90.8901*_Dummy_227*(-0.5*cos(_Dummy_226)*Derivative(_Dummy_226, t) - 1.0*cos(_Dummy_227)*Derivative(_Dummy_227, t))*Derivative(_Dummy_227, t) + 90.8901*_Dummy_227*(0.5*cos(_Dummy_225)*Derivative(_Dummy_225, t) - 1.0*cos(_Dummy_226)*Derivative(_Dummy_226, t) - 1.0*cos(_Dummy_227)*Derivative(_Dummy_227, t))*Derivative(_Dummy_227, t) - 22.722525*_Dummy_227*(-_Dummy_227*Derivative(_Dummy_227, (t, 2)) - sin(_Dummy_225)*Derivative(_Dummy_225, (t, 2)) - sin(_Dummy_226)*Derivative(_Dummy_226, (t, 2)) - cos(_Dummy_225)*Derivative(_Dummy_225, t)**2 - cos(_Dummy_226)*Derivative(_Dummy_226, t)**2 - cos(_Dummy_227)*Derivative(_Dummy_227, t)**2) + 0.5*Jm*(-2*Derivative(_Dummy_225, (t, 2)) + 2*Derivative(_Dummy_226, (t, 2)) + 2*Derivative(_Dummy_227, (t, 2))) + 1.0*Jm*Derivative(_Dummy_227, (t, 2)) + 45.44505*(-1.0*_Dummy_227 - 2.0*sin(-_Dummy_225 + _Dummy_226 + _Dummy_227))*(-0.5*_Dummy_227*Derivative(_Dummy_227, (t, 2)) + (-Derivative(_Dummy_225, t) + Derivative(_Dummy_226, t) + Derivative(_Dummy_227, t))*(1.0*Derivative(_Dummy_225, t) - 1.0*Derivative(_Dummy_226, t) - 1.0*Derivative(_Dummy_227, t))*cos(-_Dummy_225 + _Dummy_226 + _Dummy_227) + (1.0*Derivative(_Dummy_225, (t, 2)) - 1.0*Derivative(_Dummy_226, (t, 2)) - 1.0*Derivative(_Dummy_227, (t, 2)))*sin(-_Dummy_225 + _Dummy_226 + _Dummy_227) - 1.0*sin(_Dummy_225)*Derivative(_Dummy_225, (t, 2)) - 0.5*sin(_Dummy_226)*Derivative(_Dummy_226, (t, 2)) - 0.5*sin(varphi_4(t))*Der
EDIT2:因此,经过一番简化,我知道了如何得到3个常微分方程。但是它们是sympy形式,我该如何用数值方法解决它们?
−800000.0?0+800000.0?2−1770.174?˙0+242.3736?¨0−1770.174?˙1+166.63185?¨1−75.74175?¨2+4245.8661
−1200000.0?1+400000.0?2−1770.174?˙0+166.63185?¨0−1770.174?˙1+151.4835?¨1−75.74175?¨2+2830.5774
800000.0?0+400000.0?1−2000000.0?2−75.74175?¨0−75.74175?¨1+60.5934?¨2−1415.2887
答案 0 :(得分:0)
我将以双摆为例介绍Euler-Lagrange形式主义的执行,将其作为非平凡,完整的标准示例,并且在不使用sympy.physics中的专用功能的情况下,仅使用基本微分和sympy的代码编写工具。希望它足够通用,因为第二部分应该独立于问题,因此也可以直接应用于您的情况。
from sympy import sin, cos, Symbol, symbols, solve
from sympy.utilities.lambdify import lambdify
首先使用两个角度作为主要相关函数对拉格朗日算子进行物理设置,并通过笛卡尔坐标构造动能和势能。
# Symbols for the parameters of the problem
t,m1,m2,l1,l2,g = symbols("t,m_1 m_2 l_1 l_2 g")
# Variables of the problem
th1, th2 = Function("θ_1")(t), Function("θ_2")(t)
x1,y1 = l1*sin(th1), -l1*cos(th1)
x2,y2 = x1+l2*sin(th2), y1-l2*cos(th2)
# kinetic energy
vx1,vy1,vx2,vy2 = ( xx.diff(t) for xx in (x1,y1,x2,y2))
K1 = m1/2*(vx1**2+vy1**2)
K2 = m2/2*(vx2**2+vy2**2)
K = K1+K2
# potential energy
V = g*(m1*y1+m2*y2)
# Lagrangian
L = K - V
L = L.expand().simplify()
要获得抽象处理,请使用抽象参数数组和坐标向量
params = [m1, l1, m2, l2, g]
q = [th1, th2]
dotq = [ qq.diff(t) for qq in q]
如果使用角度的二阶导数,结果表达式将变得很混乱,人们会使用更结构化的方法,并希望使用冲量变量进行相应的更快的评估
pk = diff(L, dotqk)
d(pk)/dt = diff(L, qk)
其中第一个关系被视为方程式系统,用于根据dotq
计算p
。
准备新变量,准备用简单变量替换功能符号。
N = len(q)
p = [ Symbol(f"p_{k+1}") for k in range(N)]
dotq_func, dotq = dotq, [ Symbol(f"Dq_{k+1}") for k in range(N)]
q_func, q = q, [ Symbol(f"q_{k+1}") for k in range(N)]
现在用简单变量替换所有函数项
L=L.subs(list(zip(dotq_func, dotq))).subs(list(zip(q_func, q)))
现在建立从dotq
计算q,p
的函数
p_eqns = [ p[k] - L.diff(dotq[k]) for k in range(N)]
dotq_expr = solve(p_eqns, dotq)
dotq_func = lambdify([*q, *p, *params],[ dotq_expr[dq] for dq in dotq])
接下来生成一个计算p
的导数的函数
dotp_expr = [ L.diff(q[k]) for k in range(N)]
dotp_func = lambdify([*q,*dotq,*params],dotp_expr)
现在将生成的函数组装成一个完整的ODE函数,并解决一个测试问题以确认其正常工作
def odefunc(t,u,args):
q, p = u[:N], u[N:]
dotq = dotq_func(*q, *p, *args)
dotp = dotp_func(*q, *dotq, *args)
return [*dotq, *dotp]
myparams = [1,10,5,5,9.81]
t = np.linspace(0,25,301)
u = odeint(odefunc,[2,1.2, 0,0],t,args=(myparams,), tfirst=True)
%matplotlib inline
plt.figure(figsize=(8,5))
plt.plot(t,u[:,0],t,u[:,1]);
plt.grid(); plt.show()
如果动力学项(在经典力学中通常如此)保证在速度上是二次方的,则可以预期会有更好的性能。然后,通过直接提取这种二次形式的矩阵,可以将由脉冲到速度的转换中的系统解委托给数值线性系统解算器,而不必保留矩阵求逆的符号表达式。这些可能在较大的尺寸上很大。