Skip to content

Refactor atomic actions for typed planning and recovery - #448

Open
yuecideng wants to merge 5 commits into
mainfrom
refactor/atomic-action-pr1-contracts
Open

Refactor atomic actions for typed planning and recovery#448
yuecideng wants to merge 5 commits into
mainfrom
refactor/atomic-action-pr1-contracts

Conversation

@yuecideng

Copy link
Copy Markdown
Contributor

Description

This PR replaces the legacy atomic-action target/execution contract with a typed, side-effect-free planning model and a bounded closed-loop recovery runtime.

The previous API mixed target data, planner policy, predicted task state, and execution semantics. That made execute() look like a controller operation even though it only generated trajectories, and it could not represent late-bound moving goals, verified effects, or recovery from tracking errors. This refactor establishes explicit boundaries between semantic intent, embodiment binding, planning, static compilation, and feedback-driven execution.

Dependencies: None. No dependency files are changed.

Design references:

Highlights

  • Adds typed ActionGoal, ActionBinding, ActionInvocation, MotionPolicy, and RecoveryPolicy contracts.
  • Separates measured RobotObservation, verified TaskState, versioned SceneSnapshot, and immutable PlanningContext.
  • Introduces ActionPlan, phase metadata, full-robot TimedTrajectory, planner diagnostics, and declarative StateDelta effects.
  • Replaces AtomicAction.execute() with side-effect-free AtomicAction.plan().
  • Replaces AtomicActionEngine.run() with:
    • compile() for offline trajectory composition and projected state;
    • start() / ExecutionSession.tick() for incremental command generation and verified state updates.
  • Supports late-bound SceneEntityPose goals and bounded recovery for tracking error, moving goals, phase timeout, planning failure, and effect-verification failure.
  • Preserves per-environment success masks and holds failed rows without incorrectly applying symbolic effects.
  • Preserves planner timing, velocities, and accelerations when available.
  • Migrates all built-in atomic actions, tutorials, benchmarks, cuRobo examples, API docs, project context, and the add-atomic-action development skill.

Breaking changes

  • Removes ActionTarget, WorldState, ActionResult, AtomicAction.execute(), and AtomicActionEngine.run().
  • Callers must construct an ActionInvocation and PlanningContext, then call plan(), compile(), or start() as appropriate.
  • Per-call motion and recovery parameters now live in MotionPolicy and RecoveryPolicy instead of individual action configs.
  • Symbolic effects are no longer committed on planning success; runtime execution requires external effect verification.

No compatibility layer is included by design.

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • Enhancement (non-breaking change which improves an existing functionality)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (existing functionality will not work without user modification)
  • Documentation update

Validation

  • black . — 554 files unchanged
  • pytest -q tests/sim/atomic_actions -m 'not requires_sim' tests/sim/planners/test_curobo_planner.py — 143 passed, 2 skipped, 5 deselected
  • Apache header, from __future__ import annotations, and public-module export checks — passed for 49 changed Python files
  • git diff --check origin/main...HEAD — passed
  • add-atomic-action skill validation — passed

A full Sphinx -W build was attempted during implementation but remains blocked by pre-existing repository-wide warnings outside the atomic-action module. The affected atomic-action pages import and render, and the affected toctree warning was fixed.

Screenshots

Not applicable; this is an API and runtime refactor.

Checklist

  • I have run the black . command to format the code base.
  • I have made corresponding changes to the documentation.
  • I have added tests that prove the refactor and recovery behavior work.
  • Dependencies have been updated, if applicable (no dependency changes required).

Copilot AI review requested due to automatic review settings August 2, 2026 10:14
@yuecideng yuecideng added refactor breaking atomic action atomic action related functionality motion gen Things related to motion generation for robot labels Aug 2, 2026

Copilot AI 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.

Pull request overview

This pull request refactors the simulation atomic-action stack from the legacy “target + execute + threaded world state” contract into a typed, side-effect-free planning API (AtomicAction.plan(...)) with an offline compiler (AtomicActionEngine.compile(...)) and a closed-loop execution runtime (AtomicActionEngine.start(...)/ExecutionSession.tick(...)), including explicit motion and recovery policies.

