动作脚本语法

 

一、track_pose、pose

1. 概述

track_pose用于定义一套完整的“跟练操”中的一个独立动作。系统通过解析该文件,结合 Mediapipe 等姿态估计算法输出的骨骼姿态点数据,实时判断用户动作是否达标。

一个配置文件代表**一套操**,由若干个 `<track_pose>` 块组成。系统将按顺序执行这些块,只有当前 `<track_pose>` 内的所有 `<pose>` 姿态判定**同时满足**后,才会进入下一个 `<track_pose>` 动作。

 

2. 标签结构定义

2.1 <track_pose>标签(动作单元)

  • 含义:定义操中的一个独立动作。
  • 结构:该标签内可包含一个或多个 `<pose>` 子标签。
  • 执行逻辑:内部的所有 `<pose>` 判定条件构成 **“与(AND)”** 逻辑关系。即只有当所有内部 `<pose>` 的判断结果均为 `True` 时,该 `<track_pose>` 才算达标,系统才会切换至下一个动作。

2.2 <pose>标签(姿态判断单元)

  • 含义:定义单个具体的姿态约束条件。
  • 结构:通过若干个配置属性(Attribute)定义计算类型、目标数值范围及提示语。
  • 执行逻辑:根据 `type` 和 `operand` 计算出一个最终数值,并将其与 `min` 和 `max` 组成的闭区间 `[min, max]` 进行比较。若落在区间内,则判定成立。

3. <pose> 标签字段详细说明

字段名必需数据类型说明
landmarks字符串指定参与计算的 Mediapipe 骨骼姿态点索引。根据 `type` 不同,格式有所区别(详见下文)。
type枚举判断类型。可选值:`angle3p`, `angle2p`, `diff`。 
operand枚举运算单元类型。可选值:`point`, `x`, `y`, `dist_x`, `dist_y`。
name字符串该姿态判定的描述名称,用于日志记录或开发调试。
min条件浮点数判定达标的下限阈值(包含该值)。如果不出现,视为 `-∞`(或根据算法默认),但 `min` 和 `max` 至少出现一个。
max条件浮点数判定达标的上限阈值(包含该值)。如果不出现,视为 `+∞`(或根据算法默认),但 `min` 和 `max` 至少出现一个。
unsatisfied_msgstr字符串

当未设置 unsatisfied_rmax_msgstr 时:只要姿态不满足范围(无论偏大还是偏小),均播报此提示语。
当设置了 unsatisfied_rmax_msgstr 时:该字段仅表示计算值小于 min 下限时的语音提示。

unsatisfied_rmax_msgstr字符串表示计算值大于 'max' 上限时的语音提示。与 'unsatisfied_msgstr'配合使用,实现差异化引导。
abs布尔值仅对 type="diff"operand="x"operand="y"有效。true表示对计算结果取绝对值后再与 [min, max]比较;false(默认)或不填,则使用原始差值比较。 

 

4. 姿态点索引解析规则(包含伪姿态点)

4.1 真实姿态点索引(0 ~ 32)

Mediapipe 输出的 33 个骨骼姿态点索引范围固定为 0 到 32。脚本中直接使用这些数字即可(如 11 代表左肩,0 代表鼻子)。

 

4.2 伪姿态点索引(从 1000 起始)

为了解决画面绝对位置(如画面中心)的参考需求,系统专门预留了从 1000 开始的大数字作为伪姿态点索引。这些索引并非真实的骨骼,而是引擎内部硬编码的物理坐标。

当前系统预置的伪姿态点如下:

伪索引数字语义名称等效物理坐标(归一化 0~1)
1000画面正中心 (CENTER)(0.5, 0.5)

:为了便于脚本编写者理解,允许在底层解析时用单词替换。但在动作配置文件中,必须使用数字 1000 进行配置,以保证结构体字段 int 类型的统一。

 

5. landmarks 字符串的解析法则

在解析 landmarks 字段时,系统将严格遵循以下优先级:

  1. 分隔符:使用 分号 (;) 将 landmarks 字符串切割为左侧和右侧两个运算单元
  2. 左侧/右侧单元内部解析
    逗号 (,) 规则:如果某个运算单元内部出现逗号(如 "11,12"),则强制解析为“这两点求坐标平均值(中点)”
    单数字规则:如果只有一个数字(如 "0" 或 "16"),则直接提取该关键点的坐标。
    伪姿态点规则:如果数字 >= 1000(如 1000),则系统不访问 Mediapipe 数据,而是直接返回预置的固定坐标(如 (0.5, 0.5))。
  3. 计算执行:根据 operand 类型,提取两个单元的 (x, y) 或单一维度进行计算。

 

6. 数据类型(`type`)与 `landmarks` 格式详解

根据 `type` 的不同,`landmarks` 的解析方式及 `operand` 的取值范围均有明确规定。

 

6.1 类型:angle3p(三点角度)

  • 功能:计算三点构成的内角,取值范围:[0, 180]
  • 几何定义:假设三点为 A、B、C,以 B 为顶点,计算射线 BA 与 BC 之间的夹角。
  • landmarks 格式:`"A点索引; B点索引; C点索引"`(注意:必须是分号分隔的3个数字)。
  • operand 限制:必须为 `point`。系统将提取这3个点的 `(x,y)` 坐标进行计算。
  • 说明**:A、C互换位置(如 `11;13;15` 与 `15;13;11`)不影响计算结果。

 

6.2 类型:`angle2p`(两点逆时针角)

  • 功能:计算两点连线相对于水平正X轴的逆时针旋转角,取值范围:[0, 360)
  • 几何定义:以第一个点 A 为原点,画一条水平向右的射线(极轴),计算该射线绕 A 点逆时针旋转到射线 AB 所经过的角度。
  • `landmarks` 格式:`"A点索引, B点索引"`(**注意:必须是逗号分隔的2个数字**)。
  • `operand` 限制:必须为 `point`。系统将提取这2个点的 `(x,y)` 坐标进行计算。
  • 注意事项:图像坐标系中 Y 轴向下,但在 `angle2p` 计算中,角度严格按照数学坐标系(Y轴向上)的逆时针计算。

 

6.3 类型:`diff`(差值计算)

  • 功能:计算两个运算单元(由 `operand` 定义)之间的数值差。
  • `landmarks` 格式:`"单元1; 单元2"`(注意:必须是分号分隔)。
  • 返回值:默认返回 `单元1计算结果 - 单元2计算结果`。结果可为负数、零或正数。
  • `operand` 限制:由 `operand` 具体值决定计算细节

 

7. 运算单元(`operand`)类型详解

`operand` 指定了从 `landmarks` 中提取的数据形式,它决定了参与 `diff` 计算或 `angle` 计算的基础实体是什么。

`operand` 值适用 `type``landmarks` 格式说明运算单元解析说明
pointangle3p
angle2p
diff
1. `angle3p`/`angle2p`:**多个点**
2. `diff`:**`"A点索引; B点索引"`**
欧式距离:当用于 `diff` 时,表示计算两个姿态点 A 和 B 在图像上的直线距离。公式:`sqrt((x_A-x_B)² + (y_A-y_B)²)`。结果为非负数
xdiff"A点索引; B点索引"X轴坐标差:计算 `A点.x - B点.x`。
注意:若配置了 `abs="true"`,则结果为 `abs(A点.x - B点.x)`。
ydiff"A点索引; B点索引"Y轴坐标差:计算 `A点.y - B点.y`。
注意:若配置了 `abs="true"`,则结果为 `abs(A点.y - B点.y)`。
dist_xdiff"A点索引; B点索引"水平距离:计算两点X轴坐标差的绝对值,即 `abs(A点.x - B点.x)`。结果为非负数。自带绝对值效果。 
dist_ydiff"A点索引; B点索引"垂直距离:计算两点Y轴坐标差的绝对值,即 `abs(A点.y - B点.y)`。结果为非负数。自带绝对值效果。

特别说明:当 landmarks 中出现了伪姿态点索引(如 1000)时,系统在运行期取点时会自动将其替换为对应的固定坐标 (0.5, 0.5),上述所有 operand 的计算逻辑对该伪坐标完全适用。

 

8. 编写规则与补充示例解析

规则强调:

  1. `min` 与 `max`:若只定义 `min=145`,则条件隐式为 `[145, +∞)`;若只定义 `max=0.16`,则条件为 `(-∞, 0.16]`。为避免混淆,建议显式定义两个边界。
  2. 坐标归一化:Mediapipe 输出的坐标通常是归一化的相对坐标。因此 `diff` 的阈值通常是极小的浮点数(如 0.16、0.07),代表相对画面宽高比例的距离。
  3. 安全校验:引擎在执行时,若 `landmarks` 中的某个姿态点被 Mediapipe 判定为隐藏(`visibility` 或 `presence` 为 0)或不在画面内,当前 `pose` 判断应直接视为**失败**。

补充示例 1:上下限差异化提示

[pose]
    landmarks="12; 14"
    max=280
    min=260
    name="右上臂角度"
    operand="point"
    type="angle2p"
    unsatisfied_msgstr="手肘弯曲太小,身体向后移一些"    <!-- 当计算值 < 260时触发 -->
    unsatisfied_rmax_msgstr="手肘弯曲太大,身体向前移一些" <!-- 当计算值 > 280时触发 -->
[/pose]

解析:这是一个 `angle2p` 角度判断。当角度低于 `min=260` 时,提示用户“向后移”;当角度高于 `max=280` 时,提示用户“向前移”。这提供了极高的用户容错引导能力。

 

补充示例 2:绝对差值判定(`abs`的应用)

[pose]
    abs=true
    landmarks="7; 8"
    min=0.015
    name="abs(左耳.y-右耳.y)"
    operand="y"
    type="diff"
    unsatisfied_msgstr="让两耳更加倾斜" 
[/pose]

解析:计算 `左耳.y - 右耳.y`。默认情况下结果可能为负(右耳较高)或正(左耳较高)。有了 `abs="true"`,系统会取绝对值。只要**头部左右倾斜的绝对值**小于 `0.015`(即头部基本保持垂直不歪斜),就算达标。如果用于检测“歪头”超标,则可将此处的逻辑反转使用。结合 `unsatisfied_msgstr` 在未达标时给与用户清晰指引。

全部评论: 0

    写评论: