Manipulation and Head control the robot’s arm and head. Use them for manipulation tasks, gestures, and camera positioning.
Manipulation
False — so the happy path reads as a straight line and a failure can’t be silently ignored:
Both are importable from
innate.exceptions. If you don’t catch them, the run reports FAILURE with the message — usually exactly what you want.
Methods
Cartesian motion
Positions are metres inbase_link, orientations are radians:
move_to is FK-verified: after the motion it reads the real pose back, and if the arm is off target by more than the tolerance it recovers (reboot + torque on) and retries once before raising ArmUnhealthy. Pass tolerance_xy=None, tolerance_z=None to skip verification when contact is expected to stop the arm early.
move_by nudges from the arm’s measured pose rather than its last commanded one, which is the shape a visual-servoing loop wants:
Trajectories
follow() sweeps through waypoints as one smooth motion, starting from wherever the arm currently is:
follow() also beats a chain of move_to calls for anything gesture-like — the stop-and-go between separate moves is visible.
Joint motion
The gripper and the standing grip
strength is radians of preload past the closed stop, clamped to GRIPPER_MAX_STRENGTH (0.6) — beyond that the servo overcurrent-trips on a real object.
The claw runs under current-based position control, so the standing position error is the grip force. The interface remembers the last commanded claw position and carries it through every later motion, so an object stays held while the arm travels. You never thread a
gripper= argument through a trajectory, and re-reading the measured claw position — which would drop the object — is not something you can accidentally do.gripper_open() verifies the claw actually moved, since a tripped servo can stay shut, and reboots and retries once before raising ArmUnhealthy.
Doing something else while the arm moves
Passblock=False to return as soon as the command is accepted, then join with wait():
wait() is what surfaces a failure. Issuing a new command supersedes an unjoined motion.
Reading the arm
self.manipulation.pose returns an Arm — the same type as the ambient arm: Arm state feed, so a control loop reads one shape everywhere:
Servo power and recovery
bool rather than raising. move_to and gripper_open already call recover() for you on their retry path.
Head
Methods
Tilt angles
set_position returns immediately; the head takes a moment to arrive. If the next step depends on the new view, sleep first:
head_position: HeadState feed.
Example: a two-stroke wave
follow() per stroke rather than two move_to calls, so the arm sweeps instead of stopping at each end. No cancel() method and no cancellation checks: a Stop raises out of the blocking motion, and the framework halts the arm.

