Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,9 @@ dist/

# docs
docs/_build/

# Per-package local working artifacts (raw rollouts/plots/profiles kept locally for
# observation; never committed - curated small clips go in each package's assets/)
packages/**/artifacts/
# Repo-root holding for artifacts pending manual package assignment (never committed)
artifacts_unsorted/
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,10 @@ These dockerfiles will also be pushed and actively maintained in their original
| LLM | [`ollama`](packages/llm/ollama), [`llamacpp`](packages/llm/llamacpp), [`lmstudio`](packages/llm/lmstudio), [`GEPA`](packages/llm/gepa), [`Lemonade`](packages/llm/lemonade-sdk) |
| VLM | [`Gemma3`](packages/vlm/gemma3), [`SmolVLM`](packages/vlm/smolvlm), [`Phi-4`](packages/vlm/phi4), [`LFM2-VL`](packages/vlm/lfm2vl) |
| VLA | [`OpenVLA`](packages/vla/openvla), [`SmolVLA`](packages/vla/smolvla), [`GR00T-N1.5`](packages/vla/gr00t), [`openpi`](packages/vla/openpi), [`CogACT`](packages/vla/cogact), [`MolmoAct`](packages/vla/molmoact), [`MolmoAct2`](packages/vla/molmoact2) |
| WAM | [`FastWAM`](packages/wam/fastwam) |
| Graphics | [`O3DE`](packages/graphics/o3de) |
| Robotics | [`ROS 2`](packages/ros/ros), [`Gazebo`](packages/ros/gazebo), [`LeRobot`](packages/robotics/lerobot), [`ACT`](packages/robotics/act), [`RAI`](packages/robotics/rai), [`CaP-X`](packages/robotics/capx) |
| Simulation | [`Genesis`](packages/robotics/genesis), [`PyDrake`](packages/robotics/pydrake) |
| Simulation | [`Genesis`](packages/robotics/genesis), [`PyDrake`](packages/robotics/pydrake), [`LIBERO`](packages/simulation/libero), [`RoboTwin`](packages/simulation/robotwin) |
| Vision | [`OpenCV`](packages/vision/opencv), [`SAM`](packages/vision/sam), [`MobileSAM`](packages/vision/mobilesam), [`ncnn`](packages/vision/ncnn), [`DINOv3`](packages/vision/dinov3), [`SAM3`](packages/vision/sam3), [`Ultralytics`](packages/vision/ultralytics) |
| Ryzen AI NPU | [`XDNA`](packages/npu/xdna), [`IRON`](packages/npu/iron), [`NPUEval`](packages/npu/npueval), [`Ryzen AI CVML`](packages/npu/ryzenai_cvml) |
| Adaptive SoCs | [`PYNQ.remote`](packages/adaptive-socs/pynq-remote) |
Expand Down
52 changes: 52 additions & 0 deletions packages/simulation/libero/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Copyright(C) 2026 Advanced Micro Devices, Inc. All rights reserved.
# SPDX-License-Identifier: MIT
#
# Model-agnostic LIBERO sim base for Strix Halo (gfx1151): LIBERO/MuJoCo/robosuite
# closed-loop stack (headless EGL) + sim_libero harness. Policies chain on top and
# are selected at runtime via POLICY_FACTORY; weights/datasets are never baked here.

ARG BASE_IMAGE
FROM ${BASE_IMAGE}

ENV DEBIAN_FRONTEND=noninteractive \
HF_HUB_DISABLE_TELEMETRY=1 \
TOKENIZERS_PARALLELISM=false

WORKDIR /ryzers

RUN apt-get update && \
apt-get install -y --no-install-recommends \
git cmake build-essential \
libegl-dev libgles-dev libosmesa6-dev libglew-dev libglu1-mesa libglu1-mesa-dev && \
rm -rf /var/lib/apt/lists/*

# numpy pinned 1.26.4 (robosuite numba has no py3.12/numpy-2 wheel); constraint keeps the
# base ROCm torch+numpy. LIBERO installs --no-deps; missing runtime imports added explicitly.
# libero ships no top-level __init__.py, so PYTHONPATH resolves it.
ENV PYTHONPATH=/opt/LIBERO:/opt/sim
RUN pip install --no-cache-dir "numpy==1.26.4" && \
pip freeze | grep -iE "^(torch|torchvision|torchcodec|numpy)==" > /opt/torch-constraints.txt && \
PIP_CONSTRAINT=/opt/torch-constraints.txt pip install --no-cache-dir \
"robosuite==1.4.0" "bddl==1.0.1" "mujoco==3.3.2" easydict thop \
"future==1.0.0" "cloudpickle==3.1.2" "gym==0.25.2" termcolor \
"imageio>=2.34" "imageio-ffmpeg>=0.5" "pillow>=10" && \
git clone --depth 1 https://github.com/Lifelong-Robot-Learning/LIBERO /opt/LIBERO && \
PIP_CONSTRAINT=/opt/torch-constraints.txt pip install --no-cache-dir --no-deps -e /opt/LIBERO

# The sim harness (Policy seam + runners + RandomPolicy).
COPY lib/ /opt/sim/

# torch.load compat shim as a startup .pth so it applies to every Python process
# (incl. a policy's own eval script). See _torch_compat.
RUN cp /opt/sim/sim_libero_compat.pth "$(python -c 'import sysconfig; print(sysconfig.get_paths()["purelib"])')/"

# First `import libero.libero` prompts to write ~/.libero/config.yaml; feed defaults so it
# bakes in and never prompts at runtime. Also verifies the stack imports (no GPU render at
# build time; the sanity demo exercises rendering at run time).
RUN printf 'N\nN\nN\nN\nN\n' | python -c "import mujoco, robosuite; from libero.libero import benchmark; from libero.libero.envs import OffScreenRenderEnv; import sim_libero; from sim_libero.policy import load_policy; print('OK mujoco', mujoco.__version__, '| sim_libero + LIBERO envs import cleanly')"

COPY test.py /ryzers/
COPY demos/ /ryzers/demos/
RUN chmod +x /ryzers/demos/*.sh

CMD ["python", "/ryzers/test.py"]
31 changes: 31 additions & 0 deletions packages/simulation/libero/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
### LIBERO

This package provides the LIBERO simulation base (MuJoCo/EGL) as a Ryzer on AMD Ryzen AI
Max+ 395 (Strix Halo, gfx1151) under ROCm 7.14. It exposes a model-agnostic `Policy` seam

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would remove specific callout to 395 and rocm 7.14

that WAM and VLA packages chain on for closed-loop and interactive rollouts.

### Build

```sh
ryzers build libero
ryzers run # test.py: sim import + headless render sign-of-life
```

### Example: LIBERO with FastWAM

```sh
ryzers build libero fastwam --name fastwam-libero
ryzers run --name fastwam-libero /ryzers/demos/demo_closedloop_libero.sh
```

<p align="center">
<img src="assets/libero_fastwam.gif" width="480">
<br><em>FastWAM closed-loop rollout in LIBERO.</em>
</p>

### References

- Upstream: https://github.com/Lifelong-Robot-Learning/LIBERO (the Dockerfile shallow-clones the default branch)

Copyright (C) 2026 Advanced Micro Devices, Inc. All rights reserved.
SPDX-License-Identifier: MIT
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
34 changes: 34 additions & 0 deletions packages/simulation/libero/config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Copyright(C) 2026 Advanced Micro Devices, Inc. All rights reserved.
# SPDX-License-Identifier: MIT

# ROCm 7.14 base (rocm/pytorch torch 2.10.0).
init_image: rocm/pytorch:rocm7.14_ubuntu24.04_py3.12_pytorch_release_2.10.0

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why overriding default rocm7.14 image?

# Model-agnostic sim base; chain a policy: ryzers build libero <policy>

gpu_support: true
x11_display: false

environment_variables:
- "HSA_OVERRIDE_GFX_VERSION=11.5.1"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't need HSA_OVERRIDE anymore

- "MUJOCO_GL=egl"
- "PYOPENGL_PLATFORM=egl"
- "TORCH_ROCM_AOTRITON_ENABLE_EXPERIMENTAL=1"
- "TORCH_BLAS_PREFER_HIPBLASLT=0"
# Distinct mount target so this base's outputs don't collide with a chained policy's /outputs.
- "OUT_DIR=/sim_outputs"
# Sim/harness knobs (override from the host: VAR=... ryzers run /ryzers/demos/demo_*.sh).
- 'SUITE=${SUITE:-}'
- 'TASK_ID=${TASK_ID:-}'
- 'SEED=${SEED:-}'
- 'STEPS=${STEPS:-}'
- 'PORT=${PORT:-}'
- 'VIEW_RES=${VIEW_RES:-}'
- 'VIDEO_RES=${VIDEO_RES:-}'
- 'RENDER_RES=${RENDER_RES:-}'
- 'MAX_STEPS=${MAX_STEPS:-}'
- 'RT_HZ=${RT_HZ:-}'
# Policy selection: module:function returning a sim_libero.Policy (default RandomPolicy).
- 'POLICY_FACTORY=${POLICY_FACTORY:-}'

volume_mappings:
- "$PWD/workspace/simulation-libero/outputs:/sim_outputs"
15 changes: 15 additions & 0 deletions packages/simulation/libero/demos/demo_interactive.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/usr/bin/env bash
# Copyright(C) 2026 Advanced Micro Devices, Inc. All rights reserved.
# SPDX-License-Identifier: MIT
#
# Interactive LIBERO demo (chunk-replay) over HTTP/MJPEG. Default RandomPolicy; set
# POLICY_FACTORY for a real model. View at http://localhost:PORT (ssh -L PORT:localhost:PORT <host>).
# ryzers run /ryzers/demos/demo_interactive.sh
# POLICY_FACTORY=fastwam_libero_policy:build_policy ryzers run /ryzers/demos/demo_interactive.sh
set -euo pipefail
export SUITE="${SUITE:-libero_object}"
export TASK_ID="${TASK_ID:-0}"
export SEED="${SEED:-1000}"
export PORT="${PORT:-8080}"
export OUT_DIR="${OUT_DIR:-/sim_outputs}"
exec python -m sim_libero.interactive_server
17 changes: 17 additions & 0 deletions packages/simulation/libero/demos/demo_interactive_rt.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/usr/bin/env bash
# Copyright(C) 2026 Advanced Micro Devices, Inc. All rights reserved.
# SPDX-License-Identifier: MIT
#
# Real-time LIBERO demo: sim steps at wall-clock RT_HZ and the robot HOLDs while the
# policy plans, so latency is visible. Default RandomPolicy; set POLICY_FACTORY for a model.
# View at http://localhost:PORT (ssh -L PORT:localhost:PORT <host>).
# ryzers run /ryzers/demos/demo_interactive_rt.sh
# POLICY_FACTORY=fastwam_libero_policy:build_policy ryzers run /ryzers/demos/demo_interactive_rt.sh
set -euo pipefail
export SUITE="${SUITE:-libero_object}"
export TASK_ID="${TASK_ID:-0}"
export SEED="${SEED:-1000}"
export PORT="${PORT:-8081}"
export RT_HZ="${RT_HZ:-20}"
export OUT_DIR="${OUT_DIR:-/sim_outputs}"
exec python -m sim_libero.interactive_server_rt
15 changes: 15 additions & 0 deletions packages/simulation/libero/demos/demo_sim_sanity.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/usr/bin/env bash
# Copyright(C) 2026 Advanced Micro Devices, Inc. All rights reserved.
# SPDX-License-Identifier: MIT
#
# Model-free sanity rollout: rolls the built-in RandomPolicy through one scene on the
# iGPU (headless EGL) and saves an MP4. Exercises the ROCm/EGL render + MuJoCo + encode path.
# ryzers run /ryzers/demos/demo_sim_sanity.sh
# SUITE=libero_goal TASK_ID=2 STEPS=120 ryzers run /ryzers/demos/demo_sim_sanity.sh
set -euo pipefail
export SUITE="${SUITE:-libero_object}"
export TASK_ID="${TASK_ID:-0}"
export SEED="${SEED:-1000}"
export STEPS="${STEPS:-80}"
export OUT_DIR="${OUT_DIR:-/sim_outputs}"
exec python -m sim_libero.sanity
68 changes: 68 additions & 0 deletions packages/simulation/libero/examples/template_policy.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# Copyright(C) 2026 Advanced Micro Devices, Inc. All rights reserved.
# SPDX-License-Identifier: MIT
"""COPY-ME template: plug your own model into the LIBERO sim base.

The sim base is model-agnostic; you build FROM it, ship an adapter like this, and select
it at runtime (do NOT edit this package).

Steps
-----
1. Chain on the sim base in your model's Dockerfile, installing your model UNDER the
base's torch+numpy pins (needs numpy 1.26.4) so the LIBERO/robosuite/MuJoCo stack is
not broken (FastWAM's scripts/strip_cuda_torch.py is a working reference):

ARG BASE_IMAGE
FROM ${BASE_IMAGE}
COPY scripts/adapters/ /opt/model-adapters/

Build: ryzers build libero <yourmodel> --name <yourmodel>-libero

2. Implement the two methods below (load in build_policy, obs -> action chunk in
predict_action_chunk).

3. Run with your factory on PYTHONPATH:

PYTHONPATH=/opt/model-adapters:$PYTHONPATH \
POLICY_FACTORY=template_policy:build_policy \
ryzers run --name <yourmodel>-libero /ryzers/demos/demo_interactive.sh

Contract
--------
obs : raw LIBERO/robosuite observation dict. Useful keys:
obs["agentview_image"] HxWx3 uint8 (3rd-person; flipped)
obs["robot0_eye_in_hand_image"] HxWx3 uint8 (wrist; flipped)
obs["robot0_eef_pos"] (3,) end-effector position
obs["robot0_eef_quat"] (4,) end-effector orientation (xyzw)
obs["robot0_gripper_qpos"] (2,) gripper joint positions
instruction : str, the natural-language task.
return : np.ndarray [T, 7] float32 = (dx,dy,dz,droll,dpitch,dyaw, gripper), LIBERO
OSC_POSE delta control; gripper {-1 open, +1 close}. Harness executes the
first `replan_steps` rows, then calls you again.
"""
import numpy as np

from sim_libero.policy import Policy


class TemplatePolicy(Policy):
name = "template"
replan_steps = 5 # env steps executed per predicted chunk before replanning
num_steps_wait = 5 # no-op settle steps at episode start

def __init__(self, model):
self.model = model

def reset(self, instruction):
# Called once per episode; clear per-episode caches here.
pass

def predict_action_chunk(self, obs, instruction):
# TODO: preprocess obs, run inference, return actions in the OSC_POSE delta space above.
raise NotImplementedError("wire your model here")
# return np.zeros((self.replan_steps, 7), dtype=np.float32)


def build_policy():
# TODO: load your checkpoint / processor once here (env knobs: CKPT, DATASET_STATS, ...).
model = None
return TemplatePolicy(model)
14 changes: 14 additions & 0 deletions packages/simulation/libero/lib/sim_libero/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Copyright(C) 2026 Advanced Micro Devices, Inc. All rights reserved.
# SPDX-License-Identifier: MIT
"""Model-agnostic LIBERO simulator harness.

LIBERO env glue, a `Policy` seam, closed-loop/interactive runners, and a RandomPolicy.
Policies plug in via a `build_policy() -> Policy` factory selected by POLICY_FACTORY.
"""
from sim_libero._torch_compat import patch_torch_load

patch_torch_load()

from sim_libero.policy import Policy, load_policy # noqa: E402

__all__ = ["Policy", "load_policy"]
25 changes: 25 additions & 0 deletions packages/simulation/libero/lib/sim_libero/_torch_compat.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Copyright(C) 2026 Advanced Micro Devices, Inc. All rights reserved.
# SPDX-License-Identifier: MIT
"""torch.load compatibility shim for LIBERO's pickled assets.

PyTorch >= 2.6 defaults torch.load to weights_only=True, rejecting LIBERO's pickled
init-states. Restore weights_only=False (trusted assets shipped in the image). Applied via
a startup .pth (covers any policy's eval script) and from sim_libero.__init__.
"""


def patch_torch_load():
try:
import torch
except ImportError:
return
if getattr(torch.load, "_sim_libero_patched", False):
return
_orig = torch.load

def _load(*args, **kwargs):
kwargs.setdefault("weights_only", False)
return _orig(*args, **kwargs)

_load._sim_libero_patched = True
torch.load = _load
21 changes: 21 additions & 0 deletions packages/simulation/libero/lib/sim_libero/envutil.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Copyright(C) 2026 Advanced Micro Devices, Inc. All rights reserved.
# SPDX-License-Identifier: MIT
"""Env-var readers that treat an empty string as unset.

ryzers run passes optional knobs as `-e VAR=${VAR:-}` (empty when unset), so plain
os.environ.get would return "" and break int()/float(); these fall back to the default.
"""
import os


def env_str(key, default):
val = os.environ.get(key)
return val if val not in (None, "") else default


def env_int(key, default):
return int(env_str(key, str(default)))


def env_float(key, default):
return float(env_str(key, str(default)))
Loading