rl_测试液体相关以及离心机放置试管v1

This commit is contained in:
2026-03-04 10:09:44 +08:00
parent 9325184f4d
commit a9cef174f5
23 changed files with 2654 additions and 33 deletions

129
create_liquid.py Normal file
View File

@@ -0,0 +1,129 @@
import omni.isaac.core.utils.prims as prim_utils
from omni.isaac.core.simulation_context import SimulationContext
from omni.isaac.core.utils.stage import get_current_stage
from pxr import UsdGeom, UsdPhysics, PhysxSchema, Gf, Sdf
# 引入 PhysX 粒子工具 (Omniverse 内置库)
import omni.physx.scripts.utils as physxUtils
import omni.physx.scripts.particleUtils as particleUtils
def create_fluid_scene():
stage = get_current_stage()
# 1. 初始化仿真环境
sim = SimulationContext()
# 确保物理频率适合流体 (流体通常需要更小的步长或更多的子步)
sim.set_simulation_dt(physics_dt=1.0 / 60.0, rendering_dt=1.0 / 60.0)
# 2. 创建粒子系统 (Particle System)
# 这是管理所有流体粒子的容器
particle_system_path = "/World/FluidSystem"
particleUtils.add_physx_particle_system(
stage=stage,
particle_system_path=particle_system_path,
simulation_owner=None,
radius=0.02, # 粒子半径(决定流体分辨率)
contact_offset=0.03,
solid_rest_offset=0.02,
fluid_rest_offset=0.02,
mode="fluid" # 设置为流体模式
)
# 3. 创建流体材质 (定义粘度)
# 对于像蜂蜜或洗发水这样的"带流性"液体,需要高粘度
material_path = "/World/FluidMaterial"
particleUtils.add_pbd_particle_material(
stage=stage,
path=material_path,
cohesion=0.02, # 内聚力 (让液体聚在一起)
viscosity=0.5, # 粘度 (关键参数:数值越大越粘稠,如蜂蜜)
surface_tension=0.01, # 表面张力
friction=0.1, # 粒子间摩擦
damping=0.1 # 阻尼
)
# 4. 创建流体几何体 (在试管初始位置生成一堆粒子)
# 假设我们在 (0, 0, 0.5) 的位置生成一团液体
fluid_path = "/World/Liquid"
# 使用网格采样创建粒子点集
particleUtils.add_physx_particleset_pointinstancer(
stage=stage,
path=fluid_path,
particle_system_path=particle_system_path,
self_collision=True,
fluid=True,
particle_group=0,
particle_mass=0.001,
density=1000.0 # 水的密度
)
# 这里的关键是将材质绑定到几何体
physxUtils.add_physics_material_to_prim(stage, stage.GetPrimAtPath(fluid_path), material_path)
# 这里的逻辑通常需要编写一个简单的生成器,在空间中填满粒子
# 为了演示简单,我们假设通过 create_grid_particles 生成位置
# 在实际 Isaac Lab 中,你通常会加载一个预先保存好的带粒子的 USD或者使用 SamplingAPI
points = []
for x in range(5):
for y in range(5):
for z in range(10):
points.append(Gf.Vec3f(x*0.04, y*0.04, 0.5 + z*0.04))
# 将坐标赋予粒子系统
points_attr = stage.GetPrimAtPath(fluid_path).GetAttribute("positions")
points_attr.Set(points)
# 5. 创建容器 (烧杯和试管)
# 这里使用简单的圆柱管演示,实际应用需加载 .usd 模型
# 烧杯 (底部接收)
beaker_path = "/World/Beaker"
prim_utils.create_cyl(
prim_path=beaker_path,
radius=0.15,
height=0.2,
position=Gf.Vec3d(0, 0, 0.1)
)
# 注意PrimUtils创建的是实心凸包流体进不去。
# 关键步骤:必须将容器碰撞改为 Mesh (SDF) 或手动用多个面拼成空心杯子。
# 在代码中通常加载自定义 USD 资产,这里仅做说明:
# setup_concave_collision(beaker_path)
# 试管 (上方倒水)
tube_path = "/World/TestTube"
tube = prim_utils.create_cyl(
prim_path=tube_path,
radius=0.05,
height=0.2,
position=Gf.Vec3d(0.2, 0, 0.6) # 位于烧杯上方侧面
)
# 为试管添加刚体属性以便旋转
physxUtils.set_rigid_body_properties(stage, tube_path)
return sim, tube_path
def run_simulation(sim, tube_path):
# 6. 开始循环并执行“倒水”动作
sim.initialize_physics()
sim.play()
stage = get_current_stage()
tube_prim = stage.GetPrimAtPath(tube_path)
xform = UsdGeom.Xformable(tube_prim)
# 模拟 500 帧
for i in range(500):
# 简单的运动学控制:慢慢旋转试管
if i < 200:
# 旋转以倒出液体 (欧拉角或四元数)
rotation = Gf.Rotation(Gf.Vec3d(0, 1, 0), i * 0.5) # 绕Y轴旋转
# 注意:实际代码需处理完整的 Transform 设置
current_xform = xform.GetLocalTransformation()
# 这里简化处理,直接更新姿态逻辑需根据具体场景编写
sim.step()
# 执行
if __name__ == "__main__":
sim, tube = create_fluid_scene()
run_simulation(sim, tube)