Rename Lekiwi files & classes

This commit is contained in:
Simon Alibert 2025-04-04 11:44:35 +02:00 committed by Steven Palma
parent 2f769f1ff6
commit ded92d860d
No known key found for this signature in database
9 changed files with 45 additions and 47 deletions

View File

@ -184,11 +184,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.
@ -271,7 +271,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.
@ -434,7 +434,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.

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 wheels 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 wheels 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 = {}

View File

@ -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__":

View File

@ -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__":

View File

@ -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)

View File

@ -21,7 +21,7 @@ def main():
i += 1
keyboard.disconnect()
logging.info("Finished LeKiwiRobot cleanly")
logging.info("Finished LeKiwi cleanly")
if __name__ == "__main__":