diff --git a/src/lerobot/rollout/context.py b/src/lerobot/rollout/context.py index d36429dae..f07ed7e2f 100644 --- a/src/lerobot/rollout/context.py +++ b/src/lerobot/rollout/context.py @@ -43,6 +43,7 @@ from lerobot.processor import ( make_default_processors, rename_stats, ) +from lerobot.processor.relative_action_processor import RelativeActionsProcessorStep from lerobot.robots import make_robot_from_config from lerobot.teleoperators import Teleoperator, make_teleoperator_from_config from lerobot.utils.feature_utils import combine_feature_dicts, hw_to_dataset_features @@ -51,6 +52,7 @@ from .configs import BaseStrategyConfig, DAggerStrategyConfig, RolloutConfig from .inference import ( InferenceEngine, RTCInferenceConfig, + SyncInferenceConfig, create_inference_engine, ) from .robot_wrapper import ThreadSafeRobot @@ -391,6 +393,15 @@ def build_rollout_context( }, ) + if isinstance(cfg.inference, SyncInferenceConfig) and any( + isinstance(step, RelativeActionsProcessorStep) and step.enabled + for step in getattr(preprocessor, "steps", ()) + ): + raise NotImplementedError( + "SyncInferenceEngine does not support policies with relative actions for now." + "Use --inference.type=rtc or remove relative action processor steps from the policy pipeline." + ) + # --- 7. Inference strategy (needs policy + pre/post + hardware) -- logger.info( "Creating inference engine (type=%s)...", diff --git a/src/lerobot/rollout/inference/sync.py b/src/lerobot/rollout/inference/sync.py index aaed0b356..ac8e6537f 100644 --- a/src/lerobot/rollout/inference/sync.py +++ b/src/lerobot/rollout/inference/sync.py @@ -31,6 +31,20 @@ from .base import InferenceEngine logger = logging.getLogger(__name__) +# TODO(Steven): support relative-action policies. The per-tick flow refreshes +# ``RelativeActionsProcessorStep._last_state`` every call, so cached chunk +# actions popped on later ticks get reanchored to the *current* robot state and +# absolute targets drift through the chunk. Rejected at context-build time for +# now; RTC postprocesses the whole chunk and is unaffected. +# +# Candidate fix: +# Drive the policy via ``predict_action_chunk`` and serve a local FIFO of postprocessed actions. +# Eliminates drift by construction and saves per-tick pre/post work, but bypasses ``select_action`` +# — needs fallbacks for SAC (raises), ACT temporal ensembling (ensembler lives in ``select_action``), +# and Diffusion-family (obs-history queues populated as a side effect of ``select_action``). +# Not yet implemented for sake of keeping sync engine simple and focused on the most common use case. + + class SyncInferenceEngine(InferenceEngine): """Inline synchronous inference: compute one action per call.