Skip to main content
Glama
Plant Simulation Research Bridge

Plant Simulation Research Bridge

Plant Simulation Research Bridge (psbridge)

面向可重复调度实验的 Plant Simulation 控制层。它不是把两个上游 MCP 项目的 61 个工具拼在一起,而是围绕一个更窄、更严格的目标重建:

给定调度实例与派工策略 -> 在隔离模型副本上批量运行 -> 标准化指标
-> 独立实现交叉核验 -> 可复现的结果记录

当前状态(必须如实阅读)

部分

状态

依据

实例模型、派工策略、参考 oracle、指标、有效性门禁、实验运行与落盘

已验证

完整 pytest 通过,含引擎与独立 oracle 的随机实例交叉核验

COM 网关、安全操作层、Fake 后端

已验证(Fake 后端)

tests/test_com_executor.py、test_com_fake_backend.py、test_core_ops.py、test_core_validation.py

Plant Simulation 13 的 COM 表面

已实测

30 个有界探测,证据在 ../evidence/plant-sim-bridge/real-machine-probe/

Win32 COM 后端(按实测修正后)

已验证(基础 COM)/ 局部桩测

连接/加载/创建/读写/控制/连线/MU/指标 VERIFIED;与模型会话相关的边界修复在 tests/ 中用 COM 桩测试

实机单线闭环与已实测 SimTalk 生成器

已验证

1000 s 跑出 100 件三次完全一致;dispatch.py / jobshop.py 已实机通过;离线模板 psbridge/simtalk/templates.py 仍标 NOT_VERIFIED

排程驱动投料 + 多机选路

已验证

3 作业 / 2 机:18 件全部产出并排空,工时与利用率逐项手算对得上;scripts/real_machine_dispatch_smoke.py

多工序作业车间(DFJSP 路线原型)

已验证(有边界)

2 作业 x 2 工序 x 2 机交叉工艺(工序间缓冲防死锁):40 件全部按路线走完并排空,M1 120 s / M2 200 s 与工序数完全对账;scripts/real_machine_jobshop_smoke.py

MCP 传输层(stdio JSON-RPC 2.0)与工具层

已验证

共注册 30 个工具(9 个实验/SimTalk 工具 + 21 个模型/仿真/方法工具,模型会话通过单 STA ComExecutor 串行化);psbridge/mcp/server.py 经 scripts/mcp_stdio_smoke.py 真子进程校验通过

没有实机验收之前,任何涉及 Plant Simulation 的结论都不能作为论文证据。 这不是免责声明,而是本项目的有效性门禁设计的一部分:每份结果记录都带有 backend 与 engine_kind 字段,假引擎的结果永远不会被误认为实机结果。

Related MCP server: MarketCanvas-Env MCP Server

实机实测结论(2026-10-28)

本机确实安装了 Tecnomatix Plant Simulation 13。已用 30 个有界探测实测其 COM 表面,记录在 ../evidence/plant-sim-bridge/real-machine-probe/FINDINGS.md。 结论分两部分,必须一起读:

已通的部分:Dispatch 启动独立隐藏实例、GetValue("Version") → 17000000、Quit 干净退出、LoadModel/SaveModel、 <class>.createObject(<frame>, x, y) 创建对象、NumNodes/node(i) 枚举、 表格单元读写、GetValue(<表达式>) 回读、EventController.reset/start/stop 控制仿真。26 个探测全部 exit 0,单次 COM 调用最慢 0.289 s(多数 0.000 s), 整套约 36 s,leaked_pids = [](无残留进程)。

后来打通的部分(关键是找到本机自带的帮助文件):本机安装目录里有 Help/PlantSimulationENU.chm(7-Zip 可解,13382 个 HTML),照着它改了两处:

  • 连线是 .MaterialFlow.Connector.connect(a, b)——接收者是 Connector 类, 不是对象、不是框架、也不是自由函数;

  • MU 用 MuSelection + Path + TimeOfGeneration + Interval 配置 ——Source 根本没有 MU / Count 这两个属性;

  • 限定时长用 EventController.End(相对时长;EndTime 不存在), 并轮询 isRunning 等到结束——start 是异步的,睡一觉再读会读到移动靶。

实测:Source → SingleProc → Drain,1000 秒、10 秒投料、4 秒加工 → 100 个 工件,StatRelativeOccupation = 0.4,StatWorkingTime = 400 秒; 连续三次运行完全一致。三个数字可以手算互证(1000/10=100 件;100×4=400 秒; 400/1000=0.4),所以这是可核验的闭环,不是"看起来跑起来了"。

实测推翻了两个上游项目共同的三个假设(这是本次最有价值的发现):

上游假设

实测结果

