1515from __future__ import annotations
1616
1717from collections .abc import Callable , Sequence
18+ from enum import StrEnum
1819from pathlib import Path
19- from typing import Literal , Protocol , TypeAlias , cast , get_args
20+ from typing import Protocol , TypeAlias , cast
2021
2122from yourdfpy import URDF # type: ignore[import-untyped]
2223
7374COLLISION_MESH_COLOR = (210 , 40 , 220 )
7475COLLISION_MESH_OPACITY = 0.35
7576
76- RobotDisplayMode : TypeAlias = Literal ["visual" , "collision" , "both" ]
77- ROBOT_DISPLAY_MODE_VALUES : tuple [RobotDisplayMode , ...] = get_args (RobotDisplayMode )
78- _VISUAL_DISPLAY_MODE = ROBOT_DISPLAY_MODE_VALUES [0 ]
79- _COLLISION_DISPLAY_MODE = ROBOT_DISPLAY_MODE_VALUES [1 ]
80- _BOTH_DISPLAY_MODE = ROBOT_DISPLAY_MODE_VALUES [2 ]
77+ class RobotDisplayMode (StrEnum ):
78+ VISUAL = "visual"
79+ COLLISION = "collision"
80+ BOTH = "both"
8181
8282SceneHandle : TypeAlias = ViserUrdf | TransformControlsHandle | GridHandle | MeshHandle
8383
@@ -105,7 +105,7 @@ def __init__(
105105 self ._preview_visible : dict [str , bool ] = {}
106106 self ._target_tracks_current : dict [str , bool ] = {}
107107 self ._collision_fallback_urdfs : dict [str , ViserUrdf ] = {}
108- self ._robot_display_mode : RobotDisplayMode = "visual"
108+ self ._robot_display_mode = RobotDisplayMode . VISUAL
109109 self ._ensure_reference_grid ()
110110
111111 @property
@@ -114,11 +114,13 @@ def robot_display_mode(self) -> RobotDisplayMode:
114114 return self ._robot_display_mode
115115
116116 @robot_display_mode .setter
117- def robot_display_mode (self , mode : RobotDisplayMode ) -> None :
117+ def robot_display_mode (self , mode : RobotDisplayMode | str ) -> None :
118118 """Set the primary robot display mode and apply it immediately."""
119- if mode not in ROBOT_DISPLAY_MODE_VALUES :
120- raise ValueError (f"Unsupported robot display mode: { mode !r} " )
121- self ._robot_display_mode = mode
119+ try :
120+ normalized_mode = RobotDisplayMode (mode )
121+ except ValueError as error :
122+ raise ValueError (f"Unsupported robot display mode: { mode !r} " ) from error
123+ self ._robot_display_mode = normalized_mode
122124 for robot_id in self ._configs_by_id :
123125 self ._apply_robot_display_mode (robot_id )
124126
@@ -319,7 +321,7 @@ def close(self) -> None:
319321 self ._configs_by_id .clear ()
320322 self ._preview_visible .clear ()
321323 self ._target_tracks_current .clear ()
322- self ._robot_display_mode = "visual"
324+ self ._robot_display_mode = RobotDisplayMode . VISUAL
323325
324326 def _ensure_robot_urdfs (self , robot_id : str , config : RobotModelConfig ) -> None :
325327 if not config .model_path :
@@ -416,17 +418,21 @@ def _apply_robot_display_mode(self, robot_id: str) -> None:
416418 # Viser's public flags manage all links, including links whose mesh
417419 # handles are not exposed by the helper. A model without collision
418420 # geometry falls back to its visual representation.
419- current .show_visual = mode in {_VISUAL_DISPLAY_MODE , _BOTH_DISPLAY_MODE }
421+ current .show_visual = mode in {RobotDisplayMode . VISUAL , RobotDisplayMode . BOTH }
420422 current .show_collision = has_collision and mode in {
421- _COLLISION_DISPLAY_MODE ,
422- _BOTH_DISPLAY_MODE ,
423+ RobotDisplayMode . COLLISION ,
424+ RobotDisplayMode . BOTH ,
423425 }
424426 fallback = self ._collision_fallback_urdfs .get (robot_id )
425427 if fallback is not None :
426- fallback .show_visual = mode in {_COLLISION_DISPLAY_MODE , _BOTH_DISPLAY_MODE }
428+ fallback .show_visual = mode in {
429+ RobotDisplayMode .COLLISION ,
430+ RobotDisplayMode .BOTH ,
431+ }
427432 fallback .show_collision = False
428433 self ._set_handle_visibility (
429- fallback , mode in {_COLLISION_DISPLAY_MODE , _BOTH_DISPLAY_MODE }
434+ fallback ,
435+ mode in {RobotDisplayMode .COLLISION , RobotDisplayMode .BOTH },
430436 )
431437
432438 def prepared_urdf_path (self , config : RobotModelConfig ) -> Path :
0 commit comments