Update opencv and dynamixel (find_port)
This commit is contained in:
parent
7411cf2a7a
commit
f7a7ed9aa9
|
@ -155,7 +155,10 @@ class OpenCVCamera:
|
||||||
python lerobot/common/robot_devices/cameras/opencv.py --images-dir outputs/images_from_opencv_cameras
|
python lerobot/common/robot_devices/cameras/opencv.py --images-dir outputs/images_from_opencv_cameras
|
||||||
```
|
```
|
||||||
|
|
||||||
Example of uage of the class:
|
When an OpenCVCamera is instantiated, if no specific config is provided, the default fps, width, height and color
|
||||||
|
of the given camera will be used.
|
||||||
|
|
||||||
|
Example of usage of the class:
|
||||||
```python
|
```python
|
||||||
camera = OpenCVCamera(camera_index=0)
|
camera = OpenCVCamera(camera_index=0)
|
||||||
camera.connect()
|
camera.connect()
|
||||||
|
@ -163,6 +166,18 @@ class OpenCVCamera:
|
||||||
# when done using the camera, consider disconnecting
|
# when done using the camera, consider disconnecting
|
||||||
camera.disconnect()
|
camera.disconnect()
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Example of changing default fps, width, height and color:
|
||||||
|
```python
|
||||||
|
camera = OpenCVCamera(0, fps=30, width=1280, height=720)
|
||||||
|
camera = connect() # applies the settings, might error out if these settings are not compatible with the camera
|
||||||
|
|
||||||
|
camera = OpenCVCamera(0, fps=90, width=640, height=480)
|
||||||
|
camera = connect()
|
||||||
|
|
||||||
|
camera = OpenCVCamera(0, fps=90, width=640, height=480, color="bgr")
|
||||||
|
camera = connect()
|
||||||
|
```
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, camera_index: int, config: OpenCVCameraConfig | None = None, **kwargs):
|
def __init__(self, camera_index: int, config: OpenCVCameraConfig | None = None, **kwargs):
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import enum
|
import enum
|
||||||
import time
|
import time
|
||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from dynamixel_sdk import (
|
from dynamixel_sdk import (
|
||||||
|
@ -159,6 +160,35 @@ def get_log_name(var_name, fn_name, data_name, motor_names):
|
||||||
return log_name
|
return log_name
|
||||||
|
|
||||||
|
|
||||||
|
def find_available_ports():
|
||||||
|
ports = []
|
||||||
|
for path in Path("/dev").glob("tty.usbmodem*"):
|
||||||
|
ports.append(str(path))
|
||||||
|
return ports
|
||||||
|
|
||||||
|
|
||||||
|
def find_port():
|
||||||
|
print("Finding all available ports for the DynamixelMotorsBus.")
|
||||||
|
ports_before = find_available_ports()
|
||||||
|
print(ports_before)
|
||||||
|
|
||||||
|
print("Remove the usb cable from your DynamixelMotorsBus and press Enter when done.")
|
||||||
|
input()
|
||||||
|
|
||||||
|
time.sleep(0.5)
|
||||||
|
ports_after = find_available_ports()
|
||||||
|
ports_diff = list(set(ports_before) - set(ports_after))
|
||||||
|
|
||||||
|
if len(ports_diff) == 1:
|
||||||
|
port = ports_diff[0]
|
||||||
|
print(f"The port of this DynamixelMotorsBus is {port}.")
|
||||||
|
print("Reconnect the usb cable.")
|
||||||
|
elif len(ports_diff) == 0:
|
||||||
|
raise OSError(f"Could not detect the port. No difference was found ({ports_diff}).")
|
||||||
|
else:
|
||||||
|
raise OSError(f"Could not detect the port. More than one port was found ({ports_diff}).")
|
||||||
|
|
||||||
|
|
||||||
class TorqueMode(enum.Enum):
|
class TorqueMode(enum.Enum):
|
||||||
ENABLED = 1
|
ENABLED = 1
|
||||||
DISABLED = 0
|
DISABLED = 0
|
||||||
|
@ -179,7 +209,23 @@ class DriveMode(enum.Enum):
|
||||||
|
|
||||||
|
|
||||||
class DynamixelMotorsBus:
|
class DynamixelMotorsBus:
|
||||||
|
# TODO(rcadene): Add a script to find the motor indices without DynamixelWizzard2
|
||||||
"""
|
"""
|
||||||
|
The DynamixelMotorsBus class allows to efficiently read and write to the attached motors. It relies on
|
||||||
|
the python dynamixel sdk to communicate with the motors. For more info, see the [Dynamixel SDK Documentation](https://emanual.robotis.com/docs/en/software/dynamixel/dynamixel_sdk/sample_code/python_read_write_protocol_2_0/#python-read-write-protocol-20).
|
||||||
|
|
||||||
|
A DynamixelMotorsBus instance requires a port (e.g. `DynamixelMotorsBus(port="/dev/tty.usbmodem575E0031751"`)).
|
||||||
|
To find the port, you can run our utility script:
|
||||||
|
```bash
|
||||||
|
python lerobot/common/robot_devices/motors/dynamixel.py
|
||||||
|
>>> Finding all available ports for the DynamixelMotorsBus.
|
||||||
|
>>> ['/dev/tty.usbmodem575E0032081', '/dev/tty.usbmodem575E0031751']
|
||||||
|
>>> Remove the usb cable from your DynamixelMotorsBus and press Enter when done.
|
||||||
|
>>> The port of this DynamixelMotorsBus is /dev/tty.usbmodem575E0031751.
|
||||||
|
>>> Reconnect the usb cable.
|
||||||
|
```
|
||||||
|
To find the motor indices, use [DynamixelWizzard2](https://emanual.robotis.com/docs/en/software/dynamixel/dynamixel_wizard2).
|
||||||
|
|
||||||
Example of usage for 1 motor connected to the bus:
|
Example of usage for 1 motor connected to the bus:
|
||||||
```python
|
```python
|
||||||
motor_name = "gripper"
|
motor_name = "gripper"
|
||||||
|
@ -194,6 +240,7 @@ class DynamixelMotorsBus:
|
||||||
|
|
||||||
motors_bus.teleop_step()
|
motors_bus.teleop_step()
|
||||||
|
|
||||||
|
# when done, consider disconnecting
|
||||||
motors_bus.disconnect()
|
motors_bus.disconnect()
|
||||||
```
|
```
|
||||||
"""
|
"""
|
||||||
|
@ -450,3 +497,8 @@ class DynamixelMotorsBus:
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
if getattr(self, "is_connected", False):
|
if getattr(self, "is_connected", False):
|
||||||
self.disconnect()
|
self.disconnect()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
# Helper to find the usb port associated to all your DynamixelMotorsBus.
|
||||||
|
find_port()
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
def make_robot(name):
|
def make_robot(name):
|
||||||
if name == "koch":
|
if name == "koch":
|
||||||
|
# TODO(rcadene): Add configurable robot from command line and yaml config
|
||||||
|
# TODO(rcadene): Add example with and without cameras
|
||||||
from lerobot.common.robot_devices.cameras.opencv import OpenCVCamera
|
from lerobot.common.robot_devices.cameras.opencv import OpenCVCamera
|
||||||
from lerobot.common.robot_devices.motors.dynamixel import DynamixelMotorsBus
|
from lerobot.common.robot_devices.motors.dynamixel import DynamixelMotorsBus
|
||||||
from lerobot.common.robot_devices.robots.koch import KochRobot
|
from lerobot.common.robot_devices.robots.koch import KochRobot
|
||||||
|
|
|
@ -3,7 +3,7 @@ import time
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from lerobot.common.robot_devices.motors.dynamixel import DynamixelMotorsBus
|
from lerobot.common.robot_devices.motors.dynamixel import DynamixelMotorsBus, find_port
|
||||||
from lerobot.common.robot_devices.utils import RobotDeviceAlreadyConnectedError, RobotDeviceNotConnectedError
|
from lerobot.common.robot_devices.utils import RobotDeviceAlreadyConnectedError, RobotDeviceNotConnectedError
|
||||||
|
|
||||||
|
|
||||||
|
@ -81,3 +81,7 @@ def test_motors_bus():
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
new_values = motors_bus.read("Present_Position")
|
new_values = motors_bus.read("Present_Position")
|
||||||
assert (new_values == values).all()
|
assert (new_values == values).all()
|
||||||
|
|
||||||
|
|
||||||
|
def test_find_port():
|
||||||
|
find_port()
|
||||||
|
|
Loading…
Reference in New Issue