NERDDISCO commited on
Commit
7daaa53
·
1 Parent(s): b4db948

docs: updated to reflect the current state

Browse files
Files changed (1) hide show
  1. packages/web/README.md +43 -205
packages/web/README.md CHANGED
@@ -1,10 +1,11 @@
1
  # @lerobot/web
2
 
3
- Browser-native robotics control using WebSerial API. No Python dependencies required.
4
 
5
  ## Features
6
 
7
  - **Direct Hardware Control**: STS3215 motor communication via WebSerial API
 
8
  - **Real-time Teleoperation**: Keyboard control with live motor feedback
9
  - **Motor Calibration**: Automated homing offset and range recording
10
  - **Cross-browser Support**: Chrome/Edge 89+ with HTTPS or localhost
@@ -13,29 +14,54 @@ Browser-native robotics control using WebSerial API. No Python dependencies requ
13
  ## Installation
14
 
15
  ```bash
 
 
 
 
16
  npm install @lerobot/web
 
 
 
17
  ```
18
 
19
  ## Quick Start
20
 
21
  ```typescript
22
- import { findPort, calibrate, teleoperate } from "@lerobot/web";
23
 
24
  // 1. Find and connect to hardware
25
  const findProcess = await findPort();
26
  const robots = await findProcess.result;
27
  const robot = robots[0];
28
 
29
- // 2. Calibrate motors
 
 
 
 
30
  const calibrationProcess = await calibrate(robot, {
31
  onProgress: (message) => console.log(message),
32
  onLiveUpdate: (data) => console.log("Live positions:", data),
33
  });
 
 
 
 
 
 
 
 
34
  const calibrationData = await calibrationProcess.result;
35
 
36
- // 3. Start teleoperation
37
  const teleop = await teleoperate(robot, { calibrationData });
38
  teleop.start();
 
 
 
 
 
 
39
  ```
40
 
41
  ## Core API
@@ -109,55 +135,6 @@ console.log(
109
  );
110
  ```
111
 
112
- #### Complete Workflow Example
113
-
114
- ```typescript
115
- // First run: Interactive discovery
116
- async function discoverNewRobots() {
117
- const findProcess = await findPort();
118
- const robots = await findProcess.result;
119
-
120
- for (const robot of robots) {
121
- // Configure each robot
122
- robot.robotType = "so100_follower"; // User choice
123
- robot.robotId = `robot_${Date.now()}`; // User input
124
-
125
- // Save for auto-connect
126
- localStorage.setItem(
127
- `robot-${robot.serialNumber}`,
128
- JSON.stringify({
129
- robotType: robot.robotType,
130
- robotId: robot.robotId,
131
- serialNumber: robot.serialNumber,
132
- })
133
- );
134
- }
135
-
136
- return robots;
137
- }
138
-
139
- // Subsequent runs: Auto-connect
140
- async function reconnectSavedRobots() {
141
- // Load saved robot configs
142
- const robotConfigs = [];
143
- for (let i = 0; i < localStorage.length; i++) {
144
- const key = localStorage.key(i);
145
- if (key?.startsWith("robot-")) {
146
- const saved = JSON.parse(localStorage.getItem(key)!);
147
- robotConfigs.push(saved);
148
- }
149
- }
150
-
151
- if (robotConfigs.length === 0) {
152
- return discoverNewRobots(); // No saved robots, go interactive
153
- }
154
-
155
- // Auto-connect to saved robots
156
- const findProcess = await findPort({ robotConfigs });
157
- return await findProcess.result;
158
- }
159
- ```
160
-
161
  #### RobotConfig Structure
162
 
163
  ```typescript
@@ -198,7 +175,11 @@ const calibrationProcess = await calibrate(robot, {
198
  });
199
 
200
  // Move robot through full range of motion...
201
- // Press any key when done
 
 
 
 
202
 
203
  const calibrationData = await calibrationProcess.result;
204
  // Save calibration data to localStorage or file
@@ -256,8 +237,11 @@ await teleop.setMotorPositions({
256
  elbow_flex: 1500,
257
  });
258
 
259
- // Stop when done
260
- teleop.stop();
 
 
 
261
  ```
262
 
263
  #### Parameters
@@ -289,19 +273,6 @@ Escape: Emergency stop
289
 
290
  ---
291
 
292
- ### `isWebSerialSupported(): boolean`
293
-
294
- Checks if WebSerial API is available in the current browser.
295
-
296
- ```typescript
297
- if (!isWebSerialSupported()) {
298
- console.log("Please use Chrome/Edge 89+ with HTTPS or localhost");
299
- return;
300
- }
301
- ```
302
-
303
- ---
304
-
305
  ### `releaseMotors(robot, motorIds?): Promise<void>`
306
 
307
  Releases motor torque so robot can be moved freely by hand.
@@ -311,7 +282,7 @@ Releases motor torque so robot can be moved freely by hand.
311
  await releaseMotors(robot);
312
 
313
  // Release specific motors only
314
- await releaseMotors(robot, [1, 2, 3]); // First 3 motors
315
  ```
