SDK 使用说明

API 参考

1. 字段列表

本节介绍 wujihandpy 中所有可用的数据字段。

1.1 Hand 层

该层包含整手设备唯一的通用字段,例如手性、固件版本等。

handedness

该字段表示灵巧手的手性(左/右手,0 表示右手,1 表示左手)。

  • 类型uint8
  • 读写属性:只读

firmware_version

该字段表示灵巧手固件的版本号。

  • 类型uint32
  • 读写属性:只读

firmware_date

该字段表示灵巧手固件的编译日期。

  • 类型uint32
  • 读写属性:只读

system_time

该字段表示灵巧手系统运行时间,单位为毫秒。

  • 类型uint32
  • 读写属性:只读

temperature

该字段表示灵巧手手腕附近的当前温度,单位为摄氏度。

  • 类型float32
  • 读写属性:只读

input_voltage

该字段表示灵巧手母线电压的实测值,单位为伏特。

  • 类型float32
  • 读写属性:只读

1.2 Joint 层

该层包含每关节持有一个独立副本的字段,例如使能、目标位置等。

joint_firmware_version

该字段记录关节驱动板固件的版本号。

  • 类型uint32
  • 读写属性:只读

joint_firmware_date

该字段记录关节驱动板固件的编译日期。

  • 类型uint32
  • 读写属性:只读

joint_control_mode

该字段用于设置关节的控制模式。

  • 类型uint16
  • 读写属性:只写

说明:模式会自动切换,一般情况下不应修改该字段。

joint_sin_level

该字段用于设置关节驱动的正弦波激励档位。

  • 类型uint16
  • 读写属性:只写

说明:该字段用于内部调试,一般情况下不应修改该字段。

joint_effort_limit

该字段用于设置关节允许的 effort 上限。

  • 类型float64
  • 单位:安培 (A)
  • 默认值1.5
  • 合法范围0.0 ~ 3.5(超过 3.5 会被限制为 3.5)
  • 读写属性:读写

什么是 Effort?

Effort 是电流空间的执行器作用量,经过滤波处理后输出。它不是实际测量的电流值,应将其理解为相对驱动强度,适用于负载监控和碰撞检测等场景。详见 joint_effort 字段。

过热保护:Effort 限制 会随温度动态调整

为保护设备,固件会根据关节温度自动降低实际生效的 effort 限制:

温度状态触发条件实际 Effort 限制
正常低于 85°C用户设定值 (默认 1.5A)
温度预警 (Tier 1)大于等于 85°C用户设定值 × 70%
温度告警 (Tier 2)大于等于 93°C用户设定值 × 40%

恢复阶段采用 4°C 回退阈值:

  • 从 Tier 2 回退到 Tier 1:温度需降到 89°C 以下
  • 从 Tier 1 恢复到正常:温度需降到 81°C 以下

当温度恢复到安全范围后,effort 限制会自动恢复。

警告:修改 Effort 限制 可能导致设备损坏

修改此参数会改变关节的最大输出能力。如因调整 effort limit 导致设备损坏,用户需自行承担责任。

  • 默认值 1.5 适用于大多数应用场景
  • 最大值 3.5,超过此值会被自动限制
  • 增大此值会增加关节负载能力,但也增加损坏风险
  • 影响相关关节运动寿命,加速各零件磨损且无法预估影响大小
  • 可能在某工况下直接造成相关关节出现不可逆的损坏
  • 可能加速关节热保护触发,减少持续运动时间
  • 可能出现除以上情况下的其他严重后果

joint_bus_voltage

该字段记录关节当前的母线电压实测值。

  • 类型float32
  • 读写属性:只读

joint_temperature

该字段记录关节驱动板当前的温度,单位为摄氏度。

  • 类型float32
  • 读写属性:只读

joint_reset_error

向该字段写入 1 可清除关节上报的错误状态。

  • 类型uint16
  • 读写属性:只写

该字段仅能清除错误码,不能解决灵巧手出现的问题。
切勿滥用此字段,尤其不能在循环中使用此字段,否则可能导致灵巧手损坏。

joint_error_code

该字段表示各关节的当前错误码,用于诊断运行状态。 值为 0 时表示关节无异常。

  • 类型uint32
  • 读写属性:只读

joint_effort

该字段提供关节的实时 effort 反馈。

  • 类型float32
  • 单位:安培 (A)
  • 读写属性:只读

Effort 的含义

Effort 是电流空间的执行器作用量 (actuation effort in current space),经过滤波处理后输出。

  • 不是实际测量的电流值
  • 不是电流环的直接输出
  • 应将其理解为相对驱动强度,适用于负载监控和碰撞检测

典型应用场景:

  • 碰撞检测:effort 突增表示关节受阻
  • 输出监控:可通过 effort / effort_limit 计算当前输出百分比

此字段仅在实时控制模式下通过 IController.get_joint_actual_effort() 访问。

joint_enabled

该字段控制关节的使能和失能。

  • 类型bool
  • 默认值False
  • 合法范围True / False
  • 读写属性:只写

joint_actual_position

该字段提供关节的实际位置。

  • 类型float64
  • 读写属性:只读

joint_target_position

写入该字段可下发关节的目标控制角度。若数值超出合法范围,会自动限幅至允许区间。

  • 类型float64
  • 合法范围joint_lower_limit ~ joint_upper_limit
  • 读写属性:只写

joint_upper_limit

该字段记录关节的运行位置上限。

  • 类型float64
  • 读写属性:只读

与 URDF 关节范围的区别

各关节在加工时存在微小的精度误差,使每个关节的实际物理极限略有不同。
灵巧手在出厂时会对各关节的实际极限进行标定,结果写入 joint_upper_limitjoint_lower_limit 字段。
因此,这两个字段记录的是经标定的实际物理极限值,通常略大于 URDF 文件中定义的范围。

