Source code for embodichain.lab.task_program.integrations.simulation.handover
# ----------------------------------------------------------------------------
# Copyright (c) 2021-2026 DexForce Technology Co., Ltd.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ----------------------------------------------------------------------------
"""Configured simulation integration for semantic hand-over poses."""
from __future__ import annotations
from dataclasses import dataclass
from typing import TYPE_CHECKING, ClassVar
from embodichain.lab.task_program.semantics import (
SemanticPose,
)
from embodichain.lab.task_program.compiler.lowering import (
HandOverPoseProvider,
HandOverPoseTargets,
SemanticObjectTarget,
)
if TYPE_CHECKING:
from embodichain.lab.sim.atomic_actions import PlanningContext
from embodichain.lab.task_program.semantics import BoundSemanticCall, HandOver
def _validated_pose(
position: tuple[float, float, float],
quaternion_wxyz: tuple[float, float, float, float],
*,
field_name: str,
) -> SemanticPose:
"""Build and validate one unbatched semantic pose declaration."""
if type(position) is not tuple or len(position) != 3:
raise TypeError(f"{field_name}_position must be an exact 3-tuple.")
if type(quaternion_wxyz) is not tuple or len(quaternion_wxyz) != 4:
raise TypeError(f"{field_name}_quaternion_wxyz must be an exact 4-tuple.")
try:
return SemanticPose(
position=position,
quaternion_wxyz=quaternion_wxyz,
)
except (TypeError, ValueError) as exc:
raise type(exc)(f"Invalid {field_name} hand-over pose: {exc}") from exc
[docs]
@dataclass(frozen=True, slots=True)
class ConfiguredHandOverPoseProvider(HandOverPoseProvider):
"""Resolve a hand-over delivery target from immutable configuration.
The provider carries object-space poses rather than arm trajectories. The
shared semantic compiler and atomic ``HandOver`` implementation remain
responsible for grasp selection, IK, motion generation, transfer, release,
and delivery. Keeping the numeric declaration as tuple fields also makes
the provider suitable for task-registration catalog fingerprinting.
Args:
final_position: World-frame object delivery position.
final_quaternion_wxyz: World-frame object delivery orientation.
"""
provider_id: ClassVar[str] = "simulation.configured_handover_pose"
final_position: tuple[float, float, float]
final_quaternion_wxyz: tuple[float, float, float, float]
def __post_init__(self) -> None:
final = _validated_pose(
self.final_position,
self.final_quaternion_wxyz,
field_name="final",
)
object.__setattr__(
self,
"final_position",
tuple(float(value) for value in final.position.tolist()),
)
object.__setattr__(
self,
"final_quaternion_wxyz",
tuple(float(value) for value in final.quaternion_wxyz.tolist()),
)
[docs]
def resolve(
self,
call: HandOver,
*,
context: PlanningContext,
bound: BoundSemanticCall,
) -> HandOverPoseTargets:
"""Return an independently owned object-space delivery target.
Args:
call: Canonical hand-over semantic call.
context: Latest immutable planning observation.
bound: Engine/profile-bound hand-over call.
Returns:
Configured final object-space target.
"""
del call, context, bound
return HandOverPoseTargets(
final=SemanticObjectTarget(
pose=SemanticPose(
position=self.final_position,
quaternion_wxyz=self.final_quaternion_wxyz,
)
),
)
__all__ = ["ConfiguredHandOverPoseProvider"]