File size: 4,616 Bytes
bdc1ac8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
/**
 * Calibration Demo
 *
 * Demonstrates robot motor calibration with live feedback
 */

import { findPort, connectPort, releaseMotors, calibrate } from "@lerobot/node";
import type { RobotConnection, DiscoveredPort } from "@lerobot/node";

async function demoCalibrate() {
  console.log("🎯 Calibration Demo");
  console.log("===================\n");

  try {
    // Step 1: Find available robot ports
    console.log("πŸ“‘ Looking for connected robots...");
    const findProcess = await findPort();
    const discoveredPorts = await findProcess.result;

    if (discoveredPorts.length === 0) {
      throw new Error("No robots found. Please connect your robot first.");
    }

    console.log(`βœ… Found robot on ${discoveredPorts[0].path}`);

    // Step 2: Connect to robot
    console.log("πŸ”Œ Connecting to robot...");
    const robot = await connectPort(
      discoveredPorts[0].path,
      "so100_follower",
      "calibration_demo"
    );
    console.log(`βœ… Connected: ${robot.robotType} (ID: ${robot.robotId})\n`);

    // Step 3: Release motors
    console.log("πŸ”“ Releasing motors for calibration setup...");
    await releaseMotors(robot);
    console.log("βœ… Motors released - robot can now be moved by hand");

    console.log("\nπŸ“ Move robot to your preferred starting position...");
    console.log("Press any key to continue...");

    // Simple key press handler without readline conflicts
    process.stdin.setRawMode(true);
    process.stdin.resume();

    await new Promise<void>((resolve) => {
      const onData = () => {
        process.stdin.setRawMode(false);
        process.stdin.pause();
        process.stdin.removeListener("data", onData);
        resolve();
      };
      process.stdin.once("data", onData);
    });

    // Step 4: Calibration process
    console.log("\n🎯 Starting calibration process...");
    console.log("This will:");
    console.log("1. Set homing offsets (center positions)");
    console.log("2. Record range of motion for each motor");
    console.log("3. Write position limits to robot hardware");
    console.log("4. Save calibration data for future use\n");

    const calibrationProcess = await calibrate({
      robot,
      onProgress: (message) => {
        console.log(`πŸ“Š ${message}`);
      },
      onLiveUpdate: (data) => {
        // Display real-time motor positions and ranges
        const updates = Object.entries(data).map(([name, info]) => {
          const range = info.max - info.min;
          return `${name}: ${info.current} [${info.min}β†’${info.max}] (range: ${range})`;
        });

        console.clear();
        console.log("πŸ”„ Live Calibration Data:");
        console.log("========================");
        updates.forEach((update) => console.log(`   ${update}`));
        console.log("\nπŸ’‘ Move each motor through its full range of motion");
        console.log("   Press Enter to complete calibration...");
      },
    });

    // Wait for calibration to complete (it handles user input internally)
    const calibrationData = await calibrationProcess.result;

    console.log("\nβœ… Calibration completed successfully!");

    // Display detailed results
    console.log("\nπŸ“‹ Detailed Calibration Results:");
    console.log("=================================");
    Object.entries(calibrationData).forEach(([motorName, config]) => {
      const range = config.range_max - config.range_min;
      console.log(`${motorName}:`);
      console.log(`   Motor ID: ${config.id}`);
      console.log(`   Drive Mode: ${config.drive_mode}`);
      console.log(`   Homing Offset: ${config.homing_offset}`);
      console.log(
        `   Range: ${config.range_min} β†’ ${config.range_max} (${range} steps)`
      );
      console.log(`   Degrees: ~${((range / 4096) * 360).toFixed(1)}Β°\n`);
    });

    console.log("πŸ’Ύ Calibration saved to HuggingFace cache directory");
    console.log("πŸ”„ This file is compatible with Python lerobot");

    console.log("\nπŸŽ‰ Calibration demo completed!");
    console.log("πŸ’‘ You can now use this calibration data for teleoperation");

    // Ensure process can exit cleanly
    process.exit(0);
  } catch (error) {
    console.error("\n❌ Calibration failed:", error.message);
    console.log("\nπŸ”§ Troubleshooting:");
    console.log("- Ensure robot is connected and responsive");
    console.log("- Check that motors can move freely during calibration");
    console.log("- Avoid forcing motors past their mechanical limits");
    console.log("- Try restarting the robot if motors become unresponsive");
    process.exit(1);
  }
}

demoCalibrate();