Skip to main content

Overview

Configure MIT impedance control parameters, enable the motors, then interpolate smoothly from each joint’s measured position to zero and hold there. This is the basic pattern for controlling a Wuji Hand 2. The example homes the hand, but the same publisher.send() path carries teleoperation, trajectory playback, and output from a higher-level controller. Matching examples: examples/python/wuji_hand_2/2.publish.py and examples/c/wuji_hand_2/1_control_motion.c. For joint command fields and value ranges, see Joint State and Control, and for control modes and safety bounds, see Control Guide. This page covers only how to run it and what the measurements show.
This example enables the motors and drives every online joint. Clear people, cables, and desk objects from around the hand before starting, keep someone watching throughout, and stay ready to cut power.

Interpolation

Sending pos=0 directly and interpolating to pos=0 are entirely different motions under MIT impedance. MIT control produces torque proportional to position error. With the hand starting curled, the first frame at pos=0 carries an error of “current angle − 0”, and with kp=3 that becomes a large torque that snaps the hand back to zero. Interpolating means reading the current position first, then pulling the target linearly from there to 0. Each frame’s error stays small, torque stays small with it, and the whole motion is gentle. Gentleness comes from the target trajectory, not from lowering the gains, so kp and kd keep their normal values.

Prerequisites

Hardware

This example connects to the first Wuji Hand 2 it finds (hand_devices[0]). On a shared network, change it to name a serial number.

Software

Control Parameters

These three control values match the factory defaults, and reading them back returns kp=3, kd=0.05, effort_limit=1.5.

Data Flow

Parameter Setters Broadcast

set() on effort_limit and mit_params is polymorphic:

Runtime Handling

ext_state values: 0 is Init, 1 is Ready, 2 is Enabled, 3 is Stopped. Before enable every joint reads 1, and within 52 ms after enable every joint reads 2.

Integration Steps

Step 3 isn’t optional. In step 6, disable before closing the publisher.

Running It

Measurements

On a right-hand Wuji Hand 2 with all 20 joints online: There’s a 26x gap between enable() returning and the motors being ready. Commands sent inside that window are discarded or behave unexpectedly, which is why the wait is required. After homing, joints don’t land exactly on 0 but within 0.02 rad. MIT impedance is compliant control, and static friction plus gravity leave a steady-state offset between actual position and target. That’s normal.

Adapting It

Tune How Gentle Homing Is

Change HOME_SECONDS. A longer duration makes each frame’s position step smaller and the motion gentler. Don’t chase gentleness by lowering kp, which sacrifices tracking accuracy overall.

Feed Your Own Trajectory

Replace the interpolation in step 5 with your own trajectory source, leaving the publisher.send() call unchanged. Each send() carries a complete 20-element frame, which the SDK serializes and transmits without waiting for a response, so it sustains a high-rate loop.

Choosing a Publish Rate

The example uses 200 Hz. Higher rates make trajectories smoother, provided generating one frame stays reliably faster than the period. The measurement above shows an actual rate of exactly 200.0 Hz, so there’s headroom at this scale.

Controlling Only Some Joints

Every frame still carries the full 20-element array. For joints you don’t want to move, fill in their current measured positions rather than 0. Filling 0 commands them home, which is the trap the MIT joint sweep ran into.