DexHand Interface

The DexHand interface module provides high-level control of dexterous robotic hands.

Base Interface

class pyzlg_dexhand.dexhand_interface.DexHandBase(config, base_id, zcan=None, log_level=LogLevel.INFO, device_index=0, auto_init=True)[source]

Base class for dexterous hand control

NUM_MOTORS

Total number of motors in the hand (12)

NUM_BOARDS

Number of control boards (6)

joint_names

List of joint names in order:

  • th_dip: Thumb distal joint

  • th_mcp: Thumb metacarpophalangeal joint

  • th_rot: Thumb rotation

  • ff_spr: Four-finger spread

  • ff_dip: Index finger distal joint

  • ff_mcp: Index finger metacarpophalangeal

  • mf_dip: Middle finger distal joint

  • mf_mcp: Middle finger metacarpophalangeal

  • rf_dip: Ring finger distal joint

  • rf_mcp: Ring finger metacarpophalangeal

  • lf_dip: Little finger distal joint

  • lf_mcp: Little finger metacarpophalangeal

__init__(config, base_id, zcan=None, log_level=LogLevel.INFO, device_index=0, auto_init=True)[source]

Initialize dexterous hand interface

Parameters:
  • config (dict) – Configuration dictionary for the hand

  • base_id (int) – Base board ID (0x01 for left, 0x07 for right)

  • zcan (Optional[ZCANWrapper]) – Optional existing ZCANWrapper instance to share between hands

  • log_level (Optional[LogLevel]) – Logging level for this hand instance

  • device_index (int) – Device index for ZCAN device if creating new ZCAN instance

  • auto_init (bool) – Whether to automatically initialize CAN communication

clear_errors(clear_all=True, use_broadcast=False, log_level=None)[source]

Clear errors for the hand

NOTE: KNOWN BUG: The broadcast mode for clearing errors is not functioning correctly

in this version. Always set use_broadcast=False or leave at default. This will be fixed in a future release.

Parameters:
  • clear_all – If True, attempt to clear errors for all boards even if not in error state

  • use_broadcast – DEPRECATED - use_broadcast=True will not work correctly in this version and will be fixed in a future release. Set to False or leave as default.

  • log_level (Optional[LogLevel]) – Optional logging level for the operation

Returns:

True if commands sent successfully

Return type:

bool

close()[source]

Close CAN communication

get_board_firmware_version(board_idx=0)[source]

Get the firmware version from a specific board

Reads the firmware version value from memory address 0x02 of the specified board.

Parameters:

board_idx (int) – Board index (0-5)

Return type:

Optional[int]

Returns:

Firmware version number, or None if read failed

get_errors()[source]

Get error information for whole hand

Return type:

Dict[int, Optional[ErrorInfo]]

Returns:

Dict mapping board index to ErrorInfo if an error is present

get_feedback()[source]

Get feedback from all joints and touch sensors

Return type:

HandFeedback

Returns:

HandFeedback object.

get_firmware_versions()[source]

Get firmware versions from all boards

Returns a dictionary mapping joint names to their firmware versions. Boards controlling multiple joints (like the thumb board) will have the same firmware version reported for all joints controlled by that board.

Return type:

Dict[str, Optional[int]]

Returns:

Dictionary mapping joint names to firmware versions, or None if read failed

init(device_index=0)[source]

Initialize CAN communication

Parameters:

device_index (int) – Device index for ZCAN device

Returns:

True if initialization successful

Return type:

bool

move_joints(th_rot=None, th_mcp=None, th_dip=None, ff_spr=None, ff_mcp=None, ff_dip=None, mf_mcp=None, mf_dip=None, rf_mcp=None, rf_dip=None, lf_mcp=None, lf_dip=None, control_mode=ControlMode.IMPEDANCE_GRASP, use_broadcast=True, clear_error=False, request_feedback=True, log_level=None)[source]

