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 handbase_id (
int
) – Base board ID (0x01 for left, 0x07 for right)zcan (
Optional
[ZCANWrapper
]) – Optional existing ZCANWrapper instance to share between handslog_level (
Optional
[LogLevel
]) – Logging level for this hand instancedevice_index (
int
) – Device index for ZCAN device if creating new ZCAN instanceauto_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
- 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:
- 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 modeuse_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 fromtimeout (
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 enumenable_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 errorsrequest_feedback (
bool
) – Whether to request feedbackis_right_hand (
bool
) – True for right hand, False for left handpositions (
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 unitsmotor2_pos (
int
) – Position command for motor 2, in hardware unitsmotor_enable (
int
) – Motor enable flags, 0x01 for motor 1, 0x02 for motor 2, 0x03 for bothcontrol_mode (
ControlMode
) – Control modemotor1_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 modeperiod_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 disablelog_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 Nlog_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 255log_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 tovalue (
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 handslog_level (
Optional
[LogLevel
]) – Logging level for operation feedbackdevice_index (
int
) – Device index for ZCAN device if creating new instanceauto_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 handslog_level (
Optional
[LogLevel
]) – Logging level for operation feedbackdevice_index (
int
) – Device index for ZCAN device if creating new instanceauto_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
-
current:
- class pyzlg_dexhand.dexhand_interface.HandConfig(channel, hall_scale)[source]
Configuration for hand hardware
-
channel:
int
-
hall_scale:
List
[float
]
-
channel:
- 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
-
angle:
- 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
-
direction:
- 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
]
-
joints:
Enumerations
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:
The board may enter an error state
Motors on that board become unresponsive
clear_errors()
must be called to restore operationConsider clearing errors after each command for robust operation