diff --git a/lerobot/common/robots/lekiwi/README.md b/lerobot/common/robots/lekiwi/README.md index 4846fb87..50667add 100644 --- a/lerobot/common/robots/lekiwi/README.md +++ b/lerobot/common/robots/lekiwi/README.md @@ -196,11 +196,11 @@ sudo chmod 666 /dev/ttyACM1 #### d. Update config file -IMPORTANTLY: Now that you have your ports of leader and follower arm and ip address of the mobile-so100, update the **ip** in Network configuration, **port** in leader_arms and **port** in lekiwi. In the [`LeKiwiRobotConfig`](../lerobot/common/robot_devices/robots/configs.py) file. Where you will find something like: +IMPORTANTLY: Now that you have your ports of leader and follower arm and ip address of the mobile-so100, update the **ip** in Network configuration, **port** in leader_arms and **port** in lekiwi. In the [`LeKiwiConfig`](../lerobot/common/robot_devices/robots/configs.py) file. Where you will find something like: ```python @RobotConfig.register_subclass("lekiwi") @dataclass -class LeKiwiRobotConfig(RobotConfig): +class LeKiwiConfig(RobotConfig): # `max_relative_target` limits the magnitude of the relative positional target vector for safety purposes. # Set this to a positive scalar to have the same value for all motors, or a list that is the same length as # the number of motors in your follower arms. @@ -283,7 +283,7 @@ For the wired LeKiwi version your configured IP address should refer to your own ```python @RobotConfig.register_subclass("lekiwi") @dataclass -class LeKiwiRobotConfig(RobotConfig): +class LeKiwiConfig(RobotConfig): # `max_relative_target` limits the magnitude of the relative positional target vector for safety purposes. # Set this to a positive scalar to have the same value for all motors, or a list that is the same length as # the number of motors in your follower arms. @@ -448,7 +448,7 @@ You should see on your laptop something like this: ```[INFO] Connected to remote | F | Decrease speed | > [!TIP] -> If you use a different keyboard you can change the keys for each command in the [`LeKiwiRobotConfig`](../lerobot/common/robot_devices/robots/configs.py). +> If you use a different keyboard you can change the keys for each command in the [`LeKiwiConfig`](../lerobot/common/robot_devices/robots/configs.py). ### Wired version If you have the **wired** LeKiwi version please run all commands including both these teleoperation commands on your laptop. diff --git a/lerobot/common/robots/lekiwi/configuration_lekiwi.py b/lerobot/common/robots/lekiwi/config_lekiwi.py similarity index 97% rename from lerobot/common/robots/lekiwi/configuration_lekiwi.py rename to lerobot/common/robots/lekiwi/config_lekiwi.py index df163109..331dd9ff 100644 --- a/lerobot/common/robots/lekiwi/configuration_lekiwi.py +++ b/lerobot/common/robots/lekiwi/config_lekiwi.py @@ -21,7 +21,7 @@ from lerobot.common.robots.config import RobotConfig @RobotConfig.register_subclass("lekiwi") @dataclass -class LeKiwiRobotConfig(RobotConfig): +class LeKiwiConfig(RobotConfig): port = "/dev/ttyACM0" # port to connect to the bus disable_torque_on_disconnect: bool = True diff --git a/lerobot/common/robots/lekiwi/configuration_daemon_lekiwi.py b/lerobot/common/robots/lekiwi/configuration_daemon_lekiwi.py index c25d8b35..31027478 100644 --- a/lerobot/common/robots/lekiwi/configuration_daemon_lekiwi.py +++ b/lerobot/common/robots/lekiwi/configuration_daemon_lekiwi.py @@ -17,9 +17,9 @@ from dataclasses import dataclass, field from lerobot.common.robots.config import RobotConfig -@RobotConfig.register_subclass("daemon_lekiwi") +@RobotConfig.register_subclass("lekiwi_client") @dataclass -class DaemonLeKiwiRobotConfig(RobotConfig): +class LeKiwiClientConfig(RobotConfig): # Network Configuration remote_ip: str = "172.18.133.90" port_zmq_cmd: int = 5555 diff --git a/lerobot/common/robots/lekiwi/lekiwi_robot.py b/lerobot/common/robots/lekiwi/lekiwi.py similarity index 98% rename from lerobot/common/robots/lekiwi/lekiwi_robot.py rename to lerobot/common/robots/lekiwi/lekiwi.py index 512f3d21..9c9b686d 100644 --- a/lerobot/common/robots/lekiwi/lekiwi_robot.py +++ b/lerobot/common/robots/lekiwi/lekiwi.py @@ -32,12 +32,12 @@ from lerobot.common.motors.feetech import ( from ..robot import Robot from ..utils import ensure_safe_goal_position -from .configuration_lekiwi import LeKiwiRobotConfig +from .config_lekiwi import LeKiwiConfig logger = logging.getLogger(__name__) -class LeKiwiRobot(Robot): +class LeKiwi(Robot): """ The robot includes a three omniwheel mobile base and a remote follower arm. The leader arm is connected locally (on the laptop) and its joint positions are recorded and then @@ -45,10 +45,10 @@ class LeKiwiRobot(Robot): In parallel, keyboard teleoperation is used to generate raw velocity commands for the wheels. """ - config_class = LeKiwiRobotConfig + config_class = LeKiwiConfig name = "lekiwi" - def __init__(self, config: LeKiwiRobotConfig): + def __init__(self, config: LeKiwiConfig): super().__init__(config) self.config = config self.id = config.id diff --git a/lerobot/common/robots/lekiwi/daemon_lekiwi.py b/lerobot/common/robots/lekiwi/lekiwi_client.py similarity index 96% rename from lerobot/common/robots/lekiwi/daemon_lekiwi.py rename to lerobot/common/robots/lekiwi/lekiwi_client.py index 5962018e..5968c21d 100644 --- a/lerobot/common/robots/lekiwi/daemon_lekiwi.py +++ b/lerobot/common/robots/lekiwi/lekiwi_client.py @@ -26,7 +26,7 @@ from lerobot.common.errors import DeviceAlreadyConnectedError, DeviceNotConnecte from lerobot.common.robots.config import RobotMode from ..robot import Robot -from .configuration_daemon_lekiwi import DaemonLeKiwiRobotConfig +from .configuration_daemon_lekiwi import LeKiwiClientConfig # TODO(Steven): This doesn't need to inherit from Robot @@ -40,11 +40,11 @@ from .configuration_daemon_lekiwi import DaemonLeKiwiRobotConfig # 2. Adding it into the robot implementation # (meaning the policy might be needed to be train # over the teleop action space) -class DaemonLeKiwiRobot(Robot): - config_class = DaemonLeKiwiRobotConfig - name = "daemonlekiwi" +class LeKiwiClient(Robot): + config_class = LeKiwiClientConfig + name = "lekiwi_client" - def __init__(self, config: DaemonLeKiwiRobotConfig): + def __init__(self, config: LeKiwiClientConfig): super().__init__(config) self.config = config self.id = config.id @@ -150,7 +150,7 @@ class DaemonLeKiwiRobot(Robot): # TODO(Steven): Nothing to calibrate. # Consider triggering calibrate() on the remote mobile robot? # Although this would require a more complex comms schema - logging.warning("DaemonLeKiwiRobot has nothing to calibrate.") + logging.warning("LeKiwiClient has nothing to calibrate.") return # Consider moving these static functions out of the class @@ -235,7 +235,7 @@ class DaemonLeKiwiRobot(Robot): wheel_degps = wheel_degps * scale # Convert each wheel’s angular speed (deg/s) to a raw integer. - wheel_raw = [DaemonLeKiwiRobot._degps_to_raw(deg) for deg in wheel_degps] + wheel_raw = [LeKiwiClient._degps_to_raw(deg) for deg in wheel_degps] return {"left_wheel": wheel_raw[0], "back_wheel": wheel_raw[1], "right_wheel": wheel_raw[2]} @@ -259,7 +259,7 @@ class DaemonLeKiwiRobot(Robot): """ # Convert each raw command back to an angular speed in deg/s. - wheel_degps = np.array([DaemonLeKiwiRobot._raw_to_degps(int(r)) for r in wheel_raw]) + wheel_degps = np.array([LeKiwiClient._raw_to_degps(int(r)) for r in wheel_raw]) # Convert from deg/s to rad/s. wheel_radps = wheel_degps * (np.pi / 180.0) # Compute each wheel’s linear speed (m/s) from its angular speed. @@ -352,7 +352,7 @@ class DaemonLeKiwiRobot(Robot): return (self.last_frames, self.last_present_speed, self.last_remote_arm_state) return frames, present_speed, remote_arm_state_tensor - # TODO(Steven): The returned space is different from the get_observation of LeKiwiRobot + # TODO(Steven): The returned space is different from the get_observation of LeKiwi # This returns body-frames velocities instead of wheel pos/speeds def get_observation(self) -> dict[str, np.ndarray]: """ @@ -361,9 +361,7 @@ class DaemonLeKiwiRobot(Robot): and a camera frame. Receives over ZMQ, translate to body-frame vel """ if not self.is_connected: - raise DeviceNotConnectedError( - "DaemonLeKiwiRobot is not connected. You need to run `robot.connect()`." - ) + raise DeviceNotConnectedError("LeKiwiClient is not connected. You need to run `robot.connect()`.") obs_dict = {} diff --git a/lerobot/common/robots/lekiwi/daemon_lekiwi_app.py b/lerobot/common/robots/lekiwi/lekiwi_client_app.py similarity index 89% rename from lerobot/common/robots/lekiwi/daemon_lekiwi_app.py rename to lerobot/common/robots/lekiwi/lekiwi_client_app.py index 47eb2e10..2d10fe09 100644 --- a/lerobot/common/robots/lekiwi/daemon_lekiwi_app.py +++ b/lerobot/common/robots/lekiwi/lekiwi_client_app.py @@ -18,8 +18,8 @@ import numpy as np from lerobot.common.datasets.lerobot_dataset import LeRobotDataset from lerobot.common.robots.config import RobotMode -from lerobot.common.robots.lekiwi.configuration_daemon_lekiwi import DaemonLeKiwiRobotConfig -from lerobot.common.robots.lekiwi.daemon_lekiwi import DaemonLeKiwiRobot +from lerobot.common.robots.lekiwi.configuration_daemon_lekiwi import LeKiwiClientConfig +from lerobot.common.robots.lekiwi.lekiwi_client import LeKiwiClient from lerobot.common.teleoperators.keyboard import KeyboardTeleop, KeyboardTeleopConfig from lerobot.common.teleoperators.so100 import SO100Teleop, SO100TeleopConfig @@ -87,11 +87,11 @@ def main(): keyboard_config = KeyboardTeleopConfig() keyboard = KeyboardTeleop(keyboard_config) - logging.info("Configuring LeKiwiRobot Daemon") - robot_config = DaemonLeKiwiRobotConfig( + logging.info("Configuring LeKiwi Client") + robot_config = LeKiwiClientConfig( id="daemonlekiwi", calibration_dir=".cache/calibration/lekiwi", robot_mode=RobotMode.TELEOP ) - robot = DaemonLeKiwiRobot(robot_config) + robot = LeKiwiClient(robot_config) logging.info("Creating LeRobot Dataset") @@ -106,10 +106,10 @@ def main(): leader_arm.connect() keyboard.connect() - logging.info("Connecting remote LeKiwiRobot") + logging.info("Connecting remote LeKiwi") robot.connect() - logging.info("Starting LeKiwiRobot teleoperation") + logging.info("Starting LeKiwi teleoperation") i = 0 while i < 1000: arm_action = leader_arm.get_action() @@ -135,11 +135,11 @@ def main(): dataset.save_episode() # dataset.push_to_hub() - logging.info("Disconnecting Teleop Devices and LeKiwiRobot Daemon") + logging.info("Disconnecting Teleop Devices and LeKiwi Client") robot.disconnect() leader_arm.disconnect() keyboard.disconnect() - logging.info("Finished LeKiwiRobot cleanly") + logging.info("Finished LeKiwi cleanly") if __name__ == "__main__": diff --git a/lerobot/common/robots/lekiwi/lekiwi_app.py b/lerobot/common/robots/lekiwi/lekiwi_host.py similarity index 87% rename from lerobot/common/robots/lekiwi/lekiwi_app.py rename to lerobot/common/robots/lekiwi/lekiwi_host.py index bc720494..6e4d76d3 100644 --- a/lerobot/common/robots/lekiwi/lekiwi_app.py +++ b/lerobot/common/robots/lekiwi/lekiwi_host.py @@ -22,15 +22,15 @@ import numpy as np import zmq from lerobot.common.constants import OBS_STATE -from lerobot.common.robots.lekiwi.configuration_lekiwi import LeKiwiRobotConfig -from lerobot.common.robots.lekiwi.lekiwi_robot import LeKiwiRobot +from lerobot.common.robots.lekiwi.config_lekiwi import LeKiwiConfig +from lerobot.common.robots.lekiwi.lekiwi import LeKiwi # Network Configuration PORT_ZMQ_CMD: int = 5555 PORT_ZMQ_OBSERVATIONS: int = 5556 -class RemoteAgent: +class HostAgent: def __init__(self): self.zmq_context = zmq.Context() self.zmq_cmd_socket = self.zmq_context.socket(zmq.PULL) @@ -48,15 +48,15 @@ class RemoteAgent: def main(): - logging.info("Configuring LeKiwiRobot") - robot_config = LeKiwiRobotConfig() - robot = LeKiwiRobot(robot_config) + logging.info("Configuring LeKiwi") + robot_config = LeKiwiConfig() + robot = LeKiwi(robot_config) - logging.info("Connecting LeKiwiRobot") + logging.info("Connecting LeKiwi") robot.connect() - logging.info("Starting RemoteAgent") - remote_agent = RemoteAgent() + logging.info("Starting HostAgent") + remote_agent = HostAgent() last_cmd_time = time.time() logging.info("Waiting for commands...") @@ -101,7 +101,7 @@ def main(): robot.disconnect() remote_agent.disconnect() - logging.info("Finished LeKiwiRobot cleanly") + logging.info("Finished LeKiwi cleanly") if __name__ == "__main__": diff --git a/lerobot/common/robots/utils.py b/lerobot/common/robots/utils.py index 19b7c1b9..86f67882 100644 --- a/lerobot/common/robots/utils.py +++ b/lerobot/common/robots/utils.py @@ -49,22 +49,22 @@ def make_robot_config(robot_type: str, **kwargs) -> RobotConfig: return Stretch3RobotConfig(**kwargs) elif robot_type == "lekiwi": - from .lekiwi.configuration_lekiwi import LeKiwiRobotConfig + from .lekiwi.config_lekiwi import LeKiwiConfig - return LeKiwiRobotConfig(**kwargs) + return LeKiwiConfig(**kwargs) else: raise ValueError(f"Robot type '{robot_type}' is not available.") def make_robot_from_config(config: RobotConfig): - from .lekiwi.configuration_lekiwi import LeKiwiRobotConfig + from .lekiwi.config_lekiwi import LeKiwiConfig from .manipulator import ManipulatorRobotConfig if isinstance(config, ManipulatorRobotConfig): from lerobot.common.robots.manipulator import ManipulatorRobot return ManipulatorRobot(config) - elif isinstance(config, LeKiwiRobotConfig): + elif isinstance(config, LeKiwiConfig): from lerobot.common.robots.mobile_manipulator import MobileManipulator return MobileManipulator(config) diff --git a/lerobot/common/teleoperators/keyboard/teleop_keyboard_app.py b/lerobot/common/teleoperators/keyboard/teleop_keyboard_app.py index 4f463814..6ecd78bd 100755 --- a/lerobot/common/teleoperators/keyboard/teleop_keyboard_app.py +++ b/lerobot/common/teleoperators/keyboard/teleop_keyboard_app.py @@ -21,7 +21,7 @@ def main(): i += 1 keyboard.disconnect() - logging.info("Finished LeKiwiRobot cleanly") + logging.info("Finished LeKiwi cleanly") if __name__ == "__main__":