Skip to main content

Overview

Wuji Hand 2 fingertip tactile sensors describe their data format through metadata. Read each finger’s info metadata before subscribing, then use its format JSON to decode the data frame. The field describes the contact layout, units, and mounting pose. The application must read the metadata before decoding data frames. When firmware changes the point count, units, or mounting pose, the decoder can use the updated metadata. This capability depends on the hardware configuration. 2.1 hardware has no fingertip tactile sensors, which arrive with 2.2 hardware. The test device used for this page does not provide the capability. This page documents capability detection, failure behavior, and handling. For supported devices, follow the interface definition and product specification. Matching examples: examples/python/wuji_hand_2/3.fingertip_typed.py and examples/c/wuji_hand_2/3_fingertip.c. For the interface list, the field definitions of the self-describing format, and the calibration interface, see Wuji Hand 2 Fingertip Tactile. This page covers only how to run it and what the measurements show.

Prerequisites

Hardware

What 2.2 ships is a contact array: 40 contacts on the thumb and 34 on each other finger, each reporting three-axis force plus temperature at 100 Hz.

Software

Before You Start

Confirm the device has this capability. The next section shows how.

Detect Device Capability

The most reliable runtime check reads the resource list. Don’t infer it from a version number:
Measured on a device without it, topics() holds no fingertip entries at all. A device with it lists five fingertip/<finger>/data topics. This check needs no try/except and doesn’t depend on mapping hardware or firmware versions.

Data Flow

Read the sensor metadata before subscribing to the data stream. The data frame does not contain a complete format description, so it cannot be decoded correctly without the metadata.

The format Field

info.format is a JSON string that describes the data layout. The decoder is driven by its fields. The key fields: The field-type to unpack-format mapping is defined in one table. Unknown types raise an error:
Unknown field types raise an error. An incorrect field mapping causes the frame to fail decoding.

Self-Checking the Data Length

Compute the expected length before decoding and fail outright on a mismatch:
This check surfaces an info-to-data version mismatch on the very first frame.

Units Change With Firmware, So Read Them From format

Starting with firmware v2.4.0, per-contact force is normalized to the sensor’s full scale: 0 to 1 on the normal axis, −1 to 1 on the tangential axes, clipped beyond that. Earlier firmware reports newtons. The aggregate force and temperature stay in newtons and degrees Celsius on both. So pick your contact threshold from the declared unit rather than hard-coding it:
After a firmware upgrade, re-read info so the decoder picks up the new scale and unit.

Placing Contacts on the Hand Model

positions and point_rpy live in the sensor module’s own frame, and base_xyz with base_rpy give that frame’s pose relative to the finger’s tip_sensor_frame. So contact i sits in finger coordinates at:
Its force-axis rotation is R(base_rpy) @ R(point_rpy[i]). The aggregate can be recovered as a true wrench: the force is R(base_rpy) @ R(aggregate_rpy) @ (fx, fy, fz), the application point is R(base_rpy) @ aggregate_xyz + base_xyz, and the moment about the link origin is p × f. These three mounting-pose keys were added to the contract together. The example branches on that: all three missing means older firmware where position information isn’t available, while only some missing means the metadata itself is broken, which raises. Firmware without aggregate_xyz reports neither an application point nor a moment. Do not calculate these values when the field is missing. The device reports poses for its own handedness, so the same code is correct on left and right hands.

SDK Version Compatibility

This change affects interface compatibility. The C side matches, where wuji_hand_2_get_fingertip_thumb_info(dev, &out) replaces wuji_hand_2_get_fingertip_info(dev, finger, &out). There’s no compatibility shim. Measured, calling the new interface on v2026.8.31:
On the C side it fails at link time on the removed symbol. The struct layout didn’t change, so an old binary reports the missing symbol during linking. The old interface takes an integer, and the binding layer rejects a string:
Where 0=thumb, 1=index, 2=middle, 3=ring, 4=pinky.
The examples in the repository follow the newest interface. Running them against an older SDK raises AttributeError while reading info. That isn’t a device problem.

Measured Behavior on Unsupported Devices

Device details: firmware_version = 1.3.0 and hw_version = HwVersion(major=0, minor=2, patch=0). All four paths fail, with errors from different layers: All five fingers report the same error from get_fingertip_info, and topics() holds no fingertip entries either. Note that the Python object does have fingertip_thumb_data, get_fingertip_info, tactile_calibrate, and tactile_status. A method existing doesn’t mean the device supports it, because the SDK’s interface surface is defined per product while what works depends on the device’s resource list.

Runtime Handling

One finger failing to report info is normal, not a fault. The example skips it and decodes the rest, stopping only when all five fail.

Integration Steps

Running It

With the capability present, the Python example redraws in place at 100 Hz: one status line per finger (aggregate force, temperature, contact count, and the strongest contact’s position), followed by a table of fx / fy / fz per contact. Each round drains the subscription queue first so only the newest frame shows. It runs 15 seconds by default. On a device without the capability, all four paths fail:
These are real results, on firmware 1.3.0, hardware version 0.2.0, and SDK v2026.8.31.

Recalibration and Status Queries

On a device with the capability, hand.tactile_calibrate() resets all five fingertips to a fresh zero baseline. The C side is wuji_hand_2_tactile_calibrate(dev). The sensor surfaces must be unloaded during calibration. Nothing touching them, nothing pressing against them. Afterward, hand.tactile_status(finger) reports each sensor’s model and calibration state, which confirms it finished. Every frame summary on the joint_diagnostics stream carries a fingertip tactile online bitmap, so you can monitor which fingertips are online without polling.

Configuration and Adaptation

Lower the Stream Rate

Five contact arrays at 100 Hz add up. fingertip/*/data is a rate-control entry point, so a subscription handle’s set_rate() lowers it, which needs firmware v2.3.0 or later. See Wuji Hand 2 Adjusting Stream Rate.

Re-Read info After a Firmware Upgrade

scale, unit, and the mounting poses in format can all change with firmware. Skip the re-read and your decoder parses new data against the old contract, giving wrong numbers with no error. Read info right after every connection and don’t cache it to disk.

When You Only Care Whether Something Is Touched

If you don’t need three-axis force per contact, the aggregate section’s fx/fy/fz plus a threshold is enough, with no need to decode individual contacts. The aggregate is in newtons on every firmware and isn’t affected by normalization.

Tolerate Per-Finger Failure

All five fingers report info independently. In production code, handle failure per finger so one finger’s problem doesn’t break the whole pipeline. That’s how the example was changed.