1919import numpy as np
2020
2121from dataclasses import dataclass
22- from typing import List , Sequence , Optional , Union
22+ from typing import List , Sequence , Union
2323
2424from dexsim .models import MeshObject
2525from dexsim .types import RigidBodyGPUAPIReadType , RigidBodyGPUAPIWriteType
@@ -177,7 +177,7 @@ def __init__(
177177 )
178178
179179 # data for managing body data (only for dynamic and kinematic bodies) on GPU.
180- self ._data : Optional [ RigidBodyData ] = None
180+ self ._data : RigidBodyData | None = None
181181 if self .is_static is False :
182182 self ._data = RigidBodyData (entities = entities , ps = self ._ps , device = device )
183183
@@ -196,6 +196,9 @@ def __init__(
196196 # set default collision filter
197197 self ._set_default_collision_filter ()
198198
199+ # reserve flag for collision visible node existence
200+ self ._has_collision_visible_node = False
201+
199202 def __str__ (self ) -> str :
200203 parent_str = super ().__str__ ()
201204 return (
@@ -204,7 +207,7 @@ def __str__(self) -> str:
204207 )
205208
206209 @property
207- def body_data (self ) -> Optional [ RigidBodyData ] :
210+ def body_data (self ) -> RigidBodyData | None :
208211 """Get the rigid body data manager for this rigid object.
209212
210213 Returns:
@@ -266,7 +269,7 @@ def _set_default_collision_filter(self) -> None:
266269 self .set_collision_filter (collision_filter_data )
267270
268271 def set_collision_filter (
269- self , filter_data : torch .Tensor , env_ids : Optional [ Sequence [int ]] = None
272+ self , filter_data : torch .Tensor , env_ids : Sequence [int ] | None = None
270273 ) -> None :
271274 """set collision filter data for the rigid object.
272275
@@ -276,7 +279,7 @@ def set_collision_filter(
276279 If 2nd element is 0, the object will collision with all other objects in world.
277280 3rd and 4th elements are not used currently.
278281
279- env_ids (Optional[ Sequence[int]] , optional): Environment indices. If None, then all indices are used. Defaults to None.
282+ env_ids (Sequence[int] | None , optional): Environment indices. If None, then all indices are used. Defaults to None.
280283 """
281284 local_env_ids = self ._all_indices if env_ids is None else env_ids
282285
@@ -292,13 +295,13 @@ def set_collision_filter(
292295 )
293296
294297 def set_local_pose (
295- self , pose : torch .Tensor , env_ids : Optional [ Sequence [int ]] = None
298+ self , pose : torch .Tensor , env_ids : Sequence [int ] | None = None
296299 ) -> None :
297300 """Set local pose of the rigid object.
298301
299302 Args:
300303 pose (torch.Tensor): The local pose of the rigid object with shape (N, 7) or (N, 4, 4).
301- env_ids (Optional[ Sequence[int]] , optional): Environment indices. If None, then all indices are used.
304+ env_ids (Sequence[int] | None , optional): Environment indices. If None, then all indices are used.
302305 """
303306 local_env_ids = self ._all_indices if env_ids is None else env_ids
304307
@@ -395,10 +398,10 @@ def get_local_pose_cpu(
395398
396399 def add_force_torque (
397400 self ,
398- force : Optional [ torch .Tensor ] = None ,
399- torque : Optional [ torch .Tensor ] = None ,
400- pos : Optional [ torch .Tensor ] = None ,
401- env_ids : Optional [ Sequence [int ]] = None ,
401+ force : torch .Tensor | None = None ,
402+ torque : torch .Tensor | None = None ,
403+ pos : torch .Tensor | None = None ,
404+ env_ids : Sequence [int ] | None = None ,
402405 ) -> None :
403406 """Add force and/or torque to the rigid object.
404407
@@ -409,10 +412,10 @@ def add_force_torque(
409412 - if not `pos` is specified, the force and torque are applied at the center of mass of the rigid body.
410413
411414 Args:
412- force (Optional[ torch.Tensor] = None): The force to add with shape (N, 3). Defaults to None.
413- torque (Optional[ torch.Tensor] , optional): The torque to add with shape (N, 3). Defaults to None.
414- pos (Optional[ torch.Tensor] , optional): The position to apply the force at with shape (N, 3). Defaults to None.
415- env_ids (Optional[ Sequence[int]] , optional): Environment indices. If None, then all indices are used.
415+ force (torch.Tensor | None = None): The force to add with shape (N, 3). Defaults to None.
416+ torque (torch.Tensor | None , optional): The torque to add with shape (N, 3). Defaults to None.
417+ pos (torch.Tensor | None , optional): The position to apply the force at with shape (N, 3). Defaults to None.
418+ env_ids (Sequence[int] | None , optional): Environment indices. If None, then all indices are used.
416419 """
417420 if force is None and torque is None :
418421 logger .log_warning (
@@ -463,13 +466,13 @@ def add_force_torque(
463466 def set_attrs (
464467 self ,
465468 attrs : Union [RigidBodyAttributesCfg , List [RigidBodyAttributesCfg ]],
466- env_ids : Optional [ Sequence [int ]] = None ,
469+ env_ids : Sequence [int ] | None = None ,
467470 ) -> None :
468471 """Set physical attributes for the rigid object.
469472
470473 Args:
471474 attrs (Union[RigidBodyAttributesCfg, List[RigidBodyAttributesCfg]]): The physical attributes to set.
472- env_ids (Optional[ Sequence[int]] , optional): Environment indices. If None, then all indices are used.
475+ env_ids (Sequence[int] | None , optional): Environment indices. If None, then all indices are used.
473476 """
474477 local_env_ids = self ._all_indices if env_ids is None else env_ids
475478
@@ -487,13 +490,13 @@ def set_attrs(
487490 self ._entities [env_idx ].set_physical_attr (attrs [i ].attr ())
488491
489492 def set_visual_material (
490- self , mat : VisualMaterial , env_ids : Optional [ Sequence [int ]] = None
493+ self , mat : VisualMaterial , env_ids : Sequence [int ] | None = None
491494 ) -> None :
492495 """Set visual material for the rigid object.
493496
494497 Args:
495498 mat (VisualMaterial): The material to set.
496- env_ids (Optional[ Sequence[int]] , optional): Environment indices. If None, then all indices are used.
499+ env_ids (Sequence[int] | None , optional): Environment indices. If None, then all indices are used.
497500 """
498501 local_env_ids = self ._all_indices if env_ids is None else env_ids
499502
@@ -503,12 +506,12 @@ def set_visual_material(
503506 self ._visual_material [env_idx ] = mat_inst
504507
505508 def get_visual_material_inst (
506- self , env_ids : Optional [ Sequence [int ]] = None
509+ self , env_ids : Sequence [int ] | None = None
507510 ) -> List [VisualMaterialInst ]:
508511 """Get material instances for the rigid object.
509512
510513 Args:
511- env_ids (Optional[ Sequence[int]] , optional): Environment indices. If None, then all indices are used.
514+ env_ids (Sequence[int] | None , optional): Environment indices. If None, then all indices are used.
512515
513516 Returns:
514517 List[MaterialInst]: List of material instances.
@@ -533,12 +536,12 @@ def share_visual_material_inst(self, mat_insts: List[VisualMaterialInst]) -> Non
533536 entity .set_material (mat_insts [i ].mat )
534537 self ._visual_material [i ] = mat_insts [i ]
535538
536- def get_body_scale (self , env_ids : Optional [ Sequence [int ]] = None ) -> torch .Tensor :
539+ def get_body_scale (self , env_ids : Sequence [int ] | None = None ) -> torch .Tensor :
537540 """
538541 Retrieve the body scale for specified environment instances.
539542
540543 Args:
541- env_ids (Optional[ Sequence[int]] ): A sequence of environment instance IDs.
544+ env_ids (Sequence[int] | None ): A sequence of environment instance IDs.
542545 If None, retrieves the body scale for all instances.
543546
544547 Returns:
@@ -553,13 +556,13 @@ def get_body_scale(self, env_ids: Optional[Sequence[int]] = None) -> torch.Tenso
553556 )
554557
555558 def set_body_scale (
556- self , scale : torch .Tensor , env_ids : Optional [ Sequence [int ]] = None
559+ self , scale : torch .Tensor , env_ids : Sequence [int ] | None = None
557560 ) -> None :
558561 """Set the scale of the rigid body.
559562
560563 Args:
561564 scale (torch.Tensor): The scale to set with shape (N, 3).
562- env_ids (Optional[ Sequence[int]] , optional): Environment indices. If None, then all indices are used.
565+ env_ids (Sequence[int] | None , optional): Environment indices. If None, then all indices are used.
563566 """
564567 local_env_ids = self ._all_indices if env_ids is None else env_ids
565568
@@ -575,12 +578,12 @@ def set_body_scale(
575578 else :
576579 logger .log_error (f"Setting body scale on GPU is not supported yet." )
577580
578- def get_vertices (self , env_ids : Optional [ Sequence [int ]] = None ) -> torch .Tensor :
581+ def get_vertices (self , env_ids : Sequence [int ] | None = None ) -> torch .Tensor :
579582 """
580583 Retrieve the vertices of the rigid objects.
581584
582585 Args:
583- env_ids (Optional[ Sequence[int]] ): A sequence of environment IDs for which to retrieve vertices.
586+ env_ids (Sequence[int] | None ): A sequence of environment IDs for which to retrieve vertices.
584587 If None, retrieves vertices for all instances.
585588
586589 Returns:
@@ -607,11 +610,11 @@ def get_user_ids(self) -> torch.Tensor:
607610 device = self .device ,
608611 )
609612
610- def clear_dynamics (self , env_ids : Optional [ Sequence [int ]] = None ) -> None :
613+ def clear_dynamics (self , env_ids : Sequence [int ] | None = None ) -> None :
611614 """Clear the dynamics of the rigid bodies by resetting velocities and applying zero forces and torques.
612615
613616 Args:
614- env_ids (Optional[ Sequence[int]] ): Environment indices. If None, then all indices are used.
617+ env_ids (Sequence[int] | None ): Environment indices. If None, then all indices are used.
615618 """
616619 if self .is_non_dynamic :
617620 return
@@ -648,7 +651,51 @@ def clear_dynamics(self, env_ids: Optional[Sequence[int]] = None) -> None:
648651 data_type = RigidBodyGPUAPIWriteType .TORQUE ,
649652 )
650653
651- def reset (self , env_ids : Optional [Sequence [int ]] = None ) -> None :
654+ def set_physical_visible (
655+ self ,
656+ visible : bool = True ,
657+ rgba : Sequence [float ] | None = None ,
658+ ):
659+ """set collion render visibility
660+
661+ Args:
662+ visible (bool, optional): is collision body visible. Defaults to True.
663+ rgba (Sequence[float] | None, optional): collision body visible rgba. It will be defined at the first time the function is called. Defaults to None.
664+ """
665+ rgba = rgba if rgba is not None else (0.8 , 0.2 , 0.2 , 0.7 )
666+ if len (rgba ) != 4 :
667+ logger .log_error (f"Invalid rgba { rgba } , should be a sequence of 4 floats." )
668+
669+ # create collision visible node if not exist
670+ if visible :
671+ if not self ._has_collision_visible_node :
672+ for i , env_idx in enumerate (self ._all_indices ):
673+ self ._entities [env_idx ].create_physical_visible_node (
674+ np .array (
675+ [
676+ rgba [0 ],
677+ rgba [1 ],
678+ rgba [2 ],
679+ rgba [3 ],
680+ ]
681+ )
682+ )
683+ self ._has_collision_visible_node = True
684+
685+ # create collision visible node if not exist
686+ for i , env_idx in enumerate (self ._all_indices ):
687+ self ._entities [env_idx ].set_physical_visible (visible )
688+
689+ def set_visible (self , visible : bool = True ) -> None :
690+ """Set the visibility of the rigid object.
691+
692+ Args:
693+ visible (bool, optional): Whether the rigid object is visible. Defaults to True.
694+ """
695+ for i , env_idx in enumerate (self ._all_indices ):
696+ self ._entities [env_idx ].set_visible (visible )
697+
698+ def reset (self , env_ids : Sequence [int ] | None = None ) -> None :
652699 local_env_ids = self ._all_indices if env_ids is None else env_ids
653700 num_instances = len (local_env_ids )
654701 self .set_attrs (self .cfg .attrs , env_ids = local_env_ids )
0 commit comments