Skip to content

Add coordinated placement and atomic action benchmarks - #318

Merged
skywhite1024 merged 11 commits into
mainfrom
ljd/coordinated_placement_atomic_actions
Jul 3, 2026
Merged

skywhite1024 merged 11 commits into
mainfrom
ljd/coordinated_placement_atomic_actions

Conversation

@skywhite1024

@skywhite1024 skywhite1024 commented Jun 20, 2026 •

Copy link
Copy Markdown
Collaborator

Description

This PR adds the atomic action updates needed for the current branch to merge directly into main:

  • CoordinatedPlacement, an object-centric dual-arm atomic action where both arms already hold objects: the support arm keeps holding the support object, while the placing arm aligns its held object, releases it, and retreats.
  • A bread-on-pan coordinated placement tutorial with target-axis visualization and a documented GIF.
  • The Press atomic action/tutorial documentation and the atomic action benchmark suite that were previously based on ljd/benchmark_atomic_actions.
  • Merge conflict resolution against latest origin/main, keeping main robot/tutorial refactors while preserving this PR branch atomic action additions.
  • Local tutorial .glb mesh assets under scripts/tutorials/atomic_action/ are no longer tracked by git and are ignored by .gitignore.

Dependencies: none beyond the existing simulation/tutorial dependencies.

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

Screenshots

See docs/source/_static/atomic_actions/coordinated_placement.gif and the built-in atomic actions documentation.

Notes

  • CoordinatedPlacementTarget explicitly carries both placing/support HeldObjectState values instead of relying on the single-slot WorldState.held_object to represent dual held objects.
  • On success, WorldState.held_object is updated to the support object held state, because the placing object has been released while the support object remains held.
  • The coordinated placement tutorial draws target axes at the support/placing object target poses.
  • bread.glb, pan.glb, and table.glb are kept as local ignored tutorial assets instead of committed PR files.

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 my fix is effective or that my feature works
  • Dependencies have been updated, if applicable.

Tests

  • conda run -n embodichain python -m pytest tests/sim/atomic_actions/test_actions.py tests/sim/atomic_actions/test_trajectory.py
  • conda run -n embodichain black --check --diff --color ./
  • git diff --cached --check

@skywhite1024
skywhite1024 changed the base branch from ljd/press_atomic_actions to refactor/atomic-actions-redesign June 23, 2026 12:46
Base automatically changed from refactor/atomic-actions-redesign to main June 25, 2026 06:08
@skywhite1024
skywhite1024 force-pushed the ljd/coordinated_placement_atomic_actions branch from 297c3e6 to b9e4823 Compare June 26, 2026 03:07
@skywhite1024 skywhite1024 added docs Improvements or additions to documentation enhancement New feature or request motion gen Things related to motion generation for robot visualization Features or functions for visualization with the simulation labels Jun 26, 2026
@skywhite1024
skywhite1024 changed the base branch from main to ljd/benchmark_atomic_actions June 29, 2026 12:00
@skywhite1024
skywhite1024 changed the base branch from ljd/benchmark_atomic_actions to main July 1, 2026 12:41
@skywhite1024 skywhite1024 changed the title Add coordinated placement atomic action demo Add coordinated placement and atomic action benchmarks Jul 1, 2026
Copilot AI review requested due to automatic review settings July 1, 2026 13:34

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 PR expands EmbodiChain’s atomic action layer with new manipulation primitives and supporting developer tooling, including tutorials, documentation, benchmarks, and unit tests.

Changes:

  • Added two new atomic actions: Press (single-arm) and CoordinatedPlacement (dual-arm, object-centric target).
  • Added/updated tutorial utilities and a new press.py tutorial script, plus documentation updates to include the new actions/targets.
  • Introduced an atomic-action benchmark suite (dispatcher + per-action benchmarks) and integrated it into scripts/benchmark.

Reviewed changes

