跳转到内容
English

API 参考

SDK 2.x 使用三位 product_code 识别产品。21 DOF 产品包括 UB1、UD1、UF1~UF3、UT1、UT2 和 UV1~UV6;16 DOF 产品包括 PB1、PT1;13 DOF 产品包括 DB1、DT1。JointLayout 报告当前设备的逻辑关节数量和布局。当前 SDK 对上述 21 DOF 产品开放其硬件具备的功能域;16 DOF 和 13 DOF 产品当前仅提供设备识别与 JointLayout。尚未验证的能力返回 NotVerified,产品不包含对应硬件时返回 HardwareMissing。详见产品代号与兼容型号分类。

UV1~UV6 的整手运动、状态和运维能力通过本 SDK 提供。独立指尖视触觉数据由专用 SDK 通过 USB 或 serial 通道提供,不经过本 SDK 的 Modbus/CANFD 通道,也不属于 hand.touch 快照。对于带主链路指腹/手掌阵列的 UV1~UV4,设备只读探测确认压阻阵列触觉模组或高密矩阵触觉模组后,hand.touch 仅公开 5 个指腹和 1 个手掌模组。两条通道没有原子同步保证,应用需要分别管理生命周期和时间对齐。

按角色阅读:

  • 应用接入者:先看第 2 章连接流程、第 3 章 product_code,再看第 8 章错误、超时和重试。> - 运动控制开发者:重点阅读 4.1 Motion、4.2 State 和第 7 章等待与运动冲突。
  • 触觉与数据开发者:重点阅读 4.3 Touch、5.4/5.6 触觉方法和 6.3 触觉数据结构。
  • 诊断与维护人员:重点阅读 4.4 Health、4.6 Config、4.7 Calibration 和 4.8 Maintenance。
  • Python/C++/C 集成者:先看第 5 章公共方法对照,再看第 9 章单位与时间戳、第 10 章语言差异。

Manager 为设备管理器,负责设备发现与连接生命周期管理;Hand 为单只灵巧手的设备句柄,提供设备信息与各功能模块对象:

Manager (设备发现与连接管理)
└── Hand (单手设备句柄)
├── 设备信息与元数据
│ ├── DeviceInfo 整手、电机与触觉模组基本信息
│ ├── FirmwareInfo 主控、电机与触觉固件版本
│ └── JointLayout 关节映射与自由度拓扑
└── 功能模块对象
├── Motion 轨迹运动、实时流控、零力矩与软件停止
├── State 电机反馈快照与状态订阅
├── Touch 触觉区域能力、点阵触觉与力/力矩触觉采样
├── Health 系统诊断、电机健康与运行健康状态
├── ExperimentalCollision 实验性软件碰撞检测与响应
├── Config 设备参数与运行配置
├── Calibration 关节零位校准与标定
└── Maintenance 设备重启与固件升级

上图只表示功能归属,不表示具体属性或方法写法。实际名称和参数见第 2 至 5 章。

Manager 与 Hand 构成 SDK 2.x 的核心入口对象,负责设备发现、会话建立与句柄生命周期管理。

应用需首先创建 Manager 实例,负责设备发现、连接管理与句柄生命周期:

  • 设备发现与连接:
    • list_ports():列出本机可见的通信端口或适配器,供 UI、CLI 和手动选择端口使用;它不访问设备,也不返回 Hand。
    • discover(scan_all=False):扫描可用总线设备(包含端口名、传输协议与 slave_id);默认找到首个可用设备即止,设置 scan_all=True 扫描全量设备。
    • connect_auto():发现并连接一只匹配设备,适合 quickstart 和单手默认场景;可传入 port、slave_id、protocol 或 model 缩小范围。
    • connect(detected, model=None):连接一个已知 DetectedDevice,适合应用先 discover() 展示设备列表,再由用户选择目标设备。
    • connect_all(devices):批量连接多个已知设备,返回 list[Hand];适合同一总线多手或多个 Modbus 端口的启动流程。
  • 总线共享与生命周期规则:
    • 端口独占与复用:同一物理总线端口(如 RS485 / CANFD)仅打开一次 Transport 连接,供挂载于该总线上的多只 Hand(不同 slave_id)共享通信。
    • CANFD 会话限制:当前进程同一时刻只允许一个 CANFD Transport session;同一 CANFD 总线上的多个 slave_id 共享该 session。连接另一 CANFD 适配器或重新执行 CANFD discovery 前,必须先关闭现有 CANFD session;CANFD discovery 运行期间也不能建立 session。Modbus 不受此限制。
    • 句柄独立关闭:关闭单个 Hand 仅释放该设备的业务句柄与引用;最后一只 Hand 关闭后,SDK 才真正释放端口总线连接。
    • 全局释放管理:关闭 Manager 时,将原子化关闭其管理的所有 Hand 句柄与底层物理总线连接。
    • 异常失效机制:发生断线与重连恢复后,旧 Hand 句柄、数据订阅与内部缓存自动失效,应用需重新获取句柄。

Hand 是连接建立后单只物理灵巧手的核心控制句柄,聚合设备元数据只读快照与功能控制子模块:

Hand / revo3::Hand
├── device_info / device_info() --> 设备基本信息 (型号/SN/左右手类型/硬件版本)
├── firmware_info / firmware_info() --> 固件版本 (主控/驱动板/触觉)
├── joint_layout / joint_layout() --> 关节映射布局 (13/16/21 DOF)
├── slave_id / slave_id() --> 设备 Modbus 从机 ID
├── motion / motion() --> 运动控制 API (move_to, move_joint, 示教)
├── state / state() --> 状态读取 API (snapshot 状态快照)
├── touch / touch() --> 触觉传感器 API (布局、数据流与维护)
├── health / health() --> 健康与安全诊断 API
├── experimental_collision / experimental_collision() --> 实验性碰撞检测 API
├── config / config() --> 设备参数配置 API
├── calibration / calibration() --> 关节零位与标定 API
├── maintenance / maintenance() --> 固件升级与 DFU 维护 API
└── close() --> 关闭句柄并释放连接资源
  • 资源释放责任:支持调用 close() 手动关闭当前句柄;同一串口上的多设备共享总线连接,关闭单只 Hand 不会影响同端口上的其他设备。

Revo3 SDK 在 Python 和 C++ 中均提供一致的基础调用范式:

import asyncio
from bc_revo3_sdk import main_mod as sdk
async def main():
manager = sdk.Manager()
hand = None
try:
hand = await manager.connect_auto()
# 1. 读取设备元数据与布局
info = hand.device_info
layout = hand.joint_layout
if layout is None:
raise RuntimeError("Joint layout is unavailable")
print(f"Hand Model: {info.model}, SN: {info.serial_number}")
# 2. 从当前状态快照构造运动目标
state = await hand.state.snapshot()
target = list(state.positions_deg)
target[0] = 45.0 # 调整 J0 关节目标角度 (degree)
# 3. 发送一条运动指令并等待到位
handle = await hand.motion.move_to(target, duration=0.8)
result = await handle.wait(timeout=2.0)
print(f"Motion result: {result}")
finally:
if hand is not None:
await hand.close()
await manager.close()
asyncio.run(main())
#include <iostream>
#include <revo3/revo3.hpp>
#include <stdexcept>
#include <vector>
using namespace std::chrono_literals;
int main() {
revo3::Manager manager;
auto hand = manager.connect_auto();
// 1. 读取设备元数据
const auto info = hand.device_info();
std::cout << "Hand Model: " << static_cast<int>(info.model)
<< ", SN: " << info.serial_number << "\n";
// 2. 从当前状态快照构造安全运动目标
auto state = hand.state().snapshot();
const auto layout = hand.joint_layout();
if (!layout) {
throw std::runtime_error("Joint layout is unavailable");
}
std::vector<float> target(
state.motors.positions_deg,
state.motors.positions_deg + layout->joint_count);
target[0] = 45.0f; // 调整 J0 关节目标角度 (degree)
// 3. 发送运动指令并等待到位
auto handle = hand.motion().move_to(target, 800ms);
const auto result = handle.wait(2s);
std::cout << "Motion result status: " << static_cast<int>(result) << "\n";
// 4. 关闭句柄释放连接
hand.close();
return 0;
}

设备信息与元数据按生命周期分为设备发现与设备连接两个阶段:

  • 设备发现阶段:由 Manager.discover() 扫描返回 DetectedDevice,包含通信端点与基础硬件描述,作为连接输入;
  • 设备连接阶段:通过 connect() 或 connect_auto() 建立连接后,通过 Hand 句柄访问。
DetectedDevice / revo3::DetectedDevice
├── protocol_type --> 通信协议类型 (ModbusRTU / CANFD)
├── port_name --> 设备串口或端口名称 (如 /dev/ttyUSB0, can0)
├── slave_id --> 设备 Modbus 从机 ID
├── nominal_baudrate_bps --> RS485 波特率或 CAN 仲裁段波特率 (如 115200, 1000000)
├── data_baudrate_bps --> CANFD 数据段波特率 (如 5000000);Modbus 下固定为 0
├── model --> 识别到的设备型号 (如 UltraTouch)
├── hand_side --> 识别到的左右手类型 (Left / Right)
├── serial_number --> 设备唯一序列号 (如 BCUTL40124000001)
├── firmware_version --> 主控固件版本号
└── hardware_revision --> 硬件修订版本号
DeviceInfo
├── product_code --> 三位产品代号 (如 UT1)
├── model --> SDK 2.x 兼容型号分类 (如 UltraTouch)
├── serial_number --> 设备唯一序列号 (如 BCUTL40124000001)
├── hand_side --> 左右手类型 (Left / Right)
├── hardware_revision --> 硬件修订版本标识
├── motor_serial_numbers --> 电机物理 SN 列表
└── touch_serial_numbers --> 触觉模组物理 SN 列表

DeviceInfo 描述当前连接设备的基本信息与硬件元数据快照,用于设备识别、日志追溯和兼容性诊断。该快照在连接建立时自动获取并缓存;仅在产线测试、售后维护或显式强制同步时调用 await hand.refresh_device_info() 主动刷新。

若设备序列号或硬件版本缺失,hand.device_info 返回 None(不使用空字符串伪造信息)。电机与触觉部件 SN 若尚未读取或当前型号不支持,对应字段呈现为空列表 [],不影响 DeviceInfo 本身的返回。

  • product_code:三位产品代号(如 UT1),由序列号中的四位型号前缀去除手向 L / R 后得到;旧版或未知 SN 无法可靠归一化时为 None。
  • model:SDK 2.x 兼容型号分类(类型为 Revo3Model),用于连接覆盖和自由度布局解析,不作为精确产品身份。
  • serial_number:设备唯一序列号(如 "BCUTL40124000001"),用于具体设备识别、多手日志追溯与资产管理。
  • hand_side:左右手类型(Left / Right),用于运动学镜像解算、位姿变换与控制映射。
  • hardware_revision:硬件修订版本标识,用于生产追溯和兼容性诊断。应用应通过具体对象 API 和结构化错误判断运行时可用性。
  • motor_serial_numbers:按逻辑关节顺序排列的已知电机物理 SN 列表。
  • touch_serial_numbers:已知触觉模组物理 SN 列表(无触觉型号或不支持 SN 读取时为空列表)。

当前设备固件未存储独立的产品型号字段,SDK 默认根据序列号前缀自动推断 model:

  • 常规连接:DetectedDevice.model 已自动识别型号,正常调用 connect(detected) 或 connect_auto() 即可。
  • 显式型号覆盖:若旧固件序列号缺失、不正确或扫描信息不完整,可在连接时显式指定 model。显式覆盖优先于序列号识别,仅作用于当前连接上下文,不会写入设备固件。
# 示例:Python 显式指定型号建立连接
hand = await manager.connect_auto(model=sdk.Revo3Model.UltraTouch)
// 示例:C++ 显式指定型号建立连接
auto devices = manager.discover();
auto detected = devices.front();
detected.model = REVO3_MODEL_ULTRA_TOUCH;
auto hand = manager.connect(detected);

触觉模组的底层协议解析状态仅用于 SDK 内部选择解析器并生成 TouchLayout,不包含在 DeviceInfo 中。应用应通过 hand.touch.layout 判断触觉布局和触觉数据形态。

# 示例:读取设备基本信息与型号
info = hand.device_info
if info is not None:
print(f"SN: {info.serial_number}, Model: {info.model}, Hand side: {info.hand_side}")
print(f"Motor SN count: {len(info.motor_serial_numbers)}, Touch SN count: {len(info.touch_serial_numbers)}")
FirmwareInfo
├── controller_firmware_version
├── motor_firmware_versions
└── touch_firmware_versions

