物理/力学中的凯恩方法

sympy.physics.mechanics 提供了使用 Kane 方法 [Kane1985] 推导运动方程的功能。本文档将描述在此模块中使用的 Kane 方法,但不会介绍方程是如何实际推导的。

方程的结构

sympy.physics.mechanics 中,我们假设描述一个系统需要5组基本方程。它们是:完整约束、非完整约束、运动学微分方程、动力学方程和微分的非完整方程。

\[\begin{split}\mathbf{f_h}(q, t) &= 0\\ \mathbf{k_{nh}}(q, t) u + \mathbf{f_{nh}}(q, t) &= 0\\ \mathbf{k_{k\dot{q}}}(q, t) \dot{q} + \mathbf{k_{ku}}(q, t) u + \mathbf{f_k}(q, t) &= 0\\ \mathbf{k_d}(q, t) \dot{u} + \mathbf{f_d}(q, \dot{q}, u, t) &= 0\\ \mathbf{k_{dnh}}(q, t) \dot{u} + \mathbf{f_{dnh}}(q, \dot{q}, u, t) &= 0\\\end{split}\]

sympy.physics.mechanics 中,完整约束仅用于线性化过程;假设它们将过于复杂而无法求解相关坐标。如果您能够轻松求解完整约束,您应该考虑根据一组较小的坐标重新定义您的问题。或者,可以提供时间微分的完整约束。

Kane 的方法形成了两个表达式,\(F_r\)\(F_r^*\),它们的和为零。在这个模块中,这些表达式被重新排列成以下形式:

\(\mathbf{M}(q, t) \dot{u} = \mathbf{f}(q, \dot{q}, u, t)\)

对于一个具有 \(o\) 个总速度和 \(m\) 个运动约束的非完整系统,我们将得到 o - m 个方程。然后,质量矩阵/力方程按以下方式增广:

\[\begin{split}\mathbf{M}(q, t) &= \begin{bmatrix} \mathbf{k_d}(q, t) \\ \mathbf{k_{dnh}}(q, t) \end{bmatrix}\\ \mathbf{_{(forcing)}}(q, \dot{q}, u, t) &= \begin{bmatrix} - \mathbf{f_d}(q, \dot{q}, u, t) \\ - \mathbf{f_{dnh}}(q, \dot{q}, u, t) \end{bmatrix}\\\end{split}\]

物理/力学中的凯恩方法

sympy.physics.mechanics 中运动方程的构建从创建一个 KanesMethod 对象开始。在初始化 KanesMethod 对象时,需要提供一个惯性参考系,以及一些基本的系统信息,如坐标和速度

>>> from sympy.physics.mechanics import *
>>> N = ReferenceFrame('N')
>>> q1, q2, u1, u2 = dynamicsymbols('q1 q2 u1 u2')
>>> q1d, q2d, u1d, u2d = dynamicsymbols('q1 q2 u1 u2', 1)
>>> KM = KanesMethod(N, [q1, q2], [u1, u2])

如果存在相关坐标和速度,正确提供坐标和速度的顺序也很重要。它们必须在独立坐标和速度之后提供,或者作为关键字参数提供;这一点将在后面展示。:

>>> q1, q2, q3, q4 = dynamicsymbols('q1 q2 q3 q4')
>>> u1, u2, u3, u4 = dynamicsymbols('u1 u2 u3 u4')
>>> # Here we will assume q2 is dependent, and u2 and u3 are dependent
>>> # We need the constraint equations to enter them though
>>> KM = KanesMethod(N, [q1, q3, q4], [u1, u4])

此外,如果有辅助速度,它们需要在这里被识别。请参阅示例以获取更多关于此的信息。在此示例中,u4 是辅助速度。:

>>> KM = KanesMethod(N, [q1, q3, q4], [u1, u2, u3], u_auxiliary=[u4])

运动学微分方程也必须提供;它们应作为每个等于零的表达式列表提供。以下是一个简单的例子:

>>> kd = [q1d - u1, q2d - u2]

开启 mechanics_printing() 可以使表达式显著缩短,推荐使用。或者,可以使用 mprintmpprint 命令。

如果有非完整约束,则需要指定相关速度(相关坐标也是如此,但它们仅在系统线性化时起作用)。约束需要以等于零的表达式列表形式提供,以下显示了平凡运动和配置约束:

>>> N = ReferenceFrame('N')
>>> q1, q2, q3, q4 = dynamicsymbols('q1 q2 q3 q4')
>>> q1d, q2d, q3d, q4d = dynamicsymbols('q1 q2 q3 q4', 1)
>>> u1, u2, u3, u4 = dynamicsymbols('u1 u2 u3 u4')
>>> #Here we will assume q2 is dependent, and u2 and u3 are dependent
>>> speed_cons = [u2 - u1, u3 - u1 - u4]
>>> coord_cons = [q2 - q1]
>>> q_ind = [q1, q3, q4]
>>> q_dep = [q2]
>>> u_ind = [u1, u4]
>>> u_dep = [u2, u3]
>>> kd = [q1d - u1, q2d - u2, q3d - u3, q4d - u4]
>>> KM = KanesMethod(N, q_ind, u_ind, kd,
...           q_dependent=q_dep,
...           configuration_constraints=coord_cons,
...           u_dependent=u_dep,
...           velocity_constraints=speed_cons)

一个返回已求解的 \(\dot{q}\) 的字典也可以被求解:

>>> mechanics_printing(pretty_print=False)
>>> KM.kindiffdict()
{q1': u1, q2': u2, q3': u3, q4': u4}

形成运动方程的最后一步是提供一个物体和粒子的列表,以及一个形式为 (点, 向量)(参考系, 向量) 的 2-元组列表,以表示施加的力和扭矩。:

>>> N = ReferenceFrame('N')
>>> q, u = dynamicsymbols('q u')
>>> qd, ud = dynamicsymbols('q u', 1)
>>> P = Point('P')
>>> P.set_vel(N, u * N.x)
>>> Pa = Particle('Pa', P, 5)
>>> BL = [Pa]
>>> FL = [(P, 7 * N.x)]
>>> KM = KanesMethod(N, [q], [u], [qd - u])
>>> (fr, frstar) = KM.kanes_equations(BL, FL)
>>> KM.mass_matrix
Matrix([[5]])
>>> KM.forcing
Matrix([[7]])

当存在运动约束时,质量矩阵通过 \(k_{dnh}(q, t)\) 矩阵进行增广,而力矢量则通过 \(f_{dnh}(q, \dot{q}, u, t)\) 矢量进行增广。

还有“完整”质量矩阵和“完整”强迫向量项,这些包括运动学微分方程;质量矩阵的大小为 (n + o) x (n + o),即正方形且大小为所有坐标和速度的总和。:

>>> KM.mass_matrix_full
Matrix([
[1, 0],
[0, 5]])
>>> KM.forcing_full
Matrix([
[u],
[7]])

鼓励探索提供的示例,以更深入地理解 KanesMethod 对象。