SemSorter commited on
Commit
0612f0f
·
1 Parent(s): f1f9b36

Optimize MuJoCo render framebuffer cleanup and add explicit GC to video streaming

Browse files
SemSorter/server/agent_bridge.py CHANGED
@@ -542,6 +542,10 @@ def _store_latest_frame(frame) -> None:
542
  _frame_ready_loop.call_soon_threadsafe(_frame_ready_event.set)
543
  except Exception:
544
  pass
 
 
 
 
545
 
546
 
547
  def _pick_place_sync(sim, item_name: str, target) -> bool:
 
542
  _frame_ready_loop.call_soon_threadsafe(_frame_ready_event.set)
543
  except Exception:
544
  pass
545
+
546
+ # Explicit garbage collection helps keep Render 512MB RAM flat
547
+ # during high-frequency JPEG encoding.
548
+ import gc; gc.collect()
549
 
550
 
551
  def _pick_place_sync(sim, item_name: str, target) -> bool:
SemSorter/simulation/controller.py CHANGED
@@ -189,18 +189,6 @@ class SemSorterSimulation:
189
  cam_overview.quat = [0.92, 0.38, 0, 0] # Look slightly down
190
  cam_overview.fovy = 50
191
 
192
- cam_top = world.add_camera()
193
- cam_top.name = "topdown"
194
- cam_top.pos = [0, 0, 2.0]
195
- cam_top.quat = [0.0, 0.0, 0.0, 1.0] # Look straight down
196
- cam_top.fovy = 60
197
-
198
- cam_side = world.add_camera()
199
- cam_side.name = "side"
200
- cam_side.pos = [1.5, 0, 0.8]
201
- cam_side.quat = [0.65, 0.27, 0.27, 0.65] # Side view
202
- cam_side.fovy = 45
203
-
204
  # ─── Add conveyors ──────────────────────────────────────────────
205
  self._add_conveyor(spec, "input", pos=[-0.35, 0.40, 0])
206
  self._add_conveyor(spec, "output", pos=[0.35, 0.40, 0])
@@ -1109,14 +1097,19 @@ class SemSorterSimulation:
1109
  def render_frame(self, width: int = 960, height: int = 540,
1110
  camera: str = "overview") -> np.ndarray:
1111
  """Render a frame from the specified camera. Returns RGB array."""
1112
- if self.renderer is None:
1113
- self.renderer = mujoco.Renderer(self.model, height, width)
1114
 
1115
  cam_id = mujoco.mj_name2id(
1116
  self.model, mujoco.mjtObj.mjOBJ_CAMERA, camera)
1117
 
1118
- self.renderer.update_scene(self.data, camera=cam_id)
1119
- return self.renderer.render()
 
 
 
 
 
 
1120
 
1121
  def _publish_frame_if_needed(self, force: bool = False) -> None:
1122
  """
 
189
  cam_overview.quat = [0.92, 0.38, 0, 0] # Look slightly down
190
  cam_overview.fovy = 50
191
 
 
 
 
 
 
 
 
 
 
 
 
 
192
  # ─── Add conveyors ──────────────────────────────────────────────
193
  self._add_conveyor(spec, "input", pos=[-0.35, 0.40, 0])
194
  self._add_conveyor(spec, "output", pos=[0.35, 0.40, 0])
 
1097
  def render_frame(self, width: int = 960, height: int = 540,
1098
  camera: str = "overview") -> np.ndarray:
1099
  """Render a frame from the specified camera. Returns RGB array."""
1100
+ renderer = mujoco.Renderer(self.model, height, width)
 
1101
 
1102
  cam_id = mujoco.mj_name2id(
1103
  self.model, mujoco.mjtObj.mjOBJ_CAMERA, camera)
1104
 
1105
+ renderer.update_scene(self.data, camera=cam_id)
1106
+ pixels = renderer.render()
1107
+
1108
+ # Explicitly destroy the renderer to free OpenGL framebuffers
1109
+ # saving ~100MB of RAM on the Render.com free tier.
1110
+ renderer.close()
1111
+
1112
+ return pixels
1113
 
1114
  def _publish_frame_if_needed(self, force: bool = False) -> None:
1115
  """