Skip to content

Commit 80adbe8

Browse files
committed
feat(replayer): added cli for dataset replaying
1 parent dfc47af commit 80adbe8

2 files changed

Lines changed: 63 additions & 16 deletions

File tree

python/rcs/__main__.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
import typer
55
from rcs.envs.storage_wrapper import StorageWrapper
6+
from rcs.sim.replayer import replay as replay_dataset
67

78
app = typer.Typer()
89

@@ -32,5 +33,39 @@ def consolidate(
3233
typer.echo("Done.")
3334

3435

36+
@app.command("replay")
37+
def replay(
38+
dataset: Annotated[
39+
Path,
40+
typer.Argument(
41+
exists=True,
42+
help="Parquet dataset directory to replay.",
43+
),
44+
],
45+
headless: Annotated[bool, typer.Option(help="Whether to run without GUI.")] = True,
46+
frequency: Annotated[int, typer.Option(help="Simulation frequency to use during replay.")] = 30,
47+
relative_to: Annotated[
48+
str,
49+
typer.Option(help="RelativeTo enum name: CONFIGURED_ORIGIN, LAST_STEP, or NONE."),
50+
] = "CONFIGURED_ORIGIN",
51+
scene: Annotated[
52+
str,
53+
typer.Option(help="Python expression that evaluates to a scene instance."),
54+
] = "env_configs.EmptyWorldFR3Duo()",
55+
task_cfg: Annotated[
56+
str,
57+
typer.Option(help="Python expression that evaluates to a task config."),
58+
] = 'env_tasks.PickTaskConfig(robot_name="right")',
59+
):
60+
replay_dataset(
61+
dataset=dataset,
62+
headless=headless,
63+
frequency=frequency,
64+
relative_to=relative_to,
65+
scene=scene,
66+
task_cfg=task_cfg,
67+
)
68+
69+
3570
if __name__ == "__main__":
3671
app()

python/rcs/sim/replayer.py

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
1+
import typing
12
from dataclasses import dataclass
23
from pathlib import Path
34
from typing import Any
45

56
import duckdb
67
import gymnasium as gym
78
import numpy as np
9+
import rcs.envs.configs as env_configs
10+
import rcs.envs.tasks as env_tasks
811
from rcs._core.sim import SimConfig
912
from rcs.envs.base import RelativeTo, SimEnv
10-
from rcs.envs.configs import EmptyWorldFR3Duo
13+
from rcs.envs.scenes import SimEnvCreator
1114
from rcs.envs.storage_wrapper import StorageWrapper
12-
from rcs.envs.tasks import PickTaskConfig
1315

1416
DATASET_PATH = "recorded_iris"
1517

@@ -114,22 +116,36 @@ def replay_trajectory(env: gym.Env, recorded_steps: list[RecordedSimStep], headl
114116
env.get_wrapper_attr("success")()
115117

116118

117-
def replay():
118-
dataset = "/home/tobi/coding/rcs_repos/robot-control-stack/test_iris"
119-
headless = False
120-
scene = EmptyWorldFR3Duo()
121-
sim_cfg_data = scene.config()
122-
sim_cfg_data.camera_cfgs = {}
123-
sim_cfg_data.sim_cfg = SimConfig(async_control=True, realtime=not headless, frequency=30, max_convergence_steps=500)
119+
def replay(
120+
dataset: Path | str,
121+
headless: bool = True,
122+
frequency: int = 30,
123+
relative_to: str = RelativeTo.CONFIGURED_ORIGIN.name,
124+
scene: str = "env_configs.EmptyWorldFR3Duo()",
125+
task_cfg: str = 'env_tasks.PickTaskConfig(robot_name="right")',
126+
):
127+
exec_scope = {**globals(), "__builtins__": __builtins__, "env_configs": env_configs, "env_tasks": env_tasks}
128+
scene_locals: dict[str, Any] = {}
129+
exec(f"_result = {scene}", exec_scope, scene_locals)
130+
sc = typing.cast(SimEnvCreator, scene_locals["_result"])
131+
sim_cfg_data = sc.config()
132+
sim_cfg_data.sim_cfg = SimConfig(
133+
async_control=True,
134+
realtime=not headless,
135+
frequency=frequency,
136+
max_convergence_steps=500,
137+
)
124138
sim_cfg_data.headless = headless
125-
sim_cfg_data.relative_to = RelativeTo.CONFIGURED_ORIGIN
139+
sim_cfg_data.relative_to = RelativeTo[relative_to.upper()]
126140
if sim_cfg_data.root_frame_objects is None:
127141
sim_cfg_data.root_frame_objects = {}
128-
sim_cfg_data.task_cfg = PickTaskConfig(robot_name="right")
142+
task_cfg_locals: dict[str, Any] = {}
143+
exec(f"_result = {task_cfg}", exec_scope, task_cfg_locals)
144+
sim_cfg_data.task_cfg = task_cfg_locals["_result"]
129145

130146
uuids = load_distinct_uuids(dataset)
131147

132-
env_rel = scene.create_env(sim_cfg_data)
148+
env_rel = sc.create_env(sim_cfg_data)
133149
env_rel = StorageWrapper(
134150
env_rel,
135151
DATASET_PATH,
@@ -148,7 +164,3 @@ def replay():
148164
replay_trajectory(env_rel, recorded_steps, headless)
149165
finally:
150166
env_rel.close()
151-
152-
153-
if __name__ == "__main__":
154-
replay()

0 commit comments

Comments
 (0)