Skip to content

Pi0.5 on OSMO - #823

Merged
alexmillane merged 82 commits into
mainfrom
alex/feature/osmo_pi05
Jul 3, 2026
Merged

Pi0.5 on OSMO#823
alexmillane merged 82 commits into
mainfrom
alex/feature/osmo_pi05

Conversation

@alexmillane

@alexmillane alexmillane commented Jun 25, 2026

Copy link
Copy Markdown
Collaborator

Summary

Add pi0 policy-server workflow to OSMO. Refactor OSMO generator scripts in the process.

Detailed description

  • pi0 workflow
    • Schedules an openpi policy server alongside the policy-runner client
    • Note that we had to override the one function from the official pi client to stop dropouts
  • Refactor OSMO workflow structure
    • Common args no longer repeated.
    • Workflows declare multiple tasks.
    • Adds multi-task groups with a per-task lead flag (exactly one lead per group).
    • Tasks own their CLI args via add_task_arguments

alexmillane and others added 30 commits June 1, 2026 09:59
Record every value drawn by an enabled variation's sampler so
downstream sensitivity-analysis tooling has the input factors that
produced each episode.

This adds a sample-observer layer the recorder builds on: SamplerBase
gains add_listener/remove_listener and a sample() template method that
notifies listeners around the concrete _sample(); VariationBase gains
add_sample_listener/remove_sample_listener, re-binding subscriptions onto
the sampler rebuilt by apply_cfg so they survive cfg swaps.

ArenaEnvBuilder constructs a VariationRecorder, attaches it after Hydra
overrides but before any sampling, and exposes it on env.unwrapped. The
recorder is stashed on the builder rather than the env cfg because the
configclass __post_init__ deep-copies its attributes, which would orphan
the listener closures.

Signed-off-by: alex <amillane@nvidia.com>
Move the inline RecordVideo / CameraObsVideoRecorder wrapping out of
policy_runner and eval_runner into a single video_recording module
(VideoRecordingCfg + wrap_env_for_video), so the gym-wrapper plumbing
lives in one place instead of being duplicated across the two runners.

Signed-off-by: alex <amillane@nvidia.com>
- Move video_recording.py to isaaclab_arena/utils/ and drop its module docstring.
- Rename VideoRecordingCfg fields and the corresponding CLI flags:
  --video -> --record_viewport_video, --camera_video -> --record_camera_video,
  --video_dir -> --video_base_dir.
- Write videos into a reverse-dated run subdirectory (timestamped_run_dir),
  shared across all jobs in an eval run, mirroring Isaac Lab's log layout.
- Guard _resolve_video_length when both num_steps and num_episodes are None.
- Tidy wrap_env_for_video docstring args.

Signed-off-by: alex <amillane@nvidia.com>
Use underscore-only flag names (--record_viewport_video, --record_camera_video,
--video_base_dir) to match the convention used by every other CLI argument.

Signed-off-by: alex <amillane@nvidia.com>

@alexmillane alexmillane left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

More self-review.

Comment thread isaaclab_arena_openpi/policy/pi0_remote_policy.py Outdated
Comment thread isaaclab_arena_openpi/policy/pi0_remote_policy.py
Comment thread isaaclab_arena_openpi/docker/build_server_image.sh Outdated
Comment thread isaaclab_arena_openpi/policy/pi0_remote_config.py Outdated
Comment thread isaaclab_arena_openpi/policy/websocket_client.py Outdated
Comment thread osmo/workflows/openpi_plus_policy_runner_workflow.py Outdated
Comment thread osmo/workflows/workflow.py
Comment thread osmo/workflows/workflow.py Outdated
Comment thread osmo/workflows/workflow.py Outdated
Comment thread osmo/workflows/workflow_constants.py Outdated

@arena-review-bot arena-review-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Isaac Lab-Arena Review Bot

Summary

