Skip to content

Add registered real2sim qpos sources to Task Program - #799

Closed
yuecideng wants to merge 11 commits into
mainfrom
codex/real2sim-source-integration
Closed

yuecideng wants to merge 11 commits into
mainfrom
codex/real2sim-source-integration

Conversation

@yuecideng

@yuecideng yuecideng commented Oct 17, 2026 •

Copy link
Copy Markdown
Contributor

Description

Real qpos recordings can supply a complete nominal Pick plan through Task Program without first running ordinary motion planning. Integrations select an immutable expert provider ID/revision and a content-pinned source bundle. Source-independent trajectory assembly is shared with ordinary PickUp and MoveJoints planning: Skills supply semantic effects and event/dependency boundaries, and the existing plan builder produces commands and tracking.

Refs #709 and #708. This is the first B=1, sequential, fixed-qpos integration slice; these issues remain open for physical qualification, broader source modes and collection support.

  • Add dataset-independent real trajectory, frame/joint/unit normalization and anchored timing contracts, with explicit gripper decoding and raw-source JSON/NPZ bundles.

  • Add ragged (B,N_max,D) anchored resampling with explicit source/anchor counts, reusable device maps, exact event copies, terminal padding and float32/float64 Torch or Warp CPU/CUDA evaluation. CPU float64 clock preparation shares the single-path algorithm; registered Task Program providers remain B=1.

  • Register expert factories and exact expanded call occurrences in the existing simulation catalog/fingerprint. Track live provider identity with weak references so completed calls release their recordings while cached-instance reuse is rejected. Reject unknown versions, unsupported capabilities, unverified bundles, replay-incompatible recovery and ambiguous bindings before use.

  • Bind replay to the target profile and robot asset digest; validate the live joint order, restored initial state, command period, joint position limits, velocity references and every command interval’s required speed.

  • Add versioned SkillTrajectoryContract, owned SkillTrajectoryInput/typed geometry, and SkillPlanSemantics. The Engine calls a framework-owned assembler and explicit Skill semantic hook; PickUp and MoveJoints use it for both ordinary and external motion. Contracts are included in the catalog fingerprint (schema 6); unsupported Skills fail before planner fallback.

  • Retain assembly inputs on plan snapshots and reassemble same-grid candidates with current provenance, commands, tracking, semantic effects and monitor bounds. Reject stale geometric-event facts, preserve the original recorded-path Engine method as a generic compatibility adapter, and leave non-joint/non-opted-in Skills on their existing path. Task Program execution, effect assurance and host lifecycle remain authoritative.

  • Include deterministic source-neutral residual examples, a four-panel native renderer preview, and an audit/preparation CLI for one optional original DROID HDF5. CI fixtures are synthetic and have no dependency on the earlier real2sim experiment, its reconstructed assets or local outputs.

  • Add physics_preview.py using the existing fixed-cadence playback host: one estimated foreground scene, B=1 reset-isolated trials, PD robot control and gravity/contact-driven objects. Success also requires continuous measured release and stable placement for the final second; both previews expose the shared visualization CLI options.

Dependencies: no package dependency changes.

Type of change

  • New feature (non-breaking change which adds functionality)

Screenshots

The reproducible four-panel previews show the real recording, nominal qpos and two seeded variants. The physical version adds an estimated table/block/open-container scene, PD control, measured finger contacts, object lift and release/settling. Commands, controller preload and calibration scope are documented in examples/real2sim/README.md; generated videos, raw traces and assets remain external runtime outputs.

Validation

  • Current shared-assembly regression: Atomic Skills, full Task Program runtime/Gym integrations, real2sim data, expansion, context and API-checker tests: 2,369 passed, 2 skipped, 8 real-simulation cases deselected. Focused cases verify ordinary/external command and tracking parity, typed owned geometry, B=2/custom bindings/reordered environment IDs, phase/event/revision checks, interval speeds, ordered waypoint visits, protected geometric events, and complete candidate rebuilding with current lineage.

  • Earlier compute/data and compatibility/visualization validation passed 1,938 tests, including explicit CUDA cases; four real-simulation tests were deselected. Compute kernels and the physical preview are unchanged by the shared-assembly follow-up. Dedicated proxy-scene physics trials are recorded below.

  • Batch tests cover variable lengths/anchor counts, row permutations, exact signed-zero anchor copies including directly constructed maps with right-closed anchor brackets, independent interpolation references, ignored NaN padding, bounded allocation, mapping reuse, noncontiguous input, explicit backend failures and non-default CUDA stream ordering.

  • Provider regressions reject the 3 rad/s reversal whose central differences stay below 2 rad/s, accept intervals at/below the limit, verify completed recordings can be collected, and reject reused or non-weak-referenceable provider instances.

  • Release-evidence tests reject closed-gripper/contact cases and interrupted/short release windows. The previous held-inside-container false positive is rejected by the physical summary, while a released and stable trace passes. Historical action-utils aliases remain covered independently of new compute exports; both visualization coverage and preview CLI help checks pass.

  • One optional original recording was checked at three prefix lengths on Torch/Warp CPU/CUDA in float32/float64: maximum error against the previous single-path implementation was zero. Existing normalized bundle revision and raw source digest remain unchanged.

  • The reproducible scripts/benchmark/trajectory/anchored_batch.py reports preparation, cached apply, offline end-to-end transfer, memory and numerical agreement separately. For B=128, N_max=192, D=13 float64 on RTX 5090, cached Warp CUDA evaluation was about 0.12 ms versus 0.17 ms for Torch CUDA; full offline conversion was about 14 ms for both. Torch remains the default backend.

  • B=1 synthetic source -> registered selector -> complete PickUp plan -> Task Program bridge regression passes with projected semantic completion. Tests also retain measured-effect failure coverage and ensure source errors never invoke the ordinary planner.

  • Original HDF5 audit preserves raw gripper samples and camera calibration metadata, extracts a conservative Pick slice, writes a content-pinned diagnostic bundle, and confirms the original input digest is unchanged.

  • Native previews include the 397-frame kinematic comparison and a 501-frame physical comparison (including its result card) at 30 FPS. Motion-limit and measured-contact/settling checks pass within their declared scopes; source-calibration status remains unverified.

  • Black 26.3.1, API coverage (2658/2658), context routing/checks and diff whitespace checks pass.

  • Sphinx dummy build completes. Repository-wide documentation warnings remain; the added release helper has no autodoc member warning. The shared-assembly API page is documented without duplicate method/geometry indexes.

  • Fresh physical validation: 9/9 measured proxy-scene trials pass (nominal and two seeded variants, three resets each) under the stricter release criteria. The block rises about 10 cm, bilateral hold lasts about 2.88 s or longer, and measured opening without bilateral grasp contact persists for about 3.16 s before the end. Oriented containment and final-second translational/rotational stability also pass. Source calibration remains unverified.

  • The physical CLI ran all nine fresh trials with --no-render; output traces retain full/active joint names and IDs, controller targets, calibration and release thresholds. The original recording digest is unchanged.

  • The local native runtime emits an entity-balance warning at process teardown; runs return zero and the saved state traces/videos pass verification. This follow-up does not change native simulator cleanup.

Remaining scope

Real-recording formal admission remains blocked by unresolved real flange/gripper/TCP mounting, hardware jaw-width calibration, independent camera reprojection/frame alignment and final target initial-state registration. The audit retains unverified states and the configured provider rejects that sample.

Next acceptance stages are independently calibrated foreground geometry and hardware mapping, formal provider admission/verified Task Program execution for the original recording, and receipt-backed source-array attachments. The physical preview is an estimated proxy-scene diagnostic and leaves source calibration unverified. Additional Skill assemblers (Place, MoveHeldObject, HandOver and contact skills), registered-source combined expansion, batched provider execution, ActionPlan time-grid changes, eef_pose/hybrid, parallel calls and multi-slot collection are outside this slice and remain follow-ups.

Checklist

  • I have run the black . command to format the code base.
  • I reviewed affected documentation and agent context, updated the source/admission/Skill ownership guidance, and retained unchanged simulation lifecycle guidance.
  • Public API changes are reflected in the API docs (python docs/scripts/check_api_docs.py).
  • I have added tests that prove the source admission, full-plan assembly, exact call binding and bridge behavior.
  • Dependencies have been reviewed; no package dependency changes are required.

@yuecideng yuecideng added enhancement Improvements to existing capabilities; use feature for new capabilities. task Concrete tasks, deployments, objectives and recipes, including configured Task Program tasks. dataset labels Oct 17, 2026
@yuecideng yuecideng added the physics Physics backends, dynamics, contacts, fluids, deformables and physics solvers. label Oct 17, 2026
@yuecideng
yuecideng marked this pull request as ready for review October 17, 2026 09:04
@greptile-apps

greptile-apps Bot commented Oct 17, 2026 •

Copy link
Copy Markdown

RetriggerView in GreptileConfidence Score: 1/5

[Medium impact] The changes reach a bounded simulator Pick workflow and shared trajectory tools.

The PR needs fixes before merging because supported source configurations and batched plan rebuilding fail.

Fix All in CodexFindings

  1. P1 Two recorded calls cannot load ▶
  2. P1 USD robots cannot replay recordings ▶
  3. P1 Batched plan rebuilding fails ▶
  4. P1 Successful neural joint plans fail ▶