Move hand joints to specified angles with optional current and velocity settings.

For each finger, there are two independent DOFs: - MCP (metacarpophalangeal) joint: Controls base joint flexion - DIP (coupled): Controls coupled motion of PIP and DIP joints

Additional DOFs: - th_rot: Thumb rotation/opposition - ff_spr: Four-finger spread (abduction between fingers)

Parameters:
  • th_rot (Union[float, JointCommand, None]) – Thumb rotation - float (position only) or JointCommand(position, current, velocity)

  • th_mcp (Union[float, JointCommand, None]) – Thumb MCP flexion - float (position only) or JointCommand(position, current, velocity)

  • th_dip (Union[float, JointCommand, None]) – Thumb coupled PIP-DIP flexion - float (position only) or JointCommand(position, current, velocity)

  • ff_spr (Union[float, JointCommand, None]) – Four-finger spread - float (position only) or JointCommand(position, current, velocity)

  • ff_mcp (Union[float, JointCommand, None]) – Index MCP flexion - float (position only) or JointCommand(position, current, velocity)

  • ff_dip (Union[float, JointCommand, None]) – Index coupled PIP-DIP flexion - float (position only) or JointCommand(position, current, velocity)

  • mf_mcp (Union[float, JointCommand, None]) – Middle MCP flexion - float (position only) or JointCommand(position, current, velocity)

  • mf_dip (Union[float, JointCommand, None]) – Middle coupled PIP-DIP flexion - float (position only) or JointCommand(position, current, velocity)

  • rf_mcp (Union[float, JointCommand, None]) – Ring MCP flexion - float (position only) or JointCommand(position, current, velocity)

  • rf_dip (Union[float, JointCommand, None]) – Ring coupled PIP-DIP flexion - float (position only) or JointCommand(position, current, velocity)

  • lf_mcp (Union[float, JointCommand, None]) – Little MCP flexion - float (position only) or JointCommand(position, current, velocity)

  • lf_dip (Union[float, JointCommand, None]) – Little coupled PIP-DIP flexion - float (position only) or JointCommand(position, current, velocity)

  • control_mode (ControlMode) – Motor control mode

  • use_broadcast (bool) – If True, send a single broadcast command for all joints (more efficient, default: True)

  • clear_error (bool) – Whether to clear errors (only for broadcast mode) NOTE: KNOWN BUG: The combination of clear_error=True with use_broadcast=True is not functioning correctly in this version. If you need to clear errors, use either: 1. move_joints(…, clear_error=True, use_broadcast=False) 2. clear_errors(use_broadcast=False) followed by move_joints(…)

  • request_feedback (bool) – Whether to request feedback (only for broadcast mode)

  • log_level (Optional[LogLevel]) – Logging level for this operation

Examples

# Move a single joint with position only (using default current and velocity) hand.move_joints(th_rot=45)

# Move a single joint with full control over position, current, and velocity hand.move_joints(th_rot=JointCommand(position=45, current=30, velocity=10000))

# Move multiple joints with different control approaches hand.move_joints(

th_rot=45, # Position only ff_mcp=JointCommand(position=30, current=50), # Position and current, default velocity mf_dip=JointCommand(position=20, velocity=5000) # Position and velocity, default current

)

read_flash_memory(board_idx, address, timeout=0.1)[source]

Read raw data from flash memory

Parameters:
  • board_idx (int) – Board index (0-5)

  • address (int) – Memory address to read from

  • timeout (float) – Timeout in seconds

Return type:

Optional[bytes]

Returns:

Raw bytes read from memory, or None if read failed

reset_joints(use_broadcast=True, log_level=None)[source]

Reset all joints to their zero positions.

This is equivalent to setting all joint angles to 0 degrees. Uses CASCADED_PID control mode.

Parameters:
  • use_broadcast (bool) – If True, use more efficient broadcast mode (default: True)

  • log_level (Optional[LogLevel]) – Logging level for the operation

save_to_flash(board_idx)[source]

Save current configuration to flash memory

This command persists any configuration changes to flash memory so they will survive power cycles. Without this, configuration changes are temporary.

Parameters:

board_idx (int) – Board index (0-5)

Return type:

bool

Returns:

True if save succeeded, False otherwise

send_broadcast_command(control_mode, enable_motors=None, clear_error=False, request_feedback=True, is_right_hand=False, positions=None, speeds=None, currents=None, log_level=None)[source]

Send a broadcast command to control all motors at once with CAN ID 0x100.

This method sends a single CAN frame that affects all motors simultaneously, which is more efficient than sending individual commands to each board.

Parameters:
  • control_mode (ControlMode) – Control mode enum

  • enable_motors (List[bool]) – List of 12 booleans indicating which motors to enable, in order: [th_dip, th_mcp, th_rot, ff_spr, ff_dip, ff_mcp, mf_dip, mf_mcp, rf_dip, rf_mcp, lf_dip, lf_mcp]

  • clear_error (bool) – Whether to clear errors

  • request_feedback (bool) – Whether to request feedback

  • is_right_hand (bool) – True for right hand, False for left hand

  • positions (List[int]) – List of 12 position values corresponding to each motor (-32768 to 32767)

  • speeds (List[int]) – List of 12 speed values corresponding to each motor (0 to 32767)

  • currents (List[int]) – List of 12 current values corresponding to each motor (10 to 599 mA)

  • log_level (Optional[LogLevel]) – Optional logging level for this operation

Returns:

True if command sent successfully

Return type:

bool

send_global_command(function_code, data=b'', log_level=None)[source]

Send a global command that affects all boards simultaneously.

Global commands use a special command type that allows a single message to be processed by all boards in the system, such as clearing errors from all boards at once.

Parameters:
  • function_code (GlobalFunctionCode) – The global function code (defined in GlobalFunctionCode enum)

  • data (bytes) – Optional data for the command (max 6 bytes)

  • log_level (Optional[LogLevel]) – Logging level for this operation

Returns:

True if command sent successfully

Return type:

bool

send_motion_command(board_idx, motor1_pos, motor2_pos, motor_enable=3, control_mode=ControlMode.IMPEDANCE_GRASP, motor1_speed=None, motor2_speed=None, motor1_current=None, motor2_current=None, log_level=None)[source]

Send a motion command to a specific board

Parameters:
  • board_idx (int) – Board index to command (0-5)

  • motor1_pos (int) – Position command for motor 1, in hardware units

  • motor2_pos (int) – Position command for motor 2, in hardware units

  • motor_enable (int) – Motor enable flags, 0x01 for motor 1, 0x02 for motor 2, 0x03 for both

  • control_mode (ControlMode) – Control mode

  • motor1_speed (Optional[int]) – Optional speed for motor 1 (0-32767)

  • motor2_speed (Optional[int]) – Optional speed for motor 2 (0-32767)

  • motor1_current (Optional[int]) – Optional current for motor 1 (10-599 mA)

  • motor2_current (Optional[int]) – Optional current for motor 2 (10-599 mA)

  • log_level (Optional[LogLevel]) – Optional logging level for this operation

Returns:

True if command sent successfully

Return type:

bool

set_feedback_mode(mode, period_ms, enable)[source]

Configure feedback mode for all boards

Parameters:
  • mode (FeedbackMode) – Feedback mode

  • period_ms (int) – Period in milliseconds (if periodic)

  • enable (bool) – Enable flag

Returns:

True if command sent successfully

Return type:

bool

set_pressure_limit_enable(pressure_limit_enable, log_level=None)[source]

Enable/disable the pressure limit function.

Parameters:
  • pressure_limit_enable (bool) – True to enable pressure limit, False to disable

  • log_level (Optional[LogLevel]) – Optional logging level for this operation

Returns:

True if command executed successfully, False otherwise

Return type:

bool

set_pressure_limit_value(pressure_limit, log_level=None)[source]

Set the pressure limit value.

Parameters:
  • pressure_limit (int) – Pressure limit value, ranging from 0 to 20 N

  • log_level (Optional[LogLevel]) – Optional logging level for this operation

Returns:

True if set successfully, False otherwise

Return type:

bool

set_safe_temperature(safe_temperature, log_level=None)[source]

Set the security temperature to prevent overheating (default value is 55℃)

Parameters:
  • safe_temperature (int) – Safety temperature value, ranging from 0 to 255

  • log_level (Optional[LogLevel]) – Optional logging level for this operation

Returns:

True if command sent successfully, False otherwise

Return type:

bool

set_stall_time(motor_type, stall_time, log_level=None)[source]

Set the stall time for motor protection.

Parameters:
  • motor_type (str) – Motor type, can be “motor1”, “motor2”, or “motor” (for both motors)

  • stall_time (int) – The stall time in milliseconds (0-65535)

  • log_level (Optional[LogLevel]) – Optional logging level for this operation

Returns:

True if set successfully, False otherwise

Return type:

bool

write_flash_memory(board_idx, address, value, timeout=0.1)[source]

Write data to flash memory

Parameters:
  • board_idx (int) – Board index (0-5)

  • address (int) – Memory address to write to

  • value (bytes) – Data to write (up to 6 bytes)

  • timeout (float) – Timeout in seconds

Return type:

bool

Returns:

True if write succeeded, False otherwise

Hand Implementations

class pyzlg_dexhand.dexhand_interface.LeftDexHand(zcan=None, log_level=LogLevel.INFO, device_index=0, auto_init=True)[source]

Bases: DexHandBase

Control interface for left dexterous hand

__init__(zcan=None, log_level=LogLevel.INFO, device_index=0, auto_init=True)[source]

Initialize left hand interface

Parameters:
  • zcan (Optional[ZCANWrapper]) – Optional existing ZCANWrapper instance to share between hands

  • log_level (Optional[LogLevel]) – Logging level for operation feedback

  • device_index (int) – Device index for ZCAN device if creating new instance

  • auto_init (bool) – Whether to automatically initialize CAN communication

class pyzlg_dexhand.dexhand_interface.RightDexHand(zcan=None, log_level=LogLevel.INFO, device_index=0, auto_init=True)[source]

Bases: DexHandBase

Control interface for right dexterous hand

__init__(zcan=None, log_level=LogLevel.INFO, device_index=0, auto_init=True)[source]

Initialize right hand interface

Parameters:
  • zcan (Optional[ZCANWrapper]) – Optional existing ZCANWrapper instance to share between hands

  • log_level (Optional[LogLevel]) – Logging level for operation feedback

  • device_index (int) – Device index for ZCAN device if creating new instance

  • auto_init (bool) – Whether to automatically initialize CAN communication

Data Classes

class pyzlg_dexhand.dexhand_interface.JointCommand(position: float, current: int | None = None, velocity: int | None = None)[source]

Command for a single joint with position, current, and velocity parameters

current: Optional[int]

Alias for field number 1

position: float

Alias for field number 0

velocity: Optional[int]

Alias for field number 2

class pyzlg_dexhand.dexhand_interface.HandConfig(channel, hall_scale)[source]

Configuration for hand hardware

channel: int
hall_scale: List[float]
class pyzlg_dexhand.dexhand_interface.JointFeedback(timestamp, angle, encoder_position=None, current=None, velocity=None, error_code=None, impedance=None)[source]

Feedback for a specific joint command

angle: float
current: Optional[int] = None
encoder_position: Optional[int] = None
error_code: Optional[int] = None
impedance: Optional[float] = None
timestamp: float
velocity: Optional[int] = None
class pyzlg_dexhand.dexhand_interface.StampedTouchFeedback(timestamp, normal_force, normal_force_delta, tangential_force, tangential_force_delta, direction, proximity, temperature)[source]

Timestamped touch sensor feedback for a fingertip

direction: int
normal_force: float
normal_force_delta: int
proximity: int
tangential_force: float
tangential_force_delta: int
temperature: int
timestamp: float
class pyzlg_dexhand.dexhand_interface.HandFeedback(query_timestamp, joints, touch)[source]

Feedback data for whole hand

joints: Dict[str, JointFeedback]
query_timestamp: float
touch: Dict[str, StampedTouchFeedback]

Enumerations

class pyzlg_dexhand.dexhand_interface.ControlMode(*values)[source]

Motor control modes

CASCADED_PID = 68
CURRENT = 17
HALL_POSITION = 51
IMPEDANCE_GRASP = 119
MIT_TORQUE = 102
PROTECT_HALL_POSITION = 85
SPEED = 34
ZERO_TORQUE = 0

Example Usage

Basic Joint Control

from pyzlg_dexhand import RightDexHand, ControlMode, JointCommand

# Initialize hand
hand = RightDexHand()
hand.init()

# Basic position control
hand.move_joints(
    th_rot=30,     # Thumb rotation
    th_mcp=45,     # Thumb MCP flexion
    th_dip=45,     # Thumb coupled distal flexion
    control_mode=ControlMode.IMPEDANCE_GRASP
)

# Advanced control with JointCommand
hand.move_joints(
    # Position, current and velocity
    th_rot=JointCommand(position=30, current=25, velocity=12000),

    # Position and current only
    th_mcp=JointCommand(position=45, current=30),

    # Position only - same as th_dip=45
    th_dip=JointCommand(position=45),

    control_mode=ControlMode.IMPEDANCE_GRASP
)

Feedback Handling

# Get feedback
feedback = hand.get_feedback()

# Access joint feedback
thumb_angle = feedback.joints['th_rot'].angle
thumb_encoder = feedback.joints['th_rot'].encoder_position

# Access touch sensor feedback
thumb_force = feedback.touch['th'].normal_force
thumb_dir = feedback.touch['th'].direction

Error Handling

# Clear any error states
hand.clear_errors(clear_all=True)

# Check for specific errors
errors = hand.get_errors()
for board_idx, error in errors.items():
    if error:
        print(f"Board {board_idx} error: {error.description}")

Notes

Control Modes

  • CASCADED_PID: Default mode. Precise position control mode. Provides highest stiffness and position accuracy.

  • IMPEDANCE_GRASP (0x77): Optimized for safe grasping operations. This mode:
    • Provides soft, compliant grasp that adapts to object shape

    • Automatically detects contact with objects and reduces force

    • Prevents damage to both the hand and manipulated objects

    • Maintains position control until contact is detected

  • MIT_TORQUE (0x66): High-precision torque control that maintains stable force after object contact.
    • Allows direct proportional force control while maintaining position control

    • Useful when fine force control is needed during manipulation

    • Enables dynamic force adjustments during movement

    • Creates balance between position tracking and force limitation

  • HALL_POSITION: Direct hall sensor position control. Less precise but faster response.

  • PROTECT_HALL_POSITION: Safe hall position control requiring zero position at startup.

  • CURRENT: Direct current control for force-based applications.

  • SPEED: Velocity control mode.

  • ZERO_TORQUE: Disables motor torque, allowing free movement.

Joint Limits

Default joint angle limits (in degrees):

  • Thumb rotation (th_rot): 0-150

  • Metacarpophalangeal joints (mcp): 0-90

  • Distal joints (dip): 0-90

  • Four-finger spread (ff_spr): 0-30

Error Handling

When a finger encounters an obstacle or abnormal condition:

  1. The board may enter an error state

  2. Motors on that board become unresponsive

  3. clear_errors() must be called to restore operation

  4. Consider clearing errors after each command for robust operation