reachy2_sdk.grippers.gripper_joint

Reachy GripperJoint module.

Handles all specific methods to a GripperJoint.

  1"""Reachy GripperJoint module.
  2
  3Handles all specific methods to a GripperJoint.
  4"""
  5
  6import logging
  7from collections import deque
  8from typing import Deque, Optional
  9
 10import numpy as np
 11from reachy2_sdk_api.hand_pb2 import HandState
 12
 13from ..orbita.utils import to_internal_position, to_position
 14
 15
 16class GripperJoint:
 17    """Class to represent any gripper's joint of the robot.
 18
 19    The `GripperJoint` class provides methods to get output values of the joint, such as the opening,
 20    present position, and goal position. It also allows setting the goal position and checking the
 21    joint's movement status.
 22
 23    Attributes:
 24        opening: The opening of the joint as a percentage (0-100), rounded to two decimal places.
 25        present_position: The current position of the joint in degrees.
 26        goal_position: The target goal position of the joint in degrees.
 27    """
 28
 29    def __init__(
 30        self,
 31        initial_state: HandState,
 32    ):
 33        """Initialize the GripperJoint with its initial state.
 34
 35        This sets up the joint by assigning its state based on the provided initial values.
 36
 37        Args:
 38            initial_state: A HandState containing the initial state of the joint.
 39        """
 40        self._logger = logging.getLogger(__name__)
 41
 42        self._is_moving = False
 43        self._nb_steps_to_ignore = 0
 44        self._steps_ignored = 0
 45        self._last_present_positions_queue_size = 10
 46        self._last_present_positions: Deque[float] = deque(maxlen=self._last_present_positions_queue_size)
 47
 48        self._update_with(initial_state)
 49        self._last_present_positions.append(self._present_position)
 50        self._outgoing_goal_positions: Optional[float] = None
 51
 52    def __repr__(self) -> str:
 53        """Clean representation of a GripperJoint."""
 54        repr_template = "<GripperJoint on={is_on} present_position={present_position} goal_position={goal_position} >"
 55        return repr_template.format(
 56            is_on=self.is_on(),
 57            present_position=round(self.present_position, 2),
 58            goal_position=round(self.goal_position, 2),
 59        )
 60
 61    @property
 62    def opening(self) -> float:
 63        """Get the opening of the joint as a percentage.
 64
 65        Returns:
 66            The joint opening as a percentage (0-100), rounded to two decimal places.
 67        """
 68        return float(round(self._opening * 100, 2))
 69
 70    @property
 71    def present_position(self) -> float:
 72        """Get the current position of the joint.
 73
 74        Returns:
 75            The present position of the joint in degrees.
 76        """
 77        return to_position(self._present_position)
 78
 79    @property
 80    def goal_position(self) -> float:
 81        """Get the goal position of the joint.
 82
 83        Returns:
 84            The goal position of the joint in degrees.
 85        """
 86        return to_position(self._goal_position)
 87
 88    @goal_position.setter
 89    def goal_position(self, value: float | int) -> None:
 90        """Set the goal position for the joint.
 91
 92        Args:
 93            value: The goal position to set, specified as a float or int.
 94
 95        Raises:
 96            TypeError: If the provided value is not a float or int.
 97        """
 98        if isinstance(value, float) | isinstance(value, int):
 99            self._outgoing_goal_positions = to_internal_position(value)
100        else:
101            raise TypeError("goal_position must be a float or int")
102
103    def is_on(self) -> bool:
104        """Check if the joint is stiff.
105
106        Returns:
107            `True` if the joint is on (not compliant), `False` otherwise.
108        """
109        return not self._compliant
110
111    def is_off(self) -> bool:
112        """Check if the joint is compliant.
113
114        Returns:
115            `True` if the joint is off (compliant), `False` otherwise.
116        """
117        return bool(self._compliant)
118
119    def is_moving(self) -> bool:
120        """Check if the joint is currently moving.
121
122        Returns:
123            `True` if the joint is moving, `False` otherwise.
124        """
125        return self._is_moving
126
127    def _check_joint_movement(self) -> None:
128        """Check if the joint is still moving based on the present position.
129
130        This method updates the movement status by comparing the current position to the last few positions.
131        If the position has not changed significantly, the joint is considered to have stopped moving.
132        """
133        present_position = self._present_position
134        if (
135            len(self._last_present_positions) >= self._last_present_positions_queue_size
136            and np.isclose(present_position, self._last_present_positions[-1], np.deg2rad(0.1))
137            and np.isclose(present_position, self._last_present_positions[-2], np.deg2rad(0.1))
138        ):
139            self._is_moving = False
140            self._last_present_positions.clear()
141        self._last_present_positions.append(present_position)
142
143    def _update_with(self, new_state: HandState) -> None:
144        """Update the joint with a newly received (partial) state from the gRPC server.
145
146        This method updates the present position, goal position, opening, and compliance status.
147        It also checks if the joint is still moving based on the new state.
148
149        Args:
150            new_state: A HandState object representing the new state of the hand.
151        """
152        self._present_position = new_state.present_position.parallel_gripper.position.value
153        self._goal_position = new_state.goal_position.parallel_gripper.position.value
154        self._opening = new_state.opening.value
155        self._compliant = new_state.compliant.value
156        if self._is_moving:
157            self._check_joint_movement()
class GripperJoint:
 17class GripperJoint:
 18    """Class to represent any gripper's joint of the robot.
 19
 20    The `GripperJoint` class provides methods to get output values of the joint, such as the opening,
 21    present position, and goal position. It also allows setting the goal position and checking the
 22    joint's movement status.
 23
 24    Attributes:
 25        opening: The opening of the joint as a percentage (0-100), rounded to two decimal places.
 26        present_position: The current position of the joint in degrees.
 27        goal_position: The target goal position of the joint in degrees.
 28    """
 29
 30    def __init__(
 31        self,
 32        initial_state: HandState,
 33    ):
 34        """Initialize the GripperJoint with its initial state.
 35
 36        This sets up the joint by assigning its state based on the provided initial values.
 37
 38        Args:
 39            initial_state: A HandState containing the initial state of the joint.
 40        """
 41        self._logger = logging.getLogger(__name__)
 42
 43        self._is_moving = False
 44        self._nb_steps_to_ignore = 0
 45        self._steps_ignored = 0
 46        self._last_present_positions_queue_size = 10
 47        self._last_present_positions: Deque[float] = deque(maxlen=self._last_present_positions_queue_size)
 48
 49        self._update_with(initial_state)
 50        self._last_present_positions.append(self._present_position)
 51        self._outgoing_goal_positions: Optional[float] = None
 52
 53    def __repr__(self) -> str:
 54        """Clean representation of a GripperJoint."""
 55        repr_template = "<GripperJoint on={is_on} present_position={present_position} goal_position={goal_position} >"
 56        return repr_template.format(
 57            is_on=self.is_on(),
 58            present_position=round(self.present_position, 2),
 59            goal_position=round(self.goal_position, 2),
 60        )
 61
 62    @property
 63    def opening(self) -> float:
 64        """Get the opening of the joint as a percentage.
 65
 66        Returns:
 67            The joint opening as a percentage (0-100), rounded to two decimal places.
 68        """
 69        return float(round(self._opening * 100, 2))
 70
 71    @property
 72    def present_position(self) -> float:
 73        """Get the current position of the joint.
 74
 75        Returns:
 76            The present position of the joint in degrees.
 77        """
 78        return to_position(self._present_position)
 79
 80    @property
 81    def goal_position(self) -> float:
 82        """Get the goal position of the joint.
 83
 84        Returns:
 85            The goal position of the joint in degrees.
 86        """
 87        return to_position(self._goal_position)
 88
 89    @goal_position.setter
 90    def goal_position(self, value: float | int) -> None:
 91        """Set the goal position for the joint.
 92
 93        Args:
 94            value: The goal position to set, specified as a float or int.
 95
 96        Raises:
 97            TypeError: If the provided value is not a float or int.
 98        """
 99        if isinstance(value, float) | isinstance(value, int):
