fix(sim): split transfer and air-insert camera sets

This commit is contained in:
Logic
2026-05-03 10:14:04 +08:00
parent b1116e489f
commit bc4caf355b
7 changed files with 26 additions and 36 deletions

View File

@@ -7,7 +7,6 @@
<geom name="table" condim="4" contype="1" conaffinity="1" type="box" rgba="0.4 0.4 0.4 1" size="0.62 0.62 0.01" density="1500" friction="0.9 0.9 0.9"/>
</body>
<camera name="top" pos="0.0 1.0 2.0" fovy="44" mode="targetbody" target="table"/>
<camera name="left_side" pos="-0.55 0.85 0.85" fovy="65" mode="targetbody" target="table"/>
<camera name="front" pos="0 0 0.8" fovy="65" mode="fixed" quat="0.7071 0.7071 0 0"/>
</worldbody>
</mujoco>

View File

@@ -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)

View File

@@ -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]

View File

@@ -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()

View File

@@ -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': {

View File

@@ -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):

View File

@@ -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):