根框架是 .Models.Model

是 .Models.<模型名>.Frame,模型名来自文件内容而非文件名;NewModel() 出来的框架完全不可寻址

NumChildren 判断创建成功

建了 3 个对象仍返回 '0',必须用 NumNodes

模型上建 PsbridgeResult 属性做两段式回读

属性不存在,赋值报"标识符未知";直接 GetValue(<表达式>) 即可

另有两条:信息流类必须带 & 前缀(.InformationFlow.&TableFile); 时间属性只能走 ExecuteSimTalk + 数字秒,SetValue 传字符串必失败。

第三条容易踩的坑:SimTalk 的 for 循环用 next 关闭,不是 end。 早期所有多行片段报"源代码包含语法错误"都是因为这个,而不是 var 声明 不可用;print() 的输出也读不回来,结构化结果只能写表格。

边界(必须和结论一起说):2026-10-28 的初次单线闭环只是固定投料节奏;后续已在此基础上用 scripts/real_machine_dispatch_smoke.py(排程投料表 + Method 多机选路)和 scripts/real_machine_jobshop_smoke.py(2x2 交叉路线 + 缓冲防死锁)跑通真机原型。当前仍未实机验证的范围:同机多工序动态切换 ProcTime 的时间表达式、通用模板 psbridge/simtalk/templates.py 与 Table_Ready 决策闭环接线、以及含动态到达/柔性候选机的完整 DFJSP 调度器闭环——不要写成"通用 DFJSP 实验引擎已在实机全通"。

为什么需要这一层

对两个上游项目的源码审计结论(证据见 ../evidence/plant-sim-audit/,72 条主张 独立复核:68 CONFIRMED / 1 PARTIALLY_CONFIRMED / 3 NOT_VERIFIABLE_STATIC):

  • Hsiang-Chin/plant-sim-mcp:有专用 COM 单线程执行器,但多步操作共享 ApiResult,缺少操作级原子性(api result 单槽位 + 14 处读取点,COM 层唯一锁 只护连接);create_device 会先删除同名对象;属性设置可能在不适用时静默跳过 却仍报告成功。仓库没有许可证文件,不能复制源码。

  • Lang7910/PlantSimulation_mcp_skill:MIT 许可、45 个工具、有 Method/DataTable/ 模型探索能力,但没有显式 STA 执行器、没有批量实验/随机种子/指标层; save_model 指定新路径后未同步控制器路径;范围读取逐单元格调用 COM。

所以本项目的定位是:借鉴 A 的 COM 线程纪律与 B 的工具覆盖面,重建一个实验优先 的桥接层,并把"可复现、可核验"作为硬约束。审计发现到设计对策的逐条映射见 docs/AUDIT_TO_DESIGN.md。

架构

MCP / AI 客户端(python -m psbridge.mcp,stdio JSON-RPC 2.0)
      |
psbridge.experiment    实例、批量运行、指标、有效性门禁、结果落盘
      |                (FakeDispatchEngine 或真实 SimTalk 引擎)
psbridge.scheduling    FIFO/SPT/EDD 策略、独立参考 oracle、决策环境
      |
psbridge.com           单线程 COM 网关、后端协议、Win32/Fake 后端
      |
Tecnomatix Plant Simulation (COM + SimTalk)

核心设计约束:

  1. 实验层与 COM 层解耦。 DispatchEngine 协议是唯一接缝,假引擎与未来的 SimTalk 引擎共享同一套语义(S1–S9),因此实验方法论可以在没有 Plant Simulation 的机器上完整开发和验证。

  2. 两个独立实现互相核验。 psbridge/scheduling/reference.py 是从书面规范独立 写出的 oracle,不读引擎实现;随机实例上两者必须给出完全相同的调度。

  3. 失败绝不静默。 无效调度、跨核验不一致、引擎异常分别记为 invalid / failed, 仍然落盘,但永远不会被计入有效结果。

  4. 只改副本。 实验在模型克隆上运行,原模型文件 sha256 前后比对,变化即失败。

快速开始

python -m pytest                      # 完整测试,无需 Plant Simulation
python -m psbridge.demo               # FIFO/SPT/EDD 对比,多个随机种子
python -m psbridge.demo --json        # 同上,输出 JSON

# MCP 传输层:python -m psbridge.mcp 启动 stdio 服务器
# 工具层(纯函数,无传输依赖)
python -c "from psbridge import tools; print(tools.tool_names())"

# 实机验收脚手架(默认 dry-run,只生成 SimTalk 源码与参考调度)
python scripts/real_machine_smoke.py --instance .psbridge-work/instance_demo.json --policy fifo

示例输出(demo 实例,5 工件 x 3 工序,4 台机器,3 个种子,5% 工期抖动):

