mirror of
https://github.com/huggingface/lerobot.git
synced 2026-07-27 11:46:04 +00:00
feat(rollout): add smooth_handover flag to episodic strategy config
Follow-up to #3985, which added the same flag to the DAgger strategy. The episodic strategy's reset-phase handover had two gaps: - Non-actuated teleops could not skip the blocking follower slide at all. - Setting smooth_leader_to_follower_handover=false on an actuated teleop swapped which arm moves instead of skipping the handover. Add --strategy.smooth_handover (default true, existing behavior unchanged) as a master switch that skips the interpolation entirely, for clutch-style teleops that re-reference at the current robot pose on engage. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
committed by
Maxime Ellerbach
parent
0d383d09f2
commit
360e619e18
@@ -194,6 +194,7 @@ Teleop is optional — if omitted the robot holds its position during the reset
|
||||
| `--teleop.type` | Optional. Teleoperator to drive the robot during resets |
|
||||
| `--strategy.reset_to_initial_position` | Whether to reset the robot to its initial position between episodes |
|
||||
| `--strategy.smooth_leader_to_follower_handover` | Whether to turn on or off the leader -> follower smooth handover behavior. |
|
||||
| `--strategy.smooth_handover` | Smoothly hand control to the teleop at reset start (default: true). Disable for clutch-style teleops that re-reference at the current robot pose on engage |
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -149,6 +149,15 @@ class EpisodicStrategyConfig(RolloutStrategyConfig):
|
||||
# Note that leader -> follower handover is only supported when the leader has `send_feedback` capability.
|
||||
smooth_leader_to_follower_handover: bool = True
|
||||
|
||||
# Whether to turn on or off the smooth handover behavior at the start of the
|
||||
# reset phase: the leader is driven to the follower position (actuated
|
||||
# teleops, see `smooth_leader_to_follower_handover`), or the follower is
|
||||
# slid to the teleop pose (non-actuated teleops). Disable for clutch-style
|
||||
# teleoperators (e.g. VR controllers) that re-reference at the current robot
|
||||
# pose on engage: the handover is already continuous there, and the blocking
|
||||
# interpolation only delays the start of the reset phase.
|
||||
smooth_handover: bool = True
|
||||
|
||||
|
||||
@RolloutStrategyConfig.register_subclass("dagger")
|
||||
@dataclass
|
||||
|
||||
@@ -143,21 +143,25 @@ class EpisodicStrategy(RolloutStrategy):
|
||||
# position so the operator takes over without fighting the arm.
|
||||
# For non-actuated teleops: slide the follower to the teleop's current
|
||||
# pose instead, since the leader cannot be driven.
|
||||
obs = robot.get_observation()
|
||||
current_pos = {k: v for k, v in obs.items() if k.endswith(".pos")}
|
||||
if (
|
||||
teleop_supports_feedback(teleop)
|
||||
and self.config.smooth_leader_to_follower_handover
|
||||
):
|
||||
logger.info("Smooth handover: moving leader arm to follower position")
|
||||
teleop_smooth_move_to(teleop, current_pos, duration_s=2)
|
||||
teleop.disable_torque()
|
||||
else:
|
||||
logger.info("Smooth handover: sliding follower to teleop position")
|
||||
teleop_action = teleop.get_action()
|
||||
processed = ctx.processors.teleop_action_processor((teleop_action, obs))
|
||||
target = ctx.processors.robot_action_processor((processed, obs))
|
||||
follower_smooth_move_to(robot, current_pos, target, duration_s=1)
|
||||
# Disabled entirely with --strategy.smooth_handover=false (useful for
|
||||
# clutch-style teleops that re-reference at the current robot pose on
|
||||
# engage).
|
||||
if self.config.smooth_handover:
|
||||
obs = robot.get_observation()
|
||||
current_pos = {k: v for k, v in obs.items() if k.endswith(".pos")}
|
||||
if (
|
||||
teleop_supports_feedback(teleop)
|
||||
and self.config.smooth_leader_to_follower_handover
|
||||
):
|
||||
logger.info("Smooth handover: moving leader arm to follower position")
|
||||
teleop_smooth_move_to(teleop, current_pos, duration_s=2)
|
||||
teleop.disable_torque()
|
||||
else:
|
||||
logger.info("Smooth handover: sliding follower to teleop position")
|
||||
teleop_action = teleop.get_action()
|
||||
processed = ctx.processors.teleop_action_processor((teleop_action, obs))
|
||||
target = ctx.processors.robot_action_processor((processed, obs))
|
||||
follower_smooth_move_to(robot, current_pos, target, duration_s=1)
|
||||
|
||||
elif self.config.reset_to_initial_position:
|
||||
# No teleop: return the robot to its startup position.
|
||||
|
||||
Reference in New Issue
Block a user