mirror of
https://github.com/dptech-corp/Uni-Lab-OS.git
synced 2025-12-15 13:44:39 +00:00
861 lines
24 KiB
Markdown
861 lines
24 KiB
Markdown
# 设备图文件说明
|
||
|
||
设备图文件定义了实验室中所有设备、资源及其连接关系。本文档说明如何创建和使用设备图文件。
|
||
|
||
## 概述
|
||
|
||
设备图文件采用 JSON 格式,节点定义基于 **`ResourceDict`** 标准模型(定义在 `unilabos.ros.nodes.resource_tracker`)。系统会自动处理旧格式并转换为标准格式,确保向后兼容性。
|
||
|
||
**核心概念**:
|
||
|
||
- **Nodes(节点)**: 代表设备或资源,通过 `parent` 字段建立层级关系
|
||
- **Links(连接)**: 可选的连接关系定义,用于展示设备间的物理或通信连接
|
||
- **UUID**: 全局唯一标识符,用于跨系统的资源追踪
|
||
- **自动转换**: 旧格式会通过 `ResourceDictInstance.get_resource_instance_from_dict()` 自动转换
|
||
|
||
## 文件格式
|
||
|
||
Uni-Lab 支持两种格式的设备图文件:
|
||
|
||
### JSON 格式(推荐)
|
||
|
||
**优点**:
|
||
|
||
- 易于编辑和阅读
|
||
- 支持注释(使用预处理)
|
||
- 与 Web 界面完全兼容
|
||
- 便于版本控制
|
||
|
||
**示例**: `workshop1.json`
|
||
|
||
### GraphML 格式
|
||
|
||
**优点**:
|
||
|
||
- 可用图形化工具编辑(如 yEd)
|
||
- 适合复杂拓扑可视化
|
||
|
||
**示例**: `setup.graphml`
|
||
|
||
## JSON 文件结构
|
||
|
||
一个完整的 JSON 设备图文件包含两个主要部分:
|
||
|
||
```json
|
||
{
|
||
"nodes": [
|
||
/* 设备和资源节点 */
|
||
],
|
||
"links": [
|
||
/* 连接关系(可选)*/
|
||
]
|
||
}
|
||
```
|
||
|
||
### Nodes(节点)
|
||
|
||
每个节点代表一个设备或资源。节点的定义遵循 `ResourceDict` 标准模型:
|
||
|
||
```json
|
||
{
|
||
"id": "liquid_handler_1",
|
||
"uuid": "550e8400-e29b-41d4-a716-446655440000",
|
||
"name": "液体处理工作站",
|
||
"type": "device",
|
||
"class": "liquid_handler",
|
||
"config": {
|
||
"port": "/dev/ttyUSB0",
|
||
"baudrate": 9600
|
||
},
|
||
"data": {},
|
||
"position": {
|
||
"x": 100,
|
||
"y": 200
|
||
},
|
||
"parent": null
|
||
}
|
||
```
|
||
|
||
**字段说明(基于 ResourceDict 标准定义)**:
|
||
|
||
| 字段 | 必需 | 说明 | 示例 | 默认值 |
|
||
| ------------- | ---- | ------------------------ | ---------------------------------------------------- | -------- |
|
||
| `id` | ✓ | 唯一标识符 | `"pump_1"` | - |
|
||
| `uuid` | | 全局唯一标识符 (UUID) | `"550e8400-e29b-41d4-a716-446655440000"` | 自动生成 |
|
||
| `name` | ✓ | 显示名称 | `"主反应泵"` | - |
|
||
| `type` | ✓ | 节点类型 | `"device"`, `"resource"`, `"container"`, `"deck"` 等 | - |
|
||
| `class` | ✓ | 设备/资源类别 | `"liquid_handler"`, `"syringepump.runze"` | `""` |
|
||
| `config` | | Python 类的初始化参数 | `{"port": "COM3"}` | `{}` |
|
||
| `data` | | 资源的运行状态数据 | `{"status": "Idle", "position": 0.0}` | `{}` |
|
||
| `position` | | 在图中的位置 | `{"x": 100, "y": 200}` 或完整的 pose 结构 | - |
|
||
| `pose` | | 完整的 3D 位置信息 | 参见下文 | - |
|
||
| `parent` | | 父节点 ID | `"deck_1"` | `null` |
|
||
| `parent_uuid` | | 父节点 UUID | `"550e8400-..."` | `null` |
|
||
| `children` | | 子节点 ID 列表(旧格式) | `["child1", "child2"]` | - |
|
||
| `description` | | 资源描述 | `"用于精确控制试剂A的加料速率"` | `""` |
|
||
| `schema` | | 资源 schema 定义 | `{}` | `{}` |
|
||
| `model` | | 资源 3D 模型信息 | `{}` | `{}` |
|
||
| `icon` | | 资源图标 | `"pump.webp"` | `""` |
|
||
| `extra` | | 额外的自定义数据 | `{"custom_field": "value"}` | `{}` |
|
||
|
||
### Position 和 Pose(位置信息)
|
||
|
||
**简单格式(旧格式,兼容)**:
|
||
|
||
```json
|
||
"position": {
|
||
"x": 100,
|
||
"y": 200,
|
||
"z": 0
|
||
}
|
||
```
|
||
|
||
**完整格式(推荐)**:
|
||
|
||
```json
|
||
"pose": {
|
||
"size": {
|
||
"width": 127.76,
|
||
"height": 85.48,
|
||
"depth": 10.0
|
||
},
|
||
"scale": {
|
||
"x": 1.0,
|
||
"y": 1.0,
|
||
"z": 1.0
|
||
},
|
||
"layout": "x-y",
|
||
"position": {
|
||
"x": 100,
|
||
"y": 200,
|
||
"z": 0
|
||
},
|
||
"position3d": {
|
||
"x": 100,
|
||
"y": 200,
|
||
"z": 0
|
||
},
|
||
"rotation": {
|
||
"x": 0,
|
||
"y": 0,
|
||
"z": 0
|
||
},
|
||
"cross_section_type": "rectangle"
|
||
}
|
||
```
|
||
|
||
### Links(连接)
|
||
|
||
定义节点之间的连接关系(可选,主要用于物理连接或通信关系的可视化):
|
||
|
||
```json
|
||
{
|
||
"source": "pump_1",
|
||
"target": "reactor_1",
|
||
"sourceHandle": "output",
|
||
"targetHandle": "input",
|
||
"type": "physical"
|
||
}
|
||
```
|
||
|
||
**字段说明**:
|
||
|
||
| 字段 | 必需 | 说明 | 示例 |
|
||
| -------------- | ---- | ---------------- | ---------------------------------------- |
|
||
| `source` | ✓ | 源节点 ID | `"pump_1"` |
|
||
| `target` | ✓ | 目标节点 ID | `"reactor_1"` |
|
||
| `sourceHandle` | | 源节点的连接点 | `"output"` |
|
||
| `targetHandle` | | 目标节点的连接点 | `"input"` |
|
||
| `type` | | 连接类型 | `"physical"`, `"communication"` |
|
||
| `port` | | 端口映射信息 | `{"source": "port1", "target": "port2"}` |
|
||
|
||
**注意**: Links 主要用于图形化展示和文档说明,父子关系通过 `parent` 字段定义,不依赖 links。
|
||
|
||
## 完整示例
|
||
|
||
### 示例 1:液体处理工作站(PRCXI9300)
|
||
|
||
这是一个真实的液体处理工作站配置,包含设备、工作台和多个板资源。
|
||
|
||
**文件位置**: `test/experiments/prcxi_9300.json`
|
||
|
||
```json
|
||
{
|
||
"nodes": [
|
||
{
|
||
"id": "PRCXI9300",
|
||
"name": "PRCXI9300",
|
||
"parent": null,
|
||
"type": "device",
|
||
"class": "liquid_handler.prcxi",
|
||
"position": {
|
||
"x": 0,
|
||
"y": 0,
|
||
"z": 0
|
||
},
|
||
"config": {
|
||
"deck": {
|
||
"_resource_child_name": "PRCXI_Deck_9300",
|
||
"_resource_type": "unilabos.devices.liquid_handling.prcxi.prcxi:PRCXI9300Deck"
|
||
},
|
||
"host": "10.181.214.132",
|
||
"port": 9999,
|
||
"timeout": 10.0,
|
||
"axis": "Left",
|
||
"channel_num": 8,
|
||
"setup": false,
|
||
"debug": true,
|
||
"simulator": true,
|
||
"matrix_id": "71593"
|
||
},
|
||
"data": {},
|
||
"children": ["PRCXI_Deck_9300"]
|
||
},
|
||
{
|
||
"id": "PRCXI_Deck_9300",
|
||
"name": "PRCXI_Deck_9300",
|
||
"parent": "PRCXI9300",
|
||
"type": "deck",
|
||
"class": "",
|
||
"position": {
|
||
"x": 0,
|
||
"y": 0,
|
||
"z": 0
|
||
},
|
||
"config": {
|
||
"type": "PRCXI9300Deck",
|
||
"size_x": 100,
|
||
"size_y": 100,
|
||
"size_z": 100,
|
||
"rotation": {
|
||
"x": 0,
|
||
"y": 0,
|
||
"z": 0,
|
||
"type": "Rotation"
|
||
},
|
||
"category": "deck"
|
||
},
|
||
"data": {},
|
||
"children": [
|
||
"RackT1",
|
||
"PlateT2",
|
||
"trash",
|
||
"PlateT4",
|
||
"PlateT5",
|
||
"PlateT6"
|
||
]
|
||
},
|
||
{
|
||
"id": "RackT1",
|
||
"name": "RackT1",
|
||
"parent": "PRCXI_Deck_9300",
|
||
"type": "tip_rack",
|
||
"class": "",
|
||
"position": {
|
||
"x": 0,
|
||
"y": 0,
|
||
"z": 0
|
||
},
|
||
"config": {
|
||
"type": "TipRack",
|
||
"size_x": 127.76,
|
||
"size_y": 85.48,
|
||
"size_z": 100
|
||
},
|
||
"data": {},
|
||
"children": []
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
**关键点**:
|
||
|
||
- 使用 `parent` 字段建立层级关系(PRCXI9300 → Deck → Rack/Plate)
|
||
- 使用 `children` 字段(旧格式)列出子节点
|
||
- `config` 中包含设备特定的连接参数
|
||
- `data` 存储运行时状态
|
||
- `position` 使用简单的 x/y/z 坐标
|
||
|
||
### 示例 2:有机合成工作站(带 Links)
|
||
|
||
这是一个格林纳德反应的流动化学工作站配置,展示了完整的设备连接和通信关系。
|
||
|
||
**文件位置**: `test/experiments/Grignard_flow_batchreact_single_pumpvalve.json`
|
||
|
||
```json
|
||
{
|
||
"nodes": [
|
||
{
|
||
"id": "YugongStation",
|
||
"name": "愚公常量合成工作站",
|
||
"parent": null,
|
||
"type": "device",
|
||
"class": "workstation",
|
||
"position": {
|
||
"x": 620.6111111111111,
|
||
"y": 171,
|
||
"z": 0
|
||
},
|
||
"config": {
|
||
"protocol_type": [
|
||
"PumpTransferProtocol",
|
||
"CleanProtocol",
|
||
"SeparateProtocol",
|
||
"EvaporateProtocol"
|
||
]
|
||
},
|
||
"data": {},
|
||
"children": [
|
||
"serial_pump",
|
||
"pump_reagents",
|
||
"flask_CH2Cl2",
|
||
"reactor",
|
||
"pump_workup",
|
||
"separator_controller",
|
||
"flask_separator",
|
||
"rotavap",
|
||
"column"
|
||
]
|
||
},
|
||
{
|
||
"id": "serial_pump",
|
||
"name": "serial_pump",
|
||
"parent": "YugongStation",
|
||
"type": "device",
|
||
"class": "serial",
|
||
"position": {
|
||
"x": 620.6111111111111,
|
||
"y": 171,
|
||
"z": 0
|
||
},
|
||
"config": {
|
||
"port": "COM7",
|
||
"baudrate": 9600
|
||
},
|
||
"data": {},
|
||
"children": []
|
||
},
|
||
{
|
||
"id": "pump_reagents",
|
||
"name": "pump_reagents",
|
||
"parent": "YugongStation",
|
||
"type": "device",
|
||
"class": "syringepump.runze",
|
||
"position": {
|
||
"x": 620.6111111111111,
|
||
"y": 171,
|
||
"z": 0
|
||
},
|
||
"config": {
|
||
"port": "/devices/PumpBackbone/Serial/serialwrite",
|
||
"address": "1",
|
||
"max_volume": 25.0
|
||
},
|
||
"data": {
|
||
"max_velocity": 1.0,
|
||
"position": 0.0,
|
||
"status": "Idle",
|
||
"valve_position": "0"
|
||
},
|
||
"children": []
|
||
},
|
||
{
|
||
"id": "reactor",
|
||
"name": "reactor",
|
||
"parent": "YugongStation",
|
||
"type": "container",
|
||
"class": null,
|
||
"position": {
|
||
"x": 430.4087301587302,
|
||
"y": 428,
|
||
"z": 0
|
||
},
|
||
"config": {},
|
||
"data": {},
|
||
"children": []
|
||
}
|
||
],
|
||
"links": [
|
||
{
|
||
"source": "pump_reagents",
|
||
"target": "serial_pump",
|
||
"type": "communication",
|
||
"port": {
|
||
"pump_reagents": "port",
|
||
"serial_pump": "port"
|
||
}
|
||
},
|
||
{
|
||
"source": "pump_workup",
|
||
"target": "serial_pump",
|
||
"type": "communication",
|
||
"port": {
|
||
"pump_workup": "port",
|
||
"serial_pump": "port"
|
||
}
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
**关键点**:
|
||
|
||
- 多级设备层次:工作站包含多个子设备和容器
|
||
- `links` 定义通信关系(泵通过串口连接)
|
||
- `data` 字段存储设备状态(如泵的位置、速度等)
|
||
- `class` 可以使用点号分层(如 `"syringepump.runze"`)
|
||
- 容器的 `class` 可以为 `null`
|
||
|
||
## 格式兼容性和转换
|
||
|
||
### 旧格式自动转换
|
||
|
||
Uni-Lab 使用 `ResourceDictInstance.get_resource_instance_from_dict()` 方法自动处理旧格式的节点数据,确保向后兼容性。
|
||
|
||
**自动转换规则**:
|
||
|
||
1. **自动生成缺失字段**:
|
||
|
||
```python
|
||
# 如果缺少 id,使用 name 作为 id
|
||
if "id" not in content:
|
||
content["id"] = content["name"]
|
||
|
||
# 如果缺少 uuid,自动生成
|
||
if "uuid" not in content:
|
||
content["uuid"] = str(uuid.uuid4())
|
||
```
|
||
|
||
2. **Position 格式转换**:
|
||
|
||
```python
|
||
# 旧格式:简单的 x/y 坐标
|
||
"position": {"x": 100, "y": 200}
|
||
|
||
# 自动转换为新格式
|
||
"position": {
|
||
"position": {"x": 100, "y": 200}
|
||
}
|
||
```
|
||
|
||
3. **默认值填充**:
|
||
|
||
```python
|
||
# 自动填充空字段
|
||
if not content.get("class"):
|
||
content["class"] = ""
|
||
if not content.get("config"):
|
||
content["config"] = {}
|
||
if not content.get("data"):
|
||
content["data"] = {}
|
||
if not content.get("extra"):
|
||
content["extra"] = {}
|
||
```
|
||
|
||
4. **Pose 字段同步**:
|
||
```python
|
||
# 如果没有 pose,使用 position
|
||
if "pose" not in content:
|
||
content["pose"] = content.get("position", {})
|
||
```
|
||
|
||
### 使用示例
|
||
|
||
```python
|
||
from unilabos.ros.nodes.resource_tracker import ResourceDictInstance
|
||
|
||
# 旧格式节点
|
||
old_format_node = {
|
||
"name": "pump_1",
|
||
"type": "device",
|
||
"class": "syringepump",
|
||
"position": {"x": 100, "y": 200}
|
||
}
|
||
|
||
# 自动转换为标准格式
|
||
instance = ResourceDictInstance.get_resource_instance_from_dict(old_format_node)
|
||
|
||
# 访问标准化后的数据
|
||
print(instance.res_content.id) # "pump_1"
|
||
print(instance.res_content.uuid) # 自动生成的 UUID
|
||
print(instance.res_content.config) # {}
|
||
print(instance.res_content.data) # {}
|
||
```
|
||
|
||
### 格式迁移建议
|
||
|
||
虽然系统会自动处理旧格式,但建议在新文件中使用完整的标准格式:
|
||
|
||
| 字段 | 旧格式(兼容) | 新格式(推荐) |
|
||
| ------ | ---------------------------------- | ------------------------------------------------ |
|
||
| 标识符 | 仅 `id` 或仅 `name` | `id` + `uuid` |
|
||
| 位置 | `"position": {"x": 100, "y": 200}` | 完整的 `pose` 结构 |
|
||
| 父节点 | `"parent": "parent_id"` | `"parent": "parent_id"` + `"parent_uuid": "..."` |
|
||
| 配置 | 可省略 | 显式设置为 `{}` |
|
||
| 数据 | 可省略 | 显式设置为 `{}` |
|
||
|
||
## 节点类型详解
|
||
|
||
### Device 节点
|
||
|
||
设备节点代表实际的硬件设备:
|
||
|
||
```json
|
||
{
|
||
"id": "device_id",
|
||
"name": "设备名称",
|
||
"type": "device",
|
||
"class": "设备类别",
|
||
"parent": null,
|
||
"config": {
|
||
"port": "COM3"
|
||
},
|
||
"data": {},
|
||
"children": []
|
||
}
|
||
```
|
||
|
||
**常见设备类别**:
|
||
|
||
- `liquid_handler`: 液体处理工作站
|
||
- `liquid_handler.prcxi`: PRCXI 液体处理工作站
|
||
- `syringepump`: 注射泵
|
||
- `syringepump.runze`: 润泽注射泵
|
||
- `heaterstirrer`: 加热搅拌器
|
||
- `balance`: 天平
|
||
- `reactor_vessel`: 反应釜
|
||
- `serial`: 串口通信设备
|
||
- `workstation`: 自动化工作站
|
||
|
||
### Resource 节点
|
||
|
||
资源节点代表物料容器、载具等:
|
||
|
||
```json
|
||
{
|
||
"id": "resource_id",
|
||
"name": "资源名称",
|
||
"type": "resource",
|
||
"class": "资源类别",
|
||
"parent": "父节点ID",
|
||
"config": {
|
||
"size_x": 127.76,
|
||
"size_y": 85.48,
|
||
"size_z": 100
|
||
},
|
||
"data": {},
|
||
"children": []
|
||
}
|
||
```
|
||
|
||
**常见资源类型**:
|
||
|
||
- `deck`: 工作台/甲板
|
||
- `plate`: 板(96 孔板等)
|
||
- `tip_rack`: 枪头架
|
||
- `tube`: 试管
|
||
- `container`: 容器
|
||
- `well`: 孔位
|
||
- `bottle_carrier`: 瓶架
|
||
|
||
## Handle(连接点)
|
||
|
||
每个设备和资源可以有多个连接点(handles),用于定义可以连接的接口。
|
||
|
||
### 查看可用 handles
|
||
|
||
设备和资源的可用 handles 定义在注册表中:
|
||
|
||
```yaml
|
||
# 设备注册表示例
|
||
liquid_handler:
|
||
handles:
|
||
- handler_key: pipette
|
||
io_type: source
|
||
- handler_key: deck
|
||
io_type: target
|
||
```
|
||
|
||
### 常见 handles
|
||
|
||
| 设备类型 | Source Handles | Target Handles |
|
||
| ---------- | -------------- | -------------- |
|
||
| 泵 | output | input |
|
||
| 反应釜 | output, vessel | input |
|
||
| 液体处理器 | pipette | deck |
|
||
| 板 | wells | access |
|
||
|
||
## 使用 Web 界面创建图文件
|
||
|
||
Uni-Lab 提供 Web 界面来可视化创建和编辑设备图:
|
||
|
||
### 1. 启动 Uni-Lab
|
||
|
||
```bash
|
||
unilab
|
||
```
|
||
|
||
### 2. 访问 Web 界面
|
||
|
||
打开浏览器访问 `http://localhost:8002`
|
||
|
||
### 3. 图形化编辑
|
||
|
||
- 拖拽添加设备和资源
|
||
- 连线建立连接关系
|
||
- 编辑节点属性
|
||
- 保存为 JSON 文件
|
||
|
||
### 4. 导出图文件
|
||
|
||
点击"导出"按钮,下载 JSON 文件到本地。
|
||
|
||
## 从云端获取图文件
|
||
|
||
如果不指定`-g`参数,Uni-Lab 会自动从云端获取:
|
||
|
||
```bash
|
||
# 使用云端配置
|
||
unilab
|
||
|
||
# 日志会显示:
|
||
# [INFO] 未指定设备加载文件路径,尝试从HTTP获取...
|
||
# [INFO] 联网获取设备加载文件成功
|
||
```
|
||
|
||
**云端图文件管理**:
|
||
|
||
1. 登录 https://uni-lab.bohrium.com
|
||
2. 进入"设备配置"
|
||
3. 创建或编辑配置
|
||
4. 保存到云端
|
||
|
||
本地启动时会自动同步最新配置。
|
||
|
||
## 调试图文件
|
||
|
||
### 验证 JSON 格式
|
||
|
||
```bash
|
||
# 使用Python验证
|
||
python -c "import json; json.load(open('workshop1.json'))"
|
||
|
||
# 使用在线工具
|
||
# https://jsonlint.com/
|
||
```
|
||
|
||
### 检查节点引用
|
||
|
||
确保:
|
||
|
||
- 所有`links`中的`source`和`target`都存在于`nodes`中
|
||
- `parent`字段指向的节点存在
|
||
- `class`字段对应的设备/资源在注册表中存在
|
||
|
||
### 启动时验证
|
||
|
||
```bash
|
||
# Uni-Lab启动时会验证图文件
|
||
unilab -g workshop1.json
|
||
|
||
# 查看日志中的错误或警告
|
||
# [ERROR] 节点 xxx 的source端点 yyy 不存在
|
||
# [WARNING] 节点 zzz missing 'name', defaulting to ...
|
||
```
|
||
|
||
## 最佳实践
|
||
|
||
### 1. 命名规范
|
||
|
||
```json
|
||
{
|
||
"id": "pump_reagent_1", // 小写+下划线,描述性
|
||
"name": "试剂进料泵A", // 中文显示名称
|
||
"class": "syringepump" // 使用注册表中的精确名称
|
||
}
|
||
```
|
||
|
||
### 2. 层级组织
|
||
|
||
```
|
||
host_node (主节点)
|
||
└── liquid_handler_1 (设备)
|
||
└── deck_1 (资源)
|
||
├── tiprack_1 (资源)
|
||
├── plate_1 (资源)
|
||
└── reservoir_1 (资源)
|
||
```
|
||
|
||
### 3. 配置分离
|
||
|
||
将设备特定配置放在`config`中:
|
||
|
||
```json
|
||
{
|
||
"id": "pump_1",
|
||
"class": "syringepump",
|
||
"config": {
|
||
"port": "COM3", // 设备特定
|
||
"max_flow_rate": 10, // 设备特定
|
||
"volume": 50 // 设备特定
|
||
}
|
||
}
|
||
```
|
||
|
||
### 4. 版本控制
|
||
|
||
```bash
|
||
# 使用Git管理图文件
|
||
git add workshop1.json
|
||
git commit -m "Add new liquid handler configuration"
|
||
|
||
# 使用有意义的文件名
|
||
workshop_v1.json
|
||
workshop_production.json
|
||
workshop_test.json
|
||
```
|
||
|
||
### 5. 注释(通过描述字段)
|
||
|
||
虽然 JSON 不支持注释,但可以使用`description`字段:
|
||
|
||
```json
|
||
{
|
||
"id": "pump_1",
|
||
"name": "进料泵",
|
||
"description": "用于精确控制试剂A的加料速率,最大流速10mL/min",
|
||
"class": "syringepump"
|
||
}
|
||
```
|
||
|
||
## 示例文件位置
|
||
|
||
Uni-Lab 在安装时已预置了 **40+ 个真实的设备图文件示例**,位于 `unilabos/test/experiments/` 目录。这些都是真实项目中使用的配置文件,可以直接使用或作为参考。
|
||
|
||
### 📁 主要示例文件
|
||
|
||
```
|
||
test/experiments/
|
||
├── workshop.json # 综合工作台(推荐新手)
|
||
├── empty_devices.json # 空设备配置(最小化)
|
||
├── prcxi_9300.json # PRCXI液体处理工作站(本文示例1)
|
||
├── prcxi_9320.json # PRCXI 9320工作站
|
||
├── biomek.json # Biomek液体处理工作站
|
||
├── Grignard_flow_batchreact_single_pumpvalve.json # 格林纳德反应工作站(本文示例2)
|
||
├── dispensing_station_bioyond.json # Bioyond配液站
|
||
├── reaction_station_bioyond.json # Bioyond反应站
|
||
├── HPLC.json # HPLC分析系统
|
||
├── plr_test.json # PyLabRobot测试配置
|
||
├── lidocaine-graph.json # 利多卡因合成工作站
|
||
├── opcua_example.json # OPC UA设备集成示例
|
||
│
|
||
├── mock_devices/ # 虚拟设备(用于离线测试)
|
||
│ ├── mock_all.json # 完整虚拟设备集
|
||
│ ├── mock_pump.json # 虚拟泵
|
||
│ ├── mock_stirrer.json # 虚拟搅拌器
|
||
│ ├── mock_heater.json # 虚拟加热器
|
||
│ └── ... # 更多虚拟设备
|
||
│
|
||
├── Protocol_Test_Station/ # 协议测试工作站
|
||
│ ├── pumptransfer_test_station.json # 泵转移协议测试
|
||
│ ├── heatchill_protocol_test_station.json # 加热冷却协议测试
|
||
│ ├── filter_protocol_test_station.json # 过滤协议测试
|
||
│ └── ... # 更多协议测试
|
||
│
|
||
└── comprehensive_protocol/ # 综合协议示例
|
||
├── comprehensive_station.json # 综合工作站
|
||
└── comprehensive_slim.json # 精简版综合工作站
|
||
```
|
||
|
||
### 🚀 快速使用
|
||
|
||
无需下载或创建,直接使用 `-g` 参数指定路径:
|
||
|
||
```bash
|
||
# 使用简单工作台(推荐新手)
|
||
unilab --ak your_ak --sk your_sk -g test/experiments/workshop.json
|
||
|
||
# 使用虚拟设备(无需真实硬件)
|
||
unilab --ak your_ak --sk your_sk -g test/experiments/mock_devices/mock_all.json
|
||
|
||
# 使用 PRCXI 液体处理工作站
|
||
unilab --ak your_ak --sk your_sk -g test/experiments/prcxi_9300.json
|
||
|
||
# 使用格林纳德反应工作站
|
||
unilab --ak your_ak --sk your_sk -g test/experiments/Grignard_flow_batchreact_single_pumpvalve.json
|
||
```
|
||
|
||
### 📚 文件分类
|
||
|
||
| 类别 | 说明 | 文件数量 |
|
||
| ------------ | ------------------------ | -------- |
|
||
| **主工作站** | 完整的实验工作站配置 | 15+ |
|
||
| **虚拟设备** | 用于开发测试的 mock 设备 | 10+ |
|
||
| **协议测试** | 各种实验协议的测试配置 | 12+ |
|
||
| **综合示例** | 包含多种协议的综合工作站 | 3+ |
|
||
|
||
这些文件展示了不同场景下的设备图配置,涵盖液体处理、有机合成、分析检测等多个领域,是学习和创建自己配置的绝佳参考。
|
||
|
||
## 快速参考:ResourceDict 完整字段列表
|
||
|
||
基于 `unilabos.ros.nodes.resource_tracker.ResourceDict` 的完整字段定义:
|
||
|
||
```python
|
||
class ResourceDict(BaseModel):
|
||
# === 基础标识 ===
|
||
id: str # 资源ID(必需)
|
||
uuid: str # 全局唯一标识符(自动生成)
|
||
name: str # 显示名称(必需)
|
||
|
||
# === 类型和分类 ===
|
||
type: Union[Literal["device"], str] # 节点类型(必需)
|
||
klass: str # 资源类别(alias="class",必需)
|
||
|
||
# === 层级关系 ===
|
||
parent: Optional[ResourceDict] # 父资源对象(不序列化)
|
||
parent_uuid: Optional[str] # 父资源UUID
|
||
|
||
# === 位置和姿态 ===
|
||
position: ResourceDictPosition # 位置信息
|
||
pose: ResourceDictPosition # 姿态信息(推荐使用)
|
||
|
||
# === 配置和数据 ===
|
||
config: Dict[str, Any] # 设备配置参数
|
||
data: Dict[str, Any] # 运行时状态数据
|
||
extra: Dict[str, Any] # 额外自定义数据
|
||
|
||
# === 元数据 ===
|
||
description: str # 资源描述
|
||
resource_schema: Dict[str, Any] # schema定义(alias="schema")
|
||
model: Dict[str, Any] # 3D模型信息
|
||
icon: str # 图标路径
|
||
```
|
||
|
||
**Position/Pose 结构**:
|
||
|
||
```python
|
||
class ResourceDictPosition(BaseModel):
|
||
size: ResourceDictPositionSize # width, height, depth
|
||
scale: ResourceDictPositionScale # x, y, z
|
||
layout: Literal["2d", "x-y", "z-y", "x-z"]
|
||
position: ResourceDictPositionObject # x, y, z
|
||
position3d: ResourceDictPositionObject # x, y, z
|
||
rotation: ResourceDictPositionObject # x, y, z
|
||
cross_section_type: Literal["rectangle", "circle", "rounded_rectangle"]
|
||
```
|
||
|
||
## 下一步
|
||
|
||
- {doc}`../boot_examples/index` - 查看完整启动示例
|
||
- {doc}`../developer_guide/add_device` - 了解如何添加新设备
|
||
- {doc}`06_troubleshooting` - 图文件相关问题排查
|
||
- 源码参考: `unilabos/ros/nodes/resource_tracker.py` - ResourceDict 标准定义
|
||
|
||
## 获取帮助
|
||
|
||
- 在 Web 界面中使用模板创建
|
||
- 参考示例文件:`test/experiments/` 目录
|
||
- 查看 ResourceDict 源码了解完整定义
|
||
- [GitHub 讨论区](https://github.com/dptech-corp/Uni-Lab-OS/discussions)
|