Spaces:
Sleeping
Sleeping
SemSorter commited on
Commit ·
cca7c61
1
Parent(s): 0f9a8f0
Fix Render Server Crash: Switch to osmesa and lower memory usage
Browse files- Dockerfile +5 -2
- SemSorter/server/agent_bridge.py +2 -2
- SemSorter/simulation/controller.py +7 -4
- requirements-server.txt +0 -1
Dockerfile
CHANGED
|
@@ -10,6 +10,9 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
| 10 |
libglx0 \
|
| 11 |
libx11-6 \
|
| 12 |
libopengl0 \
|
|
|
|
|
|
|
|
|
|
| 13 |
wget \
|
| 14 |
git \
|
| 15 |
&& apt-get clean \
|
|
@@ -32,8 +35,8 @@ RUN git clone --depth 1 --filter=blob:none --sparse https://github.com/google-de
|
|
| 32 |
&& rm -rf .git
|
| 33 |
|
| 34 |
# ── MuJoCo environment ────────────────────────────────────────────────────────
|
| 35 |
-
ENV MUJOCO_GL=
|
| 36 |
-
ENV PYOPENGL_PLATFORM=
|
| 37 |
|
| 38 |
# ── Expose port ───────────────────────────────────────────────────────────────
|
| 39 |
EXPOSE 8000
|
|
|
|
| 10 |
libglx0 \
|
| 11 |
libx11-6 \
|
| 12 |
libopengl0 \
|
| 13 |
+
libosmesa6 \
|
| 14 |
+
libegl-mesa0 \
|
| 15 |
+
libgl1-mesa-dri \
|
| 16 |
wget \
|
| 17 |
git \
|
| 18 |
&& apt-get clean \
|
|
|
|
| 35 |
&& rm -rf .git
|
| 36 |
|
| 37 |
# ── MuJoCo environment ────────────────────────────────────────────────────────
|
| 38 |
+
ENV MUJOCO_GL=osmesa
|
| 39 |
+
ENV PYOPENGL_PLATFORM=osmesa
|
| 40 |
|
| 41 |
# ── Expose port ───────────────────────────────────────────────────────────────
|
| 42 |
EXPOSE 8000
|
SemSorter/server/agent_bridge.py
CHANGED
|
@@ -160,7 +160,7 @@ def get_simulation():
|
|
| 160 |
global _sim
|
| 161 |
with _sim_lock:
|
| 162 |
if _sim is None:
|
| 163 |
-
os.environ.setdefault("MUJOCO_GL", "
|
| 164 |
from controller import SemSorterSimulation
|
| 165 |
logger.info("Initialising MuJoCo simulation…")
|
| 166 |
_sim = SemSorterSimulation()
|
|
@@ -417,7 +417,7 @@ def render_frame(camera: str = "overview"):
|
|
| 417 |
"""
|
| 418 |
with _sim_lock:
|
| 419 |
sim = get_simulation()
|
| 420 |
-
return sim.render_frame(camera=camera, width=
|
| 421 |
|
| 422 |
|
| 423 |
def get_latest_frame_jpeg() -> Optional[bytes]:
|
|
|
|
| 160 |
global _sim
|
| 161 |
with _sim_lock:
|
| 162 |
if _sim is None:
|
| 163 |
+
os.environ.setdefault("MUJOCO_GL", "osmesa")
|
| 164 |
from controller import SemSorterSimulation
|
| 165 |
logger.info("Initialising MuJoCo simulation…")
|
| 166 |
_sim = SemSorterSimulation()
|
|
|
|
| 417 |
"""
|
| 418 |
with _sim_lock:
|
| 419 |
sim = get_simulation()
|
| 420 |
+
return sim.render_frame(camera=camera, width=sim._stream_width, height=sim._stream_height)
|
| 421 |
|
| 422 |
|
| 423 |
def get_latest_frame_jpeg() -> Optional[bytes]:
|
SemSorter/simulation/controller.py
CHANGED
|
@@ -113,8 +113,8 @@ class SemSorterSimulation:
|
|
| 113 |
self._stream_fps_busy = float(
|
| 114 |
os.environ.get("SEMSORTER_STREAM_FPS_BUSY", "30.0")
|
| 115 |
)
|
| 116 |
-
self._stream_width = int(os.environ.get("SEMSORTER_STREAM_WIDTH", "
|
| 117 |
-
self._stream_height = int(os.environ.get("SEMSORTER_STREAM_HEIGHT", "
|
| 118 |
self._freeze_conveyor_when_busy = (
|
| 119 |
os.environ.get("SEMSORTER_FREEZE_CONVEYOR_WHEN_BUSY", "1").strip()
|
| 120 |
in {"1", "true", "yes", "on"}
|
|
@@ -167,8 +167,8 @@ class SemSorterSimulation:
|
|
| 167 |
spec.modelname = "semsorter"
|
| 168 |
|
| 169 |
# Set offscreen framebuffer size for rendering (lowered to save RAM on Render Free Tier)
|
| 170 |
-
spec.visual.global_.offwidth =
|
| 171 |
-
spec.visual.global_.offheight =
|
| 172 |
|
| 173 |
# ─── Add additional lights ───────────────────────────────────────
|
| 174 |
world = spec.worldbody
|
|
@@ -229,6 +229,9 @@ class SemSorterSimulation:
|
|
| 229 |
|
| 230 |
# ─── Compile the model ──────────────────────────────────────────
|
| 231 |
self.model = spec.compile()
|
|
|
|
|
|
|
|
|
|
| 232 |
self.data = mujoco.MjData(self.model)
|
| 233 |
|
| 234 |
# Keep floor contacts in the environment collision group (not robot group).
|
|
|
|
| 113 |
self._stream_fps_busy = float(
|
| 114 |
os.environ.get("SEMSORTER_STREAM_FPS_BUSY", "30.0")
|
| 115 |
)
|
| 116 |
+
self._stream_width = int(os.environ.get("SEMSORTER_STREAM_WIDTH", "480"))
|
| 117 |
+
self._stream_height = int(os.environ.get("SEMSORTER_STREAM_HEIGHT", "270"))
|
| 118 |
self._freeze_conveyor_when_busy = (
|
| 119 |
os.environ.get("SEMSORTER_FREEZE_CONVEYOR_WHEN_BUSY", "1").strip()
|
| 120 |
in {"1", "true", "yes", "on"}
|
|
|
|
| 167 |
spec.modelname = "semsorter"
|
| 168 |
|
| 169 |
# Set offscreen framebuffer size for rendering (lowered to save RAM on Render Free Tier)
|
| 170 |
+
spec.visual.global_.offwidth = self._stream_width
|
| 171 |
+
spec.visual.global_.offheight = self._stream_height
|
| 172 |
|
| 173 |
# ─── Add additional lights ───────────────────────────────────────
|
| 174 |
world = spec.worldbody
|
|
|
|
| 229 |
|
| 230 |
# ─── Compile the model ──────────────────────────────────────────
|
| 231 |
self.model = spec.compile()
|
| 232 |
+
# Further reduce runtime memory allocations by explicitly dropping large arrays
|
| 233 |
+
self.model.opt.disableflags |= mujoco.mjtDisableBit.mjDSBL_EULERDAMP
|
| 234 |
+
self.model.opt.disableflags |= mujoco.mjtDisableBit.mjDSBL_MIDPHASE
|
| 235 |
self.data = mujoco.MjData(self.model)
|
| 236 |
|
| 237 |
# Keep floor contacts in the environment collision group (not robot group).
|
requirements-server.txt
CHANGED
|
@@ -9,7 +9,6 @@ numpy==1.26.4
|
|
| 9 |
|
| 10 |
# MuJoCo (headless, EGL)
|
| 11 |
mujoco==3.5.0
|
| 12 |
-
PyOpenGL-accelerate==3.1.7
|
| 13 |
|
| 14 |
# Google Gemini (legacy + new SDK — both used for compatibility)
|
| 15 |
google-generativeai==0.8.3
|
|
|
|
| 9 |
|
| 10 |
# MuJoCo (headless, EGL)
|
| 11 |
mujoco==3.5.0
|
|
|
|
| 12 |
|
| 13 |
# Google Gemini (legacy + new SDK — both used for compatibility)
|
| 14 |
google-generativeai==0.8.3
|