diff --git a/apis/python/node/generate_stubs.py b/apis/python/node/generate_stubs.py index 298928bd..0acc9595 100644 --- a/apis/python/node/generate_stubs.py +++ b/apis/python/node/generate_stubs.py @@ -287,8 +287,7 @@ def arguments_stub( param_names = list(real_parameters.keys()) if param_names and param_names[0] == "self": del param_names[0] - for name, t in zip(param_names, builtin[0]): - parsed_param_types[name] = t + parsed_param_types = {name: t for name, t in zip(param_names, builtin[0])} # Types from comment for match in re.findall( diff --git a/binaries/cli/src/template/python/listener/listener-template.py b/binaries/cli/src/template/python/listener/listener-template.py index 140718f2..ebcc5501 100644 --- a/binaries/cli/src/template/python/listener/listener-template.py +++ b/binaries/cli/src/template/python/listener/listener-template.py @@ -2,6 +2,7 @@ from dora import Node + def main(): """Listen for input events and print received messages.""" node = Node() diff --git a/binaries/cli/src/template/python/talker/talker-template.py b/binaries/cli/src/template/python/talker/talker-template.py index 703d6f72..e8811b65 100644 --- a/binaries/cli/src/template/python/talker/talker-template.py +++ b/binaries/cli/src/template/python/talker/talker-template.py @@ -3,6 +3,7 @@ import pyarrow as pa from dora import Node + def main(): """Process node input events and send speech output.""" node = Node() diff --git a/examples/alexk-lcr/bus.py b/examples/alexk-lcr/bus.py index d123fa67..78043e6a 100644 --- a/examples/alexk-lcr/bus.py +++ b/examples/alexk-lcr/bus.py @@ -1,17 +1,25 @@ -import enum +"""Module for managing Dynamixel servo bus communication and control. -import pyarrow as pa +This module provides functionality for communicating with and controlling Dynamixel servos +through a serial bus interface. It includes methods for reading and writing servo parameters, +managing torque and operating modes, and handling joint positions and velocities. +""" +import enum from typing import Union +import pyarrow as pa from dynamixel_sdk import ( - PacketHandler, - PortHandler, COMM_SUCCESS, + DXL_HIBYTE, + DXL_HIWORD, + DXL_LOBYTE, + DXL_LOWORD, GroupSyncRead, GroupSyncWrite, + PacketHandler, + PortHandler, ) -from dynamixel_sdk import DXL_HIBYTE, DXL_HIWORD, DXL_LOBYTE, DXL_LOWORD PROTOCOL_VERSION = 2.0 BAUD_RATE = 1_000_000 @@ -20,40 +28,37 @@ TIMEOUT_MS = 1000 def wrap_joints_and_values( joints: Union[list[str], pa.Array], - values: Union[int, list[int], pa.Array], + values: Union[list[int], pa.Array], ) -> pa.StructArray: - """ - Wraps joints and their corresponding values into a structured array. + """Wrap joints and their corresponding values into a structured array. - :param joints: A list, numpy array, or pyarrow array of joint names. - :type joints: Union[list[str], np.array, pa.Array] - :param values: A single integer value, or a list, numpy array, or pyarrow array of integer values. - If a single integer is provided, it will be broadcasted to all joints. - :type values: Union[int, list[int], np.array, pa.Array] + Args: + joints: A list, numpy array, or pyarrow array of joint names. + values: A single integer value, or a list, numpy array, or pyarrow array of integer values. + If a single integer is provided, it will be broadcasted to all joints. - :return: A structured array with two fields: - - "joints": A string field containing the names of the joints. - - "values": An Int32Array containing the values corresponding to the joints. - :rtype: pa.StructArray + Returns: + A structured array with two fields: + - "joints": A string field containing the names of the joints. + - "values": An Int32Array containing the values corresponding to the joints. - :raises ValueError: If lengths of joints and values do not match. + Raises: + ValueError: If lengths of joints and values do not match. Example: - -------- - joints = ["shoulder_pan", "shoulder_lift", "elbow_flex"] - values = [100, 200, 300] - struct_array = wrap_joints_and_values(joints, values) + joints = ["shoulder_pan", "shoulder_lift", "elbow_flex"] + values = [100, 200, 300] + struct_array = wrap_joints_and_values(joints, values) - This example wraps the given joints and their corresponding values into a structured array. + This example wraps the given joints and their corresponding values into a structured array. - Another example with a single integer value: - joints = ["shoulder_pan", "shoulder_lift", "elbow_flex"] - value = 150 - struct_array = wrap_joints_and_values(joints, value) + Another example with a single integer value: + joints = ["shoulder_pan", "shoulder_lift", "elbow_flex"] + value = 150 + struct_array = wrap_joints_and_values(joints, value) - This example broadcasts the single integer value to all joints and wraps them into a structured array. + This example broadcasts the single integer value to all joints and wraps them into a structured array. """ - if isinstance(values, int): values = [values] * len(joints) @@ -69,16 +74,20 @@ def wrap_joints_and_values( mask = values.is_null() return pa.StructArray.from_arrays( - arrays=[joints, values], names=["joints", "values"], mask=mask + arrays=[joints, values], names=["joints", "values"], mask=mask, ).drop_null() class TorqueMode(enum.Enum): + """Enumeration for servo torque control modes.""" + ENABLED = pa.scalar(1, pa.uint32()) DISABLED = pa.scalar(0, pa.uint32()) class OperatingMode(enum.Enum): + """Enumeration for servo operating modes.""" + VELOCITY = pa.scalar(1, pa.uint32()) POSITION = pa.scalar(3, pa.uint32()) EXTENDED_POSITION = pa.scalar(4, pa.uint32()) @@ -152,8 +161,17 @@ MODEL_CONTROL_TABLE = { class DynamixelBus: + """Class for managing communication with Dynamixel servos on a serial bus.""" def __init__(self, port: str, description: dict[str, (int, str)]): + """Initialize the Dynamixel bus connection. + + Args: + port: The serial port to connect to the Dynamixel bus. + description: A dictionary containing the description of the motors connected to the bus. + The keys are the motor names and the values are tuples containing the motor id + and the motor model. + """ self.port = port self.descriptions = description self.motor_ctrl = {} @@ -184,9 +202,16 @@ class DynamixelBus: self.group_writers = {} def close(self): + """Close the serial port connection.""" self.port_handler.closePort() def write(self, data_name: str, data: pa.StructArray): + """Write data to the specified servo parameters. + + Args: + data_name: Name of the parameter to write. + data: Structured array containing the data to write. + """ motor_ids = [ self.motor_ctrl[motor_name.as_py()]["id"] for motor_name in data.field("joints") @@ -239,7 +264,7 @@ class DynamixelBus: else: raise NotImplementedError( f"Value of the number of bytes to be sent is expected to be in [1, 2, 4], but {packet_bytes_size} " - f"is provided instead." + f"is provided instead.", ) if init_group: @@ -251,10 +276,19 @@ class DynamixelBus: if comm != COMM_SUCCESS: raise ConnectionError( f"Write failed due to communication error on port {self.port} for group_key {group_key}: " - f"{self.packet_handler.getTxRxResult(comm)}" + f"{self.packet_handler.getTxRxResult(comm)}", ) def read(self, data_name: str, motor_names: pa.Array) -> pa.StructArray: + """Read data from the specified servo parameters. + + Args: + data_name: Name of the parameter to read. + motor_names: Array of motor names to read from. + + Returns: + Structured array containing the read data. + """ motor_ids = [ self.motor_ctrl[motor_name.as_py()]["id"] for motor_name in motor_names ] @@ -281,13 +315,13 @@ class DynamixelBus: if comm != COMM_SUCCESS: raise ConnectionError( f"Read failed due to communication error on port {self.port} for group_key {group_key}: " - f"{self.packet_handler.getTxRxResult(comm)}" + f"{self.packet_handler.getTxRxResult(comm)}", ) values = pa.array( [ self.group_readers[group_key].getData( - idx, packet_address, packet_bytes_size + idx, packet_address, packet_bytes_size, ) for idx in motor_ids ], @@ -298,31 +332,90 @@ class DynamixelBus: return wrap_joints_and_values(motor_names, values) def write_torque_enable(self, torque_mode: pa.StructArray): + """Enable or disable torque for the specified servos. + + Args: + torque_mode: Structured array containing the torque mode for each servo. + """ self.write("Torque_Enable", torque_mode) def write_operating_mode(self, operating_mode: pa.StructArray): + """Set the operating mode for the specified servos. + + Args: + operating_mode: Structured array containing the operating mode for each servo. + """ self.write("Operating_Mode", operating_mode) def read_position(self, motor_names: pa.Array) -> pa.StructArray: + """Read the current position of the specified servos. + + Args: + motor_names: Array of motor names to read positions from. + + Returns: + Structured array containing the current positions. + """ return self.read("Present_Position", motor_names) def read_velocity(self, motor_names: pa.Array) -> pa.StructArray: + """Read the current velocity of the specified servos. + + Args: + motor_names: Array of motor names to read velocities from. + + Returns: + Structured array containing the current velocities. + """ return self.read("Present_Velocity", motor_names) def read_current(self, motor_names: pa.Array) -> pa.StructArray: + """Read the current current of the specified servos. + + Args: + motor_names: Array of motor names to read currents from. + + Returns: + Structured array containing the current currents. + """ return self.read("Present_Current", motor_names) def write_goal_position(self, goal_position: pa.StructArray): + """Set the goal position for the specified servos. + + Args: + goal_position: Structured array containing the goal positions. + """ self.write("Goal_Position", goal_position) def write_goal_current(self, goal_current: pa.StructArray): + """Set the goal current for the specified servos. + + Args: + goal_current: Structured array containing the goal currents. + """ self.write("Goal_Current", goal_current) def write_position_p_gain(self, position_p_gain: pa.StructArray): + """Set the position P gain for the specified servos. + + Args: + position_p_gain: Structured array containing the position P gains. + """ self.write("Position_P_Gain", position_p_gain) def write_position_i_gain(self, position_i_gain: pa.StructArray): + """Set the position I gain for the specified servos. + + Args: + position_i_gain: Structured array containing the position I gains. + """ self.write("Position_I_Gain", position_i_gain) def write_position_d_gain(self, position_d_gain: pa.StructArray): + """Set the position D gain for the specified servos. + + Args: + position_d_gain: Structured array containing the position D gains. + """ self.write("Position_D_Gain", position_d_gain) diff --git a/examples/alexk-lcr/configure.py b/examples/alexk-lcr/configure.py index 723a8401..dd72bd58 100644 --- a/examples/alexk-lcr/configure.py +++ b/examples/alexk-lcr/configure.py @@ -1,5 +1,4 @@ -""" -LCR Configuration Tool: This program is used to automatically configure the Low Cost Robot (LCR) for the user. +"""LCR Configuration Tool: This program is used to automatically configure the Low Cost Robot (LCR) for the user. The program will: 1. Disable all torque motors of provided LCR. @@ -14,21 +13,17 @@ It will also enable all appropriate operating modes for the LCR. """ import argparse -import time import json +import time import pyarrow as pa - -from bus import DynamixelBus, TorqueMode, OperatingMode - -from pwm_position_control.transform import pwm_to_logical_arrow, wrap_joints_and_values - +from bus import DynamixelBus, OperatingMode, TorqueMode +from pwm_position_control.functions import construct_control_table from pwm_position_control.tables import ( construct_logical_to_pwm_conversion_table_arrow, construct_pwm_to_logical_conversion_table_arrow, ) - -from pwm_position_control.functions import construct_control_table +from pwm_position_control.transform import pwm_to_logical_arrow, wrap_joints_and_values FULL_ARM = pa.array( [ @@ -56,26 +51,26 @@ def pause(): def configure_servos(bus: DynamixelBus): bus.write_torque_enable( - wrap_joints_and_values(FULL_ARM, [TorqueMode.DISABLED.value] * 6) + wrap_joints_and_values(FULL_ARM, [TorqueMode.DISABLED.value] * 6), ) bus.write_operating_mode( wrap_joints_and_values( - ARM_WITHOUT_GRIPPER, [OperatingMode.EXTENDED_POSITION.value] * 5 - ) + ARM_WITHOUT_GRIPPER, [OperatingMode.EXTENDED_POSITION.value] * 5, + ), ) bus.write_operating_mode( wrap_joints_and_values( - GRIPPER, [OperatingMode.CURRENT_CONTROLLED_POSITION.value] - ) + GRIPPER, [OperatingMode.CURRENT_CONTROLLED_POSITION.value], + ), ) def main(): parser = argparse.ArgumentParser( description="LCR Auto Configure: This program is used to automatically configure the Low Cost Robot (LCR) for " - "the user." + "the user.", ) parser.add_argument("--port", type=str, required=True, help="The port of the LCR.") @@ -95,7 +90,7 @@ def main(): help="If the LCR is the follower of the user.", ) parser.add_argument( - "--leader", action="store_true", help="If the LCR is the leader of the user." + "--leader", action="store_true", help="If the LCR is the leader of the user.", ) args = parser.parse_args() @@ -138,10 +133,10 @@ def main(): pwm_positions = (pwm_position_1, pwm_position_2) pwm_to_logical_conversion_table = construct_pwm_to_logical_conversion_table_arrow( - pwm_positions, targets + pwm_positions, targets, ) logical_to_pwm_conversion_table = construct_logical_to_pwm_conversion_table_arrow( - pwm_positions, targets + pwm_positions, targets, ) control_table_json = {} @@ -180,7 +175,7 @@ def main(): path = ( input( - f"Please enter the path of the configuration file (default is ./examples/alexk-lcr/configs/{leader}.{left}.json): " + f"Please enter the path of the configuration file (default is ./examples/alexk-lcr/configs/{leader}.{left}.json): ", ) or f"./examples/alexk-lcr/configs/{leader}.{left}.json" ) @@ -189,21 +184,21 @@ def main(): json.dump(control_table_json, file) control_table = construct_control_table( - pwm_to_logical_conversion_table, logical_to_pwm_conversion_table + pwm_to_logical_conversion_table, logical_to_pwm_conversion_table, ) while True: try: pwm_position = arm.read_position(FULL_ARM) logical_position = pwm_to_logical_arrow( - pwm_position, control_table, ranged=True + pwm_position, control_table, ranged=True, ).field("values") print(f"Logical Position: {logical_position}") except ConnectionError: print( - "Connection error occurred. Please check the connection and try again." + "Connection error occurred. Please check the connection and try again.", ) time.sleep(0.5) diff --git a/examples/alexk-lcr/nodes/interpolate_lcr_to_lcr.py b/examples/alexk-lcr/nodes/interpolate_lcr_to_lcr.py index 9f9abc33..c3c42fb3 100644 --- a/examples/alexk-lcr/nodes/interpolate_lcr_to_lcr.py +++ b/examples/alexk-lcr/nodes/interpolate_lcr_to_lcr.py @@ -1,24 +1,22 @@ -import os import argparse import json +import os import pyarrow as pa import pyarrow.compute as pc - from dora import Node - +from pwm_position_control.load import load_control_table_from_json_conversion_tables from pwm_position_control.transform import ( - wrap_joints_and_values, - pwm_to_logical_arrow, logical_to_pwm_with_offset_arrow, + pwm_to_logical_arrow, + wrap_joints_and_values, ) -from pwm_position_control.load import load_control_table_from_json_conversion_tables def main(): parser = argparse.ArgumentParser( description="Interpolation LCR Node: This Dora node is used to calculates appropriate goal positions for the " - "LCR followers knowing a Leader position and Follower position." + "LCR followers knowing a Leader position and Follower position.", ) parser.add_argument( @@ -46,19 +44,19 @@ def main(): if not os.environ.get("LEADER_CONTROL") and args.leader_control is None: raise ValueError( "The leader control is not set. Please set the configuration of the leader in the environment variables or " - "as an argument." + "as an argument.", ) if not os.environ.get("FOLLOWER_CONTROL") and args.follower_control is None: raise ValueError( "The follower control is not set. Please set the configuration of the follower in the environment " - "variables or as an argument." + "variables or as an argument.", ) with open( os.environ.get("LEADER_CONTROL") if args.leader_control is None - else args.leader_control + else args.leader_control, ) as file: leader_control = json.load(file) load_control_table_from_json_conversion_tables(leader_control, leader_control) @@ -66,11 +64,11 @@ def main(): with open( os.environ.get("FOLLOWER_CONTROL") if args.follower_control is None - else args.follower_control + else args.follower_control, ) as file: follower_control = json.load(file) load_control_table_from_json_conversion_tables( - follower_control, follower_control + follower_control, follower_control, ) initial_mask = [ @@ -130,7 +128,7 @@ def main(): ) pwm_goal = logical_to_pwm_with_offset_arrow( - follower_position, logical_goal, follower_control + follower_position, logical_goal, follower_control, ) node.send_output("follower_goal", pwm_goal, event["metadata"]) diff --git a/examples/alexk-lcr/nodes/interpolate_lcr_to_record.py b/examples/alexk-lcr/nodes/interpolate_lcr_to_record.py index ce3d43d9..c04022f8 100644 --- a/examples/alexk-lcr/nodes/interpolate_lcr_to_record.py +++ b/examples/alexk-lcr/nodes/interpolate_lcr_to_record.py @@ -1,23 +1,21 @@ -import os import argparse import json +import os import pyarrow as pa import pyarrow.compute as pc - from dora import Node - from pwm_position_control.load import load_control_table_from_json_conversion_tables from pwm_position_control.transform import ( - wrap_joints_and_values, pwm_to_logical_arrow, + wrap_joints_and_values, ) def main(): parser = argparse.ArgumentParser( description="Interpolation LCR Node: This Dora node is used to calculates appropriate goal positions for the " - "LCR followers knowing a Leader position and Follower position." + "LCR followers knowing a Leader position and Follower position.", ) parser.add_argument( @@ -45,19 +43,19 @@ def main(): if not os.environ.get("LEADER_CONTROL") and args.leader_control is None: raise ValueError( "The leader control is not set. Please set the configuration of the leader in the environment variables or " - "as an argument." + "as an argument.", ) if not os.environ.get("FOLLOWER_CONTROL") and args.follower_control is None: raise ValueError( "The follower control is not set. Please set the configuration of the follower in the environment " - "variables or as an argument." + "variables or as an argument.", ) with open( os.environ.get("LEADER_CONTROL") if args.leader_control is None - else args.leader_control + else args.leader_control, ) as file: leader_control = json.load(file) load_control_table_from_json_conversion_tables(leader_control, leader_control) @@ -65,11 +63,11 @@ def main(): with open( os.environ.get("FOLLOWER_CONTROL") if args.follower_control is None - else args.follower_control + else args.follower_control, ) as file: follower_control = json.load(file) load_control_table_from_json_conversion_tables( - follower_control, follower_control + follower_control, follower_control, ) node = Node(args.name) @@ -98,11 +96,11 @@ def main(): follower_position = event["value"] follower_position = pwm_to_logical_arrow( - follower_position, follower_control + follower_position, follower_control, ) node.send_output( - "logical_position", follower_position, event["metadata"] + "logical_position", follower_position, event["metadata"], ) elif event_type == "ERROR": diff --git a/examples/alexk-lcr/nodes/interpolate_lcr_to_simu_lcr.py b/examples/alexk-lcr/nodes/interpolate_lcr_to_simu_lcr.py index e0e2d396..925af277 100644 --- a/examples/alexk-lcr/nodes/interpolate_lcr_to_simu_lcr.py +++ b/examples/alexk-lcr/nodes/interpolate_lcr_to_simu_lcr.py @@ -1,25 +1,23 @@ -import os import argparse import json +import os import numpy as np import pyarrow as pa import pyarrow.compute as pc - from dora import Node - from pwm_position_control.load import load_control_table_from_json_conversion_tables from pwm_position_control.transform import ( - wrap_joints_and_values, - pwm_to_logical_arrow, logical_to_pwm_with_offset_arrow, + pwm_to_logical_arrow, + wrap_joints_and_values, ) def main(): parser = argparse.ArgumentParser( description="Interpolation LCR Node: This Dora node is used to calculates appropriate goal positions for the " - "LCR followers knowing a Leader position and Follower position." + "LCR followers knowing a Leader position and Follower position.", ) parser.add_argument( @@ -41,13 +39,13 @@ def main(): if not os.environ.get("LEADER_CONTROL") and args.leader_control is None: raise ValueError( "The leader control is not set. Please set the configuration of the leader in the environment variables or " - "as an argument." + "as an argument.", ) with open( os.environ.get("LEADER_CONTROL") if args.leader_control is None - else args.leader_control + else args.leader_control, ) as file: leader_control = json.load(file) load_control_table_from_json_conversion_tables(leader_control, leader_control) @@ -114,7 +112,7 @@ def main(): [ joint.as_py() + "_joint" for joint in leader_position.field("joints") - ] + ], ), pc.multiply( pc.add(leader_position.field("values"), interpolation_a), diff --git a/examples/alexk-lcr/nodes/interpolate_replay_to_lcr.py b/examples/alexk-lcr/nodes/interpolate_replay_to_lcr.py index 53024c35..b4ee763b 100644 --- a/examples/alexk-lcr/nodes/interpolate_replay_to_lcr.py +++ b/examples/alexk-lcr/nodes/interpolate_replay_to_lcr.py @@ -1,9 +1,8 @@ -import os import argparse import json +import os from dora import Node - from pwm_position_control.load import load_control_table_from_json_conversion_tables from pwm_position_control.transform import logical_to_pwm_with_offset_arrow @@ -11,7 +10,7 @@ from pwm_position_control.transform import logical_to_pwm_with_offset_arrow def main(): parser = argparse.ArgumentParser( description="Interpolation LCR Node: This Dora node is used to calculates appropriate goal positions for the " - "LCR followers knowing a Leader position and Follower position." + "LCR followers knowing a Leader position and Follower position.", ) parser.add_argument( @@ -33,17 +32,17 @@ def main(): if not os.environ.get("FOLLOWER_CONTROL") and args.follower_control is None: raise ValueError( "The follower control is not set. Please set the configuration of the follower in the environment " - "variables or as an argument." + "variables or as an argument.", ) with open( os.environ.get("FOLLOWER_CONTROL") if args.follower_control is None - else args.follower_control + else args.follower_control, ) as file: follower_control = json.load(file) load_control_table_from_json_conversion_tables( - follower_control, follower_control + follower_control, follower_control, ) node = Node(args.name) @@ -65,7 +64,7 @@ def main(): continue physical_goal = logical_to_pwm_with_offset_arrow( - follower_position, leader_position, follower_control + follower_position, leader_position, follower_control, ) node.send_output("follower_goal", physical_goal, event["metadata"]) diff --git a/examples/aloha/benchmark/python/dynamixel.py b/examples/aloha/benchmark/python/dynamixel.py index 636522b6..fefa28f8 100644 --- a/examples/aloha/benchmark/python/dynamixel.py +++ b/examples/aloha/benchmark/python/dynamixel.py @@ -1,10 +1,12 @@ from __future__ import annotations + +import enum import math import os -from dynamixel_sdk import * # Uses Dynamixel SDK library -from dataclasses import dataclass -import enum import time +from dataclasses import dataclass + +from dynamixel_sdk import * # Uses Dynamixel SDK library class ReadAttribute(enum.Enum): @@ -87,7 +89,7 @@ class Dynamixel: # self._enable_torque(motor_id) dxl_comm_result, dxl_error = self.packetHandler.write4ByteTxRx( - self.portHandler, motor_id, self.ADDR_GOAL_POSITION, goal_position + self.portHandler, motor_id, self.ADDR_GOAL_POSITION, goal_position, ) # self._process_response(dxl_comm_result, dxl_error) # print(f'set position of motor {motor_id} to {goal_position}') @@ -101,24 +103,23 @@ class Dynamixel: self._enable_torque(motor_id) # print(f'enabling torque') dxl_comm_result, dxl_error = self.packetHandler.write2ByteTxRx( - self.portHandler, motor_id, self.ADDR_GOAL_PWM, pwm_value + self.portHandler, motor_id, self.ADDR_GOAL_PWM, pwm_value, ) # self._process_response(dxl_comm_result, dxl_error) # print(f'set pwm of motor {motor_id} to {pwm_value}') if dxl_comm_result != COMM_SUCCESS: if tries <= 1: raise ConnectionError( - f"dxl_comm_result: {self.packetHandler.getTxRxResult(dxl_comm_result)}" - ) - else: - print( - f"dynamixel pwm setting failure trying again with {tries - 1} tries" + f"dxl_comm_result: {self.packetHandler.getTxRxResult(dxl_comm_result)}", ) - self.set_pwm_value(motor_id, pwm_value, tries=tries - 1) + print( + f"dynamixel pwm setting failure trying again with {tries - 1} tries", + ) + self.set_pwm_value(motor_id, pwm_value, tries=tries - 1) elif dxl_error != 0: print(f"dxl error {dxl_error}") raise ConnectionError( - f"dynamixel error: {self.packetHandler.getTxRxResult(dxl_error)}" + f"dynamixel error: {self.packetHandler.getTxRxResult(dxl_error)}", ) def read_temperature(self, motor_id: int): @@ -157,8 +158,7 @@ class Dynamixel: return self._read_value(motor_id, ReadAttribute.HARDWARE_ERROR_STATUS, 1) def set_id(self, old_id, new_id, use_broadcast_id: bool = False): - """ - sets the id of the dynamixel servo + """Sets the id of the dynamixel servo @param old_id: current id of the servo @param new_id: new id @param use_broadcast_id: set ids of all connected dynamixels if True. @@ -170,21 +170,21 @@ class Dynamixel: else: current_id = old_id dxl_comm_result, dxl_error = self.packetHandler.write1ByteTxRx( - self.portHandler, current_id, self.ADDR_ID, new_id + self.portHandler, current_id, self.ADDR_ID, new_id, ) self._process_response(dxl_comm_result, dxl_error, old_id) self.config.id = id def _enable_torque(self, motor_id): dxl_comm_result, dxl_error = self.packetHandler.write1ByteTxRx( - self.portHandler, motor_id, self.ADDR_TORQUE_ENABLE, 1 + self.portHandler, motor_id, self.ADDR_TORQUE_ENABLE, 1, ) self._process_response(dxl_comm_result, dxl_error, motor_id) self.torque_enabled[motor_id] = True def _disable_torque(self, motor_id): dxl_comm_result, dxl_error = self.packetHandler.write1ByteTxRx( - self.portHandler, motor_id, self.ADDR_TORQUE_ENABLE, 0 + self.portHandler, motor_id, self.ADDR_TORQUE_ENABLE, 0, ) self._process_response(dxl_comm_result, dxl_error, motor_id) self.torque_enabled[motor_id] = False @@ -192,42 +192,42 @@ class Dynamixel: def _process_response(self, dxl_comm_result: int, dxl_error: int, motor_id: int): if dxl_comm_result != COMM_SUCCESS: raise ConnectionError( - f"dxl_comm_result for motor {motor_id}: {self.packetHandler.getTxRxResult(dxl_comm_result)}" + f"dxl_comm_result for motor {motor_id}: {self.packetHandler.getTxRxResult(dxl_comm_result)}", ) - elif dxl_error != 0: + if dxl_error != 0: print(f"dxl error {dxl_error}") raise ConnectionError( - f"dynamixel error for motor {motor_id}: {self.packetHandler.getTxRxResult(dxl_error)}" + f"dynamixel error for motor {motor_id}: {self.packetHandler.getTxRxResult(dxl_error)}", ) def set_operating_mode(self, motor_id: int, operating_mode: OperatingMode): dxl_comm_result, dxl_error = self.packetHandler.write2ByteTxRx( - self.portHandler, motor_id, self.OPERATING_MODE_ADDR, operating_mode.value + self.portHandler, motor_id, self.OPERATING_MODE_ADDR, operating_mode.value, ) self._process_response(dxl_comm_result, dxl_error, motor_id) self.operating_modes[motor_id] = operating_mode def set_pwm_limit(self, motor_id: int, limit: int): dxl_comm_result, dxl_error = self.packetHandler.write2ByteTxRx( - self.portHandler, motor_id, 36, limit + self.portHandler, motor_id, 36, limit, ) self._process_response(dxl_comm_result, dxl_error, motor_id) def set_velocity_limit(self, motor_id: int, velocity_limit): dxl_comm_result, dxl_error = self.packetHandler.write4ByteTxRx( - self.portHandler, motor_id, self.ADDR_VELOCITY_LIMIT, velocity_limit + self.portHandler, motor_id, self.ADDR_VELOCITY_LIMIT, velocity_limit, ) self._process_response(dxl_comm_result, dxl_error, motor_id) def set_P(self, motor_id: int, P: int): dxl_comm_result, dxl_error = self.packetHandler.write2ByteTxRx( - self.portHandler, motor_id, self.POSITION_P, P + self.portHandler, motor_id, self.POSITION_P, P, ) self._process_response(dxl_comm_result, dxl_error, motor_id) def set_I(self, motor_id: int, I: int): dxl_comm_result, dxl_error = self.packetHandler.write2ByteTxRx( - self.portHandler, motor_id, self.POSITION_I, I + self.portHandler, motor_id, self.POSITION_I, I, ) self._process_response(dxl_comm_result, dxl_error, motor_id) @@ -243,7 +243,7 @@ class Dynamixel: def set_home_offset(self, motor_id: int, home_position: int): self._disable_torque(motor_id) dxl_comm_result, dxl_error = self.packetHandler.write4ByteTxRx( - self.portHandler, motor_id, ReadAttribute.HOMING_OFFSET.value, home_position + self.portHandler, motor_id, ReadAttribute.HOMING_OFFSET.value, home_position, ) self._process_response(dxl_comm_result, dxl_error, motor_id) self._enable_torque(motor_id) @@ -265,7 +265,7 @@ class Dynamixel: self._disable_torque(motor_id) dxl_comm_result, dxl_error = self.packetHandler.write1ByteTxRx( - self.portHandler, motor_id, ReadAttribute.BAUDRATE.value, baudrate_id + self.portHandler, motor_id, ReadAttribute.BAUDRATE.value, baudrate_id, ) self._process_response(dxl_comm_result, dxl_error, motor_id) @@ -273,43 +273,40 @@ class Dynamixel: try: if num_bytes == 1: value, dxl_comm_result, dxl_error = self.packetHandler.read1ByteTxRx( - self.portHandler, motor_id, attribute.value + self.portHandler, motor_id, attribute.value, ) elif num_bytes == 2: value, dxl_comm_result, dxl_error = self.packetHandler.read2ByteTxRx( - self.portHandler, motor_id, attribute.value + self.portHandler, motor_id, attribute.value, ) elif num_bytes == 4: value, dxl_comm_result, dxl_error = self.packetHandler.read4ByteTxRx( - self.portHandler, motor_id, attribute.value + self.portHandler, motor_id, attribute.value, ) except Exception: if tries == 0: raise Exception - else: - return self._read_value(motor_id, attribute, num_bytes, tries=tries - 1) + return self._read_value(motor_id, attribute, num_bytes, tries=tries - 1) if dxl_comm_result != COMM_SUCCESS: if tries <= 1: # print("%s" % self.packetHandler.getTxRxResult(dxl_comm_result)) raise ConnectionError( - f"dxl_comm_result {dxl_comm_result} for servo {motor_id} value {value}" - ) - else: - print( - f"dynamixel read failure for servo {motor_id} trying again with {tries - 1} tries" + f"dxl_comm_result {dxl_comm_result} for servo {motor_id} value {value}", ) - time.sleep(0.02) - return self._read_value(motor_id, attribute, num_bytes, tries=tries - 1) - elif ( + print( + f"dynamixel read failure for servo {motor_id} trying again with {tries - 1} tries", + ) + time.sleep(0.02) + return self._read_value(motor_id, attribute, num_bytes, tries=tries - 1) + if ( dxl_error != 0 ): # # print("%s" % self.packetHandler.getRxPacketError(dxl_error)) # raise ConnectionError(f'dxl_error {dxl_error} binary ' + "{0:b}".format(37)) if tries == 0 and dxl_error != 128: raise Exception( - f"Failed to read value from motor {motor_id} error is {dxl_error}" + f"Failed to read value from motor {motor_id} error is {dxl_error}", ) - else: - return self._read_value(motor_id, attribute, num_bytes, tries=tries - 1) + return self._read_value(motor_id, attribute, num_bytes, tries=tries - 1) return value def set_home_position(self, motor_id: int): diff --git a/examples/aloha/benchmark/python/robot.py b/examples/aloha/benchmark/python/robot.py index b57ff7b7..b2c1b0d6 100644 --- a/examples/aloha/benchmark/python/robot.py +++ b/examples/aloha/benchmark/python/robot.py @@ -1,16 +1,17 @@ -import numpy as np -from dynamixel import Dynamixel, OperatingMode, ReadAttribute import time +from enum import Enum, auto +from typing import Union + +import numpy as np +from dynamixel import OperatingMode, ReadAttribute from dynamixel_sdk import ( - GroupSyncRead, - GroupSyncWrite, - DXL_LOBYTE, DXL_HIBYTE, - DXL_LOWORD, DXL_HIWORD, + DXL_LOBYTE, + DXL_LOWORD, + GroupSyncRead, + GroupSyncWrite, ) -from enum import Enum, auto -from typing import Union class MotorControlType(Enum): @@ -65,8 +66,7 @@ class Robot: self.motor_control_state = MotorControlType.DISABLED def read_position(self, tries=2): - """ - Reads the joint positions of the robot. 2048 is the center position. 0 and 4096 are 180 degrees in each direction. + """Reads the joint positions of the robot. 2048 is the center position. 0 and 4096 are 180 degrees in each direction. :param tries: maximum number of tries to read the position :return: list of joint positions in range [0, 4096] """ @@ -74,8 +74,7 @@ class Robot: if result != 0: if tries > 0: return self.read_position(tries=tries - 1) - else: - print(f"failed to read position!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") + print("failed to read position!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") positions = [] for id in self.servo_ids: position = self.position_reader.getData(id, ReadAttribute.POSITION.value, 4) @@ -85,8 +84,7 @@ class Robot: return positions def read_velocity(self): - """ - Reads the joint velocities of the robot. + """Reads the joint velocities of the robot. :return: list of joint velocities, """ self.velocity_reader.txRxPacket() @@ -99,11 +97,9 @@ class Robot: return velocties def set_goal_pos(self, action): + """:param action: list or numpy array of target joint positions in range [0, 4096] """ - - :param action: list or numpy array of target joint positions in range [0, 4096] - """ - if not self.motor_control_state is MotorControlType.POSITION_CONTROL: + if self.motor_control_state is not MotorControlType.POSITION_CONTROL: self._set_position_control() for i, motor_id in enumerate(self.servo_ids): data_write = [ @@ -117,11 +113,10 @@ class Robot: self.pos_writer.txPacket() def set_pwm(self, action): - """ - Sets the pwm values for the servos. + """Sets the pwm values for the servos. :param action: list or numpy array of pwm values in range [0, 885] """ - if not self.motor_control_state is MotorControlType.PWM: + if self.motor_control_state is not MotorControlType.PWM: self._set_pwm_control() for i, motor_id in enumerate(self.servo_ids): data_write = [ @@ -133,15 +128,13 @@ class Robot: self.pwm_writer.txPacket() def set_trigger_torque(self): - """ - Sets a constant torque torque for the last servo in the chain. This is useful for the trigger of the leader arm + """Sets a constant torque torque for the last servo in the chain. This is useful for the trigger of the leader arm """ self.dynamixel._enable_torque(self.servo_ids[-1]) self.dynamixel.set_pwm_value(self.servo_ids[-1], 200) def limit_pwm(self, limit: Union[int, list, np.ndarray]): - """ - Limits the pwm values for the servos in for position control + """Limits the pwm values for the servos in for position control @param limit: 0 ~ 885 @return: """ diff --git a/examples/aloha/benchmark/python/teleoperate_real_robot.py b/examples/aloha/benchmark/python/teleoperate_real_robot.py index fb67bb16..74675656 100644 --- a/examples/aloha/benchmark/python/teleoperate_real_robot.py +++ b/examples/aloha/benchmark/python/teleoperate_real_robot.py @@ -1,11 +1,11 @@ -from robot import Robot from dynamixel import Dynamixel +from robot import Robot leader_dynamixel = Dynamixel.Config( - baudrate=1_000_000, device_name="/dev/ttyDXL_master_right" + baudrate=1_000_000, device_name="/dev/ttyDXL_master_right", ).instantiate() follower_dynamixel = Dynamixel.Config( - baudrate=1_000_000, device_name="/dev/ttyDXL_puppet_right" + baudrate=1_000_000, device_name="/dev/ttyDXL_puppet_right", ).instantiate() follower = Robot(follower_dynamixel, servo_ids=[1, 2, 3, 4, 5, 6, 7, 8]) leader = Robot(leader_dynamixel, servo_ids=[1, 2, 3, 4, 5, 6, 7, 8]) diff --git a/examples/aloha/benchmark/ros2/teleop.py b/examples/aloha/benchmark/ros2/teleop.py index b68939ae..dc127a67 100644 --- a/examples/aloha/benchmark/ros2/teleop.py +++ b/examples/aloha/benchmark/ros2/teleop.py @@ -1,8 +1,7 @@ import dora -from dora import Node -import pyarrow as pa import numpy as np - +import pyarrow as pa +from dora import Node ros2_context = dora.experimental.ros2_bridge.Ros2Context() ros2_node = ros2_context.new_node( @@ -13,7 +12,7 @@ ros2_node = ros2_context.new_node( # Define a ROS2 QOS topic_qos = dora.experimental.ros2_bridge.Ros2QosPolicies( - reliable=True, max_blocking_time=0.1 + reliable=True, max_blocking_time=0.1, ) # Create a publisher to cmd_vel topic @@ -22,7 +21,7 @@ puppet_arm_command = ros2_node.create_publisher( "/robot_model_puppet/commands/joint_group", "interbotix_xs_msgs/JointGroupCommand", topic_qos, - ) + ), ) gripper_command = ros2_node.create_publisher( @@ -30,13 +29,13 @@ gripper_command = ros2_node.create_publisher( "/robot_model_puppet/commands/joint_single", "interbotix_xs_msgs/JointSingleCommand", topic_qos, - ) + ), ) # Create a listener to pose topic master_state = ros2_node.create_subscription( ros2_node.create_topic( - "/robot_model_master/joint_states", "sensor_msgs/JointState", topic_qos - ) + "/robot_model_master/joint_states", "sensor_msgs/JointState", topic_qos, + ), ) # Create a dora node @@ -74,8 +73,8 @@ for event in dora_node: { "name": "gripper", "cmd": np.float32(values[6]), - } - ] + }, + ], ), ) puppet_arm_command.publish( @@ -84,7 +83,7 @@ for event in dora_node: { "name": "arm", "cmd": values[:6], - } - ] + }, + ], ), ) diff --git a/examples/aloha/nodes/gym_dora_node.py b/examples/aloha/nodes/gym_dora_node.py index 9cad666c..70af510d 100644 --- a/examples/aloha/nodes/gym_dora_node.py +++ b/examples/aloha/nodes/gym_dora_node.py @@ -1,12 +1,12 @@ -import gymnasium as gym +import time +from pathlib import Path import gym_dora # noqa: F401 +import gymnasium as gym import pandas as pd -import time -from pathlib import Path env = gym.make( - "gym_dora/DoraAloha-v0", disable_env_checker=True, max_episode_steps=10000 + "gym_dora/DoraAloha-v0", disable_env_checker=True, max_episode_steps=10000, ) observation = env.reset() @@ -49,8 +49,8 @@ class ReplayPolicy: policy = ReplayPolicy( Path( - "/home/rcadene/dora-aloha/aloha/graphs/out/018fa4ad-5942-7235-93d3-3efebe9b8a12" - ) + "/home/rcadene/dora-aloha/aloha/graphs/out/018fa4ad-5942-7235-93d3-3efebe9b8a12", + ), ) diff --git a/examples/aloha/nodes/keyboard_node.py b/examples/aloha/nodes/keyboard_node.py index 213ba448..32fee0dc 100644 --- a/examples/aloha/nodes/keyboard_node.py +++ b/examples/aloha/nodes/keyboard_node.py @@ -1,8 +1,7 @@ -from pynput import keyboard -from pynput.keyboard import Key, Events import pyarrow as pa from dora import Node - +from pynput import keyboard +from pynput.keyboard import Events, Key node = Node() buffer_text = "" @@ -17,7 +16,7 @@ with keyboard.Events() as events: cursor += 1 node.send_output("space", pa.array([cursor])) space = True - + elif event is not None and isinstance(event, Events.Release): if event.key == Key.space: @@ -25,7 +24,7 @@ with keyboard.Events() as events: space = False elif event.key == Key.backspace: node.send_output("failed", pa.array([cursor])) - + if node.next(0.001) is None: break diff --git a/examples/aloha/nodes/lerobot_webcam_saver.py b/examples/aloha/nodes/lerobot_webcam_saver.py index 864b47f0..840a39fe 100644 --- a/examples/aloha/nodes/lerobot_webcam_saver.py +++ b/examples/aloha/nodes/lerobot_webcam_saver.py @@ -1,14 +1,12 @@ #!/usr/bin/env python3 -# -*- coding: utf-8 -*- import os -import time -import numpy as np +import subprocess +from pathlib import Path + import cv2 import pyarrow as pa -from pathlib import Path from dora import Node -import subprocess node = Node() @@ -40,12 +38,12 @@ for event in node: f"ffmpeg -r {FPS} " "-f image2 " "-loglevel error " - f"-i {str(out_dir / 'frame_%06d.png')} " + f"-i {out_dir / 'frame_%06d.png'!s} " "-vcodec libx264 " "-g 2 " "-pix_fmt yuv444p " - f"{str(video_path)} &&" - f"rm -r {str(out_dir)}" + f"{video_path!s} &&" + f"rm -r {out_dir!s}" ) print(ffmpeg_cmd, flush=True) subprocess.Popen([ffmpeg_cmd], start_new_session=True, shell=True) diff --git a/examples/aloha/nodes/llm_op.py b/examples/aloha/nodes/llm_op.py index acaea635..07797349 100644 --- a/examples/aloha/nodes/llm_op.py +++ b/examples/aloha/nodes/llm_op.py @@ -1,14 +1,14 @@ -from dora import DoraStatus -import pylcs -import os -import pyarrow as pa -from transformers import AutoModelForCausalLM, AutoTokenizer -import torch - import gc # garbage collect library +import os import re import time +import pyarrow as pa +import pylcs +import torch +from dora import DoraStatus +from transformers import AutoModelForCausalLM, AutoTokenizer + CHATGPT = False MODEL_NAME_OR_PATH = "TheBloke/deepseek-coder-6.7B-instruct-GPTQ" @@ -39,14 +39,16 @@ tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME_OR_PATH, use_fast=True) def extract_python_code_blocks(text): - """ - Extracts Python code blocks from the given text that are enclosed in triple backticks with a python language identifier. + """Extracts Python code blocks from the given text that are enclosed in triple backticks with a python language identifier. - Parameters: + Parameters + ---------- - text: A string that may contain one or more Python code blocks. - Returns: + Returns + ------- - A list of strings, where each string is a block of Python code extracted from the text. + """ pattern = r"```python\n(.*?)\n```" matches = re.findall(pattern, text, re.DOTALL) @@ -55,21 +57,22 @@ def extract_python_code_blocks(text): matches = re.findall(pattern, text, re.DOTALL) if len(matches) == 0: return [text] - else: - matches = [remove_last_line(matches[0])] + matches = [remove_last_line(matches[0])] return matches def remove_last_line(python_code): - """ - Removes the last line from a given string of Python code. + """Removes the last line from a given string of Python code. - Parameters: + Parameters + ---------- - python_code: A string representing Python source code. - Returns: + Returns + ------- - A string with the last line removed. + """ lines = python_code.split("\n") # Split the string into lines if lines: # Check if there are any lines to remove @@ -78,8 +81,7 @@ def remove_last_line(python_code): def calculate_similarity(source, target): - """ - Calculate a similarity score between the source and target strings. + """Calculate a similarity score between the source and target strings. This uses the edit distance relative to the length of the strings. """ edit_distance = pylcs.edit_distance(source, target) @@ -90,8 +92,7 @@ def calculate_similarity(source, target): def find_best_match_location(source_code, target_block): - """ - Find the best match for the target_block within the source_code by searching line by line, + """Find the best match for the target_block within the source_code by searching line by line, considering blocks of varying lengths. """ source_lines = source_code.split("\n") @@ -121,8 +122,7 @@ def find_best_match_location(source_code, target_block): def replace_code_in_source(source_code, replacement_block: str): - """ - Replace the best matching block in the source_code with the replacement_block, considering variable block lengths. + """Replace the best matching block in the source_code with the replacement_block, considering variable block lengths. """ replacement_block = extract_python_code_blocks(replacement_block)[0] start_index, end_index = find_best_match_location(source_code, replacement_block) @@ -132,8 +132,7 @@ def replace_code_in_source(source_code, replacement_block: str): source_code[:start_index] + replacement_block + source_code[end_index:] ) return new_source - else: - return source_code + return source_code class Operator: @@ -155,14 +154,14 @@ class Operator: current_directory = os.path.dirname(current_file_path) path = current_directory + "/policy.py" - with open(path, "r", encoding="utf8") as f: + with open(path, encoding="utf8") as f: code = f.read() user_message = input start_llm = time.time() output = self.ask_llm( - CODE_MODIFIER_TEMPLATE.format(code=code, user_message=user_message) + CODE_MODIFIER_TEMPLATE.format(code=code, user_message=user_message), ) source_code = replace_code_in_source(code, output) @@ -213,7 +212,7 @@ if __name__ == "__main__": current_directory = os.path.dirname(current_file_path) path = current_directory + "/policy.py" - with open(path, "r", encoding="utf8") as f: + with open(path, encoding="utf8") as f: raw = f.read() op.on_event( @@ -226,7 +225,7 @@ if __name__ == "__main__": "path": path, "user_message": "When I say suit up, get the hat and the get the food.", }, - ] + ], ), "metadata": [], }, diff --git a/examples/aloha/nodes/plot_node.py b/examples/aloha/nodes/plot_node.py index 55fc641c..cfb482d9 100644 --- a/examples/aloha/nodes/plot_node.py +++ b/examples/aloha/nodes/plot_node.py @@ -1,8 +1,8 @@ import os + import cv2 from dora import Node - IMAGE_WIDTH = int(os.getenv("IMAGE_WIDTH", "1280")) IMAGE_HEIGHT = int(os.getenv("IMAGE_HEIGHT", "720")) FONT = cv2.FONT_HERSHEY_SIMPLEX diff --git a/examples/aloha/nodes/policy.py b/examples/aloha/nodes/policy.py index 1de183dc..3825c987 100644 --- a/examples/aloha/nodes/policy.py +++ b/examples/aloha/nodes/policy.py @@ -1,4 +1,3 @@ -import pyarrow as pa from dora import DoraStatus diff --git a/examples/aloha/nodes/realsense_node.py b/examples/aloha/nodes/realsense_node.py index ef5be285..0d8998d8 100644 --- a/examples/aloha/nodes/realsense_node.py +++ b/examples/aloha/nodes/realsense_node.py @@ -1,9 +1,10 @@ -import pyrealsense2 as rs -import numpy as np -from dora import Node -import pyarrow as pa import os + import cv2 +import numpy as np +import pyarrow as pa +import pyrealsense2 as rs +from dora import Node IMAGE_WIDTH = int(os.getenv("IMAGE_WIDTH", "640")) IMAGE_HEIGHT = int(os.getenv("IMAGE_HEIGHT", "480")) diff --git a/examples/aloha/nodes/replay.py b/examples/aloha/nodes/replay.py index de485cf6..755403e1 100644 --- a/examples/aloha/nodes/replay.py +++ b/examples/aloha/nodes/replay.py @@ -1,8 +1,8 @@ -from dora import Node -import pandas as pd -import pyarrow as pa import time +import pandas as pd +import pyarrow as pa +from dora import Node TOPIC = "puppet_goal_position" diff --git a/examples/aloha/nodes/webcam.py b/examples/aloha/nodes/webcam.py index 2d4806ab..219099f5 100644 --- a/examples/aloha/nodes/webcam.py +++ b/examples/aloha/nodes/webcam.py @@ -1,12 +1,10 @@ #!/usr/bin/env python3 -# -*- coding: utf-8 -*- import os -import time -import numpy as np + import cv2 +import numpy as np import pyarrow as pa - from dora import Node node = Node() @@ -26,8 +24,8 @@ for event in node: frame = np.zeros((CAMERA_HEIGHT, CAMERA_WIDTH, 3), dtype=np.uint8) cv2.putText( frame, - "No Webcam was found at index %d" % (CAMERA_ID), - (int(30), int(30)), + f"No Webcam was found at index {CAMERA_ID}", + (30, 30), font, 0.75, (255, 255, 255), diff --git a/examples/aloha/nodes/whisper_node.py b/examples/aloha/nodes/whisper_node.py index 903f5cb5..bf3ad1fe 100644 --- a/examples/aloha/nodes/whisper_node.py +++ b/examples/aloha/nodes/whisper_node.py @@ -1,14 +1,10 @@ -import pyarrow as pa -import whisper -from pynput import keyboard -from pynput.keyboard import Key, Events -from dora import Node - -import torch import numpy as np import pyarrow as pa import sounddevice as sd -import gc # garbage collect library +import whisper +from dora import Node +from pynput import keyboard +from pynput.keyboard import Events, Key model = whisper.load_model("base") @@ -48,7 +44,7 @@ with keyboard.Events() as events: if event.key == Key.alt_r: result = get_text(5) node.send_output( - "text_llm", pa.array([result["text"]]), dora_event["metadata"] + "text_llm", pa.array([result["text"]]), dora_event["metadata"], ) elif event.key == Key.ctrl_r: result = get_text(3) diff --git a/examples/aloha/tests/test_realsense.py b/examples/aloha/tests/test_realsense.py index a7750d59..30ae9d89 100644 --- a/examples/aloha/tests/test_realsense.py +++ b/examples/aloha/tests/test_realsense.py @@ -1,7 +1,8 @@ -import pyrealsense2 as rs +import os + import cv2 import numpy as np -import os +import pyrealsense2 as rs CAMERA_ID = os.getenv("CAMERA_ID") pipe = rs.pipeline() @@ -12,7 +13,7 @@ profile = pipe.start(config) try: - for i in range(0, 1000): + for i in range(1000): frames = pipe.wait_for_frames() color_frame = frames.get_color_frame() color_images = np.asanyarray(color_frame.get_data()) diff --git a/examples/lebai/nodes/interpolation.py b/examples/lebai/nodes/interpolation.py index f14baedc..06a40302 100644 --- a/examples/lebai/nodes/interpolation.py +++ b/examples/lebai/nodes/interpolation.py @@ -1,14 +1,13 @@ -from dora import Node -import pyarrow as pa from enum import Enum +import pyarrow as pa +from dora import Node + node = Node() class Action(Enum): - """ - Action abstraction - """ + """Action abstraction for robot movement commands.""" YAW_RIGHT = ("yaw right", "movej", [0, 0, 0, 0, -0.1, 0, 0.1]) YAW_LEFT = ("yaw left", "movej", [0, 0, 0, 0, 0.1, 0, 0.1]) diff --git a/examples/lebai/nodes/key_interpolation.py b/examples/lebai/nodes/key_interpolation.py index 25d7361f..1776fa6b 100644 --- a/examples/lebai/nodes/key_interpolation.py +++ b/examples/lebai/nodes/key_interpolation.py @@ -1,5 +1,5 @@ -from dora import Node import pyarrow as pa +from dora import Node node = Node() diff --git a/examples/lebai/nodes/prompt_interpolation.py b/examples/lebai/nodes/prompt_interpolation.py index 4c5ecc32..f81f6b69 100644 --- a/examples/lebai/nodes/prompt_interpolation.py +++ b/examples/lebai/nodes/prompt_interpolation.py @@ -1,5 +1,5 @@ -from dora import Node import pyarrow as pa +from dora import Node node = Node() @@ -15,7 +15,7 @@ for event in node: pa.array( [ "Respond with left, right, forward, back, up, down or go home in order for the robotic arm to " - + text - ] + + text, + ], ), ) diff --git a/examples/lebai/nodes/voice_interpolation.py b/examples/lebai/nodes/voice_interpolation.py index 43479e82..72d5c9c2 100644 --- a/examples/lebai/nodes/voice_interpolation.py +++ b/examples/lebai/nodes/voice_interpolation.py @@ -1,5 +1,5 @@ -from dora import Node import pyarrow as pa +from dora import Node node = Node() diff --git a/examples/reachy/nodes/gym_dora_node.py b/examples/reachy/nodes/gym_dora_node.py index 96030682..c1ce0640 100644 --- a/examples/reachy/nodes/gym_dora_node.py +++ b/examples/reachy/nodes/gym_dora_node.py @@ -1,14 +1,12 @@ import time -from pathlib import Path +import gym_dora # noqa: F401 import gymnasium as gym import pandas as pd from lerobot.common.datasets.lerobot_dataset import LeRobotDataset -import gym_dora # noqa: F401 - env = gym.make( - "gym_dora/DoraReachy2-v0", disable_env_checker=True, max_episode_steps=10000 + "gym_dora/DoraReachy2-v0", disable_env_checker=True, max_episode_steps=10000, ) observation = env.reset() diff --git a/examples/reachy/nodes/keyboard_node.py b/examples/reachy/nodes/keyboard_node.py index 213ba448..32fee0dc 100644 --- a/examples/reachy/nodes/keyboard_node.py +++ b/examples/reachy/nodes/keyboard_node.py @@ -1,8 +1,7 @@ -from pynput import keyboard -from pynput.keyboard import Key, Events import pyarrow as pa from dora import Node - +from pynput import keyboard +from pynput.keyboard import Events, Key node = Node() buffer_text = "" @@ -17,7 +16,7 @@ with keyboard.Events() as events: cursor += 1 node.send_output("space", pa.array([cursor])) space = True - + elif event is not None and isinstance(event, Events.Release): if event.key == Key.space: @@ -25,7 +24,7 @@ with keyboard.Events() as events: space = False elif event.key == Key.backspace: node.send_output("failed", pa.array([cursor])) - + if node.next(0.001) is None: break diff --git a/examples/reachy/nodes/lerobot_webcam_saver.py b/examples/reachy/nodes/lerobot_webcam_saver.py index 971bc791..28ba5271 100644 --- a/examples/reachy/nodes/lerobot_webcam_saver.py +++ b/examples/reachy/nodes/lerobot_webcam_saver.py @@ -1,14 +1,12 @@ #!/usr/bin/env python3 -# -*- coding: utf-8 -*- import os -import time -import numpy as np +import subprocess +from pathlib import Path + import cv2 import pyarrow as pa -from pathlib import Path from dora import Node -import subprocess node = Node() @@ -40,12 +38,12 @@ for event in node: f"ffmpeg -r {FPS} " "-f image2 " "-loglevel error " - f"-i {str(out_dir / 'frame_%06d.png')} " + f"-i {out_dir / 'frame_%06d.png'!s} " "-vcodec libx264 " "-g 2 " "-pix_fmt yuv444p " - f"{str(video_path)} &&" - f"rm -r {str(out_dir)}" + f"{video_path!s} &&" + f"rm -r {out_dir!s}" ) print(ffmpeg_cmd, flush=True) subprocess.Popen([ffmpeg_cmd], start_new_session=True, shell=True) diff --git a/examples/reachy/nodes/plot_node.py b/examples/reachy/nodes/plot_node.py index a2c4ea2b..ebc8ebd3 100644 --- a/examples/reachy/nodes/plot_node.py +++ b/examples/reachy/nodes/plot_node.py @@ -1,8 +1,8 @@ import os + import cv2 from dora import Node - IMAGE_WIDTH = int(os.getenv("IMAGE_WIDTH", "1280")) IMAGE_HEIGHT = int(os.getenv("IMAGE_HEIGHT", "720")) FONT = cv2.FONT_HERSHEY_SIMPLEX diff --git a/examples/reachy/nodes/reachy_client.py b/examples/reachy/nodes/reachy_client.py index 0fb16bc1..4477fa72 100644 --- a/examples/reachy/nodes/reachy_client.py +++ b/examples/reachy/nodes/reachy_client.py @@ -1,7 +1,4 @@ -import argparse -import os import time -from pathlib import Path # import h5py import numpy as np @@ -83,7 +80,7 @@ for event in node: # min(100, max(0, action[7] / 2.26 * 100)) # ) # replay true action value reachy.l_arm.gripper.set_opening( - 0 if action[7] < 2.0 else 100 + 0 if action[7] < 2.0 else 100, ) # trick to force the gripper to close fully reachy.r_arm.shoulder.pitch.goal_position = np.rad2deg(action[8]) @@ -97,7 +94,7 @@ for event in node: # min(100, max(0, action[15] / 2.26 * 100)) # ) # replay true action value reachy.r_arm.gripper.set_opening( - 0 if action[15] < 2.0 else 100 + 0 if action[15] < 2.0 else 100, ) # trick to force the gripper to close fully reachy.mobile_base.set_speed(action[16], action[17], np.rad2deg(action[18])) reachy.head.neck.roll.goal_position = np.rad2deg(action[19]) @@ -110,38 +107,38 @@ for event in node: mobile_base_pos = {"vx": 0, "vy": 0, "vtheta": 0} qpos = { "l_arm_shoulder_pitch": np.deg2rad( - reachy.l_arm.shoulder.pitch.present_position + reachy.l_arm.shoulder.pitch.present_position, ), "l_arm_shoulder_roll": np.deg2rad( - reachy.l_arm.shoulder.roll.present_position + reachy.l_arm.shoulder.roll.present_position, ), "l_arm_elbow_yaw": np.deg2rad(reachy.l_arm.elbow.yaw.present_position), "l_arm_elbow_pitch": np.deg2rad( - reachy.l_arm.elbow.pitch.present_position + reachy.l_arm.elbow.pitch.present_position, ), "l_arm_wrist_roll": np.deg2rad( - reachy.l_arm.wrist.roll.present_position + reachy.l_arm.wrist.roll.present_position, ), "l_arm_wrist_pitch": np.deg2rad( - reachy.l_arm.wrist.pitch.present_position + reachy.l_arm.wrist.pitch.present_position, ), "l_arm_wrist_yaw": np.deg2rad(reachy.l_arm.wrist.yaw.present_position), "l_gripper": reachy.l_arm.gripper._present_position, "r_arm_shoulder_pitch": np.deg2rad( - reachy.r_arm.shoulder.pitch.present_position + reachy.r_arm.shoulder.pitch.present_position, ), "r_arm_shoulder_roll": np.deg2rad( - reachy.r_arm.shoulder.roll.present_position + reachy.r_arm.shoulder.roll.present_position, ), "r_arm_elbow_yaw": np.deg2rad(reachy.r_arm.elbow.yaw.present_position), "r_arm_elbow_pitch": np.deg2rad( - reachy.r_arm.elbow.pitch.present_position + reachy.r_arm.elbow.pitch.present_position, ), "r_arm_wrist_roll": np.deg2rad( - reachy.r_arm.wrist.roll.present_position + reachy.r_arm.wrist.roll.present_position, ), "r_arm_wrist_pitch": np.deg2rad( - reachy.r_arm.wrist.pitch.present_position + reachy.r_arm.wrist.pitch.present_position, ), "r_arm_wrist_yaw": np.deg2rad(reachy.r_arm.wrist.yaw.present_position), "r_gripper": reachy.r_arm.gripper._present_position, diff --git a/examples/reachy/nodes/reachy_vision_client.py b/examples/reachy/nodes/reachy_vision_client.py index 1cce7c26..1a4cb7d1 100644 --- a/examples/reachy/nodes/reachy_vision_client.py +++ b/examples/reachy/nodes/reachy_vision_client.py @@ -1,7 +1,4 @@ -import argparse -import os import time -from pathlib import Path import numpy as np import pyarrow as pa @@ -21,7 +18,6 @@ cam = SDKWrapper(get_config_file_path("CONFIG_SR"), fps=freq) # ret, image = cap.read() import cv2 -import numpy as np episode = 1 dataset = LeRobotDataset("cadene/reachy2_teleop_remi") @@ -41,8 +37,6 @@ images = images.astype(np.uint8) images = cv2.cvtColor(images, cv2.COLOR_RGB2BGR) # start = time.time() -import PIL -import torch # frame_hwc = (images.permute((1, 2, 0)) * 255).type(torch.uint8).cpu().numpy() diff --git a/examples/reachy/nodes/replay_node.py b/examples/reachy/nodes/replay_node.py index f268f3fc..4f56b02d 100644 --- a/examples/reachy/nodes/replay_node.py +++ b/examples/reachy/nodes/replay_node.py @@ -1,7 +1,8 @@ -from lerobot.common.datasets.lerobot_dataset import LeRobotDataset import time -from dora import Node + import pyarrow as pa +from dora import Node +from lerobot.common.datasets.lerobot_dataset import LeRobotDataset episode = 1 dataset = LeRobotDataset("cadene/reachy2_teleop_remi") diff --git a/examples/reachy1/nodes/gym_dora_node.py b/examples/reachy1/nodes/gym_dora_node.py index 96030682..c1ce0640 100644 --- a/examples/reachy1/nodes/gym_dora_node.py +++ b/examples/reachy1/nodes/gym_dora_node.py @@ -1,14 +1,12 @@ import time -from pathlib import Path +import gym_dora # noqa: F401 import gymnasium as gym import pandas as pd from lerobot.common.datasets.lerobot_dataset import LeRobotDataset -import gym_dora # noqa: F401 - env = gym.make( - "gym_dora/DoraReachy2-v0", disable_env_checker=True, max_episode_steps=10000 + "gym_dora/DoraReachy2-v0", disable_env_checker=True, max_episode_steps=10000, ) observation = env.reset() diff --git a/examples/reachy1/nodes/key_interpolation.py b/examples/reachy1/nodes/key_interpolation.py index b997c7a0..b5107614 100644 --- a/examples/reachy1/nodes/key_interpolation.py +++ b/examples/reachy1/nodes/key_interpolation.py @@ -1,5 +1,5 @@ -from dora import Node import pyarrow as pa +from dora import Node node = Node() diff --git a/examples/reachy1/nodes/keyboard_node.py b/examples/reachy1/nodes/keyboard_node.py index 213ba448..32fee0dc 100644 --- a/examples/reachy1/nodes/keyboard_node.py +++ b/examples/reachy1/nodes/keyboard_node.py @@ -1,8 +1,7 @@ -from pynput import keyboard -from pynput.keyboard import Key, Events import pyarrow as pa from dora import Node - +from pynput import keyboard +from pynput.keyboard import Events, Key node = Node() buffer_text = "" @@ -17,7 +16,7 @@ with keyboard.Events() as events: cursor += 1 node.send_output("space", pa.array([cursor])) space = True - + elif event is not None and isinstance(event, Events.Release): if event.key == Key.space: @@ -25,7 +24,7 @@ with keyboard.Events() as events: space = False elif event.key == Key.backspace: node.send_output("failed", pa.array([cursor])) - + if node.next(0.001) is None: break diff --git a/examples/reachy1/nodes/lerobot_webcam_saver.py b/examples/reachy1/nodes/lerobot_webcam_saver.py index 971bc791..28ba5271 100644 --- a/examples/reachy1/nodes/lerobot_webcam_saver.py +++ b/examples/reachy1/nodes/lerobot_webcam_saver.py @@ -1,14 +1,12 @@ #!/usr/bin/env python3 -# -*- coding: utf-8 -*- import os -import time -import numpy as np +import subprocess +from pathlib import Path + import cv2 import pyarrow as pa -from pathlib import Path from dora import Node -import subprocess node = Node() @@ -40,12 +38,12 @@ for event in node: f"ffmpeg -r {FPS} " "-f image2 " "-loglevel error " - f"-i {str(out_dir / 'frame_%06d.png')} " + f"-i {out_dir / 'frame_%06d.png'!s} " "-vcodec libx264 " "-g 2 " "-pix_fmt yuv444p " - f"{str(video_path)} &&" - f"rm -r {str(out_dir)}" + f"{video_path!s} &&" + f"rm -r {out_dir!s}" ) print(ffmpeg_cmd, flush=True) subprocess.Popen([ffmpeg_cmd], start_new_session=True, shell=True) diff --git a/examples/reachy1/nodes/plot_node.py b/examples/reachy1/nodes/plot_node.py index a2c4ea2b..ebc8ebd3 100644 --- a/examples/reachy1/nodes/plot_node.py +++ b/examples/reachy1/nodes/plot_node.py @@ -1,8 +1,8 @@ import os + import cv2 from dora import Node - IMAGE_WIDTH = int(os.getenv("IMAGE_WIDTH", "1280")) IMAGE_HEIGHT = int(os.getenv("IMAGE_HEIGHT", "720")) FONT = cv2.FONT_HERSHEY_SIMPLEX diff --git a/examples/reachy1/nodes/reachy_client.py b/examples/reachy1/nodes/reachy_client.py index 0fb16bc1..4477fa72 100644 --- a/examples/reachy1/nodes/reachy_client.py +++ b/examples/reachy1/nodes/reachy_client.py @@ -1,7 +1,4 @@ -import argparse -import os import time -from pathlib import Path # import h5py import numpy as np @@ -83,7 +80,7 @@ for event in node: # min(100, max(0, action[7] / 2.26 * 100)) # ) # replay true action value reachy.l_arm.gripper.set_opening( - 0 if action[7] < 2.0 else 100 + 0 if action[7] < 2.0 else 100, ) # trick to force the gripper to close fully reachy.r_arm.shoulder.pitch.goal_position = np.rad2deg(action[8]) @@ -97,7 +94,7 @@ for event in node: # min(100, max(0, action[15] / 2.26 * 100)) # ) # replay true action value reachy.r_arm.gripper.set_opening( - 0 if action[15] < 2.0 else 100 + 0 if action[15] < 2.0 else 100, ) # trick to force the gripper to close fully reachy.mobile_base.set_speed(action[16], action[17], np.rad2deg(action[18])) reachy.head.neck.roll.goal_position = np.rad2deg(action[19]) @@ -110,38 +107,38 @@ for event in node: mobile_base_pos = {"vx": 0, "vy": 0, "vtheta": 0} qpos = { "l_arm_shoulder_pitch": np.deg2rad( - reachy.l_arm.shoulder.pitch.present_position + reachy.l_arm.shoulder.pitch.present_position, ), "l_arm_shoulder_roll": np.deg2rad( - reachy.l_arm.shoulder.roll.present_position + reachy.l_arm.shoulder.roll.present_position, ), "l_arm_elbow_yaw": np.deg2rad(reachy.l_arm.elbow.yaw.present_position), "l_arm_elbow_pitch": np.deg2rad( - reachy.l_arm.elbow.pitch.present_position + reachy.l_arm.elbow.pitch.present_position, ), "l_arm_wrist_roll": np.deg2rad( - reachy.l_arm.wrist.roll.present_position + reachy.l_arm.wrist.roll.present_position, ), "l_arm_wrist_pitch": np.deg2rad( - reachy.l_arm.wrist.pitch.present_position + reachy.l_arm.wrist.pitch.present_position, ), "l_arm_wrist_yaw": np.deg2rad(reachy.l_arm.wrist.yaw.present_position), "l_gripper": reachy.l_arm.gripper._present_position, "r_arm_shoulder_pitch": np.deg2rad( - reachy.r_arm.shoulder.pitch.present_position + reachy.r_arm.shoulder.pitch.present_position, ), "r_arm_shoulder_roll": np.deg2rad( - reachy.r_arm.shoulder.roll.present_position + reachy.r_arm.shoulder.roll.present_position, ), "r_arm_elbow_yaw": np.deg2rad(reachy.r_arm.elbow.yaw.present_position), "r_arm_elbow_pitch": np.deg2rad( - reachy.r_arm.elbow.pitch.present_position + reachy.r_arm.elbow.pitch.present_position, ), "r_arm_wrist_roll": np.deg2rad( - reachy.r_arm.wrist.roll.present_position + reachy.r_arm.wrist.roll.present_position, ), "r_arm_wrist_pitch": np.deg2rad( - reachy.r_arm.wrist.pitch.present_position + reachy.r_arm.wrist.pitch.present_position, ), "r_arm_wrist_yaw": np.deg2rad(reachy.r_arm.wrist.yaw.present_position), "r_gripper": reachy.r_arm.gripper._present_position, diff --git a/examples/reachy1/nodes/reachy_vision_client.py b/examples/reachy1/nodes/reachy_vision_client.py index 1cce7c26..1a4cb7d1 100644 --- a/examples/reachy1/nodes/reachy_vision_client.py +++ b/examples/reachy1/nodes/reachy_vision_client.py @@ -1,7 +1,4 @@ -import argparse -import os import time -from pathlib import Path import numpy as np import pyarrow as pa @@ -21,7 +18,6 @@ cam = SDKWrapper(get_config_file_path("CONFIG_SR"), fps=freq) # ret, image = cap.read() import cv2 -import numpy as np episode = 1 dataset = LeRobotDataset("cadene/reachy2_teleop_remi") @@ -41,8 +37,6 @@ images = images.astype(np.uint8) images = cv2.cvtColor(images, cv2.COLOR_RGB2BGR) # start = time.time() -import PIL -import torch # frame_hwc = (images.permute((1, 2, 0)) * 255).type(torch.uint8).cpu().numpy() diff --git a/examples/reachy1/nodes/replay_node.py b/examples/reachy1/nodes/replay_node.py index f268f3fc..4f56b02d 100644 --- a/examples/reachy1/nodes/replay_node.py +++ b/examples/reachy1/nodes/replay_node.py @@ -1,7 +1,8 @@ -from lerobot.common.datasets.lerobot_dataset import LeRobotDataset import time -from dora import Node + import pyarrow as pa +from dora import Node +from lerobot.common.datasets.lerobot_dataset import LeRobotDataset episode = 1 dataset = LeRobotDataset("cadene/reachy2_teleop_remi") diff --git a/examples/reachy1/nodes/text_interpolation.py b/examples/reachy1/nodes/text_interpolation.py index 0910b350..2d9a514b 100644 --- a/examples/reachy1/nodes/text_interpolation.py +++ b/examples/reachy1/nodes/text_interpolation.py @@ -1,6 +1,5 @@ -from dora import Node import pyarrow as pa -import numpy as np +from dora import Node node = Node() @@ -19,19 +18,19 @@ for event in node: node.send_output("head_action", pa.array([0, head_step, 0])) elif text == "look up": node.send_output( - "head_action", pa.array([head_step / 2, 0, -head_step / 2]) + "head_action", pa.array([head_step / 2, 0, -head_step / 2]), ) elif text == "look down": node.send_output( - "head_action", pa.array([-head_step / 2, 0, head_step / 2]) + "head_action", pa.array([-head_step / 2, 0, head_step / 2]), ) elif text == "look up": node.send_output( - "head_action", pa.array([head_step / 2, 0, -head_step / 2]) + "head_action", pa.array([head_step / 2, 0, -head_step / 2]), ) elif text == "look down": node.send_output( - "head_action", pa.array([-head_step / 2, 0, head_step / 2]) + "head_action", pa.array([-head_step / 2, 0, head_step / 2]), ) elif text == "smile": node.send_output("antenna_action", pa.array(["smile"])) @@ -54,8 +53,8 @@ for event in node: "question", pa.array( [ - "Respond with right, left, forward, backward, open, or close to grab the trash" - ] + "Respond with right, left, forward, backward, open, or close to grab the trash", + ], ), ) @@ -65,8 +64,8 @@ for event in node: "question", pa.array( [ - "Respond with right, left, forward, backward, open, or close to put the trash in your hand in the right bin" - ] + "Respond with right, left, forward, backward, open, or close to put the trash in your hand in the right bin", + ], ), ) node.send_output("gripper_action", pa.array([100])) diff --git a/examples/so100/bus.py b/examples/so100/bus.py index 2b231615..569ca9d2 100644 --- a/examples/so100/bus.py +++ b/examples/so100/bus.py @@ -1,17 +1,18 @@ import enum - -import pyarrow as pa - from typing import Union +import pyarrow as pa from scservo_sdk import ( - PacketHandler, - PortHandler, COMM_SUCCESS, + SCS_HIBYTE, + SCS_HIWORD, + SCS_LOBYTE, + SCS_LOWORD, GroupSyncRead, GroupSyncWrite, + PacketHandler, + PortHandler, ) -from scservo_sdk import SCS_HIBYTE, SCS_HIWORD, SCS_LOBYTE, SCS_LOWORD PROTOCOL_VERSION = 0 BAUD_RATE = 1_000_000 @@ -93,13 +94,12 @@ MODEL_CONTROL_TABLE = { class FeetechBus: def __init__(self, port: str, description: dict[str, (np.uint8, str)]): - """ - Args: - port: the serial port to connect to the Feetech bus - description: a dictionary containing the description of the motors connected to the bus. The keys are the - motor names and the values are tuples containing the motor id and the motor model. - """ + """Args: + port: the serial port to connect to the Feetech bus + description: a dictionary containing the description of the motors connected to the bus. The keys are the + motor names and the values are tuples containing the motor id and the motor model. + """ self.port = port self.descriptions = description self.motor_ctrl = {} @@ -183,7 +183,7 @@ class FeetechBus: else: raise NotImplementedError( f"Value of the number of bytes to be sent is expected to be in [1, 2, 4], but {packet_bytes_size} " - f"is provided instead." + f"is provided instead.", ) if init_group: @@ -195,7 +195,7 @@ class FeetechBus: if comm != COMM_SUCCESS: raise ConnectionError( f"Write failed due to communication error on port {self.port} for group_key {group_key}: " - f"{self.packet_handler.getTxRxResult(comm)}" + f"{self.packet_handler.getTxRxResult(comm)}", ) def read(self, data_name: str, motor_names: pa.Array) -> pa.StructArray: @@ -225,13 +225,13 @@ class FeetechBus: if comm != COMM_SUCCESS: raise ConnectionError( f"Read failed due to communication error on port {self.port} for group_key {group_key}: " - f"{self.packet_handler.getTxRxResult(comm)}" + f"{self.packet_handler.getTxRxResult(comm)}", ) values = pa.array( [ self.group_readers[group_key].getData( - idx, packet_address, packet_bytes_size + idx, packet_address, packet_bytes_size, ) for idx in motor_ids ], diff --git a/examples/so100/configure.py b/examples/so100/configure.py index 40b998d5..b99848bc 100644 --- a/examples/so100/configure.py +++ b/examples/so100/configure.py @@ -1,5 +1,4 @@ -""" -SO100 Auto Configure: This program is used to automatically configure the SO-ARM100 (SO100) for the user. +"""SO100 Auto Configure: This program is used to automatically configure the SO-ARM100 (SO100) for the user. The program will: 1. Disable all torque motors of provided SO100. @@ -14,20 +13,17 @@ It will also enable all appropriate operating modes for the SO100. """ import argparse -import time import json +import time import pyarrow as pa - -from bus import FeetechBus, TorqueMode, OperatingMode -from pwm_position_control.transform import pwm_to_logical_arrow, wrap_joints_and_values - +from bus import FeetechBus, OperatingMode, TorqueMode +from pwm_position_control.functions import construct_control_table from pwm_position_control.tables import ( construct_logical_to_pwm_conversion_table_arrow, construct_pwm_to_logical_conversion_table_arrow, ) - -from pwm_position_control.functions import construct_control_table +from pwm_position_control.transform import pwm_to_logical_arrow, wrap_joints_and_values FULL_ARM = pa.array( [ @@ -50,35 +46,42 @@ GRIPPER = pa.array(["gripper"], type=pa.string()) def pause(): + """Pause execution and wait for user input.""" input("Press Enter to continue...") def configure_servos(bus: FeetechBus): + """Configure the servos with default settings. + + Args: + bus: The FeetechBus instance to configure. + """ bus.write_torque_enable( - wrap_joints_and_values(FULL_ARM, [TorqueMode.DISABLED.value] * 6) + wrap_joints_and_values(FULL_ARM, [TorqueMode.DISABLED.value] * 6), ) bus.write_operating_mode( - wrap_joints_and_values(FULL_ARM, [OperatingMode.ONE_TURN.value] * 6) + wrap_joints_and_values(FULL_ARM, [OperatingMode.ONE_TURN.value] * 6), ) bus.write_max_angle_limit( - wrap_joints_and_values(FULL_ARM, [pa.scalar(0, pa.uint32())] * 6) + wrap_joints_and_values(FULL_ARM, [pa.scalar(0, pa.uint32())] * 6), ) bus.write_min_angle_limit( - wrap_joints_and_values(FULL_ARM, [pa.scalar(0, pa.uint32())] * 6) + wrap_joints_and_values(FULL_ARM, [pa.scalar(0, pa.uint32())] * 6), ) def main(): + """Main function to run the servo configuration process.""" parser = argparse.ArgumentParser( description="SO100 Auto Configure: This program is used to automatically configure the Low Cost Robot (SO100) " - "for the user." + "for the user.", ) parser.add_argument( - "--port", type=str, required=True, help="The port of the SO100." + "--port", type=str, required=True, help="The port of the SO100.", ) parser.add_argument( "--right", @@ -130,10 +133,10 @@ def main(): pwm_positions = (pwm_position_1, pwm_position_2) pwm_to_logical_conversion_table = construct_pwm_to_logical_conversion_table_arrow( - pwm_positions, targets + pwm_positions, targets, ) logical_to_pwm_conversion_table = construct_logical_to_pwm_conversion_table_arrow( - pwm_positions, targets + pwm_positions, targets, ) control_table_json = {} @@ -149,7 +152,7 @@ def main(): left = "left" if args.left else "right" path = ( input( - f"Please enter the path of the configuration file (default is ./examples/so100/configs/follower.{left}.json): " + f"Please enter the path of the configuration file (default is ./examples/so100/configs/follower.{left}.json): ", ) or f"./examples/so100/configs/follower.{left}.json" ) @@ -158,21 +161,21 @@ def main(): json.dump(control_table_json, file) control_table = construct_control_table( - pwm_to_logical_conversion_table, logical_to_pwm_conversion_table + pwm_to_logical_conversion_table, logical_to_pwm_conversion_table, ) while True: try: pwm_position = arm.read_position(FULL_ARM) logical_position = pwm_to_logical_arrow( - pwm_position, control_table, ranged=True + pwm_position, control_table, ranged=True, ).field("values") print(f"Logical Position: {logical_position}") except ConnectionError: print( - "Connection error occurred. Please check the connection and try again." + "Connection error occurred. Please check the connection and try again.", ) time.sleep(0.5) diff --git a/examples/so100/nodes/interpolate_lcr_to_so100.py b/examples/so100/nodes/interpolate_lcr_to_so100.py index c007bea7..c200cc7f 100644 --- a/examples/so100/nodes/interpolate_lcr_to_so100.py +++ b/examples/so100/nodes/interpolate_lcr_to_so100.py @@ -1,25 +1,24 @@ -import os import argparse import json +import os import pyarrow as pa import pyarrow.compute as pc - from dora import Node - +from pwm_position_control.load import load_control_table_from_json_conversion_tables from pwm_position_control.transform import ( - wrap_joints_and_values, - pwm_to_logical_arrow, logical_to_pwm_with_offset_arrow, + pwm_to_logical_arrow, + wrap_joints_and_values, ) -from pwm_position_control.load import load_control_table_from_json_conversion_tables def main(): + """Main function to handle interpolation between LCR and SO100 robot configurations.""" # Handle dynamic nodes, ask for the name of the node in the dataflow parser = argparse.ArgumentParser( description="Interpolation LCR Node: This Dora node is used to calculates appropriate goal positions for the " - "LCR followers knowing a Leader position and Follower position." + "LCR followers knowing a Leader position and Follower position.", ) parser.add_argument( @@ -48,19 +47,19 @@ def main(): if not os.environ.get("LEADER_CONTROL") and args.leader_control is None: raise ValueError( "The leader control is not set. Please set the configuration of the leader in the environment variables or " - "as an argument." + "as an argument.", ) if not os.environ.get("FOLLOWER_CONTROL") and args.follower_control is None: raise ValueError( "The follower control is not set. Please set the configuration of the follower in the environment " - "variables or as an argument." + "variables or as an argument.", ) with open( os.environ.get("LEADER_CONTROL") if args.leader_control is None - else args.leader_control + else args.leader_control, ) as file: leader_control = json.load(file) load_control_table_from_json_conversion_tables(leader_control, leader_control) @@ -68,11 +67,11 @@ def main(): with open( os.environ.get("FOLLOWER_CONTROL") if args.follower_control is None - else args.follower_control + else args.follower_control, ) as file: follower_control = json.load(file) load_control_table_from_json_conversion_tables( - follower_control, follower_control + follower_control, follower_control, ) initial_mask = [ @@ -132,7 +131,7 @@ def main(): ) pwm_goal = logical_to_pwm_with_offset_arrow( - follower_position, logical_goal, follower_control + follower_position, logical_goal, follower_control, ) node.send_output("follower_goal", pwm_goal, event["metadata"]) diff --git a/examples/so100/nodes/interpolate_lcr_x_so100_to_record.py b/examples/so100/nodes/interpolate_lcr_x_so100_to_record.py index ce3d43d9..540c13d8 100644 --- a/examples/so100/nodes/interpolate_lcr_x_so100_to_record.py +++ b/examples/so100/nodes/interpolate_lcr_x_so100_to_record.py @@ -1,23 +1,22 @@ -import os import argparse import json +import os import pyarrow as pa import pyarrow.compute as pc - from dora import Node - from pwm_position_control.load import load_control_table_from_json_conversion_tables from pwm_position_control.transform import ( - wrap_joints_and_values, pwm_to_logical_arrow, + wrap_joints_and_values, ) def main(): + """Main function to handle interpolation and recording between LCR and SO100 robot configurations.""" parser = argparse.ArgumentParser( description="Interpolation LCR Node: This Dora node is used to calculates appropriate goal positions for the " - "LCR followers knowing a Leader position and Follower position." + "LCR followers knowing a Leader position and Follower position.", ) parser.add_argument( @@ -45,19 +44,19 @@ def main(): if not os.environ.get("LEADER_CONTROL") and args.leader_control is None: raise ValueError( "The leader control is not set. Please set the configuration of the leader in the environment variables or " - "as an argument." + "as an argument.", ) if not os.environ.get("FOLLOWER_CONTROL") and args.follower_control is None: raise ValueError( "The follower control is not set. Please set the configuration of the follower in the environment " - "variables or as an argument." + "variables or as an argument.", ) with open( os.environ.get("LEADER_CONTROL") if args.leader_control is None - else args.leader_control + else args.leader_control, ) as file: leader_control = json.load(file) load_control_table_from_json_conversion_tables(leader_control, leader_control) @@ -65,11 +64,11 @@ def main(): with open( os.environ.get("FOLLOWER_CONTROL") if args.follower_control is None - else args.follower_control + else args.follower_control, ) as file: follower_control = json.load(file) load_control_table_from_json_conversion_tables( - follower_control, follower_control + follower_control, follower_control, ) node = Node(args.name) @@ -98,11 +97,11 @@ def main(): follower_position = event["value"] follower_position = pwm_to_logical_arrow( - follower_position, follower_control + follower_position, follower_control, ) node.send_output( - "logical_position", follower_position, event["metadata"] + "logical_position", follower_position, event["metadata"], ) elif event_type == "ERROR": diff --git a/examples/so100/nodes/interpolate_replay_to_so100.py b/examples/so100/nodes/interpolate_replay_to_so100.py index c4967aab..3621cde5 100644 --- a/examples/so100/nodes/interpolate_replay_to_so100.py +++ b/examples/so100/nodes/interpolate_replay_to_so100.py @@ -1,20 +1,18 @@ -import os import argparse import json - -import pyarrow as pa +import os from dora import Node - from pwm_position_control.load import load_control_table_from_json_conversion_tables from pwm_position_control.transform import logical_to_pwm_with_offset_arrow def main(): + """Main function to handle replay interpolation for SO100 robot configurations.""" # Handle dynamic nodes, ask for the name of the node in the dataflow parser = argparse.ArgumentParser( description="Interpolation LCR Node: This Dora node is used to calculates appropriate goal positions for the " - "LCR followers knowing a Leader position and Follower position." + "LCR followers knowing a Leader position and Follower position.", ) parser.add_argument( @@ -36,17 +34,17 @@ def main(): if not os.environ.get("FOLLOWER_CONTROL") and args.follower_control is None: raise ValueError( "The follower control is not set. Please set the configuration of the follower in the environment " - "variables or as an argument." + "variables or as an argument.", ) with open( os.environ.get("FOLLOWER_CONTROL") if args.follower_control is None - else args.follower_control + else args.follower_control, ) as file: follower_control = json.load(file) load_control_table_from_json_conversion_tables( - follower_control, follower_control + follower_control, follower_control, ) node = Node(args.name) @@ -68,7 +66,7 @@ def main(): continue physical_goal = logical_to_pwm_with_offset_arrow( - follower_position, leader_position, follower_control + follower_position, leader_position, follower_control, ) node.send_output("follower_goal", physical_goal, event["metadata"]) diff --git a/node-hub/dora-distil-whisper/dora_distil_whisper/main.py b/node-hub/dora-distil-whisper/dora_distil_whisper/main.py index d25d8322..fba4f250 100644 --- a/node-hub/dora-distil-whisper/dora_distil_whisper/main.py +++ b/node-hub/dora-distil-whisper/dora_distil_whisper/main.py @@ -239,5 +239,5 @@ def main(): if text.strip() == "" or text.strip() == ".": continue node.send_output( - "text", pa.array([text]), {"language": TARGET_LANGUAGE} + "text", pa.array([text]), {"language": TARGET_LANGUAGE}, ) diff --git a/node-hub/dora-llama-cpp-python/dora_llama_cpp_python/__main__.py b/node-hub/dora-llama-cpp-python/dora_llama_cpp_python/__main__.py index 7bc8a1f1..51a1554d 100644 --- a/node-hub/dora-llama-cpp-python/dora_llama_cpp_python/__main__.py +++ b/node-hub/dora-llama-cpp-python/dora_llama_cpp_python/__main__.py @@ -2,6 +2,5 @@ from .main import main - if __name__ == "__main__": main() diff --git a/node-hub/dora-llama-cpp-python/dora_llama_cpp_python/main.py b/node-hub/dora-llama-cpp-python/dora_llama_cpp_python/main.py index ec9c888d..1acff6c0 100644 --- a/node-hub/dora-llama-cpp-python/dora_llama_cpp_python/main.py +++ b/node-hub/dora-llama-cpp-python/dora_llama_cpp_python/main.py @@ -1,10 +1,11 @@ """TODO: Add docstring.""" +import logging import os +from pathlib import Path + import pyarrow as pa from dora import Node -from pathlib import Path -import logging # Configure logging logging.basicConfig(level=logging.INFO) @@ -24,7 +25,7 @@ CONTEXT_SIZE = int(os.getenv("CONTEXT_SIZE", "4096")) def get_model(): """Load a GGUF model using llama-cpp-python with optional GPU acceleration.""" from llama_cpp import Llama - + try: # Check if path exists locally model_path = Path(MODEL_NAME_OR_PATH) @@ -35,7 +36,7 @@ def get_model(): n_gpu_layers=N_GPU_LAYERS, n_ctx=CONTEXT_SIZE, n_threads=N_THREADS, - verbose=False + verbose=False, ) else: # Load from HuggingFace @@ -46,14 +47,14 @@ def get_model(): n_gpu_layers=N_GPU_LAYERS, n_ctx=CONTEXT_SIZE, n_threads=N_THREADS, - verbose=False + verbose=False, ) - + logging.info("Model loaded successfully") return llm - + except Exception as e: - logging.error(f"Error loading model: {e}") + logging.exception(f"Error loading model: {e}") raise @@ -79,9 +80,9 @@ def main(): max_tokens=MAX_TOKENS, stop=["Q:", "\n"], )["choices"][0]["text"] - + node.send_output( - output_id="text", data=pa.array([response]), metadata={} + output_id="text", data=pa.array([response]), metadata={}, ) diff --git a/node-hub/dora-magma/dora_magma/__init__.py b/node-hub/dora-magma/dora_magma/__init__.py index 0934c04c..740d94fc 100644 --- a/node-hub/dora-magma/dora_magma/__init__.py +++ b/node-hub/dora-magma/dora_magma/__init__.py @@ -16,4 +16,4 @@ except FileNotFoundError: submodule_path = Path(__file__).resolve().parent / "Magma" -sys.path.insert(0, str(submodule_path)) \ No newline at end of file +sys.path.insert(0, str(submodule_path)) diff --git a/node-hub/dora-magma/dora_magma/main.py b/node-hub/dora-magma/dora_magma/main.py index 5d50c151..66b98cd4 100644 --- a/node-hub/dora-magma/dora_magma/main.py +++ b/node-hub/dora-magma/dora_magma/main.py @@ -27,7 +27,7 @@ def load_magma_models(): DEFAULT_PATH = str(magma_dir.parent) if not os.path.exists(DEFAULT_PATH): logger.warning( - "Warning: Magma submodule not found, falling back to HuggingFace version" + "Warning: Magma submodule not found, falling back to HuggingFace version", ) DEFAULT_PATH = "microsoft/Magma-8B" @@ -42,7 +42,7 @@ def load_magma_models(): device_map="auto", ) processor = AutoProcessor.from_pretrained( - MODEL_NAME_OR_PATH, trust_remote_code=True + MODEL_NAME_OR_PATH, trust_remote_code=True, ) except Exception as e: logger.error(f"Failed to load model: {e}") @@ -72,7 +72,7 @@ def generate( ] prompt = processor.tokenizer.apply_chat_template( - convs, tokenize=False, add_generation_prompt=True + convs, tokenize=False, add_generation_prompt=True, ) try: @@ -102,7 +102,7 @@ def generate( # Parse the trajectories using the same approach as in `https://github.com/microsoft/Magma/blob/main/agents/robot_traj/app.py` traces_dict = ast.literal_eval( - "{" + traces_str.strip().replace("\n\n", ",") + "}" + "{" + traces_str.strip().replace("\n\n", ",") + "}", ) for mark_id, trace in traces_dict.items(): trajectories[mark_id] = ast.literal_eval(trace) @@ -153,7 +153,7 @@ def main(): frame = cv2.imdecode(storage, cv2.IMREAD_COLOR) if frame is None: raise ValueError( - f"Failed to decode image with encoding {encoding}" + f"Failed to decode image with encoding {encoding}", ) frame = frame[:, :, ::-1] # Convert BGR to RGB else: @@ -181,7 +181,7 @@ def main(): image = frames[image_id] response, trajectories = generate(image, task_description) node.send_output( - "text", pa.array([response]), {"image_id": image_id} + "text", pa.array([response]), {"image_id": image_id}, ) # Send trajectory data if available diff --git a/node-hub/dora-magma/tests/test_magma_node.py b/node-hub/dora-magma/tests/test_magma_node.py index 7de0ede9..28cc7ca7 100644 --- a/node-hub/dora-magma/tests/test_magma_node.py +++ b/node-hub/dora-magma/tests/test_magma_node.py @@ -3,4 +3,4 @@ def test_import_main(): """TODO: Add docstring.""" - pass # Model is too big for the CI/CD + # Model is too big for the CI/CD diff --git a/node-hub/dora-openai-server/tests/test_dora_openai_server.py b/node-hub/dora-openai-server/tests/test_dora_openai_server.py index 47f02427..18cfb6cd 100644 --- a/node-hub/dora-openai-server/tests/test_dora_openai_server.py +++ b/node-hub/dora-openai-server/tests/test_dora_openai_server.py @@ -2,4 +2,3 @@ def test_import_main(): """TODO: Add docstring.""" - pass diff --git a/node-hub/dora-outtetts/dora_outtetts/tests/test_main.py b/node-hub/dora-outtetts/dora_outtetts/tests/test_main.py index 45bf6183..ca1c6dd0 100644 --- a/node-hub/dora-outtetts/dora_outtetts/tests/test_main.py +++ b/node-hub/dora-outtetts/dora_outtetts/tests/test_main.py @@ -3,6 +3,7 @@ import os import pytest + from dora_outtetts.main import load_interface, main CI = os.getenv("CI", "false") in ["True", "true"] diff --git a/node-hub/dora-phi4/dora_phi4/main.py b/node-hub/dora-phi4/dora_phi4/main.py index 8932a48f..22a6c5d0 100644 --- a/node-hub/dora-phi4/dora_phi4/main.py +++ b/node-hub/dora-phi4/dora_phi4/main.py @@ -27,7 +27,7 @@ else: MODEL_PATH = "microsoft/Phi-4-multimodal-instruct" processor = AutoProcessor.from_pretrained( - MODEL_PATH, trust_remote_code=True, use_fast=True + MODEL_PATH, trust_remote_code=True, use_fast=True, ) # Define model config @@ -42,12 +42,12 @@ MODEL_CONFIG = { # Infer device map without full initialization device_map = infer_auto_device_map( - AutoModelForCausalLM.from_pretrained(MODEL_PATH, **MODEL_CONFIG) + AutoModelForCausalLM.from_pretrained(MODEL_PATH, **MODEL_CONFIG), ) # Load the model directly with the inferred device map model = AutoModelForCausalLM.from_pretrained( - MODEL_PATH, **MODEL_CONFIG, device_map=device_map + MODEL_PATH, **MODEL_CONFIG, device_map=device_map, ) generation_config = GenerationConfig.from_pretrained(MODEL_PATH) diff --git a/node-hub/dora-reachy1/dora_reachy1/main.py b/node-hub/dora-reachy1/dora_reachy1/main.py index f13129be..ad4355b3 100644 --- a/node-hub/dora-reachy1/dora_reachy1/main.py +++ b/node-hub/dora-reachy1/dora_reachy1/main.py @@ -16,7 +16,7 @@ def r_arm_inverse_kinematics(reachy, pose, action) -> list: [0, 1, 0, pose[1] + action[1]], [1, 0, 0, pose[2] + action[2]], [0, 0, 0, 1], - ] + ], ) return reachy.r_arm.inverse_kinematics(A) @@ -70,7 +70,7 @@ def main(): default_pose = r_arm_inverse_kinematics(reachy, r_arm_pose, [0, 0, 0]) goto( - {joint: pos for joint, pos in zip(reachy.r_arm.joints.values(), default_pose)}, + {joint: pos for joint, pos in zip(reachy.r_arm.joints.values(), default_pose, strict=False)}, duration=3, ) @@ -84,7 +84,7 @@ def main(): goto( { joint: pos - for joint, pos in zip(reachy.r_arm.joints.values(), joint_pose) + for joint, pos in zip(reachy.r_arm.joints.values(), joint_pose, strict=False) }, duration=0.200, ) @@ -119,7 +119,7 @@ def main(): { joint: pos for joint, pos in zip( - reachy.r_arm.joints.values(), default_pose + reachy.r_arm.joints.values(), default_pose, strict=False, ) }, duration=3, diff --git a/node-hub/dora-reachy1/dora_reachy1_vision/main.py b/node-hub/dora-reachy1/dora_reachy1_vision/main.py index 1ab20b21..1c087826 100644 --- a/node-hub/dora-reachy1/dora_reachy1_vision/main.py +++ b/node-hub/dora-reachy1/dora_reachy1_vision/main.py @@ -1,9 +1,10 @@ """TODO: Add docstring.""" -from reachy_sdk import ReachySDK import os -from dora import Node + import pyarrow as pa +from dora import Node +from reachy_sdk import ReachySDK def main(): diff --git a/node-hub/dora-reachy1/tests/test_dora_reachy1.py b/node-hub/dora-reachy1/tests/test_dora_reachy1.py index 02a19b80..470cc4fc 100644 --- a/node-hub/dora-reachy1/tests/test_dora_reachy1.py +++ b/node-hub/dora-reachy1/tests/test_dora_reachy1.py @@ -5,7 +5,6 @@ def test_pass(): """TODO: Add docstring.""" - pass # def test_import_main(): diff --git a/node-hub/dora-reachy2/tests/test_dora_reachy2.py b/node-hub/dora-reachy2/tests/test_dora_reachy2.py index 7a6d8fa4..824f256f 100644 --- a/node-hub/dora-reachy2/tests/test_dora_reachy2.py +++ b/node-hub/dora-reachy2/tests/test_dora_reachy2.py @@ -5,7 +5,6 @@ def test_pass(): """TODO: Add docstring.""" - pass # def test_import_camera_main(): diff --git a/node-hub/dora-transformers/dora_transformers/__init__.py b/node-hub/dora-transformers/dora_transformers/__init__.py index 0d05dafb..79cbf370 100644 --- a/node-hub/dora-transformers/dora_transformers/__init__.py +++ b/node-hub/dora-transformers/dora_transformers/__init__.py @@ -7,7 +7,7 @@ readme_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), "README.m # Read the content of the README file try: - with open(readme_path, "r", encoding="utf-8") as f: + with open(readme_path, encoding="utf-8") as f: __doc__ = f.read() except FileNotFoundError: __doc__ = "README file not found." diff --git a/node-hub/dora-transformers/dora_transformers/__main__.py b/node-hub/dora-transformers/dora_transformers/__main__.py index 7bc8a1f1..51a1554d 100644 --- a/node-hub/dora-transformers/dora_transformers/__main__.py +++ b/node-hub/dora-transformers/dora_transformers/__main__.py @@ -2,6 +2,5 @@ from .main import main - if __name__ == "__main__": main() diff --git a/node-hub/dora-transformers/dora_transformers/main.py b/node-hub/dora-transformers/dora_transformers/main.py index f963b5cb..18323e78 100644 --- a/node-hub/dora-transformers/dora_transformers/main.py +++ b/node-hub/dora-transformers/dora_transformers/main.py @@ -1,11 +1,12 @@ """TODO: Add docstring.""" +import logging import os + import pyarrow as pa +import torch from dora import Node from transformers import AutoModelForCausalLM, AutoTokenizer -import logging -import torch # Configure logging logging.basicConfig(level=logging.INFO) @@ -34,23 +35,23 @@ ACTIVATION_WORDS = os.getenv("ACTIVATION_WORDS", "what how who where you").split def load_model(): """Load the transformer model and tokenizer.""" logging.info(f"Loading model {MODEL_NAME} on {DEVICE}") - + # Memory efficient loading model_kwargs = { "torch_dtype": TORCH_DTYPE, "device_map": DEVICE, } - + if ENABLE_MEMORY_EFFICIENT and DEVICE == "cuda": model_kwargs.update({ "low_cpu_mem_usage": True, "offload_folder": "offload", - "load_in_8bit": True + "load_in_8bit": True, }) - + model = AutoModelForCausalLM.from_pretrained( MODEL_NAME, - **model_kwargs + **model_kwargs, ) tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME) logging.info("Model loaded successfully") @@ -61,37 +62,37 @@ def load_model(): def generate_response(model, tokenizer, text: str, history) -> tuple[str, list]: """Generate text using the transformer model.""" history += [{"role": "user", "content": text}] - + prompt = tokenizer.apply_chat_template( - history, tokenize=False, add_generation_prompt=True + history, tokenize=False, add_generation_prompt=True, ) - + model_inputs = tokenizer([prompt], return_tensors="pt").to(DEVICE) - + with torch.inference_mode(): generated_ids = model.generate( - **model_inputs, + **model_inputs, max_new_tokens=MAX_TOKENS, pad_token_id=tokenizer.pad_token_id, do_sample=True, temperature=0.7, - top_p=0.9, + top_p=0.9, repetition_penalty=1.2, length_penalty=0.5, ) - + generated_ids = [ output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids) ] - + response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0] history += [{"role": "assistant", "content": response}] - + # Clear CUDA cache after successful generation if enabled if ENABLE_MEMORY_EFFICIENT and DEVICE == "cuda": torch.cuda.empty_cache() - + return response, history def main(): @@ -111,11 +112,11 @@ def main(): logging.info(f"Processing input: {text}") response, history = generate_response(model, tokenizer, text, history) logging.info(f"Generated response: {response}") - + node.send_output( - output_id="text", - data=pa.array([response]), - metadata={} + output_id="text", + data=pa.array([response]), + metadata={}, ) if __name__ == "__main__": diff --git a/node-hub/dynamixel-client/dynamixel_client/bus.py b/node-hub/dynamixel-client/dynamixel_client/bus.py index a1d7f167..6809f4e7 100644 --- a/node-hub/dynamixel-client/dynamixel_client/bus.py +++ b/node-hub/dynamixel-client/dynamixel_client/bus.py @@ -1,19 +1,20 @@ """TODO: Add docstring.""" import enum - -import pyarrow as pa - from typing import Union +import pyarrow as pa from dynamixel_sdk import ( - PacketHandler, - PortHandler, COMM_SUCCESS, + DXL_HIBYTE, + DXL_HIWORD, + DXL_LOBYTE, + DXL_LOWORD, GroupSyncRead, GroupSyncWrite, + PacketHandler, + PortHandler, ) -from dynamixel_sdk import DXL_HIBYTE, DXL_HIWORD, DXL_LOBYTE, DXL_LOWORD PROTOCOL_VERSION = 2.0 BAUD_RATE = 1_000_000 @@ -70,7 +71,7 @@ def wrap_joints_and_values( mask = values.is_null() return pa.StructArray.from_arrays( - arrays=[joints, values], names=["joints", "values"], mask=mask + arrays=[joints, values], names=["joints", "values"], mask=mask, ).drop_null() @@ -248,7 +249,7 @@ class DynamixelBus: else: raise NotImplementedError( f"Value of the number of bytes to be sent is expected to be in [1, 2, 4], but {packet_bytes_size} " - f"is provided instead." + f"is provided instead.", ) if init_group: @@ -260,7 +261,7 @@ class DynamixelBus: if comm != COMM_SUCCESS: raise ConnectionError( f"Write failed due to communication error on port {self.port} for group_key {group_key}: " - f"{self.packet_handler.getTxRxResult(comm)}" + f"{self.packet_handler.getTxRxResult(comm)}", ) def read(self, data_name: str, motor_names: pa.Array) -> pa.StructArray: @@ -291,13 +292,13 @@ class DynamixelBus: if comm != COMM_SUCCESS: raise ConnectionError( f"Read failed due to communication error on port {self.port} for group_key {group_key}: " - f"{self.packet_handler.getTxRxResult(comm)}" + f"{self.packet_handler.getTxRxResult(comm)}", ) values = pa.array( [ self.group_readers[group_key].getData( - idx, packet_address, packet_bytes_size + idx, packet_address, packet_bytes_size, ) for idx in motor_ids ], diff --git a/node-hub/dynamixel-client/dynamixel_client/main.py b/node-hub/dynamixel-client/dynamixel_client/main.py index c54c1b22..fae0c375 100644 --- a/node-hub/dynamixel-client/dynamixel_client/main.py +++ b/node-hub/dynamixel-client/dynamixel_client/main.py @@ -3,13 +3,12 @@ It can be used to read positions, velocities, currents, and set goal positions and currents. """ -import os -import time import argparse import json +import os +import time import pyarrow as pa - from dora import Node from .bus import DynamixelBus, TorqueMode, wrap_joints_and_values @@ -76,7 +75,7 @@ class Client: wrap_joints_and_values( self.config["joints"], [TorqueMode.DISABLED.value] * len(self.config["joints"]), - ) + ), ) def pull_position(self, node, metadata): @@ -132,7 +131,7 @@ def main(): """Handle dynamic nodes, ask for the name of the node in the dataflow.""" parser = argparse.ArgumentParser( description="Dynamixel Client: This node is used to represent a chain of dynamixel motors. It can be used to " - "read positions, velocities, currents, and set goal positions and currents." + "read positions, velocities, currents, and set goal positions and currents.", ) parser.add_argument( @@ -162,7 +161,7 @@ def main(): if not os.environ.get("PORT") and args.port is None: raise ValueError( "The port is not set. Please set the port of the dynamixel motors in the environment variables or as an " - "argument." + "argument.", ) port = os.environ.get("PORT") if args.port is None else args.port @@ -171,7 +170,7 @@ def main(): if not os.environ.get("CONFIG") and args.config is None: raise ValueError( "The configuration is not set. Please set the configuration of the dynamixel motors in the environment " - "variables or as an argument." + "variables or as an argument.", ) with open(os.environ.get("CONFIG") if args.config is None else args.config) as file: @@ -203,7 +202,7 @@ def main(): "goal_current": wrap_joints_and_values( pa.array(config.keys(), pa.string()), pa.array( - [config[joint]["goal_current"] for joint in joints], type=pa.uint32() + [config[joint]["goal_current"] for joint in joints], type=pa.uint32(), ), ), "P": wrap_joints_and_values( diff --git a/node-hub/dynamixel-client/tests/test_dynamixel_client.py b/node-hub/dynamixel-client/tests/test_dynamixel_client.py index 7b8b9b4c..09b067cf 100644 --- a/node-hub/dynamixel-client/tests/test_dynamixel_client.py +++ b/node-hub/dynamixel-client/tests/test_dynamixel_client.py @@ -4,7 +4,6 @@ def test_pass(): """TODO: Add docstring.""" - pass # def test_import_main(): diff --git a/node-hub/feetech-client/feetech_client/__init__.py b/node-hub/feetech-client/feetech_client/__init__.py index b8973a5a..a9cca0f7 100644 --- a/node-hub/feetech-client/feetech_client/__init__.py +++ b/node-hub/feetech-client/feetech_client/__init__.py @@ -1 +1 @@ -"""TODO: Add docstring.""" \ No newline at end of file +"""TODO: Add docstring.""" diff --git a/node-hub/feetech-client/feetech_client/bus.py b/node-hub/feetech-client/feetech_client/bus.py index bca6030a..6e42d4db 100644 --- a/node-hub/feetech-client/feetech_client/bus.py +++ b/node-hub/feetech-client/feetech_client/bus.py @@ -194,7 +194,7 @@ class FeetechBus: else: raise NotImplementedError( f"Value of the number of bytes to be sent is expected to be in [1, 2, 4], but {packet_bytes_size} " - f"is provided instead." + f"is provided instead.", ) if init_group: @@ -206,7 +206,7 @@ class FeetechBus: if comm != COMM_SUCCESS: raise ConnectionError( f"Write failed due to communication error on port {self.port} for group_key {group_key}: " - f"{self.packet_handler.getTxRxResult(comm)}" + f"{self.packet_handler.getTxRxResult(comm)}", ) def read(self, data_name: str, motor_names: pa.Array) -> pa.StructArray: @@ -237,13 +237,13 @@ class FeetechBus: if comm != COMM_SUCCESS: raise ConnectionError( f"Read failed due to communication error on port {self.port} for group_key {group_key}: " - f"{self.packet_handler.getTxRxResult(comm)}" + f"{self.packet_handler.getTxRxResult(comm)}", ) values = pa.array( [ self.group_readers[group_key].getData( - idx, packet_address, packet_bytes_size + idx, packet_address, packet_bytes_size, ) for idx in motor_ids ], diff --git a/node-hub/feetech-client/feetech_client/main.py b/node-hub/feetech-client/feetech_client/main.py index c1f26d60..14203334 100644 --- a/node-hub/feetech-client/feetech_client/main.py +++ b/node-hub/feetech-client/feetech_client/main.py @@ -1,11 +1,10 @@ """Feetech Client: This node is used to represent a chain of feetech motors. It can be used to read positions, velocities, currents, and set goal positions and currents.""" -import os import argparse import json +import os import pyarrow as pa - from dora import Node from .bus import FeetechBus, TorqueMode, wrap_joints_and_values @@ -60,7 +59,7 @@ class Client: wrap_joints_and_values( self.config["joints"], [TorqueMode.DISABLED.value] * len(self.config["joints"]), - ) + ), ) def pull_position(self, node, metadata): @@ -110,7 +109,7 @@ def main(): parser = argparse.ArgumentParser( description="Feetech Client: This node is used to represent a chain of feetech motors. " "It can be used to read " - "positions, velocities, currents, and set goal positions and currents." + "positions, velocities, currents, and set goal positions and currents.", ) parser.add_argument( @@ -140,7 +139,7 @@ def main(): if not os.environ.get("PORT") and args.port is None: raise ValueError( "The port is not set. Please set the port of the feetech motors in the environment variables or as an " - "argument." + "argument.", ) port = os.environ.get("PORT") if args.port is None else args.port @@ -149,7 +148,7 @@ def main(): if not os.environ.get("CONFIG") and args.config is None: raise ValueError( "The configuration is not set. Please set the configuration of the feetech motors in the environment " - "variables or as an argument." + "variables or as an argument.", ) with open(os.environ.get("CONFIG") if args.config is None else args.config) as file: diff --git a/node-hub/feetech-client/tests/test_feetech_client.py b/node-hub/feetech-client/tests/test_feetech_client.py index b57c9bbb..de98f7e7 100644 --- a/node-hub/feetech-client/tests/test_feetech_client.py +++ b/node-hub/feetech-client/tests/test_feetech_client.py @@ -4,7 +4,6 @@ def test_pass(): """TODO: Add docstring.""" - pass # def test_import_main(): diff --git a/node-hub/lebai-client/lebai_client/main.py b/node-hub/lebai-client/lebai_client/main.py index e66b3e78..4c692a7f 100644 --- a/node-hub/lebai-client/lebai_client/main.py +++ b/node-hub/lebai-client/lebai_client/main.py @@ -1,11 +1,12 @@ """TODO: Add docstring.""" -import lebai_sdk -import numpy as np -from dora import Node import json import os import time +import lebai_sdk +import numpy as np +from dora import Node + def load_json_file(file_path): """Load JSON file and return the dictionary.""" @@ -28,7 +29,7 @@ SAVED_POSE_PATH = "pose_library.json" lebai_sdk.init() ROBOT_IP = os.getenv( - "LEBAI_IP", "10.42.0.253" + "LEBAI_IP", "10.42.0.253", ) # 设定机器人ip地址,需要根据机器人实际ip地址修改 @@ -180,7 +181,7 @@ def main(): "duration": time.time() - start_time, "joint_position": joint_position, "t": t * 2 if t == 0.1 else t, - } + }, ] start_time = time.time() diff --git a/node-hub/lebai-client/test/test.py b/node-hub/lebai-client/test/test.py index 0239ff15..8937d413 100644 --- a/node-hub/lebai-client/test/test.py +++ b/node-hub/lebai-client/test/test.py @@ -1,7 +1,6 @@ """TODO: Add docstring.""" import lebai_sdk - lebai_sdk.init() @@ -26,7 +25,7 @@ def main(): r = 0 # 交融半径 (m)。用于指定路径的平滑效果 lebai.movel( - cartesian_pose, a, v, t, r + cartesian_pose, a, v, t, r, ) # 直线运动 https://help.lebai.ltd/sdk/motion.html#%E7%9B%B4%E7%BA%BF%E8%BF%90%E5%8A%A8 lebai.wait_move() # 等待运动完成 # scene_number = "10000" #需要调用的场景编号 diff --git a/node-hub/lebai-client/tests/test_lebai_client.py b/node-hub/lebai-client/tests/test_lebai_client.py index 6bb9c958..a507997b 100644 --- a/node-hub/lebai-client/tests/test_lebai_client.py +++ b/node-hub/lebai-client/tests/test_lebai_client.py @@ -4,7 +4,6 @@ def test_pass(): """TODO: Add docstring.""" - pass # def test_import_main(): diff --git a/node-hub/lerobot-dashboard/lerobot_dashboard/__init__.py b/node-hub/lerobot-dashboard/lerobot_dashboard/__init__.py index b8973a5a..a9cca0f7 100644 --- a/node-hub/lerobot-dashboard/lerobot_dashboard/__init__.py +++ b/node-hub/lerobot-dashboard/lerobot_dashboard/__init__.py @@ -1 +1 @@ -"""TODO: Add docstring.""" \ No newline at end of file +"""TODO: Add docstring.""" diff --git a/node-hub/lerobot-dashboard/lerobot_dashboard/main.py b/node-hub/lerobot-dashboard/lerobot_dashboard/main.py index 1856bb97..2ddd742f 100644 --- a/node-hub/lerobot-dashboard/lerobot_dashboard/main.py +++ b/node-hub/lerobot-dashboard/lerobot_dashboard/main.py @@ -1,19 +1,17 @@ """Following Dora node is a minimalistic interface that shows two images and text in a Pygame window.""" -import os import argparse - -import pygame +import os import pyarrow as pa - +import pygame from dora import Node def main(): """Handle dynamic nodes, ask for the name of the node in the dataflow.""" parser = argparse.ArgumentParser( - description="LeRobot Record: This node is used to record episodes of a robot interacting with the environment." + description="LeRobot Record: This node is used to record episodes of a robot interacting with the environment.", ) parser.add_argument( @@ -66,7 +64,7 @@ def main(): if event_type == "STOP": break - elif event_type == "INPUT": + if event_type == "INPUT": event_id = event["id"] if event_id == "image_left": @@ -80,7 +78,7 @@ def main(): } image_left = pygame.image.frombuffer( - image["data"], (image["width"], image["height"]), "BGR" + image["data"], (image["width"], image["height"]), "BGR", ) elif event_id == "image_right": @@ -93,7 +91,7 @@ def main(): } image_right = pygame.image.frombuffer( - image["data"], (image["width"], image["height"]), "BGR" + image["data"], (image["width"], image["height"]), "BGR", ) elif event_id == "tick": @@ -104,7 +102,7 @@ def main(): if pygame_event.type == pygame.QUIT: running = False break - elif pygame_event.type == pygame.KEYDOWN: + if pygame_event.type == pygame.KEYDOWN: key = pygame.key.name(pygame_event.key) if key == "space": diff --git a/node-hub/lerobot-dashboard/tests/test_lerobot_dashboard.py b/node-hub/lerobot-dashboard/tests/test_lerobot_dashboard.py index c5ef139a..b3cab3b7 100644 --- a/node-hub/lerobot-dashboard/tests/test_lerobot_dashboard.py +++ b/node-hub/lerobot-dashboard/tests/test_lerobot_dashboard.py @@ -4,7 +4,6 @@ def test_pass(): """TODO: Add docstring.""" - pass # def test_import_main(): diff --git a/node-hub/mujoco-client/mujoco_client/__init__.py b/node-hub/mujoco-client/mujoco_client/__init__.py index b8973a5a..a9cca0f7 100644 --- a/node-hub/mujoco-client/mujoco_client/__init__.py +++ b/node-hub/mujoco-client/mujoco_client/__init__.py @@ -1 +1 @@ -"""TODO: Add docstring.""" \ No newline at end of file +"""TODO: Add docstring.""" diff --git a/node-hub/mujoco-client/mujoco_client/main.py b/node-hub/mujoco-client/mujoco_client/main.py index 1c2d80f1..d6543f33 100644 --- a/node-hub/mujoco-client/mujoco_client/main.py +++ b/node-hub/mujoco-client/mujoco_client/main.py @@ -1,16 +1,14 @@ """Mujoco Client: This node is used to represent simulated robot, it can be used to read virtual positions, or can be controlled.""" -import os import argparse -import time import json - -import pyarrow as pa - -from dora import Node +import os +import time import mujoco import mujoco.viewer +import pyarrow as pa +from dora import Node class Client: @@ -66,22 +64,19 @@ class Client: elif event_type == "ERROR": raise ValueError( - "An error occurred in the dataflow: " + event["error"] + "An error occurred in the dataflow: " + event["error"], ) self.node.send_output("end", pa.array([])) def pull_position(self, node, metadata): """TODO: Add docstring.""" - pass def pull_velocity(self, node, metadata): """TODO: Add docstring.""" - pass def pull_current(self, node, metadata): """TODO: Add docstring.""" - pass def write_goal_position(self, goal_position_with_joints): """TODO: Add docstring.""" @@ -96,7 +91,7 @@ def main(): """Handle dynamic nodes, ask for the name of the node in the dataflow.""" parser = argparse.ArgumentParser( description="MujoCo Client: This node is used to represent a MuJoCo simulation. It can be used instead of a " - "follower arm to test the dataflow." + "follower arm to test the dataflow.", ) parser.add_argument( @@ -114,14 +109,14 @@ def main(): ) parser.add_argument( - "--config", type=str, help="The configuration of the joints.", default=None + "--config", type=str, help="The configuration of the joints.", default=None, ) args = parser.parse_args() if not os.getenv("SCENE") and args.scene is None: raise ValueError( - "Please set the SCENE environment variable or pass the --scene argument." + "Please set the SCENE environment variable or pass the --scene argument.", ) scene = os.getenv("SCENE", args.scene) @@ -130,7 +125,7 @@ def main(): if not os.environ.get("CONFIG") and args.config is None: raise ValueError( "The configuration is not set. Please set the configuration of the simulated motors in the environment " - "variables or as an argument." + "variables or as an argument.", ) with open(os.environ.get("CONFIG") if args.config is None else args.config) as file: diff --git a/node-hub/mujoco-client/tests/test_mujoco_client.py b/node-hub/mujoco-client/tests/test_mujoco_client.py index 603a1e20..5b4f371a 100644 --- a/node-hub/mujoco-client/tests/test_mujoco_client.py +++ b/node-hub/mujoco-client/tests/test_mujoco_client.py @@ -4,7 +4,6 @@ def test_pass(): """TODO: Add docstring.""" - pass # def test_import_main(): diff --git a/node-hub/replay-client/replay_client/__init__.py b/node-hub/replay-client/replay_client/__init__.py index b8973a5a..a9cca0f7 100644 --- a/node-hub/replay-client/replay_client/__init__.py +++ b/node-hub/replay-client/replay_client/__init__.py @@ -1 +1 @@ -"""TODO: Add docstring.""" \ No newline at end of file +"""TODO: Add docstring.""" diff --git a/node-hub/replay-client/replay_client/main.py b/node-hub/replay-client/replay_client/main.py index eca1931e..931662b9 100644 --- a/node-hub/replay-client/replay_client/main.py +++ b/node-hub/replay-client/replay_client/main.py @@ -3,12 +3,11 @@ reading a dataset of actions and joints from a specific episode. """ -import os import argparse +import os -import pyarrow as pa import pandas as pd - +import pyarrow as pa from dora import Node @@ -78,7 +77,7 @@ class Client: def main(): """Handle dynamic nodes, ask for the name of the node in the dataflow.""" parser = argparse.ArgumentParser( - description="Replay Client: This node is used to replay a sequence of goals for a followee robot." + description="Replay Client: This node is used to replay a sequence of goals for a followee robot.", ) parser.add_argument( diff --git a/node-hub/replay-client/tests/test_replay_client.py b/node-hub/replay-client/tests/test_replay_client.py index 6e30406e..d612f13d 100644 --- a/node-hub/replay-client/tests/test_replay_client.py +++ b/node-hub/replay-client/tests/test_replay_client.py @@ -4,7 +4,6 @@ def test_pass(): """TODO: Add docstring.""" - pass # def test_import_main(): diff --git a/node-hub/video-encoder/tests/test_video_encoder.py b/node-hub/video-encoder/tests/test_video_encoder.py index b8b4c3da..6d3f7bed 100644 --- a/node-hub/video-encoder/tests/test_video_encoder.py +++ b/node-hub/video-encoder/tests/test_video_encoder.py @@ -4,7 +4,6 @@ def test_pass(): """TODO: Add docstring.""" - pass # def test_import_main(): diff --git a/node-hub/video-encoder/video_encoder/__init__.py b/node-hub/video-encoder/video_encoder/__init__.py index 42a8a3b2..55941eec 100644 --- a/node-hub/video-encoder/video_encoder/__init__.py +++ b/node-hub/video-encoder/video_encoder/__init__.py @@ -1 +1 @@ -"""TODO: Doc String.""" \ No newline at end of file +"""TODO: Doc String.""" diff --git a/node-hub/video-encoder/video_encoder/main.py b/node-hub/video-encoder/video_encoder/main.py index 8ccb0fa3..1f9355ed 100644 --- a/node-hub/video-encoder/video_encoder/main.py +++ b/node-hub/video-encoder/video_encoder/main.py @@ -1,13 +1,11 @@ """TODO : Doc String.""" +import argparse import os from pathlib import Path import cv2 -import argparse - import numpy as np import pyarrow as pa - from dora import Node from ffmpeg import FFmpeg @@ -15,7 +13,7 @@ from ffmpeg import FFmpeg def main(): """Handle dynamic nodes, ask for the name of the node in the dataflow.""" parser = argparse.ArgumentParser( - description="Video Encoder: This node is used to record episodes of a robot interacting with the environment." + description="Video Encoder: This node is used to record episodes of a robot interacting with the environment.", ) parser.add_argument( @@ -77,8 +75,8 @@ def main(): { "path": f"videos/{name}", "timestamp": float(frame_count) / fps, - } - ] + }, + ], ), event["metadata"], ) @@ -92,7 +90,7 @@ def main(): } data = image["data"].reshape( - (image["height"], image["width"], image["channels"]) + (image["height"], image["width"], image["channels"]), ) path = str(out_dir / f"frame_{frame_count:06d}.png") @@ -118,7 +116,7 @@ def main(): .option("y") .input(str(out_dir / "frame_%06d.png"), f="image2", r=fps) .output( - str(video_path), vcodec="libx264", g=2, pix_fmt="yuv444p" + str(video_path), vcodec="libx264", g=2, pix_fmt="yuv444p", ) )