The Python semantic API for Wuji Hand 2. Unified pattern:
hand.{resource}().{action}(). All operations target the whole hand (20 joints).wuji_sdk, pip install wuji-sdk)—for general installation, device connection, and data subscription, see the Wuji SDK docs. For source, see the wuji-sdk repository.
Connection
Network prerequisite: Wuji Hand 2 uses a static IP, not DHCP. Each device ships with a fixed address by handedness — left hand
192.168.1.110, right hand 192.168.1.111, gateway 192.168.1.1, subnet mask 255.255.255.0. Before the first connection, set your host NIC to the same subnet (for example 192.168.1.50), then connect by address. The factory IP is changeable later — see ip (SET/GET).Connect via SdkManager (Recommended)
device_name="wuji_hand_2" overloads of auto_connect and connect return a WujiHand2 instance directly (with type hints). handedness is mutually exclusive with sn and address. If multiple Hand 2 units of the same handedness are on the network, AmbiguousHandedness is raised—specify sn instead.
ConnectOptions
enable_bridge=False for exclusive single-client mode.
Instance Attributes
hand.hw_version().get() returns the factory hardware version HwVersion(major, minor, patch). 0.0.0 means it wasn’t written at the factory.
Hand-Level Resources
This section covers the whole-hand API (20 joints). Single-joint reads and actions go through theJointHandle returned by hand.joint(k) / hand.joints() (see Joint Traversal). The device runs in MIT control mode by default — the control mode isn’t set from the Python API.
handedness (GET)
Get the handedness result (left / right).online_joints_count (GET)
Get the online joint count (0–20).joint_diagnostics (SUB)
Joint diagnostics stream: subscribe to per-joint status word, current, bus voltage, temperature, and error code. Frames are variable-length and contain only online joints — identify each entry by itsnid. This stream and joint_states ride the same device stream, so lowering the push rate of one lowers both — see joint_states (SUB).
error_code_current with the static method WujiHand2.describe_error(code). The returned object carries the error name, description, severity (Warning / DeferredStop / ImmediateStop / Fatal), and clear_policy (AutoClear / ManualClear / NonClearable). Unknown codes return None. The code field of the returned object is an integer, the same value you passed in. Printing a diagnostics entry object shows error codes in hex.
For joint angles, use
position from the joint_states stream — the diagnostics stream doesn’t carry joint angles.comm_diag (GET, 1 Hz)
Communication diagnostics: returns the throughput / error rate of the 5 fingers, once per second.effort_limit (SET/GET)
Effort limit: read / write the per-joint torque cap (A).mit_params (SET/GET)
MIT impedance parameters: read / write per-joint kp / kd.clear_fault (EXEC)
Clear faults: a direct action. Without arguments it acts on the whole hand.User Origin
Calibrate the current physical position as the joint-side zero. If a joint is moving, it takes effect at the next IDLE.Enable / Disable / Emergency Stop
joint_states (SUB)
Joint state stream: subscribe to the real-time state frames of the 20 joints, at a native output rate of 1000 Hz. Lower the push rate through the subscription handle:sub.set_rate(hz) returns the rate in effect, and 0 restores the native rate — see Wuji SDK data subscription for full usage. This stream and joint_diagnostics ride the same device stream, so lowering the rate of one lowers both.
Push-rate tuning applies to the
joint_states, joint_diagnostics, fingertip tactile, and imu streams. Upgrade the firmware and the Wuji SDK together to versions that support it — see the release notes for the version requirements.position is the joint-side angle (rad) and velocity the joint-side angular velocity (rad/s)—this is the only recommended path for joint angle and speed. Frames are variable-length and contain only online joints — identify each entry by its nid. The joint_diagnostics stream doesn’t carry joint angles.joint_command (PUB)
Joint command: publish positions / velocities / torque feedforward for the 20 joints. Each send takes exactly 20JointCommand entries, one position / velocity / effort per joint.
Fingertip Tactile Streams (SUB)
Fingertip tactile requires Wuji Hand 2.2 (Beta) hardware equipped with the fingertip tactile sensors, plus firmware v2.1.0 and SDK v2026.7.21 or later, upgraded together.
FingertipSensorInfo metadata (its format JSON describes the data-frame layout), then subscribe to that finger’s FingertipSensorData stream and decode per the format. The thumb has 40 sensing points, the other fingers 34. The native output rate is 100 Hz, adjustable down through the subscription handle.
3.fingertip_typed.py example under examples/python/wuji_hand_2/.
Fingertip Tactile Calibration (EXEC) and Status (GET)
Zero-baseline recalibration: one call recalibrates all 5 fingertips to a fresh zero baseline.tactile_status is a blocking query (up to about 1 s). Calibration is complete once polling reads state == TactileState.Ready.
Flash Log Export (Diagnostics)
flash_<serial>_<YYYY-MM-DD_HHMMSS>.jsonl file to out_dir. Omit out_dir to use ~/.wuji/logs.
The SDK writes to a temporary file and makes the JSONL file available only after the export finishes. If the export fails, the SDK removes the temporary file, so the output directory contains no partial export.
When multiple sessions export logs from the same device, the SDK retries automatically. If the export still can’t finish, the call reports that the device is busy. The SDK removes the temporary files and doesn’t keep an unfinished log.
ip (SET/GET)
Read and write the device’s static IP address.set writes the new IP to the device’s flash. The firmware doesn’t hot-swap the running Ethernet stack, so the new IP takes effect only after the next reboot. Between set and reboot, get still returns the current IP.
set the new address, reboot the device, reconnect at the new IP, and get to confirm.
reboot (EXEC)
Reboot the device. The device disconnects and needs a fresh connection. Pair it withip().set() to apply a new IP written to flash.
imu (SUB)
Onboard IMU stream: pushes acceleration and angular velocity at a native output rate of 100 Hz, adjustable down through the subscription handle. The device does no onboard orientation fusion, so theorientation field is unavailable and orientation_covariance[0] = -1 marks it invalid per the ROS sensor_msgs/Imu convention. Data is reported in the IMU sensor’s own frame, and the mapping between its axes and the hand structure will be defined in a future hand model update.
ImuData is a cross-device shared type. See the Wuji SDK data reference for field definitions.
Joint Traversal
JointHandle provides label / index (for indexing into 20-element return arrays such as effort_limit() / mit_params()), plus single-joint resources and actions. FingerHandle traverses joints by finger.
JointHandle
Joint handle: provideslabel / index, single-joint resources, and single-joint actions.
FingerHandle
Finger handle: traverse the 4 joints of this finger.Data Types
JointDiagnosticsFrame / JointDiagnosticsEntry
Joint diagnostics frame: frame type of thehand.joint_diagnostics().subscribe() stream. Variable-length, online joints only.
MitParam
MIT parameters: element ofmit_params().get().
set accepts a single (kp, kd) (applied to all joints) or a list of 20 (per joint). get returns 20 entries — offline joints are None.
JointStateFrame
Joint state frame: return value ofhand.joint_states().subscribe().recv(). Variable-length, online joints only.
JointStateEntry
Single-joint state.JointCommand
Joint command: element of thejoint_command().publish().send() argument.
HandCommunicationDiagnostics
Communication diagnostics data.FingertipSensorInfo / FingertipSensorData
Fingertip sensor metadata and data frames: return value ofget_fingertip_info(finger) and frame type of the fingertip_{finger}_data subscriptions.
TactileStatus / TactileType / TactileState
Tactile status: return value ofhand.tactile_status(finger).
TactileState.Calibrating == 1.
StatusWord
Status word: the type of thestatus_word field on JointDiagnosticsEntry, the public status view exposed by the SDK.
Hand2CommSummary
Frame-level communication health summary: the type of thecomm field on JointDiagnosticsFrame, combining the device-internal bus view with the SDK-local end-to-end (Ethernet) view. The device-internal part comes from a snapshot the SDK refreshes automatically at 1 Hz — no polling required.
Reading the device-internal fields.
age_ms, tactile_* and the per-joint
comm_* fields all come from one snapshot the SDK refreshes at 1 Hz. The refresh is
deliberately skipped while a firmware upgrade or a tactile calibration is running, so a
briefly stale snapshot is expected rather than a fault. Tell the two cases apart with
comm_get_failures: a growing age_ms while comm_get_failures stays flat means the
refresh is being skipped on purpose, while comm_get_failures increasing means the refresh
itself is failing.Joint Numbering
Label format:
{finger}_S{1..4} (e.g. thumb_S1, pinky_S4).
Exception Handling
All SDK operation errors raise a unifiedWujiException whose message carries an error-type prefix (Disconnected, Timeout, PathNotFound, SchemaMismatch, SerializeError, …). Use try / except as needed.