316
 
317
  #### Parameters
@@ -319,145 +290,12 @@ await releaseMotors(robot, [1, 2, 3]); // First 3 motors
319
  - `robot: RobotConnection` - Connected robot
320
  - `motorIds?: number[]` - Specific motor IDs (default: all motors for robot type)
321
 
322
- ## Types
323
-
324
- ### `RobotConnection`
325
-
326
- ```typescript
327
- interface RobotConnection {
328
- port: SerialPort; // WebSerial port object
329
- name: string; // Display name
330
- isConnected: boolean; // Connection status
331
- robotType?: "so100_follower" | "so100_leader";
332
- robotId?: string; // User-defined ID
333
- serialNumber: string; // Device serial number
334
- error?: string; // Error message if failed
335
- }
336
- ```
337
-
338
- ### `WebCalibrationResults`
339
-
340
- ```typescript
341
- interface WebCalibrationResults {
342
- [motorName: string]: {
343
- id: number; // Motor ID (1-6)
344
- drive_mode: number; // Drive mode (0 for SO-100)
345
- homing_offset: number; // Calculated offset
346
- range_min: number; // Minimum position
347
- range_max: number; // Maximum position
348
- };
349
- }
350
- ```
351
-
352
- ### `TeleoperationState`
353
-
354
- ```typescript
355
- interface TeleoperationState {
356
- isActive: boolean; // Whether teleoperation is running
357
- motorConfigs: MotorConfig[]; // Current motor positions and limits
358
- lastUpdate: number; // Timestamp of last update
359
- keyStates: { [key: string]: { pressed: boolean; timestamp: number } };
360
- }
361
- ```
362
-
363
- ### `MotorConfig`
364
-
365
- ```typescript
366
- interface MotorConfig {
367
- id: number; // Motor ID
368
- name: string; // Motor name (e.g., "shoulder_pan")
369
- currentPosition: number; // Current position
370
- minPosition: number; // Position limit minimum
371
- maxPosition: number; // Position limit maximum
372
- }
373
- ```
374
-
375
- ### `RobotConfig`
376
-
377
- ```typescript
378
- interface RobotConfig {
379
- robotType: "so100_follower" | "so100_leader";
380
- robotId: string; // Your custom identifier (e.g., "left_arm")
381
- serialNumber: string; // Device serial number (from previous findPort)
382
- }
383
- ```
384
-
385
- ## Advanced Usage
386
-
387
- ### Custom Motor Communication
388
-
389
- ```typescript
390
- import {
391
- WebSerialPortWrapper,
392
- readMotorPosition,
393
- writeMotorPosition,
394
- } from "@lerobot/web";
395
-
396
- const port = new WebSerialPortWrapper(robotConnection.port);
397
- await port.initialize();
398
-
399
- // Read motor position directly
400
- const position = await readMotorPosition(port, 1);
401
-
402
- // Write motor position directly
403
- await writeMotorPosition(port, 1, 2048);
404
- ```
405
-
406
- ### Robot Configuration
407
-
408
- ```typescript
409
- import { createSO100Config, SO100_KEYBOARD_CONTROLS } from "@lerobot/web";
410
-
411
- const config = createSO100Config("so100_follower");
412
- console.log("Motor names:", config.motorNames);
413
- console.log("Motor IDs:", config.motorIds);
414
- console.log("Keyboard controls:", SO100_KEYBOARD_CONTROLS);
415
- ```
416
-
417
- ### Low-Level Motor Control
418
-
419
- ```typescript
420
- import { releaseMotorsLowLevel } from "@lerobot/web";
421
-
422
- const port = new WebSerialPortWrapper(robotConnection.port);
423
- await port.initialize();
424
-
425
- // Release specific motors at low level
426
- await releaseMotorsLowLevel(port, [1, 2, 3]);
427
- ```
428
-
429
- ## Error Handling
430
-
431
- ```typescript
432
- try {
433
- const findProcess = await findPort();
434
- const robots = await findProcess.result;
435
-
436
- if (robots.length === 0) {
437
- throw new Error("No robots found");
438
- }
439
-
440
- const robot = robots[0];
441
- if (!robot.isConnected) {
442
- throw new Error(`Failed to connect: ${robot.error}`);
443
- }
444
-
445
- // Proceed with calibration/teleoperation
446
- } catch (error) {
447
- console.error("Robot connection failed:", error.message);
448
- }
449
- ```
450
-
451
  ## Browser Requirements
452
 
453
- - **Chrome/Edge 89+** with WebSerial API support
454
- - **HTTPS or localhost** (required for WebSerial API)
455
  - **User gesture** required for initial port selection
456
 
457
  ## Hardware Support
458
 
459
  Currently supports SO-100 follower and leader arms with STS3215 motors. More devices coming soon.
460
-
461
- ## License
462
-
463
- Apache-2.0
 
1
  # @lerobot/web
2
 
3
+ Browser-native robotics control using WebSerial and WebUSB APIs.
4
 
5
  ## Features
6
 
7
  - **Direct Hardware Control**: STS3215 motor communication via WebSerial API
8
+ - **Device Persistence**: WebUSB API for automatic robot reconnection
9
  - **Real-time Teleoperation**: Keyboard control with live motor feedback
10
  - **Motor Calibration**: Automated homing offset and range recording
11
  - **Cross-browser Support**: Chrome/Edge 89+ with HTTPS or localhost
 
14
  ## Installation
15
 
16
  ```bash
17
+ # pnpm (recommended)
18
+ pnpm add @lerobot/web
19
+
20
+ # npm
21
  npm install @lerobot/web
22
+
23
+ # yarn
24
+ yarn add @lerobot/web
25
  ```
26
 
27
  ## Quick Start
28
 
29
  ```typescript
30
+ import { findPort, releaseMotors, calibrate, teleoperate } from "@lerobot/web";
31
 
32
  // 1. Find and connect to hardware
33
  const findProcess = await findPort();
34
  const robots = await findProcess.result;
35
  const robot = robots[0];
36
 
37
+ // 2. Release motors for manual positioning
38
+ await releaseMotors(robot);
39
+ console.log("🔓 Motors released - you can move the robot by hand");
40
+
41
+ // 3. Calibrate motors
42
  const calibrationProcess = await calibrate(robot, {
43
  onProgress: (message) => console.log(message),
44
  onLiveUpdate: (data) => console.log("Live positions:", data),
45
  });
46
+
47
+ // Move robot through its full range of motion...
48
+ // When done, stop calibration to proceed
49
+ setTimeout(() => {
50
+ console.log("⏱️ Stopping calibration...");
51
+ calibrationProcess.stop();
52
+ }, 10000); // Stop after 10 seconds, or call stop() when user is ready
53
+
54
  const calibrationData = await calibrationProcess.result;
55
 
56
+ // 4. Start teleoperation
57
  const teleop = await teleoperate(robot, { calibrationData });
58
  teleop.start();
59
+
60
+ // Stop teleoperation when done
61
+ setTimeout(() => {
62
+ console.log("⏹️ Stopping teleoperation...");
63
+ teleop.stop();
64
+ }, 30000); // Stop after 30 seconds, or call stop() when needed
65
  ```
66
 
67
  ## Core API
 
135
  );
136
  ```
137
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
138
  #### RobotConfig Structure
139
 
140
  ```typescript
 
175
  });
176
 
177
  // Move robot through full range of motion...
178
+ // When finished recording ranges, stop the calibration
179
+ console.log("Move robot through its range, then stopping in 10 seconds...");
180
+ setTimeout(() => {
181
+ calibrationProcess.stop(); // Stop range recording
182
+ }, 10000);
183
 
184
  const calibrationData = await calibrationProcess.result;
185
  // Save calibration data to localStorage or file
 
237
  elbow_flex: 1500,
238
  });
239
 
240
+ // Stop teleoperation when finished
241
+ setTimeout(() => {
242
+ console.log("Stopping teleoperation...");
243
+ teleop.stop();
244
+ }, 30000); // Or call teleop.stop() when user is done
245
  ```
246
 
247
  #### Parameters
 
273
 
274
  ---
275
 
 
 
 
 
 
 
 
 
 
 
 
 
 
276
  ### `releaseMotors(robot, motorIds?): Promise<void>`
277
 
278
  Releases motor torque so robot can be moved freely by hand.
 
282
  await releaseMotors(robot);
283
 
284
  // Release specific motors only
285
+ await releaseMotors(robot, [1, 2, 3]);
286
  ```
287
 
288
  #### Parameters
 
290
  - `robot: RobotConnection` - Connected robot
291
  - `motorIds?: number[]` - Specific motor IDs (default: all motors for robot type)
292
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
293
  ## Browser Requirements
294
 
295
+ - **chromium 89+** with WebSerial and WebUSB API support
296
+ - **HTTPS or localhost**
297
  - **User gesture** required for initial port selection
298
 
299
  ## Hardware Support
300
 
301
  Currently supports SO-100 follower and leader arms with STS3215 motors. More devices coming soon.