S1 末端工具原始透传
S1 末端工具原始透传 API 用于在 SDK 应用与左臂或右臂 TIB 之间传输不透明的 64 字节帧。
SDK 核心层只负责以下工作:
- 选择左侧或右侧 TIB;
- 通过 DDS 发布 64 字节原始命令;
- 订阅左右两侧的 1 kHz、250 Hz 原始接收流;
- 将原始数据分发给已注册的用户回调;
- 管理回调注册和注销。
SDK 核心层不解析具体设备协议。CAN ID、RS485 报文、寄存器、夹爪位置和力传感器数值等逻辑位于示例或用户自己的设备适配层。
部署前提
启动应用前需要完成以下操作:
-
部署支持 S1 末端原始透传的 WBCS 版本。
-
在当前 S1 使用的
robot_config.toml中设置以下配置并重启 WBCS:[robot_info.custom_params]
endtool_raw_enabled = true -
将 CAN 或 RS485 设备连接并配置到预期的 TIB。
-
停止或通过业务逻辑排除所有会写入同一末端的生产控制器。
SDK 返回发送成功只表示 DDS 消息已在本地成功发布,不代表 WBCS 已完成转发,也不代表 TIB 或末端设备已经接收并执行命令。
数据链路
发送链路:
应用层设备编码器
-> 64 字节 frame
-> send_endtool_raw_frame(side, frame)
-> EndToolRawCommand
-> WBCS Raw relay
-> EtherCAT -> TIB -> CAN/RS485 -> 末端设备
接收链路:
末端设备应答/主动上报
-> CAN/RS485 -> TIB -> EtherCAT
-> WBCS 1 kHz 或 250 Hz 接收缓冲区
-> singorix_proto::EndToolRawData
-> SDK 内部传输回调
-> EndToolRawData
-> 应用回调及设备协议解析器
GBS 1.18.1 使用两个公共 DDS topic:
singorix/wbcs/endtool/raw_command
singorix/wbcs/endtool/raw_data
SDK 发送时将左右侧映射为逻辑 endpoint_id,并固定使用 channel_id=command;接收时再将 endpoint_id/channel_id 映射回公开 API 的 side/kind。
传输契约
| 字段 | 含义 |
|---|---|
frame | S1 WBCS/TIB 布局下严格为 64 字节的不透明数据 |
side | SDK 将 LEFT/RIGHT 映射为 left_endtool/right_endtool |
kind | SDK 将 BUFFER_1KHZ/BUFFER_250HZ 映射为 feedback_1khz/feedback_250hz |
generation | 底层 sequence,在一个 endpoint/channel 流和一次发布进程生命周期内单调递增;WBCS 重启后可以复位 |
SDK 会订阅 side 和 kind 的四种组合。每个已注册回调都会收到全部四路数据,因此应用必须先过滤 side 和 kind,再解析设备 payload。
具体使用哪一路接收流由设备决定。例如,自研 CAN 夹爪使用 250 Hz buffer,坤维 RS485 传感器使用 1 kHz buffer。
API 使用流程
C++ 和 Python API 的生命周期一致:
robot.init() 会自动初始化 S1 原始透传节点、一个公共接收 reader 和一个公共发送 writer;任一资源创建失败时,S1 机器人初始化会返回 false。SDK 在公共 topic 内根据 endpoint/channel 分流,公开的 side/kind API 不变。
- 获取 S1 机器人实例并调用
init()。 - 注册原始接收回调。
- 将设备命令编码为严格的 64 字节帧。
- 将帧发送到选定的机械臂/TIB。
- 在回调中先过滤 side/kind,再完整校验设备帧;只有有效帧才能更新业务状态。
- 销毁 SDK 实例前注销回调。
C++ 最小结构:
auto& robot = GalbotRobot::get_instance(MachineType::S1);
if (!robot.init()) {
return 1;
}
const auto handle = robot.register_endtool_raw_callback(
[](const EndToolRawData& data) {
if (data.side != EndToolSide::LEFT ||
data.kind != EndToolRxKind::BUFFER_250HZ) {
return;
}
// 根据已安装设备的协议校验并解析 data.frame。
});
std::array<uint8_t, END_TOOL_RAW_FRAME_SIZE> frame{};
// 将设备特定的 CAN/RS485 命令编码到 frame。
const auto status = robot.send_endtool_raw_frame(EndToolSide::LEFT, frame);
robot.unregister_endtool_raw_callback(handle);
robot.destroy();
回调与资源安全
- 接收回调运行在中间件线程;应用仍应按并发回调场景保护共享状态。
- 回调应尽量简短,并使用 mutex 或 atomic 保护共享状态。
- 需要在回调结束后继续使用的数据必须复制,不要保留
EndToolRawData的引用。 unregister_endtool_raw_callback()返回时,已经开始执行的某次回调仍可能继续完成,因此回调捕获的共享状态必须具备安全生命周期。- 同一个 SDK 实例内的 Raw 发送已经串行化,但不存在跨进程或跨客户端的资源租约。
- Raw writer 仍可能与标准夹爪控制器或另一个进程对同一 TIB 的写入发生竞争。
设备适配器职责
生产级适配器不能只检查帧头。应根据设备协议检查:
- 帧类型、CAN/设备 ID 和 payload 长度;
- 命令码、功能码和 response 标志;
- 校验和或帧尾;
- 数值有限性和物理量程;
generation单调性和响应超时;- generation 持续增长时 payload 是否长期冻结;
- 发送前的命令参数范围。
坏帧必须直接拒绝,不能覆盖业务层保存的最后一份有效状态。
SDK 示例
SDK 为三种设备提供了完整的 C++ 和 Python 示例:
| 设备 | 总线 | 接收流 | 行为 |
|---|---|---|---|
| 自研二指夹爪 | CAN | 250 Hz | 初始化/运动命令及被动状态上报 |
| 大寰二指夹爪 | CAN/Modbus 变体 | 依设备响应 | 参数配置、运动和主动状态轮询 |
| 坤维六维力传感器 | RS485 | 1 kHz | 每 10 ms 主动查询并解析力/力矩 |
完整可运行源码请参阅 C++ 示例 和 Python 示例。
故障排查
| 现象 | 检查项 |
|---|---|
| Publish 成功但末端无动作 | 确认 [robot_info.custom_params].endtool_raw_enabled=true 并重启 WBCS,然后检查末端选择、设备供电和接线 |
| 没有接收回调 | 确认预期的 side/kind、WBCS Raw RX 日志、设备波特率和应答模式 |
| 大量帧被拒绝 | 检查 CAN/设备 ID、response 标志、帧尾/校验和及字节偏移 |
| generation 出现跳变 | 接收端或中间件可能过载,应减少回调中的工作量和日志量 |
| generation 增长但 payload 长期不变 | 检查传感器或设备接收链路是否冻结 |
| 命令行为偶发异常 | 确认标准控制器或第二个客户端没有同时写入同一 TIB |