MAKIINASDK

GuidesMove the gripper

Move the gripper in space

Read where each gripper is, preview a target with inverse kinematics, then move the gripper to a pose in metres.

Instead of thinking in joint angles, you can tell the robot where a gripper should be and let the kinematic twin work out the joints. This guide shows how to read a gripper's pose, try a target without moving anything, and then move there.

The twin comes with the native core, which the kit includes. In a checkout without it, the calls on this page raise an error that says so.

Read where a gripper is

Python
robot.model.ee_names()                       # ["right_arm", "left_arm"]

pose = robot.sensors.get_ee_poses()["right_arm"]
pose[:3, 3]                                  # position x, y, z in metres
pose[:3, :3]                                 # orientation, a 3x3 rotation

A pose is a 4x4 homogeneous transform of the gripper's base, in the robot's world frame (the base frame of its model), in metres. get_ee_poses() computes it from the measured joints, so it is where the gripper is now.

To see where any joint configuration would put the grippers, without moving anything:

Python
q = robot.model.named_poses()["neutral"]
robot.model.compute_ee_poses(q)              # {"right_arm": 4x4, "left_arm": 4x4}

Preview a target

solve_ik runs the same solver the robot uses and returns the joints that reach a pose. Nothing is sent to the robot, so you can use it to check a target before you commit to it:

Python
import numpy as np

target = robot.sensors.get_ee_poses()["right_arm"].copy()
target[2, 3] += 0.05                                 # 5 cm higher

q = robot.model.solve_ik({"right_arm": target})      # {"J01-R": ..., ...} rad
robot.model.compute_ee_poses(q)["right_arm"][:3, 3]  # where that really lands

A target out of reach does not raise an error; the solver returns the closest configuration it can reach. Compare the result with the target when it matters. This is what the console's copper ghost shows while you drag a handle with the robot disarmed.

Move a gripper to a pose

Python
robot.control.set_ee_poses_absolute({"right_arm": target})

The twin turns the pose into joint targets and those are what the robot receives. Arms you do not name keep their pose. The velocity limit still applies, so the gripper travels at the speed the joints allow, not in a straight line.

Move by an offset

A relative move adds an offset in the world frame:

Python
delta = np.eye(4)
delta[2, 3] = 0.02                                   # 2 cm up, along world z
robot.control.set_ee_poses_relative({"right_arm": delta})

Relative moves start from the pose you last commanded (the measured pose on the first command), so repeated calls add up.

Rotate a gripper in place

The offset of set_ee_poses_relative is applied in the world frame (new = delta @ current), so a rotation in it turns the gripper around the robot's origin, not around the gripper. To turn a gripper where it is, change only the rotation part of an absolute pose:

Python
def rot_z(angle):
    c, s = np.cos(angle), np.sin(angle)
    return np.array([[c, -s, 0], [s, c, 0], [0, 0, 1]])

pose = robot.sensors.get_ee_poses()["right_arm"].copy()
pose[:3, :3] = rot_z(0.2) @ pose[:3, :3]             # 0.2 rad about world z
robot.control.set_ee_poses_absolute({"right_arm": pose})

Follow a path

For a path, send a new pose every few milliseconds. The session resends the newest target at 90 Hz in the background, so your loop can be slower than that without the arm stopping between points. Fewer solver iterations keep each step quick, because each target is close to the last:

Python
import time

start = robot.sensors.get_ee_poses()["right_arm"]
for k in range(200):                                 # 4 s at 50 Hz
    p = start.copy()
    p[0, 3] += 0.04 * np.sin(2 * np.pi * k / 200)    # 4 cm back and forth in x
    robot.control.set_ee_poses_absolute({"right_arm": p}, iterations=10)
    time.sleep(0.02)

Open and close the gripper

Python
robot.control.set_ee_triggers({"right": 1.0})        # close
robot.control.set_ee_triggers({"right": 0.0})        # open
robot.sensors.get_ee_triggers()                      # what you last sent
robot.sensors.get_grippers()                         # the measured finger joints

Triggers run from 0 (open) to 1 (closed). The gripper names are in robot.capabilities["grippers"].