超越刚体#
Hello, Genesis World 教程仿真了一个刚体机器人。同一个 Scene 可以同时容纳水、沙、布料和软组织,因为 Genesis World 在一个场景下统一了多个物理求解器。求解器是推进某一类材料演化的一组算法;你为实体指定的材质决定了由哪个求解器来仿真它。
从下表中挑选一个求解器,然后按照其链接的示例获取完整脚本。
选择求解器#
每个实体都带有一个 material。在 Hello, Genesis World 中,材质默认为 gs.materials.Rigid(),因此由刚体求解器处理机械臂。指定另一类材料后,就会改由对应的求解器运行:
求解器 |
表示方式 |
适用场景 |
材质( |
|---|---|---|---|
MPM(物质点法) |
粒子与背景网格混合 |
在单个求解器中覆盖最广的连续介质材料:弹性体、塑性体、沙、雪 |
|
FEM(有限元法) |
四面体网格 |
精确的弹性与体积肌肉,适用于网格保真度要求高的场合 |
|
PBD(基于位置的动力学) |
粒子 + 约束 |
快速的布料、绳索以及保持拓扑的可变形体 |
|
SPH(光滑粒子流体动力学) |
粒子(拉格朗日) |
由真实流体参数驱动的自由表面液体 |
|
所有非刚体求解器的通用设置#
无论使用哪个求解器,相对于纯刚体场景都有三处变化。
1. 启用子步。 非刚体求解器的数值刚度较大,因此 Genesis World 会把每个 scene.step() 细分为若干子步。在 SimOptions 上设置较小的 dt(单位为秒)和子步数;内部的子步长为 dt / substeps。纯刚体场景会将 substeps 保留为默认值 1。
sim_options=gs.options.SimOptions(
dt=4e-3, # seconds
substeps=10, # substep_dt = 4e-4 s
)
2. 在场景上配置求解器。 每个求解器读取各自的选项对象:MPMOptions、SPHOptions、FEMOptions、PBDOptions。粒子-网格类求解器(MPM、SPH)需要仿真域,求解器会把超出 lower_bound/upper_bound(单位为米,Z 轴向上)的实体限制回该范围内。
mpm_options=gs.options.MPMOptions(
lower_bound=(-0.5, -1.0, 0.0), # meters
upper_bound=(0.5, 1.0, 1.0),
)
3. 设置材质及其渲染方式。 更换实体的 material 即可选择求解器,传入 surface 可以控制外观。vis_mode="particle" 绘制底层的粒子;vis_mode="visual" 则让原始网格跟随内部状态变形(计算机图形学中称为蒙皮)。
obj = scene.add_entity(
material=gs.materials.MPM.Elastic(),
morph=gs.morphs.Box(pos=(0.0, -0.5, 0.25), size=(0.2, 0.2, 0.2)),
surface=gs.surfaces.Default(color=(1.0, 0.4, 0.4), vis_mode="visual"),
)
MPM:可变形与颗粒材料#
物质点法将质量承载在粒子上,同时在背景网格上求解力,因此单个求解器就能覆盖弹性固体、塑性体、沙和雪。当场景需要同时表现多种连续介质行为,或需要一种先流动、随后保持变形后形状的材料时,请使用 MPM。
弹性立方体、液体立方体和弹塑性球体之间只有 material 不同:
scene.add_entity(material=gs.materials.MPM.Elastic(), ...)
scene.add_entity(material=gs.materials.MPM.Liquid(), ...)
scene.add_entity(material=gs.materials.MPM.ElastoPlastic(), ...)
FEM:精确的弹性与肌肉#
有限元法将实体离散为四面体网格,并在其上求解弹性方程。当网格级别的精度很重要时——例如刚度较高的弹性体、体积肌肉以及接触丰富的软体操作——应选择 FEM 而非 MPM。gs.materials.FEM.Elastic 直接暴露物理参数,例如杨氏模量 E(Pa)和泊松比 nu。
FEM 是 软体机器人教程 的基础,该教程驱动一块体积肌肉。FEM 实体还可以与刚体机械臂耦合以完成抓取;参见 examples/coupling/fem_cube_linked_with_arm.py。
PBD:布料与保持拓扑的可变形体#
基于位置的动力学将实体表示为通过约束连接的粒子,并直接求解位置,因此对于布料、绳索以及其他保持拓扑的 1D/2D/3D 物体来说既快速又稳定。gs.materials.PBD.Cloth 可将 2D 网格加载为布片。
构建完成后,你可以固定单个粒子。find_closest_particle 定位距离世界空间坐标点(单位:米)最近的粒子,fix_particles 则将其锚定:
scene.build()
# pin all four corners of the sheet in place
cloth.fix_particles(cloth.find_closest_particle((-1, -1, 1.0)))
cloth.fix_particles(cloth.find_closest_particle((1, 1, 1.0)))
完整脚本:examples/tutorials/pbd_cloth.py。
Warning
对平面 2D 布料网格使用 vis_mode="visual" 进行蒙皮时,可能产生退化的重心权重,表现为渲染畸变,尤其是在 euler 非零时。在问题解决之前,平面布片请使用 vis_mode="particle"。
SPH:自由表面液体#
光滑粒子流体动力学是一种纯拉格朗日(仅用粒子)的求解器,面向液体。当你希望流体由物理参数(静止密度 rho,单位 kg/m³;黏度 mu;表面张力 gamma)控制,而不是采用 MPM 提供的较粗糙的液体模型时,请使用 SPH。
把刚体方块变成水只需一行:为它指定 SPH 液体材质。通过其参数调节流动特性:
liquid = scene.add_entity(
material=gs.materials.SPH.Liquid(), # or Liquid(mu=0.02, gamma=0.02) for a thicker fluid
morph=gs.morphs.Box(pos=(0.0, 0.0, 0.65), size=(0.4, 0.4, 0.4)),
surface=gs.surfaces.Default(color=(0.4, 0.8, 1.0), vis_mode="particle"),
)
用 liquid.get_particles_pos() 读取实时粒子位置,它返回形状为 ([n_envs,] n_particles, 3) 的张量,单位为米。
完整脚本:examples/tutorials/sph_liquid.py。
Note
Liquid 材质接受一个 sampler 参数,用于控制粒子如何填充 morph:"regular"(网格晶格,SPH 为保证数值稳定性而采用的默认值)、"pbs"(基于物理的采样,会运行额外的步骤以获得自然的排列),或 "random"。
SF:气体现象(烟雾)#
Stable Fluid 求解器在固定的 3D 网格(欧拉方法)上工作:它平流一个速度场和一个或多个标量密度场,然后通过 Jacobi 压力投影使速度场无散度。用它来仿真烟雾和其他气体,并通过 SFOptions.res 设置网格分辨率。
SF 没有你可以添加和移动的拉格朗日实体:气体通过你在求解器上注册的速度射流进入,并且在至少存在一个射流之前,求解器保持不活动。每个子步都会平流速度场和密度场(使用三线性插值的 RK3 回溯),在射流处注入动量,然后运行 solver_iters 次 Jacobi 压力迭代以保持速度场无散度。状态保存在固定网格上,因此没有针对单个实体的 get/set 方法,SF 也不参与检查点。渲染时再把密度网格读回即可。
完整脚本(包括射流类以及将密度场写入图像):examples/fluid/smoke.py。
另请参阅#
软体机器人:驱动 MPM 和 FEM 肌肉。
混合实体:将刚体骨架与软体外皮耦合。
粒子发射器:向场景中持续注入 MPM、SPH 或 PBD 粒子。
求解器与耦合:求解器如何跨材料边界交换力。可运行的组合位于
examples/coupling,用于高刚度软体接触的 IPC 接触求解器位于examples/ipc。