Motion Control
Homing
Move all joints to the zero position ([0.0] * 7).
from realhand import A7lite
with A7lite(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 isTrue.
move_j
Move the arm by sending target joint angles for each joint.
from realhand import A7lite
with A7lite(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], blocking=True)
Parameters:
target_joints: Target angles for the 7 joints in radians, typelist[float]blocking: Whether to block until motion completes, defaultTrue, typebool
Exceptions:
StateError: Called again while the arm is already movingValidationError: 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 A7lite
from realhand import Pose
with A7lite(side="left", interface_name="can0") as arm:
arm.enable()
target = Pose(x=0.3, y=0.1, z=0.5, rx=0.0, ry=0.5, rz=0.0)
arm.move_p(target)
Parameters:
target_pose: Target TCP pose, typePosecurrent_angles: Initial IK guess for joint angles, typelist[float] | None; whenNone, the SDK reads the motorsblocking: Whether to block until motion completes, typebool, defaultTrue
Exceptions:
StateError: Called again while the arm is already movingRuntimeError: 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 A7lite, Pose
with A7lite(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, max_velocity=0.1, acceleration=0.2)
Parameters:
target_pose: Target TCP pose, typePosemax_velocity: Maximum linear speed for TCP trapezoidal planning in m/s, default0.05, range(0, 0.4]max_angular_velocity: Maximum angular speed for TCP rotation planning in rad/s, default0.3, range(0, 3.0]acceleration: Maximum linear acceleration for TCP trapezoidal planning in m/s², default0.1, range(0, 1.0]angular_acceleration: Maximum angular acceleration for TCP rotation planning in rad/s², default0.1, range(0, 1.0]current_pose: Starting TCP pose. IfNone, it is computed fromcurrent_anglesor by reading the motors. TypePose | Nonecurrent_angles: Starting joint angles. IfNone, they are read from the motors. Typelist[float] | None
Exceptions:
StateError: Called again while the arm is already movingValidationError: A parameter is out of rangeRuntimeError: 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 A7lite, Pose
with A7lite(side="left", interface_name="can0") as arm:
arm.enable()
arm.home()
# 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, max_velocity=0.1, acceleration=0.2)
arm.home()