I am getting this error:
I do not need the hand, but I need the particle physics for simulating fluids.
But I checked the flag, and I already enable the GPU dynamics flag through:
self._my_world._physics_context.enable_gpu_dynamics(flag=True)
log:
[omni.physx.plugin] Particle feature is only supported on GPU. Please enable GPU dynamics flag in Property/Scene of physics scene!
import os
from copy import copy
import math
import carb
import numpy as np
import gym
from gym import spaces
import signal
import time
import omni
from omni.isaac.kit import SimulationApp
app = SimulationApp({“headless”: False, “anti_aliasing”: 0})
from pxr import UsdGeom, UsdLux, Gf, Vt, UsdPhysics, PhysxSchema, Usd, UsdShade, Sdf
from schemaHelpers import (
addPhysxParticleSystem,
PhysxParticleInstancePrototype,
addPhysxParticlesSimple,
add_deformable_to_rigid_body_attachment,
)
from omni.physx.scripts import physicsUtils
def calculate_filter_alpha(half_life_seconds: float, sampling_rate: float):
N = half_life_seconds * sampling_rate
return 0.5 ** (1.0 / N)
class FluidScene(gym.Env):
metadata = {“render.modes”: [“human”]}
def __init__(self,
skip_frame=1,
physics_dt=1.0 / 60.0,
rendering_dt=1.0 / 60.0,
max_episode_length=1000,
seed=0,
headless=False,
simulaton_App = None) -> None:
self.headless = headless
self._simulation_app = simulaton_App
self._skip_frame = skip_frame
self._dt = physics_dt * self._skip_frame
self._max_episode_length = max_episode_length
self._steps_after_reset = int(rendering_dt / physics_dt)
from omni.isaac.core import World
self._my_world = World(physics_dt=physics_dt, rendering_dt=rendering_dt, stage_units_in_meters=0.01)
# self._my_world.scene.add_default_ground_plane()
self.seed(seed)
self.sd_helper = None
self.viewport_window = None
self._set_camera()
self.reward_range = (-float("inf"), float("inf"))
gym.Env.__init__(self)
self.action_space = spaces.Box(low=-0.05, high=0.05, shape=(9,), dtype=np.float32)
self.observation_space = spaces.Box(low=0, high=255, shape=(256, 256, 3), dtype=np.uint8)
from pxr import UsdGeom, UsdLux, Gf, Vt, UsdPhysics, PhysxSchema, Usd, UsdShade, Sdf
import omni.physx
from omni.physx.scripts import utils
# from schemaHelpers import (
# addPhysxParticleSystem,
# PhysxParticleInstancePrototype,
# addPhysxParticlesSimple,
# add_deformable_to_rigid_body_attachment,
# )
# SIM:
self._solver = "TGS"
self._gpuMaxNumPartitions = 4
self._gravityMagnitude = 100.0 # IN CM/s2 - use a lower gravity to avoid fluid compression at 60 FPS
self._gravityDirection = Gf.Vec3f(0.0, -1.0, 0.0)
# viewer:
self._viewerPosition = Gf.Vec3d(47.6, 25.3, 56.2)
self._viewerTarget = Gf.Vec3d(-21.17, 6.93, -33.26)
# material - applies to bones and sphere to be gripped if set to RB
# and ground plane
self._material_static_friction = 1.0
self._material_dynamic_friction = 1.0
self._material_restitution = 0.0
# masses:
self._mugMass = 0.1
self._boneMass = 0.1
self._particleMass = 0.5e-5
# Rate limiter and low-pass sensor input parameters:
self._revoluteAngleScale = 1.0
self._thumbAngleScale = 2.0
# solver parameters:
self._solverPositionIterations = 10
self._solverVelocityIterations = 0
# Articulation and RB parameters:
self._boneRestOffset = 0.0
self._boneContactOffset = 0.1
# Mug parameters
self._mugRestOffset = 0.0
self._mugContactOffset = 1.0
# SB and fluid:
self._sb_tips_schema_parameters = {
"youngsModulus": 1.0e5,
"poissonsRatio": 0.3,
"dampingScale": 1.0,
"dynamicFriction": 1.0,
"solver_position_iteration_count": self._solverPositionIterations,
"mass": 0.01,
"collisionRestOffset": 0.00001,
"collisionContactOffset": 0.5,
"self_collision": False,
"vertex_velocity_damping": 0.005,
"sleep_damping": 0.001, # disable
"sleep_threshold": 0.001, # disable
"settling_threshold": 0.001, # disable
}
self._sb_tips_resolution = 8
self._fluidSphereDiameter = 0.24
self._fluidCylinderHeight = 6.0
self._fluidCylinderRadius = 3.0
self._particleSystemSchemaParameters = {
"contact_offset": 0.3,
"particle_contact_offset": 0.25,
"rest_offset": 0.25,
"solid_rest_offset": 0,
"fluid_rest_offset": 0.5 * self._fluidSphereDiameter + 0.03,
"solver_position_iterations": self._solverPositionIterations,
"solver_velocity_iterations": self._solverVelocityIterations,
"wind": Gf.Vec3f(0, 0, 0),
}
self._particleSystemAttributes = {
"cohesion": 0.74,
"smoothing": 0.8,
"anisotropyScale": 1.0,
"anisotropyMin": 0.2,
"anisotropyMax": 2.0,
"surfaceTension": 0.74,
"vorticityConfinement": 0.5,
"viscosity": 5.0,
"particleFriction": 0.34,
}
# asset paths:
self._assetFiles = {
# "Motion": "/data/skeleton_hand_mocap_data.npy",
# "Hand": "/data/skeleton_hand_with_tips.usd",
"Mug": "/data/skeleton_hand_mug.usd"
}
# motion playback setup
self._time = 0
self._recordFrameNumber = 0
self._playBackDataLength = 0
self._recordData = None
self._paused = False
# driving and dofs
self._drives = []
self._driveGuards = []
self._numDofs = 0
self._thumbIndices = []
self._stage = omni.usd.get_context().get_stage()
# self._my_world = World(physics_dt=physics_dt, rendering_dt=rendering_dt, stage_units_in_meters=0.01)
# self._my_world.scene.add_default_ground_plane()
prim = self._stage.DefinePrim('/World', 'Xform')
self._stage.SetDefaultPrim(prim)
self.create(self._stage, True)
return
def step(self):
self._my_world.step(render=True)
def _set_camera(self):
import omni.kit
from omni.isaac.synthetic_utils import SyntheticDataHelper
camera_path = ""
# camera_path = "/World/Franka/Camera"
# camera_path = "/World/Franka/panda_hand/Camera"
if self.headless:
viewport_handle = omni.kit.viewport.get_viewport_interface()
viewport_handle.get_viewport_window().set_active_camera(str(camera_path))
viewport_window = viewport_handle.get_viewport_window()
self.viewport_window = viewport_window
viewport_window.set_texture_resolution(256, 256)
else:
viewport_handle = omni.kit.viewport.get_viewport_interface().create_instance()
new_viewport_name = omni.kit.viewport.get_viewport_interface().get_viewport_window_name(viewport_handle)
viewport_window = omni.kit.viewport.get_viewport_interface().get_viewport_window(viewport_handle)
viewport_window.set_active_camera(camera_path)
viewport_window.set_texture_resolution(256, 256)
viewport_window.set_window_pos(1000, 400)
viewport_window.set_window_size(420, 420)
self.viewport_window = viewport_window
self.sd_helper = SyntheticDataHelper()
self.sd_helper.initialize(sensor_names=["rgb"], viewport=self.viewport_window)
self._my_world.render()
# self.sd_helper.get_groundtruth(["rgb"], self.viewport_window)
return
def generate_fluid_particles(
self,
particleInstanceStr: str,
particleSystemPath: str,
lowerCenter, # Gf.Vec3f,
h: float,
radius: float,
):
from pxr import UsdGeom, UsdLux, Gf, Vt, UsdPhysics, PhysxSchema, Usd, UsdShade, Sdf
# from schemaHelpers import (
# addPhysxParticleSystem,
# PhysxParticleInstancePrototype,
# addPhysxParticlesSimple,
# add_deformable_to_rigid_body_attachment,
# )
stage = self._stage
# Simple Particle
# particleInstanceStr = "/particlesInstance" + str(i)
particleInstancePath = Sdf.Path(particleInstanceStr)
proto = PhysxParticleInstancePrototype()
proto.selfCollision = True
proto.fluid = True
proto.collisionGroup = 0
proto.mass = self._particleMass
protoArray = [proto]
positions_list = []
velocities_list = []
protoIndices_list = []
particle_rest_offset = self._particleSystemSchemaParameters["fluid_rest_offset"]
positions_list = self.generate_cylinder_y(lowerCenter, h, radius, particle_rest_offset * 2.0)
print("position list length", len(positions_list))
for _ in range(len(positions_list)):
velocities_list.append(Gf.Vec3f(0, 0, 0))
protoIndices_list.append(0)
protoIndices = Vt.IntArray(protoIndices_list)
positions = Vt.Vec3fArray(positions_list)
velocities = Vt.Vec3fArray(velocities_list)
addPhysxParticlesSimple(
stage, particleInstancePath, protoArray, protoIndices, positions, velocities, particleSystemPath
)
# Set color
color_rgb = [0.0, 0.0, 0.0]
color_rgb[2] = 1.0
color = Vt.Vec3fArray([Gf.Vec3f(color_rgb[0], color_rgb[1], color_rgb[2])])
colorPathStr = particleInstanceStr + "/particlePrototype0"
gprim = UsdGeom.Sphere.Define(stage, Sdf.Path(colorPathStr))
gprim.CreateDisplayColorAttr(color)
# enable anisotropy
# usdPrim = stage.GetPrimAtPath(particleInstancePath)
usdPrim = stage.GetPrimAtPath(colorPathStr)
usdPrim.CreateAttribute("enableAnisotropy", Sdf.ValueTypeNames.Bool, True).Set(True)
usdPrim.CreateAttribute("radius", Sdf.ValueTypeNames.Double, True).Set(0.3)
# scale = Gf.Vec3f(radius, radius, radius)
# gprim.AddScaleOp().Set(scale)
gprim.GetRadiusAttr().Set(self._fluidSphereDiameter)
# FIXME:DEBUG
# make sure scales and orientations are authored
pprim = stage.GetPrimAtPath(particleInstanceStr)
pprim.GetAttribute("scales").Set([(0.5, 0.5, 0.5) for i in range(len(positions_list))])
pprim.GetAttribute("orientations").Set([Gf.Quath(0.8660254, 0.0, 0.0, 0.5) for i in range(len(positions_list))])
# def _setup_callbacks(self):
# # callbacks
# self._timeline = omni.timeline.get_timeline_interface()
# stream = self._timeline.get_timeline_event_stream()
# self._timeline_subscription = stream.create_subscription_to_pop(self._on_timeline_event)
# # subscribe to Physics updates:
# self._physics_update_subscription = omni.physx.get_physx_interface().subscribe_physics_step_events(
# self.on_physics_step
# )
def _setup_callbacks(self):
# callbacks
self._timeline = omni.timeline.get_timeline_interface()
stream = self._timeline.get_timeline_event_stream()
self._timeline_subscription = stream.create_subscription_to_pop(self._on_timeline_event)
# subscribe to Physics updates:
self._physics_update_subscription = omni.physx.get_physx_interface().subscribe_physics_step_events(
self.on_physics_step
)
def on_physics_step(self, dt):
self._time += 1
def _deregister_callbacks(self):
self._timeline_subscription = None
self._physics_update_subscription = None
def _on_timeline_event(self, e):
if e.type == int(omni.timeline.TimelineEventType.PLAY):
if not self._paused:
self._time = 0
self._recordFrameNumber = 0
self._paused = False
elif e.type == int(omni.timeline.TimelineEventType.PAUSE):
self._paused = True
elif e.type == int(omni.timeline.TimelineEventType.STOP):
self._paused = False
def create_particle_system(self, particleSystemStr: str, scenePathStr: str):
stage = self._stage
particleSystemPath = Sdf.Path(particleSystemStr)
addPhysxParticleSystem(
stage, particleSystemPath, **self._particleSystemSchemaParameters, scenePath=Sdf.Path(scenePathStr)
)
particleSystem = stage.GetPrimAtPath(particleSystemPath)
for key, value in self._particleSystemAttributes.items():
particleSystem.GetAttribute(key).Set(value)
def assign_collision_group(self, primPath: Sdf.Path, groupPath: Sdf.Path):
stage = self._stage
physicsUtils.add_collision_to_collision_group(stage, primPath, groupPath)
# Generates hexagonal close packed samples inside an axis aligned bounding box
@staticmethod
def generate_hcp_samples(boxMin: Gf.Vec3f, boxMax: Gf.Vec3f, sphereDiameter: float):
layerDistance = math.sqrt(2.0 / 3.0) * sphereDiameter
rowShift = math.sqrt(3.0) / 2.0 * sphereDiameter
result = []
layer1Offset = (1.0 / 3.0) * (
Gf.Vec2f(0, 0) + Gf.Vec2f(0.5 * sphereDiameter, rowShift) + Gf.Vec2f(sphereDiameter, 0)
)
zIndex = 0
while True:
z = boxMin[2] + zIndex * layerDistance
if z > boxMax[2]:
break
yOffset = layer1Offset[1] if zIndex % 2 == 1 else 0
yIndex = 0
while True:
y = boxMin[1] + yIndex * rowShift + yOffset
if y > boxMax[1]:
break
xOffset = 0
if zIndex % 2 == 1:
xOffset += layer1Offset[0]
if yIndex % 2 == 1:
xOffset -= 0.5 * sphereDiameter
elif yIndex % 2 == 1:
xOffset += 0.5 * sphereDiameter
xIndex = 0
while True:
x = boxMin[0] + xIndex * sphereDiameter + xOffset
if x > boxMax[0]:
break
result.append(Gf.Vec3f(x, y, z))
xIndex += 1
yIndex += 1
zIndex += 1
return result
def generate_cylinder_y(self, lowerCenter, h: float, radius: float, sphereDiameter: float):
from pxr import UsdGeom, UsdLux, Gf, Vt, UsdPhysics, PhysxSchema, Usd, UsdShade, Sdf
samples = self.generate_hcp_samples(Gf.Vec3f(-radius, 0, -radius), Gf.Vec3f(radius, h, radius), sphereDiameter)
finalSamples = []
for p in samples:
r2 = p[0] * p[0] + p[2] * p[2]
if r2 <= radius * radius:
finalSamples.append(p + lowerCenter)
return finalSamples
def _get_asset_path(self, assetString: str) -> str:
data_folder = os.path.normpath(os.path.dirname(os.path.abspath(__file__)))
return os.path.normpath(
data_folder
+ self._assetFiles[assetString]
)
def _set_kit_physics_and_render_parameters(self):
from omni.physx.bindings._physx import (
SETTING_UPDATE_TO_USD,
SETTING_UPDATE_VELOCITIES_TO_USD,
SETTING_NUM_THREADS,
)
isregistry = carb.settings.acquire_settings_interface()
# disable grid and lights
dOptions = isregistry.get_as_int("persistent/app/viewport/displayOptions")
dOptions &= ~(1 << 6 | 1 << 8)
self._display_options = isregistry.get_as_int("persistent/app/viewport/displayOptions")
isregistry.set_int("persistent/app/viewport/displayOptions", dOptions)
self._update_to_usd = isregistry.get_as_bool(SETTING_UPDATE_TO_USD)
isregistry.set_bool(SETTING_UPDATE_TO_USD, True)
self._num_threads = isregistry.get_as_int(SETTING_NUM_THREADS)
isregistry.set_int(SETTING_NUM_THREADS, 8)
self._update_velocities = isregistry.get_as_bool(SETTING_UPDATE_VELOCITIES_TO_USD)
isregistry.set_bool(SETTING_UPDATE_VELOCITIES_TO_USD, False)
self._min_frame_rate = isregistry.get_as_int("persistent/simulation/minFrameRate")
isregistry.set_int("persistent/simulation/minFrameRate", 60)
self._post_aa_op = isregistry.get_as_int("rtx-defaults/post/aa/op")
isregistry.set_int("rtx-defaults/post/aa/op", 3)
self._max_refraction_bounces = isregistry.get_as_int("rtx-defaults/translucency/maxRefractionBounces")
isregistry.set_int("rtx-defaults/translucency/maxRefractionBounces", 6)
self._exec_mode = isregistry.get_as_int("rtx-defaults/post/dlss/execMode")
isregistry.set_int("rtx-defaults/post/dlss/execMode", 1)
def close(self):
self._simulation_app.close()
return
def _setup_rb_collision_parameters(self, prim, restOffset, contactOffset):
from pxr import UsdGeom, UsdLux, Gf, Vt, UsdPhysics, PhysxSchema, Usd, UsdShade, Sdf
physxCollisionAPI = PhysxSchema.PhysxCollisionAPI.Get(self._stage, prim.GetPath())
if not physxCollisionAPI:
physxCollisionAPI = PhysxSchema.PhysxCollisionAPI.Apply(prim)
self._setup_physics_material(prim.GetPath())
assert physxCollisionAPI.GetRestOffsetAttr().Set(restOffset)
assert physxCollisionAPI.GetContactOffsetAttr().Set(contactOffset)
assert prim.CreateAttribute("physxMeshCollision:minThickness", Sdf.ValueTypeNames.Float).Set(0.001)
def transform_mesh(self, mesh, loc, orient=Gf.Quatf(1.0), scale=Gf.Vec3d(1.0, 1.0, 1.0)):
for op in mesh.GetOrderedXformOps():
if op.GetOpType() == UsdGeom.XformOp.TypeTranslate:
op.Set(loc)
if op.GetOpType() == UsdGeom.XformOp.TypeOrient:
op.Set(orient)
if op.GetOpType() == UsdGeom.XformOp.TypeScale:
op.Set(scale)
def _setup_physics_material(self, path):
# def _setup_physics_material(self, path: Sdf.Path):
from pxr import UsdGeom, UsdLux, Gf, Vt, UsdPhysics, PhysxSchema, Usd, UsdShade, Sdf
if self._physicsMaterialPath is None:
self._physicsMaterialPath = self._stage.GetDefaultPrim().GetPath().AppendChild("physicsMaterial")
UsdShade.Material.Define(self._stage, self._physicsMaterialPath)
material = UsdPhysics.MaterialAPI.Apply(self._stage.GetPrimAtPath(self._physicsMaterialPath))
material.CreateStaticFrictionAttr().Set(self._material_static_friction)
material.CreateDynamicFrictionAttr().Set(self._material_dynamic_friction)
material.CreateRestitutionAttr().Set(self._material_restitution)
collisionAPI = UsdPhysics.CollisionAPI.Get(self._stage, path)
prim = self._stage.GetPrimAtPath(path)
if not collisionAPI:
collisionAPI = UsdPhysics.CollisionAPI.Apply(prim)
# apply material
physicsUtils.add_physics_material_to_prim(self._stage, prim, self._physicsMaterialPath)
@staticmethod
def get_quat_from_extrinsic_xyz_rotation(angleXrad: float = 0.0, angleYrad: float = 0.0, angleZrad: float = 0.0):
# angles are in radians
rotX = FluidScene.rotate_around_axis(1, 0, 0, angleXrad)
rotY = FluidScene.rotate_around_axis(0, 1, 0, angleYrad)
rotZ = FluidScene.rotate_around_axis(0, 0, 1, angleZrad)
return rotZ * rotY * rotX
@staticmethod
def rotate_around_axis(x, y, z, angle):
s = math.sin(0.5 * angle)
return Gf.Quatf(math.cos(0.5 * angle), s * x, s * y, s * z)
def _setup_geometry(self):
boneNames = ["proximal", "middle", "distal"]
self._jointGeometry = {}
self._tableRestOffset = 0.005
self._handVerticalOffset = -74
self._handPosOffset = Gf.Vec3f(0.0, -10, 0.0)
self._handInitPos = Gf.Vec3f(0.0, 20.0, 0.0)
self._mugInitPos = Gf.Vec3f(10, self._mugRestOffset, 0)
self._mugInitRot = self.get_quat_from_extrinsic_xyz_rotation(angleYrad=-0.7 * math.pi)
self._fluidPositionOffset = Gf.Vec3f(0, 1.05, 0)
scale = 1.1
self._mugScale = Gf.Vec3f(scale)
self._mugOffset = Gf.Vec3f(0, 0, 15) * scale
revoluteLimits = (-20, 120)
# Thumb:
# metacarpal = JointGeometry()
# metacarpal.bbCenterWeight = 0.67
# metacarpal.posOffsetW = Gf.Vec3d(-1.276, 0.28, 0.233)
# this quaternion is the joint pose in the inertial coordinate system
# and will be converted to the bone frame in the joint rigging
# angleY = -0.45
# angleZ = -0.5
# quat = self.get_quat_from_extrinsic_xyz_rotation(angleYrad=angleY, angleZrad=angleZ)
# metacarpal.quat = quat # first y then z, extrinsic
# metacarpal.type = "spherical"
# metacarpal.axis = "X"
# metacarpal.limits = (90, 90)
# metacarpal.defaultDriveAngles["rotY"] = angleY
# metacarpal.defaultDriveAngles["rotZ"] = angleZ
# proximal = JointGeometry()
# proximal.bbCenterWeight = 0.67
# proximal.quat = quat
# proximal.axis = "Y"
# proximal.limits = revoluteLimits
# distal = copy(proximal)
# distal.bbCenterWeight = 0.55
# self._jointGeometry["Thumb"] = {
# "metacarpal": copy(metacarpal),
# "proximal": copy(proximal),
# "distal": copy(distal),
# }
# sphericalLimits = (60, 90)
# Index:
# proximal = JointGeometry()
# proximal.bbCenterWeight = 0.67
# proximal.quat = Gf.Quatf(1.0)
# proximal.type = "spherical"
# proximal.axis = "X"
# proximal.limits = sphericalLimits
# middle = JointGeometry()
# middle.bbCenterWeight = 0.67
# xAngleRad = 5.0 * math.pi / 180.0
# middle.quat = self.get_quat_from_extrinsic_xyz_rotation(angleXrad=xAngleRad)
# middle.axis = "Z"
# middle.limits = revoluteLimits
# distal = copy(middle)
# distal.bbCenterWeight = 0.55
# geoms = [copy(g) for g in [proximal, middle, distal]]
# self._jointGeometry["Index"] = dict(zip(boneNames, geoms))
# middle:
# proximal = JointGeometry()
# proximal.bbCenterWeight = 0.67
# proximal.quat = Gf.Quatf(1.0)
# proximal.type = "spherical"
# proximal.limits = sphericalLimits
# proximal.axis = "X"
# middle = JointGeometry()
# middle.bbCenterWeight = 0.67
# middle.quat = Gf.Quatf(1.0)
# middle.axis = "Z"
# middle.limits = revoluteLimits
# distal = copy(middle)
# distal.bbCenterWeight = 0.55
# geoms = [copy(g) for g in [proximal, middle, distal]]
# self._jointGeometry["Middle"] = dict(zip(boneNames, geoms))
# ring:
# proximal = JointGeometry()
# proximal.bbCenterWeight = 0.67
# proximal.quat = Gf.Quatf(1.0)
# proximal.type = "spherical"
# proximal.limits = sphericalLimits
# proximal.axis = "X"
# middle = JointGeometry()
# middle.bbCenterWeight = 0.6
# middle.quat = Gf.Quatf(1.0)
# middle.limits = revoluteLimits
# xAngleRad = -5.0 * math.pi / 180.0
# middle.quat = self.get_quat_from_extrinsic_xyz_rotation(angleXrad=xAngleRad)
# middle.axis = "Z"
# distal = copy(middle)
# distal.bbCenterWeight = 0.55
# geoms = [copy(g) for g in [proximal, middle, distal]]
# self._jointGeometry["Ring"] = dict(zip(boneNames, geoms))
# pinky:
# proximal = JointGeometry()
# proximal.bbCenterWeight = 0.67
# yAngleRad = 8.0 * math.pi / 180.0
# proximal.quat = self.get_quat_from_extrinsic_xyz_rotation(angleXrad=xAngleRad, angleYrad=yAngleRad)
# proximal.type = "spherical"
# proximal.limits = sphericalLimits
# proximal.axis = "X"
# proximal.defaultDriveAngles["rotY"] = yAngleRad
# middle = JointGeometry()
# middle.bbCenterWeight = 0.67
# middle.quat = Gf.Quatf(1.0)
# middle.limits = revoluteLimits
# middle.axis = "Z"
# yAngleRad = 8.0 * math.pi / 180.0
# xAngleRad = -5.0 * math.pi / 180.0
# middle.quat = self.get_quat_from_extrinsic_xyz_rotation(angleXrad=xAngleRad, angleYrad=yAngleRad)
# distal = copy(middle)
# distal.bbCenterWeight = 0.55
# geoms = [copy(g) for g in [proximal, middle, distal]]
# self._jointGeometry["Pinky"] = dict(zip(boneNames, geoms))
def _apply_mass(self, mesh: UsdGeom.Mesh, mass: float):
massAPI = UsdPhysics.MassAPI.Apply(mesh.GetPrim())
massAPI.GetMassAttr().Set(mass)
def create(self, stage, Enable_Fluid):
from pxr import UsdGeom, UsdLux, Gf, Vt, UsdPhysics, PhysxSchema, Usd, UsdShade, Sdf
from omni.physx.scripts import utils
self._set_kit_physics_and_render_parameters()
# add base scene
default_prim_path = self._my_world.stage.GetDefaultPrim().GetPath()
unitsPerMeter = 100.0
UsdGeom.SetStageMetersPerUnit(stage, 1.0 / unitsPerMeter)
self._setup_geometry()
self._physicsMaterialPath = None
# callback setup
self._setup_callbacks()
# setup mugs
abspath = carb.tokens.get_tokens_interface().resolve(self._get_asset_path("Mug"))
print("abspath: ", abspath)
print("default prim path", default_prim_path )
numMugs = 2
for i in range(numMugs):
stage.DefinePrim(default_prim_path.AppendPath(f"Mug{i}")).GetReferences().AddReference(abspath)
mug = UsdGeom.Mesh.Get(self._stage, default_prim_path.AppendPath(f"Mug{i}/geom"))
utils.setPhysics(prim=mug.GetPrim(), kinematic=False)
utils.setCollider(prim=mug.GetPrim(), approximationShape="convexDecomposition")
self._setup_rb_collision_parameters(mug.GetPrim(), restOffset=self._mugRestOffset, contactOffset=self._mugContactOffset)
assert (
mug.GetPrim().CreateAttribute("physxMeshCollision:maxConvexHulls", Sdf.ValueTypeNames.Float).Set(32)
)
self.transform_mesh(mug, self._mugInitPos + self._mugOffset * i, self._mugInitRot, self._mugScale)
self._apply_mass(mug, self._mugMass)
# create and attach softbodies
# light
sphereLight = UsdLux.SphereLight.Define(stage, default_prim_path.AppendChild("SphereLight"))
sphereLight.CreateEnableColorTemperatureAttr().Set(True)
sphereLight.CreateColorTemperatureAttr().Set(4500)
sphereLight.CreateRadiusAttr().Set(10)
sphereLight.CreateIntensityAttr().Set(30000)
sphereLight.AddTranslateOp().Set(Gf.Vec3f(55, 26, 28.0))
sphereLight = UsdLux.SphereLight.Define(stage, default_prim_path.AppendChild("SphereLight2"))
sphereLight.CreateEnableColorTemperatureAttr().Set(True)
sphereLight.CreateColorTemperatureAttr().Set(4500)
sphereLight.CreateRadiusAttr().Set(2)
sphereLight.CreateIntensityAttr().Set(100000)
sphereLight.AddTranslateOp().Set(Gf.Vec3f(28, 29, -13.75))
# Physics scene
physicsScenePath = default_prim_path.AppendChild("physicsScene")
scene = UsdPhysics.Scene.Define(stage, physicsScenePath)
scene.CreateGravityDirectionAttr().Set(self._gravityDirection)
scene.CreateGravityMagnitudeAttr().Set(self._gravityMagnitude)
# scene.CreateEnableGPUDynamicsAttr().Set(True)
# scene.enableGPUDynamics(False)
self._my_world._physics_context.enable_gpu_dynamics(flag=True)
utils.set_physics_scene_asyncsimrender(scene.GetPrim())
physxAPI = PhysxSchema.PhysxSceneAPI.Apply(scene.GetPrim())
physxAPI.CreateSolverTypeAttr(self._solver)
physxAPI.CreateGpuMaxNumPartitionsAttr(self._gpuMaxNumPartitions)
# Plane
physicsUtils.add_ground_plane(stage, "/groundPlane", "Y", 750.0, Gf.Vec3f(0.0), Gf.Vec3f(0.2))
self._setup_physics_material(default_prim_path.AppendPath("groundPlane/CollisionPlane"))
# set cam:
customLayerData = {
"cameraSettings": {
"Perspective": {"position": self._viewerPosition, "radius": 111, "target": self._viewerTarget},
"boundCamera": "/OmniverseKit_Persp",
}
}
stage.SetMetadata("customLayerData", customLayerData)
# if Enable_Fluid:
particleSystemStr = default_prim_path.AppendPath("Fluid").pathString
self.create_particle_system(particleSystemStr, physicsScenePath.pathString)
self.generate_fluid_particles(
default_prim_path.AppendPath("Particles").pathString,
particleSystemStr,
Gf.Vec3f(0, 0, 0),
self._fluidCylinderHeight,
self._fluidCylinderRadius,
)
particles = UsdGeom.Xformable(stage.GetPrimAtPath(default_prim_path.AppendPath("Particles")))
particles.AddTranslateOp().Set(self._mugInitPos + self._fluidPositionOffset)
if name == “main”:
my_env = FluidScene(simulaton_App = app)
def handler(signum, frame):
res = input("Ctrl-c was pressed. Do you really want to exit? y/n ")
if res == ‘y’:
my_env.close()
exit(1)
signal.signal(signal.SIGINT, handler)
while True:
my_env.step()
time.sleep(0.05)
test_liquid.py (28.9 KB)