Changes:

  • Introduces typed planning/execution contracts (ActionInvocation, ActionBinding, PlanningContext, MotionPolicy, RecoveryPolicy, ActionPlan, StateDelta) and updates AtomicActionEngine to compile invocations instead of running targets.
  • Migrates built-in atomic actions (primitives) from execute() to plan() and replaces “targets” with typed “goals”, including late-bound scene-entity pose goals.
  • Updates tests, tutorials, benchmarks, examples, docs, and agent context to the new contracts.

Reviewed changes

Copilot reviewed 61 out of 61 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
tests/sim/planners/test_curobo_planner.py Updates cuRobo planner tests to use ActionInvocation + compile() and typed goals/policies.
tests/sim/atomic_actions/test_trajectory.py Adds tests for success-mask normalization and “owned tensor” outputs at planner boundaries.
tests/sim/atomic_actions/test_trajectory_motion_source.py Migrates motion-source tests from ActionCfg to MotionPolicy and validates plan-options forwarding behavior.
tests/sim/atomic_actions/test_motion_source_e2e.py Updates motion-source E2E test to compile() with typed invocation/binding/policy.
tests/sim/atomic_actions/test_engine.py Replaces run() sequencing tests with compiler/registry semantics and plan validation checks.
tests/sim/atomic_actions/test_engine_per_env.py Adds execution-session recovery tests for dynamic goals, tracking error, timeouts, and effect verification.
tests/sim/atomic_actions/test_curobo_motion_source_e2e.py Updates cuRobo E2E atomic action test to compile() with typed invocation.
tests/sim/atomic_actions/test_action_result_success.py Removes obsolete tests tied to removed ActionResult/legacy config surface.
scripts/tutorials/atomic_action/press.py Migrates tutorial to compile typed invocations and use MotionPolicy for sample counts.
scripts/tutorials/atomic_action/place.py Migrates PickUp→Place tutorial to typed goals/bindings/policies and compile().
scripts/tutorials/atomic_action/pickup.py Migrates PickUp tutorial to typed goals/bindings/policies and compile().
scripts/tutorials/atomic_action/move_joints.py Migrates MoveJoints tutorial to typed joint goals and compile().
scripts/tutorials/atomic_action/move_held_object.py Migrates held-object transport tutorial to typed goals/bindings/policies and compile().
scripts/tutorials/atomic_action/move_end_effector.py Migrates MoveEndEffector tutorial to typed pose goals and compile().
scripts/tutorials/atomic_action/hand_over.py Migrates HandOver demo to typed goals/bindings/policies and compile().
scripts/tutorials/atomic_action/coordinated_placement.py Migrates coordinated placement demo to plan()/compile() semantics and projected context updates.
scripts/tutorials/atomic_action/coordinated_pickment.py Migrates coordinated pickment demo to typed goal + invocation + compile().
scripts/tutorials/atomic_action/assemble.py Migrates assemble demo from AssembleTarget to AssembleGoal and compile().
scripts/benchmark/atomic_action/press_benchmark.py Migrates benchmark runner to compile() and typed invocations for timing/memory measurement.
scripts/benchmark/atomic_action/place_benchmark.py Migrates benchmark runner to compile() and typed invocations with projected context threading.
scripts/benchmark/atomic_action/pickup_benchmark.py Migrates benchmark runner to compile() and typed invocations.
scripts/benchmark/atomic_action/move_joints_benchmark.py Migrates benchmark runner to compile() and typed invocations.
scripts/benchmark/atomic_action/move_held_object_benchmark.py Migrates benchmark runner to compile() and typed invocations with projected context.
scripts/benchmark/atomic_action/move_end_effector_benchmark.py Migrates benchmark runner to compile() and typed invocations.
examples/sim/planners/curobo_planner.py Updates cuRobo example to use typed invocation/binding/policy with compile().
embodichain/lab/sim/atomic_actions/targets.py Removes legacy shared target contracts (ActionTarget-based), replaced by goal contracts.
embodichain/lab/sim/atomic_actions/primitives/press.py Refactors Press from execute() to plan() and replaces PressTarget with PressGoal.
embodichain/lab/sim/atomic_actions/primitives/place.py Refactors Place to plan() and replaces PlaceTarget/AssembleTarget with PlaceGoal/AssembleGoal plus StateDelta.
embodichain/lab/sim/atomic_actions/primitives/pick_up.py Refactors PickUp to plan() and replaces GraspTarget with GraspGoal plus StateDelta.
embodichain/lab/sim/atomic_actions/primitives/move_joints.py Refactors MoveJoints to plan() and replaces joint targets with typed joint goals.
embodichain/lab/sim/atomic_actions/primitives/move_held_object.py Refactors MoveHeldObject to plan() and replaces HeldObjectPoseTarget with HeldObjectPoseGoal.
embodichain/lab/sim/atomic_actions/primitives/move_end_effector.py Refactors MoveEndEffector to plan() and replaces EndEffectorPoseTarget with EndEffectorPoseGoal.
embodichain/lab/sim/atomic_actions/primitives/hand_over.py Refactors HandOver to plan() and uses policy-driven sample budgeting + StateDelta effects.
embodichain/lab/sim/atomic_actions/primitives/coordinated_placement.py Refactors CoordinatedPlacement to plan() with binding validation and StateDelta effects.
embodichain/lab/sim/atomic_actions/primitives/coordinated_pickment.py Refactors CoordinatedPickment to plan() with binding validation and StateDelta effects.
embodichain/lab/sim/atomic_actions/primitives/_helpers.py Updates helper utilities to operate on PlanningContext and return owned pose tensors.
embodichain/lab/sim/atomic_actions/primitives/init.py Updates public primitive exports from targets to goals.
embodichain/lab/sim/atomic_actions/policies.py Adds MotionPolicy and RecoveryPolicy configclasses used per invocation.
embodichain/lab/sim/atomic_actions/invocation.py Adds the grounded ActionInvocation contract for deterministic planning/execution.
embodichain/lab/sim/atomic_actions/goals.py Adds goal protocols and late-bound scene goal types (SceneEntityPose) with resolution helpers.
embodichain/lab/sim/atomic_actions/engine.py Replaces run() with initial_context(), compile(), and start() plus strict plan/context validation.
embodichain/lab/sim/atomic_actions/effects.py Adds declarative StateDelta expected effects with masked application semantics.
embodichain/lab/sim/atomic_actions/bindings.py Adds ActionBinding to map semantic roles to embodiment resources.
embodichain/lab/sim/atomic_actions/actions.py Removes legacy compatibility re-export facade.
embodichain/lab/sim/atomic_actions/init.py Re-exports new typed planning/execution API surface and built-in goals/actions.
docs/source/api_reference/embodichain/embodichain.lab.sim.atomic_actions.targets.rst Removes API docs page for deleted legacy targets module.
docs/source/api_reference/embodichain/embodichain.lab.sim.atomic_actions.rst Updates API reference to new planning/execution contracts and goal-based primitives.
docs/source/api_reference/embodichain/embodichain.lab.sim.atomic_actions.primitives.rst Updates primitives docs from target/execute/world-state to invocation/plan/context/effects.
agent_context/topics/atomic-actions/atomic-actions.md Updates agent-facing atomic-actions context to the new typed planning + recovery runtime.
agent_context/MAP.yaml Updates atomic-actions topic routing keywords and source-of-truth paths to new modules.
Suppressed comments (1)

