SDK User Guide

API Reference

1. Field List

This section introduces all available data fields in wujihandpy.

1.1 Hand Layer

This layer contains device-unique general fields, such as handedness, firmware version, etc.

handedness

This field indicates the handedness of the dexterous hand (left/right hand, 0 for right, 1 for left).

  • Type: uint8
  • Read/Write: Read-only

firmware_version

This field indicates the version number of the dexterous hand firmware.

  • Type: uint32
  • Read/Write: Read-only

firmware_date

This field indicates the compilation date of the dexterous hand firmware.

  • Type: uint32
  • Read/Write: Read-only

system_time

This field indicates the system running time of the dexterous hand, in milliseconds.

  • Type: uint32
  • Read/Write: Read-only

temperature

This field indicates the current temperature near the wrist of the dexterous hand, in degrees Celsius.

  • Type: float32
  • Read/Write: Read-only

input_voltage

This field indicates the measured input voltage of the dexterous hand, in volts.

  • Type: float32
  • Read/Write: Read-only

1.2 Joint Layer

This layer contains fields where each joint holds an independent copy, such as enabled status, target position, etc.

joint_firmware_version

This field records the version number of the joint driver board firmware.

  • Type: uint32
  • Read/Write: Read-only

joint_firmware_date

This field records the compilation date of the joint driver board firmware.

  • Type: uint32
  • Read/Write: Read-only

joint_control_mode

This field is used to set the control mode of the joint.

  • Type: uint16
  • Read/Write: Write-only

Note: The mode switches automatically, and this field should not be modified under normal circumstances.

joint_sin_level

This field is used to set the sine wave excitation level of the joint drive.

  • Type: uint16
  • Read/Write: Write-only

Note: This field is used for internal debugging and should not be modified under normal circumstances.

joint_effort_limit

This field is used to set the upper effort limit allowed by the joint.

  • Type: float64
  • Unit: Ampere (A)
  • Default: 1.5
  • Valid Range: 0.0 ~ 3.5 (values exceeding 3.5 will be clamped to 3.5)
  • Read/Write: Read-Write

What is Effort?

Effort is the actuation value in current space, filtered before output. It is not the actual measured current—think of it as relative actuation strength, useful for load monitoring and collision detection. See joint_effort for details.

Thermal Protection: Effort Limit is dynamically adjusted based on temperature

To protect the device, the firmware automatically reduces the effective effort limit based on joint temperature:

Temperature StatusTrigger ConditionEffective Effort Limit
NormalBelow 85°CUser-set value (default 1.5A)
Temperature Warning (Tier 1)Greater than or equal to 85°CUser-set value × 70%
Temperature Alert (Tier 2)Greater than or equal to 93°CUser-set value × 40%

Recovery uses a 4°C hysteresis threshold:

  • Tier 2 returns to Tier 1 when temperature drops below 89°C
  • Tier 1 returns to Normal when temperature drops below 81°C

When the temperature returns to a safe range, the effort limit automatically recovers.

Warning: Modifying Effort Limit may cause device damage

Modifying this parameter changes the maximum output capability of the joint. Users are responsible for any damage caused by adjusting the effort limit.

  • Default value of 1.5 is suitable for most applications
  • Maximum value is 3.5, values exceeding this will be automatically clamped
  • Increasing this value increases joint load capacity but also increases the risk of damage
  • Affects joint lifespan and accelerates component wear with unpredictable impact
  • May cause irreversible damage to joints under certain operating conditions
  • May accelerate thermal protection triggering, reducing continuous operation time
  • May cause other serious consequences beyond those listed above

joint_bus_voltage

This field records the current measured bus voltage of the joint.

  • Type: float32
  • Read/Write: Read-only

joint_temperature

This field records the current temperature of the joint driver board, in degrees Celsius.

  • Type: float32
  • Read/Write: Read-only

joint_reset_error

Writing 1 to this field can clear the error status reported by the joint.

  • Type: uint16
  • Read/Write: Write-only

This field can only clear error codes and cannot resolve issues with the dexterous hand. Do not abuse this field, especially do not use it in a loop, as it may cause damage to the dexterous hand.

joint_error_code

This field indicates the current error code of each joint, used for diagnosing operational status. A value of 0 indicates no abnormality in the joint.

  • Type: uint32
  • Read/Write: Read-only

joint_effort

This field provides real-time effort feedback of the joint.

  • Type: float32
  • Unit: Ampere (A)
  • Read/Write: Read-only

Understanding Effort

Effort is the actuation effort in current space, filtered before output.

  • It is not the actual measured current
  • It is not the direct output of the current loop
  • Should be interpreted as relative actuation strength, suitable for load monitoring and collision detection

Typical use cases:

  • Collision detection: sudden increase in effort indicates joint obstruction
  • Output monitoring: calculate output percentage via effort / effort_limit

This field is only accessible through IController.get_joint_actual_effort() in real-time control mode.

joint_enabled

This field controls the enabling and disabling of the joint.

  • Type: bool
  • Default: False
  • Valid Range: True / False
  • Read/Write: Write-only

joint_actual_position

This field provides the actual position of the joint.

  • Type: float64
  • Read/Write: Read-only

joint_target_position

Writing to this field can issue the target control angle of the joint. If the value exceeds the valid range, it will be automatically clamped to the allowed interval.

  • Type: float64
  • Valid Range: joint_lower_limit ~ joint_upper_limit
  • Read/Write: Write-only

joint_upper_limit

This field records the upper position limit of the joint.

  • Type: float64
  • Read/Write: Read-only

Difference from URDF Joint Range

There are slight precision errors during joint processing, causing the actual physical limits of each joint to vary slightly. The dexterous hand calibrates the actual limits of each joint at the factory, and the results are written to the joint_upper_limit and joint_lower_limit fields. Therefore, these two fields record the calibrated actual physical limit values, which are usually slightly larger than the range defined in the URDF file.

The joint range in the URDF file is a theoretical design value, conservatively scaled to account for processing errors, and can be used for simulation or neural network training. While joint_upper_limit and joint_lower_limit represent the actual measured range of motion.

joint_lower_limit

This field records the lower position limit of the joint.

  • Type: float64
  • Read/Write: Read-only

2. API List

2.1 Hand Class

2.1.1 Constructor

  • __init__(serial_number=None, *, side=None, usb_pid=0x2000, usb_vid=0x0483, mask=None) -> None Initialize connection to the dexterous hand. Supports specifying the device by serial number, handedness, USB ID, or device mask.

    • serial_number: USB serial number string to select one device exactly
    • side: "left" or "right". Selects the device by handedness. Mutually exclusive with serial_number (see Tutorial §1.3)

2.1.2 Finger Access

  • finger(index) -> Finger Get the finger object at the specified index, index range 0-4

2.1.3 Thread Safety Control

  • disable_thread_safe_check() -> None Disable thread safety check to allow concurrent multi-threaded access to the Hand object

Note: After disabling the thread safety check, you must use synchronization mechanisms such as threading.Lock to ensure thread-safe operations.

2.1.4 System Information

Firmware Information
  • read_firmware_version(timeout=0.5) -> uint32 Synchronously read firmware version

  • read_firmware_version_async(timeout=0.5) -> Awaitable[uint32] Asynchronously read firmware version

  • read_firmware_version_unchecked(timeout=0.5) -> None Non-blocking read firmware version

  • get_firmware_version() -> uint32 Get cached firmware version

  • read_firmware_date(timeout=0.5) -> uint32 Synchronously read firmware compilation date

  • read_firmware_date_async(timeout=0.5) -> Awaitable[uint32] Asynchronously read firmware compilation date

  • read_firmware_date_unchecked(timeout=0.5) -> None Non-blocking read firmware compilation date

  • get_firmware_date() -> uint32 Get cached firmware compilation date

  • read_handedness(timeout=0.5) -> uint8 Synchronously read left/right hand identifier (0=right, 1=left)

  • read_handedness_async(timeout=0.5) -> Awaitable[uint8] Asynchronously read left/right hand identifier

  • read_handedness_unchecked(timeout=0.5) -> None Non-blocking read left/right hand identifier

  • get_handedness() -> uint8 Get cached left/right hand identifier

System Status
  • read_system_time(timeout=0.5) -> uint32 Synchronously read system running time (milliseconds)

  • read_system_time_async(timeout=0.5) -> Awaitable[uint32] Asynchronously read system running time

  • read_system_time_unchecked(timeout=0.5) -> None Non-blocking read system running time

  • get_system_time() -> uint32 Get cached system running time

  • read_temperature(timeout=0.5) -> float32 Synchronously read palm temperature (Celsius)

  • read_temperature_async(timeout=0.5) -> Awaitable[float32] Asynchronously read palm temperature

  • read_temperature_unchecked(timeout=0.5) -> None Non-blocking read palm temperature

  • get_temperature() -> float32 Get cached palm temperature

  • read_input_voltage(timeout=0.5) -> float32 Synchronously read input voltage (volts)

  • read_input_voltage_async(timeout=0.5) -> Awaitable[float32] Asynchronously read input voltage

  • read_input_voltage_unchecked(timeout=0.5) -> None Non-blocking read input voltage

  • get_input_voltage() -> float32 Get cached input voltage

2.1.5 Joint Data (Batch Read, Returns 4 Array)

Position Data
  • read_joint_actual_position(timeout=0.5) -> NDArray[float64] Synchronously read all joint actual positions (radians)

  • read_joint_actual_position_async(timeout=0.5) -> Awaitable[NDArray[float64]] Asynchronously read all joint actual positions

  • read_joint_actual_position_unchecked(timeout=0.5) -> None Non-blocking read all joint actual positions

  • get_joint_actual_position() -> NDArray[float64] Get cached all joint actual positions

  • read_joint_upper_limit(timeout=0.5) -> NDArray[float64] Synchronously read all joint upper limit positions (radians)

  • read_joint_upper_limit_async(timeout=0.5) -> Awaitable[NDArray[float64]] Asynchronously read all joint upper limit positions

  • read_joint_upper_limit_unchecked(timeout=0.5) -> None Non-blocking read all joint upper limit positions

  • get_joint_upper_limit() -> NDArray[float64] Get cached all joint upper limit positions

  • read_joint_lower_limit(timeout=0.5) -> NDArray[float64] Synchronously read all joint lower limit positions (radians)

  • read_joint_lower_limit_async(timeout=0.5) -> Awaitable[NDArray[float64]] Asynchronously read all joint lower limit positions

  • read_joint_lower_limit_unchecked(timeout=0.5) -> None Non-blocking read all joint lower limit positions

  • get_joint_lower_limit() -> NDArray[float64] Get cached all joint lower limit positions

Status Monitoring
  • read_joint_bus_voltage(timeout=0.5) -> NDArray[float32] Synchronously read all joint bus voltages (volts)

  • read_joint_bus_voltage_async(timeout=0.5) -> Awaitable[NDArray[float32]] Asynchronously read all joint bus voltages

  • read_joint_bus_voltage_unchecked(timeout=0.5) -> None Non-blocking read all joint bus voltages

  • get_joint_bus_voltage() -> NDArray[float32] Get cached all joint bus voltages

  • read_joint_temperature(timeout=0.5) -> NDArray[float32] Synchronously read all joint temperatures (Celsius)

  • read_joint_temperature_async(timeout=0.5) -> Awaitable[NDArray[float32]] Asynchronously read all joint temperatures

  • read_joint_temperature_unchecked(timeout=0.5) -> None Non-blocking read all joint temperatures

  • get_joint_temperature() -> NDArray[float32] Get cached all joint temperatures

  • read_joint_error_code(timeout=0.5) -> NDArray[uint32] Synchronously read all joint error codes

  • read_joint_error_code_async(timeout=0.5) -> Awaitable[NDArray[uint32]] Asynchronously read all joint error codes

  • read_joint_error_code_unchecked(timeout=0.5) -> None Non-blocking read all joint error codes

  • get_joint_error_code() -> NDArray[uint32] Get cached all joint error codes

Effort Limit Data
  • read_joint_effort_limit(timeout=0.5) -> NDArray[float64] Synchronously read all joint effort limits (Ampere)
  • read_joint_effort_limit_async(timeout=0.5) -> Awaitable[NDArray[float64]] Asynchronously read all joint effort limits
  • read_joint_effort_limit_unchecked(timeout=0.5) -> None Non-blocking read all joint effort limits
  • get_joint_effort_limit() -> NDArray[float64] Get cached all joint effort limits
Firmware Information
  • read_joint_firmware_version(timeout=0.5) -> NDArray[uint32] Synchronously read all joint firmware versions

  • read_joint_firmware_version_async(timeout=0.5) -> Awaitable[NDArray[uint32]] Asynchronously read all joint firmware versions

  • read_joint_firmware_version_unchecked(timeout=0.5) -> None Non-blocking read all joint firmware versions

  • get_joint_firmware_version() -> NDArray[uint32] Get cached all joint firmware versions

  • read_joint_firmware_date(timeout=0.5) -> NDArray[uint32] Synchronously read all joint firmware build dates

  • read_joint_firmware_date_async(timeout=0.5) -> Awaitable[NDArray[uint32]] Asynchronously read all joint firmware build dates

  • read_joint_firmware_date_unchecked(timeout=0.5) -> None Non-blocking read all joint firmware build dates

  • get_joint_firmware_date() -> NDArray[uint32] Get cached all joint firmware build dates

2.1.6 Joint Control (Supports Single Value or 4 Array)

Enable Control
  • write_joint_enabled(value, timeout=0.5) -> None Synchronously set all joint enable states
  • write_joint_enabled(value_array, timeout=0.5) -> None Synchronously batch set each joint enable state
  • write_joint_enabled_async(value, timeout=0.5) -> Awaitable[None] Asynchronously set all joint enable states
  • write_joint_enabled_async(value_array, timeout=0.5) -> Awaitable[None] Asynchronously batch set each joint enable state
  • write_joint_enabled_unchecked(value, timeout=0.5) -> None Non-blocking set all joint enable states
  • write_joint_enabled_unchecked(value_array, timeout=0.5) -> None Non-blocking batch set each joint enable state
Position Control
  • write_joint_target_position(value, timeout=0.5) -> None Synchronously set all joint target positions (radians)
  • write_joint_target_position(value_array, timeout=0.5) -> None Synchronously batch set each joint target position
  • write_joint_target_position_async(value, timeout=0.5) -> Awaitable[None] Asynchronously set all joint target positions
  • write_joint_target_position_async(value_array, timeout=0.5) -> Awaitable[None] Asynchronously batch set each joint target position
  • write_joint_target_position_unchecked(value, timeout=0.5) -> None Non-blocking set all joint target positions
  • write_joint_target_position_unchecked(value_array, timeout=0.5) -> None Non-blocking batch set each joint target position
Mode Control
  • write_joint_control_mode(value, timeout=0.5) -> None Synchronously set all joint control modes
  • write_joint_control_mode(value_array, timeout=0.5) -> None Synchronously batch set each joint control mode
  • write_joint_control_mode_async(value, timeout=0.5) -> Awaitable[None] Asynchronously set all joint control modes
  • write_joint_control_mode_async(value_array, timeout=0.5) -> Awaitable[None] Asynchronously batch set each joint control mode
  • write_joint_control_mode_unchecked(value, timeout=0.5) -> None Non-blocking set all joint control modes
  • write_joint_control_mode_unchecked(value_array, timeout=0.5) -> None Non-blocking batch set each joint control mode
Effort Limit Configuration

Warning: Modifying effort limit may cause device damage, see field description for details.

  • write_joint_effort_limit(value, timeout=0.5) -> None Synchronously set all joint effort limits (Ampere)
  • write_joint_effort_limit(value_array, timeout=0.5) -> None Synchronously batch set each joint effort limit
  • write_joint_effort_limit_async(value, timeout=0.5) -> Awaitable[None] Asynchronously set all joint effort limits
  • write_joint_effort_limit_async(value_array, timeout=0.5) -> Awaitable[None] Asynchronously batch set each joint effort limit
  • write_joint_effort_limit_unchecked(value, timeout=0.5) -> None Non-blocking set all joint effort limits
  • write_joint_effort_limit_unchecked(value_array, timeout=0.5) -> None Non-blocking batch set each joint effort limit
Other Parameter Configuration
  • write_joint_sin_level(value, timeout=0.5) -> None Synchronously set all joint sine wave excitation levels

  • write_joint_sin_level(value_array, timeout=0.5) -> None Synchronously batch set each joint sine wave excitation level

  • write_joint_sin_level_async(value, timeout=0.5) -> Awaitable[None] Asynchronously set all joint sine wave excitation levels

  • write_joint_sin_level_async(value_array, timeout=0.5) -> Awaitable[None] Asynchronously batch set each joint sine wave excitation level

  • write_joint_sin_level_unchecked(value, timeout=0.5) -> None Non-blocking set all joint sine wave excitation levels

  • write_joint_sin_level_unchecked(value_array, timeout=0.5) -> None Non-blocking batch set each joint sine wave excitation level

  • write_joint_reset_error(value, timeout=0.5) -> None Synchronously reset all joint errors

  • write_joint_reset_error(value_array, timeout=0.5) -> None Synchronously batch reset each joint error

  • write_joint_reset_error_async(value, timeout=0.5) -> Awaitable[None] Asynchronously reset all joint errors

  • write_joint_reset_error_async(value_array, timeout=0.5) -> Awaitable[None] Asynchronously batch reset each joint error

  • write_joint_reset_error_unchecked(value, timeout=0.5) -> None Non-blocking reset all joint errors

  • write_joint_reset_error_unchecked(value_array, timeout=0.5) -> None Non-blocking batch reset each joint error

2.1.7 Real-time Controller

  • realtime_controller(enable_upstream, filter) -> IController Create a real-time controller for high-frequency control scenarios

2.2 Finger Class

2.2.1 Joint Access

  • joint(index) -> Joint Get the joint object at the specified index, index range 0-3

2.2.2 Joint Data (Returns 4-Element Array)

Position Data
  • read_joint_actual_position(timeout=0.5) -> NDArray[float64] Synchronously read all joint actual positions of the finger (radians)

  • read_joint_actual_position_async(timeout=0.5) -> Awaitable[NDArray[float64]] Asynchronously read all joint actual positions of the finger

  • read_joint_actual_position_unchecked(timeout=0.5) -> None Non-blocking read all joint actual positions of the finger

  • get_joint_actual_position() -> NDArray[float64] Get cached all joint actual positions of the finger

  • read_joint_upper_limit(timeout=0.5) -> NDArray[float64] Synchronously read all joint upper limit positions of the finger (radians)

  • read_joint_upper_limit_async(timeout=0.5) -> Awaitable[NDArray[float64]] Asynchronously read all joint upper limit positions of the finger

  • read_joint_upper_limit_unchecked(timeout=0.5) -> None Non-blocking read all joint upper limit positions of the finger

  • get_joint_upper_limit() -> NDArray[float64] Get cached all joint upper limit positions of the finger

  • read_joint_lower_limit(timeout=0.5) -> NDArray[float64] Synchronously read all joint lower limit positions of the finger (radians)

  • read_joint_lower_limit_async(timeout=0.5) -> Awaitable[NDArray[float64]] Asynchronously read all joint lower limit positions of the finger

  • read_joint_lower_limit_unchecked(timeout=0.5) -> None Non-blocking read all joint lower limit positions of the finger

  • get_joint_lower_limit() -> NDArray[float64] Get cached all joint lower limit positions of the finger

Status Monitoring
  • read_joint_bus_voltage(timeout=0.5) -> NDArray[float32] Synchronously read all joint bus voltages of the finger (volts)

  • read_joint_bus_voltage_async(timeout=0.5) -> Awaitable[NDArray[float32]] Asynchronously read all joint bus voltages of the finger

  • read_joint_bus_voltage_unchecked(timeout=0.5) -> None Non-blocking read all joint bus voltages of the finger

  • get_joint_bus_voltage() -> NDArray[float32] Get cached all joint bus voltages of the finger

  • read_joint_temperature(timeout=0.5) -> NDArray[float32] Synchronously read all joint temperatures of the finger (Celsius)

  • read_joint_temperature_async(timeout=0.5) -> Awaitable[NDArray[float32]] Asynchronously read all joint temperatures of the finger

  • read_joint_temperature_unchecked(timeout=0.5) -> None Non-blocking read all joint temperatures of the finger

  • get_joint_temperature() -> NDArray[float32] Get cached all joint temperatures of the finger

  • read_joint_error_code(timeout=0.5) -> NDArray[uint32] Synchronously read all joint error codes of the finger

  • read_joint_error_code_async(timeout=0.5) -> Awaitable[NDArray[uint32]] Asynchronously read all joint error codes of the finger

  • read_joint_error_code_unchecked(timeout=0.5) -> None Non-blocking read all joint error codes of the finger

  • get_joint_error_code() -> NDArray[uint32] Get cached all joint error codes of the finger

Effort Limit Data
  • read_joint_effort_limit(timeout=0.5) -> NDArray[float64] Synchronously read all joint effort limits of the finger (Ampere)
  • read_joint_effort_limit_async(timeout=0.5) -> Awaitable[NDArray[float64]] Asynchronously read all joint effort limits of the finger
  • read_joint_effort_limit_unchecked(timeout=0.5) -> None Non-blocking read all joint effort limits of the finger
  • get_joint_effort_limit() -> NDArray[float64] Get cached all joint effort limits of the finger
Firmware Information
  • read_joint_firmware_version(timeout=0.5) -> NDArray[uint32] Synchronously read all joint firmware versions of the finger

  • read_joint_firmware_version_async(timeout=0.5) -> Awaitable[NDArray[uint32]] Asynchronously read all joint firmware versions of the finger

  • read_joint_firmware_version_unchecked(timeout=0.5) -> None Non-blocking read all joint firmware versions of the finger

  • get_joint_firmware_version() -> NDArray[uint32] Get cached all joint firmware versions of the finger

  • read_joint_firmware_date(timeout=0.5) -> NDArray[uint32] Synchronously read all joint firmware build dates of the finger

  • read_joint_firmware_date_async(timeout=0.5) -> Awaitable[NDArray[uint32]] Asynchronously read all joint firmware build dates of the finger

  • read_joint_firmware_date_unchecked(timeout=0.5) -> None Non-blocking read all joint firmware build dates of the finger

  • get_joint_firmware_date() -> NDArray[uint32] Get cached all joint firmware build dates of the finger

2.2.3 Joint Control (Supports Single Value or 4-Element Array)

Enable Control
  • write_joint_enabled(value, timeout=0.5) -> None Synchronously set all joint enable states of the finger
  • write_joint_enabled(value_array, timeout=0.5) -> None Synchronously batch set each joint enable state of the finger
  • write_joint_enabled_async(value, timeout=0.5) -> Awaitable[None] Asynchronously set all joint enable states of the finger
  • write_joint_enabled_async(value_array, timeout=0.5) -> Awaitable[None] Asynchronously batch set each joint enable state of the finger
  • write_joint_enabled_unchecked(value, timeout=0.5) -> None Non-blocking set all joint enable states of the finger
  • write_joint_enabled_unchecked(value_array, timeout=0.5) -> None Non-blocking batch set each joint enable state of the finger
Position Control
  • write_joint_target_position(value, timeout=0.5) -> None Synchronously set all joint target positions of the finger (radians)
  • write_joint_target_position(value_array, timeout=0.5) -> None Synchronously batch set each joint target position of the finger
  • write_joint_target_position_async(value, timeout=0.5) -> Awaitable[None] Asynchronously set all joint target positions of the finger
  • write_joint_target_position_async(value_array, timeout=0.5) -> Awaitable[None] Asynchronously batch set each joint target position of the finger
  • write_joint_target_position_unchecked(value, timeout=0.5) -> None Non-blocking set all joint target positions of the finger
  • write_joint_target_position_unchecked(value_array, timeout=0.5) -> None Non-blocking batch set each joint target position of the finger
Mode Control
  • write_joint_control_mode(value, timeout=0.5) -> None Synchronously set all joint control modes of the finger
  • write_joint_control_mode(value_array, timeout=0.5) -> None Synchronously batch set each joint control mode of the finger
  • write_joint_control_mode_async(value, timeout=0.5) -> Awaitable[None] Asynchronously set all joint control modes of the finger
  • write_joint_control_mode_async(value_array, timeout=0.5) -> Awaitable[None] Asynchronously batch set each joint control mode of the finger
  • write_joint_control_mode_unchecked(value, timeout=0.5) -> None Non-blocking set all joint control modes of the finger
  • write_joint_control_mode_unchecked(value_array, timeout=0.5) -> None Non-blocking batch set each joint control mode of the finger
Effort Limit Configuration

Warning: Modifying effort limit may cause device damage, see field description for details.

  • write_joint_effort_limit(value, timeout=0.5) -> None Synchronously set all joint effort limits of the finger (Ampere)
  • write_joint_effort_limit(value_array, timeout=0.5) -> None Synchronously batch set each joint effort limit of the finger
  • write_joint_effort_limit_async(value, timeout=0.5) -> Awaitable[None] Asynchronously set all joint effort limits of the finger
  • write_joint_effort_limit_async(value_array, timeout=0.5) -> Awaitable[None] Asynchronously batch set each joint effort limit of the finger
  • write_joint_effort_limit_unchecked(value, timeout=0.5) -> None Non-blocking set all joint effort limits of the finger
  • write_joint_effort_limit_unchecked(value_array, timeout=0.5) -> None Non-blocking batch set each joint effort limit of the finger
Other Parameter Configuration
  • write_joint_sin_level(value, timeout=0.5) -> None Synchronously set all joint sine wave excitation levels of the finger

  • write_joint_sin_level(value_array, timeout=0.5) -> None Synchronously batch set each joint sine wave excitation level of the finger

  • write_joint_sin_level_async(value, timeout=0.5) -> Awaitable[None] Asynchronously set all joint sine wave excitation levels of the finger

  • write_joint_sin_level_async(value_array, timeout=0.5) -> Awaitable[None] Asynchronously batch set each joint sine wave excitation level of the finger

  • write_joint_sin_level_unchecked(value, timeout=0.5) -> None Non-blocking set all joint sine wave excitation levels of the finger

  • write_joint_sin_level_unchecked(value_array, timeout=0.5) -> None Non-blocking batch set each joint sine wave excitation level of the finger

  • write_joint_reset_error(value, timeout=0.5) -> None Synchronously reset all joint errors of the finger

  • write_joint_reset_error(value_array, timeout=0.5) -> None Synchronously batch reset each joint error of the finger

  • write_joint_reset_error_async(value, timeout=0.5) -> Awaitable[None] Asynchronously reset all joint errors of the finger

  • write_joint_reset_error_async(value_array, timeout=0.5) -> Awaitable[None] Asynchronously batch reset each joint error of the finger

  • write_joint_reset_error_unchecked(value, timeout=0.5) -> None Non-blocking reset all joint errors of the finger

  • write_joint_reset_error_unchecked(value_array, timeout=0.5) -> None Non-blocking batch reset each joint error of the finger

2.3 Joint Class

2.3.1 Joint Data (Returns Single Value)

Position Data
  • read_joint_actual_position(timeout=0.5) -> float64 Synchronously read joint actual position (radians)

  • read_joint_actual_position_async(timeout=0.5) -> Awaitable[float64] Asynchronously read joint actual position

  • read_joint_actual_position_unchecked(timeout=0.5) -> None Non-blocking read joint actual position

  • get_joint_actual_position() -> float64 Get cached joint actual position

  • read_joint_upper_limit(timeout=0.5) -> float64 Synchronously read joint upper limit position (radians)

  • read_joint_upper_limit_async(timeout=0.5) -> Awaitable[float64] Asynchronously read joint upper limit position

  • read_joint_upper_limit_unchecked(timeout=0.5) -> None Non-blocking read joint upper limit position

  • get_joint_upper_limit() -> float64 Get cached joint upper limit position

  • read_joint_lower_limit(timeout=0.5) -> float64 Synchronously read joint lower limit position (radians)

  • read_joint_lower_limit_async(timeout=0.5) -> Awaitable[float64] Asynchronously read joint lower limit position

  • read_joint_lower_limit_unchecked(timeout=0.5) -> None Non-blocking read joint lower limit position

  • get_joint_lower_limit() -> float64 Get cached joint lower limit position

Status Monitoring
  • read_joint_bus_voltage(timeout=0.5) -> float32 Synchronously read joint bus voltage (volts)

  • read_joint_bus_voltage_async(timeout=0.5) -> Awaitable[float32] Asynchronously read joint bus voltage

  • read_joint_bus_voltage_unchecked(timeout=0.5) -> None Non-blocking read joint bus voltage

  • get_joint_bus_voltage() -> float32 Get cached joint bus voltage

  • read_joint_temperature(timeout=0.5) -> float32 Synchronously read joint temperature (Celsius)

  • read_joint_temperature_async(timeout=0.5) -> Awaitable[float32] Asynchronously read joint temperature

  • read_joint_temperature_unchecked(timeout=0.5) -> None Non-blocking read joint temperature

  • get_joint_temperature() -> float32 Get cached joint temperature

  • read_joint_error_code(timeout=0.5) -> uint32 Synchronously read joint error code

  • read_joint_error_code_async(timeout=0.5) -> Awaitable[uint32] Asynchronously read joint error code

  • read_joint_error_code_unchecked(timeout=0.5) -> None Non-blocking read joint error code

  • get_joint_error_code() -> uint32 Get cached joint error code

Effort Limit Data
  • read_joint_effort_limit(timeout=0.5) -> float64 Synchronously read joint effort limit (Ampere)
  • read_joint_effort_limit_async(timeout=0.5) -> Awaitable[float64] Asynchronously read joint effort limit
  • read_joint_effort_limit_unchecked(timeout=0.5) -> None Non-blocking read joint effort limit
  • get_joint_effort_limit() -> float64 Get cached joint effort limit
Firmware Information
  • read_joint_firmware_version(timeout=0.5) -> uint32 Synchronously read joint firmware version

  • read_joint_firmware_version_async(timeout=0.5) -> Awaitable[uint32] Asynchronously read joint firmware version

  • read_joint_firmware_version_unchecked(timeout=0.5) -> None Non-blocking read joint firmware version

  • get_joint_firmware_version() -> uint32 Get cached joint firmware version

  • read_joint_firmware_date(timeout=0.5) -> uint32 Synchronously read joint firmware build date

  • read_joint_firmware_date_async(timeout=0.5) -> Awaitable[uint32] Asynchronously read joint firmware build date

  • read_joint_firmware_date_unchecked(timeout=0.5) -> None Non-blocking read joint firmware build date

  • get_joint_firmware_date() -> uint32 Get cached joint firmware build date

2.3.2 Joint Control (Single Value)

Enable Control
  • write_joint_enabled(value, timeout=0.5) -> None Synchronously set joint enable state
  • write_joint_enabled_async(value, timeout=0.5) -> Awaitable[None] Asynchronously set joint enable state
  • write_joint_enabled_unchecked(value, timeout=0.5) -> None Non-blocking set joint enable state
Position Control
  • write_joint_target_position(value, timeout=0.5) -> None Synchronously set joint target position (radians)
  • write_joint_target_position_async(value, timeout=0.5) -> Awaitable[None] Asynchronously set joint target position
  • write_joint_target_position_unchecked(value, timeout=0.5) -> None Non-blocking set joint target position
Mode Control
  • write_joint_control_mode(value, timeout=0.5) -> None Synchronously set joint control mode
  • write_joint_control_mode_async(value, timeout=0.5) -> Awaitable[None] Asynchronously set joint control mode
  • write_joint_control_mode_unchecked(value, timeout=0.5) -> None Non-blocking set joint control mode
Effort Limit Configuration

Warning: Modifying effort limit may cause device damage, see field description for details.

  • write_joint_effort_limit(value, timeout=0.5) -> None Synchronously set joint effort limit (Ampere)
  • write_joint_effort_limit_async(value, timeout=0.5) -> Awaitable[None] Asynchronously set joint effort limit
  • write_joint_effort_limit_unchecked(value, timeout=0.5) -> None Non-blocking set joint effort limit
Other Parameter Configuration
  • write_joint_sin_level(value, timeout=0.5) -> None Synchronously set joint sine wave excitation level

  • write_joint_sin_level_async(value, timeout=0.5) -> Awaitable[None] Asynchronously set joint sine wave excitation level

  • write_joint_sin_level_unchecked(value, timeout=0.5) -> None Non-blocking set joint sine wave excitation level

  • write_joint_reset_error(value, timeout=0.5) -> None Synchronously reset joint error

  • write_joint_reset_error_async(value, timeout=0.5) -> Awaitable[None] Asynchronously reset joint error

  • write_joint_reset_error_unchecked(value, timeout=0.5) -> None Non-blocking reset joint error

2.4 IController Interface

2.4.1 Context Management

  • __enter__() -> IController Context manager entry supporting with statement
  • __exit__(arg0, arg1, arg2) -> None Context manager exit supporting with statement
  • close() -> None Manually close the real-time controller

2.4.2 Real-time Data Retrieval

  • get_joint_actual_position() -> NDArray[float64] Real-time get all joint actual positions (high-frequency read, returns 4 array)
  • get_joint_actual_effort() -> NDArray[float64] Real-time get all joint efforts (high-frequency read, returns 4 array, unit: Ampere)

Effort Real-time Feedback

get_joint_actual_effort() returns the actuation effort in current space, filtered before output.

  • Only available in real-time controller mode
  • Suitable for collision detection and load monitoring
  • Calculate output percentage via effort / effort_limit

2.4.3 Real-time Data Setting

  • set_joint_target_position(value_array) -> None Real-time set all joint target positions (high-frequency write, parameter is 4 array)

2.5 Array Shape Description

  • Hand Class Batch Operations: Returns/receives arrays shaped {5, 4} (5 fingers × 4 joints)
  • Finger Class Batch Operations: Returns/receives arrays shaped {4} (4 joints)
  • Joint Class Operations: Returns/receives scalar values (single joint)
  • IController Operations: Handles arrays shaped {5, 4} for high-frequency real-time control

2.6 Operation Mode Description

  • Synchronous Operations (read_*, write_*): Blocking operations, ensure read/write success
  • Asynchronous Operations (*_async): Returns Awaitable objects, supports await syntax
  • Non-blocking Operations (*_unchecked): Returns immediately, does not guarantee operation success, suitable for high-frequency scenarios
  • Cached Retrieval (get_*): Gets the most recently read data, does not block

3. Tactile Sensing Glove

The Tactile Sensing Glove is an optional tactile perception accessory for Wuji Hand. The SDK provides device connection and data reading through the TactileGlove class.

3.1 Core Classes

TactileHandedness

Handedness enum:

  • TactileHandedness.LEFT (0): Left hand
  • TactileHandedness.RIGHT (1): Right hand

TactileFrame

Single-frame tactile data with the following properties:

PropertyTypeDescription
handTactileHandednessLeft or right hand
sequenceint (uint16)Frame counter, wraps at 65535
timestamp_msint (uint32)Milliseconds since device boot
pressurenumpy.ndarray (24, 32) float32Pressure matrix

Pressure value semantics:

  • Range: [0.0, 1.0]0.0 = no contact, 1.0 = maximum contact
  • NaN marks an invalid cell (not part of any finger or palm region). Skip such cells with numpy.isnan()

CRC validation happens inside the SDK before delivery, so callers never see a bad-CRC frame.

TactileGlove

Connection and data reading for the Tactile Sensing Glove.

Constructor:

TactileGlove(serial_number: str | None = None)

serial_number is the USB device serial number. Pass None to auto-discover the only attached device. Raises if more than one is present.

3.2 Device Connection

Auto-discovery

from wujihandpy import TactileGlove

glove = TactileGlove()
glove.connect()  # Returns True on success

Specific device

glove = TactileGlove(serial_number="ABC123")
glove.connect()

Context Manager

with TactileGlove() as glove:
    frame = glove.read_frame()

Connection management methods

  • connect() -> bool: Connect to device. Returns True on success
  • disconnect() -> None: Disconnect and stop streaming
  • is_connected() -> bool: Query connection status
  • get_handedness() -> TactileHandedness: Return device handedness

3.3 Data Reading

Blocking read

import numpy as np

frame = glove.read_frame(timeout_ms=100)
print(f"Sequence: {frame.sequence}")
print(f"Pressure shape: {frame.pressure.shape}")  # (24, 32)
print(f"Max pressure: {np.nanmax(frame.pressure)}")
  • Performs frame synchronization and CRC validation internally
  • Raises RuntimeError on timeout
  • Raises RuntimeError on disconnect

Streaming callback

import numpy as np

def on_frame(frame):
    print(f"Seq={frame.sequence}, Max={np.nanmax(frame.pressure)}")

glove.start_streaming(on_frame)
# ... application logic ...
glove.stop_streaming()
  • Callback invoked on the internal reader thread. Must not block
  • Register a disconnect callback with set_disconnect_callback(fn) to react to USB drop. Streaming stops automatically afterward
  • start_streaming and read_frame are mutually exclusive
  • All blocking operations release the Python GIL

3.4 Configuration and Diagnostics

MethodDescription
set_sample_rate_hz(hz)Set sample rate, 1–120 Hz
get_sample_rate_hz() -> intRead current sample rate
set_streaming(enable)Toggle the device data-frame stream
get_streaming_enabled() -> boolRead the streaming-enabled flag
set_disconnect_callback(callback)Register a Callable[[], None] invoked once when the USB device drops off the bus
get_device_info() -> TactileDeviceInfoRead serial, hw_revision, fw_version
get_fw_build() -> TactileFwBuildRead firmware build (git_short_sha)
get_diagnostics() -> TactileDiagnosticsRead counters: uptime_ms, frame_count, crc_err_count, dropout_count, usb_reset_count
reset_counters()Zero the diagnostic counters
get_device_time() -> TactileDeviceTimeRead device monotonic clock (device_monotonic_ns)
sync_host_epoch(host_unix_ns) -> TactileSyncResultExchange host UTC nanoseconds for the device clock at the same moment
reset_device()Soft reset. The device drops off the bus and re-enumerates—call connect() again afterward
enter_bootloader(magic)Jump to bootloader for OTA. Pass TACTILE_BOOTLOADER_MAGIC

3.5 Exception Handling

ExceptionTrigger
RuntimeErrorread_frame timeout, USB device disconnected during read, read_frame called when not connected, or start_streaming called while already streaming
TactileErrorDevice-reported protocol error from a command (bad length, bad CRC, unknown command, bad payload)

3.6 Complete Example

Covers the full TactileGlove workflow: auto-discovery and device info queries, host/device clock synchronization, sample-rate configuration, blocking reads and streaming callbacks, data saving, and diagnostic counters. reset_device and enter_bootloader close the current connection (device reset or jump to bootloader, respectively) and appear only as trailing comments.

import time
import numpy as np
from wujihandpy import (
    TactileGlove,
    TactileHandedness,
    TactileError,
    TACTILE_BOOTLOADER_MAGIC,
)


def on_disconnect():
    print("[event] USB disconnect detected")


# 1. Connect — context manager calls disconnect() on exit.
#    To target a specific device: TactileGlove(serial_number="ABC123").
with TactileGlove() as glove:
    if not glove.is_connected():
        print("Not connected")
        exit(1)

    glove.set_disconnect_callback(on_disconnect)

    # 2. Device info
    info = glove.get_device_info()
    hw = ".".join(str(x) for x in info.hw_revision[:3])
    fw = ".".join(str(x) for x in info.fw_version[:3])
    build = glove.get_fw_build()
    print(f"Serial: {info.serial}")
    print(f"Hardware: v{hw}, Firmware: v{fw} ({build.git_short_sha})")

    # 3. Handedness
    hand = glove.get_handedness()
    side = "left" if hand == TactileHandedness.LEFT else "right"
    print(f"Handedness: {side}")

    # 4. Clock sync and device time
    sync = glove.sync_host_epoch(time.time_ns())
    skew_ns = sync.device_ns_at_sync - sync.host_ns_echo
    dev_time = glove.get_device_time()
    print(f"Host/device clock skew: {skew_ns} ns")
    print(f"Device monotonic time: {dev_time.device_monotonic_ns} ns")

    # 5. Sample rate
    print(f"Current sample rate: {glove.get_sample_rate_hz()} Hz")
    glove.set_sample_rate_hz(60)
    print(f"New sample rate: {glove.get_sample_rate_hz()} Hz")

    # 6. Streaming toggle + single blocking read
    glove.set_streaming(True)
    print(f"Streaming enabled: {glove.get_streaming_enabled()}")
    try:
        frame = glove.read_frame(timeout_ms=200)
        side_str = "L" if frame.hand == TactileHandedness.LEFT else "R"
        print(
            f"Frame: seq={frame.sequence}, ts={frame.timestamp_ms} ms, "
            f"hand={side_str}, max={np.nanmax(frame.pressure):.3f}"
        )
    except RuntimeError as e:
        print(f"Read failed (timeout or disconnect): {e}")
    except TactileError as e:
        print(f"Device protocol error: {e}")

    # 7. Reset counters, then stream and collect
    glove.reset_counters()
    frames = []

    def collect(frame):
        frames.append(frame.pressure.copy())

    glove.start_streaming(collect)
    time.sleep(5)  # Collect for 5 seconds
    glove.stop_streaming()

    # 8. Diagnostics
    diag = glove.get_diagnostics()
    print(
        f"Collected {diag.frame_count} frames, CRC errors {diag.crc_err_count}, "
        f"dropouts {diag.dropout_count}, USB resets {diag.usb_reset_count}, "
        f"uptime {diag.uptime_ms} ms"
    )

    # 9. Save data
    if frames:
        data = np.stack(frames)  # shape: (N, 24, 32), dtype: float32
        np.save("tactile_data.npy", data)
        print(f"Saved {len(frames)} frames to tactile_data.npy")
    else:
        print("No frames collected")

# Destructive operations (commented by default; both invalidate the handle):
# glove.reset_device()
# glove.enter_bootloader(TACTILE_BOOTLOADER_MAGIC)

Example Output

[xxxx-xx-xx xx:xx:xx.xxx] [wuji] [info] SDK vx.x.x initialized
[xxxx-xx-xx xx:xx:xx.xxx] [wuji] [info] Log files can be found at ~/.wuji/log/<timestamp>_<pid>.log
Serial: WTxxxxxxxxxxxxxx
Hardware: vx.x.x, Firmware: vx.x.x (xxxxxxx)
Handedness: left
Host/device clock skew: -1779537846723254078 ns
Device monotonic time: 142623339080000 ns
Current sample rate: 60 Hz
New sample rate: 60 Hz
Streaming enabled: True
Frame: seq=33917, ts=142623244 ms, hand=L, max=0.820
Collected 326 frames, CRC errors 0, dropouts 0, USB resets 0, uptime 142628802 ms
Saved 326 frames to tactile_data.npy

3.7 Use with Wuji Hand

Hand and TactileGlove use independent USB transports and threads, so the two APIs compose in the same process with no extra coordination. The frame callback fires on the glove's streaming consumer thread, while joint commands run on the thread that calls them. This pattern enables closed-loop scenarios where tactile feedback drives motion—for example, scaling joint amplitude by the current pressure peak.

Reference example: example/joint_with_tactile.py.

Runtime behavior:

  • Prints Squeeze the glove to dampen the motion. Ctrl-C to exit. on startup
  • After joints are enabled, fingers F2–F5 perform periodic flexion–extension in a 100 Hz realtime loop. F1 (thumb) stays still
  • Higher tactile pressure peaks shrink the motion amplitude: a relaxed glove yields the full sweep (about 0.4 rad), while a firm squeeze drives amplitude toward 0
  • Releasing the glove restores the full amplitude
  • Ctrl-C stops streaming, disables joints, and disconnects the glove cleanly

3.8 Protocol Reference

This section is for advanced developers who need to parse tactile data frames directly. The TactileGlove class handles all protocol details automatically.

Data frame format

The Tactile Sensing Glove streams fixed 3088-byte frames at up to 120 Hz over USB CDC (virtual serial port). The effective rate is set via set_sample_rate_hz (1–120 Hz):

OffsetLengthFieldTypeDescription
0–12Headeru8[2]Fixed 0xAA 0x55
2–32Frame lengthu16 LEFixed 3088
41Handu80x00 = left, 0x01 = right
5–73Paddingu8[3]Aligns tactile data to a 4-byte boundary
8–30793072Tactile dataf32[24][32] LEPressure matrix, row-major, [0.0, 1.0]. NaN = invalid cell
3080–30812Sequenceu16 LEFrame counter, wraps at 65535
3082–30854Timestampu32 LEMilliseconds since device boot
3086–30872CRC16u16 LECRC16-CCITT checksum

CRC16-CCITT

  • Polynomial: 0x1021, initial value: 0xFFFF
  • Coverage: bytes [2, 3086) (frame length through timestamp, 3084 bytes)
  • Excludes header and CRC field

Frame synchronization algorithm

  1. Scan byte-by-byte for header 0xAA 0x55
  2. Read bytes 2–3, verify frame length == 3088
  3. Read remaining bytes to complete the frame
  4. Compute CRC16 and compare
  5. CRC failure: discard, resume scanning from header_position + 1
  6. CRC success: parse and deliver frame

0xAA 0x55 may appear within pressure data (false headers). CRC validation is the only reliable way to distinguish real headers from false ones.

Reference Implementation

The Python snippet below parses a single frame straight from a raw byte stream (for example, a CDC serial port opened with pyserial) without depending on the SDK. Use it as a starting point for a custom parser.

import struct
import numpy as np

FRAME_LEN = 3088
HEADER = b"\xAA\x55"


def crc16_ccitt(data: bytes, init: int = 0xFFFF) -> int:
    crc = init
    for b in data:
        crc ^= b << 8
        for _ in range(8):
            if crc & 0x8000:
                crc = ((crc << 1) ^ 0x1021) & 0xFFFF
            else:
                crc = (crc << 1) & 0xFFFF
    return crc


def parse_frame(buf: bytes) -> dict:
    """Validate a 3088-byte candidate and decode its fields."""
    if len(buf) != FRAME_LEN or buf[:2] != HEADER:
        raise ValueError("bad header or length")
    if struct.unpack_from("<H", buf, 2)[0] != FRAME_LEN:
        raise ValueError("length field mismatch")
    if crc16_ccitt(buf[2:3086]) != struct.unpack_from("<H", buf, 3086)[0]:
        raise ValueError("CRC mismatch")
    return {
        "hand": "L" if buf[4] == 0 else "R",
        "pressure": np.frombuffer(buf, dtype="<f4", count=24 * 32, offset=8).reshape(24, 32),
        "sequence": struct.unpack_from("<H", buf, 3080)[0],
        "timestamp_ms": struct.unpack_from("<I", buf, 3082)[0],
    }


def read_frame(port) -> dict:
    """Resync on a raw byte stream and return the next valid frame."""
    buf = bytearray()
    while True:
        chunk = port.read(FRAME_LEN)
        if not chunk:
            raise TimeoutError("stream exhausted")
        buf.extend(chunk)
        i = buf.find(HEADER)
        while 0 <= i and i + FRAME_LEN <= len(buf):
            try:
                frame = parse_frame(bytes(buf[i:i + FRAME_LEN]))
                del buf[: i + FRAME_LEN]
                return frame
            except ValueError:
                i = buf.find(HEADER, i + 1)
        # Keep tail so a header spanning chunk boundaries survives.
        if len(buf) > FRAME_LEN - 1:
            del buf[: len(buf) - (FRAME_LEN - 1)]

Usage:

import serial  # python3 -m pip install pyserial

with serial.Serial("/dev/ttyACM0", timeout=1.0) as port:
    frame = read_frame(port)
    print(f"seq={frame['sequence']}, ts={frame['timestamp_ms']} ms, "
          f"hand={frame['hand']}, max={np.nanmax(frame['pressure']):.3f}")

4. logging Module

The wujihandpy.logging submodule configures SDK logging at runtime. For default behavior, environment variables, and troubleshooting tips, see Getting Started - Get Logs.

4.1 Level Enum

MemberValueMeaning
Level.Trace0Most verbose, includes raw TX/RX bytes
Level.Debug1Debug details
Level.Info2Key events (default)
Level.Warn3Warnings
Level.Error4Errors
Level.Critical5Critical errors
Level.Off6Disable logging

4.2 Functions

set_log_path

Set the log file directory. Must be called before the logger initializes (in the common Hand flow that means before creating the first Hand. flush() or any other logging API also triggers logger initialization), otherwise it raises RuntimeError.

def set_log_path(value: str) -> None

set_log_level

Set the log level. Safe to call at any time and takes effect immediately.

def set_log_level(value: Level) -> None

set_log_to_file

Toggle file output. The log file is opened only if WUJI_LOG_TO_FILE is true at logger initialization, and after init this function can temporarily disable or restore file output. If file output was disabled at init, calling set_log_to_file(True) later won't re-enable it.

def set_log_to_file(value: bool) -> None

set_log_to_console

Toggle terminal output (stdout / stderr). Safe to call at any time and takes effect immediately.

def set_log_to_console(value: bool) -> None

flush

Force pending log entries to file and terminal. The SDK calls this automatically on process exit, so manual calls are rarely needed.

def flush() -> None

On this page

1. Field List
1.1 Hand Layer
handedness
firmware_version
firmware_date
system_time
temperature
input_voltage
1.2 Joint Layer
joint_firmware_version
joint_firmware_date
joint_control_mode
joint_sin_level
joint_effort_limit
joint_bus_voltage
joint_temperature
joint_reset_error
joint_error_code
joint_effort
joint_enabled
joint_actual_position
joint_target_position
joint_upper_limit
joint_lower_limit
2. API List
2.1 Hand Class
2.1.1 Constructor
2.1.2 Finger Access
2.1.3 Thread Safety Control
2.1.4 System Information
Firmware Information
System Status
2.1.5 Joint Data (Batch Read, Returns 4 Array)
Position Data
Status Monitoring
Effort Limit Data
Firmware Information
2.1.6 Joint Control (Supports Single Value or 4 Array)
Enable Control
Position Control
Mode Control
Effort Limit Configuration
Other Parameter Configuration
2.1.7 Real-time Controller
2.2 Finger Class
2.2.1 Joint Access
2.2.2 Joint Data (Returns 4-Element Array)
Position Data
Status Monitoring
Effort Limit Data
Firmware Information
2.2.3 Joint Control (Supports Single Value or 4-Element Array)
Enable Control
Position Control
Mode Control
Effort Limit Configuration
Other Parameter Configuration
2.3 Joint Class
2.3.1 Joint Data (Returns Single Value)
Position Data
Status Monitoring
Effort Limit Data
Firmware Information
2.3.2 Joint Control (Single Value)
Enable Control
Position Control
Mode Control
Effort Limit Configuration
Other Parameter Configuration
2.4 IController Interface
2.4.1 Context Management
2.4.2 Real-time Data Retrieval
2.4.3 Real-time Data Setting
2.5 Array Shape Description
2.6 Operation Mode Description
3. Tactile Sensing Glove
3.1 Core Classes
TactileHandedness
TactileFrame
TactileGlove
3.2 Device Connection
Auto-discovery
Specific device
Context Manager
Connection management methods
3.3 Data Reading
Blocking read
Streaming callback
3.4 Configuration and Diagnostics
3.5 Exception Handling
3.6 Complete Example
Example Output
3.7 Use with Wuji Hand
3.8 Protocol Reference
Data frame format
CRC16-CCITT
Frame synchronization algorithm
Reference Implementation
4. logging Module
4.1 Level Enum
4.2 Functions
set_log_path
set_log_level
set_log_to_file
set_log_to_console
flush