policy   runs  valid  invalid  failed   makespan(mean/min/max)   tardiness(mean)  tardy_jobs  wip
edd          3      3        0       0   29.07/28.74/29.37                   0.00        0.00 2.84
fifo         3      3        0       0   23.24/22.68/23.90                   0.93        1.00 3.30
spt          3      3        0       0   23.99/23.85/24.22                   0.78        1.00 3.23

这个结果本身不是研究结论(实例太小、策略太简单),它的作用是证明闭环可跑通、 指标可计算、记录可复现。

目录

  • psbridge/schema.py 实例数据模型与严格校验(稳定契约)

  • psbridge/errors.py 错误层级与错误码(稳定契约)

  • psbridge/config.py 运行时配置(超时、路径白名单、后端选择)

  • psbridge/experiment/ 引擎协议、批量 runner、指标、有效性检查、落盘

  • psbridge/scheduling/ 派工策略、独立参考实现、RL 决策环境

  • psbridge/com/ COM 网关与后端协议(Win32 / Fake)

  • psbridge/core/ 经过验证的安全操作层

  • psbridge/simtalk/ SimTalk 代码生成(部分假设已被实测推翻,见 docs/REAL_MACHINE_CHECKLIST.md §7)

  • psbridge/tools.py MCP 就绪的工具层(30 个工具:9 个实验/离线工具 + 21 个模型/仿真/方法工具;模型会话走单 STA ComExecutor,无传输依赖)

  • psbridge/mcp/ stdio JSON-RPC 2.0 传输层(python -m psbridge.mcp)

  • psbridge/demo.py 闭环演示

  • scripts/real_machine_smoke.py 实机验收脚手架(默认 dry-run)

  • tests/ 无 Plant Simulation 也能运行的完整测试

  • docs/ 架构、审计映射、实机验收清单

明确不在 v0.1 范围内

  • MCP 传输层 已完成:psbridge/mcp/ 提供 stdio JSON-RPC 2.0 服务器,覆盖 initialize / tools/list / tools/call / ping / notifications。HTTP 传输未做。

  • 多工序作业车间:已跑通(psbridge/simtalk/jobshop.py,真机 smoke 七项校验全过)。关键是用容量足够的工序间缓冲吸收被阻塞的零件,机器一处理完立刻把件放走,因此不会出现「占着机器等下一台」的死锁。仍未覆盖:同一台机器上不同工序需要不同加工时间(需时间表达式,未验证);TableFile 投料表的列类型映射也仍未解。

  • SimTalk 决策引擎的真实实现与 MU/Table_Ready 接线:依赖上一项。

  • 柔性路由(多候选机器)、非单位机器容量:引擎对这些输入明确抛 EngineUnsupported,不会给出错误的答案。

  • DFJSP(动态到达)、工人/运输资源耦合、强化学习训练:等闭环在实机通过后再扩展。

许可证与来源

本项目为 MIT。未从无许可证的 Hsiang-Chin/plant-sim-mcp 复制任何源码; 接口设计参考了 MIT 许可的 Lang7910/PlantSimulation_mcp_skill,详见 THIRD_PARTY_NOTICES.md。

Available Tools

30 tools
bridge_infoA

Return bridge version, available policies/backends, and verification status.

Inputs: no named parameters.

compare_policiesC

Run FIFO/SPT/EDD (or a subset) over seeds and compare standard metrics with reference cross-check.

Inputs: instance (required), seeds, jitter, horizon, +2 more.

experiment_summaryB

Aggregate stored run records (counts by status/policy, metric aggregates, validity failures).

Inputs: work_dir.

generate_simtalkC

Generate model/table/dispatch/result SimTalk templates for Plant Simulation (NOT_VERIFIED).

Inputs: policy (required), instance (required).

list_runsC

List stored run records under a work directory.

Inputs: work_dir.

method_createC

Create a Method object in a frame and write its SimTalk source.

Inputs: name (required), source (required), work_dir, frame_path, +1 more.

method_get_sourceC

Read a Method's SimTalk source.

Inputs: path (required), work_dir, model_root.

method_set_sourceB

Replace a Method's SimTalk source; the write is read back and compared.

Inputs: path (required), source (required), work_dir, model_root.

model_connect_objectsC

Connect a source to a target with a MaterialFlow connector.

Inputs: source (required), target (required), work_dir, frame_path, +1 more.

model_create_deviceC

Create a device from the measured class allow-list and return its path.

Inputs: name (required), class_name (required), x, y, +3 more.

model_delete_deviceB

Delete one object. Requires confirm=true; never deletes the frame.

Inputs: target (required), confirm (required), work_dir, frame_path, +1 more.

