SymPy 力学模块实战:用 Kane 方法求解滚动圆盘的非贡献约束力(rollingdisc_example_kane_constraints)
2026/9/15 13:11:56 网站建设 项目流程

SymPy 力学模块实战:用 Kane 方法求解滚动圆盘的非贡献约束力(rollingdisc_example_kane_constraints)

【免费下载链接】sympyA computer algebra system written in pure Python项目地址: https://gitcode.com/GitHub_Trending/sy/sympy

导读

本篇技术指南围绕 SymPy 力学模块(sympy.physics.mechanics)中的经典教程 rollingdisc_example_kane_constraints.rst 展开,完整演示如何基于 Kane 方法建立"无限薄圆盘在地面无滑动纯滚动"的多体系统模型,并通过引入**辅助广义速度(auxiliary generalized speeds)把通常被剔除的非贡献力(non-contributing / constraint forces)**显式求解出来。读完本文,你将掌握KanesMethodu_auxiliary参数的完整用法、auxiliary_eqs属性的含义,以及如何从质量矩阵与 forcing 向量出发得到系统的显式运动方程,并最终写出约束力关于广义坐标与广义速度的闭式表达式。

一、背景:为什么要"把约束力带入证据"

在 rollingdisc_example_kane.rst 中,圆盘模型直接从接触点向上定义运动学,滚动无滑动条件被"构造性地"满足,因此不需要引入广义速度,最终只需求解 3 个广义坐标q1, q2, q3与 3 个广义速度u1, u2, u3下的运动方程。

但很多工程场景中,我们不仅关心运动,还关心约束力本身(例如地面法向反力、摩擦力),用于强度校核或控制系统设计。Kane 方法的核心思想是:广义主动力与广义惯性力在广义速度方向上的投影之和为零,而非贡献力(约束力)在允许运动方向上不做功,因此它们不会出现在常规的 Kane 方程中。

本教程的做法(原理详见 [Kane1985])是:在接触点人为引入三个辅助广义速度u4, u5, u6,它们在纯滚动条件下恒等于零;同时引入与它们同方向的三个约束力分量f1, f2, f3。这样一来,约束力从"隐藏项"变成"显式未知量",可以在 Kane 方程之外得到一组额外的**辅助方程(auxiliary equations)**用于反解它们。

在 SymPy 源码中,这一机制由 kane.py 中的KanesMethod实现:构造器接受u_auxiliary参数(见 kane.py 第 71-72 行),并提供auxiliary_eqs属性(见 kane.py 第 110-113 行)。下面按教程的完整流程逐步实现。

二、环境准备:符号与动力学符号声明

教程首先开启力学模块打印并导入需要的符号。注意这一行:

>>> from sympy import symbols, sin, cos, tan >>> from sympy.physics.mechanics import * >>> mechanics_printing(pretty_print=False)

mechanics_printing(pretty_print=False)用于开启向量运算时的自动简化。文档明确提示:它会让小型问题的输出更美观,但较大的向量运算可能因此挂起It makes the outputs nicer for small problems, but can cause larger vector operations to hang)。因此这是本教程特意开启的开关,在大规模建模时建议谨慎使用。

接着声明广义坐标、广义速度及其一阶导数,以及圆盘半径、质量和重力加速度:

>>> q1, q2, q3, u1, u2, u3 = dynamicsymbols('q1 q2 q3 u1 u2 u3') >>> q1d, q2d, q3d, u1d, u2d, u3d = dynamicsymbols('q1 q2 q3 u1 u2 u3', 1) >>> r, m, g = symbols('r m g')

这里dynamicsymbols(..., 1)生成对应符号关于时间的一阶导数,供后续运动学微分方程(kd)使用。

三、核心新增:辅助广义速度与约束力符号

与无约束版本相比,本教程唯一新增的两行声明是:

>>> u4, u5, u6, f1, f2, f3 = dynamicsymbols('u4 u5 u6 f1 f2 f3')
  • u4, u5, u6:接触点处的三个辅助广义速度,分别沿L.x方向(圆盘侧向)、cross(Y.z, L.x)方向(沿滚动路径)、Y.z方向(垂直地面)。由于纯滚动约束,它们按定义恒为零
  • f1, f2, f3:与上述三个速度方向一一对应的约束力幅值。

从源码结构看,KanesMethod会把u_auxiliary列表中的速度从主广义速度中分离出来单独处理(见 kane.py 第 842-861 行),这正是后续能得到auxiliary_eqs的关键。

四、参考系与角速度运动学

圆盘姿态采用 3-1-2(Z、X、Y)系列的**简单旋转(simple rotation)**逐级建立中间参考系:

>>> N = ReferenceFrame('N') >>> Y = N.orientnew('Y', 'Axis', [q1, N.z]) >>> L = Y.orientnew('L', 'Axis', [q2, Y.x]) >>> R = L.orientnew('R', 'Axis', [q3, L.y]) >>> w_R_N_qd = R.ang_vel_in(N) >>> R.set_ang_vel(N, u1 * L.x + u2 * L.y + u3 * L.z)
  • N:惯性参考系(地面);
  • Y:绕N.z旋转q1(方位角),即圆盘"前进方向"所在的竖直平面;
  • L:绕Y.x旋转q2(侧倾/lean 角),称侧倾参考系,惯性主轴在此系中不变;
  • R:绕L.y旋转q3(自转角),附着于圆盘本体。

w_R_N_qd是从旋转序列解析得到的角速度表达式;随后用广义速度u1, u2, u3L系基向量上的组合显式指定角速度。之后kd方程正是用来建立这两者之间的联系。

五、平动运动学:接触点速度与质心速度

无滑滚动要求接触点速度为零。但为了把约束力带入证据,这里反其道而行:给接触点显式赋予一个由辅助速度合成的"名义速度",它在约束成立时归零:

>>> C = Point('C') >>> C.set_vel(N, u4 * L.x + u5 * cross(Y.z, L.x) + u6 * Y.z) >>> Dmc = C.locatenew('Dmc', r * L.z) >>> vel = Dmc.v2pt_theory(C, N, R)
  • C:接触点,其速度的三个分量分别沿圆盘侧向、滚动路径方向、竖直方向;
  • Dmc:圆盘质心,位于接触点正上方r * L.z处;
  • v2pt_theory(C, N, R):基于两点速度关系(两点位于同一刚体R上),由C的速度与R的角速度自动推出质心速度。

六、惯量张量

圆盘关于质心的惯量张量在L系中写出(圆盘绕自身对称轴L.y的转动惯量为m*r**2/2,两个直径方向各为m*r**2/4):

>>> I = inertia(L, m / 4 * r**2, m / 2 * r**2, m / 4 * r**2)

由于圆盘在L系中滚动时惯量不变化(圆盘轴对称),在L系表达惯量可显著简化最终方程——这一建模技巧在 rollingdisc_example_kane.rst 中有同样说明。

七、运动学微分方程(kd)

kd 方程把广义坐标导数与广义速度联系起来,通过对R的角速度在L系三个基向量上取点积得到:

>>> kd = [dot(R.ang_vel_in(N) - w_R_N_qd, uv) for uv in L]

dot(角速度表达式之差, L.x)dot(..., L.y)dot(..., L.z)三个标量方程,形式为q1d、q2d、q3du1、u2、u3之间的线性关系。

八、力清单与刚体定义

力清单同时包含主动力(重力)与约束力(三个未知分量):

>>> ForceList = [(Dmc, - m * g * Y.z), (C, f1 * L.x + f2 * cross(Y.z, L.x) + f3 * Y.z)] >>> BodyD = RigidBody('BodyD', Dmc, R, m, (I, Dmc)) >>> BodyList = [BodyD]
  • (Dmc, -m*g*Y.z):作用于质心的重力;
  • (C, f1*L.x + f2*cross(Y.z, L.x) + f3*Y.z):作用于接触点的约束力,三个分量方向与辅助速度u4, u5, u6一一对应(力与速度同方向投影,正是"广义力=约束力在虚位移上的虚功"的离散化形式)。

RigidBody('BodyD', Dmc, R, m, (I, Dmc))指定:质心点为Dmc、附着参考系为R、质量为m、惯量张量I相对Dmc给出。

