4.5.0
4.2.0
4.1.0
4.0.0
4.5.0
2023.1.1
2023.1.0-hotfix.1
Other (please specify):
Operating System
Ubuntu 22.04
Ubuntu 20.04
Windows 11
Windows 10
Other (please specify):
GPU Information
Model: NVIDIA GeForce RTX 3090 Ti
Driver Version: 535.183.01
Topic Description
Detailed Description
I want to create small attachments on different positions of my sphere-shaped deformable object. The only way I can find to create attachment is calling this : PhysxSchema.PhysxAutoAttachmentAPI.Apply(attachment.GetPrim()). It seems like it automatically chooses the attachment place. How can I specify the attachment position and size?
Error Messages
2025-04-25 17:04:01 [12,026ms] [Error] [omni.physx.plugin] PhysX error: PxDeformableElementFilter: No support for deformable group element count of 0 when filtering against a rigid body, FILE /builds/omniverse/physics/physx/source/physx/src/NpDeformableElementFilter.cpp, LINE 137
Additional Information
Related Issues
Here I found some similar issues, but no one had replied. I did exactly the same code as in this post.
I also want to mention, it seems like the attachment can only be applied to FixedCuboid or DynamicCuboid. If the target is initialized as SingleRigidPrim, the error No support for deformable group element count of 0 when filtering against a rigid body will show up. How to solve this problem?
Hi @michalin, thanks for answering. Yes, I’ve checked out that tutorial, but I don’t know how to do that in the code. Could you provide me with more help on that, like giving a simple example of how to set those parameters, or pointing out a place I can find the example code?
@lyx010318, the tutorial is actually pretty self-contained. You can use the GUI to instantiate two meshes of whichever shape and then make one deformable (or both), and create attachment between the two when they are overlapping.
If you are looking for a way to do this with code here is a recent example I put:
Hi @michalin, thanks for the reply! I have checked the code.
But my issue happens if I wrap the cube = UsdGeom.Cube.Define(stage, cube_path) with SingleRigidPrim or RigidPrim. Then the error No support for deformable group element count of 0 when filtering against a rigid body will show up.
And I’m also asking to create the attachment at specific position not automatically generated some connection points when they are overlapping.
Hi @lyx010318, so sorry for the super late reply. I am not entirely sure how you set up the RigidPrims but you will need a collider to be able to apply the attachment. Here is an example of applying an attachment to a SingleRigidPrim cube:
# Copyright (c) 2022-2024, NVIDIA CORPORATION. All rights reserved.
#
# NVIDIA CORPORATION and its licensors retain all intellectual property
# and proprietary rights in and to this software, related documentation
# and any modifications thereto. Any use, reproduction, disclosure or
# distribution of this software and related documentation without an express
# license agreement from NVIDIA CORPORATION is strictly prohibited.
#
from isaacsim import SimulationApp
simulation_app = SimulationApp({"headless": False})
from isaacsim.core.api import World
from isaacsim.core.utils.stage import create_new_stage
import isaacsim.core.utils.stage as stage_utils
from pxr import UsdGeom, Gf, UsdPhysics, PhysxSchema
import math
from omni.physx.scripts import physicsUtils
from isaacsim.core.api.materials.deformable_material import DeformableMaterial
from isaacsim.core.prims import SingleDeformablePrim, SingleRigidPrim
def create_sphere_mesh(radius=0.5, num_lat=16, num_lon=16):
"""Create a UV sphere mesh with the given parameters."""
points = []
indices = []
# Create vertices
for i in range(num_lat + 1):
theta = math.pi * i / num_lat # 0 to pi
sin_theta = math.sin(theta)
cos_theta = math.cos(theta)
for j in range(num_lon):
phi = 2 * math.pi * j / num_lon # 0 to 2pi
x = radius * sin_theta * math.cos(phi)
y = radius * sin_theta * math.sin(phi)
z = radius * cos_theta
points.append(Gf.Vec3f(x, y, z))
# Create triangular faces
for i in range(num_lat):
for j in range(num_lon):
first = i * num_lon + j
second = first + num_lon
# Two triangles per quad
indices.append(first)
indices.append(second)
indices.append(first + 1 if (j + 1) < num_lon else i * num_lon)
indices.append(second)
indices.append(second + 1 if (j + 1) < num_lon else (i + 1) * num_lon)
indices.append(first + 1 if (j + 1) < num_lon else i * num_lon)
return points, indices
# Configuration
SPHERE_RADIUS = 0.5
CIRCLE_RADIUS = 0.5 # Distance from cube center
HEIGHT = 0.75 # Height above ground
ATTACHMENT_INTERVAL = 5.0 # Seconds between attachments
ATTACHMENT_DURATION = 2.0 # How long each attachment stays active
ATTACHMENT_ANGLE_STEP = 45 # Degrees between each attachment
create_new_stage()
stage = simulation_app.context.get_stage()
my_world = World(stage_units_in_meters=1.0, backend="torch", device="cuda")
my_world.scene.add_default_ground_plane()
UsdPhysics.Scene.Define(stage, "/physicsScene")
# Rigid cube using SingleRigidPrim
cube_path = "/World/Xform"
stage_utils.get_current_stage().DefinePrim(cube_path, "Xform")
cube_prim = stage_utils.get_current_stage().DefinePrim(cube_path + "/Cube", "Cube")
UsdPhysics.CollisionAPI.Apply(cube_prim)
# Wrap the Xform as rigid prim
cube = SingleRigidPrim(cube_path)
my_world.scene.add(cube)
# Deformable sphere
sphere_path = "/World/Sphere2"
sphere_xform = UsdGeom.Xform.Define(stage, sphere_path)
mesh_path = sphere_xform.GetPrim().GetPath().AppendChild("sphere").pathString
sphere_mesh = UsdGeom.Mesh.Define(stage, mesh_path)
pts, idxs = create_sphere_mesh(SPHERE_RADIUS, num_lat=16, num_lon=16)
# Position sphere in a circle around the cube (will be updated dynamically)
sphere_translate_op = physicsUtils.set_or_add_translate_op(sphere_mesh, Gf.Vec3f(CIRCLE_RADIUS, 0, HEIGHT))
sphere_mesh.GetPointsAttr().Set(pts)
sphere_mesh.GetFaceVertexIndicesAttr().Set(idxs)
sphere_mesh.GetFaceVertexCountsAttr().Set([3] * (len(idxs)//3))
mat = DeformableMaterial(
prim_path=sphere_path + "/deformableMaterial",
dynamic_friction=0.1,
youngs_modulus=5e6,
poissons_ratio=0.4,
damping_scale=0.1,
elasticity_damping=0.1
)
deformable = SingleDeformablePrim(
name="deformableSphere2",
prim_path=mesh_path,
deformable_material=mat,
self_collision=True
)
my_world.scene.add(deformable)
attachment_counter = 0
def create_attachment(angle_degrees):
"""
Create an attachment at a specific angle around the cube.
Args:
angle_degrees: Angle in degrees around the cube (0-360) for the attachment point
"""
global attachment_counter
attachment_counter += 1
# Update sphere position to the specified angle around the cube
angle_rad = math.radians(angle_degrees)
x = CIRCLE_RADIUS * math.cos(angle_rad)
y = CIRCLE_RADIUS * math.sin(angle_rad)
sphere_translate_op.Set(Gf.Vec3f(x, y, HEIGHT))
# Create the attachment
att_path = mesh_path + f"/attachment_{attachment_counter}"
att = PhysxSchema.PhysxPhysicsAttachment.Define(stage, att_path)
att.GetActor0Rel().SetTargets([mesh_path])
att.GetActor1Rel().SetTargets([cube_path])
PhysxSchema.PhysxAutoAttachmentAPI.Apply(att.GetPrim())
print(f"Attachment {attachment_counter} created at time {my_world.current_time:.2f}s at angle {angle_degrees}°")
return att
my_world.reset()
attachments = []
last_creation_time = -ATTACHMENT_INTERVAL # Allow first attachment at 0.1s
attachment_angle = 0
try:
while simulation_app.is_running():
current_time = my_world.current_time
# Create new attachment at different angles around the circle
if current_time >= 0.1 and current_time - last_creation_time >= ATTACHMENT_INTERVAL:
att = create_attachment(attachment_angle)
attachments.append((att, current_time))
last_creation_time = current_time
attachment_angle = (attachment_angle + ATTACHMENT_ANGLE_STEP) % 360
# Deactivate attachments after specified duration
for att, creation_time in attachments:
if current_time - creation_time >= ATTACHMENT_DURATION and att.GetPrim().IsActive():
att.GetPrim().SetActive(False)
print(f"Attachment deactivated at time {current_time:.2f}s (created at {creation_time:.2f}s)")
my_world.step(render=True)
except KeyboardInterrupt:
pass
finally:
simulation_app.close()