From bc4caf355b0f9a5268c05824dc43a09f6ba8fc06 Mon Sep 17 00:00:00 2001 From: Logic Date: Sun, 3 May 2026 10:14:04 +0800 Subject: [PATCH] fix(sim): split transfer and air-insert camera sets --- .../manipulators/DianaMed/table_square.xml | 1 - roboimi/envs/double_air_insert_env.py | 7 +++++-- roboimi/envs/double_base.py | 17 +++++------------ roboimi/envs/double_pos_ctrl_env.py | 9 ++++----- roboimi/utils/constants.py | 2 +- tests/test_air_insert_env.py | 14 +++++++------- tests/test_eval_vla_headless.py | 12 ++++-------- 7 files changed, 26 insertions(+), 36 deletions(-) diff --git a/roboimi/assets/models/manipulators/DianaMed/table_square.xml b/roboimi/assets/models/manipulators/DianaMed/table_square.xml index d1127d0..fb03d1f 100644 --- a/roboimi/assets/models/manipulators/DianaMed/table_square.xml +++ b/roboimi/assets/models/manipulators/DianaMed/table_square.xml @@ -7,7 +7,6 @@ - diff --git a/roboimi/envs/double_air_insert_env.py b/roboimi/envs/double_air_insert_env.py index f1db21d..8896a91 100644 --- a/roboimi/envs/double_air_insert_env.py +++ b/roboimi/envs/double_air_insert_env.py @@ -120,15 +120,18 @@ class DualDianaMed_Air_Insert(DualDianaMed_Pos_Ctrl): set_socket_peg_task_state(self.mj_data, task_state) DualDianaMed.reset(self) self.top = None - self.left_side = None self.r_vis = None + self.l_vis = None self.front = None + if not self.is_render: + self._update_camera_images_sync() + return self.cam_flage = True while self.cam_flage: if ( type(self.top) == type(None) - or type(self.left_side) == type(None) or type(self.r_vis) == type(None) + or type(self.l_vis) == type(None) or type(self.front) == type(None) ): time.sleep(0.001) diff --git a/roboimi/envs/double_base.py b/roboimi/envs/double_base.py index 79c2611..28392b8 100644 --- a/roboimi/envs/double_base.py +++ b/roboimi/envs/double_base.py @@ -52,7 +52,6 @@ class DualDianaMed(MujocoEnv): self.r_vis = None self.l_vis = None self.top = None - self.left_side = None self.front = None self.obs = None @@ -168,10 +167,9 @@ class DualDianaMed(MujocoEnv): obs['qpos'] = self.get_obs_qpos obs['action'] = self.compute_qpos obs['images'] = dict() - obs['images']['top'] = self.top - obs['images']['left_side'] = self.left_side obs['images']['r_vis'] = self.r_vis obs['images']['l_vis'] = self.l_vis + obs['images']['top'] = self.top obs['images']['front'] = self.front return obs @@ -180,10 +178,9 @@ class DualDianaMed(MujocoEnv): self._update_camera_images_sync() obs = collections.OrderedDict() obs['images'] = dict() - obs['images']['top'] = self.top - obs['images']['left_side'] = self.left_side obs['images']['r_vis'] = self.r_vis obs['images']['l_vis'] = self.l_vis + obs['images']['top'] = self.top obs['images']['front'] = self.front return obs @@ -202,14 +199,12 @@ class DualDianaMed(MujocoEnv): @property def cam_view(self): - if self.cam == 'top': - return self.top - elif self.cam == 'left_side': - return self.left_side - elif self.cam == 'r_vis': + if self.cam == 'r_vis': return self.r_vis elif self.cam == 'l_vis': return self.l_vis + elif self.cam == 'top': + return self.top elif self.cam == 'front': return self.front else: @@ -230,8 +225,6 @@ class DualDianaMed(MujocoEnv): self.l_vis = img_renderer.render()[:, :, ::-1] img_renderer.update_scene(self.mj_data, camera="top") self.top = img_renderer.render()[:, :, ::-1] - img_renderer.update_scene(self.mj_data, camera="left_side") - self.left_side = img_renderer.render()[:, :, ::-1] img_renderer.update_scene(self.mj_data, camera="front") self.front = img_renderer.render()[:, :, ::-1] diff --git a/roboimi/envs/double_pos_ctrl_env.py b/roboimi/envs/double_pos_ctrl_env.py index ee5930f..a4fd6a4 100644 --- a/roboimi/envs/double_pos_ctrl_env.py +++ b/roboimi/envs/double_pos_ctrl_env.py @@ -73,8 +73,8 @@ class DualDianaMed_Pos_Ctrl(DualDianaMed): self.mj_data.joint('red_box_joint').qpos[6] = 0.0 super().reset() self.top = None - self.left_side = None self.r_vis = None + self.l_vis = None self.front = None if not self.is_render: self._update_camera_images_sync() @@ -83,8 +83,8 @@ class DualDianaMed_Pos_Ctrl(DualDianaMed): t=0 while self.cam_flage: if(type(self.top)==type(None) - or type(self.left_side)==type(None) or type(self.r_vis)==type(None) + or type(self.l_vis)==type(None) or type(self.front)==type(None)): time.sleep(0.001) t+=1 @@ -146,7 +146,7 @@ def make_sim_env(task_name, headless=False): is_render=not headless, control_freq=30, is_interpolate=True, - cam_view='left_side' + cam_view='front' ) return env if 'sim_transfer' in task_name: @@ -156,7 +156,7 @@ def make_sim_env(task_name, headless=False): is_render=not headless, control_freq=30, is_interpolate=True, - cam_view='left_side' + cam_view='top' ) return env else: @@ -182,4 +182,3 @@ if __name__ == "__main__": env.step(action) if env.is_render: env.render() - diff --git a/roboimi/utils/constants.py b/roboimi/utils/constants.py index e6d6d2c..5bf065a 100644 --- a/roboimi/utils/constants.py +++ b/roboimi/utils/constants.py @@ -20,7 +20,7 @@ SIM_TASK_CONFIGS = { 'dataset_dir': DATASET_DIR + '/sim_transfer', 'num_episodes': 20, 'episode_len': 700, - 'camera_names': ['top','r_vis','front'], + 'camera_names': ['r_vis', 'top', 'front'], 'xml_dir': HOME_PATH + '/assets' }, 'sim_air_insert_socket_peg': { diff --git a/tests/test_air_insert_env.py b/tests/test_air_insert_env.py index c0f3b28..2c725c5 100644 --- a/tests/test_air_insert_env.py +++ b/tests/test_air_insert_env.py @@ -94,10 +94,10 @@ class AirInsertTaskRegistrationTest(unittest.TestCase): is_render=False, control_freq=30, is_interpolate=True, - cam_view="left_side", + cam_view="front", ) - def test_diana_table_scene_uses_left_side_camera_instead_of_angle(self): + def test_diana_table_scene_exposes_only_top_and_front_scene_cameras(self): xml_path = ( pathlib.Path(__file__).resolve().parents[1] / "roboimi/assets/models/manipulators/DianaMed/table_square.xml" @@ -106,11 +106,11 @@ class AirInsertTaskRegistrationTest(unittest.TestCase): cameras = {camera.attrib["name"]: camera.attrib for camera in root.findall(".//camera")} self.assertNotIn("angle", cameras, "DianaMed scene should stop exposing the old angle camera") - self.assertIn("left_side", cameras, "DianaMed scene should expose the left-side task camera") - left_side_pos = np.fromstring(cameras["left_side"]["pos"], sep=" ") - self.assertLess(float(left_side_pos[0]), 0.0) - self.assertEqual(cameras["left_side"].get("mode"), "targetbody") - self.assertEqual(cameras["left_side"].get("target"), "table") + self.assertNotIn("left_side", cameras, "DianaMed scene should no longer expose left_side") + self.assertIn("top", cameras) + self.assertIn("front", cameras) + self.assertEqual(cameras["top"].get("mode"), "targetbody") + self.assertEqual(cameras["top"].get("target"), "table") class AirInsertResetAndStateHelpersTest(unittest.TestCase): diff --git a/tests/test_eval_vla_headless.py b/tests/test_eval_vla_headless.py index 169c6b5..416c6cf 100644 --- a/tests/test_eval_vla_headless.py +++ b/tests/test_eval_vla_headless.py @@ -74,7 +74,7 @@ class _FakeRenderer: self._env = env self._frames = [ np.full((4, 4, 3), fill_value=index, dtype=np.uint8) - for index in range(5) + for index in range(8) ] self._index = 0 @@ -144,7 +144,7 @@ class EvalVLAHeadlessTest(unittest.TestCase): is_render=False, control_freq=30, is_interpolate=True, - cam_view="left_side", + cam_view="top", ) def test_headless_sync_camera_capture_populates_images_without_gui_calls(self): @@ -153,11 +153,10 @@ class EvalVLAHeadlessTest(unittest.TestCase): env.mj_data = object() env.exit_flag = False env.is_render = False - env.cam = 'angle' + env.cam = 'top' env.r_vis = None env.l_vis = None env.top = None - env.angle = None env.front = None env._offscreen_renderer = None @@ -176,7 +175,6 @@ class EvalVLAHeadlessTest(unittest.TestCase): self.assertIsNotNone(env.r_vis) self.assertIsNotNone(env.l_vis) self.assertIsNotNone(env.top) - self.assertIsNotNone(env.angle) self.assertIsNotNone(env.front) def test_cam_start_skips_background_thread_when_headless(self): @@ -196,11 +194,10 @@ class EvalVLAHeadlessTest(unittest.TestCase): env.mj_data = object() env.exit_flag = False env.is_render = False - env.cam = "left_side" + env.cam = "top" env.r_vis = None env.l_vis = None env.top = None - env.left_side = None env.front = None with mock.patch( @@ -217,7 +214,6 @@ class EvalVLAHeadlessTest(unittest.TestCase): self.assertIsNotNone(env.r_vis) self.assertIsNotNone(env.l_vis) self.assertIsNotNone(env.top) - self.assertIsNotNone(env.left_side) self.assertIsNotNone(env.front) def test_eval_main_headless_skips_render_and_still_executes_policy(self):