Spaces:
Running
Running
File size: 5,607 Bytes
5ed471e ae872e1 9883b81 5ed471e 45fb4ba 5ed471e 45fb4ba 5ed471e 45fb4ba 5ed471e 45fb4ba 5ed471e 45fb4ba 5ed471e 45fb4ba 5ed471e 45fb4ba 5ed471e |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 |
// Import WASM module and functions from npm (published version)
import init, {
connect,
enable_torque,
disable_torque,
forward_kinematics,
inverse_kinematics,
start_fk_stream,
replay_recording,
stop,
// Video Stream (optional - for future use)
connect_video_stream,
disconnect_video_stream,
is_using_camera_fallback,
// Audio Stream (optional - for future use)
connect_audio_stream,
disconnect_audio_stream,
is_using_microphone_fallback,
} from 'https://unpkg.com/reachy-mini@0.6.1/index.js';
// Elements
const btnConnect = document.getElementById('btn-connect');
const btnTorqueOn = document.getElementById('btn-torque-on');
const btnTorqueOff = document.getElementById('btn-torque-off');
const btnFK = document.getElementById('btn-fk');
const btnIK = document.getElementById('btn-ik');
const btnRecord = document.getElementById('btn-record');
const btnReplay = document.getElementById('btn-replay');
const btnStop = document.getElementById('btn-stop');
const statusIndicator = document.getElementById('status-indicator');
const output = document.getElementById('output');
let isConnected = false;
// Logging
function log(message, type = 'info') {
console.log(`[${type}] ${message}`);
const line = document.createElement('div');
line.className = 'output-line';
const timestamp = new Date().toLocaleTimeString();
const icon = type === 'success' ? '✓' : type === 'error' ? '✗' : 'ℹ';
line.textContent = `[${timestamp}] ${icon} ${message}`;
output.appendChild(line);
output.scrollTop = output.scrollHeight;
}
// Initialize WASM
try {
console.log('Initializing WASM...');
await init();
log('WASM module loaded successfully', 'success');
console.log('connect function:', typeof connect);
} catch (err) {
console.error('WASM init error:', err);
log(`Failed to load WASM module: ${err.message}`, 'error');
log('Make sure you run from a local server: python3 -m http.server 8080', 'error');
}
// Connection
btnConnect.addEventListener('click', async () => {
console.log('Connect button clicked');
try {
btnConnect.disabled = true;
btnConnect.textContent = 'Connecting...';
log('Attempting to connect to Reachy Mini...');
console.log('Calling connect()...');
const result = await connect(null);
console.log('Connect result:', result);
isConnected = true;
statusIndicator.textContent = 'Connected';
statusIndicator.className = 'status status-connected';
btnConnect.textContent = 'Connected';
// Enable other buttons
[btnTorqueOn, btnTorqueOff, btnFK, btnIK, btnRecord, btnReplay, btnStop].forEach(btn => {
btn.disabled = false;
});
log('Successfully connected to Reachy Mini!', 'success');
} catch (err) {
console.error('Connection error:', err);
btnConnect.disabled = false;
btnConnect.textContent = 'Connect to Robot';
log(`Connection failed: ${err}`, 'error');
}
});
// Torque Control
btnTorqueOn.addEventListener('click', async () => {
try {
log('Enabling torque...');
await enable_torque();
log('Torque enabled', 'success');
} catch (err) {
log(`Error: ${err}`, 'error');
}
});
btnTorqueOff.addEventListener('click', async () => {
try {
log('Disabling torque...');
await disable_torque();
log('Torque disabled', 'success');
} catch (err) {
log(`Error: ${err}`, 'error');
}
});
// Forward Kinematics
btnFK.addEventListener('click', () => {
try {
log('Testing forward kinematics...');
const angles = [0, 0, 0, 0, 0, 0]; // 6 head motors at 0 degrees
const pose = forward_kinematics(angles);
log(`Input angles: [${angles.join(', ')}]`);
log(`Output pose [x, y, z, roll, pitch, yaw]: [${[...pose].map(v => v.toFixed(2)).join(', ')}]`, 'success');
} catch (err) {
log(`Error: ${err}`, 'error');
}
});
// Inverse Kinematics
btnIK.addEventListener('click', () => {
try {
log('Testing inverse kinematics...');
const pose = [0, 0, 0, 0, 0, 0]; // x, y, z, roll, pitch, yaw
const joints = inverse_kinematics(pose);
log(`Input pose [x, y, z, roll, pitch, yaw]: [${pose.join(', ')}]`);
log(`Output joints (degrees): [${[...joints].map(v => v.toFixed(2)).join(', ')}]`, 'success');
} catch (err) {
log(`Error: ${err}`, 'error');
}
});
// Recording
btnRecord.addEventListener('click', async () => {
try {
log('Recording movement for 10 seconds...');
btnRecord.disabled = true;
await start_fk_stream(10000); // 10 seconds
btnRecord.disabled = false;
log('Recording complete', 'success');
} catch (err) {
btnRecord.disabled = false;
log(`Error: ${err}`, 'error');
}
});
btnReplay.addEventListener('click', async () => {
try {
log('Replaying recorded movement...');
btnReplay.disabled = true;
await replay_recording();
btnReplay.disabled = false;
log('Replay complete', 'success');
} catch (err) {
btnReplay.disabled = false;
log(`Error: ${err}`, 'error');
}
});
btnStop.addEventListener('click', async () => {
try {
log('Stopping current operation...');
await stop();
log('Stopped', 'success');
} catch (err) {
log(`Error: ${err.message}`, 'error');
}
});
log('Ready to connect. Click "Connect to Robot" to begin.');
|