3. 动作生成API:动作生成接口设计、参数配置与数据校验、动作序列化与反序列化、动作库管理

各位好,我是老张。今天咱们聊聊动作生成API的设计。说实话,这个模块是整个系统的“心脏”。你想想看,动作怎么定义?怎么传参?怎么存?怎么取?搞不清楚这些,后面执行阶段全是坑。

我在好几个项目里都见过这种情况:动作定义得乱七八糟,参数校验形同虚设,序列化格式换来换去。结果呢?调试两天,上线三天就崩。嗯,咱们今天就把这块彻底理清楚。

3.1 动作生成接口设计

接口设计,说白了就是定规矩。你给外面的人(或者别的模块)一个入口,让他们能“告诉”系统:我要生成一个什么动作。

我个人习惯用RESTful风格。为什么?简单、直观、好调试。一个典型的动作生成接口长这样:

POST /api/v1/actions/generate
Content-Type: application/json

{
  "action_name": "pick_and_place",
  "action_type": "compound",
  "parameters": {
    "target_position": [120.5, 340.2, 85.0],
    "gripper_force": 15.0,
    "speed_profile": "smooth"
  },
  "constraints": {
    "max_velocity": 1.5,
    "max_acceleration": 0.8,
    "collision_check": true
  }
}

这里要注意几个点:

  • action_name:动作名称,必须唯一。我建议用下划线命名法,别整驼峰,工业场景下划线更清晰。
  • action_type:动作类型。我一般分三类——primitive(基础动作,比如直线移动)、compound(复合动作,比如抓取+放置)、sequence(序列动作,多个动作按顺序执行)。
  • parameters:动作参数。这是最灵活的部分,不同动作参数完全不同。
  • constraints:约束条件。安全相关的参数,我建议单独拎出来,别混在parameters里。
我的经验:接口设计时,一定要预留扩展字段。比如加一个"metadata"对象,里面放版本号、创建时间、作者信息。别问我为什么——有一次客户要求追溯每个动作是谁生成的,没有这个字段,我查了三天日志才找到。

3.2 参数配置与数据校验

参数配置这块,我踩过的坑比走过的路还多。你想想看,一个动作可能有几十个参数,每个参数的类型、范围、必填性都不一样。怎么管?

我的做法是:用Schema定义参数模板。每个动作类型对应一个Schema,里面写明每个参数的规则。

{
  "action_type": "pick_and_place",
  "schema": {
    "target_position": {
      "type": "array",
      "items": {"type": "number"},
      "minItems": 3,
      "maxItems": 3,
      "description": "目标位置 [x, y, z]"
    },
    "gripper_force": {
      "type": "number",
      "minimum": 5.0,
      "maximum": 50.0,
      "default": 15.0,
      "description": "夹爪力度 (N)"
    },
    "speed_profile": {
      "type": "string",
      "enum": ["slow", "normal", "smooth", "fast"],
      "default": "normal",
      "description": "速度曲线"
    }
  }
}

数据校验怎么做?我推荐用JSON Schema校验库。前端传过来的参数,先过一遍Schema,不合格的直接返回错误信息。

核心原则:校验要“早”且“狠”。早——在接口层就校验,别等到执行层才发现参数不对。狠——不合格的直接拒绝,别想着“差不多能用就行”。

我曾经在一个项目里,因为校验不够严格,允许了超出范围的夹爪力度。结果呢?夹爪直接把一个精密零件夹变形了。从那以后,我的校验逻辑里必加一条:所有数值参数必须有明确的上下界

3.3 动作序列化与反序列化

序列化,就是把内存里的动作对象转成可以存储或传输的格式。反序列化,就是反过来。工业场景里,最常用的格式是JSON和Protobuf。

我个人偏好JSON——可读性强,调试方便。但如果你对性能有极致要求,比如每秒要处理上千个动作,那Protobuf更合适。

一个典型的序列化示例:

// 动作对象 (Python示例)
class Action:
    def __init__(self, name, action_type, params, constraints):
        self.name = name
        self.action_type = action_type
        self.params = params
        self.constraints = constraints
        self.created_at = datetime.now()
        self.version = "1.0"

    def to_json(self):
        return json.dumps({
            "name": self.name,
            "type": self.action_type,
            "params": self.params,
            "constraints": self.constraints,
            "metadata": {
                "created_at": self.created_at.isoformat(),
                "version": self.version
            }
        }, indent=2)

    @classmethod
    def from_json(cls, json_str):
        data = json.loads(json_str)
        # 反序列化时一定要做版本兼容
        if data.get("metadata", {}).get("version", "1.0") != "1.0":
            # 做版本迁移逻辑
            pass
        return cls(
            name=data["name"],
            action_type=data["type"],
            params=data["params"],
            constraints=data["constraints"]
        )
注意:反序列化时,一定要做版本兼容处理。我曾经遇到过:旧版本的动作定义里有个字段叫"speed",新版本改成了"velocity"。结果反序列化时直接报错,整条产线停了20分钟。从那以后,我每个版本都写迁移脚本。

3.4 动作库管理

动作库,说白了就是你的“动作仓库”。里面存着所有定义好的动作模板。我见过最糟糕的做法:把动作定义散落在各个配置文件里,找起来跟大海捞针似的。

我的做法是:用数据库管理动作库。每个动作是一条记录,包含名称、类型、Schema、默认参数、版本号、创建时间等字段。

字段名 类型 说明
id UUID 唯一标识
name VARCHAR(128) 动作名称,唯一索引
type ENUM primitive / compound / sequence
schema JSON 参数模板定义
default_params JSON 默认参数值
version VARCHAR(16) 语义化版本号
status ENUM draft / published / deprecated
created_at DATETIME 创建时间
updated_at DATETIME 最后修改时间

动作库管理有几个关键操作:

  • 注册动作:新增一个动作模板,状态为draft。
  • 发布动作:审核通过后,状态改为published。已发布的动作不能修改,只能创建新版本。
  • 废弃动作:旧版本标记为deprecated,但保留数据,方便追溯。
  • 版本回滚:如果新版本有问题,可以快速切回旧版本。
一个小技巧:我习惯在动作库里加一个"tags"字段,用来给动作打标签。比如"焊接"、"搬运"、"检测"。这样查找动作时,按标签筛选,效率高很多。

知识体系总览

下面这张图,把咱们今天讲的内容串起来了。你一看就明白:动作生成API的各个模块是怎么配合的。

动作生成API 知识体系 接口层 (API Gateway) POST /api/v1/actions/generate | 参数接收 | 路由分发 校验层 (Validation) JSON Schema校验 | 参数类型检查 | 范围约束 | 必填项检查 序列化层 (Serialization) JSON序列化 | 版本兼容 | 字段映射 | 对象构建 存储层 (Action Library) 动作注册 | 版本管理 | 标签分类 | 状态控制

你看,整个流程是串起来的:接口层接收请求 → 校验层检查参数 → 序列化层转换格式 → 存储层入库管理。每一层各司其职,缺一不可。

好了,关于动作生成API的核心内容,今天就聊到这儿。记住:接口设计要清晰,校验要严格,序列化要兼容,库管理要规范。把这四点做好,你的动作生成系统就稳了。


专注资料整理