Copilot reviewed 21 out of 26 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
tests/sim/atomic_actions/test_actions.py Adds unit tests for Press and CoordinatedPlacement behavior/trajectory shapes.
scripts/tutorials/atomic_action/tutorial_utils.py Adds make_ur5_solver_cfg() and extends axis marker drawing with arena_index.
scripts/tutorials/atomic_action/press.py New tutorial script demonstrating Press planning/replay and target-axis visualization.
scripts/benchmark/atomic_action/run_benchmark.py New benchmark dispatcher to run one or many atomic-action benchmarks (optionally subprocess-isolated).
scripts/benchmark/atomic_action/press_benchmark.py New Press benchmark including timing/memory and “press center hit” metric + markdown report output.
scripts/benchmark/atomic_action/place_benchmark.py New Place benchmark (with PickUp precondition) using shared benchmark helpers.
scripts/benchmark/atomic_action/pickup_benchmark.py New PickUp benchmark using shared benchmark helpers.
scripts/benchmark/atomic_action/move_joints_benchmark.py New MoveJoints benchmark using shared benchmark helpers.
scripts/benchmark/atomic_action/move_held_object_benchmark.py New MoveHeldObject benchmark (with PickUp precondition) using shared benchmark helpers.
scripts/benchmark/atomic_action/move_end_effector_benchmark.py New MoveEndEffector benchmark using shared benchmark helpers.
scripts/benchmark/atomic_action/common.py New shared utilities for benchmark selection, timing/memory, video recording, and markdown reporting.
scripts/benchmark/atomic_action/init.py New benchmark package initializer.
scripts/benchmark/main.py Adds atomic-action subcommand wiring to the benchmark CLI.
embodichain/lab/sim/atomic_actions/core.py Introduces CoordinatedPlacementTarget and extends the Target union + exports.
embodichain/lab/sim/atomic_actions/actions.py Implements Press + CoordinatedPlacement actions and their config classes; updates module exports/docs.
embodichain/lab/sim/atomic_actions/init.py Re-exports new action types/configs/targets and updates module docs.
docs/source/tutorial/atomic_actions.rst Updates tutorial index to include Press and its demo script.
docs/source/overview/sim/atomic_actions/index.md Updates overview diagrams/tables to include CoordinatedPlacementTarget and new demos.
docs/source/overview/sim/atomic_actions/builtin_actions.md Documents Press and CoordinatedPlacement with config/target details and GIF references.
docs/source/api_reference/embodichain/embodichain.lab.sim.atomic_actions.rst Adds API reference entries for Press* and CoordinatedPlacement* symbols.

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

Comment on lines +394 to +398
def _default_object_types_for_profile(profile: str) -> tuple[str, ...]:
"""Return default Press primitive object names for a profile."""
if profile in ("smoke", "coverage", "full"):
return SMOKE_OBJECT_TYPES
raise ValueError(f"Unsupported benchmark profile: {profile}")
Copilot AI review requested due to automatic review settings July 2, 2026 14:09

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 20 out of 22 changed files in this pull request and generated 2 comments.

Comment on lines +50 to +64
def make_ur5_solver_cfg(tcp_z: float) -> URSolverCfg:
"""Create the UR5 arm solver cfg used by atomic-action tutorials."""
cfg = URSolverCfg(
ur_type="ur5",
end_link_name="ee_link",
root_link_name="base_link",
tcp=[
[1.0, 0.0, 0.0, 0.0],
[0.0, 1.0, 0.0, 0.0],
[0.0, 0.0, 1.0, tcp_z],
[0.0, 0.0, 0.0, 1.0],
],
)
cfg.urdf_path = None
return cfg
Comment on lines +394 to +398
def _default_object_types_for_profile(profile: str) -> tuple[str, ...]:
"""Return default Press primitive object names for a profile."""
if profile in ("smoke", "coverage", "full"):
return SMOKE_OBJECT_TYPES
raise ValueError(f"Unsupported benchmark profile: {profile}")
@skywhite1024
skywhite1024 force-pushed the ljd/coordinated_placement_atomic_actions branch from 8ed130f to 5873c4a Compare July 3, 2026 05:07
@skywhite1024
skywhite1024 merged commit 68b1e2c into main Jul 3, 2026
9 of 10 checks passed
@skywhite1024
skywhite1024 deleted the ljd/coordinated_placement_atomic_actions branch July 3, 2026 06:13
Yuan-Xinyi added a commit that referenced this pull request Sep 22, 2026
pick_up scores 52.08 % over coverage, place 37.50 % and move_held_object
27.08 %, and measuring where those cases go shows most of them are not skill
failures at all:

- Objects 0.18 m from the base sit in the arm's inner workspace. Every IK
  branch for such a grasp folds the shoulder back on itself, and driving the
  arm to any of them stalls: j1 stops 0.44 rad short with every other joint
  tracking to 0.01 rad and the limits nowhere near.
- A side approach asks for a horizontal gripper at the height of an object
  lying on the ground. Probing the same case at increasing heights, 0 of the
  sampled grasps are attainable at the object's own height and 3 of 3 become
  attainable once lifted 0.20 m, while the top approach is attainable at every
  height. The gripper is hitting the ground.

Both produce a plan that executes into thin air, and the skill's feasibility
screen cannot see either: it accepts a candidate when IK returns a solution,
which says a configuration exists, not that the arm can get to it.

has_attainable_grasp_candidate() drives each sampled grasp in physics,
pre-grasp then grasp, and stops at the first one that arrives. When none does,
the case is recorded with unsupported_capability, leaves every denominator and
lowers coverage_rate instead, which is what BENCHMARK_DESIGN.md section 5
prescribes for an unsupported case and what the standard now states for
success_rate. Supported cases pay one probe; only an unsupported one pays for
the whole candidate list.

The cases themselves are not touched: the positions, approaches and object
presets are #318's, unchanged here.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@Yuan-Xinyi Yuan-Xinyi mentioned this pull request Sep 22, 2026
6 tasks done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs Improvements or additions to documentation enhancement New feature or request motion gen Things related to motion generation for robot visualization Features or functions for visualization with the simulation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants