Wuji Dexterous Hand — SDK Setup & Teleop Guide

Complete guide to connecting, streaming, and collecting demonstration data from the Wuji dexterous hand using the wujihandpy SDK, the JSONL bridge agent, and the Fearless Platform.

Device: Wuji Dexterous Hand Device type: wuji_hand Agent: wuji_glove_agent Stream: JSONL over stdout (subprocess) Default Hz: 30
Dexterous Hand Teleoperation JSONL Stream Tactile Pressure 5-Finger × 4-Joint IMU

1. Overview

The Wuji dexterous hand is a high-DOF robotic end effector designed for contact-rich manipulation teleoperation and imitation learning data collection. It provides 5 fingers with 4 joints each (5×4 = 20 joint positions), a 24×32 tactile pressure map, an IMU channel, and an EMF (electromagnetic field) sensor channel for auxiliary contact sensing. Together these signals give a rich state representation suitable for training manipulation policies that generalize across grasp types and object geometries.

The Wuji SDK ecosystem consists of two layers. The lower layer is the wujihandpy Python package that communicates directly with the hardware over USB (VID 0x0483 by default). The upper layer is the JSONL bridge pipeline used by the RoboticsCenter teleop infrastructure: wuji_hand_sdk_stream.py reads from wujihandpy and emits one JSON object per line to stdout; wuji_glove_agent.py launches this script as a subprocess, parses the JSONL, and forwards decoded sensor data to the Fearless Platform via WebSocket.

Wuji Studio (GUI application, v0.7.0 for amd64 Linux) provides standalone visualization of joint positions and pressure maps without the platform pipeline — useful for hardware bring-up and calibration verification.

2. Full Specifications

PropertyValue
Fingers5 (thumb, index, middle, ring, little)
Joints per finger4
Total joint positions20 (5×4 array, float, radians)
Tactile pressure map24 rows × 32 columns (768 values, float [0, 1])
IMU channels6-axis style (3-axis accelerometer + 3-axis gyro), up to 16 slots in stream
EMF channelPer-finger bend + hand-back yaw (dict keyed by finger name)
USB vendor ID0x0483 (default)
SDK packagewujihandpy (Python)
Studio applicationWuji Studio v0.7.0 (Linux amd64 .deb / .tar.gz / .zip)
Stream formatJSONL (one JSON object per line, stdout)
Default stream Hz30 Hz (configurable with --hz)
Hand sides supportedLeft, right, or auto-detected from first frame
Platform device typewuji_hand
Platform agent modulewuji_glove_agent
Backend WebSocket URLws://127.0.0.1:8000 (default)
Telemetry Hz30 Hz (configurable with --telemetry-hz)
Reconnect policyExponential backoff: 1s min, 10s max

3. Quick Start

Install SDK and connect

  1. Install the Wuji SDK Python package.
    pip install wujihandpy numpy
  2. Plug in the Wuji hand via USB. Confirm the device appears. On Linux: lsusb | grep 0483. Add your user to the dialout group if needed.
  3. Start the JSONL stream.
    python3 wuji_hand_sdk_stream.py --hand-side right --hz 30
    You should see JSON objects printed to stdout at 30 Hz, each containing bends, joint_actual_position_5x4, pressure_map_24x32, imu, and emf.
  4. Launch the teleop agent connected to the platform.
    python3 wuji_glove_agent.py \
      --session YOUR_SESSION_ID \
      --node-id wuji-right \
      --glove right
    The agent auto-launches the stream script as a subprocess and begins forwarding data to the platform WebSocket.

Mock mode (no hardware)

Use the included mock_wuji_stream.py to generate synthetic JSONL frames. This emits animated finger bends, a Gaussian pressure-blob tactile map, 6-axis IMU data, and EMF readings — all at configurable Hz:

python3 mock_wuji_stream.py --hz 30 --hand-side right --seed 42

To use the mock stream with the agent, override the default stream command:

python3 wuji_glove_agent.py \
  --session YOUR_SESSION_ID \
  --node-id wuji-mock \
  --wuji-cmd "python3 mock_wuji_stream.py --hz 30 --hand-side right"
Schema field in mock frames. Mock frames include a "schema": "wuji.mock.v1" field. The agent parses both mock and real frames identically — it looks for the bends, pressure_map_24x32, imu, and emf keys regardless of schema version.

4. SDK / Python Usage

JSONL frame format

Every frame emitted by wuji_hand_sdk_stream.py contains the following fields:

FieldTypeShape / RangeDescription
tsfloatUnix secondsFrame timestamp (time.time())
hand_sidestr"left" | "right"Which hand this frame belongs to
bendsdict5 keys, [0, 1]Per-finger normalized bend (thumb, index, middle, ring, little)
joint_actual_position_5x4list[list[float]]5×4, radiansRaw joint positions from wujihandpy, reshaped to 5 fingers × 4 joints
pressure_map_24x32list[list[float]]24×32, [0, 1]Tactile pressure distribution across hand surface
imulist[float]up to 16 values6-axis IMU: [ax, ay, az, gx, gy, gz, ...] (remaining slots zeroed)
emfdictper-finger + hand_backEMF sensor readings; each entry is a float or dict with "bend"/"angle" keys

The bends values are derived from joint_actual_position_5x4 by averaging the 4 joint angles per finger and normalizing from the [0, π/2] range to [0, 1]:

import numpy as np, math

pos = np.array(hand.read_joint_actual_position(timeout=0.4)).reshape(5, 4)
bends = {}
for i, finger in enumerate(["thumb","index","middle","ring","little"]):
    val = float(np.mean(pos[i]))
    bends[finger] = min(1.0, max(0.0, val / (math.pi / 2.0)))

Bridge agent internals

wuji_glove_agent.py wraps linker_glove_agent.py with a Wuji-specific argument set. Key parameters:

FlagDefaultDescription
--backendws://127.0.0.1:8000Platform WebSocket base URL
--session(required)Teleop session ID from the platform
--node-idwuji-glove-nodeIdentifier for this device node in the session
--gloveautoHand side: left, right, or auto (read from first frame)
--device-kindwuji_handDevice type registered with platform
--telemetry-hz30.0Telemetry forwarding rate to platform
--wuji-cmdpython3 wuji_hand_sdk_stream.py --hand-side right --hz 30Shell command that emits JSONL frames to stdout
--wuji-pressure-keypressure_map_24x32JSON key for the pressure map array
--wuji-emf-keyemfJSON key for the EMF readings
--wuji-imu-keyimuJSON key for the IMU array
--reconnect-min-s1.0Minimum reconnect backoff (seconds)
--reconnect-max-s10.0Maximum reconnect backoff (seconds)

The agent uses source: "wuji_jsonl" internally to route JSONL parsing through the Wuji-specific decoder in linker_glove_agent.py, which handles the bends, joint_angles, and emf field variants that different Wuji firmware versions may emit.

Bilateral (left + right) setup

Run two agent processes simultaneously with different node IDs connected to the same session:

# Terminal 1 — right hand
python3 wuji_glove_agent.py \
  --session RC-XXXX-XXXX --node-id wuji-right --glove right \
  --wuji-cmd "python3 wuji_hand_sdk_stream.py --hand-side right --serial-number SN001"

# Terminal 2 — left hand
python3 wuji_glove_agent.py \
  --session RC-XXXX-XXXX --node-id wuji-left --glove left \
  --wuji-cmd "python3 wuji_hand_sdk_stream.py --hand-side left --serial-number SN002"
Serial number selection. Pass --serial-number to wuji_hand_sdk_stream.py when multiple Wuji hands are connected to the same host. The stream script forwards this to wujihandpy.Hand(serial_number=...) for unambiguous USB device selection.

5. Platform Integration

The Fearless Platform WebSocket endpoint at /api/teleop/ws accepts the Wuji agent registration handshake. The agent sends:

{
  "role": "robot",
  "session_id": "RC-XXXX-XXXX",
  "member_id": "wuji-right",
  "node_id": "wuji-right",
  "node_role": "robot",
  "device_type": "wuji_hand",
  "capabilities": ["glove", "tactile", "telemetry"],
  "source_host": "hostname"
}

After receiving type: "ready", the agent streams telemetry frames. The platform maps the Wuji telemetry into the GloveWorkbench UI panel, which renders:

  • Real-time bend bars for all 5 fingers (from the normalized bends dict).
  • 24×32 tactile heatmap (from pressure_map_24x32), downsampled to display resolution as needed.
  • 6-joint display values mapped from bends (thumb→j1, index→j2, middle→j3, ring→j4, little→j5, average→j6).
  • Gesture state inferred from the overall close ratio (fist / half-close / open).

Episode recording

During an active recording session, every telemetry frame is archived as JSONL. Each row contains the full joints, pressure_map_24x32, imu, and emf payload alongside the session ID and millisecond timestamp. Episodes are available in the platform episode browser for playback, download, or direct ingestion into training pipelines.

Pressure map downsampling. The agent's internal downsample_matrix() function reduces the 24×32 map to a smaller display resolution when required. The full-resolution 24×32 array is always preserved in the JSONL episode archive regardless of display settings.

6. Troubleshooting

Symptom Likely Cause Fix
wujihandpy import error Package not installed or Python environment mismatch Run pip install wujihandpy in the active virtual environment. Confirm with python3 -c "import wujihandpy; print(wujihandpy.__version__)".
No device found at 0x0483 Wrong USB VID, hand not powered, or udev rules missing Run lsusb to confirm the device appears. Pass the correct --usb-vid to the stream script. On Linux, add a udev rule for the VID/PID or run as root for initial testing.
read_joint_actual_position timeout Hand firmware not responding or USB cable issue Increase the timeout: edit the timeout=0.4 call in wuji_hand_sdk_stream.py to timeout=1.0. Re-seat the USB cable. The stream script catches exceptions and emits an error frame to keep the pipeline alive.
Agent fails to connect to platform WebSocket Backend not running or wrong --backend URL Confirm the Fearless backend is running: curl http://localhost:8000/health. Pass the correct URL with --backend ws://HOST:PORT.
pressure_map_24x32 always zeros in platform Tactile hardware not present or firmware returning placeholder This is expected if only the joint position hardware is connected. Use mock_wuji_stream.py to verify the heatmap rendering pipeline. For production use, confirm your Wuji firmware version includes tactile sensor support.
Still stuck? Contact SVRC support with the Wuji Studio version, output of lsusb, and the first 10 lines of JSONL output from wuji_hand_sdk_stream.py.
New to robotics? Learn fundamentals — dexterous hands, teleop, imitation learning — at the SVRC Robotics Academy before integrating hardware.
Have a question? Ask the community or contact support with the output of lsusb and your Wuji SDK version.

Ready to collect dexterous hand data?

Register on the platform, connect your Wuji hand, and start your first episode in minutes.