URDF 文件中的关节范围是理论设计值,经过保守缩放以考虑加工误差,可用于仿真或神经网络训练。
joint_upper_limitjoint_lower_limit 表示实际测得的可运动范围。

joint_lower_limit

该字段记录关节的运行位置下限。

  • 类型float64
  • 读写属性:只读

2. API 列表

2.1 Hand 类

2.1.1 构造函数

  • __init__(serial_number=None, *, side=None, usb_pid=0x2000, usb_vid=0x0483, mask=None) -> None 初始化灵巧手连接,支持通过序列号、左右手、USB ID 或设备掩码指定设备

    • serial_number:USB 序列号字符串,精确指定一台设备
    • side"left""right",按手性选择设备,与 serial_number 互斥(详见 教程 §1.3

2.1.2 手指访问

  • finger(index) -> Finger 获取指定索引的手指对象,索引范围 0-4

2.1.3 线程安全控制

  • disable_thread_safe_check() -> None 禁用线程安全检查,允许在多线程环境中并发访问 Hand 对象

注意:禁用线程安全检查后,用户需要自行使用互斥锁(threading.Lock)确保多线程操作的正确性。

2.1.4 系统信息

固件信息
  • read_firmware_version(timeout=0.5) -> uint32 同步读取固件版本号

  • read_firmware_version_async(timeout=0.5) -> Awaitable[uint32] 异步读取固件版本号

  • read_firmware_version_unchecked(timeout=0.5) -> None 非阻塞读取固件版本号

  • get_firmware_version() -> uint32 获取缓存的固件版本号

  • read_firmware_date(timeout=0.5) -> uint32 同步读取固件编译日期

  • read_firmware_date_async(timeout=0.5) -> Awaitable[uint32] 异步读取固件编译日期

  • read_firmware_date_unchecked(timeout=0.5) -> None 非阻塞读取固件编译日期

  • get_firmware_date() -> uint32 获取缓存的固件编译日期

  • read_handedness(timeout=0.5) -> uint8 同步读取左右手标识(0=右,1=左)

  • read_handedness_async(timeout=0.5) -> Awaitable[uint8] 异步读取左右手标识

  • read_handedness_unchecked(timeout=0.5) -> None 非阻塞读取左右手标识

  • get_handedness() -> uint8 获取缓存的左右手标识

系统状态
  • read_system_time(timeout=0.5) -> uint32 同步读取系统运行时间(毫秒)

  • read_system_time_async(timeout=0.5) -> Awaitable[uint32] 异步读取系统运行时间

  • read_system_time_unchecked(timeout=0.5) -> None 非阻塞读取系统运行时间

  • get_system_time() -> uint32 获取缓存的系统运行时间

  • read_temperature(timeout=0.5) -> float32 同步读取手掌温度(摄氏度)

  • read_temperature_async(timeout=0.5) -> Awaitable[float32] 异步读取手掌温度

  • read_temperature_unchecked(timeout=0.5) -> None 非阻塞读取手掌温度

  • get_temperature() -> float32 获取缓存的手掌温度

  • read_input_voltage(timeout=0.5) -> float32 同步读取输入电压(伏特)

  • read_input_voltage_async(timeout=0.5) -> Awaitable[float32] 异步读取输入电压

  • read_input_voltage_unchecked(timeout=0.5) -> None 非阻塞读取输入电压

  • get_input_voltage() -> float32 获取缓存的输入电压

2.1.5 关节数据(批量读取,返回 4 数组)

位置数据
  • read_joint_actual_position(timeout=0.5) -> NDArray[float64] 同步读取所有关节实际位置(弧度)

  • read_joint_actual_position_async(timeout=0.5) -> Awaitable[NDArray[float64]] 异步读取所有关节实际位置

  • read_joint_actual_position_unchecked(timeout=0.5) -> None 非阻塞读取所有关节实际位置

  • get_joint_actual_position() -> NDArray[float64] 获取缓存的所有关节实际位置

  • read_joint_upper_limit(timeout=0.5) -> NDArray[float64] 同步读取所有关节上限位置(弧度)

  • read_joint_upper_limit_async(timeout=0.5) -> Awaitable[NDArray[float64]] 异步读取所有关节上限位置

  • read_joint_upper_limit_unchecked(timeout=0.5) -> None 非阻塞读取所有关节上限位置

  • get_joint_upper_limit() -> NDArray[float64] 获取缓存的所有关节上限位置

  • read_joint_lower_limit(timeout=0.5) -> NDArray[float64] 同步读取所有关节下限位置(弧度)

  • read_joint_lower_limit_async(timeout=0.5) -> Awaitable[NDArray[float64]] 异步读取所有关节下限位置

  • read_joint_lower_limit_unchecked(timeout=0.5) -> None 非阻塞读取所有关节下限位置

  • get_joint_lower_limit() -> NDArray[float64] 获取缓存的所有关节下限位置

状态监控
  • read_joint_bus_voltage(timeout=0.5) -> NDArray[float32] 同步读取所有关节母线电压(伏特)

  • read_joint_bus_voltage_async(timeout=0.5) -> Awaitable[NDArray[float32]] 异步读取所有关节母线电压

  • read_joint_bus_voltage_unchecked(timeout=0.5) -> None 非阻塞读取所有关节母线电压

  • get_joint_bus_voltage() -> NDArray[float32] 获取缓存的所有关节母线电压

  • read_joint_temperature(timeout=0.5) -> NDArray[float32] 同步读取所有关节温度(摄氏度)

  • read_joint_temperature_async(timeout=0.5) -> Awaitable[NDArray[float32]] 异步读取所有关节温度

  • read_joint_temperature_unchecked(timeout=0.5) -> None 非阻塞读取所有关节温度

  • get_joint_temperature() -> NDArray[float32] 获取缓存的所有关节温度

  • read_joint_error_code(timeout=0.5) -> NDArray[uint32] 同步读取所有关节错误码

  • read_joint_error_code_async(timeout=0.5) -> Awaitable[NDArray[uint32]] 异步读取所有关节错误码

  • read_joint_error_code_unchecked(timeout=0.5) -> None 非阻塞读取所有关节错误码

  • get_joint_error_code() -> NDArray[uint32] 获取缓存的所有关节错误码

Effort 限制 数据
  • read_joint_effort_limit(timeout=0.5) -> NDArray[float64] 同步读取所有关节 effort limit(安培)
  • read_joint_effort_limit_async(timeout=0.5) -> Awaitable[NDArray[float64]] 异步读取所有关节 effort limit
  • read_joint_effort_limit_unchecked(timeout=0.5) -> None 非阻塞读取所有关节 effort limit
  • get_joint_effort_limit() -> NDArray[float64] 获取缓存的所有关节 effort limit
固件信息
  • read_joint_firmware_version(timeout=0.5) -> NDArray[uint32] 同步读取所有关节固件版本

  • read_joint_firmware_version_async(timeout=0.5) -> Awaitable[NDArray[uint32]] 异步读取所有关节固件版本

  • read_joint_firmware_version_unchecked(timeout=0.5) -> None 非阻塞读取所有关节固件版本

  • get_joint_firmware_version() -> NDArray[uint32] 获取缓存的所有关节固件版本

  • read_joint_firmware_date(timeout=0.5) -> NDArray[uint32] 同步读取所有关节固件编译日期

  • read_joint_firmware_date_async(timeout=0.5) -> Awaitable[NDArray[uint32]] 异步读取所有关节固件编译日期

  • read_joint_firmware_date_unchecked(timeout=0.5) -> None 非阻塞读取所有关节固件编译日期

  • get_joint_firmware_date() -> NDArray[uint32] 获取缓存的所有关节固件编译日期

2.1.6 关节控制(支持单个值或 4 数组)

使能控制
  • write_joint_enabled(value, timeout=0.5) -> None 同步设置所有关节使能状态
  • write_joint_enabled(value_array, timeout=0.5) -> None 同步批量设置各关节使能状态
  • write_joint_enabled_async(value, timeout=0.5) -> Awaitable[None] 异步设置所有关节使能状态
  • write_joint_enabled_async(value_array, timeout=0.5) -> Awaitable[None] 异步批量设置各关节使能状态
  • write_joint_enabled_unchecked(value, timeout=0.5) -> None 非阻塞设置所有关节使能状态
  • write_joint_enabled_unchecked(value_array, timeout=0.5) -> None 非阻塞批量设置各关节使能状态
位置控制
  • write_joint_target_position(value, timeout=0.5) -> None 同步设置所有关节目标位置(弧度)
  • write_joint_target_position(value_array, timeout=0.5) -> None 同步批量设置各关节目标位置
  • write_joint_target_position_async(value, timeout=0.5) -> Awaitable[None] 异步设置所有关节目标位置
  • write_joint_target_position_async(value_array, timeout=0.5) -> Awaitable[None] 异步批量设置各关节目标位置
  • write_joint_target_position_unchecked(value, timeout=0.5) -> None 非阻塞设置所有关节目标位置
  • write_joint_target_position_unchecked(value_array, timeout=0.5) -> None 非阻塞批量设置各关节目标位置
模式控制
  • write_joint_control_mode(value, timeout=0.5) -> None 同步设置所有关节控制模式
  • write_joint_control_mode(value_array, timeout=0.5) -> None 同步批量设置各关节控制模式
  • write_joint_control_mode_async(value, timeout=0.5) -> Awaitable[None] 异步设置所有关节控制模式
  • write_joint_control_mode_async(value_array, timeout=0.5) -> Awaitable[None] 异步批量设置各关节控制模式
  • write_joint_control_mode_unchecked(value, timeout=0.5) -> None 非阻塞设置所有关节控制模式
  • write_joint_control_mode_unchecked(value_array, timeout=0.5) -> None 非阻塞批量设置各关节控制模式
Effort 限制 配置

警告:修改 effort limit 可能导致设备损坏,详见字段说明。

  • write_joint_effort_limit(value, timeout=0.5) -> None 同步设置所有关节 effort limit(安培)
  • write_joint_effort_limit(value_array, timeout=0.5) -> None 同步批量设置各关节 effort limit
  • write_joint_effort_limit_async(value, timeout=0.5) -> Awaitable[None] 异步设置所有关节 effort limit
  • write_joint_effort_limit_async(value_array, timeout=0.5) -> Awaitable[None] 异步批量设置各关节 effort limit
  • write_joint_effort_limit_unchecked(value, timeout=0.5) -> None 非阻塞设置所有关节 effort limit
  • write_joint_effort_limit_unchecked(value_array, timeout=0.5) -> None 非阻塞批量设置各关节 effort limit
其他参数配置
  • write_joint_sin_level(value, timeout=0.5) -> None 同步设置所有关节正弦波激励档位

  • write_joint_sin_level(value_array, timeout=0.5) -> None 同步批量设置各关节正弦波激励档位

  • write_joint_sin_level_async(value, timeout=0.5) -> Awaitable[None] 异步设置所有关节正弦波激励档位

  • write_joint_sin_level_async(value_array, timeout=0.5) -> Awaitable[None] 异步批量设置各关节正弦波激励档位

  • write_joint_sin_level_unchecked(value, timeout=0.5) -> None 非阻塞设置所有关节正弦波激励档位

  • write_joint_sin_level_unchecked(value_array, timeout=0.5) -> None 非阻塞批量设置各关节正弦波激励档位

  • write_joint_reset_error(value, timeout=0.5) -> None 同步重置所有关节错误

  • write_joint_reset_error(value_array, timeout=0.5) -> None 同步批量重置各关节错误

  • write_joint_reset_error_async(value, timeout=0.5) -> Awaitable[None] 异步重置所有关节错误

  • write_joint_reset_error_async(value_array, timeout=0.5) -> Awaitable[None] 异步批量重置各关节错误

  • write_joint_reset_error_unchecked(value, timeout=0.5) -> None 非阻塞重置所有关节错误

  • write_joint_reset_error_unchecked(value_array, timeout=0.5) -> None 非阻塞批量重置各关节错误

2.1.7 实时控制器

  • realtime_controller(enable_upstream, filter) -> IController 创建实时控制器,用于高频控制场景

2.2 Finger 类

2.2.1 关节访问

  • joint(index) -> Joint 获取指定索引的关节对象,索引范围 0-3

2.2.2 关节数据(返回 4 元素数组)

位置数据
  • read_joint_actual_position(timeout=0.5) -> NDArray[float64] 同步读取手指所有关节实际位置(弧度)

  • read_joint_actual_position_async(timeout=0.5) -> Awaitable[NDArray[float64]] 异步读取手指所有关节实际位置

  • read_joint_actual_position_unchecked(timeout=0.5) -> None 非阻塞读取手指所有关节实际位置

  • get_joint_actual_position() -> NDArray[float64] 获取缓存的手指所有关节实际位置

  • read_joint_upper_limit(timeout=0.5) -> NDArray[float64] 同步读取手指所有关节上限位置(弧度)

  • read_joint_upper_limit_async(timeout=0.5) -> Awaitable[NDArray[float64]] 异步读取手指所有关节上限位置

  • read_joint_upper_limit_unchecked(timeout=0.5) -> None 非阻塞读取手指所有关节上限位置

  • get_joint_upper_limit() -> NDArray[float64] 获取缓存的手指所有关节上限位置

  • read_joint_lower_limit(timeout=0.5) -> NDArray[float64] 同步读取手指所有关节下限位置(弧度)

  • read_joint_lower_limit_async(timeout=0.5) -> Awaitable[NDArray[float64]] 异步读取手指所有关节下限位置

  • read_joint_lower_limit_unchecked(timeout=0.5) -> None 非阻塞读取手指所有关节下限位置

  • get_joint_lower_limit() -> NDArray[float64] 获取缓存的手指所有关节下限位置

状态监控
  • read_joint_bus_voltage(timeout=0.5) -> NDArray[float32] 同步读取手指所有关节母线电压(伏特)

  • read_joint_bus_voltage_async(timeout=0.5) -> Awaitable[NDArray[float32]] 异步读取手指所有关节母线电压

  • read_joint_bus_voltage_unchecked(timeout=0.5) -> None 非阻塞读取手指所有关节母线电压

  • get_joint_bus_voltage() -> NDArray[float32] 获取缓存的手指所有关节母线电压

  • read_joint_temperature(timeout=0.5) -> NDArray[float32] 同步读取手指所有关节温度(摄氏度)

  • read_joint_temperature_async(timeout=0.5) -> Awaitable[NDArray[float32]] 异步读取手指所有关节温度

  • read_joint_temperature_unchecked(timeout=0.5) -> None 非阻塞读取手指所有关节温度

  • get_joint_temperature() -> NDArray[float32] 获取缓存的手指所有关节温度

  • read_joint_error_code(timeout=0.5) -> NDArray[uint32] 同步读取手指所有关节错误码

  • read_joint_error_code_async(timeout=0.5) -> Awaitable[NDArray[uint32]] 异步读取手指所有关节错误码

  • read_joint_error_code_unchecked(timeout=0.5) -> None 非阻塞读取手指所有关节错误码

  • get_joint_error_code() -> NDArray[uint32] 获取缓存的手指所有关节错误码

Effort 限制 数据
  • read_joint_effort_limit(timeout=0.5) -> NDArray[float64] 同步读取手指所有关节 effort limit(安培)
  • read_joint_effort_limit_async(timeout=0.5) -> Awaitable[NDArray[float64]] 异步读取手指所有关节 effort limit
  • read_joint_effort_limit_unchecked(timeout=0.5) -> None 非阻塞读取手指所有关节 effort limit
  • get_joint_effort_limit() -> NDArray[float64] 获取缓存的手指所有关节 effort limit
固件信息
  • read_joint_firmware_version(timeout=0.5) -> NDArray[uint32] 同步读取手指所有关节固件版本

  • read_joint_firmware_version_async(timeout=0.5) -> Awaitable[NDArray[uint32]] 异步读取手指所有关节固件版本

  • read_joint_firmware_version_unchecked(timeout=0.5) -> None 非阻塞读取手指所有关节固件版本

  • get_joint_firmware_version() -> NDArray[uint32] 获取缓存的手指所有关节固件版本

  • read_joint_firmware_date(timeout=0.5) -> NDArray[uint32] 同步读取手指所有关节固件编译日期

  • read_joint_firmware_date_async(timeout=0.5) -> Awaitable[NDArray[uint32]] 异步读取手指所有关节固件编译日期

  • read_joint_firmware_date_unchecked(timeout=0.5) -> None 非阻塞读取手指所有关节固件编译日期

  • get_joint_firmware_date() -> NDArray[uint32] 获取缓存的手指所有关节固件编译日期

2.2.3 关节控制(支持单个值或 4 元素数组)

使能控制
  • write_joint_enabled(value, timeout=0.5) -> None 同步设置手指所有关节使能状态
  • write_joint_enabled(value_array, timeout=0.5) -> None 同步批量设置手指各关节使能状态
  • write_joint_enabled_async(value, timeout=0.5) -> Awaitable[None] 异步设置手指所有关节使能状态
  • write_joint_enabled_async(value_array, timeout=0.5) -> Awaitable[None] 异步批量设置手指各关节使能状态
  • write_joint_enabled_unchecked(value, timeout=0.5) -> None 非阻塞设置手指所有关节使能状态
  • write_joint_enabled_unchecked(value_array, timeout=0.5) -> None 非阻塞批量设置手指各关节使能状态
位置控制
  • write_joint_target_position(value, timeout=0.5) -> None 同步设置手指所有关节目标位置(弧度)
  • write_joint_target_position(value_array, timeout=0.5) -> None 同步批量设置手指各关节目标位置
  • write_joint_target_position_async(value, timeout=0.5) -> Awaitable[None] 异步设置手指所有关节目标位置
  • write_joint_target_position_async(value_array, timeout=0.5) -> Awaitable[None] 异步批量设置手指各关节目标位置
  • write_joint_target_position_unchecked(value, timeout=0.5) -> None 非阻塞设置手指所有关节目标位置
  • write_joint_target_position_unchecked(value_array, timeout=0.5) -> None 非阻塞批量设置手指各关节目标位置
模式控制
  • write_joint_control_mode(value, timeout=0.5) -> None 同步设置手指所有关节控制模式
  • write_joint_control_mode(value_array, timeout=0.5) -> None 同步批量设置手指各关节控制模式
  • write_joint_control_mode_async(value, timeout=0.5) -> Awaitable[None] 异步设置手指所有关节控制模式
  • write_joint_control_mode_async(value_array, timeout=0.5) -> Awaitable[None] 异步批量设置手指各关节控制模式
  • write_joint_control_mode_unchecked(value, timeout=0.5) -> None 非阻塞设置手指所有关节控制模式
  • write_joint_control_mode_unchecked(value_array, timeout=0.5) -> None 非阻塞批量设置手指各关节控制模式
Effort 限制 配置

警告:修改 effort limit 可能导致设备损坏,详见字段说明。

  • write_joint_effort_limit(value, timeout=0.5) -> None 同步设置手指所有关节 effort limit(安培)
  • write_joint_effort_limit(value_array, timeout=0.5) -> None 同步批量设置手指各关节 effort limit
  • write_joint_effort_limit_async(value, timeout=0.5) -> Awaitable[None] 异步设置手指所有关节 effort limit
  • write_joint_effort_limit_async(value_array, timeout=0.5) -> Awaitable[None] 异步批量设置手指各关节 effort limit
  • write_joint_effort_limit_unchecked(value, timeout=0.5) -> None 非阻塞设置手指所有关节 effort limit
  • write_joint_effort_limit_unchecked(value_array, timeout=0.5) -> None 非阻塞批量设置手指各关节 effort limit
其他参数配置
  • write_joint_sin_level(value, timeout=0.5) -> None 同步设置手指所有关节正弦波激励档位

  • write_joint_sin_level(value_array, timeout=0.5) -> None 同步批量设置手指各关节正弦波激励档位

  • write_joint_sin_level_async(value, timeout=0.5) -> Awaitable[None] 异步设置手指所有关节正弦波激励档位

  • write_joint_sin_level_async(value_array, timeout=0.5) -> Awaitable[None] 异步批量设置手指各关节正弦波激励档位

  • write_joint_sin_level_unchecked(value, timeout=0.5) -> None 非阻塞设置手指所有关节正弦波激励档位

  • write_joint_sin_level_unchecked(value_array, timeout=0.5) -> None 非阻塞批量设置手指各关节正弦波激励档位

  • write_joint_reset_error(value, timeout=0.5) -> None 同步重置手指所有关节错误

  • write_joint_reset_error(value_array, timeout=0.5) -> None 同步批量重置手指各关节错误

  • write_joint_reset_error_async(value, timeout=0.5) -> Awaitable[None] 异步重置手指所有关节错误

  • write_joint_reset_error_async(value_array, timeout=0.5) -> Awaitable[None] 异步批量重置手指各关节错误

  • write_joint_reset_error_unchecked(value, timeout=0.5) -> None 非阻塞重置手指所有关节错误

  • write_joint_reset_error_unchecked(value_array, timeout=0.5) -> None 非阻塞批量重置手指各关节错误

2.3 Joint 类

2.3.1 关节数据(返回单个值)

位置数据
  • read_joint_actual_position(timeout=0.5) -> float64 同步读取关节实际位置(弧度)

  • read_joint_actual_position_async(timeout=0.5) -> Awaitable[float64] 异步读取关节实际位置

  • read_joint_actual_position_unchecked(timeout=0.5) -> None 非阻塞读取关节实际位置

  • get_joint_actual_position() -> float64 获取缓存的关节实际位置

  • read_joint_upper_limit(timeout=0.5) -> float64 同步读取关节上限位置(弧度)

  • read_joint_upper_limit_async(timeout=0.5) -> Awaitable[float64] 异步读取关节上限位置

  • read_joint_upper_limit_unchecked(timeout=0.5) -> None 非阻塞读取关节上限位置

  • get_joint_upper_limit() -> float64 获取缓存的关节上限位置

  • read_joint_lower_limit(timeout=0.5) -> float64 同步读取关节下限位置(弧度)

  • read_joint_lower_limit_async(timeout=0.5) -> Awaitable[float64] 异步读取关节下限位置

  • read_joint_lower_limit_unchecked(timeout=0.5) -> None 非阻塞读取关节下限位置

  • get_joint_lower_limit() -> float64 获取缓存的关节下限位置

状态监控
  • read_joint_bus_voltage(timeout=0.5) -> float32 同步读取关节母线电压(伏特)

  • read_joint_bus_voltage_async(timeout=0.5) -> Awaitable[float32] 异步读取关节母线电压

  • read_joint_bus_voltage_unchecked(timeout=0.5) -> None 非阻塞读取关节母线电压

  • get_joint_bus_voltage() -> float32 获取缓存的关节母线电压

  • read_joint_temperature(timeout=0.5) -> float32 同步读取关节温度(摄氏度)

  • read_joint_temperature_async(timeout=0.5) -> Awaitable[float32] 异步读取关节温度

  • read_joint_temperature_unchecked(timeout=0.5) -> None 非阻塞读取关节温度

  • get_joint_temperature() -> float32 获取缓存的关节温度

  • read_joint_error_code(timeout=0.5) -> uint32 同步读取关节错误码

  • read_joint_error_code_async(timeout=0.5) -> Awaitable[uint32] 异步读取关节错误码

  • read_joint_error_code_unchecked(timeout=0.5) -> None 非阻塞读取关节错误码

  • get_joint_error_code() -> uint32 获取缓存的关节错误码

Effort 限制 数据
  • read_joint_effort_limit(timeout=0.5) -> float64 同步读取关节 effort limit(安培)
  • read_joint_effort_limit_async(timeout=0.5) -> Awaitable[float64] 异步读取关节 effort limit
  • read_joint_effort_limit_unchecked(timeout=0.5) -> None 非阻塞读取关节 effort limit
  • get_joint_effort_limit() -> float64 获取缓存的关节 effort limit
固件信息
  • read_joint_firmware_version(timeout=0.5) -> uint32 同步读取关节固件版本

  • read_joint_firmware_version_async(timeout=0.5) -> Awaitable[uint32] 异步读取关节固件版本

  • read_joint_firmware_version_unchecked(timeout=0.5) -> None 非阻塞读取关节固件版本

  • get_joint_firmware_version() -> uint32 获取缓存的关节固件版本

  • read_joint_firmware_date(timeout=0.5) -> uint32 同步读取关节固件编译日期

  • read_joint_firmware_date_async(timeout=0.5) -> Awaitable[uint32] 异步读取关节固件编译日期

  • read_joint_firmware_date_unchecked(timeout=0.5) -> None 非阻塞读取关节固件编译日期

  • get_joint_firmware_date() -> uint32 获取缓存的关节固件编译日期

2.3.2 关节控制(单个值)

使能控制
  • write_joint_enabled(value, timeout=0.5) -> None 同步设置关节使能状态
  • write_joint_enabled_async(value, timeout=0.5) -> Awaitable[None] 异步设置关节使能状态
  • write_joint_enabled_unchecked(value, timeout=0.5) -> None 非阻塞设置关节使能状态
位置控制
  • write_joint_target_position(value, timeout=0.5) -> None 同步设置关节目标位置(弧度)
  • write_joint_target_position_async(value, timeout=0.5) -> Awaitable[None] 异步设置关节目标位置
  • write_joint_target_position_unchecked(value, timeout=0.5) -> None 非阻塞设置关节目标位置
模式控制
  • write_joint_control_mode(value, timeout=0.5) -> None 同步设置关节控制模式
  • write_joint_control_mode_async(value, timeout=0.5) -> Awaitable[None] 异步设置关节控制模式
  • write_joint_control_mode_unchecked(value, timeout=0.5) -> None 非阻塞设置关节控制模式
Effort 限制 配置

警告:修改 effort limit 可能导致设备损坏,详见字段说明。

  • write_joint_effort_limit(value, timeout=0.5) -> None 同步设置关节 effort limit(安培)
  • write_joint_effort_limit_async(value, timeout=0.5) -> Awaitable[None] 异步设置关节 effort limit
  • write_joint_effort_limit_unchecked(value, timeout=0.5) -> None 非阻塞设置关节 effort limit
其他参数配置
  • write_joint_sin_level(value, timeout=0.5) -> None 同步设置关节正弦波激励档位

  • write_joint_sin_level_async(value, timeout=0.5) -> Awaitable[None] 异步设置关节正弦波激励档位

  • write_joint_sin_level_unchecked(value, timeout=0.5) -> None 非阻塞设置关节正弦波激励档位

  • write_joint_reset_error(value, timeout=0.5) -> None 同步重置关节错误

  • write_joint_reset_error_async(value, timeout=0.5) -> Awaitable[None] 异步重置关节错误

  • write_joint_reset_error_unchecked(value, timeout=0.5) -> None 非阻塞重置关节错误

2.4 IController 接口

2.4.1 上下文管理

  • __enter__() -> IController 支持 with 语句的上下文管理器入口
  • __exit__(arg0, arg1, arg2) -> None 支持 with 语句的上下文管理器出口
  • close() -> None 手动关闭实时控制器

2.4.2 实时数据获取

  • get_joint_actual_position() -> NDArray[float64] 实时获取所有关节实际位置(高频读取,返回 4 数组)
  • get_joint_actual_effort() -> NDArray[float64] 实时获取所有关节 effort(高频读取,返回 4 数组,单位:安培)

Effort 实时反馈

get_joint_actual_effort() 返回电流空间的执行器作用量 (actuation effort in current space),经过滤波处理。

  • 仅在实时控制器模式下可用
  • 适用于碰撞检测和负载监控
  • 可通过 effort / effort_limit 计算输出百分比

2.4.3 实时数据设置

  • set_joint_target_position(value_array) -> None 实时设置所有关节目标位置(高频写入,参数为 4 数组)

2.5 数组形状说明

  • Hand 类批量操作:返回/接收形状为 {5, 4} 的数组(5个手指 × 4个关节)
  • Finger 类批量操作:返回/接收形状为 {4} 的数组(4个关节)
  • Joint 类操作:返回/接收标量值(单个关节)
  • IController 操作:处理形状为 {5, 4} 的数组,用于高频实时控制

2.6 操作模式说明

  • 同步操作 (read_*, write_*):阻塞操作,确保读/写成功
  • 异步操作 (*_async):返回 Awaitable 对象,支持 await 语法
  • 非阻塞操作 (*_unchecked):立即返回,不保证操作成功,适用于高频率场景
  • 缓存获取 (get_*):获取最近一次读取的数据,不阻塞

3. 触觉感知手套

触觉感知手套(Tactile Sensing Glove)是 Wuji Hand 的选配触觉感知配件。SDK 通过 TactileGlove 类提供设备连接和数据读取接口。

3.1 核心类

TactileHandedness

手型枚举:

  • TactileHandedness.LEFT(0):左手
  • TactileHandedness.RIGHT(1):右手

TactileFrame

单帧触觉数据,包含以下属性:

属性类型说明
handTactileHandedness左手或右手
sequenceint(uint16)帧计数器,0–65535 循环
timestamp_msint(uint32)设备启动后的毫秒时间戳
pressurenumpy.ndarray(24, 32)float32压力矩阵

压力值语义:

  • 范围:[0.0, 1.0]——0.0 表示无接触,1.0 表示最大接触
  • NaN 标记无效单元(不属于任何手指或手掌区域),处理时用 numpy.isnan() 跳过

CRC 校验在 SDK 内部完成,调用方拿到的帧均已通过校验。

TactileGlove

触觉感知手套设备的连接与数据读取。

构造函数:

TactileGlove(serial_number: str | None = None)

serial_number 为 USB 设备序列号。传 None 时自动发现总线上唯一的设备,若存在多台会抛出异常。

3.2 设备连接

自动发现

from wujihandpy import TactileGlove

glove = TactileGlove()
glove.connect()  # 返回 True 表示连接成功

指定设备

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

Context Manager

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

连接管理方法

  • connect() -> bool:连接设备,成功返回 True
  • disconnect() -> None:断开连接并停止流式读取
  • is_connected() -> bool:查询连接状态
  • get_handedness() -> TactileHandedness:返回设备手型

3.3 数据读取

阻塞读取

import numpy as np

frame = glove.read_frame(timeout_ms=100)
print(f"序号: {frame.sequence}")
print(f"压力矩阵形状: {frame.pressure.shape}")  # (24, 32)
print(f"最大压力: {np.nanmax(frame.pressure)}")
  • 内部执行帧同步和 CRC 校验
  • 超时抛出 RuntimeError
  • 连接断开抛出 RuntimeError

流式回调

import numpy as np

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

glove.start_streaming(on_frame)
# ... 业务逻辑 ...
glove.stop_streaming()
  • 回调在内部读取线程中调用,不可阻塞
  • 通过 set_disconnect_callback(fn) 注册断开回调以响应 USB 拔出,之后流式读取自动停止
  • start_streamingread_frame 互斥,不可同时使用
  • 所有阻塞操作释放 Python GIL

3.4 配置与诊断

方法说明
set_sample_rate_hz(hz)设置采样率,范围 1–120 Hz
get_sample_rate_hz() -> int读取当前采样率
set_streaming(enable)开关设备数据帧流
get_streaming_enabled() -> bool读取流式输出开关状态
set_disconnect_callback(callback)注册 Callable[[], None],USB 设备脱离总线时调用一次
get_device_info() -> TactileDeviceInfo读取 serialhw_revisionfw_version
get_fw_build() -> TactileFwBuild读取固件构建信息(git_short_sha
get_diagnostics() -> TactileDiagnostics读取计数器:uptime_msframe_countcrc_err_countdropout_countusb_reset_count
reset_counters()清零诊断计数器
get_device_time() -> TactileDeviceTime读取设备单调时钟(device_monotonic_ns
sync_host_epoch(host_unix_ns) -> TactileSyncResult用主机 UTC 纳秒交换同一时刻的设备时钟
reset_device()软复位。设备会从总线断开并重新枚举,调用后需重新 connect()
enter_bootloader(magic)跳转至 bootloader 以执行 OTA,传入 TACTILE_BOOTLOADER_MAGIC

3.5 异常处理

异常触发场景
RuntimeErrorread_frame 超时、读取期间 USB 断开、未连接时调用 read_frame,或在已流式时重复调用 start_streaming
TactileError命令返回设备协议错误(长度错误、CRC 错误、未知命令、负载错误)

3.6 完整示例

覆盖 TactileGlove 的完整工作流:自动发现与设备信息查询、主机/设备时钟同步、采样率配置、阻塞读取与流式回调、数据保存以及诊断计数器读取。reset_device / enter_bootloader 会断开当前连接(设备复位或进入 bootloader),仅在末尾以注释形式给出。

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)

预期输出示例

[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 与 Wuji Hand 联合使用

HandTactileGlove 使用独立的 USB 传输和线程,可在同一进程内并行使用,无需额外协调。帧回调在触觉手套的流式消费线程中触发,关节命令运行在调用它们的线程上。该模式适合用触觉反馈驱动运动控制的闭环场景,例如根据当前压力峰值动态缩放关节运动幅度。

参考示例:example/joint_with_tactile.py

运行效果:

  • 启动后终端打印 Squeeze the glove to dampen the motion. Ctrl-C to exit.
  • 关节使能后,F2–F5 四指以 100 Hz 实时循环做周期性弯曲–伸展,F1(拇指)保持不动
  • 触觉手套压力峰值越大,关节运动幅度越小:松开手套时幅度最大(约 0.4 rad),用力按压时幅度趋近于 0
  • 松手后幅度自动恢复
  • Ctrl-C 退出时自动停止流式、关闭关节使能并断开手套

3.8 协议参考

本节面向需要自行解析触觉数据帧的高级开发者。使用 SDK 的 TactileGlove 类时无需关注协议细节。

数据帧格式

触觉感知手套通过 USB CDC(虚拟串口)以最高 120 Hz 输出固定 3088 字节的数据帧。实际速率由 set_sample_rate_hz(1–120 Hz)控制:

偏移量长度字段类型说明
0–12帧头u8[2]固定 0xAA 0x55
2–32帧长度u16 LE固定 3088
41手型u80x00 = 左手,0x01 = 右手
5–73填充u8[3]将触觉数据对齐到 4 字节边界
8–30793072触觉数据f32[24][32] LE压力矩阵,行优先,[0.0, 1.0]NaN = 无效单元
3080–30812序号u16 LE帧计数器,0–65535 循环
3082–30854时间戳u32 LE设备启动后毫秒数
3086–30872CRC16u16 LECRC16-CCITT 校验

CRC16-CCITT

  • 多项式:0x1021,初始值:0xFFFF
  • 校验范围:字节 [2, 3086)(帧长度到时间戳,共 3084 字节)
  • 不含帧头和 CRC 字段本身

帧同步算法

  1. 逐字节扫描,匹配帧头 0xAA 0x55
  2. 读取字节 2–3,验证帧长度 == 3088
  3. 读取剩余字节,凑满完整帧
  4. 计算 CRC16 并比对
  5. CRC 失败:丢弃,从 header_position + 1 继续扫描
  6. CRC 成功:解析并交付帧

0xAA 0x55 可能出现在压力数据中(伪帧头),CRC 校验是区分真伪帧头的唯一可靠手段。

参考实现

下面的 Python 片段不依赖 SDK,直接从原始字节流(例如通过 pyserial 打开 CDC 串口)解析单帧,可作为自定义解析器的起点:

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)]

调用示例:

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 模块

wujihandpy.logging 子模块用于在运行时配置 SDK 日志行为。默认行为、环境变量与排查建议见 入门 - 获取日志

4.1 Level 枚举

成员数值含义
Level.Trace0最详细,含原始收发字节
Level.Debug1调试细节
Level.Info2关键事件(默认)
Level.Warn3警告
Level.Error4错误
Level.Critical5严重错误
Level.Off6关闭日志

4.2 函数

set_log_path

设置日志文件目录。必须在 logger 初始化之前调用(常见 Hand 流程下即创建第一个 Hand 之前,flush() 或其他日志接口也会触发 logger 初始化),否则抛出 RuntimeError

def set_log_path(value: str) -> None

set_log_level

设置日志级别。可在任意时刻调用,立即生效。

def set_log_level(value: Level) -> None

set_log_to_file

控制是否写入文件。仅在 logger 初始化时 WUJI_LOG_TO_FILEtrue 才会打开日志文件,初始化后调用此函数可临时关闭或恢复文件输出。若初始化时已被禁用,运行期调用 set_log_to_file(True) 不会重新启用文件输出。

def set_log_to_file(value: bool) -> None

set_log_to_console

控制是否将日志输出到终端(标准输出 / 标准错误)。可在任意时刻调用,立即生效。

def set_log_to_console(value: bool) -> None

flush

强制将缓冲区中的日志刷入文件和终端。进程退出时 SDK 已自动调用,正常使用无需手动触发。

def flush() -> None

目录

1. 字段列表
1.1 Hand 层
handedness
firmware_version
firmware_date
system_time
temperature
input_voltage
1.2 Joint 层
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 列表
2.1 Hand 类
2.1.1 构造函数
2.1.2 手指访问
2.1.3 线程安全控制
2.1.4 系统信息
固件信息
系统状态
2.1.5 关节数据(批量读取,返回 4 数组)
位置数据
状态监控
Effort 限制 数据
固件信息
2.1.6 关节控制(支持单个值或 4 数组)
使能控制
位置控制
模式控制
Effort 限制 配置
其他参数配置
2.1.7 实时控制器
2.2 Finger 类
2.2.1 关节访问
2.2.2 关节数据(返回 4 元素数组)
位置数据
状态监控
Effort 限制 数据
固件信息
2.2.3 关节控制(支持单个值或 4 元素数组)
使能控制
位置控制
模式控制
Effort 限制 配置
其他参数配置
2.3 Joint 类
2.3.1 关节数据(返回单个值)
位置数据
状态监控
Effort 限制 数据
固件信息
2.3.2 关节控制(单个值)
使能控制
位置控制
模式控制
Effort 限制 配置
其他参数配置
2.4 IController 接口
2.4.1 上下文管理
2.4.2 实时数据获取
2.4.3 实时数据设置
2.5 数组形状说明
2.6 操作模式说明
3. 触觉感知手套
3.1 核心类
TactileHandedness
TactileFrame
TactileGlove
3.2 设备连接
自动发现
指定设备
Context Manager
连接管理方法
3.3 数据读取
阻塞读取
流式回调
3.4 配置与诊断
3.5 异常处理
3.6 完整示例
预期输出示例
3.7 与 Wuji Hand 联合使用
3.8 协议参考
数据帧格式
CRC16-CCITT
帧同步算法
参考实现
4. logging 模块
4.1 Level 枚举
4.2 函数
set_log_path
set_log_level
set_log_to_file
set_log_to_console
flush