mirror of
https://github.com/huggingface/lerobot.git
synced 2026-07-16 22:41:49 +00:00
* renaming to episodic
* changing semantics of the docstring * fixing leader - follower handover disable torque * adding optionnal config to disable handover
This commit is contained in:
@@ -647,6 +647,6 @@ The `--strategy.type` flag selects the execution mode:
|
|||||||
- `sentry`: Continuous recording with auto-upload (useful for large-scale evaluation)
|
- `sentry`: Continuous recording with auto-upload (useful for large-scale evaluation)
|
||||||
- `highlight`: Ring buffer recording with keystroke save (useful for capturing interesting events)
|
- `highlight`: Ring buffer recording with keystroke save (useful for capturing interesting events)
|
||||||
- `dagger`: Human-in-the-loop data collection (see [HIL Data Collection](./hil_data_collection))
|
- `dagger`: Human-in-the-loop data collection (see [HIL Data Collection](./hil_data_collection))
|
||||||
- `legacy`: Episode-oriented policy recording with reset phases, mirrors the old `lerobot-record` inference path
|
- `episodic`: Episode-oriented policy recording with reset phases between episodes
|
||||||
|
|
||||||
All strategies support `--inference.type=rtc` for smooth execution with slow VLA models (Pi0, Pi0.5, SmolVLA).
|
All strategies support `--inference.type=rtc` for smooth execution with slow VLA models (Pi0, Pi0.5, SmolVLA).
|
||||||
|
|||||||
@@ -157,13 +157,13 @@ Foot pedal input is also supported via `--strategy.input_device=pedal`. Configur
|
|||||||
| `--strategy.input_device` | Input device: `keyboard` or `pedal` (default: keyboard) |
|
| `--strategy.input_device` | Input device: `keyboard` or `pedal` (default: keyboard) |
|
||||||
| `--teleop.type` | **Required.** Teleoperator type |
|
| `--teleop.type` | **Required.** Teleoperator type |
|
||||||
|
|
||||||
### Legacy (`--strategy.type=legacy`)
|
### Episodic (`--strategy.type=episodic`)
|
||||||
|
|
||||||
Episode-oriented recording that mirrors the old `lerobot-record` inference path. The policy drives the robot for each episode; an optional teleoperator can drive the robot during the reset phase between episodes.
|
Episode-oriented recording that mirrors the behavior of `lerobot-record`. The policy drives the robot for each episode; an optional teleoperator can drive the robot during the reset phase between episodes.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
lerobot-rollout \
|
lerobot-rollout \
|
||||||
--strategy.type=legacy \
|
--strategy.type=episodic \
|
||||||
--policy.path=${HF_USER}/my_policy \
|
--policy.path=${HF_USER}/my_policy \
|
||||||
--robot.type=so100_follower \
|
--robot.type=so100_follower \
|
||||||
--robot.port=/dev/ttyACM0 \
|
--robot.port=/dev/ttyACM0 \
|
||||||
@@ -186,12 +186,14 @@ Teleop is optional — if omitted the robot holds its position during the reset
|
|||||||
| `←` (left) | Discard episode and re-record it |
|
| `←` (left) | Discard episode and re-record it |
|
||||||
| `ESC` | Stop the recording session |
|
| `ESC` | Stop the recording session |
|
||||||
|
|
||||||
| Flag | Description |
|
| Flag | Description |
|
||||||
| -------------------------- | ------------------------------------------------------- |
|
| -------------------------------------------- | -------------------------------------------------------------------------- |
|
||||||
| `--dataset.num_episodes` | Number of episodes to record |
|
| `--dataset.num_episodes` | Number of episodes to record |
|
||||||
| `--dataset.episode_time_s` | Duration of each recording episode in seconds |
|
| `--dataset.episode_time_s` | Duration of each recording episode in seconds |
|
||||||
| `--dataset.reset_time_s` | Duration of the reset phase between episodes in seconds |
|
| `--dataset.reset_time_s` | Duration of the reset phase between episodes in seconds |
|
||||||
| `--teleop.type` | Optional. Teleoperator to drive the robot during resets |
|
| `--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_follower_handover` | Whether to turn on or off the leader -> follower smooth handover behavior. |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -248,6 +248,8 @@ def sanity_check_dataset_robot_compatibility(
|
|||||||
|
|
||||||
########################################################################################
|
########################################################################################
|
||||||
# Teleoperator smooth handover helpers
|
# Teleoperator smooth handover helpers
|
||||||
|
# NOTE(Maxime): These functions use minimal type hints to maintain compatibility with utils
|
||||||
|
# being a root module.
|
||||||
########################################################################################
|
########################################################################################
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -23,8 +23,8 @@ from .configs import (
|
|||||||
DAggerKeyboardConfig,
|
DAggerKeyboardConfig,
|
||||||
DAggerPedalConfig,
|
DAggerPedalConfig,
|
||||||
DAggerStrategyConfig,
|
DAggerStrategyConfig,
|
||||||
|
EpisodicStrategyConfig,
|
||||||
HighlightStrategyConfig,
|
HighlightStrategyConfig,
|
||||||
LegacyStrategyConfig,
|
|
||||||
RolloutConfig,
|
RolloutConfig,
|
||||||
RolloutStrategyConfig,
|
RolloutStrategyConfig,
|
||||||
SentryStrategyConfig,
|
SentryStrategyConfig,
|
||||||
@@ -50,8 +50,8 @@ from .inference import (
|
|||||||
from .strategies import (
|
from .strategies import (
|
||||||
BaseStrategy,
|
BaseStrategy,
|
||||||
DAggerStrategy,
|
DAggerStrategy,
|
||||||
|
EpisodicStrategy,
|
||||||
HighlightStrategy,
|
HighlightStrategy,
|
||||||
LegacyStrategy,
|
|
||||||
RolloutStrategy,
|
RolloutStrategy,
|
||||||
SentryStrategy,
|
SentryStrategy,
|
||||||
create_strategy,
|
create_strategy,
|
||||||
@@ -68,8 +68,8 @@ __all__ = [
|
|||||||
"HardwareContext",
|
"HardwareContext",
|
||||||
"HighlightStrategy",
|
"HighlightStrategy",
|
||||||
"HighlightStrategyConfig",
|
"HighlightStrategyConfig",
|
||||||
"LegacyStrategy",
|
"EpisodicStrategy",
|
||||||
"LegacyStrategyConfig",
|
"EpisodicStrategyConfig",
|
||||||
"InferenceEngine",
|
"InferenceEngine",
|
||||||
"InferenceEngineConfig",
|
"InferenceEngineConfig",
|
||||||
"PolicyContext",
|
"PolicyContext",
|
||||||
|
|||||||
@@ -121,16 +121,16 @@ class DAggerPedalConfig:
|
|||||||
upload: str = "KEY_C"
|
upload: str = "KEY_C"
|
||||||
|
|
||||||
|
|
||||||
@RolloutStrategyConfig.register_subclass("legacy")
|
@RolloutStrategyConfig.register_subclass("episodic")
|
||||||
@dataclass
|
@dataclass
|
||||||
class LegacyStrategyConfig(RolloutStrategyConfig):
|
class EpisodicStrategyConfig(RolloutStrategyConfig):
|
||||||
"""Episode-oriented recording that mirrors the pre-rollout lerobot-record behavior.
|
"""Episode-oriented recording that mirrors the behavior of ``lerobot-record``.
|
||||||
|
|
||||||
Records ``dataset.num_episodes`` episodes of maximum ``dataset.episode_time_s`` each.
|
Records ``dataset.num_episodes`` episodes of maximum ``dataset.episode_time_s`` each.
|
||||||
After each episode, runs ``dataset.reset_time_s`` seconds of reset time.
|
After each episode, runs ``dataset.reset_time_s`` seconds of reset time.
|
||||||
|
|
||||||
Keyboard controls (same as lerobot-record):
|
Keyboard controls:
|
||||||
Right arrow — end episode early
|
Right arrow — end current episode or reset phase early
|
||||||
Left arrow — discard current episode and re-record
|
Left arrow — discard current episode and re-record
|
||||||
Escape — stop recording session
|
Escape — stop recording session
|
||||||
|
|
||||||
@@ -143,7 +143,11 @@ class LegacyStrategyConfig(RolloutStrategyConfig):
|
|||||||
# When True (default), moves the robot back to the joint positions captured at startup.
|
# When True (default), moves the robot back to the joint positions captured at startup.
|
||||||
# Otherwise, leave the robot in its current position.
|
# Otherwise, leave the robot in its current position.
|
||||||
reset_to_initial_position: bool = True
|
reset_to_initial_position: bool = True
|
||||||
pass
|
|
||||||
|
# Whether to turn on or off the leader -> follower smooth handover behavior.
|
||||||
|
# When False, fallback to follower -> leader handover.
|
||||||
|
# Note that leader -> follower handover is only supported when the leader has `send_feedback` capability.
|
||||||
|
smooth_leader_follower_handover: bool = True
|
||||||
|
|
||||||
|
|
||||||
@RolloutStrategyConfig.register_subclass("dagger")
|
@RolloutStrategyConfig.register_subclass("dagger")
|
||||||
@@ -259,7 +263,7 @@ class RolloutConfig:
|
|||||||
SentryStrategyConfig,
|
SentryStrategyConfig,
|
||||||
HighlightStrategyConfig,
|
HighlightStrategyConfig,
|
||||||
DAggerStrategyConfig,
|
DAggerStrategyConfig,
|
||||||
LegacyStrategyConfig,
|
EpisodicStrategyConfig,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
if needs_dataset and (self.dataset is None or not self.dataset.repo_id):
|
if needs_dataset and (self.dataset is None or not self.dataset.repo_id):
|
||||||
|
|||||||
@@ -17,9 +17,9 @@
|
|||||||
from .base import BaseStrategy
|
from .base import BaseStrategy
|
||||||
from .core import RolloutStrategy, estimate_max_episode_seconds, safe_push_to_hub, send_next_action
|
from .core import RolloutStrategy, estimate_max_episode_seconds, safe_push_to_hub, send_next_action
|
||||||
from .dagger import DAggerEvents, DAggerPhase, DAggerStrategy
|
from .dagger import DAggerEvents, DAggerPhase, DAggerStrategy
|
||||||
|
from .episodic import EpisodicStrategy
|
||||||
from .factory import create_strategy
|
from .factory import create_strategy
|
||||||
from .highlight import HighlightStrategy
|
from .highlight import HighlightStrategy
|
||||||
from .legacy import LegacyStrategy
|
|
||||||
from .sentry import SentryStrategy
|
from .sentry import SentryStrategy
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
@@ -28,7 +28,7 @@ __all__ = [
|
|||||||
"DAggerPhase",
|
"DAggerPhase",
|
||||||
"DAggerStrategy",
|
"DAggerStrategy",
|
||||||
"HighlightStrategy",
|
"HighlightStrategy",
|
||||||
"LegacyStrategy",
|
"EpisodicStrategy",
|
||||||
"RolloutStrategy",
|
"RolloutStrategy",
|
||||||
"SentryStrategy",
|
"SentryStrategy",
|
||||||
"create_strategy",
|
"create_strategy",
|
||||||
|
|||||||
+14
-15
@@ -12,17 +12,15 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
"""Legacy rollout strategy: policy-driven multi-episode recording with reset phases.
|
"""Episodic rollout strategy: mirrors the behavior of ``lerobot-record``.
|
||||||
|
|
||||||
Mirrors the pre-rollout ``lerobot-record`` inference path:
|
|
||||||
|
|
||||||
- Policy drives the robot during each recording episode.
|
- Policy drives the robot during each recording episode.
|
||||||
- An optional teleoperator can drive the robot during reset phases so the
|
- An optional teleoperator can drive the robot during reset phases so the
|
||||||
operator can bring the environment back to its starting configuration.
|
operator can bring the environment back to its starting configuration.
|
||||||
If no teleop is connected the robot stays in its current position.
|
If no teleop is connected the robot stays in its current position.
|
||||||
- Keyboard controls (identical to the old lerobot-record):
|
- Keyboard controls:
|
||||||
|
|
||||||
Right arrow — end the current episode early
|
Right arrow — end the current episode or reset phase early
|
||||||
Left arrow — discard the current episode and re-record it
|
Left arrow — discard the current episode and re-record it
|
||||||
Escape — stop the recording session
|
Escape — stop the recording session
|
||||||
|
|
||||||
@@ -49,15 +47,15 @@ from lerobot.utils.robot_utils import precise_sleep
|
|||||||
from lerobot.utils.utils import log_say
|
from lerobot.utils.utils import log_say
|
||||||
from lerobot.utils.visualization_utils import log_rerun_data
|
from lerobot.utils.visualization_utils import log_rerun_data
|
||||||
|
|
||||||
from ..configs import LegacyStrategyConfig
|
from ..configs import EpisodicStrategyConfig
|
||||||
from ..context import RolloutContext
|
from ..context import RolloutContext
|
||||||
from .core import RolloutStrategy, safe_push_to_hub, send_next_action
|
from .core import RolloutStrategy, safe_push_to_hub, send_next_action
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class LegacyStrategy(RolloutStrategy):
|
class EpisodicStrategy(RolloutStrategy):
|
||||||
"""Policy-driven multi-episode recording (mirrors old lerobot-record inference path).
|
"""Policy-driven multi-episode recording, mirrors the behavior of ``lerobot-record``.
|
||||||
|
|
||||||
Each recording episode runs the policy for maximum ``dataset.episode_time_s``
|
Each recording episode runs the policy for maximum ``dataset.episode_time_s``
|
||||||
seconds, recording every frame. A reset phase of ``dataset.reset_time_s``
|
seconds, recording every frame. A reset phase of ``dataset.reset_time_s``
|
||||||
@@ -69,14 +67,14 @@ class LegacyStrategy(RolloutStrategy):
|
|||||||
the start of each recording episode.
|
the start of each recording episode.
|
||||||
|
|
||||||
Keyboard events:
|
Keyboard events:
|
||||||
right arrow → exit current episode early
|
right arrow → end current episode or reset phase early
|
||||||
left arrow → discard & re-record current episode
|
left arrow → discard & re-record current episode
|
||||||
ESC → stop the session
|
ESC → stop the session
|
||||||
"""
|
"""
|
||||||
|
|
||||||
config: LegacyStrategyConfig
|
config: EpisodicStrategyConfig
|
||||||
|
|
||||||
def __init__(self, config: LegacyStrategyConfig) -> None:
|
def __init__(self, config: EpisodicStrategyConfig) -> None:
|
||||||
super().__init__(config)
|
super().__init__(config)
|
||||||
self._listener = None
|
self._listener = None
|
||||||
self._events: dict | None = None
|
self._events: dict | None = None
|
||||||
@@ -85,7 +83,7 @@ class LegacyStrategy(RolloutStrategy):
|
|||||||
"""Start the inference engine and attach the keyboard listener."""
|
"""Start the inference engine and attach the keyboard listener."""
|
||||||
self._init_engine(ctx)
|
self._init_engine(ctx)
|
||||||
self._listener, self._events = init_keyboard_listener()
|
self._listener, self._events = init_keyboard_listener()
|
||||||
logger.info("Legacy strategy ready")
|
logger.info("Episodic strategy ready")
|
||||||
|
|
||||||
def run(self, ctx: RolloutContext) -> None:
|
def run(self, ctx: RolloutContext) -> None:
|
||||||
"""Main multi-episode recording loop."""
|
"""Main multi-episode recording loop."""
|
||||||
@@ -150,7 +148,8 @@ class LegacyStrategy(RolloutStrategy):
|
|||||||
current_pos = {k: v for k, v in obs.items() if k.endswith(".pos")}
|
current_pos = {k: v for k, v in obs.items() if k.endswith(".pos")}
|
||||||
if teleop_supports_feedback(teleop):
|
if teleop_supports_feedback(teleop):
|
||||||
logger.info("Smooth handover: moving leader arm to follower position")
|
logger.info("Smooth handover: moving leader arm to follower position")
|
||||||
teleop_smooth_move_to(teleop, current_pos, duration_s=1)
|
teleop_smooth_move_to(teleop, current_pos, duration_s=2)
|
||||||
|
teleop.disable_torque()
|
||||||
else:
|
else:
|
||||||
logger.info("Smooth handover: sliding follower to teleop position")
|
logger.info("Smooth handover: sliding follower to teleop position")
|
||||||
teleop_action = teleop.get_action()
|
teleop_action = teleop.get_action()
|
||||||
@@ -191,7 +190,7 @@ class LegacyStrategy(RolloutStrategy):
|
|||||||
# Save any frames buffered in the current episode so an unexpected
|
# Save any frames buffered in the current episode so an unexpected
|
||||||
# exception or KeyboardInterrupt does not silently drop recorded data.
|
# exception or KeyboardInterrupt does not silently drop recorded data.
|
||||||
# suppress: save_episode raises if the buffer is empty (nothing to lose).
|
# suppress: save_episode raises if the buffer is empty (nothing to lose).
|
||||||
logger.info("Legacy control loop ended — saving any in-progress episode")
|
logger.info("Episodic control loop ended — saving any in-progress episode")
|
||||||
with contextlib.suppress(Exception):
|
with contextlib.suppress(Exception):
|
||||||
dataset.save_episode()
|
dataset.save_episode()
|
||||||
|
|
||||||
@@ -330,4 +329,4 @@ class LegacyStrategy(RolloutStrategy):
|
|||||||
return_to_initial_position=cfg.return_to_initial_position,
|
return_to_initial_position=cfg.return_to_initial_position,
|
||||||
)
|
)
|
||||||
log_say("Exiting", play_sounds)
|
log_say("Exiting", play_sounds)
|
||||||
logger.info("Legacy strategy teardown complete")
|
logger.info("Episodic strategy teardown complete")
|
||||||
@@ -21,8 +21,8 @@ from typing import TYPE_CHECKING
|
|||||||
from .base import BaseStrategy
|
from .base import BaseStrategy
|
||||||
from .core import RolloutStrategy
|
from .core import RolloutStrategy
|
||||||
from .dagger import DAggerStrategy
|
from .dagger import DAggerStrategy
|
||||||
|
from .episodic import EpisodicStrategy
|
||||||
from .highlight import HighlightStrategy
|
from .highlight import HighlightStrategy
|
||||||
from .legacy import LegacyStrategy
|
|
||||||
from .sentry import SentryStrategy
|
from .sentry import SentryStrategy
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
@@ -43,8 +43,8 @@ def create_strategy(config: RolloutStrategyConfig) -> RolloutStrategy:
|
|||||||
return HighlightStrategy(config)
|
return HighlightStrategy(config)
|
||||||
if config.type == "dagger":
|
if config.type == "dagger":
|
||||||
return DAggerStrategy(config)
|
return DAggerStrategy(config)
|
||||||
if config.type == "legacy":
|
if config.type == "episodic":
|
||||||
return LegacyStrategy(config)
|
return EpisodicStrategy(config)
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
f"Unknown strategy type '{config.type}'. Available: base, sentry, highlight, dagger, legacy"
|
f"Unknown strategy type '{config.type}'. Available: base, sentry, highlight, dagger, episodic"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ Strategies
|
|||||||
--strategy.type=sentry Continuous recording with auto-upload
|
--strategy.type=sentry Continuous recording with auto-upload
|
||||||
--strategy.type=highlight Ring buffer + keystroke save
|
--strategy.type=highlight Ring buffer + keystroke save
|
||||||
--strategy.type=dagger Human-in-the-loop (DAgger / RaC)
|
--strategy.type=dagger Human-in-the-loop (DAgger / RaC)
|
||||||
--strategy.type=legacy Episode oriented recording, mirrors old lerobot-record
|
--strategy.type=episodic Episode-oriented recording with reset phases
|
||||||
|
|
||||||
Inference backends
|
Inference backends
|
||||||
------------------
|
------------------
|
||||||
@@ -112,15 +112,15 @@ Usage examples
|
|||||||
--display_data=true \\
|
--display_data=true \\
|
||||||
--use_torch_compile=true
|
--use_torch_compile=true
|
||||||
|
|
||||||
# Legacy mode — episode-oriented recording, mirrors old lerobot-record
|
# Episodic mode — episode-oriented recording with reset phases
|
||||||
lerobot-rollout \\
|
lerobot-rollout \\
|
||||||
--strategy.type=legacy \\
|
--strategy.type=episodic \\
|
||||||
--policy.path=user/my_policy \\
|
--policy.path=user/my_policy \\
|
||||||
--robot.type=so100_follower \\
|
--robot.type=so100_follower \\
|
||||||
--robot.port=/dev/ttyACM0 \\
|
--robot.port=/dev/ttyACM0 \\
|
||||||
--teleop.type=so100_leader \\
|
--teleop.type=so100_leader \\
|
||||||
--teleop.port=/dev/ttyACM1 \\
|
--teleop.port=/dev/ttyACM1 \\
|
||||||
--dataset.repo_id=user/rollout_legacy_data \\
|
--dataset.repo_id=user/rollout_episodic_data \\
|
||||||
--dataset.num_episodes=20 \\
|
--dataset.num_episodes=20 \\
|
||||||
--dataset.single_task="Grab the cube"
|
--dataset.single_task="Grab the cube"
|
||||||
|
|
||||||
|
|||||||
@@ -59,8 +59,8 @@ def test_strategy_config_types():
|
|||||||
from lerobot.rollout import (
|
from lerobot.rollout import (
|
||||||
BaseStrategyConfig,
|
BaseStrategyConfig,
|
||||||
DAggerStrategyConfig,
|
DAggerStrategyConfig,
|
||||||
|
EpisodicStrategyConfig,
|
||||||
HighlightStrategyConfig,
|
HighlightStrategyConfig,
|
||||||
LegacyStrategyConfig,
|
|
||||||
SentryStrategyConfig,
|
SentryStrategyConfig,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -68,7 +68,7 @@ def test_strategy_config_types():
|
|||||||
assert SentryStrategyConfig().type == "sentry"
|
assert SentryStrategyConfig().type == "sentry"
|
||||||
assert HighlightStrategyConfig().type == "highlight"
|
assert HighlightStrategyConfig().type == "highlight"
|
||||||
assert DAggerStrategyConfig().type == "dagger"
|
assert DAggerStrategyConfig().type == "dagger"
|
||||||
assert LegacyStrategyConfig().type == "legacy"
|
assert EpisodicStrategyConfig().type == "episodic"
|
||||||
|
|
||||||
|
|
||||||
def test_dagger_config_invalid_input_device():
|
def test_dagger_config_invalid_input_device():
|
||||||
@@ -205,8 +205,8 @@ def test_create_strategy_dispatches():
|
|||||||
BaseStrategyConfig,
|
BaseStrategyConfig,
|
||||||
DAggerStrategy,
|
DAggerStrategy,
|
||||||
DAggerStrategyConfig,
|
DAggerStrategyConfig,
|
||||||
LegacyStrategy,
|
EpisodicStrategy,
|
||||||
LegacyStrategyConfig,
|
EpisodicStrategyConfig,
|
||||||
SentryStrategy,
|
SentryStrategy,
|
||||||
SentryStrategyConfig,
|
SentryStrategyConfig,
|
||||||
create_strategy,
|
create_strategy,
|
||||||
@@ -215,7 +215,7 @@ def test_create_strategy_dispatches():
|
|||||||
assert isinstance(create_strategy(BaseStrategyConfig()), BaseStrategy)
|
assert isinstance(create_strategy(BaseStrategyConfig()), BaseStrategy)
|
||||||
assert isinstance(create_strategy(SentryStrategyConfig()), SentryStrategy)
|
assert isinstance(create_strategy(SentryStrategyConfig()), SentryStrategy)
|
||||||
assert isinstance(create_strategy(DAggerStrategyConfig()), DAggerStrategy)
|
assert isinstance(create_strategy(DAggerStrategyConfig()), DAggerStrategy)
|
||||||
assert isinstance(create_strategy(LegacyStrategyConfig()), LegacyStrategy)
|
assert isinstance(create_strategy(EpisodicStrategyConfig()), EpisodicStrategy)
|
||||||
|
|
||||||
|
|
||||||
def test_create_strategy_unknown_raises():
|
def test_create_strategy_unknown_raises():
|
||||||
|
|||||||
Reference in New Issue
Block a user