Georg commited on
Commit ·
cd29740
1
Parent(s): c525614
Implement camera and environment reset functions in mujoco_server.py
Browse files- Added _reset_camera_for_current_robot to configure camera settings based on the active robot.
- Introduced _reset_active_environment to reset the simulation environment and camera together.
- Updated _handle_gym_ws_message to call _reset_active_environment on specific message types.
- Refactored reset logic in handle_ws_message to utilize the new reset functions, improving code organization and maintainability.
- mujoco_server.py +39 -21
mujoco_server.py
CHANGED
|
@@ -122,6 +122,36 @@ cam.lookat = np.array([0, 0, 0.8])
|
|
| 122 |
# Camera follow mode
|
| 123 |
camera_follow = True
|
| 124 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 125 |
MODEL_ROOT = Path(_nova_sim_dir) / "robots"
|
| 126 |
|
| 127 |
def discover_scene_files(robot: str) -> list[str]:
|
|
@@ -736,6 +766,7 @@ def _handle_gym_ws_message(ws, data):
|
|
| 736 |
"info": _serialize_value(info),
|
| 737 |
},
|
| 738 |
}
|
|
|
|
| 739 |
elif msg_type == "step":
|
| 740 |
action = payload.get("action", [])
|
| 741 |
render = bool(payload.get("render", False))
|
|
@@ -755,9 +786,12 @@ def _handle_gym_ws_message(ws, data):
|
|
| 755 |
if frame_jpeg:
|
| 756 |
response["data"]["frame_jpeg"] = frame_jpeg
|
| 757 |
elif msg_type == "configure":
|
| 758 |
-
robot = payload.get("robot"
|
| 759 |
scene = payload.get("scene")
|
| 760 |
session.configure(robot, scene)
|
|
|
|
|
|
|
|
|
|
| 761 |
response = {
|
| 762 |
"type": "gym_configured",
|
| 763 |
"data": {"robot": session.robot, "scene": session.scene},
|
|
@@ -990,29 +1024,14 @@ def handle_ws_message(ws, data):
|
|
| 990 |
env.set_command(vx, vy, vyaw)
|
| 991 |
|
| 992 |
elif msg_type == 'reset':
|
| 993 |
-
|
| 994 |
-
if env is not None:
|
| 995 |
-
env.reset()
|
| 996 |
-
cam.azimuth = 135
|
| 997 |
-
cam.elevation = -20
|
| 998 |
-
if current_robot == "g1":
|
| 999 |
-
cam.distance = 3.0
|
| 1000 |
-
cam.lookat = np.array([0.0, 0.0, 0.8])
|
| 1001 |
-
elif current_robot in ("ur5", "ur5_t_push"):
|
| 1002 |
-
cam.distance = 1.8
|
| 1003 |
-
cam.lookat = np.array([0.3, 0.0, 0.6])
|
| 1004 |
-
cam.azimuth = 150
|
| 1005 |
-
cam.elevation = -25
|
| 1006 |
-
else:
|
| 1007 |
-
cam.distance = 2.5
|
| 1008 |
-
cam.lookat = np.array([0.0, 0.0, 0.4])
|
| 1009 |
|
| 1010 |
elif msg_type == 'switch_robot':
|
| 1011 |
payload = data.get('data', {})
|
| 1012 |
robot = payload.get('robot', 'g1')
|
| 1013 |
scene = payload.get('scene')
|
| 1014 |
print(f"Robot switch requested: {robot} / scene: {scene}")
|
| 1015 |
-
|
| 1016 |
|
| 1017 |
elif msg_type == 'configure':
|
| 1018 |
payload = data.get('data', {})
|
|
@@ -1020,7 +1039,7 @@ def handle_ws_message(ws, data):
|
|
| 1020 |
scene = payload.get('scene')
|
| 1021 |
if robot:
|
| 1022 |
print(f"Configure requested: {robot} / scene: {scene}")
|
| 1023 |
-
|
| 1024 |
|
| 1025 |
elif msg_type == 'camera':
|
| 1026 |
payload = data.get('data', {})
|
|
@@ -3207,8 +3226,7 @@ def switch_robot_endpoint():
|
|
| 3207 |
scene = payload.get('scene')
|
| 3208 |
if not robot:
|
| 3209 |
return jsonify({"error": "robot is required"}), 400
|
| 3210 |
-
|
| 3211 |
-
needs_robot_switch = {"robot": robot, "scene": scene}
|
| 3212 |
return jsonify({"status": "pending", "robot": robot, "scene": scene}), 202
|
| 3213 |
|
| 3214 |
|
|
|
|
| 122 |
# Camera follow mode
|
| 123 |
camera_follow = True
|
| 124 |
|
| 125 |
+
def _reset_camera_for_current_robot() -> None:
|
| 126 |
+
"""Reset the orbit camera to the defaults for the active robot."""
|
| 127 |
+
cam.azimuth = 135
|
| 128 |
+
cam.elevation = -20
|
| 129 |
+
if current_robot == "g1":
|
| 130 |
+
cam.distance = 3.0
|
| 131 |
+
cam.lookat = np.array([0.0, 0.0, 0.8])
|
| 132 |
+
elif current_robot in ("ur5", "ur5_t_push"):
|
| 133 |
+
cam.distance = 1.8
|
| 134 |
+
cam.lookat = np.array([0.3, 0.0, 0.6])
|
| 135 |
+
cam.azimuth = 150
|
| 136 |
+
cam.elevation = -25
|
| 137 |
+
else:
|
| 138 |
+
cam.distance = 2.5
|
| 139 |
+
cam.lookat = np.array([0.0, 0.0, 0.4])
|
| 140 |
+
|
| 141 |
+
|
| 142 |
+
def _reset_active_environment() -> None:
|
| 143 |
+
"""Reset the primary simulation environment and associated camera."""
|
| 144 |
+
with mujoco_lock:
|
| 145 |
+
if env is not None:
|
| 146 |
+
env.reset()
|
| 147 |
+
_reset_camera_for_current_robot()
|
| 148 |
+
|
| 149 |
+
|
| 150 |
+
def _schedule_robot_switch(robot: str, scene: Optional[str]) -> None:
|
| 151 |
+
"""Schedule a robot/scene switch for the simulation loop."""
|
| 152 |
+
global needs_robot_switch
|
| 153 |
+
needs_robot_switch = {"robot": robot, "scene": scene}
|
| 154 |
+
|
| 155 |
MODEL_ROOT = Path(_nova_sim_dir) / "robots"
|
| 156 |
|
| 157 |
def discover_scene_files(robot: str) -> list[str]:
|
|
|
|
| 766 |
"info": _serialize_value(info),
|
| 767 |
},
|
| 768 |
}
|
| 769 |
+
_reset_active_environment()
|
| 770 |
elif msg_type == "step":
|
| 771 |
action = payload.get("action", [])
|
| 772 |
render = bool(payload.get("render", False))
|
|
|
|
| 786 |
if frame_jpeg:
|
| 787 |
response["data"]["frame_jpeg"] = frame_jpeg
|
| 788 |
elif msg_type == "configure":
|
| 789 |
+
robot = payload.get("robot")
|
| 790 |
scene = payload.get("scene")
|
| 791 |
session.configure(robot, scene)
|
| 792 |
+
if robot:
|
| 793 |
+
print(f"Configure requested (gym): {robot} / scene: {scene}")
|
| 794 |
+
_schedule_robot_switch(robot, scene)
|
| 795 |
response = {
|
| 796 |
"type": "gym_configured",
|
| 797 |
"data": {"robot": session.robot, "scene": session.scene},
|
|
|
|
| 1024 |
env.set_command(vx, vy, vyaw)
|
| 1025 |
|
| 1026 |
elif msg_type == 'reset':
|
| 1027 |
+
_reset_active_environment()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1028 |
|
| 1029 |
elif msg_type == 'switch_robot':
|
| 1030 |
payload = data.get('data', {})
|
| 1031 |
robot = payload.get('robot', 'g1')
|
| 1032 |
scene = payload.get('scene')
|
| 1033 |
print(f"Robot switch requested: {robot} / scene: {scene}")
|
| 1034 |
+
_schedule_robot_switch(robot, scene)
|
| 1035 |
|
| 1036 |
elif msg_type == 'configure':
|
| 1037 |
payload = data.get('data', {})
|
|
|
|
| 1039 |
scene = payload.get('scene')
|
| 1040 |
if robot:
|
| 1041 |
print(f"Configure requested: {robot} / scene: {scene}")
|
| 1042 |
+
_schedule_robot_switch(robot, scene)
|
| 1043 |
|
| 1044 |
elif msg_type == 'camera':
|
| 1045 |
payload = data.get('data', {})
|
|
|
|
| 3226 |
scene = payload.get('scene')
|
| 3227 |
if not robot:
|
| 3228 |
return jsonify({"error": "robot is required"}), 400
|
| 3229 |
+
_schedule_robot_switch(robot, scene)
|
|
|
|
| 3230 |
return jsonify({"status": "pending", "robot": robot, "scene": scene}), 202
|
| 3231 |
|
| 3232 |
|