Skip to content

Commit 11bfa3c

Browse files
committed
Add Reachy Mini OpenShell research scaffold
1 parent 5c30b57 commit 11bfa3c

12 files changed

Lines changed: 583 additions & 0 deletions

File tree

projects/README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Projects
2+
3+
This directory contains self-contained research projects. Each project should live in its own subfolder with its own dependencies, runtime notes, and source layout.
4+
5+
Current projects:
6+
7+
- `reachy-mini-openshell`: Reachy Mini simulator/backend research for running the backend inside an OpenShell runtime.
8+
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
.git
2+
.venv
3+
__pycache__
4+
*.pyc
5+
*.pyo
6+
.pytest_cache
7+
.ruff_cache
8+
dist
9+
*.egg-info
10+
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
.venv/
2+
__pycache__/
3+
*.py[cod]
4+
.pytest_cache/
5+
.ruff_cache/
6+
dist/
7+
*.egg-info/
8+
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
FROM ghcr.io/nvidia/openshell-community/sandboxes/base:latest
2+
3+
USER root
4+
WORKDIR /sandbox/reachy-mini-openshell
5+
6+
RUN apt-get update \
7+
&& apt-get install -y --no-install-recommends \
8+
build-essential \
9+
pkg-config \
10+
python3-dev \
11+
libcairo2-dev \
12+
libgirepository1.0-dev \
13+
libglib2.0-dev \
14+
libgstreamer-plugins-bad1.0-dev \
15+
libgstreamer-plugins-base1.0-dev \
16+
libgstreamer1.0-dev \
17+
libnice10 \
18+
libportaudio2 \
19+
libssl-dev \
20+
gstreamer1.0-alsa \
21+
gstreamer1.0-nice \
22+
gstreamer1.0-plugins-bad \
23+
gstreamer1.0-plugins-good \
24+
python3-gi \
25+
python3-gi-cairo \
26+
&& rm -rf /var/lib/apt/lists/*
27+
28+
COPY pyproject.toml README.md ./
29+
COPY src ./src
30+
31+
RUN python3 -m venv /opt/reachy-mini-openshell
32+
ENV PATH="/opt/reachy-mini-openshell/bin:${PATH}"
33+
ENV PYTHONDONTWRITEBYTECODE=1
34+
35+
RUN pip install --no-cache-dir ".[backend,sdk]"
36+
RUN chown -R sandbox:sandbox /sandbox/reachy-mini-openshell /opt/reachy-mini-openshell
37+
38+
USER sandbox
39+
40+
CMD ["python3", "-m", "reachy_openshell.backend", "--host", "0.0.0.0", "--port", "8080"]
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
UV ?= uv
2+
PYTHON ?= python3
3+
4+
.PHONY: install install-backend install-sim sim smoke backend
5+
6+
install:
7+
$(UV) pip install -e ".[backend,sdk]"
8+
9+
install-backend:
10+
$(UV) pip install -e ".[backend]"
11+
12+
install-sim:
13+
$(UV) pip install -e ".[backend,sim]"
14+
15+
sim:
16+
reachy-mini-daemon --sim --scene $${REACHY_SCENE:-minimal}
17+
18+
smoke:
19+
$(PYTHON) -m reachy_openshell.smoke
20+
21+
backend:
22+
$(PYTHON) -m reachy_openshell.backend
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
# Reachy Mini OpenShell Research
2+
3+
Minimal research scaffold for running a Reachy Mini backend inside an OpenShell sandbox while starting against the Reachy Mini MuJoCo simulator.
4+
5+
## Current Shape
6+
7+
- Host process: runs `reachy-mini-daemon --sim`, which starts the simulator and exposes the daemon API on port `8000`.
8+
- OpenShell process: runs this backend in a sandbox and connects to the host daemon through `host.openshell.internal:8000`.
9+
- First backend surface: `GET /health` for daemon reachability and `POST /moves/smoke` for a small head/antenna motion.
10+
11+
## Local Simulator Quickstart
12+
13+
On Linux, install the Reachy Mini GStreamer prerequisites before installing the SDK. The upstream guide lists the full package set and notes that Ubuntu 22.04 needs newer GStreamer packages.
14+
15+
```bash
16+
cd projects/reachy-mini-openshell
17+
uv venv --python 3.12
18+
source .venv/bin/activate
19+
uv pip install -e ".[backend,sim]"
20+
```
21+
22+
Start the simulator:
23+
24+
```bash
25+
reachy-mini-daemon --sim --scene minimal
26+
```
27+
28+
In another terminal:
29+
30+
```bash
31+
source .venv/bin/activate
32+
python -m reachy_openshell.smoke
33+
python -m reachy_openshell.backend
34+
```
35+
36+
Then probe the backend:
37+
38+
```bash
39+
curl http://127.0.0.1:8080/health
40+
curl -X POST http://127.0.0.1:8080/moves/smoke
41+
```
42+
43+
On macOS, the Reachy docs recommend launching the simulator with `mjpython` instead:
44+
45+
```bash
46+
mjpython -m reachy_mini.daemon.app.main --sim
47+
```
48+
49+
## OpenShell Sandbox Path
50+
51+
For the sandboxed backend to reach a host-level simulator, bind the Reachy daemon to an interface visible from containers:
52+
53+
```bash
54+
reachy-mini-daemon --sim --scene minimal --fastapi-host 0.0.0.0 --fastapi-port 8000
55+
```
56+
57+
If your installed daemon exposes different flag names, check `reachy-mini-daemon --help`; the important part is that the daemon is reachable from the sandbox at `host.openshell.internal:8000`.
58+
59+
Build and run the backend in OpenShell:
60+
61+
```bash
62+
openshell status
63+
openshell sandbox create \
64+
--name reachy-mini-backend \
65+
--from . \
66+
--policy openshell/policy.local-sim.yaml \
67+
--env REACHY_HOST=host.openshell.internal \
68+
--env REACHY_PORT=8000 \
69+
--env REACHY_CONNECTION_MODE=network \
70+
-- python3 -m reachy_openshell.backend --host 0.0.0.0 --port 8080
71+
```
72+
73+
Expose the backend service:
74+
75+
```bash
76+
openshell service expose reachy-mini-backend 8080
77+
```
78+
79+
The sandbox image installs the Linux system packages needed by the Reachy SDK before installing the Python package.
80+
81+
## Layout
82+
83+
- `src/reachy_openshell/smoke.py`: SDK smoke motion for the simulator or a real robot daemon.
84+
- `src/reachy_openshell/backend.py`: small FastAPI backend for health checks and the smoke motion.
85+
- `openshell/policy.local-sim.yaml`: starter OpenShell policy allowing Python to reach the host simulator daemon.
86+
- `Dockerfile`: OpenShell sandbox image for the backend, based on the OpenShell community base sandbox.
87+
88+
## References
89+
90+
- Reachy Mini simulator setup: https://huggingface.co/docs/reachy_mini/en/platforms/simulation/get_started
91+
- Reachy Mini Linux GStreamer prerequisites: https://huggingface.co/docs/reachy_mini/en/SDK/gstreamer-installation
92+
- Reachy Mini SDK API: https://huggingface.co/docs/reachy_mini/en/API/reachymini
93+
- OpenShell overview: https://docs.nvidia.com/openshell/about/overview
94+
- OpenShell sandbox management: https://docs.nvidia.com/openshell/sandboxes/manage-sandboxes
95+
- OpenShell policy reference: https://docs.nvidia.com/openshell/reference/policy-schema
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Research Plan
2+
3+
## Working Hypothesis
4+
5+
Keep the simulator on the host for the first spike so MuJoCo can open its viewer normally. Run only the backend in OpenShell. The sandbox reaches the host daemon through `host.openshell.internal:8000`, using a narrow OpenShell network policy.
6+
7+
## Phase 0: Simulator Bootstrap
8+
9+
- Install `reachy-mini[mujoco]` locally.
10+
- Start `reachy-mini-daemon --sim --scene minimal`.
11+
- Verify the Python SDK can connect and run the smoke motion.
12+
13+
## Phase 1: Sandboxed Backend
14+
15+
- Build the local OpenShell sandbox image from `Dockerfile`.
16+
- Run `python3 -m reachy_openshell.backend` inside the sandbox.
17+
- Confirm `GET /health` reaches the simulator daemon.
18+
- Confirm `POST /moves/smoke` moves the simulated robot.
19+
20+
## Phase 2: Policy Tightening
21+
22+
- Capture the exact daemon traffic used by the SDK.
23+
- Replace the current L4 passthrough policy with REST and WebSocket rules if the daemon API remains stable enough.
24+
- Decide whether PyPI access is needed at runtime or only at image build time.
25+
26+
## Open Questions
27+
28+
- Should the simulator stay host-side for development, or should a headless simulator move into its own OpenShell sandbox later?
29+
- Which daemon bind flags are stable across Reachy Mini SDK versions and operating systems?
30+
- Do audio and camera paths need to be disabled or mocked for OpenShell-based backend tests?
31+
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
version: 1
2+
3+
filesystem_policy:
4+
include_workdir: true
5+
read_only:
6+
- /usr
7+
- /lib
8+
- /lib64
9+
- /etc
10+
- /bin
11+
- /sbin
12+
- /opt
13+
read_write:
14+
- /sandbox
15+
- /workspace
16+
- /tmp
17+
18+
landlock:
19+
compatibility: best_effort
20+
21+
process:
22+
run_as_user: sandbox
23+
run_as_group: sandbox
24+
25+
network_policies:
26+
reachy_daemon:
27+
name: reachy-daemon-local-simulator
28+
endpoints:
29+
- host: host.openshell.internal
30+
port: 8000
31+
binaries:
32+
- path: /usr/bin/python*
33+
- path: /usr/local/bin/python*
34+
- path: /opt/reachy-mini-openshell/bin/python*
35+
- path: /sandbox/**/python*
36+
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
[build-system]
2+
requires = ["hatchling>=1.25"]
3+
build-backend = "hatchling.build"
4+
5+
[project]
6+
name = "reachy-mini-openshell"
7+
version = "0.1.0"
8+
description = "Research scaffold for running a Reachy Mini backend in OpenShell against a Reachy Mini simulator."
9+
readme = "README.md"
10+
requires-python = ">=3.10"
11+
dependencies = []
12+
13+
[project.optional-dependencies]
14+
backend = [
15+
"fastapi>=0.115,<1",
16+
"uvicorn[standard]>=0.30,<1",
17+
]
18+
sdk = [
19+
"reachy-mini>=1.8.3,<2",
20+
]
21+
sim = [
22+
"reachy-mini[mujoco]>=1.8.3,<2",
23+
]
24+
dev = [
25+
"ruff>=0.8,<1",
26+
]
27+
28+
[project.scripts]
29+
reachy-backend = "reachy_openshell.backend:main"
30+
reachy-smoke = "reachy_openshell.smoke:main"
31+
32+
[tool.hatch.build.targets.wheel]
33+
packages = ["src/reachy_openshell"]
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
__version__ = "0.1.0"
2+

0 commit comments

Comments
 (0)