453 lines
14 KiB
Markdown
453 lines
14 KiB
Markdown
|
# 换机器人接口文档
|
|||
|
|
|||
|
本文档描述了VWED系统换机器人功能的API接口,用于在任务执行过程中动态更换执行机器人。
|
|||
|
|
|||
|
## 基础信息
|
|||
|
|
|||
|
- 基础路径:`/api/vwed-task-record`
|
|||
|
- 接口标签:`VWED任务运行记录`
|
|||
|
- 版本:v1.0
|
|||
|
|
|||
|
## 功能概述
|
|||
|
|
|||
|
换机器人功能允许在任务执行过程中更换执行机器人,主要用于以下场景:
|
|||
|
|
|||
|
1. **机器人故障**:当前执行机器人出现硬件或软件故障
|
|||
|
2. **电量不足**:当前机器人电量过低,需要更换到电量充足的机器人
|
|||
|
3. **性能优化**:根据实际情况选择更合适的机器人执行任务
|
|||
|
4. **负载均衡**:优化机器人资源分配,提高系统整体效率
|
|||
|
|
|||
|
该功能支持两种场景:
|
|||
|
- **未载货场景**:机器人尚未携带货物,从原任务中自动提取参数
|
|||
|
- **已载货场景**:机器人已经携带货物,需要指定目标库位和执行动作
|
|||
|
|
|||
|
## 接口清单
|
|||
|
|
|||
|
| 序号 | 接口名称 | 接口路径 | 请求方式 | 接口描述 |
|
|||
|
| --- | --- | --- | --- | --- |
|
|||
|
| 1 | 换机器人 | `/switch-robot/{task_record_id}` | POST | 动态更换任务执行机器人 |
|
|||
|
|
|||
|
---
|
|||
|
|
|||
|
## 接口详情
|
|||
|
|
|||
|
### 1. 换机器人
|
|||
|
|
|||
|
#### 接口说明
|
|||
|
|
|||
|
在任务执行过程中动态更换执行机器人。系统会终止当前任务的所有待执行块,动态添加新的任务块(选择机器人 → 获取库位 → 执行通用动作),并通过调度器实时生效,保持任务连续运行。
|
|||
|
|
|||
|
**核心特性**:
|
|||
|
- ✅ 支持未载货和已载货两种场景
|
|||
|
- ✅ 智能参数提取(未载货时从原任务自动提取)
|
|||
|
- ✅ 实时生效(无需重启任务)
|
|||
|
- ✅ 保持任务ID不变
|
|||
|
- ✅ 完整的操作日志记录
|
|||
|
|
|||
|
#### 请求路径
|
|||
|
|
|||
|
```
|
|||
|
POST /api/vwed-task-record/switch-robot/{task_record_id}
|
|||
|
```
|
|||
|
|
|||
|
#### 路径参数
|
|||
|
|
|||
|
| 参数名 | 类型 | 是否必须 | 描述 |
|
|||
|
| --- | --- | --- | --- |
|
|||
|
| task_record_id | string | 是 | 任务记录ID,必须是正在运行中的任务 |
|
|||
|
|
|||
|
#### 请求头
|
|||
|
|
|||
|
| 参数名 | 类型 | 是否必须 | 描述 |
|
|||
|
| --- | --- | --- | --- |
|
|||
|
| Content-Type | string | 是 | application/json |
|
|||
|
| x-access-token | string | 否 | 系统任务令牌,用于主系统认证 |
|
|||
|
|
|||
|
#### 请求体参数
|
|||
|
|
|||
|
| 参数名 | 类型 | 是否必须 | 描述 |
|
|||
|
| --- | --- | --- | --- |
|
|||
|
| robot_name | string | 否 | 机器人名称(如:AGV_001) |
|
|||
|
| robot_group | string | 否 | 机器人组(如:group_A) |
|
|||
|
| robot_label_group | string | 否 | 机器人标签组(如:label_1) |
|
|||
|
| switch_reason | string | 是 | 更换原因(如:机器人电量不足、机器人故障等) |
|
|||
|
| has_cargo | boolean | 是 | 是否载货,true-已载货,false-未载货 |
|
|||
|
| site_id | string | 条件必填 | 库位ID(已载货时必填,如:AP540) |
|
|||
|
| action | string | 条件必填 | 执行动作(已载货时必填,如:pick、drop) |
|
|||
|
|
|||
|
**参数说明**:
|
|||
|
- `robot_name`、`robot_group`、`robot_label_group` 至少提供一个,用于选择新的机器人
|
|||
|
- 当 `has_cargo=true` 时,`site_id` 和 `action` 为必填项
|
|||
|
- 当 `has_cargo=false` 时,系统会从原任务定义中自动提取 `site_id` 和 `action`
|
|||
|
|
|||
|
#### 响应结果
|
|||
|
|
|||
|
**成功响应**:
|
|||
|
|
|||
|
```json
|
|||
|
{
|
|||
|
"code": 200,
|
|||
|
"message": "换机器人成功(未载货场景)",
|
|||
|
"data": {
|
|||
|
"task_record_id": "550e8400-e29b-41d4-a716-446655440000",
|
|||
|
"switch_reason": "机器人AGV_001电量不足",
|
|||
|
"has_cargo": false,
|
|||
|
"robot_name": "AGV_002",
|
|||
|
"robot_group": "group_A",
|
|||
|
"robot_label_group": "label_1",
|
|||
|
"site_id": "AP154",
|
|||
|
"action": "pick",
|
|||
|
"key_route": "LM532",
|
|||
|
"added_blocks": 1
|
|||
|
}
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
**失败响应**:
|
|||
|
|
|||
|
1. 任务记录不存在:
|
|||
|
```json
|
|||
|
{
|
|||
|
"code": 404,
|
|||
|
"message": "未找到任务记录 {task_record_id}"
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
2. 任务状态错误:
|
|||
|
```json
|
|||
|
{
|
|||
|
"code": 400,
|
|||
|
"message": "任务状态为 {status},只能对运行中的任务换机器人"
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
3. 任务定义格式错误:
|
|||
|
```json
|
|||
|
{
|
|||
|
"code": 400,
|
|||
|
"message": "任务定义格式不正确"
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
4. 已载货场景参数不足:
|
|||
|
```json
|
|||
|
{
|
|||
|
"code": 400,
|
|||
|
"message": "已载货场景需要提供库位ID和执行动作"
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
5. 系统异常:
|
|||
|
```json
|
|||
|
{
|
|||
|
"code": 500,
|
|||
|
"message": "换机器人失败: {错误详情}"
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
#### 响应字段说明
|
|||
|
|
|||
|
| 字段名 | 类型 | 描述 |
|
|||
|
| --- | --- | --- |
|
|||
|
| task_record_id | string | 任务记录ID |
|
|||
|
| switch_reason | string | 更换原因 |
|
|||
|
| has_cargo | boolean | 是否载货 |
|
|||
|
| robot_name | string | 新机器人名称 |
|
|||
|
| robot_group | string | 新机器人组 |
|
|||
|
| robot_label_group | string | 新机器人标签组 |
|
|||
|
| site_id | string | 目标库位ID |
|
|||
|
| action | string | 执行动作(pick/drop/其他) |
|
|||
|
| key_route | string | 关键路径(从原任务提取或使用site_id) |
|
|||
|
| added_blocks | integer | 添加的新任务块数量(固定为1,包含3个子块) |
|
|||
|
|
|||
|
---
|
|||
|
|
|||
|
## 使用场景和示例
|
|||
|
|
|||
|
### 场景1:未载货 - 机器人电量不足
|
|||
|
|
|||
|
**业务场景**:
|
|||
|
机器人AGV_001正在前往取货点的途中,尚未取货,系统检测到其电量不足,需要更换为电量充足的AGV_002继续执行任务。
|
|||
|
|
|||
|
**请求示例**:
|
|||
|
|
|||
|
```bash
|
|||
|
curl -X POST "http://localhost:8000/api/vwed-task-record/switch-robot/550e8400-e29b-41d4-a716-446655440000" \
|
|||
|
-H "Content-Type: application/json" \
|
|||
|
-H "x-access-token: your-token-here" \
|
|||
|
-d '{
|
|||
|
"robot_name": "AGV_002",
|
|||
|
"robot_group": "group_A",
|
|||
|
"robot_label_group": "label_1",
|
|||
|
"switch_reason": "机器人AGV_001电量不足,更换为AGV_002",
|
|||
|
"has_cargo": false
|
|||
|
}'
|
|||
|
```
|
|||
|
|
|||
|
**响应示例**:
|
|||
|
|
|||
|
```json
|
|||
|
{
|
|||
|
"code": 200,
|
|||
|
"message": "换机器人成功(未载货场景)",
|
|||
|
"data": {
|
|||
|
"task_record_id": "550e8400-e29b-41d4-a716-446655440000",
|
|||
|
"switch_reason": "机器人AGV_001电量不足,更换为AGV_002",
|
|||
|
"has_cargo": false,
|
|||
|
"robot_name": "AGV_002",
|
|||
|
"robot_group": "group_A",
|
|||
|
"robot_label_group": "label_1",
|
|||
|
"site_id": "AP154",
|
|||
|
"action": "pick",
|
|||
|
"key_route": "LM532",
|
|||
|
"added_blocks": 1
|
|||
|
}
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
**系统行为**:
|
|||
|
1. 终止当前任务的所有待执行块
|
|||
|
2. 从原任务定义中自动提取:
|
|||
|
- `site_id`: "AP154"(目标取货点)
|
|||
|
- `action`: "pick"(取货动作)
|
|||
|
- `key_route`: "LM532"(关键路径)
|
|||
|
3. 添加3个新任务块:
|
|||
|
- 选择机器人块:选择AGV_002
|
|||
|
- 获取库位块:获取AP154库位信息
|
|||
|
- 执行通用动作块:执行pick动作
|
|||
|
4. 更新任务定义并通过调度器实时生效
|
|||
|
5. AGV_002继续执行原任务的剩余步骤
|
|||
|
|
|||
|
---
|
|||
|
|
|||
|
### 场景2:已载货 - 机器人故障需要转运
|
|||
|
|
|||
|
**业务场景**:
|
|||
|
机器人AGV_001已经在AP154取货,正在前往目标放货点AP540的途中发生故障。需要将货物转运到临时库位AP300,然后更换为AGV_003继续执行任务。
|
|||
|
|
|||
|
**请求示例**:
|
|||
|
|
|||
|
```bash
|
|||
|
curl -X POST "http://localhost:8000/api/vwed-task-record/switch-robot/550e8400-e29b-41d4-a716-446655440000" \
|
|||
|
-H "Content-Type: application/json" \
|
|||
|
-H "x-access-token: your-token-here" \
|
|||
|
-d '{
|
|||
|
"robot_name": "AGV_003",
|
|||
|
"robot_group": "group_B",
|
|||
|
"switch_reason": "机器人AGV_001故障,货物转运至AP300后更换为AGV_003",
|
|||
|
"has_cargo": true,
|
|||
|
"site_id": "AP300",
|
|||
|
"action": "drop"
|
|||
|
}'
|
|||
|
```
|
|||
|
|
|||
|
**响应示例**:
|
|||
|
|
|||
|
```json
|
|||
|
{
|
|||
|
"code": 200,
|
|||
|
"message": "换机器人成功(已载货场景)",
|
|||
|
"data": {
|
|||
|
"task_record_id": "550e8400-e29b-41d4-a716-446655440000",
|
|||
|
"switch_reason": "机器人AGV_001故障,货物转运至AP300后更换为AGV_003",
|
|||
|
"has_cargo": true,
|
|||
|
"robot_name": "AGV_003",
|
|||
|
"robot_group": "group_B",
|
|||
|
"robot_label_group": null,
|
|||
|
"site_id": "AP300",
|
|||
|
"action": "drop",
|
|||
|
"key_route": "LM532",
|
|||
|
"added_blocks": 1
|
|||
|
}
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
**系统行为**:
|
|||
|
1. 终止当前任务的所有待执行块
|
|||
|
2. 使用请求参数:
|
|||
|
- `site_id`: "AP300"(临时转运点)
|
|||
|
- `action`: "drop"(放货动作)
|
|||
|
3. 添加3个新任务块:
|
|||
|
- 选择机器人块:选择AGV_003
|
|||
|
- 获取库位块:获取AP300库位信息
|
|||
|
- 执行通用动作块:执行drop动作
|
|||
|
4. 更新任务定义并通过调度器实时生效
|
|||
|
5. AGV_001将货物放到AP300后,AGV_003接管任务继续执行
|
|||
|
|
|||
|
---
|
|||
|
|
|||
|
## 技术实现说明
|
|||
|
|
|||
|
### 处理流程
|
|||
|
|
|||
|
```
|
|||
|
1. 接收换机器人请求
|
|||
|
↓
|
|||
|
2. 验证任务状态(必须是RUNNING)
|
|||
|
↓
|
|||
|
3. 解析任务定义
|
|||
|
↓
|
|||
|
4. 终止调度器中的当前任务
|
|||
|
↓
|
|||
|
5. 终止所有待执行的任务块
|
|||
|
↓
|
|||
|
6. 提取或使用参数
|
|||
|
├─ 未载货:从原任务提取 keyRoute, targetSiteLabel, action
|
|||
|
└─ 已载货:使用请求参数 site_id, action
|
|||
|
↓
|
|||
|
7. 构建3个新任务块
|
|||
|
├─ CSelectAgvBp:选择机器人块
|
|||
|
├─ GetIdleSiteBp:获取库位块
|
|||
|
└─ CAgvOperationBp:执行通用动作块
|
|||
|
↓
|
|||
|
8. 更新任务定义(追加新块到rootBlock)
|
|||
|
↓
|
|||
|
9. 更新数据库(task_def_detail, ended_reason)
|
|||
|
↓
|
|||
|
10. 通知调度器更新任务定义(实时生效)
|
|||
|
↓
|
|||
|
11. 返回换机器人结果
|
|||
|
```
|
|||
|
|
|||
|
### 核心数据结构
|
|||
|
|
|||
|
**添加的任务块结构**:
|
|||
|
|
|||
|
```json
|
|||
|
{
|
|||
|
"id": "new_block_id_1",
|
|||
|
"name": "switch_robot_xxx",
|
|||
|
"blockType": "CSelectAgvBp",
|
|||
|
"label": "选择执行机器人(换机器人)",
|
|||
|
"description": "换机器人: {switch_reason}",
|
|||
|
"inputParams": {
|
|||
|
"vehicle": {"value": "AGV_002", "type": "Simple", "required": false},
|
|||
|
"group": {"value": "group_A", "type": "Simple", "required": false},
|
|||
|
"label_group": {"value": "label_1", "type": "Simple", "required": false},
|
|||
|
"keyRoute": {"value": "LM532", "type": "Simple", "required": true}
|
|||
|
},
|
|||
|
"children": {
|
|||
|
"default": [
|
|||
|
{
|
|||
|
"id": "new_block_id_2",
|
|||
|
"name": "get_site_xxx",
|
|||
|
"blockType": "GetIdleSiteBp",
|
|||
|
"label": "获取库位(换机器人)",
|
|||
|
"inputParams": {
|
|||
|
"siteId": {"value": "AP154", "type": "Simple", "required": false},
|
|||
|
"locked": {"value": false, "type": "Simple", "required": true},
|
|||
|
"lock": {"value": true, "type": "Simple", "required": false}
|
|||
|
},
|
|||
|
"children": {}
|
|||
|
},
|
|||
|
{
|
|||
|
"id": "new_block_id_3",
|
|||
|
"name": "action_xxx",
|
|||
|
"blockType": "CAgvOperationBp",
|
|||
|
"label": "机器人通用动作(换机器人)",
|
|||
|
"inputParams": {
|
|||
|
"targetSiteLabel": {"value": "AP154", "type": "Simple", "required": true},
|
|||
|
"task": {"value": "pick", "type": "Simple", "required": false},
|
|||
|
"spin": {"value": "", "type": "Simple", "required": false}
|
|||
|
},
|
|||
|
"children": {}
|
|||
|
}
|
|||
|
]
|
|||
|
}
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
### 数据库变更
|
|||
|
|
|||
|
**任务记录表(vwed_taskrecord)**:
|
|||
|
- `task_def_detail`:更新为包含新任务块的定义
|
|||
|
- `ended_reason`:记录换机器人原因,格式:`换机器人(未载货/已载货): {switch_reason}`
|
|||
|
|
|||
|
**任务块记录表(vwed_blockrecord)**:
|
|||
|
- 所有未完成的块:
|
|||
|
- `status`:更新为 2002(CANCEL)
|
|||
|
- `ended_on`:记录终止时间
|
|||
|
- `ended_reason`:记录终止原因,格式:`换机器人终止: {switch_reason}`
|
|||
|
|
|||
|
---
|
|||
|
|
|||
|
## 注意事项和最佳实践
|
|||
|
|
|||
|
### 使用限制
|
|||
|
|
|||
|
1. **任务状态要求**:
|
|||
|
- 只能对状态为 `RUNNING`(1001)的任务执行换机器人操作
|
|||
|
- 已完成、失败、取消的任务无法换机器人
|
|||
|
|
|||
|
2. **参数要求**:
|
|||
|
- 至少提供一个机器人选择参数(robot_name、robot_group、robot_label_group)
|
|||
|
- 已载货场景必须提供 site_id 和 action
|
|||
|
|
|||
|
3. **并发控制**:
|
|||
|
- 同一任务不应同时执行多次换机器人操作
|
|||
|
- 建议在调用前检查任务当前状态
|
|||
|
|
|||
|
### 最佳实践
|
|||
|
|
|||
|
1. **参数选择**:
|
|||
|
- 优先使用 `robot_name` 指定具体机器人
|
|||
|
- 使用 `robot_group` 让系统从组中自动选择
|
|||
|
- 使用 `robot_label_group` 基于标签筛选机器人
|
|||
|
|
|||
|
2. **未载货场景**:
|
|||
|
- 系统会自动从原任务中提取参数,无需手动指定 site_id 和 action
|
|||
|
- 适用于机器人尚未开始实际操作的情况
|
|||
|
|
|||
|
3. **已载货场景**:
|
|||
|
- 必须明确指定目标库位和动作
|
|||
|
- 建议先将货物放到临时库位,再更换机器人继续后续任务
|
|||
|
- action 常用值:`pick`(取货)、`drop`(放货)
|
|||
|
|
|||
|
4. **错误处理**:
|
|||
|
- 换机器人失败时,原任务会保持原状态
|
|||
|
- 建议实现重试机制
|
|||
|
- 记录详细的换机器人日志用于问题追溯
|
|||
|
|
|||
|
5. **监控和日志**:
|
|||
|
- 通过 `ended_reason` 字段追踪换机器人历史
|
|||
|
- 通过任务块记录查看被终止的块
|
|||
|
- 建议在业务系统中记录换机器人操作日志
|
|||
|
|
|||
|
---
|
|||
|
|
|||
|
## 错误码说明
|
|||
|
|
|||
|
| 错误码 | 错误信息 | 说明 | 解决方案 |
|
|||
|
| --- | --- | --- | --- |
|
|||
|
| 404 | 未找到任务记录 | 任务记录ID不存在 | 检查任务记录ID是否正确 |
|
|||
|
| 400 | 只能对运行中的任务换机器人 | 任务状态不是RUNNING | 确认任务正在运行中 |
|
|||
|
| 400 | 任务定义解析失败 | 任务定义JSON格式错误 | 检查任务定义数据完整性 |
|
|||
|
| 400 | 任务定义格式不正确 | 缺少必要的定义字段 | 确保任务定义包含detail和rootBlock |
|
|||
|
| 400 | 已载货场景需要提供库位ID和执行动作 | 已载货时缺少site_id或action | 补充完整的请求参数 |
|
|||
|
| 500 | 换机器人失败 | 系统内部错误 | 查看详细错误日志,联系技术支持 |
|
|||
|
|
|||
|
---
|
|||
|
|
|||
|
## 相关接口
|
|||
|
|
|||
|
- [获取任务记录详情](./任务记录接口文档.md#5-获取任务记录详情):查看换机器人后的任务状态
|
|||
|
- [获取任务块运行记录](./任务记录接口文档.md#1-获取任务块运行记录):查看被终止的块和新添加的块
|
|||
|
- [获取任务执行结果](./任务记录接口文档.md#4-获取任务执行结果):查看完整的任务执行历史
|
|||
|
- [终止任务](./任务记录接口文档.md#3-终止任务):如果换机器人失败,可以终止任务
|
|||
|
|
|||
|
---
|
|||
|
|
|||
|
## 更新日志
|
|||
|
|
|||
|
| 版本 | 日期 | 更新内容 | 作者 |
|
|||
|
| --- | --- | --- | --- |
|
|||
|
| v1.0 | 2025-10-09 | 初始版本,支持未载货和已载货两种场景 | Claude |
|
|||
|
|
|||
|
---
|
|||
|
|
|||
|
## 技术支持
|
|||
|
|
|||
|
如有问题,请联系:
|
|||
|
- 技术文档:[VWED任务模块接口文档](./README.md)
|
|||
|
- 问题反馈:提交Issue到项目仓库
|