Skip to content

Commit d2046d4

Browse files
Merge branch 'main' into refactor/pretrainedconfig_device_amps_args
2 parents 8a61ec5 + e8ce388 commit d2046d4

File tree

4 files changed

+149
-20
lines changed

4 files changed

+149
-20
lines changed

README.md

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,24 @@
2323
</div>
2424

2525
<h2 align="center">
26-
<p><a href="https://github.com/huggingface/lerobot/blob/main/examples/10_use_so100.md">New robot in town: SO-100</a></p>
26+
<p><a href="https://github.com/huggingface/lerobot/blob/main/examples/10_use_so100.md">
27+
Build Your Own SO-100 Robot!</a></p>
2728
</h2>
2829

2930
<div align="center">
30-
<img src="media/so100/leader_follower.webp?raw=true" alt="SO-100 leader and follower arms" title="SO-100 leader and follower arms" width="50%">
31-
<p>We just added a new tutorial on how to build a more affordable robot, at the price of $110 per arm!</p>
32-
<p>Teach it new skills by showing it a few moves with just a laptop.</p>
33-
<p>Then watch your homemade robot act autonomously 🤯</p>
34-
<p>Follow the link to the <a href="https://github.com/huggingface/lerobot/blob/main/examples/10_use_so100.md">full tutorial for SO-100</a>.</p>
31+
<img src="media/so100/leader_follower.webp?raw=true" alt="SO-100 leader and follower arms" title="SO-100 leader and follower arms" width="50%">
32+
33+
<p><strong>Meet the SO-100 – Just $110 per arm!</strong></p>
34+
<p>Train it in minutes with a few simple moves on your laptop.</p>
35+
<p>Then sit back and watch your creation act autonomously! 🤯</p>
36+
37+
<p><a href="https://github.com/huggingface/lerobot/blob/main/examples/10_use_so100.md">
38+
Get the full SO-100 tutorial here.</a></p>
39+
40+
<p>Want to take it to the next level? Make your SO-100 mobile by building LeKiwi!</p>
41+
<p>Check out the <a href="https://github.com/huggingface/lerobot/blob/main/examples/11_use_lekiwi.md">LeKiwi tutorial</a> and bring your robot to life on wheels.</p>
42+
43+
<img src="media/lekiwi/kiwi.webp?raw=true" alt="LeKiwi mobile robot" title="LeKiwi mobile robot" width="50%">
3544
</div>
3645

3746
<br/>

examples/11_use_lekiwi.md

Lines changed: 124 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ Follow this [README](https://github.com/SIGRobotics-UIUC/LeKiwi). It contains th
2323

2424
Before assembling, you will first need to configure your motors. To this end, we provide a nice script, so let's first install LeRobot. After configuration, we will also guide you through assembly.
2525

26+
### Wired version
27+
If you have the **wired** LeKiwi version you can skip the installation of the Raspberry Pi and setting up SSH. You can also run all commands directly on your PC for both the LeKiwi scripts and the leader arm scripts for teleoperating.
28+
2629
## B. Install software on Pi
2730
Now we have to setup the remote PC that will run on the LeKiwi Robot. This is normally a Raspberry Pi, but can be any PC that can run on 5V and has enough usb ports (2 or more) for the cameras and motor control board.
2831

@@ -246,6 +249,110 @@ class LeKiwiRobotConfig(RobotConfig):
246249
}
247250
)
248251

252+
teleop_keys: dict[str, str] = field(
253+
default_factory=lambda: {
254+
# Movement
255+
"forward": "w",
256+
"backward": "s",
257+
"left": "a",
258+
"right": "d",
259+
"rotate_left": "z",
260+
"rotate_right": "x",
261+
# Speed control
262+
"speed_up": "r",
263+
"speed_down": "f",
264+
# quit teleop
265+
"quit": "q",
266+
}
267+
)
268+
269+
mock: bool = False
270+
```
271+
272+
## Wired version
273+
274+
For the wired LeKiwi version your configured IP address should refer to your own laptop (127.0.0.1), because leader arm and LeKiwi are in this case connected to own laptop. Below and example configuration for this wired setup:
275+
```python
276+
@RobotConfig.register_subclass("lekiwi")
277+
@dataclass
278+
class LeKiwiRobotConfig(RobotConfig):
279+
# `max_relative_target` limits the magnitude of the relative positional target vector for safety purposes.
280+
# Set this to a positive scalar to have the same value for all motors, or a list that is the same length as
281+
# the number of motors in your follower arms.
282+
max_relative_target: int | None = None
283+
284+
# Network Configuration
285+
ip: str = "127.0.0.1"
286+
port: int = 5555
287+
video_port: int = 5556
288+
289+
cameras: dict[str, CameraConfig] = field(
290+
default_factory=lambda: {
291+
"front": OpenCVCameraConfig(
292+
camera_index=0, fps=30, width=640, height=480, rotation=90
293+
),
294+
"wrist": OpenCVCameraConfig(
295+
camera_index=1, fps=30, width=640, height=480, rotation=180
296+
),
297+
}
298+
)
299+
300+
calibration_dir: str = ".cache/calibration/lekiwi"
301+
302+
leader_arms: dict[str, MotorsBusConfig] = field(
303+
default_factory=lambda: {
304+
"main": FeetechMotorsBusConfig(
305+
port="/dev/tty.usbmodem585A0077581",
306+
motors={
307+
# name: (index, model)
308+
"shoulder_pan": [1, "sts3215"],
309+
"shoulder_lift": [2, "sts3215"],
310+
"elbow_flex": [3, "sts3215"],
311+
"wrist_flex": [4, "sts3215"],
312+
"wrist_roll": [5, "sts3215"],
313+
"gripper": [6, "sts3215"],
314+
},
315+
),
316+
}
317+
)
318+
319+
follower_arms: dict[str, MotorsBusConfig] = field(
320+
default_factory=lambda: {
321+
"main": FeetechMotorsBusConfig(
322+
port="/dev/tty.usbmodem58760431061",
323+
motors={
324+
# name: (index, model)
325+
"shoulder_pan": [1, "sts3215"],
326+
"shoulder_lift": [2, "sts3215"],
327+
"elbow_flex": [3, "sts3215"],
328+
"wrist_flex": [4, "sts3215"],
329+
"wrist_roll": [5, "sts3215"],
330+
"gripper": [6, "sts3215"],
331+
"left_wheel": (7, "sts3215"),
332+
"back_wheel": (8, "sts3215"),
333+
"right_wheel": (9, "sts3215"),
334+
},
335+
),
336+
}
337+
)
338+
339+
teleop_keys: dict[str, str] = field(
340+
default_factory=lambda: {
341+
# Movement
342+
"forward": "w",
343+
"backward": "s",
344+
"left": "a",
345+
"right": "d",
346+
"rotate_left": "z",
347+
"rotate_right": "x",
348+
# Speed control
349+
"speed_up": "r",
350+
"speed_down": "f",
351+
# quit teleop
352+
"quit": "q",
353+
}
354+
)
355+
249356
mock: bool = False
250357
```
251358

@@ -272,6 +379,9 @@ python lerobot/scripts/control_robot.py \
272379
--control.arms='["main_follower"]'
273380
```
274381

382+
### Wired version
383+
If you have the **wired** LeKiwi version please run all commands including this calibration command on your laptop.
384+
275385
### Calibrate leader arm
276386
Then to calibrate the leader arm (which is attached to the laptop/pc). You will need to move the leader arm to these positions sequentially:
277387

@@ -326,6 +436,9 @@ You should see on your laptop something like this: ```[INFO] Connected to remote
326436
> [!TIP]
327437
> If you use a different keyboard you can change the keys for each command in the [`LeKiwiRobotConfig`](../lerobot/common/robot_devices/robots/configs.py).
328438
439+
### Wired version
440+
If you have the **wired** LeKiwi version please run all commands including both these teleoperation commands on your laptop.
441+
329442
## Troubleshoot communication
330443

331444
If you are having trouble connecting to the Mobile SO100, follow these steps to diagnose and resolve the issue.
@@ -364,6 +477,13 @@ Make sure the configuration file on both your laptop/pc and the Raspberry Pi is
364477
# G. Record a dataset
365478
Once you're familiar with teleoperation, you can record your first dataset with LeKiwi.
366479

480+
To start the program on LeKiwi, SSH into your Raspberry Pi, and run `conda activate lerobot` and this script:
481+
```bash
482+
python lerobot/scripts/control_robot.py \
483+
--robot.type=lekiwi \
484+
--control.type=remote_robot
485+
```
486+
367487
If you want to use the Hugging Face hub features for uploading your dataset and you haven't previously done it, make sure you've logged in using a write-access token, which can be generated from the [Hugging Face settings](https://huggingface.co/settings/tokens):
368488
```bash
369489
huggingface-cli login --token ${HUGGINGFACE_TOKEN} --add-to-git-credential
@@ -374,8 +494,7 @@ Store your Hugging Face repository name in a variable to run these commands:
374494
HF_USER=$(huggingface-cli whoami | head -n 1)
375495
echo $HF_USER
376496
```
377-
378-
Record 2 episodes and upload your dataset to the hub:
497+
On your laptop then run this command to record 2 episodes and upload your dataset to the hub:
379498
```bash
380499
python lerobot/scripts/control_robot.py \
381500
--robot.type=lekiwi \
@@ -393,6 +512,9 @@ python lerobot/scripts/control_robot.py \
393512

394513
Note: You can resume recording by adding `--control.resume=true`.
395514

515+
### Wired version
516+
If you have the **wired** LeKiwi version please run all commands including both these record dataset commands on your laptop.
517+
396518
# H. Visualize a dataset
397519

398520
If you uploaded your dataset to the hub with `--control.push_to_hub=true`, you can [visualize your dataset online](https://huggingface.co/spaces/lerobot/visualize_dataset) by copy pasting your repo id given by:

lerobot/common/robot_devices/robots/mobile_manipulator.py

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -392,21 +392,19 @@ def teleop_step(
392392
for name in self.leader_arms:
393393
pos = self.leader_arms[name].read("Present_Position")
394394
pos_tensor = torch.from_numpy(pos).float()
395-
# Instead of pos_tensor.item(), use tolist() to convert the entire tensor to a list
396395
arm_positions.extend(pos_tensor.tolist())
397396

398-
# (The rest of your code for generating wheel commands remains unchanged)
399-
x_cmd = 0.0 # m/s forward/backward
400-
y_cmd = 0.0 # m/s lateral
397+
y_cmd = 0.0 # m/s forward/backward
398+
x_cmd = 0.0 # m/s lateral
401399
theta_cmd = 0.0 # deg/s rotation
402400
if self.pressed_keys["forward"]:
403-
x_cmd += xy_speed
401+
y_cmd += xy_speed
404402
if self.pressed_keys["backward"]:
405-
x_cmd -= xy_speed
403+
y_cmd -= xy_speed
406404
if self.pressed_keys["left"]:
407-
y_cmd += xy_speed
405+
x_cmd += xy_speed
408406
if self.pressed_keys["right"]:
409-
y_cmd -= xy_speed
407+
x_cmd -= xy_speed
410408
if self.pressed_keys["rotate_left"]:
411409
theta_cmd += theta_speed
412410
if self.pressed_keys["rotate_right"]:
@@ -584,8 +582,8 @@ def body_to_wheel_raw(
584582
# Create the body velocity vector [x, y, theta_rad].
585583
velocity_vector = np.array([x_cmd, y_cmd, theta_rad])
586584

587-
# Define the wheel mounting angles with a -90° offset.
588-
angles = np.radians(np.array([240, 120, 0]) - 90)
585+
# Define the wheel mounting angles (defined from y axis cw)
586+
angles = np.radians(np.array([300, 180, 60]))
589587
# Build the kinematic matrix: each row maps body velocities to a wheel’s linear speed.
590588
# The third column (base_radius) accounts for the effect of rotation.
591589
m = np.array([[np.cos(a), np.sin(a), base_radius] for a in angles])
@@ -641,8 +639,8 @@ def wheel_raw_to_body(
641639
# Compute each wheel’s linear speed (m/s) from its angular speed.
642640
wheel_linear_speeds = wheel_radps * wheel_radius
643641

644-
# Define the wheel mounting angles with a -90° offset.
645-
angles = np.radians(np.array([240, 120, 0]) - 90)
642+
# Define the wheel mounting angles (defined from y axis cw)
643+
angles = np.radians(np.array([300, 180, 60]))
646644
m = np.array([[np.cos(a), np.sin(a), base_radius] for a in angles])
647645

648646
# Solve the inverse kinematics: body_velocity = M⁻¹ · wheel_linear_speeds.

media/lekiwi/kiwi.webp

219 KB
Loading

0 commit comments

Comments
 (0)