Adds a pi0 policy-server OSMO workflow (server + policy-runner client co-scheduled over {{host:policy_server}}) and refactors the workflow/task layer so tasks declare their own CLI args via add_task_arguments and workflows compose tasks via task_cls_list/lead_list. The refactor is clean, the single-lead invariant is asserted, and the vendor-specific websocket override is correctly placed in the isaaclab_arena_openpi extension package rather than core. Since this is a DRAFT, the main things to resolve before un-drafting are a few temporary/debug leftovers in policy_runner_task.py.

Findings

See inline comments.

Test Coverage

The websocket-client override is exercised by the existing test_pi0_remote_policy.py (the monkeypatch target was correctly updated to the new WebsocketClientPolicy). OSMO submit-script wiring stays untested, consistent with the rest of osmo/, and no new sim-dependent code paths were added that would need the inner/outer pattern.

Verdict

Minor fixes needed

Comment thread osmo/tasks/policy_runner_task.py Outdated
Comment thread osmo/tasks/policy_runner_task.py
Comment thread osmo/tasks/policy_runner_task.py Outdated
@alexmillane
alexmillane changed the base branch from alex/feature/record_per_episode_metadata_and_results_2 to main July 1, 2026 14:10

@arena-review-bot arena-review-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Isaac Lab-Arena Review Bot

Summary