model_get_propertyC

Read one writable attribute of an object.

Inputs: path (required), attribute (required), work_dir, frame_path, +1 more.

model_list_objectsC

List the objects in a frame (name and real class path per object).

Inputs: work_dir, frame_path, model_root.

model_object_infoC

Return one object's name and real class path.

Inputs: path (required), work_dir, model_root.

model_openC

Load a .spp model into the running Plant Simulation and fingerprint the file.

Inputs: path (required), work_dir, model_root.

model_read_countersC

Read StatNumIn, StatNumOut and StatWorkingTime for named objects in a frame.

Inputs: objects (required), work_dir, frame_path, model_root.

model_set_propertyC

Write one attribute declared writable for that object class, then read it back.

Inputs: path (required), value (required), attribute (required), work_dir, +2 more.

model_statusB

Report whether a model session is connected and which model it tracks.

Inputs: work_dir, model_root.

mu_create_attributeC

Declare a custom attribute on the MU class (e.g. OpIndex, integer).

Inputs: kind (required), name (required), work_dir, model_root.

object_set_controlC

Attach a Method as an object's EntranceCtrl, ExitCtrl or InitCtrl.

Inputs: path (required), method (required), control (required), work_dir, +1 more.

reproduce_runB

Run the same instance/policy/seed several times and verify identical schedules and metrics.

Inputs: policy (required), instance (required), seed, jitter, +2 more.

run_experimentC

Run one dispatch policy over one or more seeds and persist reproducible records.

Inputs: policy (required), instance (required), seeds, jitter, +2 more.

schedule_vs_referenceB

Compare the dispatch engine schedule with the independent reference oracle for one policy.

Inputs: policy (required), instance (required).

simulation_resetC

Reset the EventController without touching the model.

Inputs: work_dir, model_root.

simulation_runC

Start and block until the controller stops, polling isRunning.

Inputs: timeout, end_time, work_dir, model_root, +1 more.

simulation_set_sourceC

Make a Source emit a fixed number of parts, starting at a given time.

Inputs: path (required), units (required), interval (required), start, +3 more.

simulation_startB

Start the EventController. Returns immediately (measured: start is asynchronous).

Inputs: end_time, work_dir, model_root, statistics_start.

simulation_statusB

Report whether the EventController runs, the simulated time and the end period.

Inputs: work_dir, model_root.

simulation_stopB

Stop the EventController and report where it stopped.

Inputs: work_dir, model_root.

validate_instanceB

Validate a scheduling instance and report engine compatibility and summary statistics.

Inputs: instance (required).

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    C2.7/5.0

    Scored across 30 tools

    Disambiguation4/5

    Most tools have clearly distinct resource+action targets, and potentially overlapping pairs (simulation_start vs simulation_run, run_experiment vs compare_policies vs schedule_vs_reference) are differentiated by their descriptions. A few boundaries in the experiment group remain fuzzy, e.g. run_experiment vs reproduce_run vs schedule_vs_reference all execute a policy over seeds.

    Naming Consistency3/5

    Tools fall into clear families (model_*, simulation_*, method_*), but the pattern within families flips between noun_verb (model_status, simulation_status, experiment_summary) and verb_noun (model_open, simulation_start, validate_instance, list_runs). The unprefixed tools (bridge_info, generate_simtalk, object_set_control, mu_create_attribute) add further variation, though everything remains readable.

    Tool Count2/5

    30 tools is heavy relative to the apparent scope, and several (model_get_property/model_object_info, model_status/bridge_info) could plausibly be consolidated. The surface feels like it grew by adding one tool per capability rather than being scoped deliberately.

    Completeness3/5

    Scheduling (validate/run/reproduce/compare/list/aggregate) and model manipulation cover strong lifecycle depth, but there are gaps: no way to close or save a model session, no method delete or method listing, and deletion is limited to devices via model_delete_device. Agents can work around these but will hit dead ends when cleaning up or discovering existing methods.

    Maintenance

    ActivityMaintained
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      B
      quality
      B
      maintenance
      Enables controlling a local Scilab/Xcos installation to discover installed block libraries, create native block templates, read, write, and validate diagrams, and run simulations of arbitrary positive duration that return named numerical signal series. It exposes these capabilities as MCP tools over stdio or streamable HTTP, with model file access restricted to configured filesystem roots.
      11
      1
      GPL 3.0
    • A
      license
      Not graded
      quality
      Not graded
      maintenance
      Enables MCP-compatible clients such as Claude Desktop, Cursor, and Antigravity to invoke deterministic mathematical modeling and System 2 agent capabilities through a native STDIO JSON-RPC 2.0 server with zero external dependencies.
      MIT