Motion control
Choose between target motion, application-driven Servo, and SDK-managed drag control.
| Task | Entry point | Behavior |
|---|---|---|
| Hand or local target motion | move_to(), move_joint(), move_finger(), move_thumb() | Returns MotionHandle; can be waited on or cancelled |
| Continuous high-rate targets | open_servo() | Application owns send timing, timeout, and shutdown |
| SDK-managed drag | start_servo_drag() | SDK owns the drag-control loop |
| Teaching and replay | Teach / Replay APIs | Records and replays full-hand trajectories |
Do not emulate Servo by repeatedly calling move_to(). Target operations may preempt one another, so check the final OperationState.
Single-command control (SDK 2.1.2)
hand.motion.set_position(), set_current(), and set_mit() send one full-hand command without open_servo(), a heartbeat, or automatic resend. These controls currently support enabled 21-DOF models only. Arrays use logical joint order, degrees, rpm, and mA; MIT feedforward current is also in mA.
Use set_joint_*, set_finger_*, or set_thumb_* for scoped commands. Joint indices are 0–20; finger indices 1–4 identify Index, Middle, Ring, and Pinky, with a separate thumb scope. Finger and thumb writes are sequential, not atomic; inspect device state after failure.
Run these read-only commands from the public example repository root:
python python/revo3/discrete_control.py --scope joint --joint-index 0 --mode position
python python/revo3/discrete_control.py --scope finger --finger-index 1 --mode mit
./c/build/demo/discrete_control --scope thumb --mode currentAdd --run to send a command. Position mode sends the current pose; current mode sends zero current; MIT mode sends the current pose with kp=1, kd=0.1, zero velocity, and zero feedforward current. These commands can change support or motor behavior. Clear the workspace and confirm the stop procedure first. Firmware determines target retention; closing the connection does not stop control. A command may have taken effect despite an error, so inspect state before retrying.
Upstream final-wheel validation covered scoped controls on UV5 firmware 0.1.2 over CAN FD. Modbus passed with a candidate implementation, but the final-wheel retest found no device; this does not establish final-release Modbus validation. See the public example notes.
Whole-hand control mode (SDK 2.3.0)
Call await hand.motion.get_control_mode() or await hand.motion.set_control_mode(sdk.HandControlMode.Mit) only after confirming firmware support. The values are Position=0, Damping=5, and Mit=6. A mode change affects the whole hand and may change support; secure the device and confirm the stop procedure first. The setter itself sends no motion target.
The whole-hand mode is separate from the command type used by set_mit() and set_joint_mit(). Those existing methods still send position, velocity, Kp, Kd, and feedforward current without automatically switching the whole-hand mode. If newer firmware is in Position or Damping, explicitly select Mit before MIT control. MIT position error depends on gains and mechanical conditions; tune gains for the actual joint.
Use existing controls on older firmware without calling the new mode APIs. Connection and existing control calls do not automatically access the mode register. Hide or disable UI mode selection according to confirmed firmware capabilities; a communication error is not a capability result. See python/revo3/control_mode.py in the public example repository and the complete API contract for exact behavior.
Preflight
- Match every target array to
joint_layout. - Read State and preserve joints that should not change.
- Check Health and motor fault codes.
- Pass degree, rpm, and mA values directly; do not apply register scaling.
- Use a bounded wait for every motion.
Run the examples
Preview a motion from the public example repository root without connecting a device:
python python/revo3/gesture_dance_demo.pyThe opposition, finger motion, gesture choreography, and sinusoidal Servo examples connect and move only with --run. Calibrate candidate poses for the actual device and validate left and right hands separately. See the motion demonstration guide for commands and tuning.
MIT round trips should validate full-hand targets, including stationary joints, and the speed limits for both outbound and return motion. The default initial position tolerance is 0.1°; clamp accepted feedback overruns to the configured limits before using them as command targets. The Python teaching example uses teaching_mode.py read FILE to record and save a trajectory and teaching_mode.py load FILE to load and immediately replay it. Check the motion area and stop procedure before replay.
Wait for the result
handle = await hand.motion.move_joint(
joint_index=0,
target_position=20.0,
duration=1.0,
)
result = await handle.wait(timeout=3.0)
if result != sdk.OperationState.Succeeded:
raise RuntimeError(f"Motion ended in {result}")Timeout only stops the caller from waiting; it does not guarantee that physical motion stopped. For Indeterminate, read State before retrying. See the Motion API.