九、构建 KanesMethod 并求解运动方程

构造器传入u_auxiliary=[u4, u5, u6],这是与普通 Kane 建模唯一的结构性差异

>>> KM = KanesMethod(N, q_ind=[q1, q2, q3], u_ind=[u1, u2, u3], kd_eqs=kd, ... u_auxiliary=[u4, u5, u6]) >>> (fr, frstar) = KM.kanes_equations(BodyList, ForceList) >>> MM = KM.mass_matrix >>> forcing = KM.forcing >>> rhs = MM.inv() * forcing >>> kdd = KM.kindiffdict() >>> rhs = rhs.subs(kdd) >>> rhs.simplify() >>> mprint(rhs) Matrix([ [(4*g*sin(q2) + 6*r*u2*u3 - r*u3**2*tan(q2))/(5*r)], [ -2*u1*u3/3], [ (-2*u2 + u3*tan(q2))*u1]])

推导过程是标准流程:kanes_equations返回广义主动力fr与广义惯性力frstar;由mass_matrixforcing组装M·u̇ = forcingrhs = MM.inv() * forcing得到的表达式;再用kindiffdict()替换为广义速度,最终显式给出:

  • u̇1 = (4·g·sin(q2) + 6·r·u2·u3 − r·u3²·tan(q2)) / (5·r)
  • u̇2 = −2·u1·u3 / 3
  • u̇3 = (−2·u2 + u3·tan(q2)) · u1

注意这个结果与不引入约束力的 Kane 版本(见 rollingdisc_example_kane.rst 输出)完全一致——这印证了辅助速度的引入不改变真实运动方程,符合"非贡献力不影响运动"的理论预期,同时验证了建模的正确性。

十、求解约束力:auxiliary_eqs 与化简技巧

运动方程求出后,约束力藏在KM.auxiliary_eqs中。直接输出的表达式可能比较冗长,教程给出了一个专门的化简管线:

>>> from sympy import trigsimp, signsimp, collect, factor_terms >>> def simplify_auxiliary_eqs(w): ... return signsimp(trigsimp(collect(collect(factor_terms(w), f2), m*r))) >>> mprint(KM.auxiliary_eqs.applyfunc(simplify_auxiliary_eqs)) Matrix([ [ -m*r*(u1*u3 + u2') + f1], [-m*r*u1**2*sin(q2) - m*r*u2*u3/cos(q2) + m*r*cos(q2)*u1' + f2], [ -g*m + m*r*(u1**2*cos(q2) + sin(q2)*u1') + f3]])

化简策略说明:

  1. factor_terms(w):提出公共因子;
  2. collect(..., f2)/collect(..., m*r):按约束力符号和质量×半径聚集同类项;
  3. trigsimp:利用三角恒等式化简sin/cos项;
  4. signsimp:规范化符号形式。

最终辅助方程为约束力 = 惯性项,解出三个分量:

  • 侧向约束力f1 = m·r·(u1·u3 + u̇2)
  • 滚动路径方向约束力f2 = m·r·u1²·sin(q2) + m·r·u2·u3/cos(q2) − m·r·cos(q2)·u̇1
  • 法向约束力f3 = g·m − m·r·(u1²·cos(q2) + sin(q2)·u̇1)

例如f3表达式中的−g·m + m·r·(u1²·cos(q2) + sin(q2)·u̇1)即为圆盘法向反力:当圆盘侧倾角q2与侧倾速率u1耦合时,法向反力会偏离重力m·g,这正是侧倾-自转耦合(类似陀螺效应)的体现。将上一节的u̇1代入即可得到纯关于(q2, u1, u2, u3)的显式约束力公式。

十一、源码级原理:辅助方程是如何生成的

从 kane.py 的实现可以看到完整的机制:

  1. KanesMethod.__init__接受u_auxiliary参数并存入self._uaux
  2. kanes_equations中,若存在辅助速度(if self._uaux:),会构造一个以辅助速度为主广义速度的临时KanesMethodkm = KanesMethod(self._inertial, self.q, self._uaux, u_auxiliary=self._uaux, ...),见 kane.py 第 842-854 行),并复用同样的力清单与刚体清单:
    fraux = km._form_fr(loads) frstaraux = km._form_frstar(bodies) self._aux_eq = fraux + frstaraux self._fr = fr.col_join(fraux) self._frstar = frstar.col_join(frstaraux)

    即:auxiliary_eqs = fraux + frstaraux(见 kane.py 第 855-861 行)。辅助广义速度在约束下恒为零,但其"名义速度"使得约束力在该方向上的广义力分量进入方程,从而可以被反解。

  3. auxiliary_eqs作为只读属性返回self._aux_eq(见 kane.py 第 909-915 行)。

同时kanes_equations的 docstring(见 kane.py 第 806-817 行)说明:设有s个辅助速度、o个广义速度、m个运动约束,返回向量的长度为o − m + s,前o − m个是约束后的 Kane 方程,后s个即辅助 Kane 方程。

十二、测试与验证:仓库中的对应用例

仓库测试目录对该功能有专门覆盖,可作为实现正确性的证据:

  • test_kane.py 第 220-259 行:在同一滚动圆盘系统上对比"手动引入 2 个辅助速度"与"使用内置u_auxiliary=[u4, u5]"两种方式,验证二者等价;
  • test_kane2.py:覆盖了同时含辅助速度、配置约束与非完整约束的复杂用例(第 47-49 行注释明确标注ua[0]/ua[1]/ua[2]为接触点三个方向的辅助广义速度),并断言auxiliary_eqs与手动推导一致;
  • test_lagrange.py、test_linearize.py 中的rollingdisc用例则验证了不同方法(Lagrange、线性化)对同一系统的结果一致性。

这些测试从侧面印证:本教程给出的建模流程(接触点引入辅助速度→同名约束力→u_auxiliary传入)是官方推荐且经过验证的标准做法。

十三、与其他建模方式的对比

同一物理系统在教程目录doc/src/tutorials/physics/mechanics/下有三种建模视角,入口见 rollingdisc_example.rst:

教程文件方法特点
rollingdisc_example_kane.rstKane(无约束力)3 坐标 + 3 速度,最简洁,只给运动方程
本文(kane_constraints)Kane + 辅助速度额外引入 3 个零速辅助速度与 3 个约束力,得到运动方程 + 约束力闭式解
rollingdisc_example_lagrange.rstLagrange从能量角度建模,可对照验证

三种方式对同一系统的运动学结果应当一致,互为交叉验证。

十四、使用注意事项小结

  1. 自动简化开关mechanics_printing(pretty_print=False)仅适合小规模问题,大系统建议关闭以避免向量运算挂起;
  2. 辅助速度方向选择:约束力分量必须与辅助速度方向一一对应(本教程为L.xcross(Y.z, L.x)Y.z),否则广义力投影会丢失对应分量;
  3. 辅助速度恒为零:它们只是"名义自由度",不出现在最终运动方程中,rhs结果与无约束版本一致可作为正确性检验;
  4. 约束力求解KM.auxiliary_eqs是求解约束力的唯一入口,通常需要配合factor_termscollecttrigsimp等化简手段(如教程中的simplify_auxiliary_eqs)才能得到可读的闭式表达式;
  5. 扩展阅读:完整可运行脚本位于教程目录 doc/src/tutorials/physics/mechanics/,KanesMethod的全部参数(含configuration_constraintsvelocity_constraintsu_dependent等)见 kane.py 的类 docstring(kane.py 第 60-99 行)。

结语

本教程完整展示了 SymPy 力学模块中"在 Kane 方法框架下显式求解非贡献约束力"的标准工程流程:通过u_auxiliary引入辅助广义速度、构造同名约束力分量、经kanes_equations获得常规运动方程与auxiliary_eqs辅助方程,再借助符号化简管线得到三个约束力的闭式表达式。该能力对需要同时进行动力学仿真与力/力矩分析的场景(如机器人足端力、车辆轮胎力等)具有直接实用价值。

【免费下载链接】sympyA computer algebra system written in pure Python项目地址: https://gitcode.com/GitHub_Trending/sy/sympy

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询