mirror of
https://github.com/huggingface/lerobot.git
synced 2026-07-27 19:56:09 +00:00
feat(rollout): add smooth_handover flag to DAgger strategy config
The DAgger phase transitions run blocking smooth handovers: on pause the leader is driven to the follower (~2 s), and on correction start the follower is slid to the teleop pose (~1 s), both inside the record loop. For clutch-style teleoperators (e.g. VR controllers) that re-reference their command frame at the current robot pose on engage, the handover is already continuous — the interpolation only delays the start of the correction and eats its first frames. Add --strategy.smooth_handover (default true, existing behavior unchanged) to let such setups skip it, mirroring the episodic strategy's smooth_leader_to_follower_handover flag. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
committed by
Maxime Ellerbach
parent
0d383d09f2
commit
124d03608c
@@ -155,6 +155,7 @@ Foot pedal input is also supported via `--strategy.input_device=pedal`. Configur
|
|||||||
| `--strategy.record_autonomous` | Record autonomous frames too (default: false) |
|
| `--strategy.record_autonomous` | Record autonomous frames too (default: false) |
|
||||||
| `--strategy.upload_every_n_episodes` | Push to Hub every N episodes (default: 5) |
|
| `--strategy.upload_every_n_episodes` | Push to Hub every N episodes (default: 5) |
|
||||||
| `--strategy.input_device` | Input device: `keyboard` or `pedal` (default: keyboard) |
|
| `--strategy.input_device` | Input device: `keyboard` or `pedal` (default: keyboard) |
|
||||||
|
| `--strategy.smooth_handover` | Smoothly hand control over at pause / correction start (default: true). Disable for clutch-style teleops that re-reference at the current robot pose on engage |
|
||||||
| `--teleop.type` | **Required.** Teleoperator type |
|
| `--teleop.type` | **Required.** Teleoperator type |
|
||||||
|
|
||||||
### Episodic (`--strategy.type=episodic`)
|
### Episodic (`--strategy.type=episodic`)
|
||||||
|
|||||||
@@ -180,6 +180,14 @@ class DAggerStrategyConfig(RolloutStrategyConfig):
|
|||||||
# Target video file size in MB for episode rotation (record_autonomous
|
# Target video file size in MB for episode rotation (record_autonomous
|
||||||
# mode only). Defaults to DEFAULT_VIDEO_FILE_SIZE_IN_MB when None.
|
# mode only). Defaults to DEFAULT_VIDEO_FILE_SIZE_IN_MB when None.
|
||||||
target_video_file_size_mb: int | None = None
|
target_video_file_size_mb: int | None = None
|
||||||
|
# Whether to turn on or off the smooth handover behavior at phase transitions:
|
||||||
|
# the leader is driven to the follower position on pause (teleops with
|
||||||
|
# `send_feedback` capability), and the follower is slid to the teleop pose when
|
||||||
|
# a correction starts (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 correction.
|
||||||
|
smooth_handover: bool = True
|
||||||
input_device: str = "keyboard"
|
input_device: str = "keyboard"
|
||||||
keyboard: DAggerKeyboardConfig = field(default_factory=DAggerKeyboardConfig)
|
keyboard: DAggerKeyboardConfig = field(default_factory=DAggerKeyboardConfig)
|
||||||
pedal: DAggerPedalConfig = field(default_factory=DAggerPedalConfig)
|
pedal: DAggerPedalConfig = field(default_factory=DAggerPedalConfig)
|
||||||
|
|||||||
@@ -623,8 +623,8 @@ class DAggerStrategy(RolloutStrategy):
|
|||||||
# State-machine transition side-effects
|
# State-machine transition side-effects
|
||||||
# ------------------------------------------------------------------
|
# ------------------------------------------------------------------
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _apply_transition(
|
def _apply_transition(
|
||||||
|
self,
|
||||||
old_phase: DAggerPhase,
|
old_phase: DAggerPhase,
|
||||||
new_phase: DAggerPhase,
|
new_phase: DAggerPhase,
|
||||||
engine,
|
engine,
|
||||||
@@ -634,6 +634,10 @@ class DAggerStrategy(RolloutStrategy):
|
|||||||
) -> None:
|
) -> None:
|
||||||
"""Execute side-effects for a validated phase transition, including smooth handovers.
|
"""Execute side-effects for a validated phase transition, including smooth handovers.
|
||||||
|
|
||||||
|
The smooth handovers below can be disabled with
|
||||||
|
``--strategy.smooth_handover=false`` (useful for clutch-style teleops
|
||||||
|
that re-reference at the current robot pose on engage).
|
||||||
|
|
||||||
AUTONOMOUS -> PAUSED (actuated teleop):
|
AUTONOMOUS -> PAUSED (actuated teleop):
|
||||||
Pause the engine, then drive the leader arm to the follower's last
|
Pause the engine, then drive the leader arm to the follower's last
|
||||||
commanded position so the operator takes over without a jerk.
|
commanded position so the operator takes over without a jerk.
|
||||||
@@ -657,7 +661,7 @@ class DAggerStrategy(RolloutStrategy):
|
|||||||
logger.info("Pausing engine - robot holds position")
|
logger.info("Pausing engine - robot holds position")
|
||||||
engine.pause()
|
engine.pause()
|
||||||
|
|
||||||
if teleop_supports_feedback(teleop) and prev_action is not None:
|
if self.config.smooth_handover and teleop_supports_feedback(teleop) and prev_action is not None:
|
||||||
# TODO(Maxime): prev_action is in robot action key space (output of robot_action_processor).
|
# TODO(Maxime): prev_action is in robot action key space (output of robot_action_processor).
|
||||||
# send_feedback expects teleop feedback key space. For homogeneous setups (e.g. SO-101
|
# send_feedback expects teleop feedback key space. For homogeneous setups (e.g. SO-101
|
||||||
# leader + SO-101 follower) the keys are identical so this works. If the processor pipeline
|
# leader + SO-101 follower) the keys are identical so this works. If the processor pipeline
|
||||||
@@ -668,7 +672,11 @@ class DAggerStrategy(RolloutStrategy):
|
|||||||
|
|
||||||
elif old_phase == DAggerPhase.PAUSED and new_phase == DAggerPhase.CORRECTING:
|
elif old_phase == DAggerPhase.PAUSED and new_phase == DAggerPhase.CORRECTING:
|
||||||
logger.info("Entering correction mode - human teleop control")
|
logger.info("Entering correction mode - human teleop control")
|
||||||
if not teleop_supports_feedback(teleop) and prev_action is not None:
|
if (
|
||||||
|
self.config.smooth_handover
|
||||||
|
and not teleop_supports_feedback(teleop)
|
||||||
|
and prev_action is not None
|
||||||
|
):
|
||||||
logger.info("Smooth handover: sliding follower to teleop position")
|
logger.info("Smooth handover: sliding follower to teleop position")
|
||||||
obs = robot.get_observation()
|
obs = robot.get_observation()
|
||||||
teleop_action = teleop.get_action()
|
teleop_action = teleop.get_action()
|
||||||
|
|||||||
Reference in New Issue
Block a user