DexHand Protocol

The DexHand protocol implements the CANFD communication layer between host and hand hardware.

Core Protocol

Message Types

class pyzlg_dexhand.dexhand_protocol.MessageType(*values)[source]

CAN message type identifiers and their base addresses

COMMAND_READ = 1
COMMAND_WRITE = 2
CONFIG_COMMAND = 0
CONFIG_RESPONSE = 128
ERROR_MESSAGE = 1536
GLOBAL_COMMAND = 255
INVALID = 4096
MOTION_COMMAND = 256
MOTION_FEEDBACK = 384
UNKNOWN = 4097

Board IDs

class pyzlg_dexhand.dexhand_protocol.BoardID(*values)[source]

Base ID values for left and right hand boards

LEFT_HAND_BASE = 1
RIGHT_HAND_BASE = 7

Commands

Command Types

class pyzlg_dexhand.dexhand_protocol.commands.CommandType(*values)[source]

Command type identifiers

CLEAR_ERROR = 164
CONFIG_FEEDBACK = 116
MOTOR_COMMAND = 0

Control Modes

class pyzlg_dexhand.dexhand_protocol.commands.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

Feedback Modes

class pyzlg_dexhand.dexhand_protocol.commands.FeedbackMode(*values)[source]

Feedback operation modes

ON_CHANGE = 3
PERIODIC = 1
QUERY = 2

Command Classes

class pyzlg_dexhand.dexhand_protocol.commands.MotorCommand(control_mode, motor_enable, motor1_pos, motor2_pos, motor1_speed, motor2_speed, motor1_current, motor2_current)[source]

Command for a pair of motors

control_mode: ControlMode
motor1_current: int
motor1_pos: int
motor1_speed: int
motor2_current: int
motor2_pos: int
motor2_speed: int
motor_enable: int
class pyzlg_dexhand.dexhand_protocol.commands.ClearErrorCommand[source]

Command to clear error state

class pyzlg_dexhand.dexhand_protocol.commands.FeedbackConfigCommand(mode, period_ms, enable)[source]

Command to configure feedback behavior

enable: bool
mode: FeedbackMode
period_ms: int

Command Encoding

pyzlg_dexhand.dexhand_protocol.commands.encode_command(command)[source]

Encode a command for transmission

Parameters:

command (Union[MotorCommand, ClearErrorCommand, FeedbackConfigCommand, BroadcastCommand, GlobalCommand]) – Command to encode

Return type:

tuple[MessageType, bytes]

Returns:

Tuple of (message_type, encoded_bytes)

Raises:

ValueError – If command parameters are invalid

Messages

Error Types

class pyzlg_dexhand.dexhand_protocol.messages.BoardError(*values)[source]

Motor error status

BOTH_MOTORS_ERROR = 3
MOTOR1_ERROR = 1
MOTOR2_ERROR = 2
class pyzlg_dexhand.dexhand_protocol.messages.ErrorCode(*values)[source]

Error codes from protocol

CURRENT_OVERLOAD = 1
HALL_ERROR = 2
PARAM_ERROR = 4
STALL_ERROR = 3

Feedback Classes

class pyzlg_dexhand.dexhand_protocol.messages.MotorFeedback(current, velocity, position, angle, encoder_value=None, error_code=None, impedance=None)[source]

Feedback data for a single motor

angle: float
current: int
encoder_value: Optional[int] = None
error_code: Optional[int] = None
impedance: Optional[float] = None
position: int
velocity: int
class pyzlg_dexhand.dexhand_protocol.messages.TouchFeedback(normal_force, normal_force_delta, tangential_force, tangential_force_delta, direction, proximity, temperature)[source]

Feedback from touch sensor

direction: int
normal_force: float
normal_force_delta: int
proximity: int
tangential_force: float
tangential_force_delta: int
temperature: int
class pyzlg_dexhand.dexhand_protocol.messages.BoardFeedback(motor1, motor2, position_sensor1, position_sensor2, touch=None)[source]

Complete feedback from a motor control board

motor1: MotorFeedback
motor2: MotorFeedback
position_sensor1: float
position_sensor2: float
touch: Optional[TouchFeedback] = None
class pyzlg_dexhand.dexhand_protocol.messages.ErrorInfo(error_type, error_data, description)[source]

Error information from a board

description: str
error_data: bytes
error_type: BoardError

Message Processing

class pyzlg_dexhand.dexhand_protocol.messages.ProcessedMessage(sender_id, msg_type, feedback=None, error_info=None)[source]

Processed message from board

error_info: Optional[ErrorInfo] = None
feedback: Optional[BoardFeedback] = None
msg_type: MessageType
sender_id: int
pyzlg_dexhand.dexhand_protocol.messages.process_message(can_id, data)[source]

Process a received CAN message

Parameters:
  • can_id (int) – CAN ID of the message

  • data (bytes) – Raw message bytes

Return type:

ProcessedMessage

Returns:

ProcessedMessage containing decoded information

Raises:

ValueError – If message cannot be decoded

Protocol Specification

Message Structure

The protocol uses standard CANFD frames with extended identifiers. Message IDs are constructed as:

  • Base message type (e.g., 0x100 for motion commands)

  • Board ID offset (0x01-0x06 for left hand, 0x07-0x0C for right hand)

Command Format

Motor Command:

Byte 0: Control mode
Byte 1: Motor enable flags (0x01=motor1, 0x02=motor2, 0x03=both)
Byte 2-3: Motor 1 position (little endian)
Byte 4-5: Motor 2 position (little endian)

Clear Error Command:

Byte 0: 0x03 (Command prefix)
Byte 1: 0xA4 (Clear error command)

Feedback Config Command:

Byte 0: 0x03 (Command prefix)
Byte 1: 0x74 (Feedback config command)
Byte 2: Feedback mode
Byte 3: Period (10ms units)
Byte 4: Enable flag

Example Usage

Command Generation

from pyzlg_dexhand.dexhand_protocol.commands import (
    MotorCommand,
    ControlMode,
    encode_command
)

# Create motor command
command = MotorCommand(
    control_mode=ControlMode.CASCADED_PID,
    motor_enable=0x03,  # Both motors enabled
    motor1_pos=1000,
    motor2_pos=-2000
)

# Encode for transmission
msg_type, data = encode_command(command)

Message Processing

from pyzlg_dexhand.dexhand_protocol.messages import process_message

# Process received message
can_id = 0x181  # Example: Board 1 feedback
data = b'...'   # Raw message data

result = process_message(can_id, data)

if result.msg_type == MessageType.MOTION_FEEDBACK:
    print(f"Motor 1 position: {result.feedback.motor1.position}")
    print(f"Motor 2 position: {result.feedback.motor2.position}")
elif result.msg_type == MessageType.ERROR_MESSAGE:
    print(f"Error: {result.error.description}")

Notes

Message Flow

  1. Host sends commands using appropriate message type

  2. Hand processes command and returns feedback/response

  3. Any errors are reported via error messages

Error Handling

  1. Check message type from CAN ID

  2. Process messages according to type

  3. Handle errors by: - Parsing error information - Clearing errors when safe - Resuming normal operation