simpler
Browse files- README.md +3 -4
- app.js +1 -53
- index.html +0 -9
README.md
CHANGED
|
@@ -14,11 +14,11 @@ A lightweight, static HTML/JS control panel for Reachy Mini robot using WebSocke
|
|
| 14 |
## Features
|
| 15 |
|
| 16 |
- **Real-time WebSocket Control**: Instant response using WebSocket streaming
|
| 17 |
-
- **Wake Up / Go to Sleep**: Movement command buttons
|
| 18 |
- **Task Space Control**: Real-time head pose control (X, Y, Z, Roll, Pitch, Yaw)
|
| 19 |
- **Body & Antennas**: Control body yaw and antenna positions
|
| 20 |
- **Auto-reconnect**: Automatically reconnects if connection is lost
|
| 21 |
- **No Dependencies**: Pure HTML/CSS/JavaScript
|
|
|
|
| 22 |
|
| 23 |
## How to Use
|
| 24 |
|
|
@@ -67,16 +67,15 @@ php -S localhost:7860
|
|
| 67 |
|
| 68 |
- Reachy Mini daemon running on `localhost:8000`
|
| 69 |
- Modern web browser with WebSocket support
|
| 70 |
-
- Motors must be enabled before using wake/sleep commands
|
| 71 |
|
| 72 |
## Architecture
|
| 73 |
|
| 74 |
This app uses:
|
| 75 |
- **WebSocket** (`ws://localhost:8000/api/move/ws/set_target`) for real-time pose streaming
|
| 76 |
-
- **HTTP POST** for wake_up and goto_sleep commands
|
| 77 |
- Pure client-side JavaScript (no backend needed)
|
|
|
|
| 78 |
|
| 79 |
-
|
| 80 |
|
| 81 |
## Technical Details
|
| 82 |
|
|
|
|
| 14 |
## Features
|
| 15 |
|
| 16 |
- **Real-time WebSocket Control**: Instant response using WebSocket streaming
|
|
|
|
| 17 |
- **Task Space Control**: Real-time head pose control (X, Y, Z, Roll, Pitch, Yaw)
|
| 18 |
- **Body & Antennas**: Control body yaw and antenna positions
|
| 19 |
- **Auto-reconnect**: Automatically reconnects if connection is lost
|
| 20 |
- **No Dependencies**: Pure HTML/CSS/JavaScript
|
| 21 |
+
- **100% Client-Side**: No backend needed, runs entirely in the browser
|
| 22 |
|
| 23 |
## How to Use
|
| 24 |
|
|
|
|
| 67 |
|
| 68 |
- Reachy Mini daemon running on `localhost:8000`
|
| 69 |
- Modern web browser with WebSocket support
|
|
|
|
| 70 |
|
| 71 |
## Architecture
|
| 72 |
|
| 73 |
This app uses:
|
| 74 |
- **WebSocket** (`ws://localhost:8000/api/move/ws/set_target`) for real-time pose streaming
|
|
|
|
| 75 |
- Pure client-side JavaScript (no backend needed)
|
| 76 |
+
- Automatic reconnection if connection is lost
|
| 77 |
|
| 78 |
+
**Note**: Due to browser security (Mixed Content policy), the WebSocket connection from HuggingFace Spaces (HTTPS) to localhost (HTTP) may be blocked. For best results, run the app locally.
|
| 79 |
|
| 80 |
## Technical Details
|
| 81 |
|
app.js
CHANGED
|
@@ -1,9 +1,8 @@
|
|
| 1 |
// Reachy Mini Control Panel - WebSocket Version
|
| 2 |
-
// Connects to localhost:8000 WebSocket
|
| 3 |
|
| 4 |
const ROBOT_URL = 'localhost:8000';
|
| 5 |
const WS_URL = `ws://${ROBOT_URL}/api/move/ws/set_target`;
|
| 6 |
-
const HTTP_URL = `http://${ROBOT_URL}`;
|
| 7 |
|
| 8 |
// Global state
|
| 9 |
const state = {
|
|
@@ -20,8 +19,6 @@ const state = {
|
|
| 20 |
// DOM elements
|
| 21 |
const elements = {
|
| 22 |
status: document.getElementById('connectionStatus'),
|
| 23 |
-
wakeUpBtn: document.getElementById('wakeUpBtn'),
|
| 24 |
-
sleepBtn: document.getElementById('sleepBtn'),
|
| 25 |
sliders: {
|
| 26 |
headX: document.getElementById('headX'),
|
| 27 |
headY: document.getElementById('headY'),
|
|
@@ -98,9 +95,6 @@ function updateConnectionStatus(connected) {
|
|
| 98 |
|
| 99 |
// Enable/disable controls
|
| 100 |
function enableControls(enabled) {
|
| 101 |
-
elements.wakeUpBtn.disabled = !enabled;
|
| 102 |
-
elements.sleepBtn.disabled = !enabled;
|
| 103 |
-
|
| 104 |
Object.values(elements.sliders).forEach(slider => {
|
| 105 |
slider.disabled = !enabled;
|
| 106 |
});
|
|
@@ -206,57 +200,11 @@ function setupSliderHandlers() {
|
|
| 206 |
});
|
| 207 |
}
|
| 208 |
|
| 209 |
-
// HTTP API calls for movement commands
|
| 210 |
-
async function playWakeUp() {
|
| 211 |
-
try {
|
| 212 |
-
const response = await fetch(`${HTTP_URL}/api/move/play/wake_up`, {
|
| 213 |
-
method: 'POST',
|
| 214 |
-
headers: { 'Content-Type': 'application/json' }
|
| 215 |
-
});
|
| 216 |
-
|
| 217 |
-
if (!response.ok) {
|
| 218 |
-
throw new Error(`HTTP ${response.status}`);
|
| 219 |
-
}
|
| 220 |
-
|
| 221 |
-
const result = await response.json();
|
| 222 |
-
console.log('Wake up started:', result.uuid);
|
| 223 |
-
} catch (error) {
|
| 224 |
-
console.error('Wake up failed:', error);
|
| 225 |
-
alert('Failed to wake up robot: ' + error.message);
|
| 226 |
-
}
|
| 227 |
-
}
|
| 228 |
-
|
| 229 |
-
async function playGotoSleep() {
|
| 230 |
-
try {
|
| 231 |
-
const response = await fetch(`${HTTP_URL}/api/move/play/goto_sleep`, {
|
| 232 |
-
method: 'POST',
|
| 233 |
-
headers: { 'Content-Type': 'application/json' }
|
| 234 |
-
});
|
| 235 |
-
|
| 236 |
-
if (!response.ok) {
|
| 237 |
-
throw new Error(`HTTP ${response.status}`);
|
| 238 |
-
}
|
| 239 |
-
|
| 240 |
-
const result = await response.json();
|
| 241 |
-
console.log('Go to sleep started:', result.uuid);
|
| 242 |
-
} catch (error) {
|
| 243 |
-
console.error('Go to sleep failed:', error);
|
| 244 |
-
alert('Failed to put robot to sleep: ' + error.message);
|
| 245 |
-
}
|
| 246 |
-
}
|
| 247 |
-
|
| 248 |
-
// Button handlers
|
| 249 |
-
function setupButtonHandlers() {
|
| 250 |
-
elements.wakeUpBtn.addEventListener('click', playWakeUp);
|
| 251 |
-
elements.sleepBtn.addEventListener('click', playGotoSleep);
|
| 252 |
-
}
|
| 253 |
-
|
| 254 |
// Initialize app
|
| 255 |
function init() {
|
| 256 |
console.log('Initializing Reachy Mini Control Panel');
|
| 257 |
|
| 258 |
setupSliderHandlers();
|
| 259 |
-
setupButtonHandlers();
|
| 260 |
connectWebSocket();
|
| 261 |
|
| 262 |
console.log('Control panel ready');
|
|
|
|
| 1 |
// Reachy Mini Control Panel - WebSocket Version
|
| 2 |
+
// Connects to localhost:8000 WebSocket API for real-time control
|
| 3 |
|
| 4 |
const ROBOT_URL = 'localhost:8000';
|
| 5 |
const WS_URL = `ws://${ROBOT_URL}/api/move/ws/set_target`;
|
|
|
|
| 6 |
|
| 7 |
// Global state
|
| 8 |
const state = {
|
|
|
|
| 19 |
// DOM elements
|
| 20 |
const elements = {
|
| 21 |
status: document.getElementById('connectionStatus'),
|
|
|
|
|
|
|
| 22 |
sliders: {
|
| 23 |
headX: document.getElementById('headX'),
|
| 24 |
headY: document.getElementById('headY'),
|
|
|
|
| 95 |
|
| 96 |
// Enable/disable controls
|
| 97 |
function enableControls(enabled) {
|
|
|
|
|
|
|
|
|
|
| 98 |
Object.values(elements.sliders).forEach(slider => {
|
| 99 |
slider.disabled = !enabled;
|
| 100 |
});
|
|
|
|
| 200 |
});
|
| 201 |
}
|
| 202 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 203 |
// Initialize app
|
| 204 |
function init() {
|
| 205 |
console.log('Initializing Reachy Mini Control Panel');
|
| 206 |
|
| 207 |
setupSliderHandlers();
|
|
|
|
| 208 |
connectWebSocket();
|
| 209 |
|
| 210 |
console.log('Control panel ready');
|
index.html
CHANGED
|
@@ -229,15 +229,6 @@
|
|
| 229 |
</div>
|
| 230 |
</div>
|
| 231 |
|
| 232 |
-
<!-- Movement Commands -->
|
| 233 |
-
<div class="section">
|
| 234 |
-
<h2>Movement Commands</h2>
|
| 235 |
-
<div class="button-row">
|
| 236 |
-
<button id="wakeUpBtn" disabled>Wake Up</button>
|
| 237 |
-
<button id="sleepBtn" class="secondary" disabled>Go to Sleep</button>
|
| 238 |
-
</div>
|
| 239 |
-
</div>
|
| 240 |
-
|
| 241 |
<!-- Head Pose Control -->
|
| 242 |
<div class="section">
|
| 243 |
<h2>Head Pose Control</h2>
|
|
|
|
| 229 |
</div>
|
| 230 |
</div>
|
| 231 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 232 |
<!-- Head Pose Control -->
|
| 233 |
<div class="section">
|
| 234 |
<h2>Head Pose Control</h2>
|