Merge remote-tracking branch 'origin/main' into user/aliberts/2025_02_25_refactor_robots
This commit is contained in:
@@ -96,8 +96,8 @@ Reconnect the usb cable.
|
|||||||
#### Update config file
|
#### Update config file
|
||||||
|
|
||||||
Now that you have your ports, update the **port** default values of [`SO101RobotConfig`](https://github.com/huggingface/lerobot/blob/main/lerobot/common/robot_devices/robots/configs.py).
|
Now that you have your ports, update the **port** default values of [`SO101RobotConfig`](https://github.com/huggingface/lerobot/blob/main/lerobot/common/robot_devices/robots/configs.py).
|
||||||
You will find something like, update the `port` values with your actual motor ports:
|
You will find a class called `so101` where you can update the `port` values with your actual motor ports:
|
||||||
```python
|
```diff
|
||||||
@RobotConfig.register_subclass("so101")
|
@RobotConfig.register_subclass("so101")
|
||||||
@dataclass
|
@dataclass
|
||||||
class So101RobotConfig(ManipulatorRobotConfig):
|
class So101RobotConfig(ManipulatorRobotConfig):
|
||||||
@@ -110,7 +110,8 @@ class So101RobotConfig(ManipulatorRobotConfig):
|
|||||||
leader_arms: dict[str, MotorsBusConfig] = field(
|
leader_arms: dict[str, MotorsBusConfig] = field(
|
||||||
default_factory=lambda: {
|
default_factory=lambda: {
|
||||||
"main": FeetechMotorsBusConfig(
|
"main": FeetechMotorsBusConfig(
|
||||||
port="/dev/tty.usbmodem58760431091", <-- UPDATE HERE
|
- port="/dev/tty.usbmodem58760431091",
|
||||||
|
+ port="{ADD YOUR LEADER PORT}",
|
||||||
motors={
|
motors={
|
||||||
# name: (index, model)
|
# name: (index, model)
|
||||||
"shoulder_pan": [1, "sts3215"],
|
"shoulder_pan": [1, "sts3215"],
|
||||||
@@ -127,7 +128,8 @@ class So101RobotConfig(ManipulatorRobotConfig):
|
|||||||
follower_arms: dict[str, MotorsBusConfig] = field(
|
follower_arms: dict[str, MotorsBusConfig] = field(
|
||||||
default_factory=lambda: {
|
default_factory=lambda: {
|
||||||
"main": FeetechMotorsBusConfig(
|
"main": FeetechMotorsBusConfig(
|
||||||
port="/dev/tty.usbmodem585A0076891", <-- UPDATE HERE
|
- port="/dev/tty.usbmodem585A0076891",
|
||||||
|
+ port="{ADD YOUR FOLLOWER PORT}",
|
||||||
motors={
|
motors={
|
||||||
# name: (index, model)
|
# name: (index, model)
|
||||||
"shoulder_pan": [1, "sts3215"],
|
"shoulder_pan": [1, "sts3215"],
|
||||||
@@ -297,7 +299,7 @@ Remove all support material from the 3D-printed parts, the easiest way to do thi
|
|||||||
##### Wiring
|
##### Wiring
|
||||||
|
|
||||||
- Attach the motor controller on the back.
|
- Attach the motor controller on the back.
|
||||||
- Then insert all wires, use the wire guides everywhere to make sure the wires don't unplug themself and stay in place.
|
- Then insert all wires, use the wire guides everywhere to make sure the wires don't unplug themselves and stay in place.
|
||||||
|
|
||||||
<div class="video-container">
|
<div class="video-container">
|
||||||
<video controls width="600">
|
<video controls width="600">
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ camera_01_frame_000047.png
|
|||||||
|
|
||||||
Note: Some cameras may take a few seconds to warm up, and the first frame might be black or green.
|
Note: Some cameras may take a few seconds to warm up, and the first frame might be black or green.
|
||||||
|
|
||||||
Now that you have the camera indexes, you should specify the camera's in the config. TODO(pepijn): add more info about setting camera config, rotate etc..
|
Now that you have the camera indexes, you should specify the camera's in the config.
|
||||||
|
|
||||||
### Use your phone
|
### Use your phone
|
||||||
<hfoptions id="use phone">
|
<hfoptions id="use phone">
|
||||||
@@ -152,7 +152,7 @@ If everything is set up correctly, you can proceed with the rest of the tutorial
|
|||||||
|
|
||||||
## Teleoperate with cameras
|
## Teleoperate with cameras
|
||||||
|
|
||||||
We can now teleoperate again while at the same time visualizing the camera's and joint positions with `rerun`.
|
We can now teleoperate again while at the same time visualizing the cameras and joint positions with `rerun`.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
python lerobot/scripts/control_robot.py \
|
python lerobot/scripts/control_robot.py \
|
||||||
|
|||||||
@@ -145,8 +145,8 @@ Reconnect the usb cable.
|
|||||||
#### Update config file
|
#### Update config file
|
||||||
|
|
||||||
Now that you have your ports, update the **port** default values of [`SO101RobotConfig`](https://github.com/huggingface/lerobot/blob/main/lerobot/common/robot_devices/robots/configs.py).
|
Now that you have your ports, update the **port** default values of [`SO101RobotConfig`](https://github.com/huggingface/lerobot/blob/main/lerobot/common/robot_devices/robots/configs.py).
|
||||||
You will find something a class called `so101` where you can update the `port` values with your actual motor ports:
|
You will find a class called `so101` where you can update the `port` values with your actual motor ports:
|
||||||
```python
|
```diff
|
||||||
@RobotConfig.register_subclass("so101")
|
@RobotConfig.register_subclass("so101")
|
||||||
@dataclass
|
@dataclass
|
||||||
class So101RobotConfig(ManipulatorRobotConfig):
|
class So101RobotConfig(ManipulatorRobotConfig):
|
||||||
@@ -159,7 +159,8 @@ class So101RobotConfig(ManipulatorRobotConfig):
|
|||||||
leader_arms: dict[str, MotorsBusConfig] = field(
|
leader_arms: dict[str, MotorsBusConfig] = field(
|
||||||
default_factory=lambda: {
|
default_factory=lambda: {
|
||||||
"main": FeetechMotorsBusConfig(
|
"main": FeetechMotorsBusConfig(
|
||||||
port="/dev/tty.usbmodem58760431091", <-- UPDATE HERE
|
- port="/dev/tty.usbmodem58760431091",
|
||||||
|
+ port="{ADD YOUR LEADER PORT}",
|
||||||
motors={
|
motors={
|
||||||
# name: (index, model)
|
# name: (index, model)
|
||||||
"shoulder_pan": [1, "sts3215"],
|
"shoulder_pan": [1, "sts3215"],
|
||||||
@@ -176,7 +177,8 @@ class So101RobotConfig(ManipulatorRobotConfig):
|
|||||||
follower_arms: dict[str, MotorsBusConfig] = field(
|
follower_arms: dict[str, MotorsBusConfig] = field(
|
||||||
default_factory=lambda: {
|
default_factory=lambda: {
|
||||||
"main": FeetechMotorsBusConfig(
|
"main": FeetechMotorsBusConfig(
|
||||||
port="/dev/tty.usbmodem585A0076891", <-- UPDATE HERE
|
- port="/dev/tty.usbmodem585A0076891",
|
||||||
|
+ port="{ADD YOUR FOLLOWER PORT}",
|
||||||
motors={
|
motors={
|
||||||
# name: (index, model)
|
# name: (index, model)
|
||||||
"shoulder_pan": [1, "sts3215"],
|
"shoulder_pan": [1, "sts3215"],
|
||||||
@@ -308,7 +310,7 @@ Remove all support material from the 3D-printed parts.
|
|||||||
##### Wiring
|
##### Wiring
|
||||||
|
|
||||||
- Attach the motor controller on the back.
|
- Attach the motor controller on the back.
|
||||||
- Then insert all wires, use the wire guides everywhere to make sure the wires don't unplug themself and stay in place.
|
- Then insert all wires, use the wire guides everywhere to make sure the wires don't unplug themselves and stay in place.
|
||||||
|
|
||||||
<video controls width="640" src="https://github.com/user-attachments/assets/4c2cacfd-9276-4ee4-8bf2-ba2492667b78" type="video/mp4"></video>
|
<video controls width="640" src="https://github.com/user-attachments/assets/4c2cacfd-9276-4ee4-8bf2-ba2492667b78" type="video/mp4"></video>
|
||||||
|
|
||||||
@@ -351,7 +353,7 @@ python lerobot/scripts/control_robot.py \
|
|||||||
```
|
```
|
||||||
## Control your robot
|
## Control your robot
|
||||||
|
|
||||||
Congrats 🎉, your robot is all set to learn a task on its own. Next we will explain you how to train a neural network to autonomously control a real robot.
|
Congrats 🎉, your robot is all set to learn a task on its own. Next we will explain to you how to train a neural network to autonomously control a real robot.
|
||||||
|
|
||||||
**You'll learn to:**
|
**You'll learn to:**
|
||||||
1. How to record and visualize your dataset.
|
1. How to record and visualize your dataset.
|
||||||
@@ -515,7 +517,7 @@ If you have an additional camera you can add a wrist camera to the SO101. There
|
|||||||
|
|
||||||
## Teleoperate with cameras
|
## Teleoperate with cameras
|
||||||
|
|
||||||
We can now teleoperate again while at the same time visualizing the camera's and joint positions with `rerun`.
|
We can now teleoperate again while at the same time visualizing the cameras and joint positions with `rerun`.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
python lerobot/scripts/control_robot.py \
|
python lerobot/scripts/control_robot.py \
|
||||||
@@ -526,7 +528,7 @@ python lerobot/scripts/control_robot.py \
|
|||||||
|
|
||||||
## Record a dataset
|
## Record a dataset
|
||||||
|
|
||||||
Once you're familiar with teleoperation, you can record your first dataset with SO-100.
|
Once you're familiar with teleoperation, you can record your first dataset with SO-101.
|
||||||
|
|
||||||
We use the Hugging Face hub features for uploading your dataset. If you haven't previously used the Hub, make sure you can login via the cli using a write-access token, this token can be generated from the [Hugging Face settings](https://huggingface.co/settings/tokens).
|
We use the Hugging Face hub features for uploading your dataset. If you haven't previously used the Hub, make sure you can login via the cli using a write-access token, this token can be generated from the [Hugging Face settings](https://huggingface.co/settings/tokens).
|
||||||
|
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ sudo chmod 666 /dev/ttyACM1
|
|||||||
#### d. Update config file
|
#### d. Update config file
|
||||||
|
|
||||||
IMPORTANTLY: Now that you have your ports, update the **port** default values of [`SO100RobotConfig`](../lerobot/common/robot_devices/robots/configs.py). You will find something like:
|
IMPORTANTLY: Now that you have your ports, update the **port** default values of [`SO100RobotConfig`](../lerobot/common/robot_devices/robots/configs.py). You will find something like:
|
||||||
```python
|
```diff
|
||||||
@RobotConfig.register_subclass("so100")
|
@RobotConfig.register_subclass("so100")
|
||||||
@dataclass
|
@dataclass
|
||||||
class So100RobotConfig(ManipulatorRobotConfig):
|
class So100RobotConfig(ManipulatorRobotConfig):
|
||||||
@@ -141,7 +141,8 @@ class So100RobotConfig(ManipulatorRobotConfig):
|
|||||||
leader_arms: dict[str, MotorsBusConfig] = field(
|
leader_arms: dict[str, MotorsBusConfig] = field(
|
||||||
default_factory=lambda: {
|
default_factory=lambda: {
|
||||||
"main": FeetechMotorsBusConfig(
|
"main": FeetechMotorsBusConfig(
|
||||||
port="/dev/tty.usbmodem58760431091", <-- UPDATE HERE
|
- port="/dev/tty.usbmodem58760431091",
|
||||||
|
+ port="{ADD YOUR LEADER PORT}",
|
||||||
motors={
|
motors={
|
||||||
# name: (index, model)
|
# name: (index, model)
|
||||||
"shoulder_pan": [1, "sts3215"],
|
"shoulder_pan": [1, "sts3215"],
|
||||||
@@ -158,7 +159,8 @@ class So100RobotConfig(ManipulatorRobotConfig):
|
|||||||
follower_arms: dict[str, MotorsBusConfig] = field(
|
follower_arms: dict[str, MotorsBusConfig] = field(
|
||||||
default_factory=lambda: {
|
default_factory=lambda: {
|
||||||
"main": FeetechMotorsBusConfig(
|
"main": FeetechMotorsBusConfig(
|
||||||
port="/dev/tty.usbmodem585A0076891", <-- UPDATE HERE
|
- port="/dev/tty.usbmodem585A0076891",
|
||||||
|
+ port="{ADD YOUR FOLLOWER PORT}",
|
||||||
motors={
|
motors={
|
||||||
# name: (index, model)
|
# name: (index, model)
|
||||||
"shoulder_pan": [1, "sts3215"],
|
"shoulder_pan": [1, "sts3215"],
|
||||||
|
|||||||
@@ -250,6 +250,7 @@ def control_loop(
|
|||||||
observation, action = robot.teleop_step(record_data=True)
|
observation, action = robot.teleop_step(record_data=True)
|
||||||
else:
|
else:
|
||||||
observation = robot.capture_observation()
|
observation = robot.capture_observation()
|
||||||
|
action = None
|
||||||
|
|
||||||
if policy is not None:
|
if policy is not None:
|
||||||
pred_action = predict_action(
|
pred_action = predict_action(
|
||||||
@@ -266,9 +267,10 @@ def control_loop(
|
|||||||
|
|
||||||
# TODO(Steven): This should be more general (for RemoteRobot instead of checking the name, but anyways it will change soon)
|
# TODO(Steven): This should be more general (for RemoteRobot instead of checking the name, but anyways it will change soon)
|
||||||
if (display_data and not is_headless()) or (display_data and robot.robot_type.startswith("lekiwi")):
|
if (display_data and not is_headless()) or (display_data and robot.robot_type.startswith("lekiwi")):
|
||||||
for k, v in action.items():
|
if action is not None:
|
||||||
for i, vv in enumerate(v):
|
for k, v in action.items():
|
||||||
rr.log(f"sent_{k}_{i}", rr.Scalar(vv.numpy()))
|
for i, vv in enumerate(v):
|
||||||
|
rr.log(f"sent_{k}_{i}", rr.Scalar(vv.numpy()))
|
||||||
|
|
||||||
image_keys = [key for key in observation if "image" in key]
|
image_keys = [key for key in observation if "image" in key]
|
||||||
for key in image_keys:
|
for key in image_keys:
|
||||||
|
|||||||
Reference in New Issue
Block a user