:py:mod:`viam.components.arm` ============================= .. py:module:: viam.components.arm Submodules ---------- .. toctree:: :titlesonly: :maxdepth: 1 arm/index.rst client/index.rst service/index.rst Package Contents ---------------- Classes ~~~~~~~ .. autoapisummary:: viam.components.arm.KinematicsFileFormat viam.components.arm.Pose viam.components.arm.JointPositions viam.components.arm.Arm .. py:class:: KinematicsFileFormat Bases: :py:obj:`_KinematicsFileFormat` .. py:class:: Pose(*, x: float = ..., y: float = ..., z: float = ..., o_x: float = ..., o_y: float = ..., o_z: float = ..., theta: float = ...) Bases: :py:obj:`google.protobuf.message.Message` Pose is a combination of location and orientation. Location is expressed as distance which is represented by x , y, z coordinates. Orientation is expressed as an orientation vector which is represented by o_x, o_y, o_z and theta. The o_x, o_y, o_z coordinates represent the point on the cartesian unit sphere that the end of the arm is pointing to (with the origin as reference). That unit vector forms an axis around which theta rotates. This means that incrementing / decrementing theta will perform an inline rotation of the end effector. Theta is defined as rotation between two planes: the first being defined by the origin, the point (0,0,1), and the rx, ry, rz point, and the second being defined by the origin, the rx, ry, rz point and the local Z axis. Therefore, if theta is kept at zero as the north/south pole is circled, the Roll will correct itself to remain in-line. .. py:attribute:: x :type: float millimeters from the origin .. py:attribute:: y :type: float millimeters from the origin .. py:attribute:: z :type: float millimeters from the origin .. py:attribute:: o_x :type: float z component of a vector defining axis of rotation .. py:attribute:: o_y :type: float x component of a vector defining axis of rotation .. py:attribute:: o_z :type: float y component of a vector defining axis of rotation .. py:attribute:: theta :type: float degrees .. py:class:: JointPositions(*, values: collections.abc.Iterable[float] | None = ...) Bases: :py:obj:`google.protobuf.message.Message` Abstract base class for protocol messages. Protocol message classes are almost always generated by the protocol compiler. These generated types subclass Message and implement the methods shown below. .. py:property:: values :type: google.protobuf.internal.containers.RepeatedScalarFieldContainer[float] A list of joint positions. Rotations values are in degrees, translational values in mm. The numbers are ordered spatially from the base toward the end effector This is used in GetJointPositionsResponse and MoveToJointPositionsRequest .. py:class:: Arm(name: str) Bases: :py:obj:`viam.components.component_base.ComponentBase` Arm represents a physical robot arm that exists in three-dimensional space. This acts as an abstract base class for any drivers representing specific arm implementations. This cannot be used on its own. If the ``__init__()`` function is overridden, it must call the ``super().__init__()`` function. :: from viam.components.arm import Arm # To use move_to_position: from viam.proto.common import Pose # To use move_to_joint_positions: from viam.proto.component.arm import JointPositions .. py:attribute:: SUBTYPE :type: Final .. py:method:: get_end_position(*, extra: Optional[Dict[str, Any]] = None, timeout: Optional[float] = None, **kwargs) -> viam.components.arm.Pose :abstractmethod: :async: Get the current position of the end of the arm expressed as a Pose. :: my_arm = Arm.from_robot(robot=robot, name="my_arm") # Get the end position of the arm as a Pose. pos = await my_arm.get_end_position() :returns: The location and orientation of the arm described as a Pose. :rtype: Pose .. py:method:: move_to_position(pose: viam.components.arm.Pose, *, extra: Optional[Dict[str, Any]] = None, timeout: Optional[float] = None, **kwargs) :abstractmethod: :async: Move the end of the arm to the Pose specified in ``pose``. :: my_arm = Arm.from_robot(robot=robot, name="my_arm") # Create a Pose for the arm. examplePose = Pose(x=5, y=5, z=5, o_x=5, o_y=5, o_z=5, theta=20) # Move your arm to the Pose. await my_arm.move_to_position(pose=examplePose) :param pose: The destination Pose for the arm. :type pose: Pose .. py:method:: move_to_joint_positions(positions: viam.components.arm.JointPositions, *, extra: Optional[Dict[str, Any]] = None, timeout: Optional[float] = None, **kwargs) :abstractmethod: :async: Move each joint on the arm to the corresponding angle specified in ``positions``. :: my_arm = Arm.from_robot(robot=robot, name="my_arm") # Declare a list of values with your desired rotational value for each joint on # the arm. degrees = [0.0, 45.0, 0.0, 0.0, 0.0] # Declare a new JointPositions with these values. jointPos = arm.move_to_joint_positions( JointPositions(values=[0.0, 45.0, 0.0, 0.0, 0.0])) # Move each joint of the arm to the position these values specify. await my_arm.move_to_joint_positions(positions=jointPos) :param positions: The destination ``JointPositions`` for the arm. :type positions: JointPositions .. py:method:: get_joint_positions(*, extra: Optional[Dict[str, Any]] = None, timeout: Optional[float] = None, **kwargs) -> viam.components.arm.JointPositions :abstractmethod: :async: Get the JointPositions representing the current position of the arm. :: my_arm = Arm.from_robot(robot=robot, name="my_arm") # Get the current position of each joint on the arm as JointPositions. pos = await my_arm.get_joint_positions() :returns: The current JointPositions for the arm. :rtype: JointPositions .. py:method:: stop(*, extra: Optional[Dict[str, Any]] = None, timeout: Optional[float] = None, **kwargs) :abstractmethod: :async: Stop all motion of the arm. It is assumed that the arm stops immediately. :: my_arm = Arm.from_robot(robot=robot, name="my_arm") # Stop all motion of the arm. It is assumed that the arm stops immediately. await my_arm.stop() .. py:method:: is_moving() -> bool :abstractmethod: :async: Get if the arm is currently moving. :: my_arm = Arm.from_robot(robot=robot, name="my_arm") # Stop all motion of the arm. It is assumed that the arm stops immediately. await my_arm.stop() # Print if the arm is currently moving. print(my_arm.is_moving()) :returns: Whether the arm is moving. :rtype: bool .. py:method:: get_kinematics(*, extra: Optional[Dict[str, Any]] = None, timeout: Optional[float] = None) -> Tuple[viam.components.arm.KinematicsFileFormat.ValueType, bytes] :abstractmethod: :async: Get the kinematics information associated with the arm. :: my_arm = Arm.from_robot(robot=robot, name="my_arm") # Get the kinematics information associated with the arm. kinematics = await my_arm.get_kinematics() # Get the format of the kinematics file. k_file = kinematics[0] # Get the byte contents of the file. k_bytes = kinematics[1] :returns: A tuple containing two values; the first [0] value represents the format of the file, either in URDF format or Viam's kinematic parameter format (spatial vector algebra), and the second [1] value represents the byte contents of the file. :rtype: Tuple[KinematicsFileFormat.ValueType, bytes] .. py:method:: from_robot(robot: viam.robot.client.RobotClient, name: str) -> typing_extensions.Self :classmethod: Get the component named ``name`` from the provided robot. :param robot: The robot :type robot: RobotClient :param name: The name of the component :type name: str :returns: The component, if it exists on the robot :rtype: Self .. py:method:: do_command(command: Mapping[str, ValueTypes], *, timeout: Optional[float] = None, **kwargs) -> Mapping[str, ValueTypes] :abstractmethod: :async: Send/Receive arbitrary commands to the Resource :: command = {"cmd": "test", "data1": 500} result = component.do(command) :param command: The command to execute :type command: Mapping[str, ValueTypes] :raises NotImplementedError: Raised if the Resource does not support arbitrary commands :returns: Result of the executed command :rtype: Mapping[str, ValueTypes] .. py:method:: get_geometries(*, extra: Optional[Dict[str, Any]] = None, timeout: Optional[float] = None) -> List[viam.proto.common.Geometry] :async: Get all geometries associated with the Component, in their current configuration, in the frame of the Component. :: geometries = await component.get_geometries() if geometries: # Get the center of the first geometry print(f"Pose of the first geometry's centerpoint: {geometries[0].center}") :returns: The geometries associated with the Component. :rtype: List[Geometry] .. py:method:: get_resource_name(name: str) -> viam.proto.common.ResourceName :classmethod: Get the ResourceName for this Resource with the given name :: # Can be used with any resource, using an arm as an example my_arm_name = my_arm.get_resource_name("my_arm") :param name: The name of the Resource :type name: str :returns: The ResourceName of this Resource :rtype: ResourceName .. py:method:: get_operation(kwargs: Mapping[str, Any]) -> viam.operations.Operation Get the ``Operation`` associated with the currently running function. When writing custom resources, you should get the ``Operation`` by calling this function and check to see if it's cancelled. If the ``Operation`` is cancelled, then you can perform any necessary (terminating long running tasks, cleaning up connections, etc. ). :param kwargs: The kwargs object containing the operation :type kwargs: Mapping[str, Any] :returns: The operation associated with this function :rtype: viam.operations.Operation .. py:method:: close() :async: Safely shut down the resource and prevent further use. Close must be idempotent. Later configuration may allow a resource to be "open" again. If a resource does not want or need a close function, it is assumed that the resource does not need to return errors when future non-Close methods are called. :: await component.close()