Skip to content

Latest commit

 

History

History
641 lines (471 loc) · 22.2 KB

3.1-任务流水线协议.md

File metadata and controls

641 lines (471 loc) · 22.2 KB

任务流水线(Pipeline)协议

整体介绍

{
    "TaskA": {
        "next: [
            "TaskB",
            "TaskC"
        ]
        // properties ...
    },
    "TaskB": {
        // properties ...
    },
    // other task ...
}

我们执行某个 Task 时(MaaPostTask 接口传入任务名),会对其 next 列表中的 Task 依次 进行识别(根据每个 Task 的 recognition 相关设置)
且一旦匹配上了,则会退出 next 列表识别,转而去执行匹配上的任务。类似遍历比较,一旦找到了,就直接 break 转而去执行找到的那个 Task。

举例

例如我们有一个游戏,画面中可能出现一种水果,可能是苹果、橘子、香蕉,我们需要点击它。一个简单的演示 JSON:

{
    "StartFruit": {
        "next": [
            "Apple",
            "Orange",
            "Banana"
        ]
    },
    "Apple": {
        "recognition": XXX,
        "action": "Click",
        // ...
    },
    "Orange": {
        "recognition": XXX,
        "action": "Click",
        "next": [
            "Cat",
            "Dog"
        ]
    },
    "Banana": {
        // ...
    },
    // ...
}

假设现在画面中没有 Apple,但有 Orange 和 Banana。 在上述 JSON 中,若我们执行 "StartFruit"(即 MaaPostTask 接口传入 "StartFruit"),会先识别 Apple,画面中没有,所以继续识别 Orange,这次识别到了,则我们开始执行 Orange,不会再去识别 Banana 了。
执行 Orange 就是根据其 action 去进行对应的操作,当执行完成后,我们会再去识别 Orange 的 next。

Orange 的 next 中,
若识别到了 Cat,则不会继续去识别 Dog 了。这时同样会去执行 Cat 的 action,并在 action 完成后继续识别 Cat 的 next。
若 Cat, Dog 都没有识别到,我们会再次尝试识别这两个,直至超时为止。

如此循环,直至某个任务的 next 为空,即认为任务完成。

属性字段

注:对于必选字段,Pipeline JSON 文件中仍可为空,并在实际执行前通过接口设置。

  • recognition : string
    识别算法类型。可选,默认 DirectHit
    可选的值:DirectHit | TemplateMatch | FeatureMatch | ColorMatch | OCR | NeuralNetworkClassify | NeuralNetworkDetect | Custom
    详见 算法类型

  • action: string
    执行的动作。可选,默认 DoNothing
    可选的值:DoNothing | Click | Swipe | Key | Text | StartApp | StopApp | StopTask | Custom
    详见 动作类型

  • next : string | list<string, >
    接下来要执行的任务列表。可选,默认空。
    按序识别每个任务,只执行第一个识别到的。

  • is_sub: bool
    是否是子任务。可选,默认否。
    如果是子任务,执行完本任务(及后续 next 等)后,会返回来再次识别本任务 所在的 next 列表。
    例如:A.next = [B, Sub_C, D],这里的 Sub_C.is_sub = true,
    若匹配上了 Sub_C,在完整执行完 Sub_C 及后续任务后,会返回来再次识别 [B, Sub_C, D] 并执行命中项及后续任务。

  • inverse: bool
    反转识别结果,识别到了当做没识别到,没识别到的当做识别到了。可选,默认否。
    请注意由此识别出的任务,Click 等动作的点击自身将失效(因为实际并没有识别到东西),若有需求可单独设置 target

  • enabled: bool
    是否启用该 task。可选,默认 true。
    若为 false,则其他 task 的 next 列表中的该 task,会被跳过,既不会被识别也不会被执行。

  • timeout: uint
    next 识别超时时间,毫秒。默认 20 * 1000。

  • timeout_next: string | list<string, >
    超时后执行的任务列表。可选,默认空。

  • times_limit: uint
    任务执行次数。可选,默认 UINT_MAX。

  • runout_next: string | list<string, >
    任务执行次数达到了后执行的任务列表,可选,默认空。

  • pre_delay: uint
    识别到 到 执行动作前 的延迟,毫秒。可选,默认 200。
    推荐尽可能增加中间过程任务,少用延迟,不然既慢还不稳定。

  • post_delay: uint
    执行动作后 到 识别 next 的延迟,毫秒。可选,默认 500。
    推荐尽可能增加中间过程任务,少用延迟,不然既慢还不稳定。

  • pre_wait_freezes: uint | object
    识别到 到 执行动作前,等待画面不动了的时间,毫秒。可选,默认 0,即不等待。
    连续 pre_wait_freezes 毫秒 画面 没有较大变化 才会退出动作。
    若为 object,可设置更多参数,详见 等待画面静止
    具体的顺序为 pre_wait_freezes - pre_delay - action - post_wait_freezes - post_delay

  • post_wait_freezes: uint | object
    行动动作后 到 识别 next,等待画面不动了的时间,毫秒。可选,默认 0,即不等待。
    其余逻辑同 pre_wait_freezes

  • focus: bool
    是否关注任务,会额外产生部分回调消息。可选,默认 false,即不产生。
    详见 任务通知

实际业务逻辑举例

如前面举例,任务链是顺序执行的。

但实际业务逻辑在任务流水线中,大多是需要倒序判断的,以下就是一段典型的倒序判断的业务逻辑:

  • 实现启动 App 并点击 App 页面中的 Button 的业务。

  • 当 App 页面中不存在 Button 时会提示 NoButton

正常且完备的顺序如下:

graph LR;
    A[StartUp\nAnd\nClickButton] --> B[Start\nApp] --> C{Check\nInApp} --> |true| D{Click\nButton} --> |true| Z[Done];
    C --> |false| B;
    D --> |false| F{Find\nNoButton} --> |true| Z;
    F --> |false| C;
Loading

为了复用 StartAppCheckInApp 并解耦出业务核心 ClickButton ,我们引入了 is_sub 字段。

如果需要使用子任务 is_sub 字段,则需要将任务流水线中的判断倒序:

graph LR;
    A[StartUp\nAnd\nClickButton] --> B{Click\nButton} --> |true| C[Done];
    B --> |false| D{Flag\nNoButton} --> |true| C;
    D --> |false| E[Sub\nStartUp] --> F{Flag\nInApp} --> |true| A;
    F --> |false| G[Sub\nStartApp] --> E;
Loading

这是因为在一个判断倒序的流水线中,我们需要把:

  1. 任务的出口(即业务核心 ClickButton ,或者下一步)放在第一位。
  2. 任务的异常判断(即 NoButton )放在第二位。
  3. 任务的入口(即 StartUp )作为 子任务 放在第三位。
  4. 子任务(即 Sub_StartUp )也是如此(出口: Flag_InApp 、入口:Sub_StartApp )。
  5. 有且仅有一次(或有限次)的业务可以放在任务的出口之前,即第零位以便更快判断,例如弹出广告需要进行关闭。

实际业务的 json:

{
    "StartUpAndClickButton": {
        "next": [
            "Click_Button",
            "Flag_NoButton",
            "Sub_StartUp"
        ]
    },
    "Sub_StartUp": {
        "is_sub": true,
        "next": [
            "Flag_InApp",
            "Sub_StartApp"
        ]
    },
    "Sub_StartApp": {
        "is_sub": true,
        "action": "StartApp"
    },
    "Flag_InApp": {
        "recognition": "TemplateMatch",
        "template": "App.png"
    },
    "Flag_NoButton": {
        "recognition": "OCR",
        "expected": "NoButton"
    },
    "Click_Button": {
        "recognition": "OCR",
        "expected": "Button",
        "action": "Click"
    }
}

算法类型

DirectHit

直接命中,即不进行识别,直接执行动作。

TemplateMatch

模板匹配,即“找图”。

该任务属性需额外部分字段:

  • roi: array<int, 4> | list<array<int, 4>>
    识别区域坐标。可选,默认 [0, 0, 0, 0],即全屏。
    四个值分别为 [x, y, w, h]。

  • template: string | list<string, >
    模板图片路径,需要 image 文件夹的相对路径。必选。
    请注意所使用的图片需要是无损原图的裁剪。若使用安卓模拟器,请使用模拟器自带的截图功能!(不可以直接对模拟器窗口进行截图)

  • threshold: double | list<double, >
    模板匹配阈值。可选,默认 0.7 。
    若为数组,长度需和 template 数组长度相同。

  • order_by: string
    结果排序方式。可选,默认 Horizontal
    可选的值:Horizontal | Vertical | Score | Random
    可结合 index 字段使用。

  • index: int
    命中第几个结果。可选,默认 0。
    假设共有 N 个结果,则 index 的取值范围为 [-N, N - 1],其中负数使用类 Python 的规则转换为 N - index。若超出范围,则视为当前识别无结果。

  • method: int
    模板匹配算法,即 cv::TemplateMatchModes。可选,默认 5 。
    仅支持 1、3、5,可简单理解为越大的越精确,但也会更慢。
    详情请参考 OpenCV 官方文档

  • green_mask: bool
    是否进行绿色掩码。可选,默认 false。
    若为 true,可以将图片中不希望匹配的部分涂绿 RGB: (0, 255, 0),则不对绿色部分进行匹配。

FeatureMatch

特征匹配,泛化能力更强的“找图”,具有抗透视、抗尺寸变化等特点。

该任务属性需额外部分字段:

  • roi: array<int, 4> | list<array<int, 4>>
    识别区域坐标。可选,默认 [0, 0, 0, 0],即全屏。
    四个值分别为 [x, y, w, h]。

  • template: string | list<string, >
    模板图片路径,需要 image 文件夹的相对路径。必选。

  • count: int
    匹配的特征点的数量要求(阈值),默认 4。

  • order_by: string
    结果排序方式。可选,默认 Horizontal
    可选的值:Horizontal | Vertical | Score | Area | Random
    可结合 index 字段使用。

  • index: int
    命中第几个结果。可选,默认 0。
    假设共有 N 个结果,则 index 的取值范围为 [-N, N - 1],其中负数使用类 Python 的规则转换为 N - index。若超出范围,则视为当前识别无结果。

  • green_mask: bool
    是否进行绿色掩码。可选,默认 false。
    若为 true,可以将图片中不希望匹配的部分涂绿 RGB: (0, 255, 0),则不对绿色部分进行匹配。

  • detector: string
    特征检测器。可选,默认 SIFT
    目前支持以下算法:

    • SIFT
      计算复杂度高,具有尺度不变性、旋转不变性。效果最好。
    • KAZE
      适用于2D和3D图像,具有尺度不变性、旋转不变性。
    • AKAZE
      计算速度较快,具有尺度不变性、旋转不变性。
    • BRISK
      计算速度非常快,具有尺度不变性、旋转不变性。
    • ORB
      计算速度非常快,具有旋转不变性。但不具有尺度不变性。

    各算法特点详情可自行进一步查询。

  • ratio: double
    KNN 匹配算法的距离比值,[0 - 1.0], 越大则匹配越宽松(更容易连线)。可选,默认 0.6。

ColorMatch

颜色匹配,即“找色”。

该任务属性需额外部分字段:

  • roi: array<int, 4> | list<array<int, 4>>
    识别区域坐标。可选,默认 [0, 0, 0, 0],即全屏。
    四个值分别为 [x, y, w, h]。

  • method: int
    颜色匹配方式。即 cv::ColorConversionCodes。可选,默认 4 (RGB)。
    常用值:4 (RGB, 3 通道), 40 (HSV, 3 通道), 6 (GRAY, 1 通道)。
    详情请参考 OpenCV 官方文档

  • lower: list<int, > | list<list<int, >>
    颜色下限值。必选。最内层 list 长度需和 method 的通道数一致。

  • upper: list<int, > | list<list<int, >>
    颜色上限值。必选。最内层 list 长度需和 method 的通道数一致。

  • count: int
    符合的点的数量要求(阈值)。可选,默认 1。

  • order_by: string
    结果排序方式。可选,默认 Horizontal
    可选的值:Horizontal | Vertical | Score | Area | Random
    可结合 index 字段使用。

  • index: int
    命中第几个结果。可选,默认 0。
    假设共有 N 个结果,则 index 的取值范围为 [-N, N - 1],其中负数使用类 Python 的规则转换为 N - index。若超出范围,则视为当前识别无结果。

  • connected: bool
    是否是相连的点才会被计数。可选,默认否。
    若为是,在完成颜色过滤后,则只会计数像素点 全部相连 的最大块。
    若为否,则不考虑这些像素点是否相连。

OCR

文字识别。

该任务属性需额外部分字段:

  • roi: array<int, 4> | list<array<int, 4>>
    TemplateMatch.roi

  • expected: string | list<string, >
    期望的结果,支持正则。必选。

  • text: string | list<string, >
    已废弃,同 expected

  • replace: array<string, 2> | list<array<string, 2>>
    部分文字识别结果不准确,进行替换。可选。

  • order_by: string
    结果排序方式。可选,默认 Horizontal
    可选的值:Horizontal | Vertical | Area | Length | Random
    可结合 index 字段使用。

  • index: int
    命中第几个结果。可选,默认 0。
    假设共有 N 个结果,则 index 的取值范围为 [-N, N - 1],其中负数使用类 Python 的规则转换为 N - index。若超出范围,则视为当前识别无结果。

  • only_rec: bool
    是否仅识别(不进行检测,需要精确设置 roi)。可选,默认 false。

  • model: string
    模型 文件夹 路径。使用 model/ocr 文件夹的相对路径。可选,默认为空。
    若为空,则为 model/ocr 根目录下的模型文件。
    文件夹中需要包含 rec.onnx, det.onnx, keys.txt 三个文件。

NeuralNetworkClassify

深度学习分类,判断图像中的 固定位置 是否为预期的“类别”。

该任务属性需额外部分字段:

  • roi: array<int, 4> | list<array<int, 4>>
    TemplateMatch.roi

  • cls_size: int
    总分类数,必选。

  • labels: list<string, >
    标注,即每个分类的名字。可选。
    仅影响调试图片及日志等,若未填写则会填充 "Unknown"。

  • model: string
    模型文件路径。使用 model/classify 文件夹的相对路径。必选。
    目前仅支持 ONNX 模型。

  • expected: int | list<int, >
    期望的分类下标。

  • order_by: string
    结果排序方式。可选,默认 Horizontal
    可选的值:Horizontal | Vertical | Score | Random
    可结合 index 字段使用。

  • index: int
    命中第几个结果。可选,默认 0。
    假设共有 N 个结果,则 index 的取值范围为 [-N, N - 1],其中负数使用类 Python 的规则转换为 N - index。若超出范围,则视为当前识别无结果。

举例:例如画面中 固定位置 可能出现 猫、狗、老鼠,我们训练了支持该三分类的模型。
希望识别到 猫 或 老鼠 才点击,而识别到 狗 不点击,则相关字段为

{
    "cls_size": 3,
    "labels": ["Cat", "Dog", "Mouse"],
    "expected": [0, 2]
}

注意这些值需要与模型实际输出相符。

NeuralNetworkDetect

深度学习目标检测,高级版“找图”。

与分类器主要区别在于“找”,即支持任意位置。但通常来说模型复杂度会更高,需要更多的训练集、训练时间,使用时的资源占用(推理开销)也会成倍上涨。

该任务属性需额外部分字段:

  • roi: array<int, 4> | list<array<int, 4>>
    TemplateMatch.roi

  • cls_size: int
    总分类数,必选。

  • labels: list<string, >
    标注,即每个分类的名字。可选。
    仅影响调试图片及日志等,若未填写则会填充 "Unknown"。

  • model: string
    模型文件路径。使用 model/detect 文件夹的相对路径。必选。
    目前仅支持 YoloV8 ONNX 模型。

  • expected: int | list<int, >
    期望的分类下标。

  • threshold: double | list<double, >
    模型置信度阈值。可选,默认 0.3 。
    若为数组,长度需和 expected 数组长度相同。

  • order_by: string
    结果排序方式。可选,默认 Horizontal
    可选的值:Horizontal | Vertical | Score | Area | Random
    可结合 index 字段使用。

  • index: int
    命中第几个结果。可选,默认 0。
    假设共有 N 个结果,则 index 的取值范围为 [-N, N - 1],其中负数使用类 Python 的规则转换为 N - index。若超出范围,则视为当前识别无结果。

举例:例如画面中可能出现 猫、狗、老鼠,我们训练了支持该三分类的检测模型。
希望检测到 猫 或 老鼠 才点击,而识别到 狗 不点击,则相关字段为

{
    "cls_size": 3,
    "labels": ["Cat", "Dog", "Mouse"],
    "expected": [0, 2]
}

注意这些值需要与模型实际输出相符。

Custom

执行通过 MaaRegisterCustomRecognizer 接口传入的识别器句柄

该任务属性需额外部分字段:

  • custom_recognition: string
    任务名,同 MaaRegisterCustomRecognizer 接口传入的识别器名。必选。
  • custom_recognition_param: any
    任务参数,任意类型,会在执行时透传。可选,默认空 json,即 {}

动作类型

DoNothing

什么都不做。

Click

点击。

该任务属性需额外部分字段:

  • target: true | string | array<int, 4>
    点击的位置。可选,默认 true。
    - true: 点击本任务中刚刚识别到的目标(即点击自身)。
    - string: 填写任务名,点击之前执行过的某任务识别到的目标。
    - array<int, 4>: 点击固定坐标区域内随机一点,[x, y, w, h],若希望全屏可设为 [0, 0, 0, 0]。

  • target_offset: array<int, 4>
    target 的基础上额外移动再点击,四个值分别相加。可选,默认 [0, 0, 0, 0]。

Swipe

滑动。

该任务属性需额外部分字段:

  • begin: true | string | array<int, 4>
    滑动起点。可选,默认 true。值同上述 Click.target

  • begin_offset: array<int, 4>
    begin 的基础上额外移动再作为起点,四个值分别相加。可选,默认 [0, 0, 0, 0]。

  • end: true | string | array<int, 4>
    滑动终点。必选。值同上述 Click.target

  • end_offset: array<int, 4>
    end 的基础上额外移动再作为终点,四个值分别相加。可选,默认 [0, 0, 0, 0]。

  • duration: uint
    滑动持续时间,单位毫秒。可选,默认 200

Key

按键。

InputText

输入文本。

  • input_text: string
    要输入的文本,部分控制器仅支持 ascii。

StartApp

启动 App。

该任务属性需额外部分字段:

  • package: string
    启动入口。可选,默认空。
    需要填入 activity,例如 com.hypergryph.arknights/com.u8.sdk.U8UnityContext
    若为空,将启动 MaaControllerSetOption - MaaCtrlOption_DefaultAppPackageEntry 设置的入口。

StopApp

关闭 App。

该任务属性需额外部分字段:

  • package: string
    关闭要关闭的程序。可选,默认空。
    需要填入 package name,例如 com.hypergryph.arknights
    若为空,将关闭 MaaControllerSetOption - MaaCtrlOption_DefaultAppPackage 设置的 APP。

StopTask

停止当前任务链(MaaPostTask 传入的单个任务链)

Custom

执行通过 MaaRegisterCustomAction 接口传入的动作句柄

该任务属性需额外部分字段:

  • custom_action: string
    任务名,同 MaaRegisterCustomAction 接口传入的动作名。必选。
  • custom_action_param: any
    任务参数,任意类型,通过 MaaCustomRecognizerAPI 传入 json string。可选,默认空 json,即 {}

等待画面静止

等待画面静止。需连续一定时间 画面 没有较大变化 才会退出动作。

字段值为 uint 或 object,举例:

{
    "TaskA": {
        "pre_wait_freezes": 500,
    },
    "TaskB": {
        "pre_wait_freezes": {
            // more properties ...
        },
    },
}

若值为 object,可设置部分额外字段:

  • time: uint
    连续 time 毫秒 画面 没有较大变化 才会退出动作。可选,默认 1。

  • target: true | string | array<int, 4>
    等待的目标。可选,默认 true。值同上述 Click.target

  • target_offset: array<int, 4>
    target 的基础上额外移动再作为等待目标,四个值分别相加。可选,默认 [0, 0, 0, 0]。

  • threshold: double
    判断“没有较大变化”的模板匹配阈值。可选,默认 0.95 。

  • method: int
    判断“没有较大变化”的模板匹配算法,即 cv::TemplateMatchModes。可选,默认 5 。
    TemplateMatch.method

任务通知

详见 回调协议(还没写x

/*
{
    task_id: number,
    entry: string,
    uuid: string,
    hash: string,
    pre_hit_task: string,
    name: string,
    recognition: {
        id: number,
        box: [number, number, number, number],
        detail: string,
        hit: boolean,
    },
    node_id: number,
    status: number,
}
*/
#define MaaMsg_Task_Focus_ReadyToRun ("Task.Focus.ReadyToRun")
#define MaaMsg_Task_Focus_Runout ("Task.Focus.Runout")
#define MaaMsg_Task_Focus_Completed ("Task.Focus.Completed")