你的名字 commited on
Commit ·
8a45aed
1
Parent(s): d83eabc
Sync Space content from RoboMME_Interactive_Demo_cpu (CPU interactive demo).
Browse files- Dockerfile +2 -4
- README.md +9 -7
- docker-entrypoint.sh +14 -39
- gradio-web/main.py +44 -0
- gradio-web/minimal_maniskill_cpu_step.py +79 -0
- gradio-web/minimal_robomme_env_cpu_step.py +96 -0
- gradio-web/test/test_episode_builder_cpu_backend.py +119 -0
- gradio-web/test/test_main_launch_config.py +102 -1
- human_readme.md +16 -11
- sapien_offscreen.png +0 -0
- src/robomme/__init__.py +28 -0
- src/robomme/env_record_wrapper/episode_config_resolver.py +13 -0
Dockerfile
CHANGED
|
@@ -1,4 +1,4 @@
|
|
| 1 |
-
FROM
|
| 2 |
|
| 3 |
ENV DEBIAN_FRONTEND=noninteractive
|
| 4 |
|
|
@@ -11,10 +11,9 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
| 11 |
git \
|
| 12 |
ffmpeg \
|
| 13 |
libgl1 \
|
| 14 |
-
libglvnd-dev \
|
| 15 |
libglib2.0-0 \
|
| 16 |
libvulkan1 \
|
| 17 |
-
vulkan-
|
| 18 |
&& add-apt-repository ppa:deadsnakes/ppa \
|
| 19 |
&& apt-get update && apt-get install -y --no-install-recommends \
|
| 20 |
python3.11 \
|
|
@@ -32,7 +31,6 @@ RUN useradd -m -u 1000 user
|
|
| 32 |
|
| 33 |
ENV PYTHONUNBUFFERED=1 \
|
| 34 |
PIP_NO_CACHE_DIR=1 \
|
| 35 |
-
NVIDIA_DRIVER_CAPABILITIES=compute,utility,graphics \
|
| 36 |
HOME=/home/user \
|
| 37 |
PATH=/home/user/.local/bin:$PATH \
|
| 38 |
OMP_NUM_THREADS=1 \
|
|
|
|
| 1 |
+
FROM ubuntu:22.04
|
| 2 |
|
| 3 |
ENV DEBIAN_FRONTEND=noninteractive
|
| 4 |
|
|
|
|
| 11 |
git \
|
| 12 |
ffmpeg \
|
| 13 |
libgl1 \
|
|
|
|
| 14 |
libglib2.0-0 \
|
| 15 |
libvulkan1 \
|
| 16 |
+
mesa-vulkan-drivers \
|
| 17 |
&& add-apt-repository ppa:deadsnakes/ppa \
|
| 18 |
&& apt-get update && apt-get install -y --no-install-recommends \
|
| 19 |
python3.11 \
|
|
|
|
| 31 |
|
| 32 |
ENV PYTHONUNBUFFERED=1 \
|
| 33 |
PIP_NO_CACHE_DIR=1 \
|
|
|
|
| 34 |
HOME=/home/user \
|
| 35 |
PATH=/home/user/.local/bin:$PATH \
|
| 36 |
OMP_NUM_THREADS=1 \
|
README.md
CHANGED
|
@@ -2,19 +2,21 @@
|
|
| 2 |
title: RoboMME Oracle Planner
|
| 3 |
sdk: docker
|
| 4 |
app_port: 7860
|
| 5 |
-
arxiv: "2603.04639"
|
| 6 |
---
|
| 7 |
|
| 8 |
-
[Arxiv Paper](https://arxiv.org/abs/2603.04639) | [HF Paper](https://huggingface.co/papers/2603.04639) | [Website](https://robomme.github.io/) | [Benchmark Code](https://github.com/RoboMME/robomme_benchmark) | [Policy Learning Code](https://github.com/RoboMME/robomme_policy_learning)
|
| 9 |
-
|
| 10 |
This Space runs the RoboMME Gradio interface with the Docker SDK.
|
|
|
|
| 11 |
The container entrypoint is defined by the root `Dockerfile` and launches:
|
|
|
|
| 12 |
```bash
|
| 13 |
python3 gradio-web/main.py
|
| 14 |
```
|
|
|
|
| 15 |
`app_file` is intentionally not set here because this is a Docker Space; the application entrypoint comes from Docker `CMD`, while `app_port: 7860` is the external port published by the Space.
|
| 16 |
-
|
|
|
|
|
|
|
| 17 |
```bash
|
| 18 |
-
docker build -t robomme-gradio:
|
| 19 |
-
docker run --rm -
|
| 20 |
-
```
|
|
|
|
| 2 |
title: RoboMME Oracle Planner
|
| 3 |
sdk: docker
|
| 4 |
app_port: 7860
|
|
|
|
| 5 |
---
|
| 6 |
|
|
|
|
|
|
|
| 7 |
This Space runs the RoboMME Gradio interface with the Docker SDK.
|
| 8 |
+
|
| 9 |
The container entrypoint is defined by the root `Dockerfile` and launches:
|
| 10 |
+
|
| 11 |
```bash
|
| 12 |
python3 gradio-web/main.py
|
| 13 |
```
|
| 14 |
+
|
| 15 |
`app_file` is intentionally not set here because this is a Docker Space; the application entrypoint comes from Docker `CMD`, while `app_port: 7860` is the external port published by the Space.
|
| 16 |
+
|
| 17 |
+
Local CPU Docker run:
|
| 18 |
+
|
| 19 |
```bash
|
| 20 |
+
docker build -t robomme-gradio:cpu .
|
| 21 |
+
docker run --rm -p 7860:7860 robomme-gradio:cpu
|
| 22 |
+
```
|
docker-entrypoint.sh
CHANGED
|
@@ -1,50 +1,25 @@
|
|
| 1 |
#!/bin/sh
|
| 2 |
set -eu
|
| 3 |
|
| 4 |
-
pick_vulkan_icd() {
|
| 5 |
-
for candidate in \
|
| 6 |
-
/etc/vulkan/icd.d/nvidia_icd.json \
|
| 7 |
-
/etc/vulkan/icd.d/nvidia_icd.x86_64.json \
|
| 8 |
-
/usr/share/vulkan/icd.d/nvidia_icd.json \
|
| 9 |
-
/usr/share/vulkan/icd.d/nvidia_icd.x86_64.json
|
| 10 |
-
do
|
| 11 |
-
if [ -f "$candidate" ]; then
|
| 12 |
-
printf '%s\n' "$candidate"
|
| 13 |
-
return 0
|
| 14 |
-
fi
|
| 15 |
-
done
|
| 16 |
-
return 1
|
| 17 |
-
}
|
| 18 |
-
|
| 19 |
-
run_diagnostic() {
|
| 20 |
-
label="$1"
|
| 21 |
-
shift
|
| 22 |
-
echo "[entrypoint] $label"
|
| 23 |
-
if "$@"; then
|
| 24 |
-
return 0
|
| 25 |
-
else
|
| 26 |
-
status=$?
|
| 27 |
-
fi
|
| 28 |
-
echo "[entrypoint] $label failed with exit code $status"
|
| 29 |
-
return 0
|
| 30 |
-
}
|
| 31 |
-
|
| 32 |
if [ -z "${OMP_NUM_THREADS:-}" ]; then
|
| 33 |
export OMP_NUM_THREADS=1
|
| 34 |
fi
|
| 35 |
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
echo "[entrypoint] Respecting preset VK_ICD_FILENAMES: $VK_ICD_FILENAMES"
|
| 45 |
fi
|
| 46 |
|
|
|
|
| 47 |
echo "[entrypoint] OMP_NUM_THREADS=$OMP_NUM_THREADS"
|
| 48 |
-
|
| 49 |
-
|
|
|
|
|
|
|
|
|
|
| 50 |
exec "$@"
|
|
|
|
| 1 |
#!/bin/sh
|
| 2 |
set -eu
|
| 3 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4 |
if [ -z "${OMP_NUM_THREADS:-}" ]; then
|
| 5 |
export OMP_NUM_THREADS=1
|
| 6 |
fi
|
| 7 |
|
| 8 |
+
export CUDA_VISIBLE_DEVICES=-1
|
| 9 |
+
export NVIDIA_VISIBLE_DEVICES=void
|
| 10 |
+
export ROBOMME_RENDER_BACKEND="${ROBOMME_RENDER_BACKEND:-pci:0}"
|
| 11 |
+
unset NVIDIA_DRIVER_CAPABILITIES
|
| 12 |
+
unset SAPIEN_RENDER_DEVICE
|
| 13 |
+
unset MUJOCO_GL
|
| 14 |
+
if [ -z "${VK_ICD_FILENAMES:-}" ] && [ -f /usr/share/vulkan/icd.d/lvp_icd.x86_64.json ]; then
|
| 15 |
+
export VK_ICD_FILENAMES=/usr/share/vulkan/icd.d/lvp_icd.x86_64.json
|
|
|
|
| 16 |
fi
|
| 17 |
|
| 18 |
+
echo "[entrypoint] Starting RoboMME Gradio app in CPU-only mode"
|
| 19 |
echo "[entrypoint] OMP_NUM_THREADS=$OMP_NUM_THREADS"
|
| 20 |
+
echo "[entrypoint] CUDA_VISIBLE_DEVICES=$CUDA_VISIBLE_DEVICES"
|
| 21 |
+
echo "[entrypoint] NVIDIA_VISIBLE_DEVICES=$NVIDIA_VISIBLE_DEVICES"
|
| 22 |
+
echo "[entrypoint] ROBOMME_RENDER_BACKEND=$ROBOMME_RENDER_BACKEND"
|
| 23 |
+
echo "[entrypoint] SAPIEN_RENDER_DEVICE=${SAPIEN_RENDER_DEVICE:-<unset>}"
|
| 24 |
+
echo "[entrypoint] VK_ICD_FILENAMES=${VK_ICD_FILENAMES:-<unset>}"
|
| 25 |
exec "$@"
|
gradio-web/main.py
CHANGED
|
@@ -15,6 +15,18 @@ SRC_DIR = PROJECT_ROOT / "src"
|
|
| 15 |
VIDEOS_DIR = APP_DIR / "videos"
|
| 16 |
TEMP_DEMOS_DIR = PROJECT_ROOT / "temp_demos"
|
| 17 |
CWD_TEMP_DEMOS_DIR = Path.cwd() / "temp_demos"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 18 |
|
| 19 |
|
| 20 |
|
|
@@ -27,6 +39,36 @@ if str(SRC_DIR) not in sys.path:
|
|
| 27 |
sys.path.insert(0, str(SRC_DIR))
|
| 28 |
|
| 29 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 30 |
def setup_logging() -> logging.Logger:
|
| 31 |
"""Configure structured logging for Spaces runtime."""
|
| 32 |
level_name = "DEBUG"
|
|
@@ -75,6 +117,7 @@ def log_runtime_graphics_env():
|
|
| 75 |
"NVIDIA_DRIVER_CAPABILITIES",
|
| 76 |
"VK_ICD_FILENAMES",
|
| 77 |
"OMP_NUM_THREADS",
|
|
|
|
| 78 |
"SAPIEN_RENDER_DEVICE",
|
| 79 |
"MUJOCO_GL",
|
| 80 |
]
|
|
@@ -116,6 +159,7 @@ def build_allowed_paths():
|
|
| 116 |
|
| 117 |
|
| 118 |
def main():
|
|
|
|
| 119 |
from ui_layout import CSS, create_ui_blocks
|
| 120 |
|
| 121 |
LOGGER.info("Starting Gradio real environment entrypoint: %s", __file__)
|
|
|
|
| 15 |
VIDEOS_DIR = APP_DIR / "videos"
|
| 16 |
TEMP_DEMOS_DIR = PROJECT_ROOT / "temp_demos"
|
| 17 |
CWD_TEMP_DEMOS_DIR = Path.cwd() / "temp_demos"
|
| 18 |
+
DEFAULT_LLVMPipe_ICD = Path("/usr/share/vulkan/icd.d/lvp_icd.x86_64.json")
|
| 19 |
+
DEFAULT_CPU_RENDER_BACKEND = "pci:0"
|
| 20 |
+
CPU_ONLY_ENV_OVERRIDES = {
|
| 21 |
+
"CUDA_VISIBLE_DEVICES": "-1",
|
| 22 |
+
"NVIDIA_VISIBLE_DEVICES": "void",
|
| 23 |
+
"ROBOMME_RENDER_BACKEND": DEFAULT_CPU_RENDER_BACKEND,
|
| 24 |
+
}
|
| 25 |
+
CPU_ONLY_ENV_CLEAR_KEYS = (
|
| 26 |
+
"NVIDIA_DRIVER_CAPABILITIES",
|
| 27 |
+
"SAPIEN_RENDER_DEVICE",
|
| 28 |
+
"MUJOCO_GL",
|
| 29 |
+
)
|
| 30 |
|
| 31 |
|
| 32 |
|
|
|
|
| 39 |
sys.path.insert(0, str(SRC_DIR))
|
| 40 |
|
| 41 |
|
| 42 |
+
def configure_cpu_only_runtime(logger: logging.Logger | None = None):
|
| 43 |
+
"""Force CPU-only execution before importing project modules."""
|
| 44 |
+
cleared = {}
|
| 45 |
+
for key, value in CPU_ONLY_ENV_OVERRIDES.items():
|
| 46 |
+
os.environ[key] = value
|
| 47 |
+
for key in CPU_ONLY_ENV_CLEAR_KEYS:
|
| 48 |
+
previous = os.environ.pop(key, None)
|
| 49 |
+
if previous is not None:
|
| 50 |
+
cleared[key] = previous
|
| 51 |
+
vk_icd_status = "preserved"
|
| 52 |
+
if "VK_ICD_FILENAMES" not in os.environ:
|
| 53 |
+
if DEFAULT_LLVMPipe_ICD.exists():
|
| 54 |
+
os.environ["VK_ICD_FILENAMES"] = str(DEFAULT_LLVMPipe_ICD)
|
| 55 |
+
vk_icd_status = "auto-set"
|
| 56 |
+
else:
|
| 57 |
+
vk_icd_status = "unavailable"
|
| 58 |
+
if logger is not None:
|
| 59 |
+
logger.info(
|
| 60 |
+
"Configured CPU-only runtime overrides=%s cleared=%s vk_icd_status=%s vk_icd=%s",
|
| 61 |
+
CPU_ONLY_ENV_OVERRIDES,
|
| 62 |
+
cleared,
|
| 63 |
+
vk_icd_status,
|
| 64 |
+
os.environ.get("VK_ICD_FILENAMES"),
|
| 65 |
+
)
|
| 66 |
+
return cleared
|
| 67 |
+
|
| 68 |
+
|
| 69 |
+
configure_cpu_only_runtime()
|
| 70 |
+
|
| 71 |
+
|
| 72 |
def setup_logging() -> logging.Logger:
|
| 73 |
"""Configure structured logging for Spaces runtime."""
|
| 74 |
level_name = "DEBUG"
|
|
|
|
| 117 |
"NVIDIA_DRIVER_CAPABILITIES",
|
| 118 |
"VK_ICD_FILENAMES",
|
| 119 |
"OMP_NUM_THREADS",
|
| 120 |
+
"ROBOMME_RENDER_BACKEND",
|
| 121 |
"SAPIEN_RENDER_DEVICE",
|
| 122 |
"MUJOCO_GL",
|
| 123 |
]
|
|
|
|
| 159 |
|
| 160 |
|
| 161 |
def main():
|
| 162 |
+
configure_cpu_only_runtime(LOGGER)
|
| 163 |
from ui_layout import CSS, create_ui_blocks
|
| 164 |
|
| 165 |
LOGGER.info("Starting Gradio real environment entrypoint: %s", __file__)
|
gradio-web/minimal_maniskill_cpu_step.py
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Minimal ManiSkill CPU sim/render sanity check.
|
| 2 |
+
|
| 3 |
+
This uses an official ManiSkill environment instead of RoboMME wrappers so the
|
| 4 |
+
execution path stays as small as possible.
|
| 5 |
+
"""
|
| 6 |
+
|
| 7 |
+
from __future__ import annotations
|
| 8 |
+
|
| 9 |
+
import argparse
|
| 10 |
+
import os
|
| 11 |
+
import sys
|
| 12 |
+
import warnings
|
| 13 |
+
from pathlib import Path
|
| 14 |
+
|
| 15 |
+
import gymnasium as gym
|
| 16 |
+
import mani_skill.envs # noqa: F401 - registers ManiSkill environments
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
PROJECT_ROOT = Path(__file__).resolve().parents[1]
|
| 20 |
+
SRC_DIR = PROJECT_ROOT / "src"
|
| 21 |
+
|
| 22 |
+
if str(PROJECT_ROOT) not in sys.path:
|
| 23 |
+
sys.path.insert(0, str(PROJECT_ROOT))
|
| 24 |
+
if str(SRC_DIR) not in sys.path:
|
| 25 |
+
sys.path.insert(0, str(SRC_DIR))
|
| 26 |
+
|
| 27 |
+
import robomme # noqa: F401,E402 - applies ManiSkill PCI render-backend patch
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
os.environ.setdefault("ROBOMME_RENDER_BACKEND", "pci:0")
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
warnings.filterwarnings(
|
| 34 |
+
"ignore",
|
| 35 |
+
message=r"CUDA reports that you have .* fork_rng",
|
| 36 |
+
category=UserWarning,
|
| 37 |
+
)
|
| 38 |
+
|
| 39 |
+
|
| 40 |
+
def main() -> None:
|
| 41 |
+
parser = argparse.ArgumentParser()
|
| 42 |
+
parser.add_argument("--env-id", default="PickCube-v1")
|
| 43 |
+
parser.add_argument("--seed", type=int, default=0)
|
| 44 |
+
args = parser.parse_args()
|
| 45 |
+
|
| 46 |
+
env = gym.make(
|
| 47 |
+
args.env_id,
|
| 48 |
+
obs_mode="rgbd",
|
| 49 |
+
control_mode="pd_joint_pos",
|
| 50 |
+
render_mode="rgb_array",
|
| 51 |
+
sim_backend="physx_cpu",
|
| 52 |
+
render_backend=os.environ["ROBOMME_RENDER_BACKEND"],
|
| 53 |
+
)
|
| 54 |
+
|
| 55 |
+
try:
|
| 56 |
+
obs, info = env.reset(seed=args.seed)
|
| 57 |
+
print(f"reset ok: env_id={args.env_id}")
|
| 58 |
+
print(f"obs keys: {list(obs.keys())}")
|
| 59 |
+
print(f"info keys: {list(info.keys())}")
|
| 60 |
+
|
| 61 |
+
action = env.action_space.sample()
|
| 62 |
+
obs, reward, terminated, truncated, info = env.step(action)
|
| 63 |
+
|
| 64 |
+
rgb = obs["sensor_data"]["base_camera"]["rgb"]
|
| 65 |
+
depth = obs["sensor_data"]["base_camera"]["depth"]
|
| 66 |
+
|
| 67 |
+
print("step ok")
|
| 68 |
+
print(f"reward={reward}")
|
| 69 |
+
print(f"terminated={terminated}")
|
| 70 |
+
print(f"truncated={truncated}")
|
| 71 |
+
print(f"rgb shape={tuple(rgb.shape)} dtype={rgb.dtype}")
|
| 72 |
+
print(f"depth shape={tuple(depth.shape)} dtype={depth.dtype}")
|
| 73 |
+
print(f"info keys after step: {list(info.keys())}")
|
| 74 |
+
finally:
|
| 75 |
+
env.close()
|
| 76 |
+
|
| 77 |
+
|
| 78 |
+
if __name__ == "__main__":
|
| 79 |
+
main()
|
gradio-web/minimal_robomme_env_cpu_step.py
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Minimal RoboMME custom-env CPU sanity check.
|
| 2 |
+
|
| 3 |
+
This bypasses BenchmarkEnvBuilder/make_env_for_episode and instantiates a
|
| 4 |
+
RoboMME custom environment class directly.
|
| 5 |
+
"""
|
| 6 |
+
|
| 7 |
+
from __future__ import annotations
|
| 8 |
+
|
| 9 |
+
import argparse
|
| 10 |
+
import faulthandler
|
| 11 |
+
import os
|
| 12 |
+
import sys
|
| 13 |
+
import warnings
|
| 14 |
+
from pathlib import Path
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
PROJECT_ROOT = Path(__file__).resolve().parents[1]
|
| 18 |
+
SRC_DIR = PROJECT_ROOT / "src"
|
| 19 |
+
|
| 20 |
+
if str(PROJECT_ROOT) not in sys.path:
|
| 21 |
+
sys.path.insert(0, str(PROJECT_ROOT))
|
| 22 |
+
if str(SRC_DIR) not in sys.path:
|
| 23 |
+
sys.path.insert(0, str(SRC_DIR))
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
def configure_cpu_only_runtime() -> None:
|
| 27 |
+
os.environ["CUDA_VISIBLE_DEVICES"] = "-1"
|
| 28 |
+
os.environ["NVIDIA_VISIBLE_DEVICES"] = "void"
|
| 29 |
+
os.environ.setdefault("ROBOMME_RENDER_BACKEND", "pci:0")
|
| 30 |
+
os.environ.pop("NVIDIA_DRIVER_CAPABILITIES", None)
|
| 31 |
+
os.environ.pop("SAPIEN_RENDER_DEVICE", None)
|
| 32 |
+
os.environ.pop("MUJOCO_GL", None)
|
| 33 |
+
if "VK_ICD_FILENAMES" not in os.environ:
|
| 34 |
+
lvp_icd = Path("/usr/share/vulkan/icd.d/lvp_icd.x86_64.json")
|
| 35 |
+
if lvp_icd.exists():
|
| 36 |
+
os.environ["VK_ICD_FILENAMES"] = str(lvp_icd)
|
| 37 |
+
|
| 38 |
+
|
| 39 |
+
configure_cpu_only_runtime()
|
| 40 |
+
faulthandler.enable(all_threads=True)
|
| 41 |
+
|
| 42 |
+
warnings.filterwarnings(
|
| 43 |
+
"ignore",
|
| 44 |
+
message=r"CUDA reports that you have .* fork_rng",
|
| 45 |
+
category=UserWarning,
|
| 46 |
+
)
|
| 47 |
+
|
| 48 |
+
|
| 49 |
+
def main() -> None:
|
| 50 |
+
parser = argparse.ArgumentParser()
|
| 51 |
+
parser.add_argument("--env-class", default="StopCube")
|
| 52 |
+
parser.add_argument("--seed", type=int, default=0)
|
| 53 |
+
args = parser.parse_args()
|
| 54 |
+
|
| 55 |
+
import robomme.robomme_env as robomme_env
|
| 56 |
+
from robomme.env_record_wrapper.episode_config_resolver import resolve_render_backend
|
| 57 |
+
|
| 58 |
+
env_cls = getattr(robomme_env, args.env_class)
|
| 59 |
+
env = None
|
| 60 |
+
|
| 61 |
+
print(f"instantiate start: env_class={args.env_class}", flush=True)
|
| 62 |
+
try:
|
| 63 |
+
env = env_cls(
|
| 64 |
+
obs_mode="rgb+depth+segmentation",
|
| 65 |
+
control_mode="pd_joint_pos",
|
| 66 |
+
render_mode="rgb_array",
|
| 67 |
+
reward_mode="dense",
|
| 68 |
+
sim_backend="physx_cpu",
|
| 69 |
+
render_backend=resolve_render_backend(),
|
| 70 |
+
seed=args.seed,
|
| 71 |
+
)
|
| 72 |
+
print("instantiate ok", flush=True)
|
| 73 |
+
|
| 74 |
+
obs, info = env.reset(seed=args.seed)
|
| 75 |
+
print(f"reset ok: obs keys={list(obs.keys())}", flush=True)
|
| 76 |
+
print(f"reset info keys={list(info.keys())}", flush=True)
|
| 77 |
+
|
| 78 |
+
action = env.action_space.sample()
|
| 79 |
+
obs, reward, terminated, truncated, info = env.step(action)
|
| 80 |
+
rgb = obs["sensor_data"]["base_camera"]["rgb"]
|
| 81 |
+
depth = obs["sensor_data"]["base_camera"]["depth"]
|
| 82 |
+
|
| 83 |
+
print("step ok", flush=True)
|
| 84 |
+
print(f"reward={reward}", flush=True)
|
| 85 |
+
print(f"terminated={terminated}", flush=True)
|
| 86 |
+
print(f"truncated={truncated}", flush=True)
|
| 87 |
+
print(f"rgb shape={tuple(rgb.shape)} dtype={rgb.dtype}", flush=True)
|
| 88 |
+
print(f"depth shape={tuple(depth.shape)} dtype={depth.dtype}", flush=True)
|
| 89 |
+
print(f"step info keys={list(info.keys())}", flush=True)
|
| 90 |
+
finally:
|
| 91 |
+
if env is not None:
|
| 92 |
+
env.close()
|
| 93 |
+
|
| 94 |
+
|
| 95 |
+
if __name__ == "__main__":
|
| 96 |
+
main()
|
gradio-web/test/test_episode_builder_cpu_backend.py
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from __future__ import annotations
|
| 2 |
+
|
| 3 |
+
import sys
|
| 4 |
+
import types
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
class _FakeEnv:
|
| 8 |
+
pass
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
class _FakeDemonstrationWrapper:
|
| 12 |
+
last_env = None
|
| 13 |
+
last_kwargs = None
|
| 14 |
+
|
| 15 |
+
def __init__(self, env, **kwargs):
|
| 16 |
+
type(self).last_env = env
|
| 17 |
+
type(self).last_kwargs = kwargs
|
| 18 |
+
self.env = env
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
class _FakeFailAwareWrapper:
|
| 22 |
+
last_env = None
|
| 23 |
+
|
| 24 |
+
def __init__(self, env):
|
| 25 |
+
type(self).last_env = env
|
| 26 |
+
self.env = env
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
def test_builder_make_env_for_episode_forces_cpu_backends(monkeypatch, reload_module):
|
| 30 |
+
resolver = reload_module("robomme.env_record_wrapper.episode_config_resolver")
|
| 31 |
+
captured = {}
|
| 32 |
+
|
| 33 |
+
monkeypatch.setitem(
|
| 34 |
+
sys.modules,
|
| 35 |
+
"robomme.env_record_wrapper.DemonstrationWrapper",
|
| 36 |
+
types.SimpleNamespace(DemonstrationWrapper=_FakeDemonstrationWrapper),
|
| 37 |
+
)
|
| 38 |
+
monkeypatch.setitem(
|
| 39 |
+
sys.modules,
|
| 40 |
+
"robomme.env_record_wrapper.FailAwareWrapper",
|
| 41 |
+
types.SimpleNamespace(FailAwareWrapper=_FakeFailAwareWrapper),
|
| 42 |
+
)
|
| 43 |
+
|
| 44 |
+
def fake_make(env_id, **kwargs):
|
| 45 |
+
captured["env_id"] = env_id
|
| 46 |
+
captured["kwargs"] = kwargs
|
| 47 |
+
return _FakeEnv()
|
| 48 |
+
|
| 49 |
+
monkeypatch.setattr(resolver.gym, "make", fake_make)
|
| 50 |
+
|
| 51 |
+
builder = resolver.BenchmarkEnvBuilder(
|
| 52 |
+
env_id="BinFill",
|
| 53 |
+
dataset="train",
|
| 54 |
+
action_space="joint_angle",
|
| 55 |
+
gui_render=False,
|
| 56 |
+
)
|
| 57 |
+
monkeypatch.setattr(builder, "resolve_episode", lambda episode_idx: (123, "hard"))
|
| 58 |
+
|
| 59 |
+
env = builder.make_env_for_episode(7)
|
| 60 |
+
|
| 61 |
+
assert captured["env_id"] == "BinFill"
|
| 62 |
+
assert captured["kwargs"]["obs_mode"] == "rgb+depth+segmentation"
|
| 63 |
+
assert captured["kwargs"]["control_mode"] == "pd_joint_pos"
|
| 64 |
+
assert captured["kwargs"]["render_mode"] == "rgb_array"
|
| 65 |
+
assert captured["kwargs"]["reward_mode"] == "dense"
|
| 66 |
+
assert captured["kwargs"]["sim_backend"] == "physx_cpu"
|
| 67 |
+
assert captured["kwargs"]["render_backend"] == "pci:0"
|
| 68 |
+
assert captured["kwargs"]["seed"] == 123
|
| 69 |
+
assert captured["kwargs"]["difficulty"] == "hard"
|
| 70 |
+
assert _FakeDemonstrationWrapper.last_kwargs["gui_render"] is False
|
| 71 |
+
assert _FakeFailAwareWrapper.last_env is env.env
|
| 72 |
+
|
| 73 |
+
|
| 74 |
+
def test_builder_make_env_for_episode_honors_render_backend_override(monkeypatch, reload_module):
|
| 75 |
+
resolver = reload_module("robomme.env_record_wrapper.episode_config_resolver")
|
| 76 |
+
captured = {}
|
| 77 |
+
|
| 78 |
+
monkeypatch.setitem(
|
| 79 |
+
sys.modules,
|
| 80 |
+
"robomme.env_record_wrapper.DemonstrationWrapper",
|
| 81 |
+
types.SimpleNamespace(DemonstrationWrapper=_FakeDemonstrationWrapper),
|
| 82 |
+
)
|
| 83 |
+
monkeypatch.setitem(
|
| 84 |
+
sys.modules,
|
| 85 |
+
"robomme.env_record_wrapper.FailAwareWrapper",
|
| 86 |
+
types.SimpleNamespace(FailAwareWrapper=_FakeFailAwareWrapper),
|
| 87 |
+
)
|
| 88 |
+
|
| 89 |
+
def fake_make(env_id, **kwargs):
|
| 90 |
+
captured["env_id"] = env_id
|
| 91 |
+
captured["kwargs"] = kwargs
|
| 92 |
+
return _FakeEnv()
|
| 93 |
+
|
| 94 |
+
monkeypatch.setattr(resolver.gym, "make", fake_make)
|
| 95 |
+
monkeypatch.setenv("ROBOMME_RENDER_BACKEND", "pci:42")
|
| 96 |
+
|
| 97 |
+
builder = resolver.BenchmarkEnvBuilder(
|
| 98 |
+
env_id="BinFill",
|
| 99 |
+
dataset="train",
|
| 100 |
+
action_space="joint_angle",
|
| 101 |
+
gui_render=False,
|
| 102 |
+
)
|
| 103 |
+
monkeypatch.setattr(builder, "resolve_episode", lambda episode_idx: (None, None))
|
| 104 |
+
|
| 105 |
+
builder.make_env_for_episode(1)
|
| 106 |
+
|
| 107 |
+
assert captured["kwargs"]["render_backend"] == "pci:42"
|
| 108 |
+
|
| 109 |
+
|
| 110 |
+
def test_robomme_patches_maniskill_to_preserve_pci_render_backend(reload_module):
|
| 111 |
+
robomme = reload_module("robomme")
|
| 112 |
+
assert robomme is not None
|
| 113 |
+
|
| 114 |
+
from mani_skill.envs.utils.system import backend as ms_backend
|
| 115 |
+
|
| 116 |
+
backend_name, device_id = ms_backend.parse_backend_device_id("pci:0000:00:00.0")
|
| 117 |
+
|
| 118 |
+
assert backend_name == "pci:0000:00:00.0"
|
| 119 |
+
assert device_id is None
|
gradio-web/test/test_main_launch_config.py
CHANGED
|
@@ -1,7 +1,13 @@
|
|
| 1 |
from __future__ import annotations
|
| 2 |
|
|
|
|
| 3 |
import sys
|
| 4 |
import types
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5 |
|
| 6 |
|
| 7 |
class _FakeDemo:
|
|
@@ -15,7 +21,14 @@ class _FakeDemo:
|
|
| 15 |
return None
|
| 16 |
|
| 17 |
|
| 18 |
-
def
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 19 |
main = reload_module("main")
|
| 20 |
fake_demo = _FakeDemo()
|
| 21 |
fake_ui_layout = types.SimpleNamespace(
|
|
@@ -25,6 +38,12 @@ def test_main_launch_passes_ui_css(monkeypatch, reload_module):
|
|
| 25 |
|
| 26 |
monkeypatch.setitem(sys.modules, "ui_layout", fake_ui_layout)
|
| 27 |
monkeypatch.setenv("PORT", "7861")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 28 |
|
| 29 |
main.main()
|
| 30 |
|
|
@@ -34,3 +53,85 @@ def test_main_launch_passes_ui_css(monkeypatch, reload_module):
|
|
| 34 |
assert fake_demo.launch_kwargs["theme"] == fake_demo.theme
|
| 35 |
assert fake_demo.launch_kwargs["css"] == fake_ui_layout.CSS
|
| 36 |
assert fake_demo.launch_kwargs["head"] == fake_demo.head
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
from __future__ import annotations
|
| 2 |
|
| 3 |
+
import os
|
| 4 |
import sys
|
| 5 |
import types
|
| 6 |
+
from pathlib import Path
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
DEFAULT_LLVMPipe_ICD = "/usr/share/vulkan/icd.d/lvp_icd.x86_64.json"
|
| 10 |
+
DEFAULT_CPU_RENDER_BACKEND = "pci:0"
|
| 11 |
|
| 12 |
|
| 13 |
class _FakeDemo:
|
|
|
|
| 21 |
return None
|
| 22 |
|
| 23 |
|
| 24 |
+
def test_main_launch_passes_ui_css_and_forces_cpu_runtime(monkeypatch, reload_module):
|
| 25 |
+
monkeypatch.setenv("CUDA_VISIBLE_DEVICES", "0")
|
| 26 |
+
monkeypatch.setenv("NVIDIA_VISIBLE_DEVICES", "all")
|
| 27 |
+
monkeypatch.setenv("SAPIEN_RENDER_DEVICE", "cuda")
|
| 28 |
+
monkeypatch.setenv("NVIDIA_DRIVER_CAPABILITIES", "compute,utility,graphics")
|
| 29 |
+
monkeypatch.setenv("VK_ICD_FILENAMES", "/tmp/nvidia_icd.json")
|
| 30 |
+
monkeypatch.setenv("MUJOCO_GL", "egl")
|
| 31 |
+
|
| 32 |
main = reload_module("main")
|
| 33 |
fake_demo = _FakeDemo()
|
| 34 |
fake_ui_layout = types.SimpleNamespace(
|
|
|
|
| 38 |
|
| 39 |
monkeypatch.setitem(sys.modules, "ui_layout", fake_ui_layout)
|
| 40 |
monkeypatch.setenv("PORT", "7861")
|
| 41 |
+
monkeypatch.setenv("CUDA_VISIBLE_DEVICES", "2")
|
| 42 |
+
monkeypatch.setenv("NVIDIA_VISIBLE_DEVICES", "all")
|
| 43 |
+
monkeypatch.setenv("SAPIEN_RENDER_DEVICE", "cuda")
|
| 44 |
+
monkeypatch.setenv("NVIDIA_DRIVER_CAPABILITIES", "graphics")
|
| 45 |
+
monkeypatch.setenv("VK_ICD_FILENAMES", "/tmp/another_nvidia_icd.json")
|
| 46 |
+
monkeypatch.setenv("MUJOCO_GL", "egl")
|
| 47 |
|
| 48 |
main.main()
|
| 49 |
|
|
|
|
| 53 |
assert fake_demo.launch_kwargs["theme"] == fake_demo.theme
|
| 54 |
assert fake_demo.launch_kwargs["css"] == fake_ui_layout.CSS
|
| 55 |
assert fake_demo.launch_kwargs["head"] == fake_demo.head
|
| 56 |
+
assert os.environ["CUDA_VISIBLE_DEVICES"] == "-1"
|
| 57 |
+
assert os.environ["NVIDIA_VISIBLE_DEVICES"] == "void"
|
| 58 |
+
assert os.environ["ROBOMME_RENDER_BACKEND"] == DEFAULT_CPU_RENDER_BACKEND
|
| 59 |
+
assert os.environ["VK_ICD_FILENAMES"] == "/tmp/another_nvidia_icd.json"
|
| 60 |
+
assert "NVIDIA_DRIVER_CAPABILITIES" not in os.environ
|
| 61 |
+
assert "SAPIEN_RENDER_DEVICE" not in os.environ
|
| 62 |
+
assert "MUJOCO_GL" not in os.environ
|
| 63 |
+
|
| 64 |
+
|
| 65 |
+
def test_configure_cpu_only_runtime_autosets_llvmpipe_icd(monkeypatch, reload_module):
|
| 66 |
+
original_exists = Path.exists
|
| 67 |
+
|
| 68 |
+
def fake_exists(self):
|
| 69 |
+
if str(self) == DEFAULT_LLVMPipe_ICD:
|
| 70 |
+
return True
|
| 71 |
+
return original_exists(self)
|
| 72 |
+
|
| 73 |
+
monkeypatch.setattr(Path, "exists", fake_exists)
|
| 74 |
+
monkeypatch.delenv("VK_ICD_FILENAMES", raising=False)
|
| 75 |
+
monkeypatch.setenv("CUDA_VISIBLE_DEVICES", "3")
|
| 76 |
+
monkeypatch.setenv("NVIDIA_VISIBLE_DEVICES", "all")
|
| 77 |
+
monkeypatch.setenv("SAPIEN_RENDER_DEVICE", "cuda")
|
| 78 |
+
monkeypatch.setenv("NVIDIA_DRIVER_CAPABILITIES", "graphics")
|
| 79 |
+
monkeypatch.setenv("MUJOCO_GL", "egl")
|
| 80 |
+
|
| 81 |
+
main = reload_module("main")
|
| 82 |
+
monkeypatch.delenv("VK_ICD_FILENAMES", raising=False)
|
| 83 |
+
|
| 84 |
+
main.configure_cpu_only_runtime()
|
| 85 |
+
|
| 86 |
+
assert os.environ["CUDA_VISIBLE_DEVICES"] == "-1"
|
| 87 |
+
assert os.environ["NVIDIA_VISIBLE_DEVICES"] == "void"
|
| 88 |
+
assert os.environ["ROBOMME_RENDER_BACKEND"] == DEFAULT_CPU_RENDER_BACKEND
|
| 89 |
+
assert os.environ["VK_ICD_FILENAMES"] == DEFAULT_LLVMPipe_ICD
|
| 90 |
+
assert "NVIDIA_DRIVER_CAPABILITIES" not in os.environ
|
| 91 |
+
assert "SAPIEN_RENDER_DEVICE" not in os.environ
|
| 92 |
+
assert "MUJOCO_GL" not in os.environ
|
| 93 |
+
|
| 94 |
+
|
| 95 |
+
def test_configure_cpu_only_runtime_preserves_existing_vk_icd(monkeypatch, reload_module):
|
| 96 |
+
monkeypatch.setenv("CUDA_VISIBLE_DEVICES", "4")
|
| 97 |
+
monkeypatch.setenv("NVIDIA_VISIBLE_DEVICES", "all")
|
| 98 |
+
monkeypatch.setenv("ROBOMME_RENDER_BACKEND", "pci:9")
|
| 99 |
+
monkeypatch.setenv("SAPIEN_RENDER_DEVICE", "cuda")
|
| 100 |
+
monkeypatch.setenv("NVIDIA_DRIVER_CAPABILITIES", "graphics")
|
| 101 |
+
monkeypatch.setenv("VK_ICD_FILENAMES", "/tmp/custom_icd.json")
|
| 102 |
+
monkeypatch.setenv("MUJOCO_GL", "egl")
|
| 103 |
+
|
| 104 |
+
main = reload_module("main")
|
| 105 |
+
monkeypatch.setenv("CUDA_VISIBLE_DEVICES", "5")
|
| 106 |
+
monkeypatch.setenv("NVIDIA_VISIBLE_DEVICES", "all")
|
| 107 |
+
monkeypatch.setenv("ROBOMME_RENDER_BACKEND", "pci:7")
|
| 108 |
+
monkeypatch.setenv("SAPIEN_RENDER_DEVICE", "cuda")
|
| 109 |
+
monkeypatch.setenv("NVIDIA_DRIVER_CAPABILITIES", "graphics")
|
| 110 |
+
monkeypatch.setenv("VK_ICD_FILENAMES", "/tmp/preserved_icd.json")
|
| 111 |
+
monkeypatch.setenv("MUJOCO_GL", "egl")
|
| 112 |
+
|
| 113 |
+
main.configure_cpu_only_runtime()
|
| 114 |
+
|
| 115 |
+
assert os.environ["CUDA_VISIBLE_DEVICES"] == "-1"
|
| 116 |
+
assert os.environ["NVIDIA_VISIBLE_DEVICES"] == "void"
|
| 117 |
+
assert os.environ["ROBOMME_RENDER_BACKEND"] == "pci:0"
|
| 118 |
+
assert os.environ["VK_ICD_FILENAMES"] == "/tmp/preserved_icd.json"
|
| 119 |
+
assert "NVIDIA_DRIVER_CAPABILITIES" not in os.environ
|
| 120 |
+
assert "SAPIEN_RENDER_DEVICE" not in os.environ
|
| 121 |
+
assert "MUJOCO_GL" not in os.environ
|
| 122 |
+
|
| 123 |
+
|
| 124 |
+
def test_configure_cpu_only_runtime_clears_stale_sapien_render_device(monkeypatch, reload_module):
|
| 125 |
+
monkeypatch.setenv("SAPIEN_RENDER_DEVICE", "cpu")
|
| 126 |
+
monkeypatch.setenv("CUDA_VISIBLE_DEVICES", "7")
|
| 127 |
+
monkeypatch.setenv("NVIDIA_VISIBLE_DEVICES", "all")
|
| 128 |
+
|
| 129 |
+
main = reload_module("main")
|
| 130 |
+
monkeypatch.setenv("SAPIEN_RENDER_DEVICE", "cuda:0")
|
| 131 |
+
|
| 132 |
+
main.configure_cpu_only_runtime()
|
| 133 |
+
|
| 134 |
+
assert os.environ["CUDA_VISIBLE_DEVICES"] == "-1"
|
| 135 |
+
assert os.environ["NVIDIA_VISIBLE_DEVICES"] == "void"
|
| 136 |
+
assert os.environ["ROBOMME_RENDER_BACKEND"] == DEFAULT_CPU_RENDER_BACKEND
|
| 137 |
+
assert "SAPIEN_RENDER_DEVICE" not in os.environ
|
human_readme.md
CHANGED
|
@@ -15,7 +15,7 @@ uv sync
|
|
| 15 |
uv pip install -e .
|
| 16 |
```
|
| 17 |
|
| 18 |
-
## 🐳 Gradio Docker Deployment (HF Space
|
| 19 |
|
| 20 |
This repository also supports Docker deployment for the Gradio app entrypoint:
|
| 21 |
|
|
@@ -26,23 +26,23 @@ python3 gradio-web/main.py
|
|
| 26 |
Build image:
|
| 27 |
|
| 28 |
```bash
|
| 29 |
-
docker build -t robomme-gradio:
|
| 30 |
```
|
| 31 |
|
| 32 |
-
Run container
|
| 33 |
|
| 34 |
```bash
|
| 35 |
-
docker run --rm -
|
| 36 |
```
|
| 37 |
|
| 38 |
-
The
|
| 39 |
|
| 40 |
Optional metadata override:
|
| 41 |
|
| 42 |
```bash
|
| 43 |
-
docker run --rm -
|
| 44 |
-e ROBOMME_METADATA_ROOT=/home/user/app/src/robomme/env_metadata/train \
|
| 45 |
-
robomme-gradio:
|
| 46 |
```
|
| 47 |
|
| 48 |
Notes:
|
|
@@ -148,13 +148,18 @@ Want to add your model? Download the [dataset](https://huggingface.co/datasets/Y
|
|
| 148 |
|
| 149 |
A1: Use a physical display or set up a virtual display for GUI rendering (e.g. install a VNC server and set the `DISPLAY` variable correctly).
|
| 150 |
|
| 151 |
-
**Q2: Failure related to
|
| 152 |
|
| 153 |
-
A2:
|
| 154 |
|
| 155 |
```python
|
| 156 |
-
os.environ['
|
| 157 |
-
os.environ['
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 158 |
```
|
| 159 |
|
| 160 |
|
|
|
|
| 15 |
uv pip install -e .
|
| 16 |
```
|
| 17 |
|
| 18 |
+
## 🐳 Gradio Docker Deployment (HF Space CPU-only)
|
| 19 |
|
| 20 |
This repository also supports Docker deployment for the Gradio app entrypoint:
|
| 21 |
|
|
|
|
| 26 |
Build image:
|
| 27 |
|
| 28 |
```bash
|
| 29 |
+
docker build -t robomme-gradio:cpu .
|
| 30 |
```
|
| 31 |
|
| 32 |
+
Run container:
|
| 33 |
|
| 34 |
```bash
|
| 35 |
+
docker run --rm -p 7860:7860 robomme-gradio:cpu
|
| 36 |
```
|
| 37 |
|
| 38 |
+
The container forces CPU-only ManiSkill/SAPIEN backends and does not require NVIDIA runtime or `--gpus all`, which keeps it aligned with Hugging Face Docker Spaces CPU deployments.
|
| 39 |
|
| 40 |
Optional metadata override:
|
| 41 |
|
| 42 |
```bash
|
| 43 |
+
docker run --rm -p 7860:7860 \
|
| 44 |
-e ROBOMME_METADATA_ROOT=/home/user/app/src/robomme/env_metadata/train \
|
| 45 |
+
robomme-gradio:cpu
|
| 46 |
```
|
| 47 |
|
| 48 |
Notes:
|
|
|
|
| 148 |
|
| 149 |
A1: Use a physical display or set up a virtual display for GUI rendering (e.g. install a VNC server and set the `DISPLAY` variable correctly).
|
| 150 |
|
| 151 |
+
**Q2: Failure related to ManiSkill/SAPIEN rendering initialization.**
|
| 152 |
|
| 153 |
+
A2: This Docker image is configured for CPU-only execution and should not rely on NVIDIA runtime settings. If rendering still fails, first check that no external environment variables are forcing GPU paths, then keep the container on the CPU-only defaults:
|
| 154 |
|
| 155 |
```python
|
| 156 |
+
os.environ['CUDA_VISIBLE_DEVICES'] = '-1'
|
| 157 |
+
os.environ['NVIDIA_VISIBLE_DEVICES'] = 'void'
|
| 158 |
+
os.environ.setdefault('ROBOMME_RENDER_BACKEND', 'pci:0') # llvmpipe software Vulkan on CPU
|
| 159 |
+
os.environ.pop('SAPIEN_RENDER_DEVICE', None)
|
| 160 |
+
os.environ.pop('NVIDIA_DRIVER_CAPABILITIES', None)
|
| 161 |
+
os.environ.pop('MUJOCO_GL', None)
|
| 162 |
+
os.environ.setdefault('VK_ICD_FILENAMES', '/usr/share/vulkan/icd.d/lvp_icd.x86_64.json')
|
| 163 |
```
|
| 164 |
|
| 165 |
|
sapien_offscreen.png
ADDED
|
src/robomme/__init__.py
CHANGED
|
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""RoboMME package initialization."""
|
| 2 |
+
|
| 3 |
+
from __future__ import annotations
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
def _patch_maniskill_pci_render_backend() -> None:
|
| 7 |
+
"""Allow ManiSkill to pass PCI-style Vulkan device strings through intact."""
|
| 8 |
+
try:
|
| 9 |
+
from mani_skill.envs.utils.system import backend as ms_backend
|
| 10 |
+
except Exception:
|
| 11 |
+
return
|
| 12 |
+
|
| 13 |
+
if getattr(ms_backend, "_robomme_pci_backend_patch", False):
|
| 14 |
+
return
|
| 15 |
+
|
| 16 |
+
original = ms_backend.parse_backend_device_id
|
| 17 |
+
|
| 18 |
+
def patched_parse_backend_device_id(backend: str):
|
| 19 |
+
if isinstance(backend, str) and backend.startswith("pci:"):
|
| 20 |
+
return backend, None
|
| 21 |
+
return original(backend)
|
| 22 |
+
|
| 23 |
+
ms_backend.parse_backend_device_id = patched_parse_backend_device_id
|
| 24 |
+
ms_backend._robomme_pci_backend_patch = True
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
_patch_maniskill_pci_render_backend()
|
| 28 |
+
|
src/robomme/env_record_wrapper/episode_config_resolver.py
CHANGED
|
@@ -14,6 +14,7 @@ DATASET_ROOT = Path(__file__).resolve().parents[1] / "env_metadata"
|
|
| 14 |
|
| 15 |
_ALLOWED_DATASETS = {"train", "test"}
|
| 16 |
_ALLOWED_ACTION_SPACES = {"joint_angle", "ee_pose", "waypoint", "multi_choice"}
|
|
|
|
| 17 |
_DEFAULT_TASK_LIST = [
|
| 18 |
"PickXtimes",
|
| 19 |
"StopCube",
|
|
@@ -87,6 +88,16 @@ def get_episode_metadata(
|
|
| 87 |
return metadata_index.get((task, episode))
|
| 88 |
|
| 89 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 90 |
class BenchmarkEnvBuilder:
|
| 91 |
"""
|
| 92 |
Episode environment builder.
|
|
@@ -195,6 +206,8 @@ class BenchmarkEnvBuilder:
|
|
| 195 |
control_mode="pd_joint_pos",
|
| 196 |
render_mode=self.render_mode,
|
| 197 |
reward_mode="dense",
|
|
|
|
|
|
|
| 198 |
)
|
| 199 |
if seed is not None:
|
| 200 |
env_kwargs["seed"] = seed
|
|
|
|
| 14 |
|
| 15 |
_ALLOWED_DATASETS = {"train", "test"}
|
| 16 |
_ALLOWED_ACTION_SPACES = {"joint_angle", "ee_pose", "waypoint", "multi_choice"}
|
| 17 |
+
_DEFAULT_CPU_RENDER_BACKEND = "pci:0"
|
| 18 |
_DEFAULT_TASK_LIST = [
|
| 19 |
"PickXtimes",
|
| 20 |
"StopCube",
|
|
|
|
| 88 |
return metadata_index.get((task, episode))
|
| 89 |
|
| 90 |
|
| 91 |
+
def resolve_render_backend(default: str = _DEFAULT_CPU_RENDER_BACKEND) -> str:
|
| 92 |
+
"""Resolve the render backend for CPU-only execution.
|
| 93 |
+
|
| 94 |
+
Docker CPU mode uses llvmpipe, which SAPIEN exposes as a Vulkan PCI device
|
| 95 |
+
rather than the string "cpu".
|
| 96 |
+
"""
|
| 97 |
+
value = str(os.environ.get("ROBOMME_RENDER_BACKEND", default)).strip()
|
| 98 |
+
return value or default
|
| 99 |
+
|
| 100 |
+
|
| 101 |
class BenchmarkEnvBuilder:
|
| 102 |
"""
|
| 103 |
Episode environment builder.
|
|
|
|
| 206 |
control_mode="pd_joint_pos",
|
| 207 |
render_mode=self.render_mode,
|
| 208 |
reward_mode="dense",
|
| 209 |
+
sim_backend="physx_cpu",
|
| 210 |
+
render_backend=resolve_render_backend(),
|
| 211 |
)
|
| 212 |
if seed is not None:
|
| 213 |
env_kwargs["seed"] = seed
|