diff --git a/docs/boot_examples/liquid_handler.md b/docs/boot_examples/liquid_handler.md index 707b1551..4343362a 100644 --- a/docs/boot_examples/liquid_handler.md +++ b/docs/boot_examples/liquid_handler.md @@ -13,18 +13,16 @@ ```json { "nodes": [ - { - "id": "PLR_STATION", - "name": "PLR_LH_TEST", - "parent": null, - "type": "device", - "class": "liquid_handler", - "config": {}, - "data": {}, - "children": [ - "deck" - ] - }, + { + "id": "PLR_STATION", + "name": "PLR_LH_TEST", + "parent": null, + "type": "device", + "class": "liquid_handler", + "config": {}, + "data": {}, + "children": ["deck"] + }, { "id": "deck", "name": "deck", @@ -32,12 +30,12 @@ "class": null, "parent": "PLR_STATION", "children": [ - "trash", - "trash_core96", - "teaching_carrier", - "tip_rack", - "plate" - ] + "trash", + "trash_core96", + "teaching_carrier", + "tip_rack", + "plate" + ] } ], "links": [] @@ -45,6 +43,7 @@ ``` 配置文件定义了移液站的组成部分,主要包括: + - 移液站本体(LiquidHandler)- 设备类型 - 移液站携带物料实例(deck)- 物料类型 @@ -55,7 +54,7 @@ 使用以下命令启动移液站设备: ```bash -unilab -g test/experiments/plr_test.json --app_bridges "" +unilab -g test/experiments/plr_test.json --ak [通过网页获取的ak值] --sk [通过网页获取的sk值] ``` ### 2. 执行枪头插入操作 @@ -66,35 +65,50 @@ unilab -g test/experiments/plr_test.json --app_bridges "" ros2 action send_goal /devices/PLR_STATION/pick_up_tips unilabos_msgs/action/_liquid_handler_pick_up_tips/LiquidHandlerPickUpTips "{ tip_spots: [ { id: 'tip_rack_tipspot_0_0', name: 'tip_rack_tipspot_0_0', sample_id: null, children: [], parent: 'tip_rack', type: 'device', config: { position: { x: 7.2, y: 68.3, z: -83.5 }, size_x: 9.0, size_y: 9.0, size_z: 0, rotation: { x: 0, y: 0, z: 0, type: 'Rotation' }, category: 'tip_spot', model: null, type: 'TipSpot', prototype_tip: { type: 'HamiltonTip', total_tip_length: 95.1, has_filter: true, maximal_volume: 1065, pickup_method: 'OUT_OF_RACK', tip_size: 'HIGH_VOLUME' } }, data: { tip: { type: 'HamiltonTip', total_tip_length: 95.1, has_filter: true, maximal_volume: 1065, pickup_method: 'OUT_OF_RACK', tip_size: 'HIGH_VOLUME' }, tip_state: { liquids: [], pending_liquids: [], liquid_history: [] }, pending_tip: { type: 'HamiltonTip', total_tip_length: 95.1, has_filter: true, maximal_volume: 1065, pickup_method: 'OUT_OF_RACK', tip_size: 'HIGH_VOLUME' } } } ], use_channels: [ 0 ], offsets: [ { x: 0.0, y: 0.0, z: 0.0 } ] }" ``` -此命令会通过ros通信触发移液站执行枪头插入操作,得到如下的PyLabRobot的输出日志。 +此命令会通过 ros 通信触发移液站执行枪头插入操作,得到如下的 PyLabRobot 的输出日志。 ```log Picking up tips: -pip# resource offset tip type max volume (µL) fitting depth (mm) tip length (mm) filter - p0: tip_rack_tipspot_0_0 0.0,0.0,0.0 HamiltonTip 1065 8 95.1 Yes +pip# resource offset tip type max volume (µL) fitting depth (mm) tip length (mm) filter + p0: tip_rack_tipspot_0_0 0.0,0.0,0.0 HamiltonTip 1065 8 95.1 Yes ``` +也可以登陆网页,给`tip_spots`选择`tip_rack_tipspot_0_0`,`use_channels`为`0`,`offsets`均填写`0`,同样可观察到上面的日志 + ## 常见问题 -1. **重复插入枪头不成功**:操作编排应该符合实际操作顺序,可自行通过PyLabRobot进行测试 +1. **重复插入枪头不成功**:操作编排应该符合实际操作顺序,可自行通过 PyLabRobot 进行测试 ## 移液站支持的操作 移液站支持多种操作,以下是当前系统支持的操作列表: -1. **LiquidHandlerAspirate** - 吸液操作 -2. **LiquidHandlerDispense** - 排液操作 -3. **LiquidHandlerDiscardTips** - 丢弃枪头 -4. **LiquidHandlerDropTips** - 卸下枪头 -5. **LiquidHandlerDropTips96** - 卸下96通道枪头 -6. **LiquidHandlerMoveLid** - 移动盖子 -7. **LiquidHandlerMovePlate** - 移动板子 -8. **LiquidHandlerMoveResource** - 移动资源 -9. **LiquidHandlerPickUpTips** - 插入枪头 -10. **LiquidHandlerPickUpTips96** - 插入96通道枪头 -11. **LiquidHandlerReturnTips** - 归还枪头 -12. **LiquidHandlerReturnTips96** - 归还96通道枪头 -13. **LiquidHandlerStamp** - 打印标记 -14. **LiquidHandlerTransfer** - 液体转移 +1. **LiquidHandlerProtocolCreation** - 协议创建 +2. **LiquidHandlerAspirate** - 吸液操作 +3. **LiquidHandlerDispense** - 排液操作 +4. **LiquidHandlerDiscardTips** - 丢弃枪头 +5. **LiquidHandlerDropTips** - 卸下枪头 +6. **LiquidHandlerDropTips96** - 卸下 96 通道枪头 +7. **LiquidHandlerMoveLid** - 移动盖子 +8. **LiquidHandlerMovePlate** - 移动板子 +9. **LiquidHandlerMoveResource** - 移动资源 +10. **LiquidHandlerPickUpTips** - 插入枪头 +11. **LiquidHandlerPickUpTips96** - 插入 96 通道枪头 +12. **LiquidHandlerReturnTips** - 归还枪头 +13. **LiquidHandlerReturnTips96** - 归还 96 通道枪头 +14. **LiquidHandlerSetLiquid** - 设置液体 +15. **LiquidHandlerSetTipRack** - 设置枪头架 +16. **LiquidHandlerStamp** - 打印标记 +17. **LiquidHandlerTransfer** - 液体转移 +18. **LiquidHandlerSetGroup** - 设置分组 +19. **LiquidHandlerTransferBiomek** - Biomek 液体转移 +20. **LiquidHandlerIncubateBiomek** - Biomek 孵育 +21. **LiquidHandlerMoveBiomek** - Biomek 移动 +22. **LiquidHandlerOscillateBiomek** - Biomek 振荡 +23. **LiquidHandlerTransferGroup** - 分组转移 +24. **LiquidHandlerAdd** - 添加操作 +25. **LiquidHandlerMix** - 混合操作 +26. **LiquidHandlerMoveTo** - 移动到指定位置 +27. **LiquidHandlerRemove** - 移除操作 -这些操作可通过ROS2 Action接口进行调用,以实现复杂的移液流程。 \ No newline at end of file +这些操作可通过 ROS2 Action 接口进行调用,以实现复杂的移液流程。 diff --git a/docs/developer_guide/add_device.md b/docs/developer_guide/add_device.md index 1fae4bdb..0cec54da 100644 --- a/docs/developer_guide/add_device.md +++ b/docs/developer_guide/add_device.md @@ -13,36 +13,36 @@ class MockGripper: self._velocity: float = 2.0 self._torque: float = 0.0 self._status = "Idle" - + @property def position(self) -> float: return self._position - + @property def velocity(self) -> float: return self._velocity - + @property def torque(self) -> float: return self._torque - + # 会被自动识别的设备属性,接入 Uni-Lab 时会定时对外广播 @property def status(self) -> str: return self._status - + # 会被自动识别的设备动作,接入 Uni-Lab 时会作为 ActionServer 接受任意控制者的指令 @status.setter def status(self, target): self._status = target - + # 需要在注册表添加的设备动作,接入 Uni-Lab 时会作为 ActionServer 接受任意控制者的指令 def push_to(self, position: float, torque: float, velocity: float = 0.0): self._status = "Running" current_pos = self.position if velocity == 0.0: velocity = self.velocity - + move_time = abs(position - current_pos) / velocity for i in range(20): self._position = current_pos + (position - current_pos) / 20 * (i+1) @@ -68,7 +68,7 @@ public class MockGripper public double velocity { get; private set; } = 2.0; public double torque { get; private set; } = 0.0; public string status { get; private set; } = "Idle"; - + // 需要在注册表添加的设备动作,接入 Uni-Lab 时会作为 ActionServer 接受任意控制者的指令 public async Task PushToAsync(double Position, double Torque, double Velocity = 0.0) { @@ -94,107 +94,61 @@ public class MockGripper C# 驱动设备在完成注册表后,需要调用 Uni-Lab C# 编译后才能使用,但只需一次。 -## 注册表文件位置 +## 快速开始:使用注册表编辑器(推荐) -Uni-Lab 启动时会自动读取默认注册表路径 `unilabos/registry/devices` 下的所有注册设备。您也可以任意维护自己的注册表路径,只需要在 Uni-Lab 启动时使用 `--registry` 参数将路径添加即可。 +推荐使用 Uni-Lab-OS 自带的可视化编辑器,它能自动分析您的设备驱动并生成大部分配置: -在 `/devices` 中新建一个 yaml 文件,即可开始撰写。您可以将多个设备写到同一个 yaml 文件中。 +1. 启动 Uni-Lab-OS +2. 在浏览器中打开"注册表编辑器"页面 +3. 选择您的 Python 设备驱动文件 +4. 点击"分析文件",让系统读取类信息 +5. 填写基本信息(设备描述、图标等) +6. 点击"生成注册表",复制生成的内容 +7. 保存到 `devices/` 目录下 -## 注册表的结构 +--- -1. 顶层名称:每个设备的注册表以设备名称开头,例如 `new_device`, `gripper.mock`。 -1. `class` 字段:定义设备的模块路径和驱动程序语言。 -1. `status_types` 字段:定义设备定时对 Uni-Lab 实验室内发送的属性名及其类型。 -1. `action_value_mappings` 字段:定义设备支持的动作及其目标、反馈和结果。 -1. `schema` 字段:定义设备定时对 Uni-Lab 云端监控发送的属性名及其类型、描述(非必须) +## 手动编写注册表(简化版) -## 创建新的注册表教程 +如果需要手动编写,只需要提供两个必需字段,系统会自动补全其余内容: -1. 创建文件 - 在 devices 文件夹中创建一个新的 YAML 文件,例如 `new_device.yaml`。 -2. 定义设备名称 - 在文件中定义设备的顶层名称,例如:`new_device` 或 `gripper.mock` -3. 定义设备的类信息 - 添加设备的模块路径和类型: +### 最小配置示例 ```yaml -gripper.mock: - class: # 定义设备的类信息 - module: unilabos.devices.gripper.mock:MockGripper - type: python # 指定驱动语言为 Python - status_types: - position: Float64 - torque: Float64 - status: String +my_device: # 设备唯一标识符 + class: + module: unilabos.devices.your_module.my_device:MyDevice # Python 类路径 + type: python # 驱动类型 ``` -4. 定义设备的定时发布属性。注意,对于 Python Class 来说,PROP 是 class 的 `property`,或满足能被 `getattr(cls, PROP)` 或 `cls.get_PROP` 读取到的属性值的对象。 +### 注册表文件位置 + +- 默认路径:`unilabos/registry/devices` +- 自定义路径:启动时使用 `--registry` 参数指定 +- 可将多个设备写在同一个 yaml 文件中 + +### 系统自动生成的内容 + +系统会自动分析您的 Python 驱动类并生成: + +- `status_types`:从 `get_*` 方法自动识别状态属性 +- `action_value_mappings`:从类方法自动生成动作映射 +- `init_param_schema`:从 `__init__` 方法分析初始化参数 +- `schema`:前端显示用的属性类型定义 + +### 完整结构概览 ```yaml - status_types: - PROP: TYPE -``` -5. 定义设备支持的动作 - 添加设备支持的动作及其目标、反馈和结果: - -```yaml - action_value_mappings: - set_speed: - type: SendCmd - goal: - command: speed - feedback: {} - result: - success: success +my_device: + class: + module: unilabos.devices.your_module.my_device:MyDevice + type: python + status_types: {} # 自动生成 + action_value_mappings: {} # 自动生成 + description: '' # 可选:设备描述 + icon: '' # 可选:设备图标 + init_param_schema: {} # 自动生成 + schema: {} # 自动生成 ``` -在 devices 文件夹中的 YAML 文件中,action_value_mappings 是用来将驱动内的动作函数,映射到 Uni-Lab 标准动作(actions)及其目标参数值(goal)、反馈值(feedback)和结果值(result)的映射规则。若在 Uni-Lab 指令集内找不到符合心意的,请【创建新指令】。 - -```yaml - action_value_mappings: - : # :动作的名称 - # start:启动设备或某个功能。 - # stop:停止设备或某个功能。 - # set_speed:设置设备的速度。 - # set_temperature:设置设备的温度。 - # move_to_position:移动设备到指定位置。 - # stir:执行搅拌操作。 - # heatchill:执行加热或冷却操作。 - # send_nav_task:发送导航任务(例如机器人导航)。 - # set_timer:设置设备的计时器。 - # valve_open_cmd:打开阀门。 - # valve_close_cmd:关闭阀门。 - # execute_command_from_outer:执行外部命令。 - # push_to:控制设备推送到某个位置(例如机械爪)。 - # move_through_points:导航设备通过多个点。 - - type: # 动作的类型,表示动作的功能 - # 根据动作的功能选择合适的类型,请查阅 Uni-Lab 已支持的指令集。 - - goal: # 定义动作的目标值映射,表示需要传递给设备的参数。 - : #确定设备需要的输入参数,并将其映射到设备的字段。 - - feedback: # 定义动作的反馈值映射,表示设备执行动作时返回的实时状态。 - : - result: # 定义动作的结果值映射,表示动作完成后返回的最终结果。 - : -``` - -6. 定义设备的网页展示属性类型,这部分会被用于在 Uni-Lab 网页端渲染成状态监控 - 添加设备的属性模式,包括属性类型和描述: - -```yaml -schema: - type: object - properties: - status: - type: string - description: The status of the device - speed: - type: number - description: The speed of the device - required: - - status - - speed - additionalProperties: false -``` +详细的注册表编写指南和高级配置,请参考{doc}`yaml 注册表编写指南 `。 diff --git a/docs/user_guide/installation.md b/docs/user_guide/installation.md index 68ad62ed..fe71c2e7 100644 --- a/docs/user_guide/installation.md +++ b/docs/user_guide/installation.md @@ -1,24 +1,26 @@ # **Uni-Lab 安装** -请先 `git clone` 本仓库,随后按照以下步骤安装项目: +## 快速开始 -`Uni-Lab` 建议您采用 `mamba` 管理环境。若需从头建立 `Uni-Lab` 的运行依赖环境,请执行 +1. **配置 Conda 环境** + +Uni-Lab-OS 建议使用 `mamba` 管理环境。创建新的环境: ```shell -mamba env create -f unilabos-.yaml -mamba activate unilab +mamba create -n unilab uni-lab::unilabos -c robostack-staging -c conda-forge ``` -其中 `YOUR_OS` 是您的操作系统,可选值 `win64`, `linux-64`, `osx-64`, `osx-arm64` - -若需将依赖安装进当前环境,请执行 +2. **安装开发版 Uni-Lab-OS** ```shell -conda env update --file unilabos-.yml -``` +# 配置好conda环境后,克隆仓库 +git clone https://github.com/dptech-corp/Uni-Lab-OS.git +cd Uni-Lab-OS -随后,可在本仓库安装 `unilabos` 的开发版: - -```shell +# 安装 Uni-Lab-OS pip install . ``` + +3. **启动 Uni-Lab 系统** + +请参见{doc}`启动样例 <../boot_examples/index>`或{doc}`启动指南 `了解详细的启动方法。 diff --git a/unilabos/app/web/client.py b/unilabos/app/web/client.py index 91d19a7c..96bbe6cd 100644 --- a/unilabos/app/web/client.py +++ b/unilabos/app/web/client.py @@ -131,6 +131,7 @@ class HTTPClient: Returns: Response: API响应对象 """ + return self.resource_add(resources) response = requests.patch( f"{self.remote_addr}/lab/resource/batch_update/?edge_format=1", json=resources,