Spaces:
Running
Running
# ๐ค LeRobot Arena - Complete Robot Control System | |
A comprehensive WebSocket-based robot control platform featuring **master-slave architecture**, real-time 3D visualization, and seamless integration between physical robots and digital twins. | |
## ๐๏ธ Core Architecture | |
### Master-Slave Pattern | |
``` | |
โโโโโโโโโโโโโโโโโโโ Commands โโโโโโโโโโโโโโโโโโโ Execution โโโโโโโโโโโโโโโโโโโ | |
โ ๐ฎ MASTERS โ โโโโโโโโโโโโโโโโบโ ๐ค ROBOT CORE โ โโโโโโโโโโโโโโโโบโ ๐ง SLAVES โ | |
โ โ โ โ โ โ | |
โ โข Remote Server โ WebSocket โ โข Robot Manager โ USB/Mock/WS โ โข Physical Bot โ | |
โ โข Demo Scripts โ HTTP API โ โข State Sync โ Direct I/O โ โข 3D Simulation โ | |
โ โข Manual UI โ Sequences โ โข Safety Logic โ Commands โ โข Mock Testing โ | |
โ โข AI Agents โ โ โข Multi-Robot โ โ โข Remote Proxy โ | |
โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ | |
``` | |
**Key Principles:** | |
- ๐ฏ **Single Source of Truth**: Only one master per robot at a time | |
- ๐ **Safety First**: Manual control disabled when master active | |
- ๐ **Multi-Modal**: Same commands work across all slave types | |
- ๐ **Real-Time Sync**: Virtual and physical states synchronized | |
- ๐ก **Network Native**: Built for remote operation from day one | |
## ๐ Quick Start Guide | |
### 1. Server Setup | |
```bash | |
# Install dependencies | |
cd src-python | |
uv sync | |
# Start the WebSocket server | |
python start_server.py | |
# Server runs on http://localhost:8080 | |
``` | |
### 2. Frontend Integration | |
```bash | |
# In your Svelte app | |
npm run dev | |
# Visit http://localhost:5173 | |
``` | |
### 3. Create & Control Robot | |
```javascript | |
// Create robot in UI or via API | |
const robot = await robotManager.createRobot('my-robot', robotUrdfConfig); | |
// Option 1: Manual control (sliders in UI) | |
await robot.updateJointValue('Rotation', 45); | |
// Option 2: Demo sequences | |
await robotManager.connectDemoSequences('my-robot'); | |
// Option 3: Remote server control | |
await robotManager.connectMaster('my-robot', { | |
type: "remote-server", | |
url: "ws://localhost:8080" | |
}); | |
// Option 4: Direct API sequence trigger | |
curl -X POST http://localhost:8080/api/robots/my-robot/play-sequence/gentle-wave | |
``` | |
## ๐ฎ Master Drivers (Command Sources) | |
### MockSequenceMaster | |
**Pre-programmed movement patterns for testing and demos** | |
```typescript | |
const config: MasterDriverConfig = { | |
type: "mock-sequence", | |
sequences: DEMO_SEQUENCES, | |
autoStart: true, | |
loopMode: true | |
}; | |
await robotManager.connectMaster("robot-1", config); | |
``` | |
**Available Sequences:** | |
- **๐ Gentle Wave Pattern** (6s): Smooth greeting gesture with wrist movements | |
- **๐ Small Scanning Pattern** (8s): Horizontal sweep for environment scanning | |
- **๐ช Tiny Flex Pattern** (8s): Articulation demonstration with elbow/jaw coordination | |
**Features:** | |
- โ Safe movement ranges (ยฑ25ยฐ max) | |
- โ Smooth interpolation between keyframes | |
- โ Loop mode for continuous operation | |
- โ Automatic master takeover | |
### RemoteServerMaster | |
**WebSocket connection to external control systems** | |
```typescript | |
const config: MasterDriverConfig = { | |
type: "remote-server", | |
url: "ws://localhost:8080", | |
apiKey: "optional-auth-token" | |
}; | |
await robotManager.connectMaster("robot-1", config); | |
``` | |
**Features:** | |
- โ Real-time bidirectional communication | |
- โ Automatic reconnection with exponential backoff | |
- โ Heartbeat monitoring (30s intervals) | |
- โ Command acknowledgment | |
- โ Status and error reporting | |
**Message Format:** | |
```json | |
{ | |
"type": "command", | |
"timestamp": "2024-01-01T12:00:00Z", | |
"data": { | |
"timestamp": 1704110400000, | |
"joints": [{ "name": "Rotation", "value": 45, "speed": 100 }] | |
} | |
} | |
``` | |
## ๐ง Slave Drivers (Execution Targets) | |
### MockSlave | |
**Perfect simulation for development and testing** | |
```typescript | |
const config: SlaveDriverConfig = { | |
type: "mock-slave", | |
simulateLatency: 50, // Realistic response delay | |
simulateErrors: false, // Random connection issues | |
responseDelay: 20 // Command execution time | |
}; | |
await robotManager.connectSlave("robot-1", config); | |
``` | |
**Features:** | |
- โ Perfect command execution (real_value = virtual_value) | |
- โ Configurable network latency simulation | |
- โ Error injection for robustness testing | |
- โ Instant connection without hardware | |
- โ Real-time state feedback | |
### USBSlave | |
**Direct serial communication with physical robots** | |
```typescript | |
const config: SlaveDriverConfig = { | |
type: "usb-slave", | |
port: "/dev/ttyUSB0", // Auto-detect if undefined | |
baudRate: 115200 | |
}; | |
await robotManager.connectSlave("robot-1", config); | |
``` | |
**Features:** | |
- โ Feetech servo protocol support | |
- โ Position and speed control | |
- โ Real servo position feedback | |
- โ Calibration workflow for sync | |
- โ Error handling and recovery | |
**Calibration Process:** | |
1. Manually position robot to match digital twin | |
2. Click "Calibrate" to sync virtual/real coordinates | |
3. System calculates offset: `real_pos = raw_pos + offset` | |
4. All future commands automatically compensated | |
### WebSocketSlave | |
**Remote robot control via WebSocket relay** | |
```typescript | |
const config: SlaveDriverConfig = { | |
type: "websocket-slave", | |
url: "ws://robot-proxy:8080", | |
robotId: "remote-arm-1" | |
}; | |
await robotManager.connectSlave("robot-1", config); | |
``` | |
**Use Cases:** | |
- ๐ Control robots across internet | |
- ๐ข Enterprise robot fleet management | |
- ๐ Firewall-friendly robot access | |
- ๐ก Proxy through edge devices | |
## ๐ก WebSocket Protocol Specification | |
### Master โ Server Communication | |
#### Send Joint Command | |
```json | |
{ | |
"type": "command", | |
"timestamp": "2024-01-01T12:00:00Z", | |
"data": { | |
"timestamp": 1704110400000, | |
"joints": [ | |
{ "name": "Rotation", "value": 45, "speed": 100 }, | |
{ "name": "Pitch", "value": -30, "speed": 150 } | |
], | |
"duration": 2000, | |
"metadata": { "source": "manual_control" } | |
} | |
} | |
``` | |
#### Send Movement Sequence | |
```json | |
{ | |
"type": "sequence", | |
"timestamp": "2024-01-01T12:00:00Z", | |
"data": { | |
"id": "custom-dance", | |
"name": "Custom Dance Sequence", | |
"commands": [ | |
{ | |
"timestamp": 0, | |
"joints": [{ "name": "Rotation", "value": -30 }], | |
"duration": 1000 | |
}, | |
{ | |
"timestamp": 1000, | |
"joints": [{ "name": "Rotation", "value": 30 }], | |
"duration": 1000 | |
} | |
], | |
"total_duration": 2000, | |
"loop": false | |
} | |
} | |
``` | |
#### Heartbeat | |
```json | |
{ | |
"type": "heartbeat", | |
"timestamp": "2024-01-01T12:00:00Z" | |
} | |
``` | |
### Slave โ Server Communication | |
#### Status Update | |
```json | |
{ | |
"type": "status_update", | |
"timestamp": "2024-01-01T12:00:00Z", | |
"data": { | |
"isConnected": true, | |
"lastConnected": "2024-01-01T11:58:00Z", | |
"error": null | |
} | |
} | |
``` | |
#### Joint State Feedback | |
```json | |
{ | |
"type": "joint_states", | |
"timestamp": "2024-01-01T12:00:00Z", | |
"data": [ | |
{ | |
"name": "Rotation", | |
"servo_id": 1, | |
"type": "revolute", | |
"virtual_value": 45.0, | |
"real_value": 44.8, | |
"limits": { | |
"lower": -180, | |
"upper": 180, | |
"velocity": 200 | |
} | |
} | |
] | |
} | |
``` | |
#### Error Reporting | |
```json | |
{ | |
"type": "error", | |
"timestamp": "2024-01-01T12:00:00Z", | |
"data": { | |
"code": "SERVO_TIMEOUT", | |
"message": "Servo 3 not responding", | |
"joint": "Elbow", | |
"severity": "warning" | |
} | |
} | |
``` | |
## ๐ ๏ธ REST API Reference | |
### Robot Management | |
| Method | Endpoint | Description | Example | | |
| ------ | ------------------------- | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | | |
| GET | `/` | Server status & metrics | `curl http://localhost:8080/` | | |
| GET | `/api/robots` | List all robots | `curl http://localhost:8080/api/robots` | | |
| POST | `/api/robots` | Create new robot | `curl -X POST -H "Content-Type: application/json" -d '{"robot_type":"so-arm100","name":"My Robot"}' http://localhost:8080/api/robots` | | |
| GET | `/api/robots/{id}` | Get robot details | `curl http://localhost:8080/api/robots/robot-123` | | |
| GET | `/api/robots/{id}/status` | Get connection status | `curl http://localhost:8080/api/robots/robot-123/status` | | |
| DELETE | `/api/robots/{id}` | Delete robot | `curl -X DELETE http://localhost:8080/api/robots/robot-123` | | |
### Sequence Control | |
| Method | Endpoint | Description | Example | | |
| ------ | ----------------------------------------- | ------------------- | ----------------------------------------------------------------------------------- | | |
| GET | `/api/sequences` | List demo sequences | `curl http://localhost:8080/api/sequences` | | |
| POST | `/api/robots/{id}/play-sequence/{seq_id}` | Play sequence | `curl -X POST http://localhost:8080/api/robots/robot-123/play-sequence/gentle-wave` | | |
| POST | `/api/robots/{id}/stop-sequence` | Stop sequences | `curl -X POST http://localhost:8080/api/robots/robot-123/stop-sequence` | | |
### WebSocket Endpoints | |
| Endpoint | Purpose | Client Type | Example | | |
| ----------------------- | ---------------- | ----------------- | ----------------------------------------- | | |
| `/ws/master/{robot_id}` | Send commands | Control sources | `ws://localhost:8080/ws/master/robot-123` | | |
| `/ws/slave/{robot_id}` | Receive commands | Execution targets | `ws://localhost:8080/ws/slave/robot-123` | | |
## ๐ฏ Usage Scenarios | |
### 1. ๐งช Development & Testing | |
```bash | |
# Create robot with mock slave for safe testing | |
robot = await robotManager.createRobot('test-bot', urdfConfig); | |
await robotManager.connectMockSlave('test-bot', 50); | |
await robotManager.connectDemoSequences('test-bot'); | |
``` | |
**Perfect for:** | |
- Algorithm development without hardware risk | |
- UI/UX testing with realistic feedback | |
- Automated testing pipelines | |
- Demo presentations | |
### 2. ๐ฆพ Physical Robot Control | |
```bash | |
# Connect real hardware | |
robot = await robotManager.createRobot('real-bot', urdfConfig); | |
await robotManager.connectUSBSlave('real-bot', '/dev/ttyUSB0'); | |
# Manual control via UI sliders | |
# OR automated via demo sequences | |
await robotManager.connectDemoSequences('real-bot'); | |
``` | |
**Calibration Workflow:** | |
1. Connect USB slave to robot | |
2. Manually position to match 3D model rest pose | |
3. Click "Calibrate" to sync coordinate systems | |
4. Robot now mirrors 3D model movements precisely | |
### 3. ๐ Remote Operation | |
```bash | |
# Master controls slave over internet | |
# Master side: | |
await robotManager.connectMaster('local-avatar', { | |
type: "remote-server", | |
url: "wss://robot-farm.com:8080" | |
}); | |
# Slave side (at robot location): | |
await robotManager.connectSlave('physical-robot', { | |
type: "websocket-slave", | |
url: "wss://robot-farm.com:8080", | |
robotId: "local-avatar" | |
}); | |
``` | |
**Use Cases:** | |
- Telepresence robotics | |
- Remote maintenance and inspection | |
- Distributed manufacturing | |
- Educational robot sharing | |
### 4. ๐ค Multi-Robot Coordination | |
```bash | |
# One master controlling multiple robots | |
await robotManager.connectMaster('fleet-commander', masterConfig); | |
// Multiple slaves executing same commands | |
for (const robot of robotFleet) { | |
await robotManager.connectSlave(robot.id, slaveConfig); | |
} | |
``` | |
**Applications:** | |
- Synchronized dance performances | |
- Assembly line coordination | |
- Swarm robotics research | |
- Entertainment shows | |
### 5. ๐ง AI Agent Integration | |
```javascript | |
// AI agent as master driver | |
class AIAgentMaster implements MasterDriver { | |
async generateNextCommand(): Promise<RobotCommand> { | |
const sensorData = await this.readEnvironment(); | |
const decision = await this.aiModel.predict(sensorData); | |
return this.convertToRobotCommand(decision); | |
} | |
} | |
await robot.setMaster(new AIAgentMaster(config)); | |
``` | |
## ๐ง Integration Guide | |
### Frontend Integration (Svelte) | |
```typescript | |
import { robotManager } from "$lib/robot/RobotManager.svelte"; | |
import { robotUrdfConfigMap } from "$lib/configs/robotUrdfConfig"; | |
// Create robot | |
const robot = await robotManager.createRobot("my-robot", robotUrdfConfigMap["so-arm100"]); | |
// Add visualization | |
await robotManager.connectMockSlave("my-robot"); | |
// Add control | |
await robotManager.connectDemoSequences("my-robot", true); | |
// Monitor state | |
robot.joints.forEach((joint) => { | |
console.log(`${joint.name}: virtual=${joint.virtualValue}ยฐ real=${joint.realValue}ยฐ`); | |
}); | |
``` | |
### Backend Integration (Python) | |
```python | |
import asyncio | |
import websockets | |
import json | |
async def robot_controller(): | |
uri = "ws://localhost:8080/ws/master/my-robot" | |
async with websockets.connect(uri) as websocket: | |
# Send command | |
command = { | |
"type": "command", | |
"timestamp": "2024-01-01T12:00:00Z", | |
"data": { | |
"timestamp": 1704110400000, | |
"joints": [{"name": "Rotation", "value": 45}] | |
} | |
} | |
await websocket.send(json.dumps(command)) | |
# Listen for responses | |
async for message in websocket: | |
data = json.loads(message) | |
if data["type"] == "joint_states": | |
print(f"Robot position: {data['data']}") | |
asyncio.run(robot_controller()) | |
``` | |
### Hardware Integration (Arduino/C++) | |
```cpp | |
#include <WiFi.h> | |
#include <WebSocketsClient.h> | |
#include <ArduinoJson.h> | |
WebSocketsClient webSocket; | |
void onWebSocketEvent(WStype_t type, uint8_t * payload, size_t length) { | |
if (type == WStype_TEXT) { | |
DynamicJsonDocument doc(1024); | |
deserializeJson(doc, payload); | |
if (doc["type"] == "execute_command") { | |
JsonArray joints = doc["data"]["joints"]; | |
for (JsonObject joint : joints) { | |
String name = joint["name"]; | |
float value = joint["value"]; | |
moveServo(name, value); | |
} | |
} | |
} | |
} | |
void setup() { | |
webSocket.begin("192.168.1.100", 8080, "/ws/slave/arduino-bot"); | |
webSocket.onEvent(onWebSocketEvent); | |
} | |
``` | |
## ๐ก๏ธ Security & Production | |
### Authentication | |
```typescript | |
// API key authentication (planned) | |
const master = new RemoteServerMaster( | |
{ | |
type: "remote-server", | |
url: "wss://secure-robot-farm.com:8080", | |
apiKey: "your-secret-api-key" | |
}, | |
robotId | |
); | |
``` | |
### TLS/SSL | |
```bash | |
# Production deployment with SSL | |
uvicorn main:app --host 0.0.0.0 --port 443 --ssl-keyfile key.pem --ssl-certfile cert.pem | |
``` | |
### Rate Limiting & Safety | |
```python | |
# Built-in protections | |
- Command rate limiting (100 commands/second max) | |
- Joint velocity limits from URDF | |
- Emergency stop on connection loss | |
- Position bounds checking | |
- Servo temperature monitoring | |
``` | |
## ๐ Deployment Options | |
### Development | |
```bash | |
cd src-python && python start_server.py | |
``` | |
### Docker | |
```dockerfile | |
FROM python:3.12-slim | |
COPY src-python/ /app/ | |
WORKDIR /app | |
RUN pip install -r requirements.txt | |
EXPOSE 8080 | |
CMD ["python", "start_server.py"] | |
``` | |
### Cloud (Railway/Heroku) | |
```bash | |
# Procfile | |
web: cd src-python && python start_server.py | |
``` | |
### Raspberry Pi (Edge) | |
```bash | |
# systemd service for autostart | |
sudo systemctl enable lerobot-arena | |
sudo systemctl start lerobot-arena | |
``` | |
## ๐งช Testing & Debugging | |
### Unit Tests | |
```bash | |
cd src-python | |
pytest tests/ -v | |
``` | |
### Integration Tests | |
```javascript | |
// Frontend testing | |
import { expect, test } from "@playwright/test"; | |
test("robot creation and control", async ({ page }) => { | |
await page.goto("/"); | |
await page.click('[data-testid="create-robot"]'); | |
await page.click('[data-testid="connect-demo-sequences"]'); | |
await expect(page.locator('[data-testid="robot-status"]')).toContainText("Master + Slaves"); | |
}); | |
``` | |
### Debug Mode | |
```bash | |
# Enable verbose logging | |
export LOG_LEVEL=DEBUG | |
python start_server.py | |
# Frontend debug | |
export VITE_DEBUG=true | |
npm run dev | |
``` | |
### Health Monitoring | |
```bash | |
# Check server health | |
curl http://localhost:8080/ | |
# Monitor WebSocket connections | |
curl http://localhost:8080/api/robots | |
``` | |
## ๐ฎ Roadmap | |
### v2.0 - Enhanced Control | |
- [ ] **Script Player Master**: Execute Python/JS scripts | |
- [ ] **Simulation Slave**: Physics-based simulation | |
- [ ] **Force Control**: Torque and compliance modes | |
- [ ] **Vision Integration**: Camera feeds and computer vision | |
### v2.1 - Enterprise Features | |
- [ ] **Authentication**: JWT tokens and user management | |
- [ ] **Multi-tenancy**: Isolated robot fleets per organization | |
- [ ] **Monitoring**: Prometheus metrics and Grafana dashboards | |
- [ ] **Recording**: Command sequences and replay | |
### v2.2 - Advanced Robotics | |
- [ ] **Path Planning**: Trajectory optimization | |
- [ ] **Collision Detection**: Safety in shared workspaces | |
- [ ] **AI Integration**: Reinforcement learning environments | |
- [ ] **ROS Bridge**: Integration with ROS2 ecosystem | |
## ๐ค Contributing | |
### Development Setup | |
```bash | |
# Frontend | |
npm install | |
npm run dev | |
# Backend | |
cd src-python | |
uv sync | |
python start_server.py | |
# Tests | |
npm run test | |
cd src-python && pytest | |
``` | |
### Code Style | |
- **TypeScript**: ESLint + Prettier | |
- **Python**: Black + isort + mypy | |
- **Commits**: Conventional commits format | |
### Pull Request Process | |
1. Fork repository | |
2. Create feature branch | |
3. Add tests for new functionality | |
4. Ensure all tests pass | |
5. Update documentation | |
6. Submit PR with clear description | |
## ๐ License | |
MIT License - Feel free to use in commercial and personal projects. | |
--- | |
**Built with โค๏ธ for the robotics community** | |
_LeRobot Arena bridges the gap between digital twins and physical robots, making robotics accessible to developers, researchers, and enthusiasts worldwide._ | |