固件信息与设备基本信息及硬件元数据分开,在升级或重新连接后必须重新读取。主控固件属于设备本体,但它仍是软件版本,因此保留在 FirmwareInfo。各字段含义如下:

  • controller_firmware_version:主控板固件版本,决定系统级协议、总线调度与主控通信能力。
  • motor_firmware_versions:当前已知的各电机驱动板固件版本,按逻辑关节顺序排列。
  • touch_firmware_versions:当前已知的触觉模组固件版本;非 Touch SKU 该列表为空。

空列表表示当前快照中没有已知版本,可能是设备没有对应模组,也可能是尚未读取到版本;当前 API 不提供固件清单完整性字段。需要刷新组件版本时调用 await hand.refresh_firmware_info()。

# 示例:读取主控与电机/触觉板固件版本列表
fw = hand.firmware_info
print(f"Controller FW: {fw.controller_firmware_version}, Motor FW count: {len(fw.motor_firmware_versions)}")

Python 和 C++ 的 hand.joint_layout 用于确认当前布局和数组长度。该属性包含 layout_id、version 和 joint_count:

JointLayout
├── layout_id --> 运动学关节拓扑标识 (如 Revo3Ultra21 / Revo3Pro16 / Revo3Basic13,多款触觉型号共享)
├── version --> 布局协议规范的版本号 (当前为 1)
└── joint_count --> 逻辑关节总数 (21 / 16 / 13)

21 DOF Ultra 布局使用下面的固定逻辑顺序。读取 Pro 和 Basic 元数据的工具应根据 JointLayout.joint_count 解释 16/13 DOF 布局,不能按 21 个有效关节处理;这不表示 Motion、State、Touch、Health、Config、Calibration 或 Maintenance 已对这些型号开放。Ultra 运行时的位置和速度限制从 DeviceConfig 读取;控制器通道由 SDK 在协议层完成映射,不进入 Python/C++ API。

Python 在布局尚不可用时返回 None;C++ 返回 std::optional<JointLayout>,调用者应先检查是否有值。两种语言中的 layout_id 均为稳定字符串 schema ID,不使用关节数量代替布局标识。

JointLayout 是由当前连接上下文中已识别的产品型号派生的只读元数据。SDK 不提供 set_joint_layout() 或关节布局 override;旧固件序列号缺失、不正确或扫描信息不完整时,应在连接阶段通过 model 参数显式修正型号。该修正仅作用于当前连接上下文,不写入设备固件,也不会绕过对应型号的 runtime 能力检查。

# 示例:获取关节布局 ID 与关节数
layout = hand.joint_layout
print(f"Layout: {layout.layout_id}, Joint Count: {layout.joint_count}")

当前 21 DOF 逻辑分组为:

分组 逻辑索引 关节数
Pinky 0..3 4
Ring 4..7 4
Middle 8..11 4
Index 12..15 4
Thumb 16..20 5

Thumb 公共逻辑编号顺序为 J16、J17、J18、J19、J20,分别表示 CMC Flex(根部屈伸)、MCP、IP、CMC Abd 和 CMC Rotation。协议适配层处理底层顺序,应用按 J 编号传参。

三位 product_code 是不区分左右手的精确产品身份,由序列号中的四位型号前缀去除手向 L / R 后得到。统一规格型号为 BC-Revo-3。下表列出产品身份和硬件配置;产品是否已上市不等于对应 SDK 功能可用。

产品代号 产品线名称 DoF 功能与触觉配置 SN 前缀(左 / 右)
UB1 BrainCo Revo3(Basic) UBL1/UBR1 21 标准型,无触觉(V0W0) UBL1 / UBR1
UD1 BrainCo Revo3(Basic) UDL1/UDR1 21 展示手套装,无触觉 UDL1 / UDR1
UF1 BrainCo Revo3(3DForce) UFL1/UFR1 21 指尖三维力/力矩触觉模组,5 个指尖(V0W3) UFL1 / UFR1
UF2 BrainCo Revo3(3DForce) UFL2/UFR2 21 指尖三维力/力矩触觉模组 + 指腹/手掌压阻阵列触觉模组(V1W3) UFL2 / UFR2
UF3 BrainCo Revo3(3DForce) UFL3/UFR3 21 指尖三维力/阵列触觉模组 + 指腹/手掌压阻阵列触觉模组(V1W4) UFL3 / UFR3
UT1 BrainCo Revo3(Touch) UTL1/UTR1 21 全手压阻阵列触觉模组(V1W1) UTL1 / UTR1
UT2 BrainCo Revo3(Touch) UTL2/UTR2 21 全手高密矩阵触觉模组(V2W2) UTL2 / UTR2
UV1 BrainCo Revo3(Vision) UVL1/UVR1 21 指腹/手掌压阻阵列触觉模组 + 独立指尖视触觉模组方案 1(V1W5) UVL1 / UVR1
UV2 BrainCo Revo3(Vision) UVL2/UVR2 21 指腹/手掌压阻阵列触觉模组 + 独立指尖视触觉模组方案 2(V1W6) UVL2 / UVR2
UV3 BrainCo Revo3(Vision) UVL3/UVR3 21 指腹/手掌高密矩阵触觉模组 + 独立指尖视触觉模组方案 1(V2W5) UVL3 / UVR3
UV4 BrainCo Revo3(Vision) UVL4/UVR4 21 指腹/手掌高密矩阵触觉模组 + 独立指尖视触觉模组方案 2(V2W6) UVL4 / UVR4
UV5 BrainCo Revo3(Vision) UVL5/UVR5 21 无主链路阵列;独立指尖视触觉模组方案 2(V0W6) UVL5 / UVR5
UV6 BrainCo Revo3(Vision) UVL6/UVR6 21 无主链路阵列;独立指尖视触觉模组方案 1(V0W5) UVL6 / UVR6
PB1 BrainCo Revo3(Basic) PBL1/PBR1 16 标准型,无触觉 PBL1 / PBR1
PT1 BrainCo Revo3(Touch) PTL1/PTR1 16 压阻阵列触觉模组 PTL1 / PTR1
DB1 BrainCo Revo3(Basic) DBL1/DBR1 13 标准型,无触觉 DBL1 / DBR1
DT1 BrainCo Revo3(Touch) DTL1/DTR1 13 压阻阵列触觉模组 DTL1 / DTR1

当前 SDK 支持范围:UB1、UD1 的 21 DOF 运动、状态、配置和维护等整手功能可用,但没有触觉硬件;UF1~UF3、UT1、UT2 在已识别且受支持的触觉布局上还可使用 hand.touch。UV1~UV4 的整手功能和主链路指腹/手掌触觉可用,独立视触觉指尖不属于本 SDK 的 hand.touch;UV5、UV6 没有主链路触觉阵列,独立指尖使用专用 SDK。PB1、PT1、DB1、DT1 当前仅支持设备识别与 JointLayout;其他功能返回 NotVerified,无相应硬件的功能返回 HardwareMissing。触觉能力还取决于连接时识别到的具体布局,不能仅凭产品代号推断每个模组均可读取。

Revo3Model 是用于旧设备连接覆盖、关节布局和 ABI 兼容的公开枚举,不是产品名称,也不能替代 product_code。兼容分类映射:UB1、UD1 → Ultra;UF1~UF3、UT1、UT2 → UltraTouch;UV1~UV6 → UltraVisionTouch;PB1 → Pro;PT1 → ProTouch;DB1 → Basic;DT1 → BasicTouch。

SDK 将从 SN 识别出的已知三位产品代号作为硬件拓扑和触觉配置的权威依据,不使用可能未同步的设备元数据覆盖它。旧版 SN 或未知变体无法识别三位产品代号时,继续使用只读设备元数据探测。

Python 公开整数枚举提供只读 int_value 属性,用于取得与 C ABI/协议值一致的整数表示;业务逻辑仍应优先比较枚举成员,不直接写死整数。

ProtocolType 用于扫描和连接参数。Auto 只表示由 SDK 选择已支持的传输,不是独立的设备协议。

枚举项 数值 描述说明
Auto 0 自动探测 Modbus RTU 或 CANFD
Modbus 1 通过 RS485 使用 Modbus RTU
CanFd 3 使用 CANFD

Python 连接 API 使用该强类型枚举。C++ DiscoveryOptions.modbus_baudrate 当前使用 bps 整数值。

枚举项 数值 线路速率
Baud1Mbps 1 1,000,000 bps
Baud2Mbps 2 2,000,000 bps
Baud3Mbps 3 3,000,000 bps
Baud5Mbps 5 5,000,000 bps

Python 连接 API 使用该强类型枚举;C++ DiscoveryOptions.canfd_data_baudrate 当前使用 bps 整数值。该枚举表示 CANFD 数据域速率;仲裁域速率由适配器和传输实现确定,不通过此枚举配置。

枚举项 数值 数据域速率
Baud1Mbps 1 1,000,000 bps
Baud2Mbps 2 2,000,000 bps
Baud4Mbps 4 4,000,000 bps
Baud5Mbps 5 5,000,000 bps

该枚举用于 Python init_logging()、C ABI revo3_init_logging() 和 C++ revo3::init_logging()。

枚举项 数值 描述说明
Error 0 仅错误日志
Warn 1 警告和错误日志
Info 2 常规运行信息,默认级别
Debug 3 调试信息
Trace 4 最详细的跟踪信息

Python 类型名为 FirmwareTarget,C++ 类型名为 FirmwareTarget。

Python 枚举项 C++ 枚举项 数值 描述说明
MainFirmware MainFirmware 0 主控制器固件
Image Image 1 设备镜像目标;仅在对应固件明确支持时可用
MotorFirmware MotorFirmware 2 电机模组固件

枚举成员只标识升级目标,不代表当前设备、固件或传输支持该目标。非主控制器目标还要求固件支持目标寄存器的写入与回读确认;确认失败时升级操作失败,不得自动改写为其他目标。

Hand 的能力按用户职责组织如下:

职责分组 API 章节 主要用途
运动控制 4.1 Motion 运动控制 API 轨迹运动、关节/手指/拇指控制、实时 Servo、拖拽、示教与回放
状态读取 4.2 State 状态读取 API 读取关节位置、速度、电流、故障码和状态订阅
触觉数据 4.3 Touch 触觉数据 API 触觉布局、快照、订阅、模组配置、校准和维护
健康与安全 4.4 Health 系统诊断与安全状态 API 系统状态、电源/温度、电机诊断、安全状态和故障清除
碰撞保护 4.5 ExperimentalCollision 实验性碰撞保护 API 软件碰撞检测配置、锁存状态读取和复位
运行配置 4.6 Config 配置 API 蜂鸣器、振动、触屏、广播 ID、保护电流和运行参数
标定 4.7 Calibration 标定 API 关节零点、软限位、力控相关标定流程
设备维护 4.8 Maintenance 维护 API 重启、固件升级、升级中止、状态恢复和恢复出厂设置

Motion 按职责分为:

  • 目标轨迹运动:move_to()、move_joint()、move_finger()、flex_finger()、move_thumb()。
  • 实时流式控制:open_servo() 与 ServoSession.send_*()。
  • 托管拖拽控制:start_servo_drag()、update_servo_drag()、stop_servo_drag()、cancel_servo_drag()。
  • 示教与回放:teach_joint()、teach_hand()、replay_joint()、replay_hand()。

4.1.1 轨迹运动 API:move_to、move_joint、move_finger 与 move_thumb

Section titled “4.1.1 轨迹运动 API:move_to、move_joint、move_finger 与 move_thumb”

注意: 底层轨迹与下发机制:move_to()、move_joint()、move_finger() 和 move_thumb() 在 SDK 底层均基于五次平滑多项式 (Quintic Polynomial Trajectory) 进行连续轨迹插值,确保起点与终点的速度和加速度连续光滑。插值过程中,SDK 内部以高频插值周期将当前位置与速度序列转化为 五项 MIT 混合控制指令 (Kp, Kd, Pos, Vel, Feedforward Current) 实时下发至灵巧手驱动器。公共 API 的反馈与前馈量保持命名为 current / current_ma;设备不提供已标定的关节力矩反馈,因此不把电流错误标注为 torque。

整手按指定时长运动使用 move_to():

# 示例:整手按指定时长运动至目标姿态
target_positions = [0.0] * 21 # 21 个关节的目标位置,单位为 degree
handle = await hand.motion.move_to(target_positions, duration=2.0)
await handle.wait(timeout=3.0)
// 示例:C++ 整手按指定时长运动
std::vector<float> target_positions(21, 0.0f);
auto handle = hand.motion().move_to(target_positions, std::chrono::seconds(2));
handle.wait(std::chrono::seconds(3));