Fix with agent prompt
### Issue 1
embodichain/lab/task_program/integrations/configured.py:2222-2223
Configuring two sequential Pick occurrences always fails. The decoder adds a factory for each entry, but every factory has the same `provider_id` and `revision`. `ExpertSourceRegistry` therefore raises `Duplicate expert source provider version`, even with different `call_index` values.

Separate each call’s bundle selection from the registered implementation, and reuse one factory declaration when appropriate.

### Issue 2
embodichain/lab/task_program/integrations/real2sim.py:119
Robots loaded through `RobotCfg.source=UsdSourceCfg(...)` leave `cfg.fpath` as `None` and store the asset path in `cfg.source.file_path`. Calling `Path(engine.robot.cfg.fpath)` therefore raises before the digest check, so a correctly pinned recording cannot run.

Resolve the file through the same `_asset_file_path` helper used when loading the robot.

### Issue 3
embodichain/lab/sim/atomic_actions/engine.py:945-950
Rebuilding an ordinary batched `MoveJoints` plan now rejects its terminal padding. `to_full_robot_trajectory` keeps zero-duration terminal holds for shorter rows, but this branch sends them through `_validate_external_trajectory`, which rejects every later zero interval. Even rebuilding an unchanged plan fails when successful rows have different durations.

Preserve valid stationary padding when rebuilding ordinary plans, while retaining strict interval checks for imported recordings.

### Issue 4
embodichain/lab/sim/atomic_actions/primitives/move_joints.py:181-188
Ordinary `MoveJoints` now runs this check, which requires the final joint positions to be within `0.0001` rad of the goal. But `NeuralPlanner` supports joint moves and accepts errors below its configured `joint_eps`, which defaults to `0.02` rad. It returns the reached position without snapping it to the goal.

A successful rollout ending `0.005` rad short therefore raises here instead of producing a plan. Preserve the planner's accepted tolerance for ordinary planning, or make the stricter requirement explicit rather than applying it to every backend.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Summary

Adds registered, content-pinned real recordings as complete Task Program plans.

  • Batched joint paths keep their event samples on a shared clock.
  • PickUp and MoveJoints build supplied paths into complete action plans.
  • A registered recording can supply one fixed-replay Pick plan.
  • Real2sim examples show recorded paths in kinematic and physical previews.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  Config[Integration configuration] --> Registry[ExpertSourceRegistry]
  Registry --> Provider[Real2SimExpertSourceProvider]
  Bundle[Content-pinned source bundle] --> Provider
  Provider --> Admission[Engine motion checks]
  Ordinary[Ordinary Skill planning] --> Assembly[Shared trajectory assembly]
  Admission --> Assembly
  Assembly --> Plan[Commands, tracking and expected effects]
  Plan --> Runtime[Task Program execution and effect checks]
Loading

Reviews (4) · Last reviewed commit: "chore(real2sim): merge latest main into ..." · Reviewed by Greptile

