From 26cb4614c961e6da04e4b83b6178331f4150650d Mon Sep 17 00:00:00 2001 From: Adil Zouitine Date: Sun, 20 Jul 2025 23:41:19 +0200 Subject: [PATCH] fix: calibration workflow when using robot_id with existing calibration files (#1528) --- src/lerobot/robots/koch_follower/koch_follower.py | 12 ++++++++++++ src/lerobot/robots/lekiwi/lekiwi.py | 12 ++++++++++++ src/lerobot/robots/so100_follower/so100_follower.py | 13 +++++++++++++ src/lerobot/robots/so101_follower/so101_follower.py | 13 +++++++++++++ .../teleoperators/koch_leader/koch_leader.py | 12 ++++++++++++ .../teleoperators/so100_leader/so100_leader.py | 13 +++++++++++++ .../teleoperators/so101_leader/so101_leader.py | 13 +++++++++++++ 7 files changed, 88 insertions(+) diff --git a/src/lerobot/robots/koch_follower/koch_follower.py b/src/lerobot/robots/koch_follower/koch_follower.py index 1cfc6cf0..b09b9b8e 100644 --- a/src/lerobot/robots/koch_follower/koch_follower.py +++ b/src/lerobot/robots/koch_follower/koch_follower.py @@ -94,6 +94,9 @@ class KochFollower(Robot): self.bus.connect() if not self.is_calibrated and calibrate: + logger.info( + "Mismatch between calibration values in the motor and the calibration file or no calibration file found" + ) self.calibrate() for cam in self.cameras.values(): @@ -107,6 +110,15 @@ class KochFollower(Robot): return self.bus.is_calibrated def calibrate(self) -> None: + if self.calibration: + # Calibration file exists, ask user whether to use it or run new calibration + user_input = input( + f"Press ENTER to use provided calibration file associated with the id {self.id}, or type 'c' and press ENTER to run calibration: " + ) + if user_input.strip().lower() != "c": + logger.info(f"Writing calibration file associated with the id {self.id} to the motors") + self.bus.write_calibration(self.calibration) + return logger.info(f"\nRunning calibration of {self}") self.bus.disable_torque() for motor in self.bus.motors: diff --git a/src/lerobot/robots/lekiwi/lekiwi.py b/src/lerobot/robots/lekiwi/lekiwi.py index ff1465d8..7004cc0f 100644 --- a/src/lerobot/robots/lekiwi/lekiwi.py +++ b/src/lerobot/robots/lekiwi/lekiwi.py @@ -114,6 +114,9 @@ class LeKiwi(Robot): self.bus.connect() if not self.is_calibrated and calibrate: + logger.info( + "Mismatch between calibration values in the motor and the calibration file or no calibration file found" + ) self.calibrate() for cam in self.cameras.values(): @@ -127,6 +130,15 @@ class LeKiwi(Robot): return self.bus.is_calibrated def calibrate(self) -> None: + if self.calibration: + # Calibration file exists, ask user whether to use it or run new calibration + user_input = input( + f"Press ENTER to use provided calibration file associated with the id {self.id}, or type 'c' and press ENTER to run calibration: " + ) + if user_input.strip().lower() != "c": + logger.info(f"Writing calibration file associated with the id {self.id} to the motors") + self.bus.write_calibration(self.calibration) + return logger.info(f"\nRunning calibration of {self}") motors = self.arm_motors + self.base_motors diff --git a/src/lerobot/robots/so100_follower/so100_follower.py b/src/lerobot/robots/so100_follower/so100_follower.py index e5da6bc1..ac52293f 100644 --- a/src/lerobot/robots/so100_follower/so100_follower.py +++ b/src/lerobot/robots/so100_follower/so100_follower.py @@ -92,6 +92,9 @@ class SO100Follower(Robot): self.bus.connect() if not self.is_calibrated and calibrate: + logger.info( + "Mismatch between calibration values in the motor and the calibration file or no calibration file found" + ) self.calibrate() for cam in self.cameras.values(): @@ -105,6 +108,16 @@ class SO100Follower(Robot): return self.bus.is_calibrated def calibrate(self) -> None: + if self.calibration: + # Calibration file exists, ask user whether to use it or run new calibration + user_input = input( + f"Press ENTER to use provided calibration file associated with the id {self.id}, or type 'c' and press ENTER to run calibration: " + ) + if user_input.strip().lower() != "c": + logger.info(f"Writing calibration file associated with the id {self.id} to the motors") + self.bus.write_calibration(self.calibration) + return + logger.info(f"\nRunning calibration of {self}") self.bus.disable_torque() for motor in self.bus.motors: diff --git a/src/lerobot/robots/so101_follower/so101_follower.py b/src/lerobot/robots/so101_follower/so101_follower.py index 3ae3c396..3ef66d70 100644 --- a/src/lerobot/robots/so101_follower/so101_follower.py +++ b/src/lerobot/robots/so101_follower/so101_follower.py @@ -92,6 +92,9 @@ class SO101Follower(Robot): self.bus.connect() if not self.is_calibrated and calibrate: + logger.info( + "Mismatch between calibration values in the motor and the calibration file or no calibration file found" + ) self.calibrate() for cam in self.cameras.values(): @@ -105,6 +108,16 @@ class SO101Follower(Robot): return self.bus.is_calibrated def calibrate(self) -> None: + if self.calibration: + # self.calibration is not empty here + user_input = input( + f"Press ENTER to use provided calibration file associated with the id {self.id}, or type 'c' and press ENTER to run calibration: " + ) + if user_input.strip().lower() != "c": + logger.info(f"Writing calibration file associated with the id {self.id} to the motors") + self.bus.write_calibration(self.calibration) + return + logger.info(f"\nRunning calibration of {self}") self.bus.disable_torque() for motor in self.bus.motors: diff --git a/src/lerobot/teleoperators/koch_leader/koch_leader.py b/src/lerobot/teleoperators/koch_leader/koch_leader.py index 8eb076fa..e0318cca 100644 --- a/src/lerobot/teleoperators/koch_leader/koch_leader.py +++ b/src/lerobot/teleoperators/koch_leader/koch_leader.py @@ -75,6 +75,9 @@ class KochLeader(Teleoperator): self.bus.connect() if not self.is_calibrated and calibrate: + logger.info( + "Mismatch between calibration values in the motor and the calibration file or no calibration file found" + ) self.calibrate() self.configure() @@ -85,6 +88,15 @@ class KochLeader(Teleoperator): return self.bus.is_calibrated def calibrate(self) -> None: + if self.calibration: + # Calibration file exists, ask user whether to use it or run new calibration + user_input = input( + f"Press ENTER to use provided calibration file associated with the id {self.id}, or type 'c' and press ENTER to run calibration: " + ) + if user_input.strip().lower() != "c": + logger.info(f"Writing calibration file associated with the id {self.id} to the motors") + self.bus.write_calibration(self.calibration) + return logger.info(f"\nRunning calibration of {self}") self.bus.disable_torque() for motor in self.bus.motors: diff --git a/src/lerobot/teleoperators/so100_leader/so100_leader.py b/src/lerobot/teleoperators/so100_leader/so100_leader.py index 18dad44d..a8f6d29b 100644 --- a/src/lerobot/teleoperators/so100_leader/so100_leader.py +++ b/src/lerobot/teleoperators/so100_leader/so100_leader.py @@ -72,6 +72,9 @@ class SO100Leader(Teleoperator): self.bus.connect() if not self.is_calibrated and calibrate: + logger.info( + "Mismatch between calibration values in the motor and the calibration file or no calibration file found" + ) self.calibrate() self.configure() @@ -82,6 +85,16 @@ class SO100Leader(Teleoperator): return self.bus.is_calibrated def calibrate(self) -> None: + if self.calibration: + # Calibration file exists, ask user whether to use it or run new calibration + user_input = input( + f"Press ENTER to use provided calibration file associated with the id {self.id}, or type 'c' and press ENTER to run calibration: " + ) + if user_input.strip().lower() != "c": + logger.info(f"Writing calibration file associated with the id {self.id} to the motors") + self.bus.write_calibration(self.calibration) + return + logger.info(f"\nRunning calibration of {self}") self.bus.disable_torque() for motor in self.bus.motors: diff --git a/src/lerobot/teleoperators/so101_leader/so101_leader.py b/src/lerobot/teleoperators/so101_leader/so101_leader.py index 2ce28d2e..15a363e3 100644 --- a/src/lerobot/teleoperators/so101_leader/so101_leader.py +++ b/src/lerobot/teleoperators/so101_leader/so101_leader.py @@ -73,6 +73,9 @@ class SO101Leader(Teleoperator): self.bus.connect() if not self.is_calibrated and calibrate: + logger.info( + "Mismatch between calibration values in the motor and the calibration file or no calibration file found" + ) self.calibrate() self.configure() @@ -83,6 +86,16 @@ class SO101Leader(Teleoperator): return self.bus.is_calibrated def calibrate(self) -> None: + if self.calibration: + # Calibration file exists, ask user whether to use it or run new calibration + user_input = input( + f"Press ENTER to use provided calibration file associated with the id {self.id}, or type 'c' and press ENTER to run calibration: " + ) + if user_input.strip().lower() != "c": + logger.info(f"Writing calibration file associated with the id {self.id} to the motors") + self.bus.write_calibration(self.calibration) + return + logger.info(f"\nRunning calibration of {self}") self.bus.disable_torque() for motor in self.bus.motors: