Files
Uni-Lab-OS/docs/developer_guide/add_device.md
Junhan Chang c78ac482d8 Initial commit
2025-04-17 15:19:47 +08:00

8.1 KiB
Raw Blame History

添加新设备

在 Uni-Lab 中设备Device是实验操作的基础单元。Uni-Lab 使用注册表机制来兼容管理种类繁多的设备驱动程序。回顾 {ref}instructions 中的概念,抽象的设备对外拥有【话题】【服务】【动作】三种通信机制,因此将设备添加进 Uni-Lab实际上是将设备驱动中的三种机制映射到 Uni-Lab 标准指令集上。

能被 Uni-Lab 添加的驱动程序类型有以下种类:

  1. Python Class
class MockGripper:
    def __init__(self):
        self._position: float = 0.0
        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)
            self._torque = torque / (20 - i)
            self._velocity = velocity
            time.sleep(move_time / 20)
        self._torque = torque
        self._status = "Idle"

Python 类设备驱动在完成注册表后可以直接在 Uni-Lab 使用。

  1. C# Class
using System;
using System.Threading.Tasks;

public class MockGripper
{
    // 会被自动识别的设备属性,接入 Uni-Lab 时会定时对外广播
    public double position { get; private set; } = 0.0;
    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)
    {
        status = "Running";
        double currentPos = Position;
        if (Velocity == 0.0)
        {
            velocity = Velocity;
        }
        double moveTime = Math.Abs(Position - currentPos) / velocity;
        for (int i = 0; i < 20; i++)
        {
            position = currentPos + (Position - currentPos) / 20 * (i + 1);
            torque = Torque / (20 - i);
            velocity = Velocity;
            await Task.Delay((int)(moveTime * 1000 / 20)); // Convert seconds to milliseconds
        }
        torque = Torque;
        status = "Idle";
    }
}

C# 驱动设备在完成注册表后,需要调用 Uni-Lab C# 编译后才能使用,但只需一次。

注册表文件位置

Uni-Lab 启动时会自动读取默认注册表路径 unilabos/registry/devices 下的所有注册设备。您也可以任意维护自己的注册表路径,只需要在 Uni-Lab 启动时使用 --registry 参数将路径添加即可。

<path-to-registry>/devices 中新建一个 yaml 文件,即可开始撰写。您可以将多个设备写到同一个 yaml 文件中。

注册表的结构

  1. 顶层名称:每个设备的注册表以设备名称开头,例如 new_device, gripper.mock
  2. class 字段:定义设备的模块路径和驱动程序语言。
  3. status_types 字段:定义设备定时对 Uni-Lab 实验室内发送的属性名及其类型。
  4. action_value_mappings 字段:定义设备支持的动作及其目标、反馈和结果。
  5. schema 字段:定义设备定时对 Uni-Lab 云端监控发送的属性名及其类型、描述(非必须)

创建新的注册表教程

  1. 创建文件 在 devices 文件夹中创建一个新的 YAML 文件,例如 new_device.yaml
  2. 定义设备名称 在文件中定义设备的顶层名称,例如:new_devicegripper.mock
  3. 定义设备的类信息 添加设备的模块路径和类型:
gripper.mock:
  class:   # 定义设备的类信息
    module: unilabos.devices.gripper.mock:MockGripper
    type: python  # 指定驱动语言为 Python
    status_types:
      position: Float64
      torque: Float64
      status: String
  1. 定义设备的定时发布属性。注意,对于 Python Class 来说PROP 是 class 的 property,或满足能被 getattr(cls, PROP)cls.get_PROP 读取到的属性值的对象。
    status_types:
      PROP: TYPE
  1. 定义设备支持的动作 添加设备支持的动作及其目标、反馈和结果:
    action_value_mappings:
      set_speed:
        type: SendCmd
        goal:
          command: speed
        feedback: {}
        result:
          success: success

在 devices 文件夹中的 YAML 文件中action_value_mappings 是用来将驱动内的动作函数,映射到 Uni-Lab 标准动作actions及其目标参数值goal、反馈值feedback和结果值result的映射规则。若在 Uni-Lab 指令集内找不到符合心意的,请【创建新指令】。

  action_value_mappings:
    <action_name>:                      # <action_name>:动作的名称
                                        # 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: <ActionType>                # 动作的类型,表示动作的功能
                                        # 根据动作的功能选择合适的类型,请查阅 Uni-Lab 已支持的指令集。

      goal:                             # 定义动作的目标值映射,表示需要传递给设备的参数。
        <goal_key>: <mapped_value>      #确定设备需要的输入参数,并将其映射到设备的字段。

      feedback:                         # 定义动作的反馈值映射,表示设备执行动作时返回的实时状态。
        <feedback_key>: <mapped_value>
      result:                           # 定义动作的结果值映射,表示动作完成后返回的最终结果。
        <result_key>: <mapped_value>
  1. 定义设备的网页展示属性类型,这部分会被用于在 Uni-Lab 网页端渲染成状态监控 添加设备的属性模式,包括属性类型和描述:
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