scripts/benchmark/atomic_action/place_benchmark.py:333

  • is_success is later used in Python boolean contexts (bool(is_success), is_success and ..., elif not is_success). Since plan_success is a tensor mask, this will crash at runtime unless reduced to a bool.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

),
)
)
is_success = result.plan_success
)
)
is_success, traj, final_state = result
is_success = result.plan_success
),
)
)
is_success = result.plan_success
)
)
is_success, traj, _ = result
is_success = result.plan_success
elapsed, mem_delta, peak_gpu, result = timed_call(
lambda: atomic_engine.compile(steps)
)
is_success = result.plan_success
)
)
is_success, traj, final_state = result
is_success = result.plan_success
),
)
)
is_success = result.plan_success
Copilot AI review requested due to automatic review settings August 2, 2026 15:40

Copilot AI 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.

Pull request overview

Copilot reviewed 62 out of 62 changed files in this pull request and generated no new comments.

Suppressed comments (8)

scripts/benchmark/atomic_action/place_benchmark.py:235

  • CompiledTrajectory.plan_success is a per-environment bool tensor. Using it directly in a Python if not is_success condition will raise when the benchmark runs with more than one environment. Convert it to a scalar boolean (e.g., all() + .item()) before branching.
    scripts/benchmark/atomic_action/place_benchmark.py:333
  • result.plan_success is a vector mask; later code uses bool(is_success) / elif not is_success, which will error when multiple envs are present. Store a scalar is_success boolean derived from the mask (typically all() for benchmarks) and keep the trajectory/state separate.
    scripts/benchmark/atomic_action/move_held_object_benchmark.py:250
  • plan_success is returned as a per-env tensor mask. Using if not is_success will raise for multi-env runs. Convert to a scalar boolean (e.g., all().item()) before branching in this precondition helper.
    scripts/benchmark/atomic_action/move_held_object_benchmark.py:348
  • result.plan_success is a per-environment tensor mask but this function later treats is_success as a boolean (e.g., bool(is_success), elif not is_success). Convert to a scalar boolean derived from the mask to avoid ambiguous truth-value errors when multiple envs are used.
    scripts/benchmark/atomic_action/pickup_benchmark.py:201
  • result.plan_success is a per-environment boolean tensor, but this benchmark later uses bool(is_success) and if is_success ..., which will raise when more than one environment is active. Convert the mask to a scalar is_success boolean (e.g., all().item()) before using it in control flow and reporting.
    scripts/benchmark/atomic_action/move_end_effector_benchmark.py:146
  • CompiledTrajectory.plan_success is a per-environment tensor mask. This benchmark treats is_success as a Python boolean (bool(is_success), if is_success ...), which will fail for multi-env runs. Convert to a scalar boolean derived from the mask (e.g., all().item()).
    scripts/benchmark/atomic_action/move_joints_benchmark.py:155
  • result.plan_success is a vector mask over environments. The code later treats is_success as a boolean (bool(is_success), if is_success ...), which will raise when batch size > 1. Convert it to a scalar boolean (e.g., all().item()) before branching/reporting.
    scripts/benchmark/atomic_action/press_benchmark.py:599
  • This function returns planning_success which is used as a boolean by callers, but result.plan_success is a per-environment tensor mask. Convert to a scalar boolean (e.g., all().item()) to avoid ambiguous truth-value errors if the benchmark is ever run with multiple environments.

Copilot AI review requested due to automatic review settings August 2, 2026 17:59

Copilot AI 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.

Pull request overview

Copilot reviewed 67 out of 67 changed files in this pull request and generated no new comments.

Suppressed comments (2)

scripts/benchmark/atomic_action/place_benchmark.py:240

  • result.plan_success is a per-environment torch.Tensor; using if not is_success will raise RuntimeError: Boolean value of Tensor with more than one value is ambiguous when running with num_envs > 1. Convert to a scalar with .all().item() (or otherwise aggregate) before using it in a Python boolean context.
    scripts/benchmark/atomic_action/move_held_object_benchmark.py:253
  • is_success is a per-environment torch.Tensor; if not is_success is invalid when there is more than one environment row. Use an explicit reduction (e.g., .all().item()) before using it in a Python boolean context.

Copilot AI review requested due to automatic review settings August 3, 2026 15:19

Copilot AI 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.

Copilot wasn't able to review this pull request because it exceeds the maximum number of lines (20,000). Try reducing the number of changed lines and requesting a review from Copilot again.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

atomic action atomic action related functionality breaking motion gen Things related to motion generation for robot refactor

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants