first auto-review
This commit is contained in:
@@ -83,7 +83,7 @@ python lerobot/scripts/find_motors_bus_port.py
|
|||||||
|
|
||||||
Example output when identifying the leader arm's port (e.g., `/dev/tty.usbmodem575E0031751` on Mac, or possibly `/dev/ttyACM0` on Linux):
|
Example output when identifying the leader arm's port (e.g., `/dev/tty.usbmodem575E0031751` on Mac, or possibly `/dev/ttyACM0` on Linux):
|
||||||
```
|
```
|
||||||
Finding all available ports for the DynamixelMotorsBus.
|
Finding all available ports for the MotorBus.
|
||||||
['/dev/tty.usbmodem575E0032081', '/dev/tty.usbmodem575E0031751']
|
['/dev/tty.usbmodem575E0032081', '/dev/tty.usbmodem575E0031751']
|
||||||
Remove the usb cable from your DynamixelMotorsBus and press Enter when done.
|
Remove the usb cable from your DynamixelMotorsBus and press Enter when done.
|
||||||
|
|
||||||
@@ -95,7 +95,7 @@ Reconnect the usb cable.
|
|||||||
|
|
||||||
Example output when identifying the follower arm's port (e.g., `/dev/tty.usbmodem575E0032081`, or possibly `/dev/ttyACM1` on Linux):
|
Example output when identifying the follower arm's port (e.g., `/dev/tty.usbmodem575E0032081`, or possibly `/dev/ttyACM1` on Linux):
|
||||||
```
|
```
|
||||||
Finding all available ports for the DynamixelMotorsBus.
|
Finding all available ports for the MotorBus.
|
||||||
['/dev/tty.usbmodem575E0032081', '/dev/tty.usbmodem575E0031751']
|
['/dev/tty.usbmodem575E0032081', '/dev/tty.usbmodem575E0031751']
|
||||||
Remove the usb cable from your DynamixelMotorsBus and press Enter when done.
|
Remove the usb cable from your DynamixelMotorsBus and press Enter when done.
|
||||||
|
|
||||||
@@ -544,8 +544,7 @@ To instantiate an [`OpenCVCamera`](../lerobot/common/robot_devices/cameras/openc
|
|||||||
|
|
||||||
To find the camera indices, run the following utility script, which will save a few frames from each detected camera:
|
To find the camera indices, run the following utility script, which will save a few frames from each detected camera:
|
||||||
```bash
|
```bash
|
||||||
python lerobot/scripts/save_images_from_cameras.py \
|
python lerobot/common/robot_devices/cameras/opencv.py \
|
||||||
--driver opencv \
|
|
||||||
--images-dir outputs/images_from_opencv_cameras
|
--images-dir outputs/images_from_opencv_cameras
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -198,6 +198,8 @@ available_robots = [
|
|||||||
"koch",
|
"koch",
|
||||||
"koch_bimanual",
|
"koch_bimanual",
|
||||||
"aloha",
|
"aloha",
|
||||||
|
"so100",
|
||||||
|
"moss",
|
||||||
]
|
]
|
||||||
|
|
||||||
# lists all available cameras from `lerobot/common/robot_devices/cameras`
|
# lists all available cameras from `lerobot/common/robot_devices/cameras`
|
||||||
@@ -209,6 +211,7 @@ available_cameras = [
|
|||||||
# lists all available motors from `lerobot/common/robot_devices/motors`
|
# lists all available motors from `lerobot/common/robot_devices/motors`
|
||||||
available_motors = [
|
available_motors = [
|
||||||
"dynamixel",
|
"dynamixel",
|
||||||
|
"feetech",
|
||||||
]
|
]
|
||||||
|
|
||||||
# keys and values refer to yaml files
|
# keys and values refer to yaml files
|
||||||
|
|||||||
@@ -200,8 +200,7 @@ class IntelRealSenseCamera:
|
|||||||
|
|
||||||
To find the camera indices of your cameras, you can run our utility script that will save a few frames for each camera:
|
To find the camera indices of your cameras, you can run our utility script that will save a few frames for each camera:
|
||||||
```bash
|
```bash
|
||||||
python lerobot/scripts/save_images_from_cameras.py \
|
python lerobot/common/robot_devices/cameras/intelrealsense.py \
|
||||||
--driver intelrealsense \
|
|
||||||
--images-dir outputs/images_from_intelrealsense_cameras
|
--images-dir outputs/images_from_intelrealsense_cameras
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -216,8 +216,7 @@ class OpenCVCamera:
|
|||||||
|
|
||||||
To find the camera indices of your cameras, you can run our utility script that will be save a few frames for each camera:
|
To find the camera indices of your cameras, you can run our utility script that will be save a few frames for each camera:
|
||||||
```bash
|
```bash
|
||||||
python lerobot/scripts/save_images_from_cameras.py \
|
python lerobot/common/robot_devices/cameras/opencv.py \
|
||||||
--driver opencv \
|
|
||||||
--images-dir outputs/images_from_opencv_cameras
|
--images-dir outputs/images_from_opencv_cameras
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -325,7 +324,7 @@ class OpenCVCamera:
|
|||||||
if self.camera_index not in available_cam_ids:
|
if self.camera_index not in available_cam_ids:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
f"`camera_index` is expected to be one of these available cameras {available_cam_ids}, but {self.camera_index} is provided instead. "
|
f"`camera_index` is expected to be one of these available cameras {available_cam_ids}, but {self.camera_index} is provided instead. "
|
||||||
"To find the camera index you should use, run `python lerobot/scripts/save_images_from_cameras.py --driver opencv`."
|
"To find the camera index you should use, run `python lerobot/lerobot/common/robot_devices/cameras/opencv.py`."
|
||||||
)
|
)
|
||||||
|
|
||||||
raise OSError(f"Can't access OpenCVCamera({camera_idx}).")
|
raise OSError(f"Can't access OpenCVCamera({camera_idx}).")
|
||||||
|
|||||||
@@ -261,7 +261,7 @@ class DynamixelMotorsBus:
|
|||||||
To find the port, you can run our utility script:
|
To find the port, you can run our utility script:
|
||||||
```bash
|
```bash
|
||||||
python lerobot/scripts/find_motors_bus_port.py
|
python lerobot/scripts/find_motors_bus_port.py
|
||||||
>>> Finding all available ports for the DynamixelMotorsBus.
|
>>> Finding all available ports for the MotorBus.
|
||||||
>>> ['/dev/tty.usbmodem575E0032081', '/dev/tty.usbmodem575E0031751']
|
>>> ['/dev/tty.usbmodem575E0032081', '/dev/tty.usbmodem575E0031751']
|
||||||
>>> Remove the usb cable from your DynamixelMotorsBus and press Enter when done.
|
>>> Remove the usb cable from your DynamixelMotorsBus and press Enter when done.
|
||||||
>>> The port of this DynamixelMotorsBus is /dev/tty.usbmodem575E0031751.
|
>>> The port of this DynamixelMotorsBus is /dev/tty.usbmodem575E0031751.
|
||||||
@@ -371,14 +371,14 @@ class DynamixelMotorsBus:
|
|||||||
print(e)
|
print(e)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def find_motor_indices(self, possible_ids=None):
|
def find_motor_indices(self, possible_ids=None, num_retry=2):
|
||||||
if possible_ids is None:
|
if possible_ids is None:
|
||||||
possible_ids = range(MAX_ID_RANGE)
|
possible_ids = range(MAX_ID_RANGE)
|
||||||
|
|
||||||
indices = []
|
indices = []
|
||||||
for idx in tqdm.tqdm(possible_ids):
|
for idx in tqdm.tqdm(possible_ids):
|
||||||
try:
|
try:
|
||||||
present_idx = self.read_with_motor_ids(self.motor_models, [idx], "ID")[0]
|
present_idx = self.read_with_motor_ids(self.motor_models, [idx], "ID", num_retry=num_retry)[0]
|
||||||
except ConnectionError:
|
except ConnectionError:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@@ -638,7 +638,7 @@ class DynamixelMotorsBus:
|
|||||||
values = np.round(values).astype(np.int32)
|
values = np.round(values).astype(np.int32)
|
||||||
return values
|
return values
|
||||||
|
|
||||||
def read_with_motor_ids(self, motor_models, motor_ids, data_name):
|
def read_with_motor_ids(self, motor_models, motor_ids, data_name, num_retry=NUM_READ_RETRY):
|
||||||
if self.mock:
|
if self.mock:
|
||||||
import tests.mock_dynamixel_sdk as dxl
|
import tests.mock_dynamixel_sdk as dxl
|
||||||
else:
|
else:
|
||||||
@@ -655,7 +655,11 @@ class DynamixelMotorsBus:
|
|||||||
for idx in motor_ids:
|
for idx in motor_ids:
|
||||||
group.addParam(idx)
|
group.addParam(idx)
|
||||||
|
|
||||||
comm = group.txRxPacket()
|
for _ in range(num_retry):
|
||||||
|
comm = group.txRxPacket()
|
||||||
|
if comm == dxl.COMM_SUCCESS:
|
||||||
|
break
|
||||||
|
|
||||||
if comm != dxl.COMM_SUCCESS:
|
if comm != dxl.COMM_SUCCESS:
|
||||||
raise ConnectionError(
|
raise ConnectionError(
|
||||||
f"Read failed due to communication error on port {self.port_handler.port_name} for indices {motor_ids}: "
|
f"Read failed due to communication error on port {self.port_handler.port_name} for indices {motor_ids}: "
|
||||||
@@ -745,7 +749,7 @@ class DynamixelMotorsBus:
|
|||||||
|
|
||||||
return values
|
return values
|
||||||
|
|
||||||
def write_with_motor_ids(self, motor_models, motor_ids, data_name, values):
|
def write_with_motor_ids(self, motor_models, motor_ids, data_name, values, num_retry=NUM_WRITE_RETRY):
|
||||||
if self.mock:
|
if self.mock:
|
||||||
import tests.mock_dynamixel_sdk as dxl
|
import tests.mock_dynamixel_sdk as dxl
|
||||||
else:
|
else:
|
||||||
@@ -763,7 +767,11 @@ class DynamixelMotorsBus:
|
|||||||
data = convert_to_bytes(value, bytes, self.mock)
|
data = convert_to_bytes(value, bytes, self.mock)
|
||||||
group.addParam(idx, data)
|
group.addParam(idx, data)
|
||||||
|
|
||||||
comm = group.txPacket()
|
for _ in range(num_retry):
|
||||||
|
comm = group.txPacket()
|
||||||
|
if comm == dxl.COMM_SUCCESS:
|
||||||
|
break
|
||||||
|
|
||||||
if comm != dxl.COMM_SUCCESS:
|
if comm != dxl.COMM_SUCCESS:
|
||||||
raise ConnectionError(
|
raise ConnectionError(
|
||||||
f"Write failed due to communication error on port {self.port_handler.port_name} for indices {motor_ids}: "
|
f"Write failed due to communication error on port {self.port_handler.port_name} for indices {motor_ids}: "
|
||||||
|
|||||||
@@ -94,6 +94,7 @@ SCS_SERIES_CONTROL_TABLE = {
|
|||||||
"Status": (65, 1),
|
"Status": (65, 1),
|
||||||
"Moving": (66, 1),
|
"Moving": (66, 1),
|
||||||
"Present_Current": (69, 2),
|
"Present_Current": (69, 2),
|
||||||
|
# Not in the Memory Table
|
||||||
"Maximum_Acceleration": (85, 2),
|
"Maximum_Acceleration": (85, 2),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,6 +128,7 @@ MODEL_BAUDRATE_TABLE = {
|
|||||||
"sts3215": SCS_SERIES_BAUDRATE_TABLE,
|
"sts3215": SCS_SERIES_BAUDRATE_TABLE,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# High number of retries is needed for feetech compared to dynamixel motors.
|
||||||
NUM_READ_RETRY = 20
|
NUM_READ_RETRY = 20
|
||||||
NUM_WRITE_RETRY = 20
|
NUM_WRITE_RETRY = 20
|
||||||
|
|
||||||
@@ -235,7 +237,6 @@ class JointOutOfRangeError(Exception):
|
|||||||
|
|
||||||
|
|
||||||
class FeetechMotorsBus:
|
class FeetechMotorsBus:
|
||||||
# TODO(rcadene): Add a script to find the motor indices without feetechWizzard2
|
|
||||||
"""
|
"""
|
||||||
The FeetechMotorsBus class allows to efficiently read and write to the attached motors. It relies on
|
The FeetechMotorsBus class allows to efficiently read and write to the attached motors. It relies on
|
||||||
the python feetech sdk to communicate with the motors. For more info, see the [feetech SDK Documentation](https://emanual.robotis.com/docs/en/software/feetech/feetech_sdk/sample_code/python_read_write_protocol_2_0/#python-read-write-protocol-20).
|
the python feetech sdk to communicate with the motors. For more info, see the [feetech SDK Documentation](https://emanual.robotis.com/docs/en/software/feetech/feetech_sdk/sample_code/python_read_write_protocol_2_0/#python-read-write-protocol-20).
|
||||||
@@ -243,8 +244,8 @@ class FeetechMotorsBus:
|
|||||||
A FeetechMotorsBus instance requires a port (e.g. `FeetechMotorsBus(port="/dev/tty.usbmodem575E0031751"`)).
|
A FeetechMotorsBus instance requires a port (e.g. `FeetechMotorsBus(port="/dev/tty.usbmodem575E0031751"`)).
|
||||||
To find the port, you can run our utility script:
|
To find the port, you can run our utility script:
|
||||||
```bash
|
```bash
|
||||||
python lerobot/common/robot_devices/motors/feetech.py
|
python lerobot/scripts/find_motors_bus_port.py
|
||||||
>>> Finding all available ports for the FeetechMotorsBus.
|
>>> Finding all available ports for the MotorsBus.
|
||||||
>>> ['/dev/tty.usbmodem575E0032081', '/dev/tty.usbmodem575E0031751']
|
>>> ['/dev/tty.usbmodem575E0032081', '/dev/tty.usbmodem575E0031751']
|
||||||
>>> Remove the usb cable from your FeetechMotorsBus and press Enter when done.
|
>>> Remove the usb cable from your FeetechMotorsBus and press Enter when done.
|
||||||
>>> The port of this FeetechMotorsBus is /dev/tty.usbmodem575E0031751.
|
>>> The port of this FeetechMotorsBus is /dev/tty.usbmodem575E0031751.
|
||||||
@@ -255,7 +256,7 @@ class FeetechMotorsBus:
|
|||||||
```python
|
```python
|
||||||
motor_name = "gripper"
|
motor_name = "gripper"
|
||||||
motor_index = 6
|
motor_index = 6
|
||||||
motor_model = "xl330-m288"
|
motor_model = "sts3215"
|
||||||
|
|
||||||
motors_bus = FeetechMotorsBus(
|
motors_bus = FeetechMotorsBus(
|
||||||
port="/dev/tty.usbmodem575E0031751",
|
port="/dev/tty.usbmodem575E0031751",
|
||||||
|
|||||||
@@ -39,7 +39,6 @@ def compute_nearest_rounded_position(position, models):
|
|||||||
delta_turn = convert_degrees_to_steps(ROTATED_POSITION_DEGREE, models)
|
delta_turn = convert_degrees_to_steps(ROTATED_POSITION_DEGREE, models)
|
||||||
nearest_pos = np.round(position.astype(float) / delta_turn) * delta_turn
|
nearest_pos = np.round(position.astype(float) / delta_turn) * delta_turn
|
||||||
return nearest_pos.astype(position.dtype)
|
return nearest_pos.astype(position.dtype)
|
||||||
return position
|
|
||||||
|
|
||||||
|
|
||||||
def run_arm_calibration(arm: MotorsBus, robot_type: str, arm_name: str, arm_type: str):
|
def run_arm_calibration(arm: MotorsBus, robot_type: str, arm_name: str, arm_type: str):
|
||||||
|
|||||||
@@ -30,8 +30,8 @@ import time
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from lerobot.common.robot_devices.motors.dynamixel import find_port
|
|
||||||
from lerobot.common.robot_devices.utils import RobotDeviceAlreadyConnectedError, RobotDeviceNotConnectedError
|
from lerobot.common.robot_devices.utils import RobotDeviceAlreadyConnectedError, RobotDeviceNotConnectedError
|
||||||
|
from lerobot.scripts.find_motors_bus_port import find_port
|
||||||
from tests.utils import TEST_MOTOR_TYPES, make_motors_bus, require_motor
|
from tests.utils import TEST_MOTOR_TYPES, make_motors_bus, require_motor
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user