"""End-effector handles for KinematicsHandle."""
from typing import TYPE_CHECKING, Optional
from olo.kinematics._timeouts import _DEFAULT_SHORT_TIMEOUT_SEC
from olo.kinematics.types import EndEffector, GripperInfo, GripperResult
if TYPE_CHECKING:
from olo.kinematics import Kinematics
class EndEffectorHandle:
"""Base class for namespace-scoped end-effector commands."""
def __init__(self, client: "Kinematics", namespace: str, info: EndEffector) -> None:
self._client = client
self.namespace = namespace
self.info = info
[docs]
class Gripper(EndEffectorHandle):
"""Gripper end-effector handle."""
[docs]
def __init__(
self,
client: "Kinematics",
namespace: str,
info: EndEffector,
gripper_info: GripperInfo,
) -> None:
super().__init__(client, namespace, info)
self._gripper_info = gripper_info
[docs]
def goal(
self,
position: float,
*,
max_effort: Optional[float] = None,
timeout: float = _DEFAULT_SHORT_TIMEOUT_SEC,
) -> GripperResult:
"""Command the gripper to a raw controller-coordinate target.
``position`` is passed straight through to the active controller, so its
meaning depends on the underlying hardware: it may be a physical aperture
distance or an actuator joint value. Use :meth:`open` and :meth:`close`
for portable, direction-independent intent. Treats a stall as success.
"""
return self._client.command_end_effector(
position=position,
robot_namespace=self.namespace,
planning_group=self.info.parent_group,
max_effort=max_effort,
accept_stall=True,
timeout=timeout,
)
[docs]
def open(
self,
*,
max_effort: Optional[float] = None,
timeout: float = _DEFAULT_SHORT_TIMEOUT_SEC,
) -> GripperResult:
"""Open the gripper to its declared open target.
Uses the open position from the robot description rather than a joint
limit, so it opens correctly regardless of controller direction. Strict:
a stall is treated as a failure.
"""
return self._client.command_end_effector(
position=self._gripper_info.open_position,
robot_namespace=self.namespace,
planning_group=self.info.parent_group,
max_effort=max_effort,
accept_stall=False,
timeout=timeout,
)
[docs]
def close(
self,
*,
max_effort: Optional[float] = None,
timeout: float = _DEFAULT_SHORT_TIMEOUT_SEC,
) -> GripperResult:
"""Close the gripper to its declared closed target.
Uses the closed position from the robot description and treats a stall as
success, since closing onto an object is the expected grasp outcome.
"""
return self.goal(
self._gripper_info.closed_position,
max_effort=max_effort,
timeout=timeout,
)
__all__ = ["EndEffectorHandle", "Gripper"]