MAKIINASDK

GuidesMove joints

Move joints safely

Set limits, move one joint or many, reach named poses with a smooth ramp, then hold or release the robot.

This guide takes you from a fresh session to smooth, repeatable joint moves. It works the same for an arm on your PC and for the full robot; the examples use the right arm's joint names, J01-R to J06-R.

Set the limits first

The robot does not move until your first motion command. Use that moment to set the two limits it enforces on its own side:

Python
robot.safety.set_torque_fraction(0.4)       # 40 % of each joint's current limit
robot.safety.set_max_joint_velocity(1.0)    # rad/s at the joint

Every later command is clamped by these limits, however large a step you ask for. Start low and raise them once your code behaves.

Move one joint

A relative move adds to the current target:

Python
robot.control.set_joints_relative({"J01-R": 0.1})     # base turns 0.1 rad

An absolute move sets the target directly:

Python
robot.control.set_joints_absolute({"J01-R": 0.0})     # base back to 0 rad

Joints you do not name keep their target. On the very first command both kinds start from the measured pose, so the arm never jumps to a stale target. The call returns at once; the joint runs to its target at no more than the velocity limit.

A joint name the robot does not have raises an error that lists the valid names. Either spelling works: the wire names (J01-R, J01-L) and the part names (right_J1, left_J1).

Move several joints at once

Python
robot.control.set_joints_absolute({"J02-R": 1.1, "J03-R": -1.1, "J04-R": -0.9})

All named joints start together, and each runs at up to the velocity limit, so short moves finish before long ones.

Reach a named pose

Every robot model declares two poses: zero, with the arms stretched straight out, and neutral, a folded ready pose.

Python
poses = robot.model.named_poses()           # {"zero": {...}, "neutral": {...}}
robot.control.set_joints_absolute(poses["neutral"])

Move smoothly over a set time

A single absolute command makes every joint run at the velocity limit and stop abruptly. For a move that starts and ends gently and takes a known time, stream intermediate targets. This is what Go neutral does in the console:

Python
import time

def move_to(target, seconds=2.0, hz=50):
    start = robot.sensors.get_joints()
    steps = int(seconds * hz)
    for k in range(1, steps + 1):
        a = k / steps
        a = a * a * (3 - 2 * a)             # smoothstep: gentle start and stop
        robot.control.set_joints_absolute(
            {j: start[j] + a * (target[j] - start[j]) for j in target})
        time.sleep(1 / hz)

move_to(robot.model.named_poses()["neutral"], seconds=2.0)

The ramp starts from the measured joints, not from an old target, so it is safe to call after the arm was moved by hand. Ctrl+C in the middle of it leaves the arm holding where it got to.

Know what you commanded

Python
robot.control.get_commanded_joints()    # the targets being sent right now
robot.sensors.get_joints()              # where the joints actually are

The difference between the two is the tracking error. It is small at rest and grows while a joint is moving or pushing against something.

Hold, release, and let go

Python
robot.control.stop()        # disarm: the robot holds its pose, motion commands pause
robot.safety.torque_off()   # release the motors: the arm sags under its weight
robot.safety.torque_on()    # energise again: the arm holds where it is now

After stop() nothing moves until your next motion command, which re-arms the session and continues from the targets you had. torque_off() is the way to move an arm by hand; support it before you call it.

What happens if your script dies

Your session sends commands continuously in the background, at 90 Hz by default. If they stop arriving for 30 seconds, because your process crashed or the network went away, the robot server shuts down and the session ends. The drives keep their last target, so the arm stays where it was.

Python
robot.actuation.get_frequency()     # 90.0, the rate commands are resent at
robot.actuation.set_frequency(60)