@@ -58,7 +58,7 @@ def _find_single_rigid_body_prim_in_subtree(root_prim: Usd.Prim, entity_name: st
5858
5959
6060def _compute_geometry_bounds_in_prim_frame (prim : Usd .Prim ) -> AxisAlignedBoundingBox :
61- """Compute descendant geometry bounds in the prim frame."""
61+ """Compute descendant geometry bounds expressed in the prim's local frame ``P`` ."""
6262 assert prim .IsValid (), "Prim must be valid."
6363
6464 time_code = Usd .TimeCode .Default ()
@@ -79,12 +79,12 @@ def _compute_geometry_bounds_in_prim_frame(prim: Usd.Prim) -> AxisAlignedBoundin
7979 geometry_bounds = bounding_box_cache .ComputeWorldBound (geometry_prim )
8080 # Remove the prim's initial world translation and rotation while leaving spawned scale in the bounds.
8181 geometry_bounds .Transform (T_P_W )
82- geometry_range = geometry_bounds .ComputeAlignedRange ()
83- if geometry_range .IsEmpty ():
82+ geometry_range_P = geometry_bounds .ComputeAlignedRange ()
83+ if geometry_range_P .IsEmpty ():
8484 continue
8585
86- lower_P = np .minimum (lower_P , np .asarray (geometry_range .GetMin (), dtype = np .float64 ))
87- upper_P = np .maximum (upper_P , np .asarray (geometry_range .GetMax (), dtype = np .float64 ))
86+ lower_P = np .minimum (lower_P , np .asarray (geometry_range_P .GetMin (), dtype = np .float64 ))
87+ upper_P = np .maximum (upper_P , np .asarray (geometry_range_P .GetMax (), dtype = np .float64 ))
8888 found_geometry = True
8989
9090 prim_path = prim .GetPath ()
@@ -99,17 +99,24 @@ def compute_spawned_geometry_bounds_in_entity_frame(
9999 scene : InteractiveScene ,
100100 entity_name : str ,
101101) -> AxisAlignedBoundingBox :
102- """Build spawned geometry bounds in the entity's live pose frame."""
102+ """Build spawned geometry bounds expressed in entity frame ``E``.
103+
104+ Args:
105+ scene: Interactive scene containing the spawned entity.
106+ entity_name: Scene entity whose prim-local coordinate system defines frame ``E``.
107+
108+ Returns:
109+ One batched AABB aligned with frame ``E`` and measured from its origin.
110+ The bounds do not change when the entity's live pose changes.
111+ """
103112 assert (
104113 entity_name in scene .rigid_objects or entity_name in scene .extras
105114 ), f"Scene entity '{ entity_name } ' must be a rigid object or an AssetBaseCfg scene entry."
106115 is_rigid_object = entity_name in scene .rigid_objects
107116 resolved_geometry_prim_path = getattr (scene .cfg , entity_name ).prim_path .format (ENV_REGEX_NS = scene .env_regex_ns )
108117
109- minimum_points_in_entity_frame_by_environment = torch .empty (
110- (scene .num_envs , 3 ), dtype = torch .float32 , device = scene .device
111- )
112- maximum_points_in_entity_frame_by_environment = torch .empty_like (minimum_points_in_entity_frame_by_environment )
118+ minimum_points_E_by_environment = torch .empty ((scene .num_envs , 3 ), dtype = torch .float32 , device = scene .device )
119+ maximum_points_E_by_environment = torch .empty_like (minimum_points_E_by_environment )
113120 coverage_count = [0 ] * scene .num_envs
114121
115122 for representative_prim , environment_ids in _get_spawned_entity_groups (
@@ -122,14 +129,10 @@ def compute_spawned_geometry_bounds_in_entity_frame(
122129 if is_rigid_object
123130 else representative_prim
124131 )
125- geometry_bounds_in_entity_frame = _compute_geometry_bounds_in_prim_frame (entity_frame_prim ).to (scene .device )
132+ geometry_bounds_E = _compute_geometry_bounds_in_prim_frame (entity_frame_prim ).to (scene .device )
126133 environment_indices = torch .tensor (environment_ids , dtype = torch .long , device = scene .device )
127- minimum_points_in_entity_frame_by_environment [environment_indices ] = geometry_bounds_in_entity_frame .min_point [
128- 0
129- ]
130- maximum_points_in_entity_frame_by_environment [environment_indices ] = geometry_bounds_in_entity_frame .max_point [
131- 0
132- ]
134+ minimum_points_E_by_environment [environment_indices ] = geometry_bounds_E .min_point [0 ]
135+ maximum_points_E_by_environment [environment_indices ] = geometry_bounds_E .max_point [0 ]
133136 for environment_id in environment_ids :
134137 coverage_count [environment_id ] += 1
135138
@@ -138,13 +141,13 @@ def compute_spawned_geometry_bounds_in_entity_frame(
138141 f" { coverage_count } ."
139142 )
140143 return AxisAlignedBoundingBox (
141- min_point = minimum_points_in_entity_frame_by_environment ,
142- max_point = maximum_points_in_entity_frame_by_environment ,
144+ min_point = minimum_points_E_by_environment ,
145+ max_point = maximum_points_E_by_environment ,
143146 )
144147
145148
146149class AssetBaseCfgPoseReader :
147- """Read current poses for one named AssetBaseCfg scene entry."""
150+ """Read current ``T_W_E`` poses for an AssetBaseCfg scene entry defining frame ``E`` ."""
148151
149152 def __init__ (self , scene : InteractiveScene , entity_name : str ):
150153 assert entity_name in scene .extras , f"Scene entity '{ entity_name } ' must be an AssetBaseCfg scene entry."
@@ -172,11 +175,13 @@ def __init__(self, scene: InteractiveScene, entity_name: str):
172175 )
173176
174177 def get_pose_w (self ) -> torch .Tensor :
175- """Return the entry's current world pose as ``(x, y, z, qx, qy, qz, qw)``."""
178+ """Return ``T_W_E`` as ``(x, y, z, qx, qy, qz, qw)``."""
176179 position_w_buffer , orientation_w_buffer = self ._frame_view .get_world_poses ()
177- pose_w = torch .cat ((position_w_buffer .torch , orientation_w_buffer .torch ), dim = - 1 )
178- assert pose_w .shape == (self ._num_envs , 7 ), (
179- f"AssetBaseCfg scene entry '{ self ._entity_name } ' returned pose shape { tuple (pose_w .shape )} ; "
180+ t_W_E = position_w_buffer .torch
181+ q_W_E = orientation_w_buffer .torch
182+ T_W_E = torch .cat ((t_W_E , q_W_E ), dim = - 1 )
183+ assert T_W_E .shape == (self ._num_envs , 7 ), (
184+ f"AssetBaseCfg scene entry '{ self ._entity_name } ' returned pose shape { tuple (T_W_E .shape )} ; "
180185 f"expected ({ self ._num_envs } , 7)."
181186 )
182- return pose_w
187+ return T_W_E
0 commit comments