BananaKick

1. 案例背景

这是一个基于 Sysplorer MCP 和 Modelica MultiBody 标准库实现的“世界杯主题香蕉球”教学案例。

案例目标不是复现真实比赛级空气动力学细节,而是用一个可运行、可动画展示、可参数化调节的 Modelica 工程,演示下面这类问题如何落地:

  • 如何把足球建成一个真正参与动力学计算的三维刚体,而不是简单动画球。
  • 如何把球门封装成一个独立的三维组件,而不是在顶层临时拼图。
  • 如何通过空气阻力和马格努斯力让足球在飞行中产生“香蕉球”式侧向弯曲。
  • 如何通过参数选择球门目标点,并让球稳定命中指定区域。

这个案例适合用来做:

  • Sysplorer + Modelica 物理建模入门演示。
  • MultiBody 三维动画建模示例。
  • 参数化轨迹控制与命中判断示例。
  • 足球香蕉球这一类“物理 + 可视化”小型案例教学。

2. 案例包含什么

工程主包为 BananaKick,结构如下:

BananaKick
├── Types
├── Functions
├── Components
└── Examples

其中:

  • Types:定义目标点枚举类型,例如球门中心、左右上角、左右下角。
  • Functions:负责目标点计算、瞄准点计算、初速度计算、初始旋转计算等。
  • Components:封装足球、球门、气动力、目标标记、场地。
  • Examples:给出默认参数化案例和若干目标点示例。

当前默认主案例是:

  • BananaKick.Examples.ParameterizedBananaKick

它负责装配:

  • 世界坐标系 World
  • 足球组件 FootballBody
  • 球门组件 GoalBody
  • 场地组件 PitchField
  • 目标点组件 TargetMarker
  • 气动力组件 AerodynamicForce
  • WorldForce
  • 位置、速度、角速度传感器
  • 命中判断逻辑

3. 关键知识点

这个案例覆盖的知识点主要有四类。

3.1 MultiBody 刚体建模

足球不是一个普通球形贴图,而是 FootballBody 中的刚体对象。它需要同时满足:

  • 具有质量、半径、转动惯量。
  • 可以设置初始位置、初始速度、初始角速度。
  • 可以连接 WorldForce,接受外力作用。
  • 可以在三维动画中可见。

这部分适合理解:

  • Modelica.Mechanics.MultiBody.Parts.BodyShape
  • 刚体初值设置
  • 三维可视化与物理实体的一致性

3.2 独立球门组件封装

球门被封装在 GoalBody 中,而不是在顶层模型里直接堆多个图形。这样做的好处是:

  • 结构清晰,便于复用。
  • 球门位置只需要通过 goalCenter 统一控制。
  • 三维动画对象和物理装配关系一致。

这部分适合理解:

  • Modelica.Mechanics.MultiBody.Visualizers.FixedShape
  • Modelica.Mechanics.MultiBody.Parts.FixedTranslation
  • 局部坐标系下的相对布置

3.3 香蕉球空气动力学

香蕉球效果来自两个部分:

  • 空气阻力 F_drag
  • 马格努斯力 F_magnus

本案例采用教学型简化模型,核心思想是:

  • 根据足球速度计算空气阻力。
  • 根据足球自旋方向和飞行方向计算侧向偏转趋势。
  • 通过 WorldForce 把气动力真正施加到足球 frame 上,而不是直接“改轨迹”。

这部分适合理解:

  • 阻力与速度的关系
  • 自旋与侧向偏转的关系
  • 为什么香蕉球效果应该由外力产生,而不是由动画伪造

3.4 参数化命中控制

案例支持通过参数选择目标区域,例如:

  • Center
  • LeftTop
  • LeftBottom
  • RightTop
  • RightBottom

然后通过下面这组参数控制轨迹:

  • shotSpeed
  • curveOffset
  • sideSpinAbs
  • liftSpin
  • Cd
  • kMagnus

案例里还会输出:

  • reachedGoalPlane
  • insideGoal
  • hitTarget
  • missDistance

这部分适合理解:

  • 目标点驱动的轨迹生成
  • 目标命中判定
  • 参数调优如何影响结果

4. 当前默认效果

默认示例当前做的是一个 20 米距离的弧线射门,目标点为球门右上区域。

当前版本的弧线方向已经调整为:

  • 足球先向目标外侧偏出去;
  • 然后在接近球门时再回拉;
  • 最终命中指定目标区域。

这类轨迹更接近常见“外脚背兜回门内”的视觉效果。

5. 这个案例是怎么开发出来的

可以把开发过程理解为五步。

第一步:先确定工程结构

先把案例拆成四层:

  • 类型层
  • 函数层
  • 组件层
  • 示例层

这样做的目的是避免把所有逻辑都写进一个顶层模型里,后期调参、改动画或换目标点时会更稳定。

第二步:先做可见的三维对象

先保证三维动画里能看到:

  • 足球
  • 球门
  • 目标点
  • 场地

如果这一层没有搭好,后面即使仿真通过,用户也很难直观看懂案例。

第三步:再接入传感器和气动力

足球飞行状态需要通过传感器拿到:

  • 位置
  • 速度
  • 角速度

然后把这些量送入 AerodynamicForce,再通过 WorldForce 把力作用到足球 frame。

第四步:建立目标点和命中判断

先计算目标点,再根据目标点生成:

  • 瞄准点
  • 初速度
  • 初始自旋

最后在足球到达球门平面时记录位置,并判断:

  • 是否进门
  • 是否命中目标
  • 偏差距离是多少

第五步:反复调参和验证

这一步是案例能否“好看且能命中”的关键。

主要需要反复调的参数是:

  • curveOffset
  • sideSpinAbs
  • kMagnus
  • shotSpeed
  • 初始高度修正

调参方式不是拍脑袋,而是看球门平面交点与目标点之间的偏差,再往回调。

6. 如何快速运行这个案例

推荐直接打开并运行:

  • BananaKick.Examples.ParameterizedBananaKick

建议关注三类结果:

  1. 三维动画里是否能清楚看到足球、球门、目标点和场地。
  2. 足球轨迹是否先向目标外侧偏出,再回到球门目标位置。
  3. 仿真输出里 hitTargetinsideGoalmissDistance 是否符合预期。

如果只是想快速切换射门区域,可以直接修改:

  • target

如果想调弧线强弱,可以优先修改:

  • curveOffset
  • sideSpinAbs
  • kMagnus

如果想调飞行高低,可以优先修改:

  • shotSpeed
  • liftSpin
  • 初始速度函数中的高度修正

7. 适合谁看

这个案例适合下面几类用户:

  • 刚开始接触 Sysplorer/Modelica 三维物理建模的人。
  • 想找一个完整小案例学习 MultiBody 建模方法的人。
  • 想做“物理效果 + 动画可视化 + 参数调优”一体化示例的人。
  • 想把一个抽象空气动力学效果包装成可展示教学案例的人。

8. 进一步扩展方向

如果后续要继续扩展,这个案例可以往下面几个方向发展:

  • 增加不同踢法,例如内脚背、外脚背、贴地斩。
  • 给不同目标点做独立参数集,而不是共用一套默认参数。
  • 引入更细的旋转衰减或升力模型。
  • 增加命中门柱、擦网、越过横梁等判定。
  • 增加批量参数扫描,自动寻找更稳定的命中参数。

如果你是第一次接触这个工程,建议先跑 ParameterizedBananaKick,再回头看 FunctionsComponents,理解“目标点 -> 瞄准点 -> 初速度/自旋 -> 气动力 -> 命中判断”这条主线。