From e2957d778397fd70f7200fb69763238dc1aaa132 Mon Sep 17 00:00:00 2001 From: Steven Palma Date: Tue, 6 Jan 2026 20:09:43 +0100 Subject: [PATCH] fix: precise_sleep is never called with negative value (#2757) --- docs/source/envhub_leisaac.mdx | 2 +- docs/source/il_robots.mdx | 2 +- examples/backward_compatibility/replay.py | 2 +- examples/phone_to_so100/replay.py | 2 +- examples/so100_to_so100_EE/replay.py | 2 +- src/lerobot/rl/actor.py | 2 +- src/lerobot/rl/gym_manipulator.py | 6 +++--- src/lerobot/scripts/lerobot_record.py | 2 +- src/lerobot/scripts/lerobot_replay.py | 2 +- src/lerobot/scripts/lerobot_teleoperate.py | 2 +- 10 files changed, 12 insertions(+), 12 deletions(-) diff --git a/docs/source/envhub_leisaac.mdx b/docs/source/envhub_leisaac.mdx index ff848d415..5cf4a0e45 100644 --- a/docs/source/envhub_leisaac.mdx +++ b/docs/source/envhub_leisaac.mdx @@ -196,7 +196,7 @@ def teleop_loop(teleop: Teleoperator, env: gym.Env, fps: int): obs, info = env.reset() dt_s = time.perf_counter() - loop_start - precise_sleep(1 / fps - dt_s) + precise_sleep(max(1 / fps - dt_s, 0.0)) loop_s = time.perf_counter() - loop_start print(f"\ntime: {loop_s * 1e3:.2f}ms ({1 / loop_s:.0f} Hz)") diff --git a/docs/source/il_robots.mdx b/docs/source/il_robots.mdx index 0bc1ca681..eb779d2b1 100644 --- a/docs/source/il_robots.mdx +++ b/docs/source/il_robots.mdx @@ -432,7 +432,7 @@ for idx in range(dataset.num_frames): } robot.send_action(action) - precise_sleep(1.0 / dataset.fps - (time.perf_counter() - t0)) + precise_sleep(max(1.0 / dataset.fps - (time.perf_counter() - t0), 0.0)) robot.disconnect() ``` diff --git a/examples/backward_compatibility/replay.py b/examples/backward_compatibility/replay.py index ed52a24c9..85f3ecef7 100644 --- a/examples/backward_compatibility/replay.py +++ b/examples/backward_compatibility/replay.py @@ -97,7 +97,7 @@ def replay(cfg: ReplayConfig): robot.send_action(action) dt_s = time.perf_counter() - start_episode_t - precise_sleep(1 / dataset.fps - dt_s) + precise_sleep(max(1 / dataset.fps - dt_s, 0.0)) robot.disconnect() diff --git a/examples/phone_to_so100/replay.py b/examples/phone_to_so100/replay.py index a7b18a53c..ab6ce3ced 100644 --- a/examples/phone_to_so100/replay.py +++ b/examples/phone_to_so100/replay.py @@ -96,7 +96,7 @@ def main(): # Send action to robot _ = robot.send_action(joint_action) - precise_sleep(1.0 / dataset.fps - (time.perf_counter() - t0)) + precise_sleep(max(1.0 / dataset.fps - (time.perf_counter() - t0), 0.0)) # Clean up robot.disconnect() diff --git a/examples/so100_to_so100_EE/replay.py b/examples/so100_to_so100_EE/replay.py index 9951b139d..59c524078 100644 --- a/examples/so100_to_so100_EE/replay.py +++ b/examples/so100_to_so100_EE/replay.py @@ -97,7 +97,7 @@ def main(): # Send action to robot _ = robot.send_action(joint_action) - precise_sleep(1.0 / dataset.fps - (time.perf_counter() - t0)) + precise_sleep(max(1.0 / dataset.fps - (time.perf_counter() - t0), 0.0)) # Clean up robot.disconnect() diff --git a/src/lerobot/rl/actor.py b/src/lerobot/rl/actor.py index 13fd66507..641a21d03 100644 --- a/src/lerobot/rl/actor.py +++ b/src/lerobot/rl/actor.py @@ -398,7 +398,7 @@ def act_with_policy( if cfg.env.fps is not None: dt_time = time.perf_counter() - start_time - precise_sleep(1 / cfg.env.fps - dt_time) + precise_sleep(max(1 / cfg.env.fps - dt_time, 0.0)) # Communication Functions - Group all gRPC/messaging functions diff --git a/src/lerobot/rl/gym_manipulator.py b/src/lerobot/rl/gym_manipulator.py index ad1fdf55f..7bc74a959 100644 --- a/src/lerobot/rl/gym_manipulator.py +++ b/src/lerobot/rl/gym_manipulator.py @@ -238,7 +238,7 @@ class RobotEnv(gym.Env): reset_follower_position(self.robot, np.array(self.reset_pose)) log_say("Reset the environment done.", play_sounds=True) - precise_sleep(self.reset_time_s - (time.perf_counter() - start_time)) + precise_sleep(max(self.reset_time_s - (time.perf_counter() - start_time), 0.0)) super().reset(seed=seed, options=options) @@ -713,7 +713,7 @@ def control_loop( transition = env_processor(transition) # Maintain fps timing - precise_sleep(dt - (time.perf_counter() - step_start_time)) + precise_sleep(max(dt - (time.perf_counter() - step_start_time), 0.0)) if dataset is not None and cfg.dataset.push_to_hub: logging.info("Pushing dataset to hub") @@ -745,7 +745,7 @@ def replay_trajectory( ) transition = action_processor(transition) env.step(transition[TransitionKey.ACTION]) - precise_sleep(1 / cfg.env.fps - (time.perf_counter() - start_time)) + precise_sleep(max(1 / cfg.env.fps - (time.perf_counter() - start_time), 0.0)) @parser.wrap() diff --git a/src/lerobot/scripts/lerobot_record.py b/src/lerobot/scripts/lerobot_record.py index eafd32ace..62bf21653 100644 --- a/src/lerobot/scripts/lerobot_record.py +++ b/src/lerobot/scripts/lerobot_record.py @@ -374,7 +374,7 @@ def record_loop( log_rerun_data(observation=obs_processed, action=action_values) dt_s = time.perf_counter() - start_loop_t - precise_sleep(1 / fps - dt_s) + precise_sleep(max(1 / fps - dt_s, 0.0)) timestamp = time.perf_counter() - start_episode_t diff --git a/src/lerobot/scripts/lerobot_replay.py b/src/lerobot/scripts/lerobot_replay.py index d5808c768..5cde4251c 100644 --- a/src/lerobot/scripts/lerobot_replay.py +++ b/src/lerobot/scripts/lerobot_replay.py @@ -123,7 +123,7 @@ def replay(cfg: ReplayConfig): _ = robot.send_action(processed_action) dt_s = time.perf_counter() - start_episode_t - precise_sleep(1 / dataset.fps - dt_s) + precise_sleep(max(1 / dataset.fps - dt_s, 0.0)) robot.disconnect() diff --git a/src/lerobot/scripts/lerobot_teleoperate.py b/src/lerobot/scripts/lerobot_teleoperate.py index bf722d6f1..9866e7629 100644 --- a/src/lerobot/scripts/lerobot_teleoperate.py +++ b/src/lerobot/scripts/lerobot_teleoperate.py @@ -177,7 +177,7 @@ def teleop_loop( move_cursor_up(len(robot_action_to_send) + 3) dt_s = time.perf_counter() - loop_start - precise_sleep(1 / fps - dt_s) + precise_sleep(max(1 / fps - dt_s, 0.0)) loop_s = time.perf_counter() - loop_start print(f"Teleop loop time: {loop_s * 1e3:.2f}ms ({1 / loop_s:.0f} Hz)") move_cursor_up(1)