单关节按指定时长运动使用 move_joint():

handle = await hand.motion.move_joint(joint_index=0, target_position=15.0, duration=1.0)

单手指按指定时长运动使用 move_finger() 和 flex_finger():

# move_finger: 传入 4 个关节目标位置 [Abd, MCP, PIP, DIP]
handle = await hand.motion.move_finger(finger_index=1, target_positions=[0.0, 30.0, 45.0, 20.0], duration=1.0)
# flex_finger: 简易弯曲控制
handle = await hand.motion.flex_finger(finger_index=1, flexion_position=60.0, duration=1.0)

拇指按指定时长运动使用 move_thumb():

# move_thumb: pass five joint targets in [J16, J17, J18, J19, J20] order
handle = await hand.motion.move_thumb(target_positions=[10.0, 20.0, 30.0, 0.0, 40.0], duration=1.0)

move_to()、move_joint()、move_finger() 与 move_thumb() 的动作对应表:

方法名称 目标数组长度 (21-DOF 手型) 对应含义
move_to() 21 控制全手 21 个关节的目标位置
move_joint() 1 控制索引为 joint_index (0..20) 的单个关节
move_finger() 4 finger_index 为 1=Index, 2=Middle, 3=Ring, 4=Pinky;21-DOF 手型上传入 4 个角度,按 Abd, MCP, PIP, DIP 顺序解算
flex_finger() 1 与 move_finger() 相同的 finger_index;flexion_position 作用于 MCP、PIP、DIP 关节,Abd 关节维持当前反馈位置
move_thumb() 5 21-DOF 手型上传入 5 个角度,按 J16、J17、J18、J19、J20 顺序解算

move_joint() 支持与 move_to() 相同的 duration/speed、统一 kp/kd 和 dt 参数。move_finger()、flex_finger() 和 move_thumb() 均按时长控制,并支持可选的统一或逐关节 kp/kd。move_finger() 为全姿态控制(包含侧摆 Abd);flex_finger() 为语义弯曲控制,适合快速上手、抓握动作或 GUI 控制。四者均返回 OperationHandle,低频重规划时可以互相替换或替换 move_to()(旧句柄变为 Preempted);四者均与 open_servo() 冲突。

调用 hand.motion.open_servo() 可建立 ServoSession。调用者可通过 send_position()、send_velocity()、send_current()、send_impedance() 或 send_mit() 发送目标。