Comment on lines +181 to +188
tolerance = 1e-4
for row in motion.planning_success.nonzero().flatten().tolist():
if not torch.allclose(
positions[row, -1], goals[row, -1].to(positions), atol=tolerance, rtol=0
):
raise ValueError(
"MoveJoints trajectory does not reach its requested joint goal"
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Successful neural joint plans fail

Ordinary MoveJoints now runs this check, which requires the final joint positions to be within 0.0001 rad of the goal. But NeuralPlanner supports joint moves and accepts errors below its configured joint_eps, which defaults to 0.02 rad. It returns the reached position without snapping it to the goal.

A successful rollout ending 0.005 rad short therefore raises here instead of producing a plan. Preserve the planner's accepted tolerance for ordinary planning, or make the stricter requirement explicit rather than applying it to every backend.

Prompt To Fix With AI
This is a comment left during a code review.
Path: embodichain/lab/sim/atomic_actions/primitives/move_joints.py
Line: 181-188

Comment:
**Successful neural joint plans fail**

Ordinary `MoveJoints` now runs this check, which requires the final joint positions to be within `0.0001` rad of the goal. But `NeuralPlanner` supports joint moves and accepts errors below its configured `joint_eps`, which defaults to `0.02` rad. It returns the reached position without snapping it to the goal.

A successful rollout ending `0.005` rad short therefore raises here instead of producing a plan. Preserve the planner's accepted tolerance for ordinary planning, or make the stricter requirement explicit rather than applying it to every backend.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Fix in Codex Fix in Claude Code

Merge origin/main at cd55892.
Retain both anchored/minimum-jerk exports, ODS/real2sim lazy modules,
physical evidence/nominal providers, and asset/source integration validation.
Adapt recorded-path test fixtures to main's velocity-limit mock behavior.

Validation: 2773 regression cases passed, and the remaining three cases
passed after the fixture adaptation; nine real-simulation cases deselected.
Black 26.3.1, API coverage (2845/2845), context validation and whitespace
checks pass. Existing context now retains both main and source contracts.
Tests used the pinned DexSim 0.5.1rc1 from an isolated temporary directory.
Comment on lines +2222 to +2223
source_factories.append(
Real2SimExpertSourceProviderFactory(

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Two recorded calls cannot load

Configuring two sequential Pick occurrences always fails. The decoder adds a factory for each entry, but every factory has the same provider_id and revision. ExpertSourceRegistry therefore raises Duplicate expert source provider version, even with different call_index values.

Separate each call’s bundle selection from the registered implementation, and reuse one factory declaration when appropriate.

Prompt To Fix With AI
This is a comment left during a code review.
Path: embodichain/lab/task_program/integrations/configured.py
Line: 2222-2223

Comment:
**Two recorded calls cannot load**

Configuring two sequential Pick occurrences always fails. The decoder adds a factory for each entry, but every factory has the same `provider_id` and `revision`. `ExpertSourceRegistry` therefore raises `Duplicate expert source provider version`, even with different `call_index` values.

Separate each call’s bundle selection from the registered implementation, and reuse one factory declaration when appropriate.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Fix in Codex Fix in Claude Code

raise ValueError(
"Source target profile differs from the selected embodiment"
)
asset_path = Path(engine.robot.cfg.fpath)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 USD robots cannot replay recordings

Robots loaded through RobotCfg.source=UsdSourceCfg(...) leave cfg.fpath as None and store the asset path in cfg.source.file_path. Calling Path(engine.robot.cfg.fpath) therefore raises before the digest check, so a correctly pinned recording cannot run.

Resolve the file through the same _asset_file_path helper used when loading the robot.

Prompt To Fix With AI
This is a comment left during a code review.
Path: embodichain/lab/task_program/integrations/real2sim.py
Line: 119

Comment:
**USD robots cannot replay recordings**

Robots loaded through `RobotCfg.source=UsdSourceCfg(...)` leave `cfg.fpath` as `None` and store the asset path in `cfg.source.file_path`. Calling `Path(engine.robot.cfg.fpath)` therefore raises before the digest check, so a correctly pinned recording cannot run.

Resolve the file through the same `_asset_file_path` helper used when loading the robot.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Fix in Codex Fix in Claude Code

Comment on lines +945 to +950
return self.build_plan_from_trajectory(
request,
context,
replace(
source, trajectory=trajectory, diagnostics=owned_plan.diagnostics
),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Batched plan rebuilding fails

Rebuilding an ordinary batched MoveJoints plan now rejects its terminal padding. to_full_robot_trajectory keeps zero-duration terminal holds for shorter rows, but this branch sends them through _validate_external_trajectory, which rejects every later zero interval. Even rebuilding an unchanged plan fails when successful rows have different durations.

Preserve valid stationary padding when rebuilding ordinary plans, while retaining strict interval checks for imported recordings.

Prompt To Fix With AI
This is a comment left during a code review.
Path: embodichain/lab/sim/atomic_actions/engine.py
Line: 945-950

Comment:
**Batched plan rebuilding fails**

Rebuilding an ordinary batched `MoveJoints` plan now rejects its terminal padding. `to_full_robot_trajectory` keeps zero-duration terminal holds for shorter rows, but this branch sends them through `_validate_external_trajectory`, which rejects every later zero interval. Even rebuilding an unchanged plan fails when successful rows have different durations.

Preserve valid stationary padding when rebuilding ordinary plans, while retaining strict interval checks for imported recordings.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Fix in Codex Fix in Claude Code

@yuecideng yuecideng added data-pipeline Data collection, ODS, sampling, recording, persistence, conversion and analysis. feature New user-facing capabilities. motion gen Robot motion planning, MotionGenerator, trajectory generation, retiming and expansion. task-program Task Program language, semantics, compiler, runtime and integration contracts. atomic-skill Atomic Skill goals, planning, execution, verification and recovery. compute Shared numerical algorithms and kernels independent of simulation objects. docs Documentation, API references and example explanations. and removed enhancement Improvements to existing capabilities; use feature for new capabilities. physics Physics backends, dynamics, contacts, fluids, deformables and physics solvers. dataset labels Oct 25, 2026
@yuecideng yuecideng removed the task Concrete tasks, deployments, objectives and recipes, including configured Task Program tasks. label Oct 25, 2026
@yuecideng yuecideng closed this Oct 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

atomic-skill Atomic Skill goals, planning, execution, verification and recovery. compute Shared numerical algorithms and kernels independent of simulation objects. data-pipeline Data collection, ODS, sampling, recording, persistence, conversion and analysis. docs Documentation, API references and example explanations. feature New user-facing capabilities. motion gen Robot motion planning, MotionGenerator, trajectory generation, retiming and expansion. task-program Task Program language, semantics, compiler, runtime and integration contracts.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant