Requirements
The interfaces on this page apply to devices equipped with fingertip tactile sensors. Before subscribing, read the sensor metadata to confirm that the connected device provides the required interfaces. The examples on this page use Wuji SDK v2026.10.12 or later. Each capability requires the firmware version listed below or later.
The table below shows the currently documented sensor specifications, with a native output rate of 100 Hz. For the connected device, read the point count from
point_count in the FingertipSensorInfo.format JSON and the native output rate from FingertipSensorInfo.rate_hz.
After subscribing, use
Subscription.set_rate() to lower the output rate, and pass 0 to restore the device default. The C SDK uses wuji_sub_set_rate().
API Overview
Python’s
fingertip_<finger>_info(), fingertip_<finger>_data(), and fingertip_<finger>_status() name the finger in the method: thumb, index, middle, ring, or pinky. fingertip_online() returns five booleans in thumb-to-pinky order and reports whether each fingertip module is answering the hand heartbeat now. It doesn’t indicate whether a module is installed.
tactile_calibrate(), tactile_status(finger), TactileType, TactileState, and TactileStatus remain available as compatibility aliases, but they’re deprecated and will be removed in 2026.11. The C aliases wuji_hand_2_tactile_calibrate(), wuji_hand_2_tactile_status(), WujiTactileType, and WujiTactileState are deprecated as well. Use the fingertip names in the table for new code.Self-Describing Data Format
Read the finger’sFingertipSensorInfo first, then decode FingertipSensorData.data from its format JSON. Don’t hardcode the payload length, field offsets, scales, or units.
WujiException in that case. Skip that finger and keep decoding the others. This is an expected state, not a fault.
Metadata and Data Frames
The
v, encoding, point_count, point_stride, point_fields, aggregate_stride, aggregate_fields, and unit keys in format describe the payload. Check that v is 1 and encoding is point_array before decoding. The payload length equals point_count * point_stride + aggregate_stride, so use it to validate each frame. Each sensing point contains fx, fy, and fz. Aggregate fields provide the three-axis resultant force and temperature.
Normalized per-point force uses the sensor’s full scale. The normal axis ranges from 0 to 1, and the two tangential axes range from -1 to 1, clamped beyond that. Unnormalized per-point force is reported in newtons. Aggregate force stays in newtons, and temperature stays in degrees Celsius. Read scale and unit from format to support both formats.
Place Points on the Hand Model
Thepoint_rpy, base_xyz, and base_rpy fields in format describe the mounting pose. The format can include positions without the other mounting-pose fields. Treat the mounting pose as available only when point_rpy, base_xyz, and base_rpy are all present. positions and point_rpy must each contain point_count rows of three numbers. base_xyz and base_rpy must each contain three numbers. Treat a partial set or a shape mismatch as an invalid format instead of placing points with incomplete metadata.
positions and point_rpy use the sensor module frame. base_xyz and base_rpy describe that frame relative to the finger’s tip_sensor_frame. Convert each contact point and its force axes with:
R(rpy) uses URDF fixed-axis roll, pitch, and yaw: Rz(yaw) * Ry(pitch) * Rx(roll). format reports positions in meters and angles in radians. Both formulas transform values from the sensor module frame into the finger’s tip_sensor_frame.
The device reports the mounting pose that matches its handedness, so the same transform works for left and right hands. When none of the three mounting-pose keys is present, force data remains available, but the points can’t be placed on the hand model.
Locate the Resultant Force
Theaggregate_xyz and aggregate_rpy fields in format describe the resultant-force application point and orientation. aggregate_xyz is the fixed geometric centroid of the sensor pad in the sensor module frame, and the resultant force from aggregate_fields is applied at that point. The point doesn’t follow the center of pressure from frame to frame. Convert it to the finger link with:
aggregate_rpy describes the resultant-force axes in the same sensor module frame. Convert the force and its moment about the finger link origin with:
aggregate_xyz is fixed, moment_link is the moment of the resultant force about a fixed lever arm, not a measured contact moment.
Firmware that provides neither aggregate_xyz nor aggregate_rpy still reports the resultant force, but not its point of application or moment. When aggregate_rpy is absent, use the sensor mounting orientation R(base_rpy) alone for the force axes, whether or not aggregate_xyz is present. If aggregate_xyz or aggregate_rpy is present but doesn’t hold exactly three numbers, treat the whole format as invalid rather than as a missing field.
Read and Display Examples
The Python and C examples read metadata for all five fingers and build decoders that match the currentdigest. Python subscribes only to the fingers that report metadata, while C subscribes to all five streams and skips fingers without metadata when displaying. The terminal refreshes the same display area at 100 Hz to show:
- Resultant force, temperature, contact count, and strongest contact for each finger
- Three-axis force for every sensing point, where
fxandfyare tangential components along the local x- and y-axes, andfzis the normal component along the local z-axis - Position and force direction of the strongest contact
- Position of the aggregate force point and its moment about the origin of the finger link frame
Frame Handling and Status
The Python example drains every subscription queue on each refresh and displays only the newest frame for each finger. The C example stores the latest frame for each finger, then refreshes the display from the main thread. Wheninfo_digest differs from the current metadata, the corresponding status line tells you to read FingertipSensorInfo again and rebuild the decoder. When the payload length doesn’t match format, the example skips that finger’s frame while the other fingers keep updating.
The C example reports waiting, lagged, stream ended, stream error, metadata changed, and unexpected payload length on each finger’s status line. The Python example also keeps running after a payload-length error for one finger.
Format Validation
Both examples requireaggregate_fields to contain fx, fy, fz, and temperature. Before subscribing, the C example validates point counts, strides, field offsets, and scales. It rejects nonfinite values, noninteger layout values, out-of-range fields, and per-finger layouts larger than 2048 bytes.
When a force value exceeds the expected column width, the table widens the row instead of truncating it.
The examples select a contact threshold from the unit declared in format. They use 0.02 for normalized data and 0.2 N for data in newtons. These values serve the example display and aren’t part of the SDK data contract.
- Python:
3.fingertip_typed.py - C:
3_fingertip.c
C subscription callbacks run on SDK worker threads. The frame and its
data stay valid only for the callback duration. The example copies each payload into mutex-protected storage before the callback returns, then renders a five-finger snapshot on the main thread. Build it with the provided CMakeLists.txt, which links the math library and Threads/pthread. Close each subscription with wuji_sub_close() when the example exits.Zero-Baseline Calibration and Status
Keep all five sensor surfaces unloaded before calibration. One call triggers every sensor from thumb through pinky. The call raises an error on the first offline finger, and later fingers aren’t triggered. For the error types, see Handle an Offline Sensor.FingertipSensorState.Ready, and set an overall timeout for the wait. Each status query blocks for up to about one second, so one round over five fingers can take about five seconds, and the deadline is checked between rounds. The example treats a finger that raises NodeOfflineError as not ready and keeps waiting until the deadline.
FingertipSensorModel.Thumb identifies the 40-point thumb sensor, and FingertipSensorModel.Standard identifies a 34-point standard sensor. Runtime states include FingertipSensorState.Calibrating and FingertipSensorState.Ready.
Handle an Offline Sensor
A fingertip data subscription can still be created while its sensor is offline. If the subscription doesn’t receive any frames, callfingertip_<finger>_status().get() for that finger to check whether the sensor is offline.
With firmware that meets the offline-node error requirement:
- Python
fingertip_<finger>_info().get(),fingertip_<finger>_status().get(), andcalibrate_fingertipraiseNodeOfflineError. - The corresponding C calls return
WUJI_STATUS_ERR_NODE_OFFLINE (-12). - Generic GET, SET, and EXEC requests return the same typed result when their target is offline.
NodeOfflineError inherits from WujiException, not RuntimeError. Existing code that catches WujiException continues to work. Code that caught RuntimeError for these operations must catch NodeOfflineError or WujiException instead.
Tactile Communication Diagnostics
Subscribe withhand.joint_diagnostics().subscribe(), then read JointDiagnosticsFrame.comm from each frame that recv() or recv_async() returns:
comm includes tactile communication status:
Use
tactile_online_mask to locate an offline finger, then check the response rate and timeout count for continuing communication degradation.
The mask and both per-finger arrays come from a device-internal snapshot. When that snapshot is unavailable, all three read as zeros. Check age_ms before reading them as five offline fingers. A growing age_ms with a flat comm_get_failures means the SDK is skipping the refresh on purpose, which happens during tactile calibration and firmware upgrades. A growing age_ms with an increasing comm_get_failures means the refresh itself is failing.
For the full Hand2CommSummary field list, see Wuji Hand 2 SDK Reference — Hand2CommSummary.
For a measured run, how to detect the capability, and SDK interface compatibility, see Wuji Hand 2 Fingertip Tactile in practice.