Compare commits
2 Commits
af67751937
...
edb01463ff
| Author | SHA1 | Date | |
|---|---|---|---|
| edb01463ff | |||
| b54c2936be |
123
README.md
123
README.md
@ -139,119 +139,16 @@ sudo script/ethercat/stop_ethercat.sh eno1
|
||||
sudo script/ethercat/stop_ethercat.sh eno1 --restore-network
|
||||
```
|
||||
|
||||
## MotorService 与 Modbus TCP PLC
|
||||
## 组件文档
|
||||
|
||||
工程包含从 gRPC `MotorService`、`MotorManager`、`AbstractMotor` 到
|
||||
`ModbusTcpMotorBusRuntime` 的 CMVR PLC v1 电机控制链,x86-64 的 libmodbus
|
||||
3.1.11 已放在 `dependency/x86/third_party/modbus/3.1.11`。
|
||||
具体能力、配置、协议和安全边界由对应代码目录下的 README 维护:
|
||||
|
||||
PLC 对接时特别注意:
|
||||
- [MotorService gRPC 接口](cmvr-es/service/README.md#motorservice)
|
||||
- [电机设备模块](cmvr-es/devices/motor/README.md)
|
||||
- [Modbus TCP PLC runtime](cmvr-es/devices/motor/bus_runtime/modbus_tcp/README.md)
|
||||
- [MotorService 与 CMVR PLC v1 完整协议](docs/motor_service_modbus_tcp.md)
|
||||
- [AUBO 控制柜 Standard 数字 IO](cmvr-es/devices/arm/aubo_arm/README.md)
|
||||
- [配置与部署规则](cmvr-es/config/README.md)
|
||||
|
||||
- `host` 必须配置为 IPv4 字面量,PLC boot ID 必须非零且每次重启变化;
|
||||
- owner 决策、命令 ACK 都必须回显对应 session,重连不得执行旧 mailbox;
|
||||
- PLC 在进程启动时可以离线;连接 supervisor 会继续退避重试,离线期间状态
|
||||
返回不可用且运动命令不会写 mailbox;
|
||||
- 状态区按 odd/even seqlock 发布,上位机使用
|
||||
sequence-before → 64-word block → sequence-after 三段读取验证;
|
||||
- 每次 `OpenCyclicPosition/Velocity` 创建新 stream epoch,PLC 必须原子清零
|
||||
`last_applied_cyclic_sequence`、旧样本去重状态和 cyclic watchdog,确认
|
||||
`StreamActive` 与正确 mode 后才 ACK;重开后的首样本序列从 `1` 开始并必须
|
||||
重新应用;
|
||||
- 活动 cyclic 流跨 `connection_epoch` 后不会自动重开;旧流的当前和后续
|
||||
setpoint 均被拒绝并在 Quick Stop 后终止,客户端必须新建 gRPC 流。断链前
|
||||
或断链期间 pending 的 setpoint 不会应用到新 session;
|
||||
- 任何清理 Quick Stop 未确认时,MotorService 都会 fail-closed 锁存,并在
|
||||
成功执行 `setEnabled(true)` 前拒绝新的运动命令;
|
||||
- Modbus Quick Stop 只是功能性停止,不能替代硬接线急停或驱动器 STO。
|
||||
- 当前 Modbus 后端只提供 x86-64 的 libmodbus 3.1.11;`dependency/arm`
|
||||
尚无对应库,因此 ARM 构建暂不支持该后端。
|
||||
|
||||
完整 gRPC 语义、配置样例、寄存器表、TIA Portal 要求、构建测试和安全边界见
|
||||
[`docs/motor_service_modbus_tcp.md`](docs/motor_service_modbus_tcp.md)。
|
||||
|
||||
## AUBO 控制柜 IO
|
||||
|
||||
`AuboArm` 通过通用的 `executeJsonCommand` 接口提供控制柜 Standard 数字 IO
|
||||
读写。第一版支持以下命令:
|
||||
|
||||
| `operation` | 说明 | 必填字段 |
|
||||
| --- | --- | --- |
|
||||
| `get_di` | 读取控制柜数字输入 | `index` |
|
||||
| `get_do` | 读取控制柜数字输出及其 runstate | `index` |
|
||||
| `set_do` | 设置控制柜数字输出 | `index`、`value` |
|
||||
|
||||
JSON 命令示例:
|
||||
|
||||
```json
|
||||
{"command":"cabinet_io","operation":"get_di","index":0}
|
||||
{"command":"cabinet_io","operation":"get_do","index":0}
|
||||
{"command":"cabinet_io","operation":"set_do","index":0,"value":true}
|
||||
```
|
||||
|
||||
其中 `index` 从 `0` 开始,运行时会根据控制器返回的 IO 数量检查范围。
|
||||
`set_do.value` 必须是 JSON 布尔值 `true` 或 `false`,不接受 `0/1` 或字符串。
|
||||
`set_do` 成功响应中的 `requested_value` 表示 SDK 已接受的请求值;需要确认控制器
|
||||
当前输出状态时,再调用一次 `get_do` 读取实际值。
|
||||
|
||||
成功响应示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"command": "cabinet_io",
|
||||
"operation": "get_di",
|
||||
"index": 0,
|
||||
"count": 16,
|
||||
"value": false
|
||||
}
|
||||
```
|
||||
|
||||
### 通过 gRPC 调用
|
||||
|
||||
该功能复用 `cmvr.api.SystemService/ExecuteJsonCommand`。默认配置中的 gRPC
|
||||
端口是 `50052`,读取 DI0:
|
||||
|
||||
```shell
|
||||
grpcurl -plaintext \
|
||||
-d '{
|
||||
"header":{"deviceId":"aubo_arm"},
|
||||
"requestJson":"{\"command\":\"cabinet_io\",\"operation\":\"get_di\",\"index\":0}"
|
||||
}' \
|
||||
127.0.0.1:50052 \
|
||||
cmvr.api.SystemService/ExecuteJsonCommand
|
||||
```
|
||||
|
||||
设置 DO0 为高电平:
|
||||
|
||||
```shell
|
||||
grpcurl -plaintext \
|
||||
-d '{
|
||||
"header":{"deviceId":"aubo_arm"},
|
||||
"requestJson":"{\"command\":\"cabinet_io\",\"operation\":\"set_do\",\"index\":0,\"value\":true}"
|
||||
}' \
|
||||
127.0.0.1:50052 \
|
||||
cmvr.api.SystemService/ExecuteJsonCommand
|
||||
```
|
||||
|
||||
使用源码树默认配置时,先在 `cmvr-es/config/manager/device_manager.pb.txt` 中把
|
||||
`aubo_arm` 的 `enable` 改为 `true`,并在
|
||||
`cmvr-es/config/devices/arm/aubo_arm.pb.txt` 中配置正确的控制器地址和登录信息,
|
||||
然后重新安装配置并启动安装产物:
|
||||
|
||||
```shell
|
||||
cmake --install build
|
||||
./output/bin/cmvr_es
|
||||
```
|
||||
|
||||
`output/bin/cmvr_es` 读取的是 `output/bin/config/`;如果进程使用显式配置路径,
|
||||
应修改该配置根下的对应文件。
|
||||
设备未启用或初始化失败时,gRPC 会返回 `Device not found: aubo_arm`。
|
||||
|
||||
### 安全约束
|
||||
|
||||
- 该接口只访问控制柜 Standard 数字 IO,不操作工具端 IO、可配置 IO 或安全 IO。
|
||||
- `set_do` 不会修改控制器的输出 runstate。只有目标通道的 runstate 为
|
||||
`StandardOutputRunState::None` 时才允许写入,否则返回
|
||||
`output_managed_by_runstate`。
|
||||
- 接口不会调用会重置全部输出配置的 `setDigitalOutputRunstateDefault()`。
|
||||
- 模拟量 IO 涉及 domain、单位和量程,第一版暂不通过该 JSON 接口开放。
|
||||
Modbus Quick Stop 只是功能性停止,不能替代硬接线急停或驱动器 STO。AUBO
|
||||
JSON 接口只访问控制柜 Standard 数字 IO,不访问安全 IO。
|
||||
|
||||
@ -18,8 +18,6 @@ cmvr_es.pb.txt
|
||||
入口文件:
|
||||
|
||||
- [`cmvr_es.pb.txt`](cmvr_es.pb.txt)
|
||||
- [`cmvr_es_ume.pb.txt`](cmvr_es_ume.pb.txt):UME 主端样例
|
||||
- [`cmvr_es_robot.pb.txt`](cmvr_es_robot.pb.txt):人形机械臂从端样例
|
||||
- [`manager/device_manager.pb.txt`](manager/device_manager.pb.txt)
|
||||
- [`manager/task_manager.pb.txt`](manager/task_manager.pb.txt)
|
||||
|
||||
@ -111,47 +109,48 @@ output/bin/protoc \
|
||||
|
||||
该命令只验证 Proto Text 解析,不验证文件、设备、证书、网络和跨字段语义。最终仍需运行组件测试和进程烟雾测试。
|
||||
|
||||
## 双边遥操部署样例
|
||||
## 双边遥操配置
|
||||
|
||||
仓库提供两个相互独立的 CMVR-ES 配置入口:
|
||||
源码仓库保持唯一根入口 [`cmvr_es.pb.txt`](cmvr_es.pb.txt)。统一的
|
||||
[`manager/device_manager.pb.txt`](manager/device_manager.pb.txt) 已声明
|
||||
`ume_left`、`ume_right`、`ti5_motors` 和 `right_arm`;统一的
|
||||
[`manager/task_manager.pb.txt`](manager/task_manager.pb.txt) 已声明
|
||||
`ume_teleop` 和 gRPC server。角色差异不通过增加新的源码根配置文件表达,而由
|
||||
两台机器各自的外部部署配置决定。
|
||||
|
||||
- UME 主端:[`cmvr_es_ume.pb.txt`](cmvr_es_ume.pb.txt),只声明
|
||||
`ume_left` 和 `ume_right`。两条机械臂在 DeviceManager 层默认关闭,
|
||||
[`devices/arm/ume_arms.pb.txt`](devices/arm/ume_arms.pb.txt) 内部的
|
||||
`hardware_enabled` 也默认关闭;两层开关必须经过标定与安全验收后分别启用。
|
||||
出站 `ume_teleop` Task 默认关闭,样例不包含机器人地址或凭据。当前 Task
|
||||
只实现会话/重连/心跳和 latest-only 指令邮箱,尚无生产算法调用
|
||||
UME 主端部署配置应只启用本机需要的 UME 设备和 `ume_teleop` Task:
|
||||
|
||||
- `ume_left`、`ume_right` 在 DeviceManager 层默认关闭;
|
||||
- [`devices/arm/ume_arms.pb.txt`](devices/arm/ume_arms.pb.txt) 内部的
|
||||
`hardware_enabled` 也默认关闭;
|
||||
- 两层硬件门必须在完成 CAN 映射、限位标定和安全验收后分别启用;
|
||||
- 当前 Task 只实现会话、重连、心跳和 latest-only 指令邮箱,尚无生产算法调用
|
||||
`submitSetpoint()`,返回 effort 也尚未接入本地触觉协调器。
|
||||
- 人形机械臂从端:[`cmvr_es_robot.pb.txt`](cmvr_es_robot.pb.txt),通用 gRPC
|
||||
server 可以启动,但 `ti5_motors` 和 `right_arm` 仍默认关闭。生产
|
||||
`ArmTeleop` 已实现真实 `RobotArm` 适配,但服务配置的 `enable` 显式关闭且
|
||||
样例哈希故意留空。`MotorRobotArm.enable_teleop_group_servo` 目前只是预留字段;
|
||||
因为现有 `servoJ` 仍是逐关节顺序写,代码即使看到该字段为 true 也会拒绝能力。
|
||||
必须先实现并验收原子或定时的组下发原语。因此启动 gRPC server 不等于允许遥操
|
||||
执行,也不能绕过设备层硬件门。
|
||||
|
||||
在两台边缘设备各自的源码或安装目录运行:
|
||||
机器人从端部署配置应只启用经过验收的机械臂设备以及所需的 gRPC server:
|
||||
|
||||
```bash
|
||||
# UME 主端(源码配置)
|
||||
./output/bin/cmvr_es \
|
||||
--config ./cmvr-es/config/cmvr_es_ume.pb.txt
|
||||
- `ti5_motors`、`right_arm` 默认关闭;
|
||||
- `ArmTeleop` 服务后端默认关闭,模型哈希必须由部署配置明确给出;
|
||||
- 当前 `MotorRobotArm::servoJ()` 仍是逐关节顺序写,不满足遥操作组伺服能力门;
|
||||
- 启动 gRPC server 不代表允许遥操作执行,也不能绕过设备层硬件门。
|
||||
|
||||
# 人形机械臂从端(源码配置)
|
||||
./output/bin/cmvr_es \
|
||||
--config ./cmvr-es/config/cmvr_es_robot.pb.txt
|
||||
部署时应把完整配置树分别复制到两台机器的外部目录,并继续使用相同的标准文件名:
|
||||
|
||||
```text
|
||||
/etc/cmvr-es/ume/cmvr_es.pb.txt
|
||||
/etc/cmvr-es/robot/cmvr_es.pb.txt
|
||||
```
|
||||
|
||||
如果使用安装后的配置副本,则相应命令为:
|
||||
两套根配置都继续引用各自目录下同名的
|
||||
`manager/device_manager.pb.txt` 和 `manager/task_manager.pb.txt`。运行命令为:
|
||||
|
||||
```bash
|
||||
./output/bin/cmvr_es --config ./output/bin/config/cmvr_es_ume.pb.txt
|
||||
./output/bin/cmvr_es --config ./output/bin/config/cmvr_es_robot.pb.txt
|
||||
./output/bin/cmvr_es --config /etc/cmvr-es/ume/cmvr_es.pb.txt
|
||||
./output/bin/cmvr_es --config /etc/cmvr-es/robot/cmvr_es.pb.txt
|
||||
```
|
||||
|
||||
上线前应把两套配置分别复制到两台机器的外部配置目录。主端需要填写从端地址、
|
||||
会话 manifest 和认证配置;从端需要换成现场机械臂设备配置,并在真实硬件测试后
|
||||
逐层开启。不要把生产 IP、token、私钥或设备标定值提交到仓库样例。
|
||||
UME 主端需要填写从端地址、会话 manifest 和认证配置;机器人从端需要填写现场
|
||||
机械臂配置。不要把生产 IP、token、私钥或设备标定值提交到仓库默认配置。
|
||||
|
||||
## 生产配置
|
||||
|
||||
|
||||
@ -1,11 +0,0 @@
|
||||
# Follower robot-side CMVR-ES profile.
|
||||
#
|
||||
# The RobotArm ArmTeleop backend is implemented but explicitly disabled. The
|
||||
# physical arm and service backend remain closed. Current MotorRobotArm
|
||||
# sequential joint writes are rejected as a teleop group-servo capability until
|
||||
# an atomic/timed group primitive and its safety timing gates are accepted.
|
||||
cmvr_es {
|
||||
logger_config_file: "logger/logger.pb.txt"
|
||||
device_manager_config_file: "manager/device_manager_robot.pb.txt"
|
||||
task_manager_config_file: "manager/task_manager_robot.pb.txt"
|
||||
}
|
||||
@ -1,10 +0,0 @@
|
||||
# UME leader-side CMVR-ES profile.
|
||||
#
|
||||
# All relative paths below are resolved from this file's directory. This
|
||||
# checked-in profile contains no production endpoint, credentials or hardware
|
||||
# enablement.
|
||||
cmvr_es {
|
||||
logger_config_file: "logger/logger.pb.txt"
|
||||
device_manager_config_file: "manager/device_manager_ume.pb.txt"
|
||||
task_manager_config_file: "manager/task_manager_ume.pb.txt"
|
||||
}
|
||||
@ -1,24 +0,0 @@
|
||||
# Follower robot-side devices.
|
||||
device_manager {
|
||||
name: "cmvr_es_robot"
|
||||
version: "0.1"
|
||||
description: "CMVR humanoid follower edge system"
|
||||
init_all_motors_when_no_active_joints: false
|
||||
|
||||
devices {
|
||||
id: "ti5_motors"
|
||||
type: DEVICE_TYPE_MOTOR_SYSTEM
|
||||
config_file: "devices/motor/ti5_motors.pb.txt"
|
||||
# Physical motor communication remains fail-closed in this example.
|
||||
enable: false
|
||||
}
|
||||
|
||||
devices {
|
||||
id: "right_arm"
|
||||
type: DEVICE_TYPE_ROBOT_ARM
|
||||
config_file: "devices/arm/arm.pb.txt"
|
||||
# Do not enable until the motor system, URDF, limits, servoJ timing and
|
||||
# independent emergency-stop path have passed the robot safety checkout.
|
||||
enable: false
|
||||
}
|
||||
}
|
||||
@ -1,24 +0,0 @@
|
||||
# UME leader-side devices only.
|
||||
device_manager {
|
||||
name: "cmvr_es_ume"
|
||||
version: "0.1"
|
||||
description: "UME leader edge system"
|
||||
init_all_motors_when_no_active_joints: false
|
||||
|
||||
devices {
|
||||
id: "ume_right"
|
||||
type: DEVICE_TYPE_ROBOT_ARM
|
||||
config_file: "devices/arm/ume_arms.pb.txt"
|
||||
# Hardware gate 1/2. Gate 2/2 is ume.hardware_enabled in the arm config.
|
||||
# Keep both false until CAN mapping, limits and physical safety are verified.
|
||||
enable: false
|
||||
}
|
||||
|
||||
devices {
|
||||
id: "ume_left"
|
||||
type: DEVICE_TYPE_ROBOT_ARM
|
||||
config_file: "devices/arm/ume_arms.pb.txt"
|
||||
# Hardware gate 1/2. Gate 2/2 is ume.hardware_enabled in the arm config.
|
||||
enable: false
|
||||
}
|
||||
}
|
||||
@ -1,14 +0,0 @@
|
||||
# Follower robot-side tasks.
|
||||
task_manager {
|
||||
tasks {
|
||||
id: "grpc_server"
|
||||
type: TASK_TYPE_GRPC_SERVER
|
||||
run_mode: TASK_RUN_MODE_BLOCKING_SERVICE
|
||||
config_file: "tasks/grpc_server_task/grpc_server_task.pb.txt"
|
||||
# The generic gRPC server may be enabled for integration. This does not
|
||||
# enable a physical arm: device entries and the implemented RobotArm
|
||||
# ArmTeleop adapter are explicitly disabled. Current MotorRobotArm
|
||||
# sequential joint dispatch also fails the group-servo capability gate.
|
||||
enable: true
|
||||
}
|
||||
}
|
||||
@ -1,12 +0,0 @@
|
||||
# UME leader-side tasks.
|
||||
task_manager {
|
||||
tasks {
|
||||
id: "ume_teleop"
|
||||
type: TASK_TYPE_UME_TELEOP
|
||||
run_mode: TASK_RUN_MODE_BLOCKING_SERVICE
|
||||
config_file: "tasks/ume_teleop_task/ume_teleop_task.pb.txt"
|
||||
# Fail-closed: configure the follower endpoint, expected manifest and
|
||||
# transport security before enabling outbound teleoperation.
|
||||
enable: false
|
||||
}
|
||||
}
|
||||
@ -37,12 +37,12 @@ config/cmvr_es.pb.txt
|
||||
| --- | --- | --- | --- |
|
||||
| Camera | [`camera/abstract_camera.h`](camera/abstract_camera.h) | [`camera/camera_factory.h`](camera/camera_factory.h) | UVC、RealSense、Hikvision |
|
||||
| AGV | [`agv/abstract_agv.h`](agv/abstract_agv.h) | [`agv/agv_factory.h`](agv/agv_factory.h) | MyAgv、SRC1100 |
|
||||
| RobotArm | [`arm/robot_arm.h`](arm/robot_arm.h) | [`arm/robot_arm_factory.h`](arm/robot_arm_factory.h) | MotorRobotArm、AUBO、Huayan |
|
||||
| RobotArm | [`arm/robot_arm.h`](arm/robot_arm.h) | [`arm/robot_arm_factory.h`](arm/robot_arm_factory.h) | MotorRobotArm、[AUBO](arm/aubo_arm/README.md)、Huayan、UME |
|
||||
| DexHand | [`dexhand/abstract_dexhand.h`](dexhand/abstract_dexhand.h) | [`dexhand/dexhand_factory.h`](dexhand/dexhand_factory.h) | RH56DFTP、PX6AXGen3 |
|
||||
| Microphone | [`microphone/abstract_microphone.h`](microphone/abstract_microphone.h) | [`microphone/microphone_factory.h`](microphone/microphone_factory.h) | FFmpeg |
|
||||
| Speaker | [`speaker/abstract_speaker.h`](speaker/abstract_speaker.h) | [`speaker/speaker_factory.h`](speaker/speaker_factory.h) | FFmpeg |
|
||||
| BioHead | [`biohead/abstract_biohead.h`](biohead/abstract_biohead.h) | DeviceFactory 直接创建 | BioHeadRobot |
|
||||
| MotorSystem | `motor/motor_system/` | DeviceFactory 直接创建 | CAN/MuJoCo motor group |
|
||||
| MotorSystem | [`motor/`](motor/README.md) | DeviceFactory 直接创建 | CAN、MuJoCo、EtherCAT、Modbus TCP PLC |
|
||||
|
||||
代码目录存在不等于已经接入配置创建链:
|
||||
|
||||
|
||||
124
cmvr-es/devices/arm/aubo_arm/README.md
Normal file
124
cmvr-es/devices/arm/aubo_arm/README.md
Normal file
@ -0,0 +1,124 @@
|
||||
# AUBO RobotArm 与控制柜 IO
|
||||
|
||||
`AuboArm` 是 AUBO SDK v0.27.1 的 `RobotArm` 后端。控制柜 Standard 数字 IO
|
||||
通过设备通用的 `executeJsonCommand` 接口访问,远程调用复用
|
||||
`cmvr.api.SystemService/ExecuteJsonCommand`,不经过 `ArmService` 或
|
||||
`MotorService`。
|
||||
|
||||
返回 [Devices 模块指南](../../README.md) 或 [项目总览](../../../../README.md)。
|
||||
|
||||
## 代码与配置
|
||||
|
||||
- 实现:[`aubo_arm.h`](aubo_arm.h)、[`aubo_arm.cpp`](aubo_arm.cpp)
|
||||
- 测试:[`tests/aubo_arm_json_command_test.cpp`](tests/aubo_arm_json_command_test.cpp)
|
||||
- 设备配置:[`../../../config/devices/arm/aubo_arm.pb.txt`](../../../config/devices/arm/aubo_arm.pb.txt)
|
||||
- DeviceManager 配置:
|
||||
[`../../../config/manager/device_manager.pb.txt`](../../../config/manager/device_manager.pb.txt)
|
||||
- SystemService 实现:
|
||||
[`../../../service/grpc/src/grpc_system_service.cpp`](../../../service/grpc/src/grpc_system_service.cpp)
|
||||
- Proto:[`../../../../protos/cmvr/api/system_service.proto`](../../../../protos/cmvr/api/system_service.proto)
|
||||
|
||||
仓库配置使用 SDK RPC 端口 `30004`。现场部署必须填写真实控制器地址和凭据,
|
||||
不要把生产密码提交到默认配置。
|
||||
|
||||
## 控制柜 Standard 数字 IO
|
||||
|
||||
当前支持:
|
||||
|
||||
| `operation` | 说明 | 必填字段 |
|
||||
| --- | --- | --- |
|
||||
| `get_di` | 读取控制柜数字输入 | `index` |
|
||||
| `get_do` | 读取控制柜数字输出及其 runstate | `index` |
|
||||
| `set_do` | 设置控制柜数字输出 | `index`、`value` |
|
||||
|
||||
JSON 命令:
|
||||
|
||||
```json
|
||||
{"command":"cabinet_io","operation":"get_di","index":0}
|
||||
{"command":"cabinet_io","operation":"get_do","index":0}
|
||||
{"command":"cabinet_io","operation":"set_do","index":0,"value":true}
|
||||
```
|
||||
|
||||
`index` 从 `0` 开始,运行时根据控制器返回的 IO 数量检查范围。
|
||||
`set_do.value` 必须是 JSON 布尔值 `true` 或 `false`,不接受 `0/1` 或字符串。
|
||||
`set_do` 成功响应中的 `requested_value` 只表示 SDK 已接受请求;确认实际输出时
|
||||
必须再调用 `get_do`。
|
||||
|
||||
读取成功响应示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"command": "cabinet_io",
|
||||
"operation": "get_di",
|
||||
"index": 0,
|
||||
"count": 16,
|
||||
"value": false
|
||||
}
|
||||
```
|
||||
|
||||
## 通过 gRPC 调用
|
||||
|
||||
默认 gRPC 端口为 `50052`。读取 DI0:
|
||||
|
||||
```shell
|
||||
grpcurl -plaintext \
|
||||
-d '{
|
||||
"header":{"deviceId":"aubo_arm"},
|
||||
"requestJson":"{\"command\":\"cabinet_io\",\"operation\":\"get_di\",\"index\":0}"
|
||||
}' \
|
||||
127.0.0.1:50052 \
|
||||
cmvr.api.SystemService/ExecuteJsonCommand
|
||||
```
|
||||
|
||||
设置 DO0 为高电平:
|
||||
|
||||
```shell
|
||||
grpcurl -plaintext \
|
||||
-d '{
|
||||
"header":{"deviceId":"aubo_arm"},
|
||||
"requestJson":"{\"command\":\"cabinet_io\",\"operation\":\"set_do\",\"index\":0,\"value\":true}"
|
||||
}' \
|
||||
127.0.0.1:50052 \
|
||||
cmvr.api.SystemService/ExecuteJsonCommand
|
||||
```
|
||||
|
||||
使用源码默认配置时:
|
||||
|
||||
1. 在 `cmvr-es/config/devices/arm/aubo_arm.pb.txt` 填写正确地址和登录信息;
|
||||
2. 在 `cmvr-es/config/manager/device_manager.pb.txt` 将 `aubo_arm.enable`
|
||||
改为 `true`;
|
||||
3. 重新安装配置并启动安装产物。
|
||||
|
||||
```shell
|
||||
cmake --install build
|
||||
./output/bin/cmvr_es
|
||||
```
|
||||
|
||||
`output/bin/cmvr_es` 默认读取 `output/bin/config/`。使用 `--config` 时,应修改
|
||||
对应外部配置根。设备未启用或初始化失败时,gRPC 返回
|
||||
`Device not found: aubo_arm`。
|
||||
|
||||
## 安全与语义边界
|
||||
|
||||
- 只访问控制柜 Standard 数字 IO,不访问工具端 IO、可配置 IO 或安全 IO;
|
||||
- `set_do` 不修改输出 runstate;
|
||||
- 只有 `StandardOutputRunState::None` 的通道允许写入,否则返回
|
||||
`output_managed_by_runstate`;
|
||||
- 普通访问不会调用会重置全部输出配置的
|
||||
`setDigitalOutputRunstateDefault()`;
|
||||
- 模拟量 IO 涉及 domain、单位和量程,当前 JSON 接口不开放;
|
||||
- gRPC/JSON 返回成功不代表目标 IO 具备功能安全等级;
|
||||
- 真实写测试前应确认通道用途、负载、电气隔离、默认电平和控制器程序所有权。
|
||||
|
||||
## 测试
|
||||
|
||||
```bash
|
||||
cmake --build build --target aubo_arm_json_command_test -j4
|
||||
ctest --test-dir build \
|
||||
-R '^aubo_arm_json_command_test$' \
|
||||
--output-on-failure
|
||||
```
|
||||
|
||||
该测试覆盖 JSON 校验和无硬件错误路径,不代表已在真实 AUBO 控制柜完成 DI/DO
|
||||
读取、写入或 runstate 拒绝验证。
|
||||
82
cmvr-es/devices/motor/README.md
Normal file
82
cmvr-es/devices/motor/README.md
Normal file
@ -0,0 +1,82 @@
|
||||
# Motor 设备模块
|
||||
|
||||
`devices/motor/` 提供电机管理、协议适配、总线 runtime 和厂商驱动。Service、
|
||||
RobotArm 和业务 Task 只依赖 `MotorManager`/`AbstractMotor` 的稳定接口,不应
|
||||
直接访问 libmodbus、CAN、EtherCAT 或厂商 SDK。
|
||||
|
||||
返回 [Devices 模块指南](../README.md) 或 [项目总览](../../../README.md)。
|
||||
|
||||
## 目录职责
|
||||
|
||||
| 目录 | 职责 |
|
||||
| --- | --- |
|
||||
| `manager/` | 创建 MotorGroup,按 `motor_id`/`joint_name` 暴露 `AbstractMotor` |
|
||||
| `bus_runtime/` | 连接、收发、重连、watchdog 和总线生命周期 |
|
||||
| `drivers/` | CANopen、EtherCAT、MuJoCo、Modbus PLC 等具体后端 |
|
||||
| `drivers/modbus_plc_motor/` | 关节限位、SI 单位和 CMVR PLC v1 命令映射 |
|
||||
|
||||
PLC 电机链路为:
|
||||
|
||||
```text
|
||||
gRPC MotorService
|
||||
|
|
||||
v
|
||||
MotorManager -> AbstractMotor
|
||||
|
|
||||
v
|
||||
CmvrPlcMotorProtocol
|
||||
|
|
||||
v
|
||||
ModbusTcpMotorBusRuntime
|
||||
|
|
||||
v
|
||||
libmodbus -> PLC -> 驱动器/电机
|
||||
```
|
||||
|
||||
各层边界:
|
||||
|
||||
- `MotorService` 负责 API 校验、单电机控制权、deadline/cancellation 和
|
||||
fail-closed Quick Stop;
|
||||
- `MotorManager` 负责电机查找与统一抽象;
|
||||
- `CmvrPlcMotorProtocol` 负责关节限位、SI 单位和 CMVR PLC v1 命令映射;
|
||||
- `ModbusTcpMotorBusRuntime` 负责 PLC session、mailbox、ACK、状态和重连;
|
||||
- PLC/驱动器必须独立实现通信 watchdog、周期 watchdog 和硬件安全动作。
|
||||
|
||||
## Modbus TCP PLC
|
||||
|
||||
实现、配置、依赖和测试入口见:
|
||||
|
||||
- [Modbus TCP runtime README](bus_runtime/modbus_tcp/README.md)
|
||||
- [完整 MotorService/CMVR PLC v1 协议](../../../docs/motor_service_modbus_tcp.md)
|
||||
- [MotorService 文档](../../service/README.md#motorservice)
|
||||
- [`plc_motors.pb.txt`](../../config/devices/motor/plc_motors.pb.txt)
|
||||
|
||||
当前 Modbus 后端只提供 x86-64 的 libmodbus 3.1.11。ARM 目录没有对应库,
|
||||
不能把 x86 ELF 复制到 ARM 设备使用。
|
||||
|
||||
## 安全边界
|
||||
|
||||
- MotorService 是单轴 API,不提供多轴同扫描周期的原子 commit;
|
||||
- PLC/Modbus 的 Profile 或 cyclic 能力不能直接当成毫秒级机械臂组伺服;
|
||||
- 软件 `emergencyStop`、Quick Stop 和普通 PLC 输出都不是安全急停;
|
||||
- 真实设备必须具有独立的硬接线急停、安全继电器或 F-CPU/F-I/O,以及驱动器
|
||||
STO 等经风险评估确定的安全链;
|
||||
- 新硬件配置保持 `enable: false`,完成方向、限位、watchdog 和故障注入验证后
|
||||
才能启用。
|
||||
|
||||
## 测试
|
||||
|
||||
```bash
|
||||
cmake --build build --target \
|
||||
modbus_tcp_motor_bus_runtime_test \
|
||||
grpc_motor_service_test \
|
||||
grpc_motor_service_modbus_e2e_test \
|
||||
-j4
|
||||
|
||||
ctest --test-dir build \
|
||||
-R '^(modbus_tcp_motor_bus_runtime_test|grpc_motor_service_test|grpc_motor_service_modbus_e2e_test)$' \
|
||||
--output-on-failure
|
||||
```
|
||||
|
||||
端到端 fake PLC 测试需要本地 TCP bind/listen 权限。软件测试不能代替真实
|
||||
S7-1215C、驱动器、STO 和断网故障台架。
|
||||
93
cmvr-es/devices/motor/bus_runtime/modbus_tcp/README.md
Normal file
93
cmvr-es/devices/motor/bus_runtime/modbus_tcp/README.md
Normal file
@ -0,0 +1,93 @@
|
||||
# Modbus TCP PLC Runtime
|
||||
|
||||
本目录实现 CMVR PLC v1 的 Modbus TCP 总线 runtime。它负责 PLC 连接、身份
|
||||
握手、session、心跳、重连、命令 mailbox、ACK 轮询和状态快照,不负责 gRPC
|
||||
请求解析,也不提供功能安全急停。
|
||||
|
||||
返回 [Motor 设备模块](../../README.md) 或 [Devices 模块指南](../../../README.md)。
|
||||
|
||||
## 代码与配置
|
||||
|
||||
- [`include/modbus_tcp_client.h`](include/modbus_tcp_client.h):有界超时的
|
||||
libmodbus client
|
||||
- [`include/modbus_tcp_motor_bus_runtime.h`](include/modbus_tcp_motor_bus_runtime.h):
|
||||
连接 supervisor、命令和状态 runtime
|
||||
- [`include/cmvr_plc_register_map.h`](include/cmvr_plc_register_map.h):
|
||||
CMVR PLC v1 寄存器常量
|
||||
- [`src/modbus_tcp_client.cpp`](src/modbus_tcp_client.cpp)
|
||||
- [`src/modbus_tcp_motor_bus_runtime.cpp`](src/modbus_tcp_motor_bus_runtime.cpp)
|
||||
- [`tests/modbus_tcp_motor_bus_runtime_test.cpp`](tests/modbus_tcp_motor_bus_runtime_test.cpp)
|
||||
- [`../../../../config/devices/motor/plc_motors.pb.txt`](../../../../config/devices/motor/plc_motors.pb.txt)
|
||||
|
||||
完整寄存器表、TIA Portal 数据块、gRPC 语义和台架步骤由
|
||||
[MotorService 与 CMVR PLC v1 完整协议](../../../../../docs/motor_service_modbus_tcp.md)
|
||||
统一维护。
|
||||
|
||||
## 连接与协议约束
|
||||
|
||||
- `host` 必须是 IPv4 字面量,避免 DNS 让建连或停止出现无界等待;
|
||||
- PLC boot ID 必须非零且每次 PLC 重启变化;
|
||||
- owner 决策和命令 ACK 必须回显当前 session,旧 session 的 mailbox 不得执行;
|
||||
- runtime `start()` 启动连接 supervisor,PLC 可以在进程启动时离线;
|
||||
- 离线期间状态不可用,运动命令必须在写 mailbox 前失败;
|
||||
- 重连必须重新完成身份、版本、boot ID 和 session 握手,不得重放旧命令;
|
||||
- 状态区按 odd/even seqlock 发布,CMVR 使用
|
||||
sequence-before → 64-word block → sequence-after 三段读取;
|
||||
- payload 必须先完整写入,commit sequence 最后写入,PLC 只原子消费新的
|
||||
commit;
|
||||
- Quick Stop、Disable、故障和通信 watchdog 的状态必须通过当前 session
|
||||
的 ACK/状态确认,不能把本地写成功解释为驱动器已经安全停止。
|
||||
|
||||
## Cyclic stream
|
||||
|
||||
每次 `OpenCyclicPosition/Velocity` 都创建新的轴级 stream epoch。PLC 必须在
|
||||
同一个原子状态事务中:
|
||||
|
||||
1. 清零 `last_applied_cyclic_sequence`;
|
||||
2. 清理旧样本去重状态;
|
||||
3. 重置 cyclic watchdog;
|
||||
4. 设置正确的 CSP/CSV mode;
|
||||
5. 发布 `StreamActive=1` 后再 ACK。
|
||||
|
||||
重开后的首个样本序列从 `1` 开始,必须重新应用。活动 cyclic 流跨
|
||||
`connection_epoch` 后不会自动重开;旧流的当前和后续 setpoint 都被拒绝,
|
||||
Quick Stop 后客户端必须建立新的 gRPC 流。断链前或断链期间 pending 的
|
||||
setpoint 不得进入新 session。
|
||||
|
||||
## 依赖与平台
|
||||
|
||||
x86-64 的 libmodbus 3.1.11 位于:
|
||||
|
||||
```text
|
||||
dependency/x86/third_party/modbus/3.1.11
|
||||
```
|
||||
|
||||
`dependency/arm/third_party/` 当前没有对应 libmodbus,因此 ARM 构建不支持
|
||||
该后端。支持 ARM 前必须为目标 ABI 单独编译并验证库,不能复用 x86 二进制。
|
||||
|
||||
## 安全边界
|
||||
|
||||
标准 S7-1215C DC/DC/DC 不是 failsafe PLC。Modbus Quick Stop、
|
||||
MotorService `emergencyStop`、普通 OB/FB 和普通数字输出都只是功能性控制,
|
||||
不能替代:
|
||||
|
||||
- 硬接线急停;
|
||||
- 安全继电器或 F-CPU/F-I/O;
|
||||
- 驱动器双通道 STO;
|
||||
- 接触器、抱闸反馈与必要的 EDM。
|
||||
|
||||
PLC 侧通信 watchdog 和 cyclic watchdog 必须在没有 CMVR 进程参与时独立停止
|
||||
危险运动。真实启用前必须在禁能或脱载轴上验证寄存器、方向、限位、断网、PLC
|
||||
重启、交换机故障和 Quick Stop 失败。
|
||||
|
||||
## 测试
|
||||
|
||||
```bash
|
||||
cmake --build build --target modbus_tcp_motor_bus_runtime_test -j4
|
||||
ctest --test-dir build \
|
||||
-R '^modbus_tcp_motor_bus_runtime_test$' \
|
||||
--output-on-failure
|
||||
```
|
||||
|
||||
fake PLC 测试需要本地 TCP bind/listen 权限。测试通过只证明软件协议和故障注入
|
||||
路径,不代表真实 PLC、驱动器或硬件安全链已经验收。
|
||||
@ -21,6 +21,42 @@ gRPC 和 QUIC 的职责边界:
|
||||
- 实时音视频使用 QUIC DATAGRAM;
|
||||
- `quic_edge/` 不是平台 Gateway,也不是浏览器服务器。
|
||||
|
||||
## MotorService
|
||||
|
||||
`MotorService` 将 gRPC 电机命令适配到已经由 `DeviceManager` 创建的
|
||||
`MotorManager` 和 `AbstractMotor`,不直接持有 PLC、现场总线或厂商驱动。
|
||||
|
||||
关键文件:
|
||||
|
||||
- Proto:[`../../protos/cmvr/api/motor_service.proto`](../../protos/cmvr/api/motor_service.proto)
|
||||
和 [`../../protos/cmvr/api/motor_command.proto`](../../protos/cmvr/api/motor_command.proto)
|
||||
- 实现:[`grpc/include/grpc_motor_service.h`](grpc/include/grpc_motor_service.h)
|
||||
和 [`grpc/src/grpc_motor_service.cpp`](grpc/src/grpc_motor_service.cpp)
|
||||
- 注册:[`../task/grpc_server_task/src/grpc_server_task.cpp`](../task/grpc_server_task/src/grpc_server_task.cpp)
|
||||
- 单元测试:[`grpc/tests/grpc_motor_service_test.cpp`](grpc/tests/grpc_motor_service_test.cpp)
|
||||
- gRPC–Modbus 端到端测试:
|
||||
[`grpc/tests/grpc_motor_service_modbus_e2e_test.cpp`](grpc/tests/grpc_motor_service_modbus_e2e_test.cpp)
|
||||
|
||||
服务按单电机仲裁。同步 Profile 命令、Cyclic Position/Velocity 双向流、
|
||||
`setEnabled`、状态读取和软件 `emergencyStop` 共用同一控制权状态:
|
||||
|
||||
- 同一电机已有 owner 时拒绝新的控制调用;
|
||||
- cyclic 流首帧必须是 `open`,后续 setpoint sequence 必须严格递增;
|
||||
- reader 使用 latest-wins 邮箱,客户端必须持续并发读取反馈;
|
||||
- 取消、deadline、watchdog、非法帧、后端拒绝或写失败都会触发 Quick Stop;
|
||||
- 任何清理 Quick Stop 未确认时,服务进入 fail-closed 锁存;
|
||||
- 只有成功执行 `setEnabled(true)` 才解除服务内软件急停锁存;
|
||||
- 服务层 Quick Stop 和 `emergencyStop` 都不具备功能安全等级。
|
||||
|
||||
PLC 后端的连接 epoch、stream epoch、寄存器、ACK 和 TIA Portal 要求见:
|
||||
|
||||
- [Modbus TCP PLC runtime](../devices/motor/bus_runtime/modbus_tcp/README.md)
|
||||
- [MotorService 与 CMVR PLC v1 完整协议](../../docs/motor_service_modbus_tcp.md)
|
||||
|
||||
AUBO 控制柜 IO 不经过 `MotorService` 或 `ArmService`,而是复用
|
||||
`SystemService/ExecuteJsonCommand`。厂商命令和安全约束见
|
||||
[AUBO 控制柜 IO](../devices/arm/aubo_arm/README.md)。
|
||||
|
||||
## 新增 gRPC Service
|
||||
|
||||
当前没有动态 service registry,必须完成以下全部步骤。
|
||||
|
||||
Loading…
Reference in New Issue
Block a user