Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Motion Control

Homing

Move all joints back to the zero position.

from realhand import A7

with A7(side="left", interface_name="can0") as arm:
    arm.enable()
    arm.home()  # Blocking mode
    arm.home(blocking=False)  # Non-blocking mode

Parameter:

  • blocking: Whether to block until motion completes. Default is True.

move_j

Move the arm by sending target joint angles for each joint.

from realhand import A7

with A7(side="left", interface_name="can0") as arm:
    arm.enable()
    arm.move_j([0.0, 0.0, 0.0, 1.57, 0.0, 0.0, 0.0])

Parameters:

  • target_joints: Target angles for the 7 joints in radians, type list[float]
  • blocking: Whether to block until motion completes, default True, type bool

Exceptions:

  • StateError: Called again while the arm is already moving
  • ValidationError: Target angles exceed joint limits

move_p

Move the arm by sending a TCP 6D pose (x, y, z, rx, ry, rz). The SDK first solves inverse kinematics and then executes joint motion. The end-effector path is not guaranteed to be a straight line.

from realhand import A7, Pose

with A7(side="left", interface_name="can0") as arm:
    arm.enable()
    target = Pose(x=0.0, y=0.33, z=-0.25, rx=1.85, ry=0.0, rz=-1.57)
    arm.move_p(target)

Parameters:

  • target_pose: Target TCP pose, type realhand.arm.Pose
  • current_angles: Initial IK guess for joint angles, type list[float] | None; when None, the SDK reads the motors
  • blocking: Whether to block until motion completes, type bool, default True

Exceptions:

  • StateError: Called again while the arm is already moving
  • RuntimeError: IK solving failed

move_l

Move the arm in a straight line by sending a TCP 6D pose (x, y, z, rx, ry, rz). The end effector follows a straight Cartesian path. Position uses trapezoidal velocity planning, and orientation uses spherical linear interpolation (Slerp). move_l always blocks until motion completes and therefore has no blocking parameter.

from realhand import A7, Pose

with A7(side="left", interface_name="can0") as arm:
    arm.enable()
    target = Pose(x=0.0, y=0.33, z=-0.25, rx=1.85, ry=0.0, rz=-1.57)
    arm.move_l(target)

Parameters:

  • target_pose: Target TCP pose, type Pose
  • max_velocity: Maximum linear speed for TCP trapezoidal planning in m/s, default 0.05, range (0, 0.4]
  • max_angular_velocity: Maximum angular speed for TCP rotation planning in rad/s, default 0.3, range (0, 3.0]
  • acceleration: Maximum linear acceleration for TCP trapezoidal planning in m/s², default 0.1, range (0, 1.0]
  • angular_acceleration: Maximum angular acceleration for TCP rotation planning in rad/s², default 0.1, range (0, 1.0]
  • current_pose: Starting TCP pose. If None, it is computed from current_angles or by reading the motors. Type Pose | None
  • current_angles: Starting joint angles. If None, they are read from the motors. Type list[float] | None

Exceptions:

  • StateError: Called again while the arm is already moving
  • ValidationError: A parameter is out of range
  • RuntimeError: IK failed for a path waypoint

Motion Status

Returns whether the arm is currently moving.

if arm.is_moving():
    print("Arm is moving...")

Return value:

  • bool: Whether the arm is moving

Wait for Motion Completion

Block the current thread until the motion timer reaches zero. This is typically used together with blocking=False.

arm.move_j([0.0, 0.0, 0.0, 1.57, 0.0, 0.0, 0.0], blocking=False)
# ... do other work ...
arm.wait_motion_done()  # Wait for motion to finish

Examples

Non-Blocking Motion and Waiting

from realhand import A7, Pose

with A7(side="left", interface_name="can0") as arm:
    arm.enable()
    arm.home()

    # Set speed and acceleration
    arm.set_velocities([1.0] * 7)
    arm.set_accelerations([10.0] * 7)

    # Non-blocking move_j: returns immediately after sending the command
    arm.move_j([0.0, 0.0, 0.0, 1.57, 0.0, 0.0, 0.0], blocking=False)
    print("move_j sent, arm is moving...")
    arm.wait_motion_done()  # Wait until the motion completes

    # Blocking move_p: returns only after motion is done
    target = Pose(x=0.0, y=0.33, z=-0.25, rx=1.85, ry=0.0, rz=-1.57)
    arm.move_p(target)

    # move_l is always blocking
    target = Pose(x=0.1, y=0.33, z=-0.2, rx=1.85, ry=0.0, rz=-1.57)
    arm.move_l(target)

    arm.home()