This draft adds a pi0 policy-server workflow (server co-scheduled with the policy-runner client over OSMO's {{host:policy_server}} substitution) and cleans up the OSMO workflow structure: workflows declare tasks via task_cls_list/lead_list, tasks own their CLI args via add_task_arguments, and per-policy PolicyRunnerTask subclasses replace the old workflow-type→args map. The refactor is coherent and the new _assert_single_lead_task invariant reads well. The main thing holding it back from merge is leftover debug/temporary scaffolding in policy_runner_task.py — flagged below (all confined to osmo/ deployment scripts, so no core-boundary concerns).

Findings

🟡 Warning: osmo/tasks/policy_runner_task.py:18DEFAULT_IMAGE points at a personal :alex_testing tag (was :latest). This looks like a temporary testing value that would ship to everyone submitting a policy-runner workflow — worth reverting to :latest (or a real pinned tag) before this leaves draft.

🟡 Warning: osmo/tasks/policy_runner_task.py:67_get_inputs carries a # REMOVE! marker and the arena-lfs-data input commented out, now returning []. Is dropping the LFS test-data input intended, or WIP scaffolding? Either way the commented line + # REMOVE! should go before merge.

🔵 Improvement: osmo/tasks/policy_runner_task.py:84 — the old _get_run_script body is left commented out and the live path is now just set -euxo pipefail\n{command}. Beyond deleting the dead block: are the dropped setup steps (ldconfig, the _isaac_sim symlink, the LFS cp) now handled by the image/entrypoint? If the runner relies on any of them this would fail at runtime — worth a confirming note.

Test Coverage

test_pi0_remote_policy.py is updated to patch the new WebsocketClientPolicy override, so the existing suite stays green. The new keepalive params on the override aren't directly exercised, but they're thin passthroughs to websockets.sync.client.connect — not worth a dedicated test. No new test needed for the OSMO submit scripts (deployment glue).

Verdict

Minor fixes needed — clear out the # REMOVE! / commented scaffolding and the alex_testing image tag before taking this out of draft.

Comment thread osmo/tasks/policy_runner_task.py Outdated
Comment thread osmo/tasks/policy_runner_task.py Outdated
Comment thread osmo/tasks/policy_runner_task.py Outdated
@alexmillane
alexmillane marked this pull request as ready for review July 1, 2026 15:46
@alexmillane alexmillane changed the title DRAFT: policy-server to OSMO Pi0.5 on OSMO Jul 1, 2026

@arena-review-bot arena-review-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Isaac Lab-Arena Review Bot

Summary

Draft PR adds a pi0 policy-server OSMO workflow (server + policy-runner co-scheduled) and refactors the OSMO workflow/task structure so tasks own their CLI args, workflows declare a task_cls_list with per-task lead flags, and build logic is shared. The refactor is a clean simplification overall — dropping the WorkflowType/PolicyType enums and the single-lead assertion read well, and extracting build_server_image.sh de-duplicates the docker build. A few things below are worth confirming before this leaves draft, mostly around behavior that silently changed in the policy-runner task and an edge in the new arg-dedup.

Findings

🟡 Warning: osmo/workflows/workflow.py:77_deduplicate_args dedups by class identity, but add_task_arguments is inherited; two sibling subclasses sharing it would each add the same args and argparse would raise. Dedup on the resolved method instead.
🟡 Warning: osmo/tasks/policy_runner_task.py:83 — the env-setup boilerplate and the arena-lfs-data input were dropped from the run script; confirm the entrypoint now covers this.
🔵 Improvement: osmo/workflows/workflow_constants.py:16 — three URL constants are unused.
🔵 Improvement: osmo/tasks/pi0_server_task.py:14 — policy config/dir are hardcoded; consider exposing them.

Test Coverage

osmo/ has no pytest harness, so the new pure-logic bits (_assert_single_lead_task, _deduplicate_args, build_parser) are untested — consistent with the existing lack of coverage there, but they're now the kind of logic a small unit test would protect. On the policy side, test_pi0_remote_policy.py was correctly updated to patch the new WebsocketClientPolicy, but nothing asserts that ping_interval/ping_timeout actually reach the client — a light addition given they're the point of the override.

Verdict

Minor fixes needed (draft).

Comment thread osmo/workflows/workflow.py
Comment thread osmo/tasks/policy_runner_task.py
Comment thread osmo/workflows/workflow_constants.py
Comment thread osmo/tasks/pi0_server_task.py
@greptile-apps

greptile-apps Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds a pi0.5 inference-server workflow to OSMO, co-scheduling a Pi0ServerTask alongside the existing Pi0RemotePolicyRunnerTask, and refactors the OSMO generator layer so workflows declare their tasks as class-level lists with per-task lead flags and a shared build_parser() classmethod.

  • pi0 workflow: New Pi0PlusPolicyRunnerWorkflow pairs the policy-runner client with the openpi inference server; a local WebsocketClientPolicy subclass exposes configurable keepalive ping settings to prevent dropout during OSMO kernel-compilation warmup.
  • OSMO refactor: Workflow now uses declarative task_cls_list/lead_list class attributes; task-specific CLI args are registered via add_task_arguments(); common args and parser construction are centralized in build_parser(); URL/path constants move to workflow_constants.py.
  • Docker: Build logic is extracted from run_openpi_server.sh into a standalone build_server_image.sh that can be invoked independently.

Confidence Score: 4/5

Safe to merge with one fix: the documented minimal invocations in both submit-script docstrings will fail at argument parsing because --arena_env_args is now required with no default.

The refactor is structurally clean and the new pi0 workflow logic is sound. The one concrete breakage is that both submit-script docstrings advertise a minimal invocation that will immediately error out because --arena_env_args has no default.

osmo/tasks/policy_runner_task.py and the two submit scripts whose docstrings show the now-broken minimal invocation.

Important Files Changed

Filename Overview
osmo/tasks/policy_runner_task.py Now abstract; delegates policy selection to _get_policy_args(); removes all container setup steps and relies on image entrypoint instead. --arena_env_args is required=True but documented usage examples omit it.
osmo/tasks/base_task.py Refactored to drop WorkflowType dependency; adds lead flag, outputs abstract method, and add_task_arguments hook. lead=None default can produce null in rendered YAML if a task is instantiated outside the workflow machinery.
osmo/tasks/pi0_server_task.py New task that serves the pi0 inference server; POLICY_CONFIG and POLICY_DIR are hardcoded module-level constants with no CLI override path.
osmo/tasks/pi0_remote_policy_runner_task.py New task connecting policy_runner to the remote pi0 server via OSMO host-alias. Hardcodes --ping_timeout 300 before user-supplied args.
osmo/workflows/workflow.py Significant refactor: workflow now declared via class-level task_cls_list/lead_list, parser built via build_parser() classmethod, and a single task_args namespace shared across all tasks. Logic is sound.
isaaclab_arena_openpi/policy/websocket_client.py New WebsocketClientPolicy override that exposes ping_interval/ping_timeout. _wait_for_server only catches ConnectionRefusedError; transient OSError/ConnectionResetError will propagate.
isaaclab_arena_openpi/docker/build_server_image.sh New standalone build script extracted from run_openpi_server.sh; handles clone, Dockerfile patching, and push cleanly with proper tmpdir cleanup trap.
osmo/workflows/pi0_plus_policy_runner_workflow.py New two-task workflow pairing Pi0RemotePolicyRunnerTask (lead) with Pi0ServerTask; lead_list correctly designates exactly one lead.
osmo/workflows/workflow_constants.py New module centralizing OSMO output/Swift URL constants, extracted from per-task hardcoding.
isaaclab_arena_openpi/policy/pi0_remote_policy.py Switches from upstream WebsocketClientPolicy to local override to expose ping_interval/ping_timeout; reconnect path also updated consistently.

Reviews (3): Last reviewed commit: "Bring memory limit back down to make it ..." | Re-trigger Greptile

Comment thread osmo/tasks/policy_runner_task.py
Comment thread isaaclab_arena_openpi/policy/websocket_client.py
Comment thread osmo/tasks/base_task.py
Comment thread osmo/tasks/pi0_remote_policy_runner_task.py
Comment thread osmo/tasks/pi0_server_task.py

@arena-review-bot arena-review-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Isaac Lab-Arena Review Bot

Summary

Adds a co-scheduled pi0 policy-server + policy-runner OSMO workflow and refactors the OSMO generator into per-workflow classes with per-task CLI args and a per-task lead flag. The refactor reads cleanly and the layering is sound (the vendor-specific websocket override lives in isaaclab_arena_openpi, the generic mechanism stays in osmo/workflows). My main concern is that the refactor quietly changed the documented default policy-runner path so that the arg-less "default" invocations the submit scripts advertise no longer run.

Design, Boundaries & Scope

The move from a single enum-switched submit_evaluation_workflow.py to explicit per-policy task/workflow classes is justified — different policies genuinely need different args and run scripts (pi0 needs a co-scheduled server + connection flags), which the old WorkflowType/PolicyType enums couldn't model. Dropping the ldconfig / mkdir / _isaac_sim symlink boilerplate from the run script is a good cleanup — docker/setup/entrypoint.sh already does all of it.

The scope concern is default behavior: --policy_runner_args now defaults to "" (was --num_steps 100 --headless) and --arena_env_args is now required=True with no default. Together these mean the "default" commands the submit-script docstrings advertise now fail (details inline). Worth confirming this is intended and updating the docs.

Findings

See inline comments.

Test Coverage

test_pi0_remote_policy.py is correctly updated to patch the new WebsocketClientPolicy subclass, and the keepalive plumbing is exercised indirectly. The OSMO refactor itself (per-task lead flags, _assert_single_lead_task, build_parser/_deduplicate_args) has no test — a small --dry-run/render test asserting the generated dict (exactly one lead, expected task names, a non-failing default parse) would have caught the broken-default and required-arg issues above cheaply. Not a blocker for infra glue, but worth considering.

Verdict

Minor fixes needed

Comment thread osmo/tasks/policy_runner_task.py
Comment thread osmo/submit_zero_action_policy_runner_workflow.py Outdated
Comment thread osmo/workflows/workflow_constants.py
Comment thread osmo/submit_pi0_plus_policy_runner_workflow.py Outdated
Comment thread osmo/workflows/workflow.py
Comment thread osmo/submit_zero_action_policy_runner_workflow.py Outdated

@arena-review-bot arena-review-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Isaac Lab-Arena Review Bot

Summary

Adds a pi0 policy-server + policy-runner OSMO workflow and refactors the OSMO generator into per-workflow classes with declarative task_cls_list / lead_list, task-owned CLI args, and a shared build_parser. The refactor is clean and the class-attribute-driven workflow model reads well. A couple of points below are worth a look before merge — chiefly whether dropping the run-script's ldconfig step is safe on OSMO, plus some duplication and a fake default.

Findings

🟡 Warning: osmo/tasks/policy_runner_task.py:83 — the run script no longer runs ldconfig, which previously mirrored entrypoint.sh. OSMO overrides the image ENTRYPOINT, so /entrypoint.sh (and its ldconfig) never runs — see inline.

🔵 Improvement: osmo/submit_zero_action_policy_runner_workflow.py:39 — near-identical main() duplicated across the two submit scripts; could share one helper.

🔵 Improvement: osmo/tasks/base_task.py:26lead is effectively required but defaults to None, which would render lead: null.

Test Coverage

test_pi0_remote_policy.py is correctly re-pointed at the new WebsocketClientPolicy subclass and the existing reconnect/adapter tests still cover the client path. The new keepalive plumbing (ping_interval/ping_timeout flowing into the connection) and the overridden _wait_for_server aren't directly exercised, but that's hard to unit-test without a live server and is low-risk config plumbing — no blocker.

Verdict

Minor fixes needed

Comment thread osmo/tasks/policy_runner_task.py
Comment thread osmo/submit_zero_action_policy_runner_workflow.py Outdated
Comment thread osmo/tasks/base_task.py

@arena-review-bot arena-review-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Isaac Lab-Arena Review Bot

Summary

This PR adds a pi0 policy-runner + inference-server OSMO workflow and refactors the OSMO generator scripts: tasks now own their CLI args via add_task_arguments, workflows declare their task list with per-task lead flags, and common args are centralized. The refactor is a clear improvement (the WorkflowType/PolicyType enums and the repeated arg blocks are gone). A couple of default-behavior changes and a bit of residual duplication are worth a look before merge.

Design, Boundaries & Scope

submit_zero_action_policy_runner_workflow.py and submit_pi0_plus_policy_runner_workflow.py have main() bodies that are identical except for the workflow class and the description string. Could we collapse them into one shared entry point — e.g. a submit_workflow_cli(workflow_cls, description, epilog) helper in workflows/ (or a small Workflow.run_cli classmethod) — so a new workflow needs only its Workflow subclass and not another copy of this boilerplate?

Findings

See inline comments.

Test Coverage

test_pi0_remote_policy.py is correctly updated to patch the new WebsocketClientPolicy subclass, so the existing coverage still exercises the reconnect path. The new keepalive-ping override and the refactored OSMO task/workflow assembly (e.g. Workflow._assert_single_lead_task, create_task_dict output) are untested; a small unit test rendering a multi-task workflow dict and asserting the single-lead invariant would guard the new group logic. The OSMO scripts are host-side tooling (not part of the sim test phases), so no inner/outer sim-test pattern is needed here.

Verdict

Minor fixes needed

Comment thread osmo/tasks/policy_runner_task.py
Comment thread osmo/submit_zero_action_policy_runner_workflow.py Outdated
Comment thread osmo/tasks/pi0_remote_policy_runner_task.py
@alexmillane
alexmillane enabled auto-merge (squash) July 3, 2026 07:53
@alexmillane
alexmillane merged commit b7afee9 into main Jul 3, 2026
6 checks passed
david-tingdahl-nvidia pushed a commit that referenced this pull request Jul 10, 2026
## Summary
Add pi0 policy-server workflow to OSMO. Refactor OSMO generator scripts
in the process.

## Detailed description
- **pi0 workflow**
  - Schedules an openpi policy server alongside the policy-runner client
- _Note that we had to override the one function from the official pi
client to stop dropouts_
- **Refactor OSMO workflow structure**
  - Common args no longer repeated.
  - Workflows declare multiple tasks.
- Adds multi-task groups with a per-task `lead` flag (exactly one lead
per group).
  - Tasks own their CLI args via `add_task_arguments`

---------

Signed-off-by: alex <amillane@nvidia.com>
Co-authored-by: aiguldzh-nvidia <adzhumamurat@nvidia.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants