rmscript-demo / README.md
dlouapre's picture
dlouapre HF Staff
Comprehensive README update with architecture, troubleshooting, and development history
8227ce2
---
title: RMScript Web Demo
emoji: πŸ€–
colorFrom: purple
colorTo: blue
sdk: docker
app_port: 7860
pinned: false
---
# RMScript Web Demo
Web-based IDE for writing, verifying, and executing rmscript code on Reachy Mini.
## Architecture
### Components
- **Frontend** (`frontend/`): Pure HTML/CSS/JavaScript web IDE
- `index.html`: UI layout with embedded CSS styling
- `app.js`: Application logic, compilation API calls, robot communication
- Auto-detects environment (file:// for local, web server for production)
- **Backend** (`backend/`): FastAPI server (Python 3.11)
- `app.py`: REST API for rmscript compilation and validation
- Serves frontend files via static file mounting
- Runs on port 8001 (local) or port 7860 (HuggingFace Spaces)
- **Robot Daemon**: Reachy Mini daemon (expected on localhost:8000)
- REST API: `/api/move/goto` (with duration support)
- WebSocket API: `/api/move/ws/set_target` (streaming, no duration)
- State API: `/api/state/*` (robot current state)
### Communication Flow
1. **Script Verification/Compilation**:
- Frontend β†’ Backend (`/api/verify` or `/api/compile`)
- Backend compiles rmscript using the rmscript package
- Returns IR (Intermediate Representation) + errors/warnings
2. **Script Execution** (Local):
- Frontend β†’ Robot Daemon (`POST /api/move/goto`)
- Each IR action sent with duration and interpolation mode
- Proper timing with minimum-jerk interpolation
3. **Script Execution** (HuggingFace Spaces):
- Frontend β†’ Robot Daemon (WebSocket `/api/move/ws/set_target`)
- Fallback due to HTTPS β†’ HTTP localhost blocking
- No duration control - moves are instant
## Quick Start
### On HuggingFace Spaces
Just open the Space - the web IDE will load automatically.
**Requirements:**
- Reachy Mini daemon running on `localhost:8000` on your local machine
- Modern web browser with WebSocket support
### Local Development
1. Install rmscript package:
```bash
cd rmscript
uv sync
```
2. Start backend server:
```bash
cd backend
uv sync
uv run python app.py
```
3. Make sure your Reachy Mini daemon is running on `localhost:8000`
4. Open `frontend/index.html` in your web browser
## Features
- **Code Editor**: Write rmscript with syntax examples
- **Verify Button**: Check script validity without executing
- **Execute Button**: Compile and run script on connected robot
- **Live Compilation**: See IR (Intermediate Representation) of your script
- **Example Scripts**: Load pre-written examples (basic, complex, repeat)
- **Real-time Logging**: Console shows compilation errors, warnings, and execution progress
## Usage
1. Write rmscript in the editor (or load an example)
2. Click "Verify" to check syntax and semantics
3. Review any errors/warnings in the console
4. Click "Execute" to run on the robot (robot must be connected)
5. Watch execution progress in the Execution Info panel
## Current Limitations
- Sound and picture actions are not yet implemented in execution
- **Movement timing on HuggingFace Spaces**: Due to browser security (HTTPS cannot fetch `http://localhost`), the Space version cannot use the robot's `/goto` endpoint which supports duration control.
- **On Spaces**: Robot moves to each target as fast as possible (instant), but script execution pauses for the specified duration before the next move
- **Locally**: Robot moves smoothly with proper duration and minimum-jerk interpolation
- **Recommendation**: For demos requiring accurate movement timing, run locally
## Deployment to HuggingFace Spaces
To deploy this demo to HuggingFace Spaces:
1. **Prepare the repository structure:**
- Copy the `rmscript` and `reachy_mini` directories (without `.git` and binary files):
```bash
cd rmscript_space_demo
# Option 1: Using rsync (recommended - cleaner)
rsync -av --exclude='.git' --exclude='.venv' --exclude='__pycache__' \
--exclude='*.pyc' ../rmscript/ ./rmscript/
rsync -av --exclude='.git' --exclude='.venv' --exclude='__pycache__' \
--exclude='*.pyc' ../reachy_mini/ ./reachy_mini/
# Option 2: Using cp then cleanup
cp -r ../rmscript ./rmscript
cp -r ../reachy_mini ./reachy_mini
rm -rf ./rmscript/.git ./reachy_mini/.git
rm -rf ./rmscript/.venv ./reachy_mini/.venv
# Remove binary files that HuggingFace Spaces rejects
rm -rf ./reachy_mini/src/reachy_mini/assets/*.wav
rm -rf ./reachy_mini/src/reachy_mini/daemon/app/dashboard/static/fonts/*.ttf
rm -rf ./reachy_mini/docs ./reachy_mini/examples
rm -rf ./reachy_mini/src/reachy_mini/descriptions/reachy_mini/mjcf
rm -rf ./rmscript/examples ./rmscript/tests
```
- Your structure should be:
```
rmscript_space_demo/
β”œβ”€β”€ Dockerfile
β”œβ”€β”€ README.md
β”œβ”€β”€ .dockerignore
β”œβ”€β”€ backend/
β”œβ”€β”€ frontend/
β”œβ”€β”€ rmscript/ ← copied source (no .git, no binaries)
└── reachy_mini/ ← copied source (no .git, no binaries)
```
2. **Create a new Space:**
- Go to https://huggingface.co/new-space
- Select "Docker" as the SDK
- Push this directory to your Space repository
3. **The Space will:**
- Build the Docker container
- Install rmscript and dependencies
- Serve the web IDE on port 7860
**Note:** The Space connects to your local robot daemon on `localhost:8000`. Make sure it's running when using the demo.
## Development
### File Structure
```
rmscript_space_demo/
β”œβ”€β”€ Dockerfile # Docker build config for HuggingFace Spaces
β”œβ”€β”€ .dockerignore # Excludes .git, .venv, __pycache__, etc.
β”œβ”€β”€ README.md # This file (includes HF Space metadata in YAML)
β”œβ”€β”€ backend/
β”‚ β”œβ”€β”€ app.py # FastAPI server (compilation + static file serving)
β”‚ └── pyproject.toml # Python dependencies
└── frontend/
β”œβ”€β”€ index.html # Web IDE UI (with embedded CSS)
└── app.js # Frontend logic (compilation + execution)
```
### Key Implementation Details
**Matrix to Euler Conversion** (`frontend/app.js:328-355`):
- Converts 4x4 pose matrices (from rmscript IR) to euler angles (roll, pitch, yaw)
- Uses XYZ euler convention to match `scipy.spatial.transform.Rotation.as_euler("xyz")`
- Required because WebSocket API expects `{x, y, z, roll, pitch, yaw}` format
**Environment Detection** (`frontend/app.js:9-11`):
- Detects `file://` protocol β†’ uses `http://localhost:8001` for backend
- Detects web server β†’ uses relative URLs (same origin)
- Script loading path adapts similarly for `app.js` imports
**Execution Strategy** (`frontend/app.js:357-427`):
- **Tries** `POST /api/move/goto` with duration (works locally)
- **Catches** fetch failures β†’ falls back to WebSocket (for Spaces)
- Logs warnings when fallback is used
### Modifying the Demo
**Frontend Changes:**
- Edit `frontend/app.js` for logic changes
- Edit `frontend/index.html` for UI/styling changes
- Test by opening `index.html` directly in browser (local mode)
**Backend Changes:**
- Edit `backend/app.py` for API changes
- Run locally: `cd backend && uv run python app.py`
- Test API at `http://localhost:8001/docs` (FastAPI Swagger UI)
**Deployment:**
- Changes auto-deploy when pushed to HuggingFace Space repo
- Build logs visible in Space's "Build" tab
- Runtime logs visible in Space's "Logs" tab
## Technical Notes
### Browser Security & Mixed Content
**The Problem:**
- HuggingFace Spaces serve content over HTTPS
- Robot daemon runs on `http://localhost:8000` (HTTP, not HTTPS)
- Modern browsers block HTTPS β†’ HTTP requests (mixed content policy)
- This blocks `fetch()` to the robot's REST API
**Current Solution:**
- WebSocket connections are allowed (less strict security)
- Use WebSocket `/ws/set_target` as fallback
- Limitation: No duration control via WebSocket
**Why We Can't Fix This:**
- Robot daemon is on user's local machine
- Space backend runs on HuggingFace servers (can't reach localhost)
- Can't proxy through Space backend
- Can't get robot's current state for client-side interpolation
**Alternative Approaches (Not Implemented):**
1. **Client-side interpolation**: Would need current robot state (blocked by same security issue)
2. **Local HTTPS proxy**: Too complex for end users
3. **Run robot daemon on HTTPS**: Requires SSL certificates for localhost
### Deployment Gotchas
**Binary Files:**
- HuggingFace Spaces reject binary files (WAV, TTF, PNG, etc.)
- Must remove from `reachy_mini/` and `rmscript/` copies before pushing
- Already removed: docs/, examples/, assets/, fonts/
**OpenGL Dependencies:**
- OpenCV (cv2) requires system libraries: `libgl1`, `libglib2.0-0`, etc.
- Must install in Dockerfile (see lines 8-15)
- Package name changed from `libgl1-mesa-glx` β†’ `libgl1` in newer Debian
**Git Submodules:**
- Don't copy `.git` directories from `rmscript/` and `reachy_mini/`
- Use `rsync --exclude='.git'` or remove after copying
- Otherwise Space treats them as submodules (causes issues)
## Future Improvements
### Potential Enhancements
1. **Sound & Picture Support:**
- Currently IR supports these actions but execution skips them
- Would need to implement in `frontend/app.js:executeScript()`
2. **Syntax Highlighting:**
- Add CodeMirror or Monaco Editor for better editing experience
- Custom rmscript syntax highlighting rules
3. **Save/Load Scripts:**
- localStorage for saving scripts in browser
- Or integrate with HuggingFace Datasets for cloud storage
4. **Real-time Error Highlighting:**
- Show errors inline in editor (like VS Code)
- Currently only shows in console panel
5. **Movement Visualization:**
- 3D preview of robot movements before execution
- Using Three.js or similar
6. **Execution Controls:**
- Pause/resume execution
- Step through script line-by-line
- Stop/cancel running script
### Known Issues
- **Spaces timing limitation**: Cannot be fixed without changing browser security or deployment architecture
- **Cached IR bug**: Fixed - now always compiles fresh editor content
- **Euler angle conversion**: Works but could add gimbal lock handling improvements
### Development History & Fixes
**Issues Fixed During Development:**
1. **Robot not executing moves** (2025-11-26):
- **Problem**: Robot daemon connected but moves didn't execute
- **Cause**: Frontend was extracting translation but hardcoding euler angles to 0
- **Fix**: Implemented `matrixToEulerXYZ()` to properly extract rotation from 4x4 matrices
- **Location**: `frontend/app.js:328-355`
2. **Modified scripts not executing** (2025-11-26):
- **Problem**: Editing script in editor didn't affect execution - same old script ran
- **Cause**: `executeScript()` was using cached IR instead of compiling fresh
- **Fix**: Always compile editor content before execution
- **Location**: `frontend/app.js:285-290`
3. **Local development broken after Space changes** (2025-11-26):
- **Problem**: Opening `index.html` locally didn't load `app.js`
- **Cause**: Changed script path to `/static/app.js` for Space deployment
- **Fix**: Auto-detect environment and load appropriate path
- **Location**: `frontend/index.html:320-329`
4. **Binary files rejected during Space deployment** (2025-11-26):
- **Problem**: HuggingFace push rejected due to WAV/TTF/PNG files
- **Cause**: HuggingFace Spaces don't allow binary files without LFS
- **Fix**: Remove docs, examples, assets from copied dependencies
- **Commands**: See deployment section step 1
5. **Docker build failing on Spaces** (2025-11-26):
- **Problem**: `libgl1-mesa-glx` package not found during build
- **Cause**: Package renamed in newer Debian (Trixie)
- **Fix**: Changed to `libgl1` in Dockerfile
- **Location**: `Dockerfile:10`
6. **Duration not respected in execution** (2025-11-26):
- **Problem**: All moves happened instantly regardless of specified duration
- **Cause**: Using WebSocket `/ws/set_target` which doesn't support duration
- **Fix**: Switch to REST API `POST /api/move/goto` with duration parameter
- **Location**: `frontend/app.js:394-405`
7. **Fetch failures on HuggingFace Spaces** (2025-11-26):
- **Problem**: "Failed to fetch" errors when executing on Space
- **Cause**: Browser mixed content policy blocks HTTPS β†’ HTTP localhost
- **Fix**: Fallback to WebSocket when fetch fails (timing limitation accepted)
- **Location**: `frontend/app.js:407-426`
## Troubleshooting
**Backend won't start locally:**
```bash
# Make sure rmscript is installed
cd ../rmscript && uv sync
cd ../rmscript_space_demo/backend
# Install backend deps
uv sync
uv run python app.py
```
**Robot not connecting:**
- Check robot daemon is running: `curl http://localhost:8000/api/health`
- Check WebSocket connection in browser console
- Try reloading the page
**Space build fails:**
- Check build logs in Space's "Build" tab
- Common issues: binary files not removed, missing system dependencies
- Dockerfile may need updating for new Debian versions
**Compilation errors:**
- Check rmscript syntax in examples
- Use "Verify" button before "Execute"
- Check console for detailed error messages
## Credits
Built with:
- [rmscript](../rmscript/) - Kid-friendly robot programming language
- [reachy_mini](../reachy_mini/) - Reachy Mini SDK
- [FastAPI](https://fastapi.tiangolo.com/) - Backend framework
- [HuggingFace Spaces](https://huggingface.co/spaces) - Deployment platform