33from scipy .spatial import Delaunay
44import torch as th
55
6- import omnigibson as og
76import omnigibson .lazy as lazy
87from omnigibson .utils .geometry_utils import (
98 check_points_in_cone ,
1211 check_points_in_sphere ,
1312)
1413import omnigibson .utils .transform_utils as T
15- from omnigibson .macros import gm
1614from omnigibson .prims .xform_prim import XFormPrim
1715from omnigibson .utils .numpy_utils import vtarray_to_torch
18- from omnigibson .utils .python_utils import assert_valid_key
1916from omnigibson .utils .ui_utils import create_module_logger
2017from omnigibson .utils .usd_utils import mesh_prim_shape_to_trimesh_mesh
2118
@@ -27,7 +24,11 @@ class GeomPrim(XFormPrim):
2724 """
2825 Provides high level functions to deal with a geom prim and its attributes / properties.
2926 If there is an geom prim present at the path, it will use it. By default, a geom prim cannot be directly
30- created from scratch.at
27+ created from scratch.
28+
29+ Geom prims are not inherently distinguished as collision or visual. Instead, at the link level
30+ (RigidPrim), they are tracked separately based on whether they appear with a CollisionAPI or as a child of one.
31+ Collision-related APIs and methods live on RigidPrim and operate on all collision meshes of a link.
3132
3233 Args:
3334 relative_prim_path (str): Scene-local prim path of the Prim to encapsulate or create.
@@ -43,6 +44,7 @@ def __init__(
4344 load_config = None ,
4445 ):
4546 self ._mesh_type = None
47+ self ._applied_physics_material = None
4648
4749 # Run super method
4850 super ().__init__ (
@@ -295,202 +297,6 @@ def extent(self):
295297 points = self .points
296298 return th .max (points , dim = 0 ).values - th .min (points , dim = 0 ).values
297299
298-
299- class CollisionGeomPrim (GeomPrim ):
300- def __init__ (
301- self ,
302- relative_prim_path ,
303- name ,
304- load_config = None ,
305- ):
306- # Store values created at runtime
307- self ._collision_api = None
308- self ._mesh_collision_api = None
309- self ._physx_collision_api = None
310- self ._applied_physics_material = None
311-
312- # Run super method
313- super ().__init__ (
314- relative_prim_path = relative_prim_path ,
315- name = name ,
316- load_config = load_config ,
317- )
318-
319- def _post_load (self ):
320- # run super first
321- super ()._post_load ()
322-
323- # By default, CollisionGeomPrim does not show up in the rendering.
324- self .purpose = "guide"
325-
326- # Create API references
327- self ._collision_api = (
328- lazy .pxr .UsdPhysics .CollisionAPI (self ._prim )
329- if self ._prim .HasAPI (lazy .pxr .UsdPhysics .CollisionAPI )
330- else lazy .pxr .UsdPhysics .CollisionAPI .Apply (self ._prim )
331- )
332- self ._physx_collision_api = (
333- lazy .pxr .PhysxSchema .PhysxCollisionAPI (self ._prim )
334- if self ._prim .HasAPI (lazy .pxr .PhysxSchema .PhysxCollisionAPI )
335- else lazy .pxr .PhysxSchema .PhysxCollisionAPI .Apply (self ._prim )
336- )
337-
338- # Optionally add mesh collision API if this is a mesh
339- if self ._prim .GetPrimTypeInfo ().GetTypeName () == "Mesh" :
340- self ._mesh_collision_api = (
341- lazy .pxr .UsdPhysics .MeshCollisionAPI (self ._prim )
342- if self ._prim .HasAPI (lazy .pxr .UsdPhysics .MeshCollisionAPI )
343- else lazy .pxr .UsdPhysics .MeshCollisionAPI .Apply (self ._prim )
344- )
345- # Set the approximation to be convex hull by default
346- self .set_collision_approximation (approximation_type = "convexHull" )
347-
348- self .collision_enabled = not gm .VISUAL_ONLY
349-
350- @property
351- def collision_enabled (self ):
352- """
353- Returns:
354- bool: Whether collisions are enabled for this collision mesh
355- """
356- return self .get_attribute ("physics:collisionEnabled" )
357-
358- @collision_enabled .setter
359- def collision_enabled (self , enabled ):
360- """
361- Sets whether collisions are enabled for this mesh
362-
363- Args:
364- enabled (bool): Whether collisions should be enabled for this mesh
365- """
366- # Currently, trying to toggle while simulator is playing while using GPU dynamics results in a crash, so we
367- # assert that the sim is stopped here
368- if self ._initialized and gm .USE_GPU_DYNAMICS :
369- assert og .sim .is_stopped (), "Cannot toggle collisions while using GPU dynamics unless simulator is stopped!"
370- self .set_attribute ("physics:collisionEnabled" , enabled )
371-
372- # TODO: Maybe this should all be added to RigidPrim instead?
373- def set_contact_offset (self , offset ):
374- """
375- Args:
376- offset (float): Contact offset of a collision shape. Allowed range [maximum(0, rest_offset), 0].
377- Default value is -inf, means default is picked by simulation based on the shape extent.
378- """
379- self ._physx_collision_api .GetContactOffsetAttr ().Set (offset )
380- return
381-
382- def get_contact_offset (self ):
383- """
384- Returns:
385- float: contact offset of the collision shape.
386- """
387- return self ._physx_collision_api .GetContactOffsetAttr ().Get ()
388-
389- def set_rest_offset (self , offset ):
390- """
391- Args:
392- offset (float): Rest offset of a collision shape. Allowed range [-max_float, contact_offset.
393- Default value is -inf, means default is picked by simulatiion. For rigid bodies its zero.
394- """
395- self ._physx_collision_api .GetRestOffsetAttr ().Set (offset )
396- return
397-
398- def get_rest_offset (self ):
399- """
400- Returns:
401- float: rest offset of the collision shape.
402- """
403- return self ._physx_collision_api .GetRestOffsetAttr ().Get ()
404-
405- def set_torsional_patch_radius (self , radius ):
406- """
407- Args:
408- radius (float): radius of the contact patch used to apply torsional friction. Allowed range [0, max_float].
409- """
410- self ._physx_collision_api .GetTorsionalPatchRadiusAttr ().Set (radius )
411- return
412-
413- def get_torsional_patch_radius (self ):
414- """
415- Returns:
416- float: radius of the contact patch used to apply torsional friction. Allowed range [0, max_float].
417- """
418- return self ._physx_collision_api .GetTorsionalPatchRadiusAttr ().Get ()
419-
420- def set_min_torsional_patch_radius (self , radius ):
421- """
422- Args:
423- radius (float): minimum radius of the contact patch used to apply torsional friction. Allowed range [0, max_float].
424- """
425- self ._physx_collision_api .GetMinTorsionalPatchRadiusAttr ().Set (radius )
426- return
427-
428- def get_min_torsional_patch_radius (self ):
429- """
430- Returns:
431- float: minimum radius of the contact patch used to apply torsional friction. Allowed range [0, max_float].
432- """
433- return self ._physx_collision_api .GetMinTorsionalPatchRadiusAttr ().Get ()
434-
435- def set_collision_approximation (self , approximation_type ):
436- """
437- Args:
438- approximation_type (str): approximation used for collision.
439- Can be one of: {"none", "convexHull", "convexDecomposition", "meshSimplification", "sdf",
440- "boundingSphere", "boundingCube"}
441- If None, the approximation will use the underlying triangle mesh.
442- """
443- assert self ._mesh_collision_api is not None , "collision_approximation only applicable for meshes!"
444- assert_valid_key (
445- key = approximation_type ,
446- valid_keys = {
447- "none" ,
448- "convexHull" ,
449- "convexDecomposition" ,
450- "meshSimplification" ,
451- "sdf" ,
452- "boundingSphere" ,
453- "boundingCube" ,
454- },
455- name = "collision approximation type" ,
456- )
457-
458- # Make sure to add the appropriate API if we're setting certain values
459- if approximation_type == "convexHull" and not self ._prim .HasAPI (
460- lazy .pxr .PhysxSchema .PhysxConvexHullCollisionAPI
461- ):
462- lazy .pxr .PhysxSchema .PhysxConvexHullCollisionAPI .Apply (self ._prim )
463- elif approximation_type == "convexDecomposition" and not self ._prim .HasAPI (
464- lazy .pxr .PhysxSchema .PhysxConvexDecompositionCollisionAPI
465- ):
466- lazy .pxr .PhysxSchema .PhysxConvexDecompositionCollisionAPI .Apply (self ._prim )
467- elif approximation_type == "meshSimplification" and not self ._prim .HasAPI (
468- lazy .pxr .PhysxSchema .PhysxTriangleMeshSimplificationCollisionAPI
469- ):
470- lazy .pxr .PhysxSchema .PhysxTriangleMeshSimplificationCollisionAPI .Apply (self ._prim )
471- elif approximation_type == "sdf" and not self ._prim .HasAPI (lazy .pxr .PhysxSchema .PhysxSDFMeshCollisionAPI ):
472- lazy .pxr .PhysxSchema .PhysxSDFMeshCollisionAPI .Apply (self ._prim )
473- elif approximation_type == "none" and not self ._prim .HasAPI (lazy .pxr .PhysxSchema .PhysxTriangleMeshCollisionAPI ):
474- lazy .pxr .PhysxSchema .PhysxTriangleMeshCollisionAPI .Apply (self ._prim )
475-
476- if approximation_type == "convexHull" :
477- pch_api = lazy .pxr .PhysxSchema .PhysxConvexHullCollisionAPI (self ._prim )
478- # Also make sure the maximum vertex count is 60 (max number compatible with GPU)
479- # https://docs.omniverse.nvidia.com/app_create/prod_extensions/ext_physics/rigid-bodies.html#collision-settings
480- if pch_api .GetHullVertexLimitAttr ().Get () is None :
481- pch_api .CreateHullVertexLimitAttr ()
482- pch_api .GetHullVertexLimitAttr ().Set (60 )
483-
484- self ._mesh_collision_api .GetApproximationAttr ().Set (approximation_type )
485-
486- def get_collision_approximation (self ):
487- """
488- Returns:
489- str: approximation used for collision, could be "none", "convexHull" or "convexDecomposition"
490- """
491- assert self ._mesh_collision_api is not None , "collision_approximation only applicable for meshes!"
492- return self ._mesh_collision_api .GetApproximationAttr ().Get ()
493-
494300 def apply_physics_material (self , physics_material , weaker_than_descendants = False ):
495301 """
496302 Used to apply physics material to the held prim and optionally its descendants.
@@ -534,40 +340,3 @@ def get_applied_physics_material(self):
534340 else :
535341 self ._applied_physics_material = lazy .isaacsim .core .api .materials .PhysicsMaterial (prim_path = path )
536342 return self ._applied_physics_material
537-
538-
539- class VisualGeomPrim (GeomPrim ):
540- def _post_load (self ):
541- # run super first
542- super ()._post_load ()
543-
544- # TODO: tmp fix for visible metalinks
545- if "meta" in self .name :
546- if "togglebutton" in self .name :
547- # Make sure togglebutton mesh is visible
548- self .purpose = "default"
549- elif any (
550- [
551- metalink in self .name
552- for metalink in [
553- "particlesource" ,
554- "particlesink" ,
555- "fillable" ,
556- "particleremover" ,
557- "particleapplier" ,
558- "slicer" ,
559- ]
560- ]
561- ):
562- # Make sure particlesource, particlesink and fillable meshes are not visible
563- self .purpose = "guide"
564-
565-
566- class CollisionVisualGeomPrim (CollisionGeomPrim , VisualGeomPrim ):
567- def _post_load (self ):
568- # run super first
569- super ()._post_load ()
570-
571- # The purpose should be default, not guide as set by CollisionGeomPrim
572- # this is to make sure the geom is visualized, even though it's also collidable
573- self .purpose = "default"
0 commit comments