3535
3636_TABLE_CENTER = (
3737 wc .TABLE_X_MIN + wc .TABLE_DIMS [0 ] / 2 ,
38- - 0.10 ,
38+ - 0.20 ,
3939 wc .TABLE_TOP_Z - wc .TABLE_DIMS [2 ] / 2 ,
4040)
4141
@@ -64,6 +64,30 @@ def _cuboid_object_cfg(prim_name: str, size, mass, color, init_pos) -> RigidObje
6464 )
6565
6666
67+ def _tray_cfg (place ) -> RigidObjectCfg :
68+ """White, kinematic (immovable but collidable) tray from tray.usda, scaled
69+ and positioned so its interior centre lands at place.tray_center. The asset
70+ origin is a corner, so the root is offset by scale * TRAY_LOCAL_CENTER."""
71+ s = place .tray_scale
72+ sz = s * place .tray_height_scale # wall-height scale (footprint unchanged)
73+ root = (
74+ place .tray_center [0 ] - s * wc .TRAY_LOCAL_CENTER [0 ],
75+ place .tray_center [1 ] - s * wc .TRAY_LOCAL_CENTER [1 ],
76+ wc .TABLE_TOP_Z , # tray bottom rests on the table top
77+ )
78+ return RigidObjectCfg (
79+ prim_path = "{ENV_REGEX_NS}/Tray" ,
80+ init_state = RigidObjectCfg .InitialStateCfg (pos = root ),
81+ spawn = sim_utils .UsdFileCfg (
82+ usd_path = wc .TRAY_USDA ,
83+ scale = (s , s , sz ),
84+ rigid_props = sim_utils .RigidBodyPropertiesCfg (kinematic_enabled = True ),
85+ collision_props = sim_utils .CollisionPropertiesCfg (),
86+ visual_material = sim_utils .PreviewSurfaceCfg (diffuse_color = (0.95 , 0.95 , 0.95 )),
87+ ),
88+ )
89+
90+
6791def _look_at_quat_ros (eye , target , up = (0.0 , 0.0 , 1.0 )) -> tuple :
6892 """Camera quaternion (wxyz, ROS optical convention: +Z forward, +Y down)."""
6993 eye , target = np .asarray (eye , float ), np .asarray (target , float )
@@ -99,7 +123,7 @@ class PickPlaceSceneCfg(InteractiveSceneCfg):
99123 physics_material = sim_utils .RigidBodyMaterialCfg (
100124 static_friction = 0.9 , dynamic_friction = 0.8 , restitution = 0.0
101125 ),
102- visual_material = sim_utils .PreviewSurfaceCfg (diffuse_color = (0.45 , 0.35 , 0.25 )),
126+ visual_material = sim_utils .PreviewSurfaceCfg (diffuse_color = (0.02 , 0.02 , 0.02 )),
103127 ),
104128 )
105129
@@ -117,6 +141,7 @@ class PickPlaceSceneCfg(InteractiveSceneCfg):
117141 # Filled by make_env_cfg from PickPlaceTaskParams:
118142 object : RigidObjectCfg = None
119143 place_object : RigidObjectCfg = None
144+ tray : RigidObjectCfg = None
120145 camera_external : TiledCameraCfg = None
121146 camera_wrist : TiledCameraCfg = None
122147
@@ -212,6 +237,8 @@ def apply_task_params(cfg: "PickPlaceBimanualEnvCfg", params: PickPlaceTaskParam
212237
213238 reset_assets = [SceneEntityCfg ("object" )]
214239 z_values = [obj_rest_z ]
240+ cfg .scene .place_object = None
241+ cfg .scene .tray = None
215242 if params .place .mode == "stack" :
216243 pl = params .place
217244 stack_rest_z = wc .TABLE_TOP_Z + pl .stack_object_size [2 ] / 2 + 0.002
@@ -221,16 +248,30 @@ def apply_task_params(cfg: "PickPlaceBimanualEnvCfg", params: PickPlaceTaskParam
221248 )
222249 reset_assets .append (SceneEntityCfg ("place_object" ))
223250 z_values .append (stack_rest_z )
224- else :
225- cfg .scene .place_object = None
226-
251+ elif params .place .mode == "tray" :
252+ # Fixed tray; not randomized, so it stays out of reset_assets. The cube
253+ # spawn band (object.x_range/y_range) is set to avoid the tray footprint.
254+ cfg .scene .tray = _tray_cfg (params .place )
255+
256+ # In tray mode the cube may spawn anywhere in its band EXCEPT on the tray,
257+ # so it can appear on any side of the tray (not just -y). Keep-out = tray
258+ # footprint + cube half-size + margin, in the env frame.
259+ keepout = None
260+ if params .place .mode == "tray" :
261+ s = params .place .tray_scale
262+ keepout = (
263+ params .place .tray_center [0 ], params .place .tray_center [1 ],
264+ wc .TRAY_FOOTPRINT [0 ] / 2 * s + obj .size [0 ] / 2 + 0.01 ,
265+ wc .TRAY_FOOTPRINT [1 ] / 2 * s + obj .size [1 ] / 2 + 0.01 ,
266+ )
227267 cfg .events .reset_objects .params = {
228268 "x_range" : obj .x_range ,
229269 "y_range" : obj .y_range ,
230270 "yaw_range" : obj .yaw_range ,
231271 "z_values" : z_values ,
232272 "min_separation" : params .place .min_separation ,
233273 "asset_cfgs" : reset_assets ,
274+ "keepout" : keepout ,
234275 }
235276 if params .noise .enabled :
236277 fr = params .noise .friction_range
@@ -289,6 +330,13 @@ def apply_task_params(cfg: "PickPlaceBimanualEnvCfg", params: PickPlaceTaskParam
289330 # guaranteed by the cuRobo planner instead.
290331 cfg .scene .robot .spawn .articulation_props .enabled_self_collisions = False
291332
333+ # Demo readability: bind a single blue visual material over the whole arm
334+ # USD. Applied to this task's robot copy only (BIMANUAL_ARM_CFG.replace deep-
335+ # copies the spawn), so the shared teleop config is untouched.
336+ cfg .scene .robot .spawn .visual_material = sim_utils .PreviewSurfaceCfg (
337+ diffuse_color = (0.1 , 0.3 , 0.9 )
338+ )
339+
292340 # Actuator effort overrides (see EpisodeParams for rationale/flags).
293341 ep_lim = params .episode
294342 cfg .scene .robot .actuators ["left_shoulder" ].effort_limit_sim = ep_lim .shoulder_effort_limit
0 commit comments