Environment layer¶
maniguard/envs/ does not define a live environment class — task-gen replay,
datagen, and eval build OmniGibson envs directly from frozen scene snapshots. The
three building blocks every downstream stage shares are:
| Module | Role |
|---|---|
registry.py |
Discover frozen scene snapshots and parse them into typed specs |
frozen_task_runtime.py |
Build an OmniGibson env config from a snapshot + controller presets |
perturbation_runtime.py |
Apply visual/structural perturbations to a loaded scene |
Scene registry (registry.py)¶
A benchmark root is a directory of per-scene subdirs, each containing a frozen
scene_ep1.json snapshot and a diagnostics.jsonl. build_scene_registry()
walks it and returns a list of immutable ManiGuardSceneSpec records:
from maniguard.envs.registry import build_scene_registry
registry = build_scene_registry(
benchmark_root="outputs/benchmarks/pnp_clutter",
activity_root="behavior-1k/bddl3/bddl/activity_definitions",
scene_names=["Benevolence_1_int"], # optional filter
max_scenes=None,
)
spec = registry[0] # ManiGuardSceneSpec(scene_name, scene_file, diagnostics_file,
# activity_name, problem_file, target_synset,
# target_object_name, support_object_name/_label, prompt)
Each spec is built by cross-referencing three sources: the scene snapshot
(object init info), the first line of diagnostics.jsonl (activity name,
selection, active_object_summary roles, surface), and the dataset-local
problem0.bddl. Helpers in the same module:
build_runtime_scene_info()/build_runtime_task_metadata()— attach aninst_to_namemap (BDDL instance id → scene object name) to the snapshot's task metadata so aDummyTaskenv can resolve LTL propositions.extract_scene_robot_setup()/strip_scene_robots_from_scene_info()— pull the saved robot pose/joints out of a snapshot and remove scene robots so the runtime can re-insert a canonical robot.slice_scene_registry_for_worker(registry, num_envs, seed_offset)— deterministically shard scenes across parallel envs/workers.
Frozen-snapshot env builder (frozen_task_runtime.py)¶
build_env_config() turns a snapshot into an OmniGibson env config dict, with
scene robots stripped and a canonical robot re-inserted under locked conventions:
from maniguard.envs.frozen_task_runtime import build_env_config, FrozenTaskRuntimeSession
cfg = build_env_config(
scene_info, diagnostics,
controller_preset="joint_position", # see table below
grasping_mode="assisted", # "sticky" for lid / thin-object pipelines
camera_names=["cam_opposite", "cam_left", "cam_right"],
action_frequency=20, rendering_frequency=20, physics_frequency=120,
)
with FrozenTaskRuntimeSession(headless=True) as sess: # boots OmniGibson, stops sim on exit
env = sess.og.Environment(configs=cfg)
...
Controller presets¶
The arm/gripper controller pair is selected by a single controller_preset
arg — never reach into the controller config dict directly. Two conventions
are locked across pipelines: action_normalize=False (raw radians/meters) and
grasping_mode="assisted" (override to "sticky" for lids/thin objects).
| Preset | Arm controller | Used by |
|---|---|---|
joint_position |
JointController, absolute position |
teleop replay, validation, default |
joint_position_impedance |
JointController + impedances, input_limits=None |
cuRobo Phase-A replays (accurate tracking, no clip) |
joint_position_raw |
JointController, raw-radian, no command clipping (rigid Isaac drive) |
datagen + benchmark rollouts (BENCH_CONTROLLER_PRESET) |
osc |
OperationalSpaceController, raw 6-D pose-delta |
pnp Phase-B replay, VLA policies emitting EEF deltas |
ik |
InverseKinematicsController, binary gripper |
live teleop (GELLO / SO-101) |
Other runtime helpers: FrozenTaskRuntimeSession (context manager that boots
OmniGibson headless and stops the sim on exit), ReviewVideoRecorder +
position_diagnostics_cameras() (taskgen-style multi-camera review MP4s),
step_idle(), compute_floor_z(), save_scene_snapshot(), and
resolve_runtime_python() (locates a torch-capable interpreter; override with
MANIGUARD_RUNTIME_PYTHON).
Runtime perturbations (perturbation_runtime.py)¶
When a scene's task metadata carries a perturbation spec (written by the
perturbation generator),
apply_runtime_perturbations(env) materializes it on the loaded scene:
- Visual overrides — per-object diffuse color / texture swaps.
- Local reconstruct instructions, dispatched by
type:restack_chain,liquid_refill_target,place_lid_on_container,restage_on_support.
Each returns a structured result (applied, reason, counts) so the caller can
log exactly what was and wasn't materialized — no silent failures.