100            self._outgoing_goal_positions = to_internal_position(value)
101        else:
102            raise TypeError("goal_position must be a float or int")
103
104    def is_on(self) -> bool:
105        """Check if the joint is stiff.
106
107        Returns:
108            `True` if the joint is on (not compliant), `False` otherwise.
109        """
110        return not self._compliant
111
112    def is_off(self) -> bool:
113        """Check if the joint is compliant.
114
115        Returns:
116            `True` if the joint is off (compliant), `False` otherwise.
117        """
118        return bool(self._compliant)
119
120    def is_moving(self) -> bool:
121        """Check if the joint is currently moving.
122
123        Returns:
124            `True` if the joint is moving, `False` otherwise.
125        """
126        return self._is_moving
127
128    def _check_joint_movement(self) -> None:
129        """Check if the joint is still moving based on the present position.
130
131        This method updates the movement status by comparing the current position to the last few positions.
132        If the position has not changed significantly, the joint is considered to have stopped moving.
133        """
134        present_position = self._present_position
135        if (
136            len(self._last_present_positions) >= self._last_present_positions_queue_size
137            and np.isclose(present_position, self._last_present_positions[-1], np.deg2rad(0.1))
138            and np.isclose(present_position, self._last_present_positions[-2], np.deg2rad(0.1))
139        ):
140            self._is_moving = False
141            self._last_present_positions.clear()
142        self._last_present_positions.append(present_position)
143
144    def _update_with(self, new_state: HandState) -> None:
145        """Update the joint with a newly received (partial) state from the gRPC server.
146
147        This method updates the present position, goal position, opening, and compliance status.
148        It also checks if the joint is still moving based on the new state.
149
150        Args:
151            new_state: A HandState object representing the new state of the hand.
152        """
153        self._present_position = new_state.present_position.parallel_gripper.position.value
154        self._goal_position = new_state.goal_position.parallel_gripper.position.value
155        self._opening = new_state.opening.value
156        self._compliant = new_state.compliant.value
157        if self._is_moving:
158            self._check_joint_movement()

Class to represent any gripper's joint of the robot.

The GripperJoint class provides methods to get output values of the joint, such as the opening, present position, and goal position. It also allows setting the goal position and checking the joint's movement status.

Attributes:
  • opening: The opening of the joint as a percentage (0-100), rounded to two decimal places.
  • present_position: The current position of the joint in degrees.
  • goal_position: The target goal position of the joint in degrees.
GripperJoint(initial_state: hand_pb2.HandState)
30    def __init__(
31        self,
32        initial_state: HandState,
33    ):
34        """Initialize the GripperJoint with its initial state.
35
36        This sets up the joint by assigning its state based on the provided initial values.
37
38        Args:
39            initial_state: A HandState containing the initial state of the joint.
40        """
41        self._logger = logging.getLogger(__name__)
42
43        self._is_moving = False
44        self._nb_steps_to_ignore = 0
45        self._steps_ignored = 0
46        self._last_present_positions_queue_size = 10
47        self._last_present_positions: Deque[float] = deque(maxlen=self._last_present_positions_queue_size)
48
49        self._update_with(initial_state)
50        self._last_present_positions.append(self._present_position)
51        self._outgoing_goal_positions: Optional[float] = None

Initialize the GripperJoint with its initial state.

This sets up the joint by assigning its state based on the provided initial values.

Arguments:
  • initial_state: A HandState containing the initial state of the joint.
opening: float
62    @property
63    def opening(self) -> float:
64        """Get the opening of the joint as a percentage.
65
66        Returns:
67            The joint opening as a percentage (0-100), rounded to two decimal places.
68        """
69        return float(round(self._opening * 100, 2))

Get the opening of the joint as a percentage.

Returns:

The joint opening as a percentage (0-100), rounded to two decimal places.

present_position: float
71    @property
72    def present_position(self) -> float:
73        """Get the current position of the joint.
74
75        Returns:
76            The present position of the joint in degrees.
77        """
78        return to_position(self._present_position)

Get the current position of the joint.

Returns:

The present position of the joint in degrees.

goal_position: float
80    @property
81    def goal_position(self) -> float:
82        """Get the goal position of the joint.
83
84        Returns:
85            The goal position of the joint in degrees.
86        """
87        return to_position(self._goal_position)

Get the goal position of the joint.

Returns:

The goal position of the joint in degrees.

def is_on(self) -> bool:
104    def is_on(self) -> bool:
105        """Check if the joint is stiff.
106
107        Returns:
108            `True` if the joint is on (not compliant), `False` otherwise.
109        """
110        return not self._compliant

Check if the joint is stiff.

Returns:

True if the joint is on (not compliant), False otherwise.

def is_off(self) -> bool:
112    def is_off(self) -> bool:
113        """Check if the joint is compliant.
114
115        Returns:
116            `True` if the joint is off (compliant), `False` otherwise.
117        """
118        return bool(self._compliant)

Check if the joint is compliant.

Returns:

True if the joint is off (compliant), False otherwise.

def is_moving(self) -> bool:
120    def is_moving(self) -> bool:
121        """Check if the joint is currently moving.
122
123        Returns:
124            `True` if the joint is moving, `False` otherwise.
125        """
126        return self._is_moving

Check if the joint is currently moving.

Returns:

True if the joint is moving, False otherwise.