# 示例:打开高频实时流式控制会话
session = hand.motion.open_servo()
try:
for _ in range(100):
await session.send_position([0.0] * 21)
await asyncio.sleep(0.01)
finally:
session.close()
// 示例:C++ 实时流式控制会话
auto session = hand.motion().open_servo();
std::vector<float> targets(21, 0.0f);
for (int i = 0; i < 100; ++i) {
session.send_position(targets);
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
session.close();

4.1.3 托管拖拽控制 (start_servo_drag)

Section titled “4.1.3 托管拖拽控制 (start_servo_drag)”

对于仅在目标变化时产生事件的控制源(如 GUI Slider),使用 Motion.start_servo_drag(joint_index, target_position) 启动拖拽,通过 update_servo_drag(joint_index, target_position) 传入最新目标。松开滑条时调用 stop_servo_drag(joint_index, final_position) 发送保持帧;主动取消或断线清理时调用 cancel_servo_drag(joint_index) 停止写控制帧。filter_mode 使用 ServoFilterMode,不接受无类型的整数模式值。

4.1.4 实时控制入口对比:open_servo 与 start_servo_drag

Section titled “4.1.4 实时控制入口对比:open_servo 与 start_servo_drag”

针对实时发包和连续运动场景,SDK 提供了两类不同层级的控制入口:

  • open_servo()(用户循环托管):打开一个 ServoSession,把高频实时控制权移交给调用方自建的循环。适合 VR 手套、遥操作、外部策略或强化学习(RL)按 5–20ms 周期自主发包。
  • start_servo_drag(...)(SDK 后台托管):在 SDK 内部启动一个单关节后台发包 Worker。适合 GUI 滑条拖动、鼠标滑动控制,调用方只需在目标变化时轻量调用 update_servo_drag(),SDK 自动按固定周期维持下发,并提供平滑滤波、限速与碰撞保护。

核心特性对比表:

对比维度 open_servo()(流式会话) start_servo_drag()(托管拖拽)
一句话定位 “把实时控制权交给用户循环” “SDK 帮你托管一个单关节拖动循环”
适用场景 遥操作、VR 手套、算法/RL 每 5-20ms 连续更新多关节 GUI Slider 拖动、面板交互、鼠标滑动控制
控制权托管 用户循环(用户负责外层 loop 和发包频率) SDK 后台(SDK Worker 自动按固定周期连续发包)
控制粒度 整手命令帧,数组长度必须等于当前 joint_count 单关节 (Joint)
方法列表 send_position(), send_velocity(), send_mit() 等 start_servo_drag(), update_servo_drag(), stop_servo_drag()
生命周期管理 需显式 session.close() 释放,支持 command_timeout_ms 自动超时 Expire 释放滑条用 stop_servo_drag()(发送保持帧);收尾或中断用 cancel_servo_drag()
高级保护 需算法层控制轨迹平滑 包含滤波、速度限制、碰撞保护与空闲保持 (Idle Hold)

1. open_servo() 会话说明: 调用 hand.motion.open_servo() 会打开一个 ServoSession。用户按自己的控制流程调用 send_position()、send_velocity()、send_current()、send_impedance() 或 send_mit() 提供新目标。command_timeout_ms 表示相邻两次命令允许的最长间隔;超时后 ServoSession.state 变为 Expired,SDK 释放软件控制权,并拒绝该会话继续发送命令。

当前所有 ServoSession.send_*() 方法都接收完整整手命令帧,各数组长度必须等于当前设备的 joint_count。调用者可以只改变目标数组中的部分关节值,但仍须为其他关节提供明确目标;SDK 不公开隐式沿用上一帧或自动读取反馈值的单关节、手指、拇指流控方法。

2. start_servo_drag() 拖拽说明: 对于仅在目标变化时产生事件的控制源(如 GUI Slider),使用 Motion.start_servo_drag(joint_index, target_position) 启动拖拽,通过 update_servo_drag(joint_index, target_position) 传入最新目标。松开滑条时调用 stop_servo_drag(joint_index, final_position) 发送保持帧;主动取消或断线清理时调用 cancel_servo_drag(joint_index) 停止写控制帧。C ABI 对应 revo3_device_*_servo_drag。

teach_joint() 和 teach_hand() 在指定时间内采集关节反馈位置,返回可用于后续回放的轨迹数组。replay_joint() 和 replay_hand() 按给定 dt、kp 和 kd 回放轨迹。它们属于 Motion 域 API,执行时会占用运动控制权,并与 move_to()、局部轨迹运动、open_servo() 和 拖拽控制互斥。

joint_positions = await hand.motion.teach_joint(
joint_index=0,
duration=3.0,
dt=0.01,
)
await hand.motion.replay_joint(
joint_index=0,
positions=joint_positions,
dt=0.01,
kp=1.0,
kd=0.1,
)
hand_trajectory = await hand.motion.teach_hand(duration=3.0, dt=0.01)
await hand.motion.replay_hand(hand_trajectory, dt=0.01, kp=1.0, kd=0.1)

HandState 包含每个电机的 operating_states、position、velocity 和 current。高频状态读取覆盖输入寄存器 2000..2110,不读取低频诊断区。位置单位为 deg,速度单位为 rpm,电流单位为 mA。逐电机原始状态码、系统状态和全局错误码从 HealthSnapshot 读取。读取失败时调用返回 SdkError。

State 还包含一个接收 timestamp。Linux SocketCAN 使用最后一个状态响应的 SO_TIMESTAMPNS 内核软件时间,其他 CANFD 和 Modbus 路径记录 SDK 完成读取的时间。只有 clock 相同的 timestamp 才能比较。它不是固件采样时间,也不能用于跨设备同步。

# 示例:读取电机控制反馈状态快照或开启 50Hz 异步订阅
snapshot = await hand.state.snapshot()
print(f"Current positions (deg): {snapshot.positions_deg}")
# 异步订阅
sub = hand.state.subscribe(period=0.02)
try:
frame = await sub.next()
finally:
sub.close()

本节同时包含 SDK 使用说明和兼容性实现说明。集成 SDK 时,优先阅读“应用使用说明”部分;其中的字段、单位、能力矩阵、错误行为和调用约束是应用可以依赖的公开行为。带有“实现参考”标记的内容用于固件联调、兼容性排查和问题定位,不要求应用直接依赖寄存器地址或 SDK 的内部探测顺序。

4.3.1 应用使用说明:布局、数据和能力

Section titled “4.3.1 应用使用说明:布局、数据和能力”

推荐的接入流程如下:

  1. 建立 Hand 连接并读取 hand.touch.layout。
  2. 以设备的 product_code 判断产品能力,再根据模块的 signals 和 point_count 判断当前连接实际返回的数据。
  3. 使用 snapshot() 读取一次快照,或使用 subscribe() 连续读取。
  4. 按公开 module_id 查找模块,不要用数组位置替代模块 ID。
  5. 只有在布局无法识别且已确认实物配置时,才使用 set_layout() 设置当前会话布局。

产品主链路触觉能力如下:

产品 主链路阵列 指尖力/力矩 点阵数据 独立视触觉
UF1 — 有 48 点或无点阵 —
UF2、UF3 有 有 按布局 —
UT1、UT2 有 — 有 —
UV1~UV4 有 — 按布局 有
UV5、UV6 — — — 有

SDK 使用 TouchLayout 描述当前设备的触觉能力,使用 TouchFrame 返回采样数据。应用只需要关注布局中的模块、信号和点数,不需要了解设备内部的寄存器映射。

触觉能力:

  • 点阵数据:触觉模块按点返回数据,实际点数以 point_count 为准。
  • 区域合力数据:部分设备在兼容读取模式下提供区域合力,写入 regional_forces_mn;新应用不应假设所有设备都支持。
  • 指尖三维力/力矩数据:部分模块提供 force3d、torque2d 和 resultant_force_mn,部分布局同时提供 48 点数据。
  • 组合触觉数据:同一设备可以同时返回点阵、区域合力和指尖力/力矩数据,具体以 signals 和 sample_state 为准。
  • 独立视触觉数据:通过专用 SDK 和独立通道读取,不属于 hand.touch。

TouchLayout 包含 regions 和 modules。每个模块提供 module_id、region、region_index、signals 和 point_count。layout_id 是用于热力图、仿真和兼容性排查的可选 schema 标识;应用不应仅凭它判断产品能力。应用应按 module_id 查找模块;组合布局中模块数组位置不一定等于模块 ID。

TouchFrame 包含接收时间戳、序列号和 TouchModuleData 数组。模块数据可能包含 points、force3d、torque2d、resultant_force_mn 和 sample_state;具体字段由模块的 signals 和当前读取模式决定。公开力值统一使用 mN,力矩使用 Nm。

module_id 是当前产品布局中的稳定公开标识,不表示数组下标。纯阵列布局通常使用连续编号;组合布局使用稀疏编号:0 为手掌,1/3/5/7/9 为拇指至小指指尖,2/4/6/8/10 为拇指至小指指腹。应用应先按 module_id 查找模块,再读取其 region、signals 和数据字段。

应用判断数据是否可用时应优先检查 sample_state == Valid,再检查具体字段是否为 None。Disabled 表示模块被关闭,Unavailable 表示当前能力或数据不可用,WarmingUp 表示指尖模组尚未完成预热,SensorFault 表示传感器报告异常;NotSampled 和 ReadFailed 是保留状态,通常不会出现在成功的完整快照中。

触觉操作按当前布局路由。不支持的操作返回 UnsupportedCapability,不会向设备发送命令。 常见处理方式如下:

情况 应用处理
产品不提供该触觉能力 根据 product_code 跳过对应 UI 或功能入口
当前布局未确认 重新读取设备信息和 hand.touch.layout;不要猜测布局
操作不受当前模组支持 捕获 UnsupportedCapability,不要自动改发其他触觉命令
单次读取通信失败 按第 8 章的 retryable 和 operation_effect 判断是否重试;不要用零值补齐失败数据

snapshot() 适合单次读取,subscribe() 适合连续读取;set_layout() 只在布局无法自动确认且已确认实物配置时使用,并且只影响当前连接会话。

本 API 文档不展开寄存器地址、Modbus 功能码或 SDK 内部探测顺序。应用只需要依赖前文定义的布局、数据结构、能力判断和错误行为。需要进行固件联调、寄存器排查或兼容性分析时,请参考对应的 Revo3 固件协议文档和内部兼容性排查记录。

SDK 的公共行为包括:布局无法确认时不猜测;不支持的操作返回 UnsupportedCapability;显式 set_layout() 只影响当前连接会话,不写入设备;设备重连后需要重新确认布局。

4.4 Health 系统诊断与安全状态 API

Section titled “4.4 Health 系统诊断与安全状态 API”

Health 按职责分为:

  • 系统健康快照:hand.health.snapshot(),读取逐电机原始状态码、系统状态、电流、电压、功率、温度和安全状态。
  • 电机诊断:motor_module_temperatures_c()、motor_online_mask(),读取逐模组温度和在线状态。
  • 故障处理:clear_motor_faults(),清除设备当前可清除的电机故障。

HealthSnapshot 是只读诊断信息,包含系统状态、全局错误码、电流、电压、功率、系统温度、21 个电机的原始状态码、故障电机数量和 safety_state。逐电机状态码来自输入寄存器 2120..2140,同时包含故障位和非故障状态位,与高频 HandState 分开采集。Bit 11 表示运行中,0x0800 不计入故障电机数量;0x0900 表示运行中且存在堵转。Bit 5 表示校准失败,Bit 9 表示校准中,这两个位适用于 0.4 及以上版本的电机固件;校准中不计入故障。逐电机模组温度和在线 bitmask 属于健康诊断查询,通过 hand.health.motor_module_temperatures_c() 和 hand.health.motor_online_mask() 读取。这些值当前不重复内嵌到 HealthSnapshot。完整保护状态及其 SafetyState 映射仍需固件语义和真机异常测试确认。

HealthSnapshot 和 SafetyState 均为通过普通 Modbus RTU / CANFD 链路采集、聚合的软件级诊断,不是功能安全状态,不得直接作为 ISO 13849 PL、IEC 61508 SIL、安全 PLC、Emergency Stop(紧急停止)回路或 STO 的判定证据。有明确错误时,SafetyState 返回 Faulted;信息不足时返回 Unknown。Software Stop(软件停止)和 Servo 超时仅提供软件层级的控制降级,不具备硬件级功能安全承诺。现场安全保护必须由系统风险评估确定的独立安全链路承担。

# 示例:读取系统只读健康诊断与安全置信度
health = await hand.health.snapshot()
print(f"Safety State: {health.safety_state}, Faulted Motors: {health.faulted_motor_count}")
print(f"Motor Fault Codes: {health.motor_fault_codes}")
temperatures = await hand.health.motor_module_temperatures_c()
online_mask = await hand.health.motor_online_mask()
motor_0_online = bool(online_mask & (1 << 0))

C++ 可通过 hand.health().motor_module_diagnostics() 一次读取逐电机模组温度数组和在线 bitmask。

4.5 ExperimentalCollision 实验性碰撞保护 API

Section titled “4.5 ExperimentalCollision 实验性碰撞保护 API”

碰撞检测保留为明确的实验性功能域,不属于 Health。Python 通过 hand.experimental_collision,C++ 通过 hand.experimental_collision(),C 通过 revo3_experimental_collision_* 使用。

该能力默认关闭,目前主要依赖 SDK 侧读取的位置误差、电流和缓存状态判断,并在命中阈值后执行软件停止、零力或保持当前反馈位置等策略。它不属于功能安全机制,不保证固定检测延迟,也不承诺无漏检或无误检;通信周期、缓存状态年龄、阈值和固件反馈及时性都会影响效果。不能用它替代急停、硬件限位或经过安全认证的控制器互锁。实验性 API 可能在后续 2.x minor 版本根据真机验证调整配置字段和判定语义。

config = sdk.ExperimentalCollisionConfig(
enable=True,
source=sdk.CollisionDetectionSource.HardwareOnly,
strategy=sdk.CollisionProtectionStrategy.SoftStop,
)
await hand.experimental_collision.configure(config)
active_joints = await hand.experimental_collision.active_joints()
await hand.experimental_collision.reset()
revo3::ExperimentalCollisionConfig config;
config.enabled = true;
hand.experimental_collision().configure(config);
const auto active_joints = hand.experimental_collision().active_joints();
hand.experimental_collision().reset();
枚举项 数值 描述说明
HardwareOnly 0 仅使用设备上报的硬件碰撞状态
SoftwareOnly 1 仅使用 SDK 侧位置误差和电流阈值判断
Hybrid 2 同时使用硬件状态和 SDK 侧阈值判断
枚举项 数值 描述说明
SoftStop 0 触发 SDK 软件停止
ZeroForce 1 下发零力控制命令
HoldActualPosition 2 以触发时的实际反馈位置作为保持目标

Python 和 C++ 调用方必须传入已定义的枚举成员。未知整数值属于 InvalidArgument,不得回退为默认检测源或保护策略。该输入约束不改变本节开头声明的实验性边界和非功能安全定位。

Config 按职责分为:

  • 配置读取:hand.config.snapshot(),读取设备配置快照。
  • SDK 运行参数:runtime_options、set_runtime_options(...),分别设置 State/Touch/Health 默认订阅间隔和 Servo 命令超时。
  • 设备开关:蜂鸣器、振动、触屏、广播 ID、上电自动标定和自动清除电机故障。
  • 保护参数:最大连续电流、全局保护电流、逐关节保护电流,以及位置/速度限制。

Config 管理设备配置快照和 SDK 运行参数。设备配置由固件持久化;运行参数只影响当前 SDK 进程。

  • hand.config.snapshot() 返回 DeviceConfig,包含 slave_id、RS485 波特率、设备开关、保护电流、位置与速度限制以及 persistence_scope。hand.config 还提供逐项命名的 setter,不提供会同时覆盖无关字段的批量更新。固件是配置持久化的唯一事实来源。

  • hand.config.runtime_options 返回 RuntimeOptions,包含 state_subscription_period_ms(默认 20)、touch_subscription_period_ms(默认 20)、health_subscription_period_ms(默认 1000)和 servo_command_timeout_ms(默认 100)。这些参数只更新当前进程,不写入设备。调用者也可以在创建订阅或流式控制会话时按场景指定参数;拉取间隔不是设备采样周期或固定频率承诺。 拇指 J16 为 CMC Flex(根部屈伸,0~75°),J17 为中间关节屈伸(−10~90°),J18 为末端关节屈伸(−20~90°),J20 为自转(0~105°)。SDK 的 MCP/IP 标签分别对应 J17/J18。运行时限位以 hand.config.snapshot() 的设备回读值为准。

  • 通信参数使用 Rs485Baudrate / CanFdBaudrate 枚举设置。C ABI 对应符号为 revo3_device_set_rs485_baudrate() / revo3_device_set_canfd_baudrate()。

  • SDK 不提供 SafetyConfig。固件已有的限制不在 SDK 中重复定义。

config = await hand.config.snapshot()
print(f"Slave ID: {config.slave_id}, Baudrate: {config.rs485_baudrate}")
runtime = hand.config.runtime_options

Calibration 按职责分为:

  • 关节标定:calibrate_joints(),执行关节标定流程。
  • 标定电流:set_current(current_ma),设置标定过程使用的电流。
  • 零位设置:set_current_position_as_zero(),将当前反馈位置记录为零位。

Calibration 提供关节标定、标定电流和零位操作。标定前自动校验 Motion 空闲;固件没有进度或取消结果,响应丢失时不自动重发。

await hand.calibration.calibrate_joints() # 关节标定
await hand.calibration.set_current(120.0)
await hand.calibration.set_current_position_as_zero()

Maintenance 按职责分为:

  • 设备重启:reboot(),返回可等待的 OperationHandle。
  • 固件升级:update_firmware(file_path, target=None, wait_secs=10),执行控制器、电机或触觉目标的 OTA/DFU。
  • 升级中止与恢复:abort_firmware_update()、reset_firmware_update_state()。
  • 恢复出厂:factory_reset(),恢复设备出厂配置。

Maintenance 提供恢复出厂、重启和固件升级。update_firmware(file_path, target=None, wait_secs=10) 是唯一的对象层升级入口;当前内部通过设备 DFU/OTA 流程完成。重启与固件更新返回可查询的 OperationHandle。

reboot_handle = hand.maintenance.reboot() # 重启设备
ota_handle = hand.maintenance.update_firmware("revo3_controller.bin")

本章列出 Python 与 C++ 对象层 public API。Python 中会发起 I/O 的方法通常返回 awaitable;表格中写 await ... 表示推荐调用方式。C++ 同名能力位于 revo3 命名空间。

Python 写法 C++ 写法 返回值 行为说明
sdk.Manager() revo3::Manager manager; manager 创建设备管理器
manager.list_ports() - list[SerialPortInfo] 列出本机端口/适配器,不访问设备
await manager.discover(...) manager.discover(options) list[DetectedDevice] 扫描设备
await manager.connect_auto(...) manager.connect_auto(options) Hand 自动扫描并连接首个设备
await manager.connect(detected, model=None) manager.connect(detected) Hand 连接扫描阶段选择的设备
await manager.connect_all(devices) manager.connect_all(devices) list[Hand] / std::vector<Hand> 批量连接
await manager.close() manager.close() None 关闭管理器和其持有连接

Python 返回标准 list[Hand],支持迭代、切片和按零基索引访问;按序列号选择设备时,应用可根据 hand.device_info.serial_number 过滤列表。C++ 的批量连接结果使用 std::vector<Hand>。

Python SerialPortInfo 提供以下只读字段:

字段 类型 说明
port_name str 操作系统端口名
manufacturer str | None USB 厂商字符串(系统未提供时为 None)
product_name str | None USB 产品字符串(系统未提供时为 None)
serial_number str | None 适配器序列号(系统未提供时为 None)
vid / pid int | None USB VID/PID(非 USB 端口或系统未提供时为 None)

discover(…) 流式回调 (Streaming Callback)

Section titled “discover(…) 流式回调 (Streaming Callback)”
  • Python 签名: await manager.discover(scan_all=False, port=None, protocol=None, slave_id=None, modbus_baudrate=None, canfd_data_baudrate=None, broadcast=True, on_found=None)
    • on_found: 可选回调 Callable[[DetectedDevice], bool | None]。每发现一台设备时触发,返回 False 可提前终止扫描。
  • C++ 签名: std::vector<DetectedDevice> manager.discover(const DiscoveryOptions &options)
    • DiscoveryOptions.on_found: 可选回调 std::function<bool(const DetectedDevice &device)>。返回 false 可提前终止扫描。

回调抛出异常时,扫描会停止,并在扫描线程完成清理后把原异常重新抛给 discover() 调用者;不会返回静默截断的设备列表,也不会让 C++ 异常穿过 C ABI。

Hand 对象能力树:

Hand
├── motion
├── state
├── touch
├── health
├── experimental_collision
├── config
├── calibration
├── maintenance
└── statistics

Hand 本体还提供 device_info、firmware_info、joint_layout、slave_id 属性,以及 refresh_device_info()、refresh_firmware_info() 和 close() 生命周期方法。

Python 写法 C++ 写法 返回值 行为说明
hand.device_info hand.device_info() DeviceInfo / None 设备和部件物理身份
hand.firmware_info hand.firmware_info() FirmwareInfo 主控、电机、触觉固件版本
hand.joint_layout hand.joint_layout() JointLayout / None 关节数量和布局
await hand.refresh_device_info() hand.refresh_device_info() DeviceInfo 重新读取设备身份
await hand.refresh_firmware_info() hand.refresh_firmware_info() FirmwareInfo 重新读取固件版本
hand.motion hand.motion() Motion 运动控制域
hand.state hand.state() State 电机反馈域
hand.touch hand.touch() Touch 触觉域
hand.health hand.health() Health 健康诊断域
hand.experimental_collision hand.experimental_collision() ExperimentalCollision 实验性软件碰撞检测与响应
hand.config hand.config() Config 配置域
hand.calibration hand.calibration() Calibration 标定域
hand.maintenance hand.maintenance() Maintenance 维护域
hand.statistics hand.statistics() RuntimeStatistics 运行读写和失败计数
await hand.close() hand.close() None 关闭当前手句柄

除目标运动、Servo、拖拽和示教回放外,Motion 还提供 set_zero_force_enabled()、software_stop() 和 recover_software_stop()。目标运动返回 OperationHandle,可通过 id、state、error、wait(timeout) 和 cancel() 管理。

Python 写法 C++ 写法 返回值 行为说明
await hand.motion.move_to(...) hand.motion().move_to(...) OperationHandle 整手目标运动
await hand.motion.move_joint(...) hand.motion().move_joint(...) OperationHandle 单关节目标运动
await hand.motion.move_finger(...) hand.motion().move_finger(...) OperationHandle 手指全姿态运动,包含 Abd
await hand.motion.flex_finger(...) hand.motion().flex_finger(...) OperationHandle 手指语义弯曲,Abd 保持当前值
await hand.motion.move_thumb(...) hand.motion().move_thumb(...) OperationHandle 拇指目标运动
hand.motion.open_servo(...) hand.motion().open_servo(...) ServoSession 同步创建实时流控会话;后续 send_*() 为异步 I/O
await session.send_position(...) session.send_position(...) None 发送位置流控帧
await session.send_velocity(...) session.send_velocity(...) None 发送速度流控帧
await session.send_current(...) session.send_current(...) None 发送电流流控帧
await session.send_impedance(...) session.send_impedance(...) None 发送阻抗流控帧
await session.send_mit(...) session.send_mit(...) None 发送 MIT 流控帧
session.state session.state() ServoSessionState 读取会话状态
session.close() session.close() None 关闭流控会话
await hand.motion.start_servo_drag(...) hand.motion().start_servo_drag(...) None 启动托管拖拽
hand.motion.update_servo_drag(...) hand.motion().update_servo_drag(...) None 更新拖拽目标
await hand.motion.stop_servo_drag(...) hand.motion().stop_servo_drag(...) None 正常停止拖拽
await hand.motion.cancel_servo_drag(...) hand.motion().cancel_servo_drag(...) None 取消拖拽发包
await hand.motion.teach_joint(...) hand.motion().teach_joint(...) list[float] 记录单关节轨迹
await hand.motion.teach_hand(...) hand.motion().teach_hand(...) list[list[float]] 记录整手轨迹
await hand.motion.replay_joint(...) hand.motion().replay_joint(...) None 回放单关节轨迹
await hand.motion.replay_hand(...) hand.motion().replay_hand(...) None 回放整手轨迹
await hand.motion.set_zero_force_enabled(enabled) hand.motion().set_zero_force_enabled(enabled) None 零力矩/示教模式开关
await hand.motion.software_stop() hand.motion().software_stop() None 发送软件停止指令并等待本次设备 I/O 完成
await hand.motion.recover_software_stop() hand.motion().recover_software_stop() None 发送软件停止恢复指令并等待本次设备 I/O 完成

StateSubscription、TouchSubscription 和 HealthSubscription 都使用同一生命周期约定:调用 next() 拉取下一帧,调用 close() 取消订阅并释放后台拉取任务。period 是 SDK 拉取间隔,不是固件采样频率承诺。

Python 写法 C++ 写法 返回值 行为说明
await hand.state.snapshot() hand.state().snapshot() HandState 读取电机反馈快照
hand.state.subscribe(period) hand.state().subscribe(period) StateSubscription 创建状态拉取订阅
await sub.next() sub.next() HandState 读取下一帧状态
hand.touch.layout hand.touch().layout() TouchLayout | None / TouchLayout 读取触觉区域分组和 module 布局;C++ 在不可用时抛出异常
await hand.touch.set_layout(layout) hand.touch().set_layout(layout);C ABI:revo3_device_touch_set_layout(...) None 为当前连接会话设置经确认的完整触觉布局;不写设备寄存器,未知或不完整布局失败
await hand.touch.snapshot() hand.touch().snapshot() TouchFrame 读取触觉快照
await hand.touch.snapshot(module_indices=[...]) hand.touch().snapshot({...}) TouchFrame 按请求顺序读取指定模块;C ABI:revo3_device_touch_get_snapshot_modules(...)
await hand.touch.module_snapshot(i) hand.touch().module_snapshot(i) TouchModuleData 读取单个模块
hand.touch.subscribe(period) hand.touch().subscribe(period) TouchSubscription 创建触觉订阅
await hand.touch.enabled_mask() hand.touch().enabled_mask() int 读取触觉使能 bitmask
await hand.touch.set_enabled_mask(mask) hand.touch().set_enabled_mask(mask) None 设置触觉使能 bitmask
await hand.touch.module_enabled(i) hand.touch().module_enabled(i) bool 读取单模块使能
await hand.touch.set_module_enabled(i, enabled) hand.touch().set_module_enabled(i, enabled) None 设置单模块使能
await hand.touch.tare(module_index=None) hand.touch().tare() / hand.touch().tare(module_index) None 通用触觉零漂校准入口;不传 module_index 时表示全部清零,传入时表示单模块清零(自动按当前布局路由到支持的触觉模块)
await hand.health.snapshot() hand.health().snapshot() HealthSnapshot 系统健康快照
await hand.health.motor_module_temperatures_c() hand.health().motor_module_diagnostics() list[float] / MotorModuleDiagnostics 逐电机模组温度
await hand.health.motor_online_mask() hand.health().motor_module_diagnostics() int / MotorModuleDiagnostics 电机在线 bitmask
await hand.health.clear_motor_faults() hand.health().clear_motor_faults() None 清除电机故障

5.5 ExperimentalCollision 实验性碰撞保护

Section titled “5.5 ExperimentalCollision 实验性碰撞保护”
Python 写法 C++ 写法 C 写法 返回值 行为说明
await hand.experimental_collision.configure(config) hand.experimental_collision().configure(config) revo3_experimental_collision_configure(...) None 配置或关闭实验性软件碰撞检测;默认关闭
await hand.experimental_collision.active_joints() hand.experimental_collision().active_joints() revo3_experimental_collision_get_active(...) 21 个 bool 查询当前锁存的碰撞关节状态
await hand.experimental_collision.reset() hand.experimental_collision().reset() revo3_experimental_collision_reset(...) None 重置锁存状态

ExperimentalCollisionConfig / revo3::ExperimentalCollisionConfig / CRevo3ExperimentalCollisionConfig 包含开关、检测来源、位置误差阈值、电流阈值、去抖时间、可复用状态最大年龄、响应策略和自动清除时间。其风险边界见 4.5。

Python 配置字段和构造默认值如下;字段均可在调用 configure() 前修改:

字段 默认值 单位或语义
enable False 总开关
source HardwareOnly 检测来源
position_error_threshold_deg 15.0 degree
current_threshold_ma 800.0 mA
debounce_time_ms 100 ms
max_cached_status_age_ms 50 ms
strategy SoftStop 保护策略
auto_clear_time_ms 1000 ms

5.6 Touch、Config、Calibration 与 Maintenance

Section titled “5.6 Touch、Config、Calibration 与 Maintenance”

Touch 统一承载触觉读取、配置和维护操作。产品级能力以 DeviceInfo.product_code 为准,当前连接的实际字段由 TouchLayout、signals 和 point_count 补充说明;不支持的操作返回 UnsupportedCapability。

Config、Calibration 和 Maintenance 也按以下职责归类:

  • Config 通信参数:set_rs485_baudrate()、set_canfd_baudrate()。
  • Config 位置/速度限制:set_joint_position_limits()、set_all_joint_position_limits()、set_joint_speed_limits()。
  • Calibration 零位与默认参数:zero_positions()、set_zero_positions()、reset_finger_defaults()。
  • Maintenance 升级生命周期:abort_firmware_update()、reset_firmware_update_state();reboot() 和 update_firmware() 返回 OperationHandle,其他维护操作返回 awaitable。

Touch API 按职责分为:读取与订阅、布局配置、模组启停、读取模式、数值模式、零点与力校准、模组信息与维护。下表保留跨语言签名对照,详细语义按上述职责阅读。

  • hand.touch.layout:读取当前 TouchLayout。
  • await hand.touch.snapshot():读取单帧 TouchFrame。
  • await hand.touch.snapshot(module_indices=[...]):只读取指定模块,并按传入的 module ID 顺序返回。
  • await hand.touch.module_snapshot(module_index):读取并直接返回单个 TouchModuleData。
  • hand.touch.subscribe(period):创建 TouchSubscription,通过 next() 拉取下一帧,通过 close() 取消。
  • await hand.touch.set_layout(layout):为当前连接会话设置经确认的完整布局;不写设备寄存器,仅更新 SDK 解析路由。
  • 支持 UF1~UF3、UT1、UT2 的完整集成布局,以及 UV1~UV4 的主链路指腹/手掌布局;未知、不完整或包含独立视触觉指尖的 UV1~UV4 布局在发送设备请求前失败。
  • set_module_enabled(module_index, enabled) / module_enabled(module_index):操作单个逻辑模组。
  • set_enabled_mask(enabled_mask) / enabled_mask():操作或读取逻辑模组 bitmask。
  • module_index 取值为公开 module_id:纯 压阻阵列触觉模组 / 高密矩阵触觉模组 布局下等于 TouchLayout.modules 的数组下标(0~10 密集编号);组合拓扑下为稀疏编号,与数组下标不再一致。
  • set_read_mode(mode) / read_mode():切换或读取 压阻阵列触觉模组 的 PointArray / LegacyForceSummary 模式。
  • LegacyForceSummary 是兼容读取模式,后续可能移除;该模式下点阵字段为 None,区域合力写入 regional_forces_mn。新应用不应依赖该模式。
  • set_value_mode(mode, module_index=None) / value_mode(module_index=None):读取或设置 压阻阵列触觉模组 / 高密矩阵触觉模组 的 ADC 或压力值模式。
  • 公开枚举仅包含 Adc (0) 与 Force (2);其他值不属于公开枚举,不接受该输入。
  • tare(module_index=None):统一零漂校准入口,支持 压阻阵列触觉模组、高密矩阵触觉模组、指尖三维力/力矩触觉模组。
  • cancel_tare(module_index=None):仅 高密矩阵触觉模组 支持,写入取消命令以恢复默认/出厂零点基线;它不表示必须存在一个正在进行的异步流程。
  • tare_status(module_index=None):仅 高密矩阵触觉模组 支持,读取协议定义的清零状态;指尖三维力/力矩触觉模组 没有对应状态寄存器。
  • point_counts():读取 压阻阵列触觉模组 或 高密矩阵触觉模组 运行时点数。
  • restart(module_index=None):重启 高密矩阵触觉模组 模组。
  • hand.device_info.touch_serial_numbers:读取已发现的触觉模组序列号;C ABI 从 CRevo3DeviceInfo.touch_serial_numbers 读取。
Python 写法 C++ 写法 返回值 行为说明
await hand.touch.read_mode() hand.touch().read_mode() TouchReadMode / TouchReadMode 读取触觉数据布局模式
await hand.touch.set_read_mode(mode) hand.touch().set_read_mode(mode) None 设置触觉数据布局模式
await hand.touch.value_mode(module_index=None) hand.touch().value_mode(module_index) TouchValueMode / TouchValueMode 读取触觉值模式
await hand.touch.set_value_mode(mode, module_index=None) hand.touch().set_value_mode(mode, module_index) None 设置触觉值模式
await hand.touch.tare(module_index=None) hand.touch().tare(module_index) None 执行零漂校准
await hand.touch.cancel_tare(module_index=None) hand.touch().cancel_tare(module_index) None 高密矩阵触觉模组 恢复默认/出厂零点基线
await hand.touch.tare_status(module_index=None) hand.touch().tare_status(module_index) TouchTareStatus 高密矩阵触觉模组 查询协议定义的清零状态
await hand.touch.point_counts() hand.touch().point_counts() list[int] / std::vector<uint16_t> 读取触觉模组点数
await hand.touch.restart(module_index=None) hand.touch().restart(module_index) None 重启触觉模组

Touch 操作按当前协议能力路由;不支持的组合在发送请求前返回 UnsupportedCapability:

操作 压阻阵列触觉模组 高密矩阵触觉模组 指尖三维力/力矩触觉模组
snapshot() 支持 支持 支持
set_read_mode() / read_mode() 支持 不支持 不支持
set_value_mode() / value_mode() 支持 支持 不支持
tare() 支持 支持 支持
cancel_tare() / tare_status() 不支持 支持 不支持(协议未提供对应寄存器)
point_counts() 支持 支持 不支持
restart() 不支持 支持 不支持

C ABI 对应的 Touch 符号为:

revo3_device_touch_get_layout
revo3_device_touch_set_layout
revo3_device_touch_get_snapshot
revo3_device_touch_get_snapshot_modules
revo3_device_touch_set_module_enabled
revo3_device_touch_get_module_enabled
revo3_device_touch_set_enabled_mask
revo3_device_touch_get_enabled_mask
revo3_device_touch_set_read_mode
revo3_device_touch_get_read_mode
revo3_device_touch_set_value_mode
revo3_device_touch_get_value_mode
revo3_device_touch_tare
revo3_device_touch_cancel_tare
revo3_device_touch_get_tare_status
revo3_device_touch_restart

C ABI 的 module_index 使用负数表示全部模组;非负值表示公开 module ID(纯 压阻阵列触觉模组 / 高密矩阵触觉模组 布局下等于 TouchLayout.modules 数组下标;组合拓扑下为与协议物理编号对齐的稀疏编号,不等于数组下标)。

Python 写法 C++ 写法 返回值 行为说明
await hand.config.snapshot() hand.config().snapshot() DeviceConfig 读取设备配置
hand.config.runtime_options hand.config().runtime_options() RuntimeOptions 读取 SDK 运行参数
hand.config.set_runtime_options(options) hand.config().set_runtime_options(options) None 设置 SDK 运行参数
await hand.config.set_buzzer(enabled) hand.config().set_buzzer(enabled) None 设置蜂鸣器
await hand.config.set_vibration(enabled) hand.config().set_vibration(enabled) None 设置振动
await hand.config.set_touch_screen(enabled) hand.config().set_touch_screen(enabled) None 设置触屏
await hand.config.set_use_broadcast_id(enabled) hand.config().set_use_broadcast_id(enabled) None 设置广播 ID 使用
await hand.config.set_power_on_auto_calibration(enabled) hand.config().set_power_on_auto_calibration(enabled) None 设置上电自动标定开关
await hand.config.set_auto_clear_motor_faults(enabled) hand.config().set_auto_clear_motor_faults(enabled) None 设置自动清除电机故障
await hand.config.set_max_continuous_current(ma) hand.config().set_max_continuous_current(ma) None 设置最大连续电流
await hand.config.set_global_protect_current(ma) hand.config().set_global_protect_current(ma) None 设置全局保护电流
await hand.config.set_joint_protect_current(i, ma) hand.config().set_joint_protect_current(i, ma) None 设置单关节保护电流
await hand.config.set_joint_position_limits(i, min, max) hand.config().set_joint_position_limits(i, min, max) None 设置单关节位置限制
await hand.config.set_all_joint_position_limits(minimums, maximums) hand.config().set_all_joint_position_limits(minimums, maximums) None 校验并同步整手 21 个关节位置限制
await hand.config.set_joint_speed_limits(i, min, max) hand.config().set_joint_speed_limits(i, min, max) None 设置单关节速度限制
await hand.config.set_rs485_baudrate(baudrate) hand.config().set_rs485_baudrate(baudrate) None / void 设置 RS485 波特率
await hand.config.set_canfd_baudrate(baudrate) hand.config().set_canfd_baudrate(baudrate) None / void 设置 CANFD 波特率
await hand.calibration.calibrate_joints() hand.calibration().calibrate_joints() None 关节标定
await hand.calibration.set_current(ma) hand.calibration().set_current(ma) None 设置标定电流
await hand.calibration.zero_positions() hand.calibration().zero_positions() list[float] 读取零位
await hand.calibration.set_zero_positions(values) hand.calibration().set_zero_positions(values) None 设置零位
await hand.calibration.set_current_position_as_zero() hand.calibration().set_current_position_as_zero() None 当前姿态设为零位
await hand.calibration.reset_finger_defaults() hand.calibration().reset_finger_defaults() None 恢复手指默认参数
hand.maintenance.reboot() hand.maintenance().reboot() OperationHandle 重启设备
hand.maintenance.update_firmware(path, target=None, wait_secs=10) hand.maintenance().update_firmware(path, target) OperationHandle 固件升级
await hand.maintenance.factory_reset() hand.maintenance().factory_reset() None 恢复出厂
await hand.maintenance.abort_firmware_update() hand.maintenance().abort_firmware_update() None 中止固件升级
await hand.maintenance.reset_firmware_update_state() hand.maintenance().reset_firmware_update_state() None 重置升级状态

6. 数据结构与类型参考 (Data Structures & Types)

Section titled “6. 数据结构与类型参考 (Data Structures & Types)”

本章详述 SDK 2.1 返回的核心数据结构、状态枚举及详细属性字段说明。

6.1 诊断与健康数据结构 (Health & Diagnostics)

Section titled “6.1 诊断与健康数据结构 (Health & Diagnostics)”

包含系统主控板只读健康诊断与安全状态信息:

属性字段 数据类型 描述说明
system_state int 系统全局状态 (0=Normal, 1=Fault)
error_code int 系统全局错误码 (0=Normal, 1=CommError, 2=NoCalibration, 3=TempAbnormal)
current_ma int 系统总电流 (mA)
voltage_v float 系统母线电压 (V),由寄存器原始值除以 100 得到,分辨率为 0.01 V
power_w float 系统总功率 (W),由寄存器原始值除以 100 得到,分辨率为 0.01 W
temperature_c int 主控芯片/板级温度 (°C)
motor_fault_codes list[int] / std::array<int, 21> 21 个电机的原始状态码,来自输入寄存器 2120..2140;字段名为兼容保留,值中同时包含故障位和非故障状态位
faulted_motor_count int 当前至少有一个已定义故障位置位的电机总数
safety_state SafetyState 系统安全诊断状态 (Normal / RecoveryRequired / Faulted / Unknown)
observed_at Timestamp 观察与采样时刻时间戳

包含 SDK 传输层运行与通信质量统计信息:

属性字段 数据类型 描述说明
state_reads int 电机状态反馈读取成功帧数
touch_reads int 触觉传感帧读取成功次数
commands_sent int 下发的写命令总数
failed_operations int 操作失败与通信异常总次数
servo_command_timeouts int 实时流控心跳超时断开次数
servo_commands int 实时伺服控制帧成功下发累计数
state_read_fps float 电机状态反馈读取频率,单位为帧/秒;按设备生命周期累计平均值计算
servo_command_fps float 实时伺服控制帧下发频率,单位为帧/秒;按设备生命周期累计平均值计算
touch_read_fps float 触觉传感帧读取频率,单位为帧/秒;按设备生命周期累计平均值计算

包含 21 电机驱动层诊断详细信息:

属性字段 数据类型 描述说明
temperatures_c list[float] / std::array<float, 21> 21 个电机的实时摄氏温度 (°C)
online_mask int / uint32_t 21-bit 电机在线掩码 (Bit 020 分别代表电机 020 的在线状态)
serial_numbers list[str] / std::vector<std::string> 21 个电机的出厂序列号
  • Operational (0): 系统运行正常,元数据与诊断信息可靠。
  • RecoveryRequired (1): 存在可恢复错误,需要进行重启或故障恢复。
  • Faulted (2): 严重故障状态,停止下发运动命令。
  • Unknown (3): 状态未知。

6.2 实时流控会话与数据订阅 (ServoSession & Subscriptions)

Section titled “6.2 实时流控会话与数据订阅 (ServoSession & Subscriptions)”

整手 21 个电机的实时状态与反馈数据快照:

属性字段 数据类型 描述说明
operating_states list[int] / std::array<int, 21> 21 个电机的原始运行状态 bitmask,来自输入寄存器 2000..2020
positions_deg list[float] / std::array<float, 21> 21 个电机的实时位置 (deg)
velocities_rpm list[float] / std::array<float, 21> 21 个电机的实时速度 (rpm)
currents_ma list[float] / std::array<float, 21> 21 个电机的实时电流 (mA)
timestamp Timestamp 数据帧接收时刻时间戳
positions_rad (Python) list[float] 21 个电机的实时位置 (rad),按 ROS REP 103 标准转换的只读属性
velocities_rad_s (Python) list[float] 21 个电机的实时速度 (rad/s),按 ROS REP 103 标准转换的只读属性
currents_a (Python) list[float] 21 个电机的实时电流 (A),国际单位制只读属性

SDK 当前不公开 MotorOperatingState 或 MotorFaultCode 枚举。HandState.operating_states 与 HealthSnapshot.motor_fault_codes 均保留固件原始整数语义,来自相互独立的寄存器数据源;应用不得在两者之间推导、回填或替代。在 Python 中,HandState 额外提供只读属性 positions_rad、velocities_rad_s 与 currents_a,方便 ROS 开发者直接接入 sensor_msgs/JointState。

  • Active (0): 实时流控会话处于活动中,允许持续下发高频控制帧(如位置/速度/MIT)。
  • Expired (1): 控制心跳超时(默认 >100ms 无新帧下发),流控已自动失效。
  • Closed (2): 会话已被显式调用 close() 关闭,或相关资源已被回收。

ServoSession.state 仅用于观测、诊断和区分超时失效与显式关闭。状态可能在读取后立即变化,应用不得将“先判断 Active、再发送命令”视为并发安全保证;每次发送仍以该调用的成功结果或结构化错误为准。Expired 和 Closed 均为终止状态,必须重新打开 Servo 会话才能继续发送。

枚举项 数值 描述说明
Disabled 0 不启用平滑滤波,目标值直接进入拖拽控制循环
FirstOrderLpf 1 使用一阶低通滤波平滑目标位置
SecondOrderCriticallyDamped 2 使用二阶临界阻尼滤波平滑目标位置

StateSubscription / TouchSubscription / HealthSubscription

Section titled “StateSubscription / TouchSubscription / HealthSubscription”

数据订阅流对象,用于按周期拉取采样:

方法 返回值 描述说明
await sub.next() / sub.next() HandState / TouchFrame / HealthSnapshot 异步/阻塞等待并读取下一帧订阅数据
sub.close() None 显式关闭并释放订阅句柄

close() 可从另一线程或任务调用,并会唤醒正在等待下一个采样周期的 next()。为保证协议事务完整性,已经进入底层设备 I/O 的单次读取不会被强制中断;关闭状态会阻止后续读取。

next() 返回一次 SDK 拉取获得的快照;订阅对象不是固件逐帧队列,不保存两次调用之间产生的全部物理采样,也不承诺无丢帧。period 是 SDK 的最小拉取间隔,不是设备采样周期、固定频率或端到端交付保证。当前公共 API 不提供 DataCollector、共享 Buffer 或连续帧流;需要逐帧记录的场景必须经过单独的能力与接口评审。

触觉传感器阵列与区域布局定义,用于描述设备接入的触觉硬件拓扑(包括纯 压阻阵列触觉模组、高密矩阵触觉模组、指尖三维力/力矩触觉模组,fingertip force/torque + piezoresistive-array、fingertip force/torque + high-density-matrix、fingertip force/torque + high-density-matrix + piezoresistive-array 组合拓扑,以及 UV1~UV4 上自动探测到的稀疏 压阻阵列触觉模组/高密矩阵触觉模组 指腹与手掌布局):

应用通过设备 product_code 确认产品能力,再通过 TouchLayout 获取当前连接实际返回的触觉分布;以 regions 获取解剖学区域分组(手掌/指尖/指腹),以 modules 获取各模块的 point_count 及 signals 数据形态。layout_id 仅用于需要稳定 schema key 的渲染、仿真或兼容性工具。LegacyForceSummary 兼容模式的二次标定区域合力直接从对应 TouchModuleData.regional_forces_mn 读取。

注意: UV1~UV6 的独立视触觉指尖采用专用数据链路,不并入主链路 TouchLayout 与 TouchFrame。UV1~UV4 上自动探测到的 压阻阵列触觉模组/高密矩阵触觉模组 指腹和手掌属于主链路,可以出现在上述结构中。

属性字段 数据类型 描述说明
regions list[TouchRegionLayout] 按区域分组的触觉模块布局
modules list[TouchModuleLayout] 触觉模块分布列表

按解剖学区域分组的触觉拓扑:

属性字段 数据类型 描述说明
region TouchRegion 触觉区域枚举
module_ids list[int] 属于该区域的稳定模组 ID 列表

单个触觉模组的拓扑与通道定义:

属性字段 数据类型 描述说明
module_id int 稳定模组 ID (0~10)
region TouchRegion 触觉区域枚举
region_index int 区域内部序号
layout_id str 可选的触觉 schema 标识;用于渲染、仿真或兼容性工具,不能替代 product_code 的产品能力判断
point_count int 触觉点阵总点数
signals list[TouchSignal] 该模组支持的触觉信号形态列表

单帧触觉传感数据快照:

属性字段 数据类型 描述说明
sequence int 数据帧序号
timestamp Timestamp 数据包接收时间戳
modules list[TouchModuleData] 逐模组触觉传感数据列表

TouchFrame 不使用单一 mode 概括整帧,因为组合拓扑的一帧可以同时包含点阵、模块级 summary 和力/力矩数据。应用应检查各 module 的 sample_state、points、regional_forces_mn、force3d、torque2d 和 resultant_force_mn。设备读取配置由独立的 TouchReadMode 表示。

单个触觉模块的多通道传感器数据:

属性字段 数据类型 描述说明
region TouchRegion 触觉区域
region_index int 区域内序号
module_id int 稳定模组 ID
layout_id str 可选的触觉 schema 标识,用于 GUI 热力图、仿真和兼容性工具;应用能力判断应以 product_code、signals 和 point_count 为准
sample_state TouchSampleState 当前模块在本帧中的采样状态
points list[int] | None 点阵数据;模块未采样、禁用或当前模式不返回点阵时为 None
regional_forces_mn list[int] | None 压阻阵列触觉模组 的 LegacyForceSummary 兼容模式下,该模组对应的一个或多个二次标定区域合力值,单位 mN;其他模式为 None
force3d TouchForce3D | None 指尖三维力/力矩触觉模组 模组局部坐标系的 Fx/Fy/Fz,单位 mN
torque2d TouchTorque2D | None 指尖三维力/力矩触觉模组 模组绕局部 X/Y 轴的 Mx/My,单位 Nm
resultant_force_mn float | None 指尖三维力/力矩触觉模组 模组触觉区域的标量合力 Fn,单位 mN;不是 Fz
diagnostics TouchModuleDiagnostics | None 可选的协议级原始诊断值;仅用于故障排查,不作为业务状态判断依据

TouchModuleDiagnostics 保留设备上报的原始状态,供日志记录和协议故障排查使用。应用应使用 TouchModuleData.sample_state 判断数据是否有效。

属性字段 数据类型 描述说明
module_status_raw int 模组原始状态:0 表示预热中,1 表示已就绪,2 或未知值表示不可用
sensor_fault_code_raw int 传感器原始故障码:0 表示正常,非零值表示异常

三维力与二维力矩向量:

类型 属性字段 数据类型 描述说明
TouchForce3D x, y, z float 三维力向量 Fx, Fy, Fz (mN)
TouchTorque2D x, y float 二维力矩向量 Mx, My (Nm)
枚举项 数值 描述说明
Valid 1 模块数据在本帧有效
Disabled 2 模块已禁用
NotSampled 3 本帧未轮询该模组,且该模组没有为当前帧贡献任何数据
ReadFailed 4 模块读取失败
Unavailable 5 模块数据不可用
WarmingUp 6 指尖三维力/力矩触觉模组 模块预热尚未完成
SensorFault 7 指尖三维力/力矩触觉模组 模块已就绪,但传感器状态异常

快照读取采用请求范围内的一致性策略:完整 snapshot() 的任何已启用模块读取失败时整帧失败;选择式 snapshot(module_indices=[...]) 的任何已选择且已启用模块读取失败时,本次选择读取整体失败。返回值不会用零值补齐失败模块;未选择模块直接不出现在返回帧中。因此 NotSampled 和 ReadFailed 仍为保留状态,正常快照中不会产生。

触觉模组 layout_id(可选 schema 标识)
Section titled “触觉模组 layout_id(可选 schema 标识)”

layout_id 不是产品识别码。产品能力以 DeviceInfo.product_code 为准;只有需要稳定布局 key 的工具才使用 layout_id。其基础格式为 <prefix>_<region>_<actual_point_count>:

  • 压阻阵列触觉模组:如 pressure_array_palm_36, pressure_array_thumb_tip_31, pressure_array_fingertip_21, pressure_array_thumb_pad_57, pressure_array_finger_pad_52
  • 高密矩阵触觉模组:根据设备运行时上报的实际点数生成;近期真机记录示例为 high_density_matrix_palm_53、high_density_matrix_fingertip_56、high_density_matrix_finger_pad_22、high_density_matrix_fingertip_21 和 high_density_matrix_finger_pad_27。协议容量 200/80/120 不是实际点数,不得用于构造 layout ID
  • 指尖三维力/力矩触觉模组:fingertip_force_torque_48 表示带 48 点点阵的指尖模组;fingertip_force_torque 表示不带点阵、仅提供力/力矩及合力信号的指尖模组

基础 ID 只区分区域和实际点数。同点数模组的点序或空间几何不同时,必须由受控硬件 revision 或模组身份映射提供 _v2、_v3 等版本后缀;SDK 不根据点数猜测布局版本。当前自动识别只生成基础 ID,版本后缀必须先纳入 SDK 的受控 layout mapping 后才能作为公共 ID 发布。应用遇到未知 ID 时应停止套用已有坐标映射,但仍可按 point_count 读取一维数据。

枚举项 Python 数值 C/C++ 数值 描述说明
Fingertip 0 1 指尖区域;具体手指由 region_index 表示
FingerPad 1 2 指腹区域;具体手指由 region_index 表示
Palm 2 3 手掌区域,region_index 为 0

region_index 在 Fingertip 和 FingerPad 区域内按 Thumb/Index/Middle/Ring/Pinky = 0/1/2/3/4 编号。应用不得使用不存在的 ThumbTip、IndexPad 等枚举项。

C ABI 额外定义 C_REVO3_TOUCH_REGION_UNKNOWN = 0,用于保证零初始化 CRevo3TouchLayout 的未使用区域槽位具有合法表示。CRevo3TouchLayout 不包含显式 module 计数;有效 module 必须从 modules[0] 开始连续排列,第一个 layout_id[0] == '\0' 的槽位结束有效列表,后续槽位必须保持未使用。有效 module 使用 Unknown region、或在结束槽位之后再次出现非空 layout_id 时,revo3_device_touch_set_layout() 返回参数错误。Python 和 C++ 对象 API 不公开该哨兵成员。

枚举项 描述说明
TouchPoint 触觉阵列压力点阵采样
Force3D 三维接触力 (Fx, Fy, Fz)
Torque2D 二维接触力矩 (Mx, My)
ResultantForce 接触法向标量合力 (Fn)

C ABI 额外定义 C_REVO3_TOUCH_SIGNAL_UNKNOWN = 0,用途同上。它只能出现在 signal_count 范围外的未使用槽位;有效信号列表包含该值时,布局设置失败。Python 和 C++ 对象 API 不公开该哨兵成员。

触觉数据模式:

枚举项 数值 描述说明
PointArray 0 点阵模式:输出点阵数据,点值类型由 TouchValueMode 决定。
LegacyForceSummary 1 二次标定区域合力兼容模式:部分设备可能支持;后续可能移除,新应用不应形成依赖。

适用范围:仅适用于 压阻阵列触觉模组 模组。

触觉值模式:

枚举项 数值 描述说明
Adc 0 ADC 读数:电路原始采样值(调试用)。
Force 2 压力值:设备输出的压力值。

支持模式:

  • 压阻阵列触觉模组 模组:支持 Adc (0) 与 Force (2);枚举值仅支持 Adc (0) 与 Force (2);其他值不属于公开 API。
  • 高密矩阵触觉模组 模组:支持 Adc (0) 与 Force (2);SDK 将公开值 2 映射为 高密矩阵触觉模组 底层寄存器值 1。
枚举项 数值 描述
NotTared 0 尚未完成零漂校准
Tared 1 零漂校准已完成
BusyOrFailed 2 操作进行中或失败;设备协议未提供更细粒度状态

6.4 设备元数据结构 (Device Metadata)

Section titled “6.4 设备元数据结构 (Device Metadata)”

设备基本信息与硬件标识:

属性字段 数据类型 描述说明
product_code Python: str | None;C++: std::string 三位产品代号(如 UB1、UT2);旧版或未知 SN 在 Python 返回 None,在 C++ 返回空字符串
model Revo3Model 仅用于旧版或未知 SN 回退的 SDK 2.x 粗粒度兼容分类;精确产品身份与能力判断使用 product_code
serial_number str 整手出厂序列号 (如 BCUBR40124000001)
hand_side HandSide 左右手类型 (Left / Right)
hardware_revision str 硬件版本号 (如 v1.0.0)
motor_serial_numbers list[str] 按当前逻辑关节顺序排列的已知电机出厂序列号列表
touch_serial_numbers list[str] 触觉模块序列号列表

模块固件版本信息:

属性字段 数据类型 描述说明
controller_firmware_version str | None 当前已知的主控板固件版本;未知时为 None
motor_firmware_versions list[str] 按逻辑关节顺序排列的已知电机驱动板固件版本
touch_firmware_versions list[str] 当前已知的触觉模组固件版本;无已知版本时为空列表

逻辑关节拓扑与数量定义:

属性字段 数据类型 描述说明
layout_id str 运动学关节拓扑标识符 (如 Revo3Ultra21, Revo3Pro16, Revo3Basic13,同系列不同触觉型号共享)
version int 布局定义规范的版本号 (如 1)
joint_count int 逻辑关节总数 (如 21, 16, 13)

设备硬件与控制参数配置快照:

属性字段 Python / C++ 类型 描述说明
slave_id int 当前设备从站 ID
rs485_baudrate int 当前 RS485 波特率 (bps)
canfd_baudrate int 当前 CANFD 数据域波特率 (bps)
buzzer_enabled bool 蜂鸣器状态
vibration_enabled bool 振动马达状态
touch_screen_enabled bool 触摸屏状态
teaching_mode_enabled bool 零力/示教模式状态
software_stop_enabled bool 软件停止状态
use_broadcast_id bool 广播 ID 使用状态
power_on_auto_calibration_enabled bool 上电自动标定使能
auto_clear_motor_faults_enabled bool 自动清除电机故障使能
max_continuous_current_ma float 最大连续电流 (mA)
global_protect_current_ma float 全局保护电流 (mA)
joint_protect_current_ma list[float] / std::array<float, 21> 各逻辑关节保护电流 (mA);有效长度由 JointLayout.joint_count 决定
joint_min_position_deg list[float] / std::array<float, 21> 各逻辑关节最小位置限制 (deg);有效长度由 JointLayout.joint_count 决定
joint_max_position_deg list[float] / std::array<float, 21> 各逻辑关节最大位置限制 (deg);有效长度由 JointLayout.joint_count 决定
joint_min_speed_rpm list[float] / std::array<float, 21> 各逻辑关节最小速度限制 (rpm);有效长度由 JointLayout.joint_count 决定
joint_max_speed_rpm list[float] / std::array<float, 21> 各逻辑关节最大速度限制 (rpm);有效长度由 JointLayout.joint_count 决定
persistence_scope str / - Python 快照提供的持久化范围说明;当前值为 firmware-defined

SDK 运行客户端参数配置(进程内默认值,不写入设备):

属性字段 数据类型 描述说明
state_subscription_period_ms int State 订阅默认拉取间隔 (ms),默认 20
touch_subscription_period_ms int Touch 订阅默认拉取间隔 (ms),默认 20
health_subscription_period_ms int Health 订阅默认拉取间隔 (ms),默认 1000
servo_command_timeout_ms int Servo 会话相邻两次流式命令的默认超时 (ms),默认 100

数据帧接收与系统时间戳:

属性字段 数据类型 描述说明
sec int 秒数
nsec int 纳秒数 (0~999,999,999)
clock TimestampClock 时钟源类型 (ProcessMonotonic, UnixRealtime)
枚举项 数值 描述说明
ProcessMonotonic 0 进程内单调递增时钟 (SDK 内部时钟,不受系统时间调整影响)
UnixRealtime 1 协调世界时 Unix 纪元时间戳 (UTC epoch realtime clock)
枚举项 数值 描述说明
Left 0 左手
Right 1 右手

目标运动、设备重启和固件升级返回 Handle。程序可以通过 Handle 查看状态、等待完成或请求取消。OperationHandle 是面向调用方的运动/维护操作句柄名称,其生命周期统一使用 OperationState;SDK 不定义重复的 MotionState。关节标定、软件停止和软件停止恢复是直接等待设备 I/O 的单次命令,不返回 Handle。设备重启一旦进入设备 I/O 就不能撤回,对其 Handle 调用 cancel() 会保持当前状态。

OperationHandle
├── id
├── state
└── error

Handle 状态包括 Pending、Running、Succeeded、Cancelled、Preempted、Failed 和 Indeterminate。注:在当前硬件通信模型下,主动调用 cancel() 的协作式取消终态为 Indeterminate(结果不确定,需先读实际状态,不能直接重试);Cancelled 作为保留枚举成员供未来支持确定性硬件取消确认的协议扩展使用。当前固件没有提供统一的进度和设备端开始、完成时间,因此 Handle 不提供这些字段。Indeterminate 表示 SDK 不知道设备最终执行到了哪一步,调用者不能直接重试。

枚举项 数值 是否终态 描述说明
Pending 0 否 已创建,尚未开始执行
Running 1 否 正在执行
Succeeded 2 是 操作成功完成
Cancelled 3 是 设备端已确定取消;当前协议通常不能提供该确认
Preempted 4 是 被同类新操作替换
Failed 5 是 操作失败且错误对象可读
Indeterminate 6 是 最终设备效果无法确认,必须先读取实际状态

目标运动使用协作式取消:SDK 会等待当前寄存器请求完整结束,在下一个控制周期边界停止发送轨迹点并释放软件控制权,不会中途丢弃串口请求。固件升级取消会在下一个 DFU 轮询或数据包边界发送设备端 abort 命令。取消请求已经发出但设备最终位置或写入结果无法确认时,Handle 状态为 Indeterminate。

Python 的 handle.error 和 C++ 的 handle.error() 返回与该 Handle 绑定的 SdkError;没有错误时分别返回 None 和 std::nullopt。终态与错误作为同一个结果发布,因此观察到 Failed 或带错误的 Indeterminate 时,对应错误已经可读,不依赖线程局部的最近一次 API 错误。

同一只 Hand 不能同时执行 move_to() 和 ServoSession,冲突时返回 ControlConflict。move_to() 由 SDK 生成并发送轨迹;ServoSession 由用户持续发送新目标。

正在执行 move_to() 时再次调用 move_to(),新目标会替换旧目标。SDK 从当前反馈位置和速度重新规划,旧 OperationHandle 进入 Preempted。该行为只适合低频重新规划,不适合频繁更新目标;频繁发送目标应使用 open_servo()。

关节标定使用单命令方式。发送前检查当前没有运动;Touch 读取和 Touch 标定不影响运动。固件没有提供标定进度或完成状态,写响应只表示命令已经发出,不能证明设备内部标定已经结束。

SdkError
├── code
├── message
├── retryable
├── operation_effect
├── recovery_requirement
└── low_level_cause

SdkError 是所有 API 失败时返回的结构化错误对象,各字段描述不同维度:code 表示失败原因;operation_effect 表示命令对设备的影响;recovery_requirement 表示再次操作前必须完成的恢复步骤;retryable 表示完成该恢复步骤后是否允许重试同一操作;message 是稳定的用户可读说明,low_level_cause 仅用于底层诊断。写命令失败且 operation_effect 为 Indeterminate(结果不确定)时,命令可能已在设备生效但响应丢失,程序应先读取设备状态,不能直接重试。C ABI 的 CRevo3ErrorInfo 使用定长字符串保存 message 和 low_level_cause,C++ SdkError::low_level_cause() 返回 std::optional<std::string>。

Python 中 code、operation_effect 和 recovery_requirement 分别使用 SdkErrorCode、OperationEffect 和 RecoveryRequirement 枚举;C++ 使用同名强类型枚举,不公开无类型的整数错误字段。

SdkErrorCode 是可供程序分支判断的唯一错误标识。C++ 额外保留 Unknown = 0,用于转换无法识别的 C ABI 值;Python 不导出该成员。

数值 SdkErrorCode 典型含义
1 ConnectionFailed 建立连接或传输失败
2 InvalidArgument 参数不满足公开约束
3 InvalidState 当前生命周期或设备状态不允许该操作
4 Timeout 有界等待或通信超时
5 UnsupportedCapability 当前型号、固件、布局或传输不支持该能力
6 DeviceFault 设备明确报告故障
7 Internal SDK 内部错误
8 ControlConflict 与当前运动或流式控制所有权冲突
枚举项 数值 描述说明
NotApplied 1 已确认操作未应用到设备
PartiallyApplied 2 操作仅部分生效,需读取状态并按具体 API 恢复
Indeterminate 3 无法确认是否生效,不得直接重试写命令
Python 枚举项 C++ 枚举项 数值 描述说明
None_ None 0 不要求额外恢复动作;Python 使用 None_ 避免与关键字混淆
Retry Retry 1 无需重连或人工处置;retryable=true 时可直接重试
Reconnect Reconnect 2 需要重新建立连接并重新获取会话状态
OperatorAction OperatorAction 3 设备明确报告故障,需要操作人员检查或干预

SDK 只返回当前有明确判定依据的恢复动作。安全保护恢复和整机断电重启尚无统一的固件语义与自动判定路径,因此不作为 RecoveryRequirement 枚举项对外暴露。

retryable=true 不等于 recovery_requirement=Retry。例如只读操作因连接失败时返回 Reconnect 和 retryable=true,表示必须先重连,之后才允许重试原读取;Retry 表示不需要重连即可重试。任何 Indeterminate 写操作都不会标记为可重试。

重试规则:

  • 以下规则适用于 Hand API 发起的设备请求。Manager 的设备扫描、连接和重连按各自流程处理,不属于命令重试。
  • 只读请求只有在连接未发生重建且策略允许时才能自动重试。
  • 会改变设备状态的请求在响应丢失后必须返回“结果未知”:命令可能已执行,也可能未执行,SDK 不能自动再发一次。
  • 断联、重连、安全恢复和重新发送命令是不同动作。
  • wait(timeout) 超时只结束本次等待,不自动取消设备操作。
  • Python 和 C++ 必须保留相同的错误码和处理方式。
# 示例:捕获结构化 SDK 异常与 Indeterminate 结果判断
try:
await hand.motion.move_to(targets, duration=1.0)
except sdk.SdkError as error:
print(f"Code: {error.code}")
if error.operation_effect == sdk.OperationEffect.Indeterminate:
# 响应丢失:先读状态确认是否已生效,不可盲目重复发送
state = await hand.state.snapshot()
  • 控制与反馈单位:SDK 公共 API 统一使用角度 degree (°)、旋转角速度 rpm 与电流 mA;底层驱动负责必要的进制或物理量转换。
  • 电流不是已标定关节力矩:电机反馈和 MIT 前馈字段都是 mA 电流。设备未提供 Nm 单位的已标定关节力矩,因此公共字段保持 current / current_ma,不改名为 torque。
  • 接收时间戳:State 与 Touch 快照中的 timestamp 表示 SDK 接收到数据包的时间。Linux SocketCAN 优先使用内核接收时间戳,其他传输层使用进程单调时钟。
  • 定位与限制:timestamp 不是固件物理采样时刻,不可用于多设备间的硬件时钟同步。多帧拼接的快照可能存在微小传输时差,timestamp 表示整组数据接收完成的时间,不保证各字段同一时刻采样。

9.3 物理单位转换 (Physical Unit Conversion)

Section titled “9.3 物理单位转换 (Physical Unit Conversion)”

为方便 ROS / ROS 2 机器人算法与国际单位制 (SI Units) 场景对接,SDK 在各语言层提供显式物理量换算基准与转换工具函数:

除非 API 字段或参数另有明确说明,SDK 公共 API 默认使用 degree(角度)、rpm(角速度)和 mA(电流)。rad、rad/s 和 A 是通过本节工具显式换算得到的 SI 单位;调用转换工具不会改变其他 API 的默认单位。

  • 角度 (Angle): 1 degree = (π / 180) rad (约 0.0174533 rad), 1 rad = (180 / π) degree (约 57.2958 degree)
  • 角速度 (Angular Velocity): 1 rpm = (π / 30) rad/s (约 0.10472 rad/s), 1 rad/s = (30 / π) rpm (约 9.5493 rpm)
  • 电流 (Current): 1 mA = 0.001 A, 1 A = 1000 mA
  • C ABI (revo3-sdk.h):
    • 标量转换:revo3_deg_to_rad(float), revo3_rad_to_deg(float), revo3_rpm_to_rad_s(float), revo3_rad_s_to_rpm(float), revo3_ma_to_a(float), revo3_a_to_ma(float)
    • 批量数组转换:revo3_deg_to_rad_array(const float* in, float* out, size_t count), revo3_rad_to_deg_array(...), revo3_rpm_to_rad_s_array(...), revo3_rad_s_to_rpm_array(...), revo3_ma_to_a_array(...), revo3_a_to_ma_array(...)
  • C++ 命名空间 (revo3::units):
    • 提供 revo3::units::deg_to_rad(...) 等重载,支持 float、std::vector<float> 与 std::array<float, N>。
  • main_mod.deg_to_rad(value):支持传入单数值或浮点数列表/元组,返回对应的弧度值或列表。
  • main_mod.rad_to_deg(value):将弧度转为角度。
  • main_mod.rpm_to_rad_s(value):将转速 rpm 转为角速度 rad/s。
  • main_mod.rad_s_to_rpm(value):将角速度 rad/s 转为转速 rpm。
  • main_mod.ma_to_a(value):将电流 mA 转为安培 A。
  • main_mod.a_to_ma(value):将安培 A 转为电流 mA。
# 示例:Python 批量与单值单位转换
from bc_revo3_sdk import main_mod as sdk
rad_positions = sdk.deg_to_rad(state.positions_deg) # list[float] 批量转为 rad
target_deg = sdk.rad_to_deg(ros_command_rad) # 将 ROS rad 指令转为 deg

9.4 基础运行时与模块级工具 (Runtime Utilities & Logging)

Section titled “9.4 基础运行时与模块级工具 (Runtime Utilities & Logging)”

SDK 提供跨语言的基础环境配置、日志管理、版本查询及端口探测工具:

  • C ABI (revo3-sdk.h):revo3_init_logging(level, enable_file_logging);enable_file_logging=true 时同时写入 logs/revo3_<timestamp>.log。
  • C++ (revo3::init_logging):revo3::init_logging(level=LOG_LEVEL_INFO, enable_file_logging=true)。建议在进程启动时初始化一次;后续调用可更新日志级别,但输出目标由首次调用确定。
  • Python (main_mod.init_logging):main_mod.init_logging(level=LogLevel.Info, enable_file_logging=True)。设置 SDK 日志级别;启用文件日志时添加 SDK 专用的 Python logging.FileHandler,写入 logs/revo3_<timestamp>.log。重复调用会替换该专用文件 handler,不影响应用自行配置的其他 handler。
  • 版本查询:
    • Python:main_mod.get_sdk_version() 返回包含预发布后缀的精确 SDK 版本字符串。
    • C++:revo3::api_version() 返回编码版本号与语义版本字符串。
  • 端口枚举与白名单配置:
    • main_mod.list_available_ports():返回 list[SerialPortInfo],只枚举本机候选端口,不主动探测设备。
    • main_mod.configure_usb_vid_pid_allowlist(custom_ids=[], include_defaults=True):配置 USB 适配器 VID/PID 白名单;include_defaults=False 时只使用调用方提供的条目。
  • 命名空间与类型:最低编译器标准为 C++17,公共类型位于 revo3 命名空间(如 revo3::Manager、revo3::Hand、revo3::OperationHandle),类名与方法名不重复添加 revo3_ 前缀。
  • 版本查询:revo3::api_version() 返回编码版本、major/minor/patch 和包含预发布后缀的精确字符串(例如 2.0.0-rc.3)。
  • C ABI:revo3-sdk.h 可由 C11 和 C++17 编译器直接包含;C 符号统一使用 revo3_ 前缀。SDK 2.0 不导出 1.x 的 DeviceHandler、手动 transport 初始化、全局 callback setter 或无前缀 stark_* 兼容入口。
  • 对象层:C++17 对象 API 基于公开 C ABI 实现,提供 RAII、强类型参数和异常转换,不额外形成第二套底层协议实现。
  • 资源管理与生命周期:Manager 与 Hand 仅支持移动构造与赋值,禁止拷贝。对象离开作用域时自动释放资源;亦可显式调用 close(),重复调用不会报错。
  • 异步句柄与等待:目标运动、重启与固件升级等长耗时操作立即返回 Handle 对象,支持调用 wait(std::chrono::milliseconds) 阻塞等待完成。
  • 异常与状态表达:运行时错误抛出 revo3::SdkError,运动与操作状态通过 OperationState 返回。
  • 模块设计与类型:只导出本规范定义的类、枚举与数据结构,不提供 1.x module-level 或 DeviceContext 兼容入口;最低支持 Python 3.10,并使用 T | None、Sequence[T] 和精确的 Awaitable[T] stub 类型。
  • 资源管理与生命周期:支持显式调用 close(),也支持 async with 上下文管理器,确保退出时自动关闭端口与连接。
  • 异步句柄与等待:目标运动、重启与固件升级等长耗时操作返回 Handle 对象,调用 await handle.wait(timeout) 等待完成(Handle 本身不可直接 await)。
  • 异常与状态表达:与 C++ 共享相同的 SdkError 异常结构与 OperationState 状态表达。