Skip to content

atomic action#243

Open
matafela wants to merge 10 commits intoyueci/atomic-action-initfrom
cj/atomic-action-init
Open

atomic action#243
matafela wants to merge 10 commits intoyueci/atomic-action-initfrom
cj/atomic-action-init

Conversation

@matafela
Copy link
Copy Markdown
Collaborator

@matafela matafela commented Apr 22, 2026

Description

  • Implement atomic action.
  • Fix qpos seed shape error in MotionGenerator.
  • Fix waypoint buliding error in ToppraPlanner
  • example: ‵scripts/tutorials/sim/atom_action.py`

TODO:

  • Place and Move action
  • comments and docs
  • unittest

Fixes # (issue)

  • Fix qpos seed shape error in MotionGenerator.
  • Fix waypoint buliding error in ToppraPlanner

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)

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.

@matafela matafela marked this pull request as draft April 22, 2026 08:44
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

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 introduces an “atomic actions” workflow for simulation (engine + actions + semantics), adds a runnable tutorial script, and fixes two motion-planning issues (Toppra waypoint construction and MotionGenerator IK seed shaping).

Changes:

  • Add/extend atomic action engine semantics resolution (including dict “convenience” targets) and new action implementations (pick/place/move).
  • Fix planner bugs: Toppra waypoint building and MotionGenerator qpos_seed/batch-IK seed shaping.
  • Add a tutorial script and expand atomic-action unit tests.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 16 comments.

Show a summary per file
File Description
embodichain/lab/sim/atomic_actions/core.py Refactors affordances/semantics and action base config; adds AntipodalAffordance and binds affordance geometry.
embodichain/lab/sim/atomic_actions/engine.py Adds dict target resolution + enhanced SemanticAnalyzer; changes action instantiation to accept configs.
embodichain/lab/sim/atomic_actions/actions.py Adds new Move/PickUp/Place actions and adjusts existing actions to new base init.
embodichain/lab/sim/atomic_actions/__init__.py Updates exports (but currently inconsistent with removed GraspPose).
embodichain/lab/sim/planners/motion_generator.py Fixes qpos seed fallback and passes correctly-shaped joint_seed into batch IK.
embodichain/lab/sim/planners/toppra_planner.py Fixes waypoint building by converting qpos tensors to CPU numpy arrays.
tests/sim/atomic_actions/test_core.py Adds new tests for affordance geometry/custom_config and dict-target convenience; still references removed GraspPose.
scripts/tutorials/sim/atom_action.py Adds an example script demonstrating registration and execution of atomic actions.

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

Comment on lines +317 to 318
cfg: ActionCfg = ActionCfg(),
):
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

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

AtomicAction.__init__(..., cfg: ActionCfg = ActionCfg()) uses an instance as a default argument, so all actions created without an explicit cfg will share the same config object. Use cfg: ActionCfg | None = None and instantiate a fresh config inside __init__.

Suggested change
cfg: ActionCfg = ActionCfg(),
):
cfg: ActionCfg | None = None,
):
if cfg is None:
cfg = ActionCfg()

Copilot uses AI. Check for mistakes.
Comment on lines +147 to +153
approach_direction: torch.Tensor = torch.tensor(
[0, 0, -1], dtype=torch.float32
),
) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor]:
if self.generator is None:
self._init_generator()

Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

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

get_best_grasp_poses() uses a default approach_direction=torch.tensor(...) created on CPU at import time. If obj_poses/the generator are on GPU, this can cause device-mismatch errors. Prefer approach_direction: torch.Tensor | None = None and create/to(obj_poses.device) inside the method.

Suggested change
approach_direction: torch.Tensor = torch.tensor(
[0, 0, -1], dtype=torch.float32
),
) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor]:
if self.generator is None:
self._init_generator()
approach_direction: torch.Tensor | None = None,
) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor]:
if self.generator is None:
self._init_generator()
if approach_direction is None:
approach_direction = torch.tensor(
[0, 0, -1], dtype=torch.float32, device=obj_poses.device
)
else:
approach_direction = approach_direction.to(
device=obj_poses.device, dtype=torch.float32
)

Copilot uses AI. Check for mistakes.
Comment on lines +140 to +144
grasp_affordance = AntipodalAffordance(
object_label=label,
poses=default_poses,
grasp_types=["default"],
)

# Default interaction points
interaction_affordance = InteractionPoints(
object_label=label,
points=torch.zeros(1, 3),
point_types=["contact"],
custom_config=custom_config or {},
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

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

SemanticAnalyzer.analyze() constructs AntipodalAffordance with poses= and grasp_types=, but AntipodalAffordance doesn’t define those dataclass fields. This will raise TypeError when resolving a string/dict target. Either use an affordance type that supports poses (e.g. keep GraspPose) or update AntipodalAffordance’s API/fields accordingly.

Copilot uses AI. Check for mistakes.
Comment on lines +115 to +116
def create_robot(sim: SimulationManager, position=[0.0, 0.0, 0.0]):
"""
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

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

create_robot(..., position=[0.0, 0.0, 0.0]) uses a mutable list as a default argument. If the list is ever mutated, the default will be shared across calls. Use an immutable tuple (or None + assign inside) instead.

Copilot uses AI. Check for mistakes.
Comment on lines 173 to +177
self,
robot: "Robot",
motion_generator: "MotionGenerator",
device: torch.device = torch.device("cuda"),
actions_cfg_dict: Optional[Dict[str, ActionCfg]] = dict(),
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

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

actions_cfg_dict: Optional[Dict[str, ActionCfg]] = dict() is a mutable default argument and will be shared across AtomicActionEngine instances. Use None as the default and replace with a new {} inside __init__.

Copilot uses AI. Check for mistakes.
Comment thread tests/sim/atomic_actions/test_core.py Outdated
Comment on lines 22 to 26
from embodichain.lab.sim.atomic_actions import (
Affordance,
GraspPose,
InteractionPoints,
ObjectSemantics,
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

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

This test module imports and exercises GraspPose, but this PR removes GraspPose from the embodichain.lab.sim.atomic_actions public surface. Tests will fail to import/run until they’re updated to the new affordance type (e.g. AntipodalAffordance) or GraspPose is restored.

Copilot uses AI. Check for mistakes.
Comment on lines 268 to +272
label: str = "none"
"""Object category label (e.g., 'apple', 'bottle')."""

uid: Optional[str] = None
"""Optional unique identifier for the object instance."""
entity: BatchEntity | None = None
"""Optional reference to the underlying simulation entity representing this object."""
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

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

ObjectSemantics no longer defines a uid, but other new code in this PR (e.g. AtomicActionEngine._resolve_target) and tests still set/read semantics.uid. This will raise at runtime. Reintroduce uid: Optional[str] = None on ObjectSemantics (and keep it stable in __post_init__).

Copilot uses AI. Check for mistakes.

self.n_envs = self.robot.get_qpos().shape[0]
self.arm_joint_ids = self.robot.get_joint_ids(name=self.cfg.control_part)
self.dof = len(self.arm_joint_ids)
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

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

ReachAction.__init__ still accepts control_part/device (and robot) but the refactor now calls super().__init__(motion_generator) and doesn’t apply these arguments. This makes ReachAction silently use the default ActionCfg.control_part instead of the requested control_part. Either remove the unused params or update the init path to set self.control_part/config consistently.

Suggested change
self.dof = len(self.arm_joint_ids)
super().__init__(motion_generator)
self.robot = robot
self.control_part = control_part
self.device = device

Copilot uses AI. Check for mistakes.
Comment thread scripts/tutorials/sim/atom_action.py Outdated
)
from embodichain.lab.sim.planners import MotionGenerator, MotionGenCfg, ToppraPlannerCfg
import os
from embodichain.lab.sim.shapes import MeshCfg, CubeCfg
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

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

MeshCfg is imported twice (once at line 31 and again combined at line 45), and CubeCfg appears unused. Remove the duplicate import(s) to avoid confusion and potential lint failures.

Suggested change
from embodichain.lab.sim.shapes import MeshCfg, CubeCfg

Copilot uses AI. Check for mistakes.
Comment on lines +25 to +34
import open3d as o3d
import torch

from embodichain.lab.sim import SimulationManager, SimulationManagerCfg
from embodichain.lab.sim.objects import Robot, RigidObject
from embodichain.lab.sim.utility.action_utils import interpolate_with_distance
from embodichain.lab.sim.shapes import MeshCfg
from embodichain.lab.sim.solvers import PytorchSolverCfg
from embodichain.data import get_data_path
from embodichain.utils import logger
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

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

This tutorial script has several imports that appear unused (open3d as o3d, interpolate_with_distance, logger). If the repo enforces unused-import checks, this file will fail linting. Remove unused imports to keep the example minimal.

Suggested change
import open3d as o3d
import torch
from embodichain.lab.sim import SimulationManager, SimulationManagerCfg
from embodichain.lab.sim.objects import Robot, RigidObject
from embodichain.lab.sim.utility.action_utils import interpolate_with_distance
from embodichain.lab.sim.shapes import MeshCfg
from embodichain.lab.sim.solvers import PytorchSolverCfg
from embodichain.data import get_data_path
from embodichain.utils import logger
import torch
from embodichain.lab.sim import SimulationManager, SimulationManagerCfg
from embodichain.lab.sim.objects import Robot, RigidObject
from embodichain.lab.sim.shapes import MeshCfg
from embodichain.lab.sim.solvers import PytorchSolverCfg
from embodichain.data import get_data_path

Copilot uses AI. Check for mistakes.
@matafela matafela marked this pull request as ready for review April 22, 2026 11:37
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.

2 participants