完善 xyzbc-trt 刀具偏置闭环
This commit is contained in:
@@ -10758,3 +10758,75 @@ nginx: configuration file /etc/nginx/nginx.conf test is successful
|
|||||||
17. 执行 `git status --short`,确认推送后仅剩未跟踪生成目录 `app/dist/` 和 `tools/__pycache__/`。
|
17. 执行 `git status --short`,确认推送后仅剩未跟踪生成目录 `app/dist/` 和 `tools/__pycache__/`。
|
||||||
18. 执行 `git log -1 --oneline` 和 `git ls-remote origin refs/heads/master`,确认本地和远端 `master` 均为 `fb128e6`。
|
18. 执行 `git log -1 --oneline` 和 `git ls-remote origin refs/heads/master`,确认本地和远端 `master` 均为 `fb128e6`。
|
||||||
19. 本轮结论:源码、证据和工作文档已提交并推送到云仓库;未跟踪构建产物和 Python 缓存未提交。
|
19. 本轮结论:源码、证据和工作文档已提交并推送到云仓库;未跟踪构建产物和 Python 缓存未提交。
|
||||||
|
|
||||||
|
## 2026-07-02 09:14:51 EDT Codex 执行过程日志
|
||||||
|
|
||||||
|
1. 接收用户要求:接续上一轮,按 `/home/mes123456/cnc_wams/web-rtcp-5axis-xyzbc-trt-sim-plan/working` 持续编写程序。
|
||||||
|
2. 读取 workspace 规则,确认每轮结束必须将中文过程日志追加到 `/home/mes123456/cnc_wams/web-rtcp-5axis-sim-plan/gptlog-process/gpdlog.md`。
|
||||||
|
3. 检查目标目录文件,确认 `working` 下存在推进台账、任务矩阵、验收证据、全量对标矩阵和 evidence JSON。
|
||||||
|
4. 读取 `working/README.md`、`03-推进台账.md`、`04-任务矩阵.md`,确认当前主要缺口包含 T-014 浏览器 smoke、T-029 Vismach 3D pin 对标、T-034 tool-offset 闭环、T-019/T-037 native path 重采集。
|
||||||
|
5. 检查目标 app 源码、profile、Node smoke 和 package 脚本,确认默认 profile 已为 `xyzbc-trt`,已有 Web evidence 和 compare 脚本。
|
||||||
|
6. 读取 `five-axis-scene.js`、`store.js`、`main.js`、`collect-web-xyzbc-trt-evidence.mjs`、`linuxcnc-task-hal-runtime.js`、`tool-db-simulation.js`,确认 Three.js 机床参考模型仍是静态几何,尚未按 Vismach HAL pin 层级驱动。
|
||||||
|
7. 新增 `app/src/runtime/vismach-model-state.js`,统一生成 `table-x/saddle-y/spindle-z/tilt-b/rotate-c/tool-offset/x-offset/z-offset` pin 状态、模型变换、HAL net 对标关系和语义边界。
|
||||||
|
8. 修改 `app/src/visualization/five-axis-scene.js`,把参考模型拆成 `vismach-table-x`、`vismach-saddle-y`、`vismach-spindle-z`、`vismach-tilt-b`、`vismach-rotate-c`、`vismach-tool-offset` 层级,并在渲染时由 `buildVismachModelState()` 驱动位移和旋转。
|
||||||
|
9. 在 canvas dataset 中新增 `threeVismachPins`、`threeVismachTransforms`、`threeVismachPinDrivenModel`,供浏览器 smoke 验证 WebGL 模型和 HAL pin 语义。
|
||||||
|
10. 修改 `tools/collect-web-xyzbc-trt-evidence.mjs`,将 `vismachEquivalent` 从静态 pin 清单升级为包含 `pinValues`、`transforms`、`halNets` 和 `semanticBoundary` 的 evidence 字段。
|
||||||
|
11. 扩展 `tests/node/verify_xyzbc_trt_web_app.mjs`,增加 profile feedback/offset net 断言,以及 Vismach pin 到模型变换的 smoke 断言。
|
||||||
|
12. 运行 `npm --prefix web-rtcp-5axis-xyzbc-trt-sim-plan/app run smoke:node`,结果通过,输出 `xyzbc_trt_web_app_smoke=ok`。
|
||||||
|
13. 运行 `npm --prefix web-rtcp-5axis-xyzbc-trt-sim-plan/app run evidence:web`,重新生成 `working/evidence/web-xyzbc-trt-evidence.json`。
|
||||||
|
14. 抽查 Web evidence,确认 `status=ready-for-wasm-runtime`、`blockers=[]`、`previewPath.sampleCount=3074`、`executionPath.sampleCount=569`,并确认 `vismachEquivalent` 已包含 pin 值、变换和 9 条 HAL net。
|
||||||
|
15. 运行 `npm --prefix web-rtcp-5axis-xyzbc-trt-sim-plan/app run evidence:compare`,重新生成 compare JSON;结果为真实失败 `fail_count=5`,失败原因仍是 native `previewPath`/`executionPath` 样本和采样周期字段缺失。
|
||||||
|
16. 运行 `npm --prefix web-rtcp-5axis-xyzbc-trt-sim-plan/app run build`,结果通过,输出 `gmoccapy_static_build=ok`。
|
||||||
|
17. 更新 `working/03-推进台账.md`、`04-任务矩阵.md`、`05-验收证据.md`、`07-全量对标追踪矩阵.md`,记录 T-029 完成、Web evidence 字段和剩余 native path 缺口。
|
||||||
|
18. 检查已有浏览器 smoke,发现从参考项目复制的脚本仍指向 `web-rtcp-5axis-sim-plan`,并包含大量 `xyzac-trt` 假设,不适合作为当前目标项目 T-014 验收。
|
||||||
|
19. 新增 `tests/browser/xyzbc_trt_browser_smoke.html`,实现精简的 `xyzbc-trt` 浏览器验收:默认 profile、kinematics/interpreter/task-HAL worker runtime、默认程序预览、canvas 非空和 Vismach dataset。
|
||||||
|
20. 新增 `tests/browser/verify_xyzbc_trt_browser.sh`,通过临时 HTTP server 和 headless Chromium 加载 `app/dist/index.html`,执行浏览器 smoke。
|
||||||
|
21. 修改 `app/package.json`,增加 `smoke:browser` 脚本。
|
||||||
|
22. 执行 `chmod +x tests/browser/verify_xyzbc_trt_browser.sh`,然后运行 `npm --prefix web-rtcp-5axis-xyzbc-trt-sim-plan/app run smoke:browser`,结果通过,输出 `xyzbc_trt_browser_smoke=ok`。
|
||||||
|
23. 再次更新 `working/03-推进台账.md`、`04-任务矩阵.md`、`05-验收证据.md`、`07-全量对标追踪矩阵.md`,将 T-014 标记为完成,并记录浏览器 smoke 验收内容。
|
||||||
|
24. 执行 `git diff --check -- web-rtcp-5axis-xyzbc-trt-sim-plan`,未发现空白错误。
|
||||||
|
25. 执行 `git status --short web-rtcp-5axis-xyzbc-trt-sim-plan`,确认本轮修改包含 app/package、Vismach runtime、Three.js 场景、Web evidence 脚本、Node/browser smoke、working 文档和 evidence JSON;未跟踪的 `app/dist/` 与 `tools/__pycache__/` 为已有/生成物,未清理。
|
||||||
|
26. 本轮结论:T-029 Vismach 3D pin 对标和 T-014 目标浏览器 smoke 已完成并通过验证;compare 剩余失败仍来自 native path evidence 未重采集,下一步应推进 T-019/T-037 或 T-034。
|
||||||
|
27. 按前端应用规则尝试启动开发服务器:先运行 `npm --prefix web-rtcp-5axis-xyzbc-trt-sim-plan/app run dev`,端口 4174 已被占用,启动失败。
|
||||||
|
28. 尝试在 app 目录运行 `python3 -m http.server 4175`,端口 4175 也已被占用。
|
||||||
|
29. 通过 Python 端口探测找到 4176 可用。
|
||||||
|
30. 在 `/home/mes123456/cnc_wams/web-rtcp-5axis-xyzbc-trt-sim-plan/app` 运行 `python3 -m http.server 4176`,服务器已启动,访问地址为 `http://127.0.0.1:4176/`。
|
||||||
|
|
||||||
|
## 2026-07-02 Codex 执行过程日志 - T-034 tool-offset 闭环
|
||||||
|
|
||||||
|
1. 接收用户要求:接续上一轮,按 `/home/mes123456/cnc_wams/web-rtcp-5axis-xyzbc-trt-sim-plan/working` 持续编写程序。
|
||||||
|
2. 检查目标项目 `working` 目录、任务矩阵和推进台账,确认上一轮已完成 T-014 浏览器 smoke 与 T-029 Vismach pin 驱动模型,当前可继续推进 T-034 tool table 到 tool-offset 闭环。
|
||||||
|
3. 执行 `git status --short`,确认工作区已有上一轮未提交改动,包括 `app/package.json`、`five-axis-scene.js`、browser smoke、evidence JSON 和 working 文档;本轮在这些成果基础上继续,不回退用户或上一轮改动。
|
||||||
|
4. 读取 `app/src/runtime/tool-db-simulation.js`,确认已有 LinuxCNC tool table 解析、T/M6/G43/M61 命令模拟、activeToolOffset 和 interpreter parameter 5400-5413 生成能力。
|
||||||
|
5. 读取 `app/src/runtime/vismach-model-state.js`,确认 Vismach tool-offset 当时优先读取 `toolDbSimulation.activeToolOffset.offset.z`,否则回退 `toolPreview.length`。
|
||||||
|
6. 读取 `tools/collect-web-xyzbc-trt-evidence.mjs`,确认 Web path 样本 tool 字段仍使用 `firstTool(profile)`,没有从 staged `xyzbc-trt.tbl` 和 active G43 偏置生成。
|
||||||
|
7. 读取 `wasm-port/vendor/linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzbc-trt.tbl`,确认真实工具表包含 `T1 P1 D1` 和 `T2 P2 Z10 D8`。
|
||||||
|
8. 读取默认程序 `xyzbc_switchkins.ngc`,确认该程序调用子程序但自身没有 T/M6/G43;因此本轮设计为 evidence 同时记录程序扫描命令和工具表默认激活证据,避免伪造程序命令。
|
||||||
|
9. 修改 `app/src/runtime/tool-db-simulation.js`,新增 `createToolRuntimeState()`,统一输出当前工具、active offset、`motion.tooloffset.z` 等效值、下游 `xyzbc-trt-kins.tool-offset` 与 `xyzbc-trt-gui.tool-offset`、path tool 和 Vismach tool-offset。
|
||||||
|
10. 修改 `app/src/runtime/vismach-model-state.js`,让 `toolRuntimeState.vismach.toolOffset` 优先于旧的 `toolPreview.length`,使 Web 3D 模型刀具长度来自 active tool offset。
|
||||||
|
11. 修改 `tools/collect-web-xyzbc-trt-evidence.mjs`,引入 tool DB 解析和命令扫描逻辑,从 staged `xyzbc-trt.tbl` 创建 tool DB,并扫描选定程序中的 T/M6/G43。
|
||||||
|
12. 在默认程序无工具命令时,`collect-web-xyzbc-trt-evidence.mjs` 选择工具表中第一个带 Z 偏置的工具 T2,生成 T/M6/G43 默认激活证据,并记录 `defaultActivationUsed=true`。
|
||||||
|
13. 修改 Web path 采集逻辑,使 `previewPath.samples[].tool` 和 `executionPath.samples[].tool` 使用 `toolRuntime.pathTool`,即 T2/P2/Z10/D8。
|
||||||
|
14. 在 Web evidence 中新增 `toolRuntime` 和 `toolOffsetClosure` 字段,记录 source tool table、selected program、programToolCommands、activeToolOffset、kinematicsToolOffsetZ、pathTool、vismachToolOffset 和 closed 状态。
|
||||||
|
15. 扩展 `coverage.toolTableToToolOffsetClosed`,要求 tool table ready、active offset applied、kinematics/path/Vismach 三方 tool length 一致才通过。
|
||||||
|
16. 修改 `tests/node/verify_xyzbc_trt_web_app.mjs`,断言 staged `xyzbc-trt.tbl` 包含 `T2 P2 Z10 D8`。
|
||||||
|
17. 扩展 Node smoke,使用 T2/M6/G43 创建 tool runtime state,并断言 active tool number=2、pocket=2、current tool Z=10、diameter=8、kinematics toolOffsetZ=10、path tool length=10、Vismach toolOffset=10。
|
||||||
|
18. 扩展 Vismach smoke 断言,确认 `buildVismachModelState()` 在传入 toolRuntimeState 后输出 `pinValues.tool-offset=10`,tool transform Z 为 `-25`。
|
||||||
|
19. 运行 `npm --prefix app run smoke:node`,结果通过,输出 `xyzbc_trt_web_app_smoke=ok`。
|
||||||
|
20. 运行 `npm --prefix app run evidence:web`,重新生成 `working/evidence/web-xyzbc-trt-evidence.json`。
|
||||||
|
21. 抽查 Web evidence,确认 `toolRuntime.ready=true`、`activeOffsetApplied=true`、`activeToolNumber=2`、`activePocket=2`、`kinematics.toolOffsetZ=10`、`pathTool.length=10`、`pathTool.diameter=8`、`vismach.toolOffset=10`、`toolOffsetClosure.closed=true`、`coverage.toolTableToToolOffsetClosed=true`。
|
||||||
|
22. 运行 `npm --prefix app run evidence:compare`,重新生成 compare evidence,仍为真实失败 `fail_count=5`,失败原因仍集中在 native preview/execution path 样本缺失。
|
||||||
|
23. 运行 `npm --prefix app run build`,结果通过,输出 `gmoccapy_static_build=ok`。
|
||||||
|
24. 运行 `npm --prefix app run smoke:browser`,结果通过,输出 `xyzbc_trt_browser_smoke=ok`。
|
||||||
|
25. 更新 `working/04-任务矩阵.md`,将 T-034 从“待实现”改为“完成”,验收标准改为 T2/P2/Z10/D8 驱动 kinematics、path tool 和 Vismach tool-offset。
|
||||||
|
26. 更新 `working/05-验收证据.md`,新增 “Tool table 到 tool-offset 闭环验收” 章节,记录 smoke、evidence、compare、build、browser smoke 命令和 JSON 摘要。
|
||||||
|
27. 更新 `working/03-推进台账.md`,新增本轮 T-034 实现记录、修改文件、验证结果和下一步。
|
||||||
|
28. 更新 `working/07-全量对标追踪矩阵.md`,把 `xyzbc-trt.tbl` 与 `tool-offset/x-offset/z-offset` 的状态改为 Web evidence 已完成 tool table active offset 闭环,native 仍待重采集对比。
|
||||||
|
29. 修改 `tools/compare-xyzbc-trt-evidence.mjs`,新增 compare 检查 `web tool table active offset drives kinematics, path, and Vismach`,使 T-034 不只停留在 Web evidence,而是进入自动对比报告。
|
||||||
|
30. 重跑 `npm --prefix app run evidence:compare`,确认新增 T-034 检查通过,compare 摘要变为 `checkCount=24`、`passCount=19`、`failCount=5`。
|
||||||
|
31. 重跑 `npm --prefix app run smoke:node`,结果仍通过。
|
||||||
|
32. 更新 `working/04-任务矩阵.md` 中 T-017 摘要为当前 `19/24` 通过,剩余 5 项均为 native preview/execution path 样本缺失。
|
||||||
|
33. 更新 `working/05-验收证据.md` 与 `working/03-推进台账.md`,记录 compare 当前 19/24 通过以及 T-034 compare 检查通过。
|
||||||
|
34. 执行 `git diff --check -- web-rtcp-5axis-xyzbc-trt-sim-plan`,未发现空白或格式错误。
|
||||||
|
35. 执行 `git status --short` 和 `git diff --stat -- web-rtcp-5axis-xyzbc-trt-sim-plan`,确认本轮改动包含 tool DB runtime、Vismach state、Web evidence、compare、Node smoke、working 文档和 evidence JSON;未跟踪的 `app/dist/`、browser smoke 文件、Vismach state 文件等为上一轮/当前未提交工作区内容,未删除。
|
||||||
|
36. 本轮结论:T-034 已完成,Web evidence 与 compare 均证明 `xyzbc-trt.tbl` 的 T2/P2/Z10/D8 已闭环驱动 kinematics tool-offset、path JSON 和 Vismach tool-offset;剩余主要任务仍是 T-019/T-037 native path 重采集、T-026/T-038 AXIS/UI 状态流复核、T-028/T-030 basic_sim 与 Ngcgui/remap 执行验收。
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
"dev": "python3 -m http.server 4174",
|
"dev": "python3 -m http.server 4174",
|
||||||
"smoke": "npm run smoke:node",
|
"smoke": "npm run smoke:node",
|
||||||
"smoke:node": "node ../tests/node/verify_xyzbc_trt_web_app.mjs",
|
"smoke:node": "node ../tests/node/verify_xyzbc_trt_web_app.mjs",
|
||||||
|
"smoke:browser": "bash ../tests/browser/verify_xyzbc_trt_browser.sh",
|
||||||
"evidence:web": "node ../tools/collect-web-xyzbc-trt-evidence.mjs",
|
"evidence:web": "node ../tools/collect-web-xyzbc-trt-evidence.mjs",
|
||||||
"evidence:compare": "node ../tools/compare-xyzbc-trt-evidence.mjs"
|
"evidence:compare": "node ../tools/compare-xyzbc-trt-evidence.mjs"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -553,6 +553,78 @@ export function createToolDbReadiness(toolDb) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function createToolRuntimeState(toolDb, options = {}) {
|
||||||
|
if (!toolDb) {
|
||||||
|
return {
|
||||||
|
apiName: "web-rtcp-5axis-tool-runtime-state",
|
||||||
|
ready: false,
|
||||||
|
activeOffsetApplied: false,
|
||||||
|
toolInSpindle: 0,
|
||||||
|
toolFromPocket: 0,
|
||||||
|
currentPocket: 0,
|
||||||
|
activeToolNumber: 0,
|
||||||
|
activePocket: 0,
|
||||||
|
currentTool: null,
|
||||||
|
activeToolOffset: null,
|
||||||
|
kinematics: {
|
||||||
|
toolOffsetZ: 0,
|
||||||
|
source: "tool_db_not_ready",
|
||||||
|
},
|
||||||
|
pathTool: createPathTool(null, 0),
|
||||||
|
vismach: {
|
||||||
|
toolOffset: finiteNumber(options.fallbackToolLength, 0),
|
||||||
|
source: "fallback_tool_preview_length",
|
||||||
|
},
|
||||||
|
interpreterParameters: createToolParameters(null),
|
||||||
|
semanticBoundary: "linuxcnc_current_tool_offset_runtime_state_for_web_simulation",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const state = cloneToolDb(toolDb);
|
||||||
|
const activeOffset = state.activeToolOffset
|
||||||
|
? {
|
||||||
|
...state.activeToolOffset,
|
||||||
|
offset: { ...state.activeToolOffset.offset },
|
||||||
|
}
|
||||||
|
: null;
|
||||||
|
const currentTool = state.toolTableCurrent
|
||||||
|
? cloneToolEntry(state.toolTableCurrent)
|
||||||
|
: cloneToolEntry(state.toolTable.pockets[0] || createEmptyToolEntry({ idx: 0, pocket: 0, toolNumber: 0 }));
|
||||||
|
const activeToolNumber = activeOffset?.toolNumber
|
||||||
|
?? (currentTool.toolNumber > 0 ? currentTool.toolNumber : 0);
|
||||||
|
const activePocket = activeOffset?.pocket
|
||||||
|
?? (currentTool.toolNumber > 0 ? currentTool.pocket : 0);
|
||||||
|
const activeOffsetZ = activeOffset ? finiteNumber(activeOffset.offset?.z, 0) : 0;
|
||||||
|
|
||||||
|
return {
|
||||||
|
apiName: "web-rtcp-5axis-tool-runtime-state",
|
||||||
|
ready: state.processReady === true,
|
||||||
|
activeOffsetApplied: Boolean(activeOffset),
|
||||||
|
toolInSpindle: state.toolInSpindle,
|
||||||
|
toolFromPocket: state.toolFromPocket,
|
||||||
|
currentPocket: state.currentPocket,
|
||||||
|
activeToolNumber,
|
||||||
|
activePocket,
|
||||||
|
currentTool,
|
||||||
|
activeToolOffset: activeOffset,
|
||||||
|
kinematics: {
|
||||||
|
toolOffsetZ: activeOffsetZ,
|
||||||
|
source: activeOffset ? "activeToolOffset.offset.z" : "no_active_g43_tool_length_offset",
|
||||||
|
halPin: "motion.tooloffset.z",
|
||||||
|
downstreamPins: ["xyzbc-trt-kins.tool-offset", "xyzbc-trt-gui.tool-offset"],
|
||||||
|
},
|
||||||
|
pathTool: createPathTool(activeOffset || currentTool, activeOffsetZ),
|
||||||
|
vismach: {
|
||||||
|
toolOffset: activeOffset
|
||||||
|
? activeOffsetZ
|
||||||
|
: finiteNumber(options.fallbackToolLength, 0),
|
||||||
|
source: activeOffset ? "activeToolOffset.offset.z" : "fallback_tool_preview_length",
|
||||||
|
},
|
||||||
|
interpreterParameters: { ...state.interpreterParameters },
|
||||||
|
semanticBoundary: "linuxcnc_current_tool_offset_runtime_state_for_web_simulation",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function detectToolDbStorageCapability(globalScope = globalThis) {
|
export function detectToolDbStorageCapability(globalScope = globalThis) {
|
||||||
const forcedUnavailable = Boolean(globalScope.__WEB_RTCP_FORCE_OPFS_UNAVAILABLE__);
|
const forcedUnavailable = Boolean(globalScope.__WEB_RTCP_FORCE_OPFS_UNAVAILABLE__);
|
||||||
const isBrowser = typeof globalScope.window === "object" || typeof globalScope.document === "object";
|
const isBrowser = typeof globalScope.window === "object" || typeof globalScope.document === "object";
|
||||||
@@ -855,6 +927,23 @@ function createToolParameters(activeOffset) {
|
|||||||
return parameters;
|
return parameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function createPathTool(tool, length) {
|
||||||
|
return {
|
||||||
|
id: Number(tool?.toolNumber) || 0,
|
||||||
|
pocket: Number(tool?.pocket) || 0,
|
||||||
|
length: finiteNumber(length, 0),
|
||||||
|
diameter: finiteNumber(tool?.diameter, 0),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function finiteNumber(...values) {
|
||||||
|
for (const value of values) {
|
||||||
|
const number = Number(value);
|
||||||
|
if (Number.isFinite(number)) return number;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
function createToolDbEvent(code, payload = {}) {
|
function createToolDbEvent(code, payload = {}) {
|
||||||
return {
|
return {
|
||||||
apiName: "web-rtcp-5axis-tool-db-event",
|
apiName: "web-rtcp-5axis-tool-db-event",
|
||||||
|
|||||||
@@ -0,0 +1,111 @@
|
|||||||
|
const DEFAULT_LINEAR_UNITS = "mm";
|
||||||
|
|
||||||
|
export const XYZBC_TRT_VISMACH_PINS = [
|
||||||
|
"table-x",
|
||||||
|
"saddle-y",
|
||||||
|
"spindle-z",
|
||||||
|
"tilt-b",
|
||||||
|
"rotate-c",
|
||||||
|
"tool-offset",
|
||||||
|
"x-offset",
|
||||||
|
"z-offset",
|
||||||
|
];
|
||||||
|
|
||||||
|
export function buildVismachModelState(state = {}) {
|
||||||
|
const profile = state.profile || {};
|
||||||
|
const axisPose = resolveAxisPose(state);
|
||||||
|
const offsets = profile.offsets || {};
|
||||||
|
const toolOffset = resolveToolOffset(state);
|
||||||
|
const xOffset = finiteNumber(offsets.x, -20);
|
||||||
|
const zOffset = finiteNumber(offsets.z, -15);
|
||||||
|
const linearUnits = resolveLinearUnits(state);
|
||||||
|
|
||||||
|
return {
|
||||||
|
apiName: "web-rtcp-5axis-vismach-model-state",
|
||||||
|
profileId: profile.id || state.machineProfile || null,
|
||||||
|
sourceGui: "src/hal/user_comps/vismach/xyzbc-trt-gui.py",
|
||||||
|
webModel: "app/src/visualization/five-axis-scene.js",
|
||||||
|
linearUnits,
|
||||||
|
pins: {
|
||||||
|
"table-x": finiteNumber(axisPose.x, 0),
|
||||||
|
"saddle-y": finiteNumber(axisPose.y, 0),
|
||||||
|
"spindle-z": finiteNumber(axisPose.z, 0),
|
||||||
|
"tilt-b": finiteNumber(axisPose.b, 0),
|
||||||
|
"rotate-c": finiteNumber(axisPose.c, 0),
|
||||||
|
"tool-offset": toolOffset,
|
||||||
|
"x-offset": xOffset,
|
||||||
|
"z-offset": zOffset,
|
||||||
|
},
|
||||||
|
transforms: {
|
||||||
|
table: {
|
||||||
|
translate: { x: finiteNumber(axisPose.x, 0), y: 0, z: 0 },
|
||||||
|
sourcePins: ["table-x"],
|
||||||
|
},
|
||||||
|
saddle: {
|
||||||
|
translate: { x: 0, y: finiteNumber(axisPose.y, 0), z: 0 },
|
||||||
|
sourcePins: ["saddle-y"],
|
||||||
|
},
|
||||||
|
spindle: {
|
||||||
|
translate: { x: 0, y: 0, z: finiteNumber(axisPose.z, 0) },
|
||||||
|
sourcePins: ["spindle-z"],
|
||||||
|
},
|
||||||
|
tilt: {
|
||||||
|
rotateDeg: { x: 0, y: finiteNumber(axisPose.b, 0), z: 0 },
|
||||||
|
sourcePins: ["tilt-b"],
|
||||||
|
},
|
||||||
|
rotary: {
|
||||||
|
rotateDeg: { x: 0, y: 0, z: finiteNumber(axisPose.c, 0) },
|
||||||
|
sourcePins: ["rotate-c"],
|
||||||
|
},
|
||||||
|
tool: {
|
||||||
|
translate: { x: xOffset, y: 0, z: zOffset - toolOffset },
|
||||||
|
sourcePins: ["tool-offset", "x-offset", "z-offset"],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
halNets: [
|
||||||
|
{ signal: "table-x", source: "joint.0.pos-fb", target: "xyzbc-trt-gui.table-x" },
|
||||||
|
{ signal: "saddle-y", source: "joint.1.pos-fb", target: "xyzbc-trt-gui.saddle-y" },
|
||||||
|
{ signal: "spindle-z", source: "joint.2.pos-fb", target: "xyzbc-trt-gui.spindle-z" },
|
||||||
|
{ signal: "tilt-b", source: "joint.3.pos-fb", target: "xyzbc-trt-gui.tilt-b" },
|
||||||
|
{ signal: "rotate-c", source: "joint.4.pos-fb", target: "xyzbc-trt-gui.rotate-c" },
|
||||||
|
{ signal: "tool-offset", source: "motion.tooloffset.z", target: "xyzbc-trt-kins.tool-offset" },
|
||||||
|
{ signal: "tool-offset", source: "xyzbc-trt-kins.tool-offset", target: "xyzbc-trt-gui.tool-offset" },
|
||||||
|
{ signal: "x-offset", source: "xyzbc-trt-kins.x-offset", target: "xyzbc-trt-gui.x-offset" },
|
||||||
|
{ signal: "z-offset", source: "xyzbc-trt-kins.z-offset", target: "xyzbc-trt-gui.z-offset" },
|
||||||
|
],
|
||||||
|
clearTraceSignal: "pyvcp.vismach-clear => vismach.plotclear",
|
||||||
|
semanticBoundary: "web_threejs_vismach_equivalent_driven_by_xyzbc_trt_hal_pins",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function resolveAxisPose(state) {
|
||||||
|
if (state.programRuntimeFeedback?.axisPose) return state.programRuntimeFeedback.axisPose;
|
||||||
|
if (state.taskHalStatus?.ui?.axisPose) return state.taskHalStatus.ui.axisPose;
|
||||||
|
return state.axisPose || {};
|
||||||
|
}
|
||||||
|
|
||||||
|
function resolveToolOffset(state) {
|
||||||
|
if (Number.isFinite(Number(state.toolRuntimeState?.vismach?.toolOffset))) {
|
||||||
|
return Number(state.toolRuntimeState.vismach.toolOffset);
|
||||||
|
}
|
||||||
|
return finiteNumber(
|
||||||
|
state.toolDbSimulation?.activeToolOffset?.offset?.z,
|
||||||
|
state.toolPreview?.length,
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function resolveLinearUnits(state) {
|
||||||
|
return state.linuxCncIniConfig?.traj?.linearUnits
|
||||||
|
|| state.programRuntimeFeedback?.linearUnits
|
||||||
|
|| state.programExecutionTiming?.linearUnits
|
||||||
|
|| DEFAULT_LINEAR_UNITS;
|
||||||
|
}
|
||||||
|
|
||||||
|
function finiteNumber(...values) {
|
||||||
|
for (const value of values) {
|
||||||
|
const number = Number(value);
|
||||||
|
if (Number.isFinite(number)) return number;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -5,6 +5,7 @@ import {
|
|||||||
linearValueToMeters,
|
linearValueToMeters,
|
||||||
resolveStateLinearUnits,
|
resolveStateLinearUnits,
|
||||||
} from "../runtime/linear-units.js";
|
} from "../runtime/linear-units.js";
|
||||||
|
import { buildVismachModelState } from "../runtime/vismach-model-state.js";
|
||||||
|
|
||||||
const scenes = new WeakMap();
|
const scenes = new WeakMap();
|
||||||
const CAMERA_PRESETS = {
|
const CAMERA_PRESETS = {
|
||||||
@@ -62,6 +63,7 @@ export function renderFiveAxisScene(canvas, state) {
|
|||||||
preview.executedPath.geometry,
|
preview.executedPath.geometry,
|
||||||
preview.currentSegmentPath.geometry,
|
preview.currentSegmentPath.geometry,
|
||||||
]),
|
]),
|
||||||
|
vismachModel: preview.currentVismachModelState,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,6 +125,7 @@ function createScene(canvas) {
|
|||||||
toolMarker,
|
toolMarker,
|
||||||
toolAxis,
|
toolAxis,
|
||||||
currentToolhead: new THREE.Vector3(),
|
currentToolhead: new THREE.Vector3(),
|
||||||
|
currentVismachModelState: null,
|
||||||
lastSelectedView: null,
|
lastSelectedView: null,
|
||||||
lastCameraRevision: null,
|
lastCameraRevision: null,
|
||||||
lastFitKey: null,
|
lastFitKey: null,
|
||||||
@@ -177,6 +180,7 @@ function renderFallbackPreview(preview, state) {
|
|||||||
currentSegmentPointCount: currentSegmentPoints.length,
|
currentSegmentPointCount: currentSegmentPoints.length,
|
||||||
pathFitBounds: computePointBounds(previewPoints.concat(executedPoints, currentSegmentPoints)) !== null,
|
pathFitBounds: computePointBounds(previewPoints.concat(executedPoints, currentSegmentPoints)) !== null,
|
||||||
pathBounds: summarizeBounds(computePointBounds(previewPoints.concat(executedPoints, currentSegmentPoints))),
|
pathBounds: summarizeBounds(computePointBounds(previewPoints.concat(executedPoints, currentSegmentPoints))),
|
||||||
|
vismachModel: buildVismachModelState(state),
|
||||||
});
|
});
|
||||||
canvas.dataset.threeFallbackReason = preview.errorMessage;
|
canvas.dataset.threeFallbackReason = preview.errorMessage;
|
||||||
|
|
||||||
@@ -268,6 +272,9 @@ function exposePreviewDataset(canvas, state, preview) {
|
|||||||
canvas.dataset.threeArcPathPoints = String(preview.arcPointCount || 0);
|
canvas.dataset.threeArcPathPoints = String(preview.arcPointCount || 0);
|
||||||
canvas.dataset.threeCurrentSegmentPoints = String(preview.currentSegmentPointCount || 0);
|
canvas.dataset.threeCurrentSegmentPoints = String(preview.currentSegmentPointCount || 0);
|
||||||
canvas.dataset.threeCurrentSegmentType = currentSegmentType(state);
|
canvas.dataset.threeCurrentSegmentType = currentSegmentType(state);
|
||||||
|
canvas.dataset.threeVismachPins = JSON.stringify(preview.vismachModel?.pins || {});
|
||||||
|
canvas.dataset.threeVismachTransforms = JSON.stringify(preview.vismachModel?.transforms || {});
|
||||||
|
canvas.dataset.threeVismachPinDrivenModel = preview.vismachModel?.semanticBoundary || "none";
|
||||||
}
|
}
|
||||||
|
|
||||||
function createLine(color, opacity) {
|
function createLine(color, opacity) {
|
||||||
@@ -291,6 +298,19 @@ function createMachineReferenceModel() {
|
|||||||
);
|
);
|
||||||
base.position.z = -0.016;
|
base.position.z = -0.016;
|
||||||
|
|
||||||
|
const tableAxis = new THREE.Group();
|
||||||
|
tableAxis.name = "vismach-table-x";
|
||||||
|
const saddleAxis = new THREE.Group();
|
||||||
|
saddleAxis.name = "vismach-saddle-y";
|
||||||
|
const spindleAxis = new THREE.Group();
|
||||||
|
spindleAxis.name = "vismach-spindle-z";
|
||||||
|
const tiltAxis = new THREE.Group();
|
||||||
|
tiltAxis.name = "vismach-tilt-b";
|
||||||
|
const rotaryAxis = new THREE.Group();
|
||||||
|
rotaryAxis.name = "vismach-rotate-c";
|
||||||
|
const toolOffsetAxis = new THREE.Group();
|
||||||
|
toolOffsetAxis.name = "vismach-tool-offset";
|
||||||
|
|
||||||
const table = new THREE.Mesh(
|
const table = new THREE.Mesh(
|
||||||
new THREE.BoxGeometry(0.37, 0.235, 0.005),
|
new THREE.BoxGeometry(0.37, 0.235, 0.005),
|
||||||
new THREE.MeshBasicMaterial({ color: 0x3a444d, transparent: true, opacity: 0.78 }),
|
new THREE.MeshBasicMaterial({ color: 0x3a444d, transparent: true, opacity: 0.78 }),
|
||||||
@@ -329,9 +349,21 @@ function createMachineReferenceModel() {
|
|||||||
cutter.position.z = 0.008;
|
cutter.position.z = 0.008;
|
||||||
toolHolder.add(holderBody, cutter);
|
toolHolder.add(holderBody, cutter);
|
||||||
|
|
||||||
root.add(base, table, xAxis, yAxis, zAxis, rotaryA, rotaryC, toolHolder);
|
toolOffsetAxis.add(toolHolder);
|
||||||
|
spindleAxis.add(toolOffsetAxis);
|
||||||
|
rotaryAxis.add(table, rotaryC);
|
||||||
|
tiltAxis.add(rotaryA, rotaryAxis);
|
||||||
|
saddleAxis.add(tiltAxis);
|
||||||
|
tableAxis.add(saddleAxis);
|
||||||
|
root.add(base, xAxis, yAxis, zAxis, tableAxis, spindleAxis);
|
||||||
return {
|
return {
|
||||||
root,
|
root,
|
||||||
|
tableAxis,
|
||||||
|
saddleAxis,
|
||||||
|
spindleAxis,
|
||||||
|
tiltAxis,
|
||||||
|
rotaryAxis,
|
||||||
|
toolOffsetAxis,
|
||||||
rotaryA,
|
rotaryA,
|
||||||
rotaryC,
|
rotaryC,
|
||||||
toolHolder,
|
toolHolder,
|
||||||
@@ -410,15 +442,23 @@ function updateToolExecutionMarker(preview, state, toolPosition) {
|
|||||||
function updateMachineReferenceModel(preview, state, toolPosition) {
|
function updateMachineReferenceModel(preview, state, toolPosition) {
|
||||||
const model = preview.machineModel;
|
const model = preview.machineModel;
|
||||||
if (!model) return;
|
if (!model) return;
|
||||||
const a = degreesToRadians(state.axisPose?.a);
|
const vismach = buildVismachModelState(state);
|
||||||
const b = degreesToRadians(state.axisPose?.b);
|
preview.currentVismachModelState = summarizeVismachModelStateForDataset(vismach);
|
||||||
const c = degreesToRadians(state.axisPose?.c);
|
const toMeters = (value) => linearValueToMeters(value, vismach.linearUnits);
|
||||||
model.rotaryA.rotation.x = a;
|
model.tableAxis.position.x = toMeters(vismach.transforms.table.translate.x);
|
||||||
model.rotaryA.rotation.y = Math.PI / 2 + b;
|
model.saddleAxis.position.y = toMeters(vismach.transforms.saddle.translate.y);
|
||||||
model.rotaryC.rotation.z = c;
|
model.spindleAxis.position.z = toMeters(vismach.transforms.spindle.translate.z);
|
||||||
|
model.tiltAxis.rotation.y = degreesToRadians(vismach.transforms.tilt.rotateDeg.y);
|
||||||
|
model.rotaryAxis.rotation.z = degreesToRadians(vismach.transforms.rotary.rotateDeg.z);
|
||||||
|
model.toolOffsetAxis.position.set(
|
||||||
|
toMeters(vismach.transforms.tool.translate.x),
|
||||||
|
0,
|
||||||
|
toMeters(vismach.transforms.tool.translate.z),
|
||||||
|
);
|
||||||
|
model.rotaryA.rotation.y = Math.PI / 2;
|
||||||
|
model.rotaryC.rotation.x = Math.PI / 2;
|
||||||
|
|
||||||
const tcpPosition = toolPosition || toPreviewVector(state.tcpPose || state.axisPose, state);
|
const tcpPosition = toolPosition || toPreviewVector(state.tcpPose || state.axisPose, state);
|
||||||
model.toolHolder.position.copy(tcpPosition);
|
|
||||||
const toolVector = toToolVector(state.toolAxisVector);
|
const toolVector = toToolVector(state.toolAxisVector);
|
||||||
model.toolHolder.lookAt(tcpPosition.clone().add(toolVector));
|
model.toolHolder.lookAt(tcpPosition.clone().add(toolVector));
|
||||||
}
|
}
|
||||||
@@ -652,6 +692,26 @@ function summarizeBounds(bounds) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function summarizeVismachModelStateForDataset(vismach) {
|
||||||
|
const summarizeVector = (vector = {}) => ({
|
||||||
|
x: round(vector.x),
|
||||||
|
y: round(vector.y),
|
||||||
|
z: round(vector.z),
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
...vismach,
|
||||||
|
pins: Object.fromEntries(Object.entries(vismach.pins).map(([key, value]) => [key, round(value)])),
|
||||||
|
transforms: {
|
||||||
|
table: { ...vismach.transforms.table, translate: summarizeVector(vismach.transforms.table.translate) },
|
||||||
|
saddle: { ...vismach.transforms.saddle, translate: summarizeVector(vismach.transforms.saddle.translate) },
|
||||||
|
spindle: { ...vismach.transforms.spindle, translate: summarizeVector(vismach.transforms.spindle.translate) },
|
||||||
|
tilt: { ...vismach.transforms.tilt },
|
||||||
|
rotary: { ...vismach.transforms.rotary },
|
||||||
|
tool: { ...vismach.transforms.tool, translate: summarizeVector(vismach.transforms.tool.translate) },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
function drawFallbackPolyline(ctx, points, cx, cy, scale) {
|
function drawFallbackPolyline(ctx, points, cx, cy, scale) {
|
||||||
for (let index = 0; index < points.length; index += 1) {
|
for (let index = 0; index < points.length; index += 1) {
|
||||||
const point = points[index];
|
const point = points[index];
|
||||||
|
|||||||
78
web-rtcp-5axis-xyzbc-trt-sim-plan/tests/browser/verify_xyzbc_trt_browser.sh
Executable file
78
web-rtcp-5axis-xyzbc-trt-sim-plan/tests/browser/verify_xyzbc_trt_browser.sh
Executable file
@@ -0,0 +1,78 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
ROOT_DIR="$(cd "$(dirname "$0")/../../.." && pwd)"
|
||||||
|
PROJECT_DIR="$ROOT_DIR/web-rtcp-5axis-xyzbc-trt-sim-plan"
|
||||||
|
CHROMIUM="${CHROMIUM:-$(command -v chromium || command -v chromium-browser || command -v google-chrome || command -v google-chrome-stable || true)}"
|
||||||
|
|
||||||
|
if [[ -z "$CHROMIUM" ]]; then
|
||||||
|
echo "missing Chromium-compatible browser; set CHROMIUM=/path/to/browser" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
npm --prefix "$PROJECT_DIR/app" run build >/dev/null
|
||||||
|
|
||||||
|
TMP_DIR="$(mktemp -d)"
|
||||||
|
PORT_FILE="$TMP_DIR/port"
|
||||||
|
SERVER_LOG="$TMP_DIR/server.log"
|
||||||
|
CHROME_PROFILE="$TMP_DIR/chrome-profile"
|
||||||
|
mkdir -p "$CHROME_PROFILE"
|
||||||
|
|
||||||
|
cleanup() {
|
||||||
|
if [[ -n "${SERVER_PID:-}" ]]; then
|
||||||
|
kill "$SERVER_PID" 2>/dev/null || true
|
||||||
|
wait "$SERVER_PID" 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
rm -rf "$TMP_DIR"
|
||||||
|
}
|
||||||
|
trap cleanup EXIT
|
||||||
|
|
||||||
|
python3 - <<'PY' "$ROOT_DIR" "$PORT_FILE" >"$SERVER_LOG" 2>&1 &
|
||||||
|
import functools
|
||||||
|
import http.server
|
||||||
|
import pathlib
|
||||||
|
import socketserver
|
||||||
|
import sys
|
||||||
|
|
||||||
|
root = pathlib.Path(sys.argv[1])
|
||||||
|
port_file = pathlib.Path(sys.argv[2])
|
||||||
|
|
||||||
|
handler = functools.partial(http.server.SimpleHTTPRequestHandler, directory=str(root))
|
||||||
|
with socketserver.TCPServer(("127.0.0.1", 0), handler) as httpd:
|
||||||
|
port_file.write_text(str(httpd.server_address[1]), encoding="ascii")
|
||||||
|
httpd.serve_forever()
|
||||||
|
PY
|
||||||
|
SERVER_PID=$!
|
||||||
|
|
||||||
|
for _ in $(seq 1 100); do
|
||||||
|
[[ -s "$PORT_FILE" ]] && break
|
||||||
|
sleep 0.05
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ ! -s "$PORT_FILE" ]]; then
|
||||||
|
echo "xyzbc-trt browser smoke HTTP server did not start" >&2
|
||||||
|
cat "$SERVER_LOG" >&2 || true
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
PORT="$(cat "$PORT_FILE")"
|
||||||
|
APP_PATH="../../app/dist/index.html"
|
||||||
|
URL="http://127.0.0.1:$PORT/web-rtcp-5axis-xyzbc-trt-sim-plan/tests/browser/xyzbc_trt_browser_smoke.html?app=$APP_PATH"
|
||||||
|
OUT="$TMP_DIR/chromium-xyzbc-trt.out"
|
||||||
|
|
||||||
|
"$CHROMIUM" \
|
||||||
|
--headless=new \
|
||||||
|
--disable-gpu \
|
||||||
|
--no-sandbox \
|
||||||
|
--user-data-dir="$CHROME_PROFILE" \
|
||||||
|
--virtual-time-budget=15000 \
|
||||||
|
--dump-dom \
|
||||||
|
"$URL" >"$OUT" 2>&1
|
||||||
|
|
||||||
|
if ! grep -Fq "xyzbc_trt_browser_smoke=ok" "$OUT"; then
|
||||||
|
echo "xyzbc-trt browser smoke failed" >&2
|
||||||
|
sed -n '1,260p' "$OUT" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "xyzbc_trt_browser_smoke=ok"
|
||||||
@@ -0,0 +1,180 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<title>xyzbc-trt browser smoke</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<pre id="result">xyzbc_trt_browser_smoke=pending</pre>
|
||||||
|
<iframe id="app-frame" title="xyzbc-trt app"></iframe>
|
||||||
|
<script type="module">
|
||||||
|
const result = document.querySelector("#result");
|
||||||
|
const frame = document.querySelector("#app-frame");
|
||||||
|
const appSrc = new URLSearchParams(window.location.search).get("app") || "../../app/index.html";
|
||||||
|
frame.src = appSrc;
|
||||||
|
|
||||||
|
const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
||||||
|
|
||||||
|
async function runSmoke() {
|
||||||
|
await new Promise((resolve, reject) => {
|
||||||
|
frame.addEventListener("load", resolve, { once: true });
|
||||||
|
frame.addEventListener("error", reject, { once: true });
|
||||||
|
});
|
||||||
|
|
||||||
|
const win = frame.contentWindow;
|
||||||
|
const doc = frame.contentDocument;
|
||||||
|
const runtimeErrors = [];
|
||||||
|
win.addEventListener("error", (event) => {
|
||||||
|
runtimeErrors.push(event.message || String(event.error || "window error"));
|
||||||
|
});
|
||||||
|
win.addEventListener("unhandledrejection", (event) => {
|
||||||
|
runtimeErrors.push(event.reason?.message || String(event.reason || "unhandled rejection"));
|
||||||
|
});
|
||||||
|
|
||||||
|
await waitFor(() => win.webRtcp5AxisSimulation, "public simulation API");
|
||||||
|
const api = win.webRtcp5AxisSimulation;
|
||||||
|
const [kinematics, interpreter, taskHal] = await Promise.all([
|
||||||
|
api.kinematicsRuntimeReady,
|
||||||
|
api.interpreterRuntimeReady,
|
||||||
|
api.taskHalRuntimeReady,
|
||||||
|
]);
|
||||||
|
|
||||||
|
assertRuntime(kinematics, {
|
||||||
|
name: "kinematics",
|
||||||
|
moduleId: "xyzbc-trt",
|
||||||
|
required: ["loaded"],
|
||||||
|
});
|
||||||
|
if (kinematics.executionContext !== "worker") {
|
||||||
|
throw new Error(`kinematics runtime should run in worker: ${JSON.stringify(kinematics)}`);
|
||||||
|
}
|
||||||
|
assertRuntime(interpreter, {
|
||||||
|
name: "interpreter",
|
||||||
|
required: ["loaded", "runProgramReady", "plannerRuntimeReady"],
|
||||||
|
});
|
||||||
|
if (interpreter.executionContext !== "worker") {
|
||||||
|
throw new Error(`interpreter runtime should run in worker: ${JSON.stringify(interpreter)}`);
|
||||||
|
}
|
||||||
|
assertRuntime(taskHal, {
|
||||||
|
name: "task/HAL",
|
||||||
|
required: ["loaded", "taskRuntimeReady", "motionRuntimeReady", "halRuntimeReady"],
|
||||||
|
});
|
||||||
|
if (taskHal.executionContext !== "worker") {
|
||||||
|
throw new Error(`task/HAL runtime should run in worker: ${JSON.stringify(taskHal)}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
await api.machineFileSeedReady;
|
||||||
|
await waitFor(() => {
|
||||||
|
const state = api.getState();
|
||||||
|
return !state.interpreterExecutionPending
|
||||||
|
&& state.programExecution?.sourceMode === "linuxcnc-interpreter-wasm"
|
||||||
|
&& state.machineFileStaging?.status === "staged";
|
||||||
|
}, "default xyzbc program preview");
|
||||||
|
|
||||||
|
const state = api.getState();
|
||||||
|
if (state.machineProfile !== "xyzbc-trt" || state.profile?.traj?.coordinates !== "XYZBC") {
|
||||||
|
throw new Error(`default profile mismatch: ${state.machineProfile}/${state.profile?.traj?.coordinates}`);
|
||||||
|
}
|
||||||
|
if (state.profile?.kinematicsModuleId !== "xyzbc-trt") {
|
||||||
|
throw new Error(`profile kinematics module mismatch: ${state.profile?.kinematicsModuleId}`);
|
||||||
|
}
|
||||||
|
if (state.machineFileStaging?.profileId !== "xyzbc-trt") {
|
||||||
|
throw new Error(`staging profile mismatch: ${state.machineFileStaging?.profileId}`);
|
||||||
|
}
|
||||||
|
if (!state.machineFileStaging?.gcodeSources?.some((source) => source.filename === "xyzbc_switchkins.ngc")) {
|
||||||
|
throw new Error("staged sources missing xyzbc_switchkins.ngc");
|
||||||
|
}
|
||||||
|
if (!state.machineFileStaging?.gcodeSources?.some((source) => source.filename === "boat-xyzbc.ngc")) {
|
||||||
|
throw new Error("staged sources missing boat-xyzbc.ngc");
|
||||||
|
}
|
||||||
|
if (state.programExecution?.summary?.motionEventCount < 1) {
|
||||||
|
throw new Error(`default program did not produce canonical motion: ${JSON.stringify(state.programExecution?.summary)}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const canvas = await waitFor(() => doc.querySelector("[data-five-axis-canvas]"), "preview canvas");
|
||||||
|
await waitFor(() => canvas.dataset.threeReady === "true" && Number(canvas.dataset.threePathPoints || 0) > 0, "Three.js dataset");
|
||||||
|
if (
|
||||||
|
canvas.dataset.threeRenderer !== "webgl" ||
|
||||||
|
canvas.dataset.threeFrameApi !== "web-rtcp-5axis-motion-frame" ||
|
||||||
|
canvas.dataset.threeSceneMode !== "program-preview-and-tool-execution" ||
|
||||||
|
canvas.dataset.threeMachineReferenceModel !== "webgl-five-axis-reference" ||
|
||||||
|
canvas.dataset.threePreviewScope !== "machine-reference-and-toolpath" ||
|
||||||
|
canvas.dataset.threeProgramPreviewSource !== "linuxcnc-interpreter-wasm" ||
|
||||||
|
canvas.dataset.threeVismachPinDrivenModel !== "web_threejs_vismach_equivalent_driven_by_xyzbc_trt_hal_pins"
|
||||||
|
) {
|
||||||
|
throw new Error(`unexpected canvas dataset: ${JSON.stringify(canvas.dataset)}`);
|
||||||
|
}
|
||||||
|
if (Number(canvas.dataset.threeSceneObjects || 0) < 12) {
|
||||||
|
throw new Error(`scene object count too low: ${canvas.dataset.threeSceneObjects}`);
|
||||||
|
}
|
||||||
|
const vismachPins = JSON.parse(canvas.dataset.threeVismachPins || "{}");
|
||||||
|
for (const pin of ["table-x", "saddle-y", "spindle-z", "tilt-b", "rotate-c", "tool-offset", "x-offset", "z-offset"]) {
|
||||||
|
if (!Number.isFinite(Number(vismachPins[pin]))) {
|
||||||
|
throw new Error(`missing Vismach pin ${pin}: ${JSON.stringify(vismachPins)}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const vismachTransforms = JSON.parse(canvas.dataset.threeVismachTransforms || "{}");
|
||||||
|
if (
|
||||||
|
vismachTransforms.table?.sourcePins?.[0] !== "table-x" ||
|
||||||
|
vismachTransforms.saddle?.sourcePins?.[0] !== "saddle-y" ||
|
||||||
|
vismachTransforms.spindle?.sourcePins?.[0] !== "spindle-z" ||
|
||||||
|
vismachTransforms.tilt?.sourcePins?.[0] !== "tilt-b" ||
|
||||||
|
vismachTransforms.rotary?.sourcePins?.[0] !== "rotate-c" ||
|
||||||
|
!vismachTransforms.tool?.sourcePins?.includes("tool-offset")
|
||||||
|
) {
|
||||||
|
throw new Error(`Vismach transform source pins mismatch: ${JSON.stringify(vismachTransforms)}`);
|
||||||
|
}
|
||||||
|
assertCanvasNonblank(canvas);
|
||||||
|
|
||||||
|
if (runtimeErrors.length > 0) {
|
||||||
|
throw new Error(`runtime errors: ${runtimeErrors.join(" | ")}`);
|
||||||
|
}
|
||||||
|
result.textContent = "xyzbc_trt_browser_smoke=ok";
|
||||||
|
}
|
||||||
|
|
||||||
|
function assertRuntime(readiness, { name, moduleId = null, required }) {
|
||||||
|
for (const key of required) {
|
||||||
|
if (readiness?.[key] !== true) {
|
||||||
|
throw new Error(`${name} runtime missing ${key}: ${JSON.stringify(readiness)}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (moduleId && readiness?.moduleId !== moduleId) {
|
||||||
|
throw new Error(`${name} runtime module mismatch: ${JSON.stringify(readiness)}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function waitFor(predicate, label) {
|
||||||
|
for (let attempt = 0; attempt < 240; attempt += 1) {
|
||||||
|
const value = predicate();
|
||||||
|
if (value) return value;
|
||||||
|
await wait(50);
|
||||||
|
}
|
||||||
|
throw new Error(`timed out waiting for ${label}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
function assertCanvasNonblank(canvas) {
|
||||||
|
const context = canvas.getContext("webgl2") || canvas.getContext("webgl") || canvas.getContext("2d");
|
||||||
|
if (!context) {
|
||||||
|
throw new Error("preview canvas has no readable context");
|
||||||
|
}
|
||||||
|
const width = canvas.width;
|
||||||
|
const height = canvas.height;
|
||||||
|
if (width <= 0 || height <= 0) {
|
||||||
|
throw new Error(`preview canvas has invalid size ${width}x${height}`);
|
||||||
|
}
|
||||||
|
if (context.readPixels) {
|
||||||
|
const pixels = new Uint8Array(4);
|
||||||
|
context.readPixels(Math.floor(width / 2), Math.floor(height / 2), 1, 1, context.RGBA, context.UNSIGNED_BYTE, pixels);
|
||||||
|
if (pixels.some((value) => value !== 0)) return;
|
||||||
|
}
|
||||||
|
const imageData = canvas.toDataURL("image/png");
|
||||||
|
if (!imageData || imageData.length < 2000) {
|
||||||
|
throw new Error("preview canvas appears blank");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
runSmoke().catch((error) => {
|
||||||
|
result.textContent = `xyzbc_trt_browser_smoke=fail ${error.stack || error.message || error}`;
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -17,6 +17,11 @@ import {
|
|||||||
import { getFiveAxisProfile } from "../../app/src/profiles/index.js";
|
import { getFiveAxisProfile } from "../../app/src/profiles/index.js";
|
||||||
import { createSimulationStore } from "../../app/src/state/store.js";
|
import { createSimulationStore } from "../../app/src/state/store.js";
|
||||||
import { createLinuxCncTaskHalSdk } from "../../../wasm-port/runtime/sdk/src/linuxcnc-task-hal.js";
|
import { createLinuxCncTaskHalSdk } from "../../../wasm-port/runtime/sdk/src/linuxcnc-task-hal.js";
|
||||||
|
import { buildVismachModelState, XYZBC_TRT_VISMACH_PINS } from "../../app/src/runtime/vismach-model-state.js";
|
||||||
|
import {
|
||||||
|
applyToolCommandSequence,
|
||||||
|
createToolRuntimeState,
|
||||||
|
} from "../../app/src/runtime/tool-db-simulation.js";
|
||||||
|
|
||||||
const profile = getFiveAxisProfile();
|
const profile = getFiveAxisProfile();
|
||||||
|
|
||||||
@@ -30,6 +35,19 @@ assert.equal(profile.machineFileStaging.defaultProgramFilename, "xyzbc_switchkin
|
|||||||
assert.equal(profile.panelSchema.id, "xyzbc-trt-switchkins-pyvcp");
|
assert.equal(profile.panelSchema.id, "xyzbc-trt-switchkins-pyvcp");
|
||||||
assert.ok(profile.halPins.includes("xyzbc-trt-kins.x-offset"));
|
assert.ok(profile.halPins.includes("xyzbc-trt-kins.x-offset"));
|
||||||
assert.ok(profile.halPins.includes("motion.switchkins-type"));
|
assert.ok(profile.halPins.includes("motion.switchkins-type"));
|
||||||
|
assert.deepEqual(profile.hal.halcmd.feedbackNets.map((net) => net.signal), [
|
||||||
|
"table-x",
|
||||||
|
"saddle-y",
|
||||||
|
"spindle-z",
|
||||||
|
"tilt-b",
|
||||||
|
"rotate-c",
|
||||||
|
]);
|
||||||
|
assert.deepEqual(profile.hal.halcmd.offsetNets.map((net) => net.target), [
|
||||||
|
"xyzbc-trt-kins.tool-offset",
|
||||||
|
"xyzbc-trt-gui.tool-offset",
|
||||||
|
"xyzbc-trt-gui.x-offset",
|
||||||
|
"xyzbc-trt-gui.z-offset",
|
||||||
|
]);
|
||||||
assert.deepEqual(profile.samplePrograms, [
|
assert.deepEqual(profile.samplePrograms, [
|
||||||
"configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzbc_switchkins.ngc",
|
"configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzbc_switchkins.ngc",
|
||||||
"configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/boat-xyzbc.ngc",
|
"configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/boat-xyzbc.ngc",
|
||||||
@@ -80,6 +98,7 @@ assert.ok(staged.save.files.some((file) => file.sourceRel.endsWith("remap_subs/h
|
|||||||
assert.ok(staged.save.gcodeSources.some((source) => source.filename === "xyzbc_switchkins.ngc"));
|
assert.ok(staged.save.gcodeSources.some((source) => source.filename === "xyzbc_switchkins.ngc"));
|
||||||
assert.ok(staged.save.gcodeSources.some((source) => source.filename === "boat-xyzbc.ngc"));
|
assert.ok(staged.save.gcodeSources.some((source) => source.filename === "boat-xyzbc.ngc"));
|
||||||
assert.equal(staged.save.files.some((file) => file.sourceRel.endsWith("xyzbc.var") && file.kind === "parameters"), true);
|
assert.equal(staged.save.files.some((file) => file.sourceRel.endsWith("xyzbc.var") && file.kind === "parameters"), true);
|
||||||
|
assert.equal(staged.save.files.find((file) => file.sourceRel.endsWith("xyzbc-trt.tbl")).text.includes("T2 P2 Z10 D8"), true);
|
||||||
|
|
||||||
const selectedPlan = selectMachineFileProgram(
|
const selectedPlan = selectMachineFileProgram(
|
||||||
staged.plan,
|
staged.plan,
|
||||||
@@ -145,6 +164,58 @@ assert.equal(state.sessionName, "xyzbc-trt-web-session");
|
|||||||
assert.equal(state.kinematicsRuntimeReadiness, null);
|
assert.equal(state.kinematicsRuntimeReadiness, null);
|
||||||
|
|
||||||
const storeStage = await store.stageMachineFiles({ storage: createMemorySessionStorage() });
|
const storeStage = await store.stageMachineFiles({ storage: createMemorySessionStorage() });
|
||||||
|
const toolOffsetDb = applyToolCommandSequence(store.getState().toolDbSimulation, [
|
||||||
|
{ code: "T", toolNumber: 2 },
|
||||||
|
{ code: "M6" },
|
||||||
|
{ code: "G43", h: 2 },
|
||||||
|
]);
|
||||||
|
const toolRuntimeState = createToolRuntimeState(toolOffsetDb, {
|
||||||
|
fallbackToolLength: state.toolPreview.length,
|
||||||
|
});
|
||||||
|
assert.equal(toolRuntimeState.ready, true);
|
||||||
|
assert.equal(toolRuntimeState.activeOffsetApplied, true);
|
||||||
|
assert.equal(toolRuntimeState.activeToolNumber, 2);
|
||||||
|
assert.equal(toolRuntimeState.activePocket, 2);
|
||||||
|
assert.equal(toolRuntimeState.currentTool.offset.z, 10);
|
||||||
|
assert.equal(toolRuntimeState.currentTool.diameter, 8);
|
||||||
|
assert.equal(toolRuntimeState.kinematics.toolOffsetZ, 10);
|
||||||
|
assert.equal(toolRuntimeState.kinematics.halPin, "motion.tooloffset.z");
|
||||||
|
assert.deepEqual(toolRuntimeState.kinematics.downstreamPins, [
|
||||||
|
"xyzbc-trt-kins.tool-offset",
|
||||||
|
"xyzbc-trt-gui.tool-offset",
|
||||||
|
]);
|
||||||
|
assert.equal(toolRuntimeState.pathTool.id, 2);
|
||||||
|
assert.equal(toolRuntimeState.pathTool.pocket, 2);
|
||||||
|
assert.equal(toolRuntimeState.pathTool.length, 10);
|
||||||
|
assert.equal(toolRuntimeState.pathTool.diameter, 8);
|
||||||
|
assert.equal(toolRuntimeState.vismach.toolOffset, 10);
|
||||||
|
|
||||||
|
const vismachState = buildVismachModelState({
|
||||||
|
...state,
|
||||||
|
axisPose: { x: 12.5, y: -6.25, z: 3.75, b: 35, c: -90 },
|
||||||
|
toolPreview: { ...state.toolPreview, length: 84.019 },
|
||||||
|
toolRuntimeState,
|
||||||
|
});
|
||||||
|
assert.deepEqual(Object.keys(vismachState.pins), XYZBC_TRT_VISMACH_PINS);
|
||||||
|
assert.equal(vismachState.pins["table-x"], 12.5);
|
||||||
|
assert.equal(vismachState.pins["saddle-y"], -6.25);
|
||||||
|
assert.equal(vismachState.pins["spindle-z"], 3.75);
|
||||||
|
assert.equal(vismachState.pins["tilt-b"], 35);
|
||||||
|
assert.equal(vismachState.pins["rotate-c"], -90);
|
||||||
|
assert.equal(vismachState.pins["x-offset"], -20);
|
||||||
|
assert.equal(vismachState.pins["z-offset"], -15);
|
||||||
|
assert.equal(vismachState.pins["tool-offset"], 10);
|
||||||
|
assert.deepEqual(vismachState.transforms.table.sourcePins, ["table-x"]);
|
||||||
|
assert.deepEqual(vismachState.transforms.saddle.sourcePins, ["saddle-y"]);
|
||||||
|
assert.deepEqual(vismachState.transforms.spindle.sourcePins, ["spindle-z"]);
|
||||||
|
assert.deepEqual(vismachState.transforms.tilt.sourcePins, ["tilt-b"]);
|
||||||
|
assert.deepEqual(vismachState.transforms.rotary.sourcePins, ["rotate-c"]);
|
||||||
|
assert.deepEqual(vismachState.transforms.tool.sourcePins, ["tool-offset", "x-offset", "z-offset"]);
|
||||||
|
assert.equal(vismachState.transforms.tool.translate.x, -20);
|
||||||
|
assert.equal(vismachState.transforms.tool.translate.z, -25);
|
||||||
|
assert.equal(vismachState.halNets.length, 9);
|
||||||
|
assert.equal(vismachState.semanticBoundary, "web_threejs_vismach_equivalent_driven_by_xyzbc_trt_hal_pins");
|
||||||
|
|
||||||
const stagedState = store.getState();
|
const stagedState = store.getState();
|
||||||
assert.equal(storeStage.save.profileId, "xyzbc-trt");
|
assert.equal(storeStage.save.profileId, "xyzbc-trt");
|
||||||
assert.equal(stagedState.machineFileStaging.profileId, "xyzbc-trt");
|
assert.equal(stagedState.machineFileStaging.profileId, "xyzbc-trt");
|
||||||
|
|||||||
@@ -8,8 +8,16 @@ import {
|
|||||||
selectMachineFileProgram,
|
selectMachineFileProgram,
|
||||||
stageProfileMachineFiles,
|
stageProfileMachineFiles,
|
||||||
} from "../app/src/runtime/linuxcnc-machine-file-staging.js";
|
} from "../app/src/runtime/linuxcnc-machine-file-staging.js";
|
||||||
|
import {
|
||||||
|
applyToolCommandSequence,
|
||||||
|
createToolDbSimulation,
|
||||||
|
createToolRuntimeState,
|
||||||
|
extractToolCommandSequenceFromProgram,
|
||||||
|
parseLinuxCncToolTable,
|
||||||
|
} from "../app/src/runtime/tool-db-simulation.js";
|
||||||
import { createSimulationStore } from "../app/src/state/store.js";
|
import { createSimulationStore } from "../app/src/state/store.js";
|
||||||
import { getFiveAxisProfile } from "../app/src/profiles/index.js";
|
import { getFiveAxisProfile } from "../app/src/profiles/index.js";
|
||||||
|
import { buildVismachModelState } from "../app/src/runtime/vismach-model-state.js";
|
||||||
|
|
||||||
const SAMPLE_PERIOD_MS = 20;
|
const SAMPLE_PERIOD_MS = 20;
|
||||||
const repoRoot = resolve(dirname(fileURLToPath(import.meta.url)), "../..");
|
const repoRoot = resolve(dirname(fileURLToPath(import.meta.url)), "../..");
|
||||||
@@ -42,7 +50,13 @@ const paths = await collectPathEvidence({
|
|||||||
selectedPlan,
|
selectedPlan,
|
||||||
wasmArtifacts,
|
wasmArtifacts,
|
||||||
});
|
});
|
||||||
const semanticFields = buildSemanticFields({ profile, ini, staged, state });
|
const toolRuntime = buildToolRuntimeEvidence({
|
||||||
|
profile,
|
||||||
|
staged,
|
||||||
|
selectedPlan,
|
||||||
|
fallbackToolLength: state.toolPreview?.length,
|
||||||
|
});
|
||||||
|
const semanticFields = buildSemanticFields({ profile, ini, staged, state, toolRuntime });
|
||||||
|
|
||||||
const evidence = {
|
const evidence = {
|
||||||
apiName: "xyzbc-trt-web-opfs-wasm-evidence",
|
apiName: "xyzbc-trt-web-opfs-wasm-evidence",
|
||||||
@@ -110,6 +124,7 @@ const evidence = {
|
|||||||
pathSampling: createPathSampling(),
|
pathSampling: createPathSampling(),
|
||||||
previewPath: paths.previewPath,
|
previewPath: paths.previewPath,
|
||||||
executionPath: paths.executionPath,
|
executionPath: paths.executionPath,
|
||||||
|
toolRuntime,
|
||||||
...semanticFields,
|
...semanticFields,
|
||||||
wasm: wasmArtifacts,
|
wasm: wasmArtifacts,
|
||||||
coverage: {
|
coverage: {
|
||||||
@@ -137,6 +152,11 @@ const evidence = {
|
|||||||
&& Boolean(semanticFields.axisJointLimits.axisLimits.C),
|
&& Boolean(semanticFields.axisJointLimits.axisLimits.C),
|
||||||
previewPathAvailable: paths.previewPath.sampleCount > 0,
|
previewPathAvailable: paths.previewPath.sampleCount > 0,
|
||||||
executionPathAvailable: paths.executionPath.sampleCount > 0,
|
executionPathAvailable: paths.executionPath.sampleCount > 0,
|
||||||
|
toolTableToToolOffsetClosed: toolRuntime.ready
|
||||||
|
&& toolRuntime.toolTable.toolCount > 0
|
||||||
|
&& toolRuntime.activeOffsetApplied
|
||||||
|
&& toolRuntime.kinematics.toolOffsetZ === toolRuntime.pathTool.length
|
||||||
|
&& toolRuntime.vismach.toolOffset === toolRuntime.pathTool.length,
|
||||||
wasmArtifactsReady: wasmArtifacts.ready,
|
wasmArtifactsReady: wasmArtifacts.ready,
|
||||||
},
|
},
|
||||||
blockers: [
|
blockers: [
|
||||||
@@ -222,11 +242,16 @@ async function collectPathEvidence({ profile, staged, selectedPlan, wasmArtifact
|
|||||||
files: staged.save.files,
|
files: staged.save.files,
|
||||||
executionMode: "fiveAxisRemap",
|
executionMode: "fiveAxisRemap",
|
||||||
});
|
});
|
||||||
const previewPath = pathFromWebMotion(execution, profile);
|
const toolRuntime = buildToolRuntimeEvidence({
|
||||||
|
profile,
|
||||||
|
staged,
|
||||||
|
selectedPlan,
|
||||||
|
});
|
||||||
|
const previewPath = pathFromWebMotion(execution, profile, toolRuntime.pathTool);
|
||||||
return {
|
return {
|
||||||
previewPath,
|
previewPath,
|
||||||
executionPath: wasmArtifacts.ready
|
executionPath: wasmArtifacts.ready
|
||||||
? await pathFromTaskHalExecution({ profile, staged, selectedPlan, execution })
|
? await pathFromTaskHalExecution({ profile, staged, selectedPlan, execution, toolRuntime })
|
||||||
: emptyPath("web-task-hal", "missing task/HAL WASM runtime artifacts"),
|
: emptyPath("web-task-hal", "missing task/HAL WASM runtime artifacts"),
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -237,7 +262,7 @@ async function collectPathEvidence({ profile, staged, selectedPlan, wasmArtifact
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function pathFromWebMotion(execution, profile) {
|
function pathFromWebMotion(execution, profile, pathTool = null) {
|
||||||
const plannerSamples = execution.plannerTiming?.samples || [];
|
const plannerSamples = execution.plannerTiming?.samples || [];
|
||||||
const motion = execution.motion || [];
|
const motion = execution.motion || [];
|
||||||
const motionByIndex = new Map(motion.map((event, index) => [index, event]));
|
const motionByIndex = new Map(motion.map((event, index) => [index, event]));
|
||||||
@@ -252,7 +277,7 @@ function pathFromWebMotion(execution, profile) {
|
|||||||
motionType: motionTypeFromCanonical(sample.type || event.type),
|
motionType: motionTypeFromCanonical(sample.type || event.type),
|
||||||
activeKinematics: activeKinematics(event),
|
activeKinematics: activeKinematics(event),
|
||||||
axes,
|
axes,
|
||||||
tool: firstTool(profile),
|
tool: pathTool || firstTool(profile),
|
||||||
feed: sample.currentVelocityMmPerMin ?? event.feedRate ?? 0,
|
feed: sample.currentVelocityMmPerMin ?? event.feedRate ?? 0,
|
||||||
spindle: 0,
|
spindle: 0,
|
||||||
});
|
});
|
||||||
@@ -311,7 +336,7 @@ function interpolatePlannerSample(left, right, timeMs) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async function pathFromTaskHalExecution({ profile, staged, selectedPlan, execution }) {
|
async function pathFromTaskHalExecution({ profile, staged, selectedPlan, execution, toolRuntime = null }) {
|
||||||
try {
|
try {
|
||||||
const { createLinuxCncTaskHalSdk } = await import("../../wasm-port/runtime/sdk/src/linuxcnc-task-hal.js");
|
const { createLinuxCncTaskHalSdk } = await import("../../wasm-port/runtime/sdk/src/linuxcnc-task-hal.js");
|
||||||
const {
|
const {
|
||||||
@@ -377,7 +402,7 @@ async function pathFromTaskHalExecution({ profile, staged, selectedPlan, executi
|
|||||||
switchkinsType: status.ui?.switchkinsType ?? motion.switchkinsType,
|
switchkinsType: status.ui?.switchkinsType ?? motion.switchkinsType,
|
||||||
}),
|
}),
|
||||||
axes: xyzbcAxesFromTaskHalStatus(status),
|
axes: xyzbcAxesFromTaskHalStatus(status),
|
||||||
tool: firstTool(profile),
|
tool: toolRuntime?.pathTool || firstTool(profile),
|
||||||
feed: status.ui?.currentVelocity ?? Number(motion.currentVel || motion.currentVelocity || 0) * 60,
|
feed: status.ui?.currentVelocity ?? Number(motion.currentVel || motion.currentVelocity || 0) * 60,
|
||||||
spindle: spindleFromTaskHalStatus(status),
|
spindle: spindleFromTaskHalStatus(status),
|
||||||
});
|
});
|
||||||
@@ -409,7 +434,7 @@ async function pathFromTaskHalExecution({ profile, staged, selectedPlan, executi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildSemanticFields({ profile, ini, staged, state }) {
|
function buildSemanticFields({ profile, ini, staged, state, toolRuntime }) {
|
||||||
const postguiNets = [
|
const postguiNets = [
|
||||||
{ signal: "kinstype.is-0", source: "kinstype.is-0", target: "pyvcp.multilabel.0.legend0", boundary: "postgui-hal" },
|
{ signal: "kinstype.is-0", source: "kinstype.is-0", target: "pyvcp.multilabel.0.legend0", boundary: "postgui-hal" },
|
||||||
{ signal: "kinstype.is-1", source: "kinstype.is-1", target: "pyvcp.multilabel.0.legend1", boundary: "postgui-hal" },
|
{ signal: "kinstype.is-1", source: "kinstype.is-1", target: "pyvcp.multilabel.0.legend1", boundary: "postgui-hal" },
|
||||||
@@ -425,6 +450,10 @@ function buildSemanticFields({ profile, ini, staged, state }) {
|
|||||||
...(profile.hal?.halcmd?.offsetNets || []),
|
...(profile.hal?.halcmd?.offsetNets || []),
|
||||||
].filter(Boolean).map((net) => ({ ...net, boundary: "ini-halcmd" }));
|
].filter(Boolean).map((net) => ({ ...net, boundary: "ini-halcmd" }));
|
||||||
const gcodeFiles = staged.save.gcodeFiles || [];
|
const gcodeFiles = staged.save.gcodeFiles || [];
|
||||||
|
const vismachModelState = buildVismachModelState({
|
||||||
|
...state,
|
||||||
|
toolRuntimeState: toolRuntime,
|
||||||
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
startupSequence: [
|
startupSequence: [
|
||||||
@@ -460,6 +489,8 @@ function buildSemanticFields({ profile, ini, staged, state }) {
|
|||||||
zRotPoint: profile.offsets?.zRotPoint,
|
zRotPoint: profile.offsets?.zRotPoint,
|
||||||
conventionalDirections: profile.offsets?.conventionalDirections,
|
conventionalDirections: profile.offsets?.conventionalDirections,
|
||||||
toolOffsetSource: "motion.tooloffset.z",
|
toolOffsetSource: "motion.tooloffset.z",
|
||||||
|
toolOffsetValue: toolRuntime.kinematics.toolOffsetZ,
|
||||||
|
toolOffsetToolNumber: toolRuntime.activeToolNumber,
|
||||||
pins: profile.halPins,
|
pins: profile.halPins,
|
||||||
},
|
},
|
||||||
axisJointLimits: {
|
axisJointLimits: {
|
||||||
@@ -498,17 +529,26 @@ function buildSemanticFields({ profile, ini, staged, state }) {
|
|||||||
vismachEquivalent: {
|
vismachEquivalent: {
|
||||||
sourceGui: "src/hal/user_comps/vismach/xyzbc-trt-gui.py",
|
sourceGui: "src/hal/user_comps/vismach/xyzbc-trt-gui.py",
|
||||||
webModel: "app/src/visualization/five-axis-scene.js",
|
webModel: "app/src/visualization/five-axis-scene.js",
|
||||||
pins: [
|
pins: Object.keys(vismachModelState.pins),
|
||||||
"table-x",
|
pinValues: vismachModelState.pins,
|
||||||
"saddle-y",
|
transforms: vismachModelState.transforms,
|
||||||
"spindle-z",
|
halNets: vismachModelState.halNets,
|
||||||
"tilt-b",
|
|
||||||
"rotate-c",
|
|
||||||
"tool-offset",
|
|
||||||
"x-offset",
|
|
||||||
"z-offset",
|
|
||||||
],
|
|
||||||
clearTraceSignal: "pyvcp.vismach-clear => vismach.plotclear",
|
clearTraceSignal: "pyvcp.vismach-clear => vismach.plotclear",
|
||||||
|
semanticBoundary: vismachModelState.semanticBoundary,
|
||||||
|
},
|
||||||
|
toolOffsetClosure: {
|
||||||
|
sourceToolTable: toolRuntime.toolTable.sourceRel,
|
||||||
|
selectedProgramSourceRel: toolRuntime.selectedProgramSourceRel,
|
||||||
|
programToolCommands: toolRuntime.programToolCommands,
|
||||||
|
activeToolOffset: toolRuntime.activeToolOffset,
|
||||||
|
kinematicsToolOffsetZ: toolRuntime.kinematics.toolOffsetZ,
|
||||||
|
pathTool: toolRuntime.pathTool,
|
||||||
|
vismachToolOffset: toolRuntime.vismach.toolOffset,
|
||||||
|
closed: toolRuntime.ready
|
||||||
|
&& toolRuntime.activeOffsetApplied
|
||||||
|
&& toolRuntime.kinematics.toolOffsetZ === toolRuntime.pathTool.length
|
||||||
|
&& toolRuntime.vismach.toolOffset === toolRuntime.pathTool.length,
|
||||||
|
semanticBoundary: "tool_table_current_t_p_z_d_drives_kinematics_path_and_vismach",
|
||||||
},
|
},
|
||||||
ngcguiSubroutines: ["xyzbc_switchkins_sub.ngc", "centering.ngc", "helix_bc.ngc"].map((filename) => ({
|
ngcguiSubroutines: ["xyzbc_switchkins_sub.ngc", "centering.ngc", "helix_bc.ngc"].map((filename) => ({
|
||||||
filename,
|
filename,
|
||||||
@@ -524,6 +564,58 @@ function buildSemanticFields({ profile, ini, staged, state }) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function buildToolRuntimeEvidence({ profile, staged, selectedPlan, fallbackToolLength = 0 }) {
|
||||||
|
const toolTableFile = staged.save.files.find((file) => file.sourceRel === profile.toolTablePath)
|
||||||
|
|| staged.save.files.find((file) => file.kind === "toolTable");
|
||||||
|
const programFile = staged.save.files.find((file) => (
|
||||||
|
file.sourceRel === selectedPlan.selectedProgramSourceRel
|
||||||
|
|| (file.wasmPath || file.path) === selectedPlan.wasmProgramPath
|
||||||
|
));
|
||||||
|
const toolTable = parseLinuxCncToolTable(toolTableFile?.text || "", {
|
||||||
|
sourceRel: toolTableFile?.sourceRel || profile.toolTablePath,
|
||||||
|
path: toolTableFile?.wasmPath || toolTableFile?.path || null,
|
||||||
|
});
|
||||||
|
const programToolCommands = extractToolCommandSequenceFromProgram(programFile?.text || "");
|
||||||
|
const commands = programToolCommands.length > 0
|
||||||
|
? programToolCommands
|
||||||
|
: defaultToolActivationCommands(toolTable);
|
||||||
|
const toolDb = applyToolCommandSequence(createToolDbSimulation({
|
||||||
|
toolTable,
|
||||||
|
profile,
|
||||||
|
storageMode: staged.save.storageMode,
|
||||||
|
}), commands);
|
||||||
|
const runtimeState = createToolRuntimeState(toolDb, { fallbackToolLength });
|
||||||
|
return {
|
||||||
|
...runtimeState,
|
||||||
|
selectedProgramSourceRel: selectedPlan.selectedProgramSourceRel,
|
||||||
|
toolTable: {
|
||||||
|
sourceRel: toolTable.sourceRel,
|
||||||
|
toolCount: toolTable.toolCount,
|
||||||
|
entries: toolTable.entries.map((entry) => ({
|
||||||
|
idx: entry.idx,
|
||||||
|
toolNumber: entry.toolNumber,
|
||||||
|
pocket: entry.pocket,
|
||||||
|
z: entry.offset.z,
|
||||||
|
diameter: entry.diameter,
|
||||||
|
})),
|
||||||
|
},
|
||||||
|
programToolCommands,
|
||||||
|
appliedToolCommands: commands,
|
||||||
|
defaultActivationUsed: programToolCommands.length === 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function defaultToolActivationCommands(toolTable) {
|
||||||
|
const preferred = toolTable.entries.find((entry) => entry.offset.z !== 0)
|
||||||
|
|| toolTable.entries.find((entry) => entry.toolNumber > 0);
|
||||||
|
if (!preferred) return [];
|
||||||
|
return [
|
||||||
|
{ code: "T", toolNumber: preferred.toolNumber, source: "default-tool-table-activation" },
|
||||||
|
{ code: "M6", source: "default-tool-table-activation" },
|
||||||
|
{ code: "G43", h: preferred.toolNumber, toolNumber: preferred.toolNumber, source: "default-tool-table-activation" },
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
function createPathSampling() {
|
function createPathSampling() {
|
||||||
return {
|
return {
|
||||||
samplePeriodMs: SAMPLE_PERIOD_MS,
|
samplePeriodMs: SAMPLE_PERIOD_MS,
|
||||||
|
|||||||
@@ -37,6 +37,17 @@ const checks = [
|
|||||||
check("tool-table", "web tool table staged", webEvidence.coverage?.toolTableStaged === true, {
|
check("tool-table", "web tool table staged", webEvidence.coverage?.toolTableStaged === true, {
|
||||||
toolTable: webEvidence.ini?.toolTable,
|
toolTable: webEvidence.ini?.toolTable,
|
||||||
}),
|
}),
|
||||||
|
check("tool-table", "web tool table active offset drives kinematics, path, and Vismach", webEvidence.coverage?.toolTableToToolOffsetClosed === true, {
|
||||||
|
toolRuntime: {
|
||||||
|
activeToolNumber: webEvidence.toolRuntime?.activeToolNumber,
|
||||||
|
activePocket: webEvidence.toolRuntime?.activePocket,
|
||||||
|
kinematicsToolOffsetZ: webEvidence.toolRuntime?.kinematics?.toolOffsetZ,
|
||||||
|
pathTool: webEvidence.toolRuntime?.pathTool,
|
||||||
|
vismachToolOffset: webEvidence.toolRuntime?.vismach?.toolOffset,
|
||||||
|
defaultActivationUsed: webEvidence.toolRuntime?.defaultActivationUsed,
|
||||||
|
},
|
||||||
|
toolOffsetClosure: webEvidence.toolOffsetClosure,
|
||||||
|
}),
|
||||||
check("pyvcp", "web PyVCP XML staged", webEvidence.coverage?.pyvcpXmlStaged === true, {
|
check("pyvcp", "web PyVCP XML staged", webEvidence.coverage?.pyvcpXmlStaged === true, {
|
||||||
pyvcpXmlPath: webEvidence.profile?.pyvcpXmlPath,
|
pyvcpXmlPath: webEvidence.profile?.pyvcpXmlPath,
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -1,5 +1,108 @@
|
|||||||
# 03-推进台账
|
# 03-推进台账
|
||||||
|
|
||||||
|
## 2026-07-02 Tool table 到 tool-offset 闭环实现轮次
|
||||||
|
|
||||||
|
### 本轮目标
|
||||||
|
|
||||||
|
接续 `working` 任务矩阵,完成 T-034:把 `xyzbc-trt.tbl` 的 T/P/Z/D 当前刀具偏置闭环接到 kinematics tool-offset、Web 模型刀长和 path JSON。
|
||||||
|
|
||||||
|
### 已做事项
|
||||||
|
|
||||||
|
- 修改 `app/src/runtime/tool-db-simulation.js`:
|
||||||
|
- 新增 `createToolRuntimeState()`,统一输出当前刀具、active G43 偏置、`motion.tooloffset.z` 等效值、path tool 和 Vismach tool-offset。
|
||||||
|
- 运行时状态记录 `xyzbc-trt-kins.tool-offset`、`xyzbc-trt-gui.tool-offset` 下游 pin 边界。
|
||||||
|
- 修改 `app/src/runtime/vismach-model-state.js`:
|
||||||
|
- `toolRuntimeState.vismach.toolOffset` 优先于旧的静态 `toolPreview.length`,使模型刀具长度来自 active tool offset。
|
||||||
|
- 修改 `tools/collect-web-xyzbc-trt-evidence.mjs`:
|
||||||
|
- 从 staged `xyzbc-trt.tbl` 解析工具表。
|
||||||
|
- 扫描选定程序 T/M6/G43;默认程序无工具命令时,使用工具表中第一个有 Z 偏置的 T2 生成默认激活证据。
|
||||||
|
- 新增 `toolRuntime` 和 `toolOffsetClosure`,并把 `previewPath.samples[].tool`、`executionPath.samples[].tool` 改为当前 active tool。
|
||||||
|
- 扩展 `tests/node/verify_xyzbc_trt_web_app.mjs`:
|
||||||
|
- 断言 `T2 P2 Z10 D8` 进入 tool DB。
|
||||||
|
- 断言 kinematics tool offset、path tool 和 Vismach pin 均为 T2/Z10/D8 闭环结果。
|
||||||
|
- 重新生成:
|
||||||
|
- `working/evidence/web-xyzbc-trt-evidence.json`
|
||||||
|
- `working/evidence/compare-xyzbc-trt-evidence.json`
|
||||||
|
- 更新 `04-任务矩阵.md`,将 T-034 标记为完成。
|
||||||
|
|
||||||
|
### 验证情况
|
||||||
|
|
||||||
|
- `npm --prefix web-rtcp-5axis-xyzbc-trt-sim-plan/app run smoke:node` 通过。
|
||||||
|
- `npm --prefix web-rtcp-5axis-xyzbc-trt-sim-plan/app run evidence:web` 通过。
|
||||||
|
- `npm --prefix web-rtcp-5axis-xyzbc-trt-sim-plan/app run evidence:compare` 已生成真实失败报告:当前 19/24 通过;T-034 compare 检查已通过,剩余 5 项失败均来自 native evidence 尚缺 `previewPath`/`executionPath` 样本和采样周期字段。
|
||||||
|
- `npm --prefix web-rtcp-5axis-xyzbc-trt-sim-plan/app run build` 通过,输出 `gmoccapy_static_build=ok`。
|
||||||
|
- `npm --prefix web-rtcp-5axis-xyzbc-trt-sim-plan/app run smoke:browser` 通过,输出 `xyzbc_trt_browser_smoke=ok`。
|
||||||
|
- `web-xyzbc-trt-evidence.json` 当前摘要:
|
||||||
|
- `toolRuntime.activeToolNumber=2`
|
||||||
|
- `toolRuntime.activePocket=2`
|
||||||
|
- `toolRuntime.kinematics.toolOffsetZ=10`
|
||||||
|
- `toolRuntime.pathTool.length=10`
|
||||||
|
- `toolRuntime.pathTool.diameter=8`
|
||||||
|
- `toolRuntime.vismach.toolOffset=10`
|
||||||
|
- `toolOffsetClosure.closed=true`
|
||||||
|
- `coverage.toolTableToToolOffsetClosed=true`
|
||||||
|
|
||||||
|
### 下一步
|
||||||
|
|
||||||
|
1. 继续 T-019/T-037:在 `/home/mes123456/cnc_wams/linuxcnc/scripts/rip-environment` 下重跑 native evidence,使 native path 进入 20ms 可比状态。
|
||||||
|
2. 继续 T-026/T-038:基于新 browser smoke 扩展 AXIS 主界面与 native 状态流复核。
|
||||||
|
3. 继续 T-028/T-030:补 basic_sim 等效 task/HAL 细节和 Ngcgui/remap 子程序执行验收。
|
||||||
|
|
||||||
|
## 2026-07-02 Vismach 3D pin 驱动模型实现轮次
|
||||||
|
|
||||||
|
### 本轮目标
|
||||||
|
|
||||||
|
接续 `working` 任务矩阵,完成 T-029:让 Web 3D 机床参考模型由 `xyzbc-trt-gui.py` 对应的 Vismach HAL pin 驱动,并把 pin 值、HAL net 和模型变换写入 Web evidence。
|
||||||
|
|
||||||
|
### 已做事项
|
||||||
|
|
||||||
|
- 新增 `app/src/runtime/vismach-model-state.js`:
|
||||||
|
- 统一生成 `table-x/saddle-y/spindle-z/tilt-b/rotate-c/tool-offset/x-offset/z-offset` pin 状态。
|
||||||
|
- 将 pin 映射到 Web 模型变换:table X、saddle Y、spindle Z、tilt B、rotate C、tool offset。
|
||||||
|
- 记录 9 条 native HAL net 对标关系和 `web_threejs_vismach_equivalent_driven_by_xyzbc_trt_hal_pins` 语义边界。
|
||||||
|
- 修改 `app/src/visualization/five-axis-scene.js`:
|
||||||
|
- 将静态参考模型拆成 `vismach-table-x`、`vismach-saddle-y`、`vismach-spindle-z`、`vismach-tilt-b`、`vismach-rotate-c`、`vismach-tool-offset` 层级。
|
||||||
|
- 渲染时按 `buildVismachModelState()` 输出更新 Three.js group 的位移和旋转。
|
||||||
|
- 在 canvas dataset 增加 `threeVismachPins`、`threeVismachTransforms`、`threeVismachPinDrivenModel`,供后续浏览器 smoke 直接断言。
|
||||||
|
- 修改 `tools/collect-web-xyzbc-trt-evidence.mjs`:
|
||||||
|
- `vismachEquivalent` 从静态 pin 清单升级为 `pins`、`pinValues`、`transforms`、`halNets` 和 `semanticBoundary`。
|
||||||
|
- 扩展 `tests/node/verify_xyzbc_trt_web_app.mjs`:
|
||||||
|
- 断言 profile 中 Vismach feedback/offset net。
|
||||||
|
- 断言 pin 到模型变换的映射和 tool-offset/x-offset/z-offset 组合。
|
||||||
|
- 新增目标浏览器 smoke:
|
||||||
|
- `tests/browser/xyzbc_trt_browser_smoke.html`
|
||||||
|
- `tests/browser/verify_xyzbc_trt_browser.sh`
|
||||||
|
- `app/package.json` 增加 `smoke:browser`。
|
||||||
|
- 浏览器断言默认 profile 为 `xyzbc-trt`,kinematics/interpreter/task-HAL 均在 worker 中 ready,canvas 非空,`threeVismachPinDrivenModel` 和 Vismach pin/transform dataset 可读。
|
||||||
|
- 重新生成:
|
||||||
|
- `working/evidence/web-xyzbc-trt-evidence.json`
|
||||||
|
- `working/evidence/compare-xyzbc-trt-evidence.json`
|
||||||
|
- 更新 `04-任务矩阵.md`,将 T-014、T-029 标记为完成,并补充 T-035 Web evidence 字段。
|
||||||
|
|
||||||
|
### 验证情况
|
||||||
|
|
||||||
|
- `npm --prefix web-rtcp-5axis-xyzbc-trt-sim-plan/app run smoke:node` 通过。
|
||||||
|
- `npm --prefix web-rtcp-5axis-xyzbc-trt-sim-plan/app run evidence:web` 通过。
|
||||||
|
- `web-xyzbc-trt-evidence.json` 当前摘要:
|
||||||
|
- `status=ready-for-wasm-runtime`
|
||||||
|
- `blockers=[]`
|
||||||
|
- `vismachEquivalent.pinValues.table-x=43`
|
||||||
|
- `vismachEquivalent.pinValues.saddle-y=-32.15`
|
||||||
|
- `vismachEquivalent.pinValues.spindle-z=-11.306`
|
||||||
|
- `vismachEquivalent.pinValues.tool-offset=84.019`
|
||||||
|
- `vismachEquivalent.pinValues.x-offset=-20`
|
||||||
|
- `vismachEquivalent.pinValues.z-offset=-15`
|
||||||
|
- `vismachEquivalent.halNets.length=9`
|
||||||
|
- `npm --prefix web-rtcp-5axis-xyzbc-trt-sim-plan/app run evidence:compare` 已生成真实失败报告:仍为 5 项失败,均来自 native evidence 尚缺 `previewPath`/`executionPath` 样本和采样周期字段。
|
||||||
|
- `npm --prefix web-rtcp-5axis-xyzbc-trt-sim-plan/app run build` 通过,输出 `gmoccapy_static_build=ok`。
|
||||||
|
- `npm --prefix web-rtcp-5axis-xyzbc-trt-sim-plan/app run smoke:browser` 通过,输出 `xyzbc_trt_browser_smoke=ok`。
|
||||||
|
|
||||||
|
### 下一步
|
||||||
|
|
||||||
|
1. 继续 T-019/T-037:在 `/home/mes123456/cnc_wams/linuxcnc/scripts/rip-environment` 下重跑 native evidence,使 native path 进入 20ms 可比状态。
|
||||||
|
2. 继续 T-034:把 tool table 当前 T/P/Z/D 的 active tool offset 闭环接到 kinematics/tool model/path JSON。
|
||||||
|
3. 继续 T-026/T-038:基于新 browser smoke 扩展 AXIS 主界面与 native 状态流复核。
|
||||||
|
|
||||||
## 2026-07-02 Web task/HAL executionPath 采集实现轮次
|
## 2026-07-02 Web task/HAL executionPath 采集实现轮次
|
||||||
|
|
||||||
### 本轮目标
|
### 本轮目标
|
||||||
|
|||||||
@@ -15,10 +15,10 @@
|
|||||||
| T-011 | 完整 kinematics WASM 验证 | 完成 | `SKIP_KINEMATICS_BUILD=1 wasm-port/tests/wasm/node/verify_kinematics_wasm.sh` 通过,覆盖 `xyzbc-trt` |
|
| T-011 | 完整 kinematics WASM 验证 | 完成 | `SKIP_KINEMATICS_BUILD=1 wasm-port/tests/wasm/node/verify_kinematics_wasm.sh` 通过,覆盖 `xyzbc-trt` |
|
||||||
| T-012 | 完整 interpreter/remap WASM 验证 | 完成 | `wasm-port/tests/wasm/node/verify_interp_wasm.sh` 通过,输出 `interp_wasm_node_smoke=ok` |
|
| T-012 | 完整 interpreter/remap WASM 验证 | 完成 | `wasm-port/tests/wasm/node/verify_interp_wasm.sh` 通过,输出 `interp_wasm_node_smoke=ok` |
|
||||||
| T-013 | 完整 task/HAL WASM 验证 | 完成 | `SKIP_TASK_HAL_BUILD=1 wasm-port/tests/wasm/node/verify_task_hal_wasm.sh` 通过 |
|
| T-013 | 完整 task/HAL WASM 验证 | 完成 | `SKIP_TASK_HAL_BUILD=1 wasm-port/tests/wasm/node/verify_task_hal_wasm.sh` 通过 |
|
||||||
| T-014 | 目标浏览器 smoke | 待前置 | 页面默认显示 `xyzbc-trt`,worker runtime ready,canvas 非空 |
|
| T-014 | 目标浏览器 smoke | 完成 | `npm run smoke:browser` 通过;页面默认显示 `xyzbc-trt`,kinematics/interpreter/task-HAL worker runtime ready,canvas 非空并暴露 Vismach dataset |
|
||||||
| T-015 | native 真实执行 JSON 采集 | 完成 | `native-xyzbc-trt-evidence.json` 记录真实执行事件,状态 completed |
|
| T-015 | native 真实执行 JSON 采集 | 完成 | `native-xyzbc-trt-evidence.json` 记录真实执行事件,状态 completed |
|
||||||
| T-016 | Web OPFS/WASM readiness JSON 采集 | 完成 | `web-xyzbc-trt-evidence.json` 记录 Web profile/INI/staging/WASM readiness |
|
| T-016 | Web OPFS/WASM readiness JSON 采集 | 完成 | `web-xyzbc-trt-evidence.json` 记录 Web profile/INI/staging/WASM readiness |
|
||||||
| T-017 | native/Web JSON 对比 | 部分完成 | `compare-xyzbc-trt-evidence.json` 已生成;当前 18/23 通过,剩余 5 项均为 native preview/execution path 样本缺失 |
|
| T-017 | native/Web JSON 对比 | 部分完成 | `compare-xyzbc-trt-evidence.json` 已生成;当前 19/24 通过,剩余 5 项均为 native preview/execution path 样本缺失 |
|
||||||
| T-018 | WASM artifact 构建前置 | 完成 | 已生成 core/kinematics/tp/task-hal 所需 `.js/.wasm`,`web-xyzbc-trt-evidence.json.wasm.missing=[]` |
|
| T-018 | WASM artifact 构建前置 | 完成 | 已生成 core/kinematics/tp/task-hal 所需 `.js/.wasm`,`web-xyzbc-trt-evidence.json.wasm.missing=[]` |
|
||||||
| T-019 | native 刀具预览路径 JSON 采集 | 待实现 | `native-xyzbc-trt-evidence.json.previewPath.samples` 使用 20ms 周期记录 LinuxCNC 预览刀路 |
|
| T-019 | native 刀具预览路径 JSON 采集 | 待实现 | `native-xyzbc-trt-evidence.json.previewPath.samples` 使用 20ms 周期记录 LinuxCNC 预览刀路 |
|
||||||
| T-020 | native 刀具执行路径 JSON 采集 | 部分完成 | native 脚本已从 `stat()` 执行事件重采样为 20ms `executionPath`;需用新基线重跑生成证据 |
|
| T-020 | native 刀具执行路径 JSON 采集 | 部分完成 | native 脚本已从 `stat()` 执行事件重采样为 20ms `executionPath`;需用新基线重跑生成证据 |
|
||||||
@@ -30,13 +30,13 @@
|
|||||||
| T-026 | AXIS 主界面等效功能 | 待实现 | Web 首屏包含程序、坐标、状态、MDI/switchkins、override、工具和预览/执行区域 |
|
| T-026 | AXIS 主界面等效功能 | 待实现 | Web 首屏包含程序、坐标、状态、MDI/switchkins、override、工具和预览/执行区域 |
|
||||||
| T-027 | POSTGUI HAL/PyVCP 连接等效 | 完成 | Web evidence JSON 记录 `pyvcp.* -> halui.mdi-command-* -> M428/M429/M430` 和 multilabel 状态 |
|
| T-027 | POSTGUI HAL/PyVCP 连接等效 | 完成 | Web evidence JSON 记录 `pyvcp.* -> halui.mdi-command-* -> M428/M429/M430` 和 multilabel 状态 |
|
||||||
| T-028 | basic_sim 等效 task/HAL | 待前置 | Web task/HAL runtime 覆盖模拟回零、manual toolchange、spindle、joint feedback |
|
| T-028 | basic_sim 等效 task/HAL | 待前置 | Web task/HAL runtime 覆盖模拟回零、manual toolchange、spindle、joint feedback |
|
||||||
| T-029 | Vismach 3D 模型 pin 对标 | 待实现 | Web 3D 模型由 `table-x/saddle-y/spindle-z/tilt-b/rotate-c/tool-offset/x-offset/z-offset` 驱动 |
|
| T-029 | Vismach 3D 模型 pin 对标 | 完成 | Web 3D 模型由 `table-x/saddle-y/spindle-z/tilt-b/rotate-c/tool-offset/x-offset/z-offset` 驱动;`web-xyzbc-trt-evidence.json.vismachEquivalent` 记录 pin 值、HAL net 和变换 |
|
||||||
| T-030 | Ngcgui/remap 子程序全集 | 部分完成 | staging 和 Web evidence 覆盖 `xyzbc_switchkins_sub.ngc`、`centering.ngc`、`helix_bc.ngc`;执行仍待 WASM |
|
| T-030 | Ngcgui/remap 子程序全集 | 部分完成 | staging 和 Web evidence 覆盖 `xyzbc_switchkins_sub.ngc`、`centering.ngc`、`helix_bc.ngc`;执行仍待 WASM |
|
||||||
| T-031 | 演示程序全集 | 完成 | staging、profile samplePrograms 和 Web evidence 覆盖 `xyzbc_switchkins.ngc` 与 `boat-xyzbc.ngc` |
|
| T-031 | 演示程序全集 | 完成 | staging、profile samplePrograms 和 Web evidence 覆盖 `xyzbc_switchkins.ngc` 与 `boat-xyzbc.ngc` |
|
||||||
| T-032 | TRAJ/AXIS/JOINT 限制对标 | 部分完成 | Web evidence 覆盖 XYZBC 单位、速度/加速度、B/C 限位、JOG_AXES、GEOMETRY;UI 全量复核仍待浏览器/WASM |
|
| T-032 | TRAJ/AXIS/JOINT 限制对标 | 部分完成 | Web evidence 覆盖 XYZBC 单位、速度/加速度、B/C 限位、JOG_AXES、GEOMETRY;UI 全量复核仍待浏览器/WASM |
|
||||||
| T-033 | kinematics HAL pins 对标 | 完成 | Web/native evidence 脚本记录 `x-offset=-20`、`z-offset=-15`、rot-point、conventional-directions、tool-offset |
|
| T-033 | kinematics HAL pins 对标 | 完成 | Web/native evidence 脚本记录 `x-offset=-20`、`z-offset=-15`、rot-point、conventional-directions、tool-offset |
|
||||||
| T-034 | tool table 到 tool-offset 闭环 | 待实现 | T/P/Z/D 解析影响 kinematics tool-offset、Web 模型刀长和 path JSON |
|
| T-034 | tool table 到 tool-offset 闭环 | 完成 | `xyzbc-trt.tbl` T2/P2/Z10/D8 解析后驱动 `toolRuntime.kinematics.toolOffsetZ=10`、Web path tool length/diameter 和 Vismach `tool-offset=10` |
|
||||||
| T-035 | 全量 evidence JSON 字段 | 部分完成 | Web JSON 已包含 `startupSequence`、`iniDisplay`、`halNets`、`kinematicsPins`、`axisJointLimits`、`uiEquivalence`;native 脚本已补字段,需重采集 |
|
| T-035 | 全量 evidence JSON 字段 | 部分完成 | Web JSON 已包含 `startupSequence`、`iniDisplay`、`halNets`、`kinematicsPins`、`axisJointLimits`、`uiEquivalence`、`vismachEquivalent.pinValues/transforms`;native 脚本已补字段,需重采集 |
|
||||||
| T-036 | native 基线切换到 `/home/mes123456/cnc_wams/linuxcnc` | 完成 | `scripts/rip-environment`、`bin/axis`、`bin/xyzbc-trt-gui`、`rtlib/xyzbc-trt-kins.so` 已生成,RIP 环境可导入 `linuxcnc` Python 模块 |
|
| T-036 | native 基线切换到 `/home/mes123456/cnc_wams/linuxcnc` | 完成 | `scripts/rip-environment`、`bin/axis`、`bin/xyzbc-trt-gui`、`rtlib/xyzbc-trt-kins.so` 已生成,RIP 环境可导入 `linuxcnc` Python 模块 |
|
||||||
| T-037 | 基于新 native 基线重采集 JSON | 部分完成 | native 脚本默认基线已切到 `/home/mes123456/cnc_wams/linuxcnc`;需在 RIP 环境下重新运行采集命令 |
|
| T-037 | 基于新 native 基线重采集 JSON | 部分完成 | native 脚本默认基线已切到 `/home/mes123456/cnc_wams/linuxcnc`;需在 RIP 环境下重新运行采集命令 |
|
||||||
| T-038 | Web 界面按新 native 运行结果复核 | 待实现 | UI/逻辑与 `/home/mes123456/cnc_wams/linuxcnc` 真实 `xyzbc-trt` 的状态流、按钮、路径、HAL pin 对齐 |
|
| T-038 | Web 界面按新 native 运行结果复核 | 待实现 | UI/逻辑与 `/home/mes123456/cnc_wams/linuxcnc` 真实 `xyzbc-trt` 的状态流、按钮、路径、HAL pin 对齐 |
|
||||||
|
|||||||
@@ -1,5 +1,99 @@
|
|||||||
# 05-验收证据
|
# 05-验收证据
|
||||||
|
|
||||||
|
## Tool table 到 tool-offset 闭环验收
|
||||||
|
|
||||||
|
### 命令
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm --prefix web-rtcp-5axis-xyzbc-trt-sim-plan/app run smoke:node
|
||||||
|
npm --prefix web-rtcp-5axis-xyzbc-trt-sim-plan/app run evidence:web
|
||||||
|
npm --prefix web-rtcp-5axis-xyzbc-trt-sim-plan/app run evidence:compare
|
||||||
|
npm --prefix web-rtcp-5axis-xyzbc-trt-sim-plan/app run build
|
||||||
|
npm --prefix web-rtcp-5axis-xyzbc-trt-sim-plan/app run smoke:browser
|
||||||
|
```
|
||||||
|
|
||||||
|
### 结果
|
||||||
|
|
||||||
|
```text
|
||||||
|
xyzbc_trt_web_app_smoke=ok
|
||||||
|
web_xyzbc_trt_evidence=.../working/evidence/web-xyzbc-trt-evidence.json
|
||||||
|
compare_xyzbc_trt_status=fail fail_count=5
|
||||||
|
gmoccapy_static_build=ok
|
||||||
|
xyzbc_trt_browser_smoke=ok
|
||||||
|
```
|
||||||
|
|
||||||
|
### JSON 摘要
|
||||||
|
|
||||||
|
```text
|
||||||
|
web.toolRuntime.ready = true
|
||||||
|
web.toolRuntime.activeOffsetApplied = true
|
||||||
|
web.toolRuntime.activeToolNumber = 2
|
||||||
|
web.toolRuntime.activePocket = 2
|
||||||
|
web.toolRuntime.kinematics.toolOffsetZ = 10
|
||||||
|
web.toolRuntime.pathTool.length = 10
|
||||||
|
web.toolRuntime.pathTool.diameter = 8
|
||||||
|
web.toolRuntime.vismach.toolOffset = 10
|
||||||
|
web.toolOffsetClosure.closed = true
|
||||||
|
web.coverage.toolTableToToolOffsetClosed = true
|
||||||
|
web.previewPath.samples[0].tool = { id: 2, pocket: 2, length: 10, diameter: 8 }
|
||||||
|
web.executionPath.samples[0].tool = { id: 2, pocket: 2, length: 10, diameter: 8 }
|
||||||
|
compare.summary.passCount = 19
|
||||||
|
compare.summary.failCount = 5
|
||||||
|
compare.checks["web tool table active offset drives kinematics, path, and Vismach"].status = pass
|
||||||
|
```
|
||||||
|
|
||||||
|
结论:
|
||||||
|
|
||||||
|
- `xyzbc-trt.tbl` 中 `T2 P2 Z10 D8` 已进入 Web tool DB 运行时摘要。
|
||||||
|
- 当前 active tool offset 已同时写入 kinematics `motion.tooloffset.z` 等效值、路径样本 tool 字段和 Vismach `tool-offset` pin。
|
||||||
|
- 默认程序本身无 T/M6/G43,因此 Web evidence 记录 `defaultActivationUsed=true`,用于证明 tool table 偏置链路;带 T/M6/G43 的程序会使用程序扫描命令。
|
||||||
|
- compare 仍保持失败是正确结果:剩余 5 项仍来自 native path evidence 未重采集。
|
||||||
|
|
||||||
|
## Vismach 3D pin 驱动模型验收
|
||||||
|
|
||||||
|
### 命令
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm --prefix web-rtcp-5axis-xyzbc-trt-sim-plan/app run smoke:node
|
||||||
|
npm --prefix web-rtcp-5axis-xyzbc-trt-sim-plan/app run evidence:web
|
||||||
|
npm --prefix web-rtcp-5axis-xyzbc-trt-sim-plan/app run evidence:compare
|
||||||
|
npm --prefix web-rtcp-5axis-xyzbc-trt-sim-plan/app run build
|
||||||
|
npm --prefix web-rtcp-5axis-xyzbc-trt-sim-plan/app run smoke:browser
|
||||||
|
```
|
||||||
|
|
||||||
|
### 结果
|
||||||
|
|
||||||
|
```text
|
||||||
|
xyzbc_trt_web_app_smoke=ok
|
||||||
|
web_xyzbc_trt_evidence=.../working/evidence/web-xyzbc-trt-evidence.json
|
||||||
|
compare_xyzbc_trt_status=fail fail_count=5
|
||||||
|
gmoccapy_static_build=ok
|
||||||
|
xyzbc_trt_browser_smoke=ok
|
||||||
|
```
|
||||||
|
|
||||||
|
### JSON 摘要
|
||||||
|
|
||||||
|
```text
|
||||||
|
web.status = ready-for-wasm-runtime
|
||||||
|
web.blockers = []
|
||||||
|
web.vismachEquivalent.pins = table-x,saddle-y,spindle-z,tilt-b,rotate-c,tool-offset,x-offset,z-offset
|
||||||
|
web.vismachEquivalent.pinValues.table-x = 43
|
||||||
|
web.vismachEquivalent.pinValues.saddle-y = -32.15
|
||||||
|
web.vismachEquivalent.pinValues.spindle-z = -11.306
|
||||||
|
web.vismachEquivalent.pinValues.tool-offset = 84.019
|
||||||
|
web.vismachEquivalent.pinValues.x-offset = -20
|
||||||
|
web.vismachEquivalent.pinValues.z-offset = -15
|
||||||
|
web.vismachEquivalent.halNets.length = 9
|
||||||
|
web.vismachEquivalent.semanticBoundary = web_threejs_vismach_equivalent_driven_by_xyzbc_trt_hal_pins
|
||||||
|
```
|
||||||
|
|
||||||
|
结论:
|
||||||
|
|
||||||
|
- Web 3D 参考模型已由 Vismach 等效 pin 状态驱动。
|
||||||
|
- canvas dataset 已输出 `threeVismachPins`、`threeVismachTransforms`、`threeVismachPinDrivenModel`,后续浏览器 smoke 可直接断言。
|
||||||
|
- `smoke:browser` 已断言默认 `xyzbc-trt`、三类 worker runtime ready、canvas 非空、Vismach pin/transform dataset。
|
||||||
|
- compare 仍保持失败是正确结果:剩余 5 项仍来自 native path evidence 未重采集。
|
||||||
|
|
||||||
## evidence 字段与路径对比实现验收
|
## evidence 字段与路径对比实现验收
|
||||||
|
|
||||||
### 命令
|
### 命令
|
||||||
@@ -45,6 +139,8 @@ uiEquivalence
|
|||||||
vismachEquivalent
|
vismachEquivalent
|
||||||
ngcguiSubroutines
|
ngcguiSubroutines
|
||||||
demoPrograms
|
demoPrograms
|
||||||
|
vismachEquivalent.pinValues
|
||||||
|
vismachEquivalent.transforms
|
||||||
```
|
```
|
||||||
|
|
||||||
当前 compare evidence 已包含:
|
当前 compare evidence 已包含:
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
| `.desktop` 启动 `rip-environment linuxcnc xyzbc-trt.ini` | `/home/mes123456/cnc_wams/linuxcnc/linuxcnc-rtcp-5axis-shortcuts/.../xyzbc-trt.desktop` | Web profile 一键进入 `xyzbc-trt`,自动加载同一 INI/staging 文件集 | web JSON 记录 `profile=xyzbc-trt`、`iniPath`、`startupSequence` |
|
| `.desktop` 启动 `rip-environment linuxcnc xyzbc-trt.ini` | `/home/mes123456/cnc_wams/linuxcnc/linuxcnc-rtcp-5axis-shortcuts/.../xyzbc-trt.desktop` | Web profile 一键进入 `xyzbc-trt`,自动加载同一 INI/staging 文件集 | web JSON 记录 `profile=xyzbc-trt`、`iniPath`、`startupSequence` |
|
||||||
| `linuxcncsvr`、`rtapi_app`、`milltask`、`halui` | 当前进程清单 | Web runtime 用 worker/WASM/task-HAL 表示 server/task/halui 边界 | compare 检查 `runtimeComponents` 包含 `interp`、`tp`、`taskHal`、`haluiEquivalent` |
|
| `linuxcncsvr`、`rtapi_app`、`milltask`、`halui` | 当前进程清单 | Web runtime 用 worker/WASM/task-HAL 表示 server/task/halui 边界 | compare 检查 `runtimeComponents` 包含 `interp`、`tp`、`taskHal`、`haluiEquivalent` |
|
||||||
| AXIS 主界面进程 | `bin/axis -ini xyzbc-trt.ini` | Web 首屏直接进入 CNC 操作界面,不做营销页 | 浏览器 smoke 检查坐标、程序、switchkins、3D canvas 均可见 |
|
| AXIS 主界面进程 | `bin/axis -ini xyzbc-trt.ini` | Web 首屏直接进入 CNC 操作界面,不做营销页 | 浏览器 smoke 检查坐标、程序、switchkins、3D canvas 均可见 |
|
||||||
| Vismach 进程 | `loadusr -W xyzbc-trt-gui` | Web 3D 机床模型按 HAL pin 驱动 | evidence 记录 Vismach pin 等效映射 |
|
| Vismach 进程 | `loadusr -W xyzbc-trt-gui` | Web 3D 机床模型按 HAL pin 驱动 | evidence 记录 Vismach pin 值、HAL net 和模型变换 |
|
||||||
|
|
||||||
## INI 与显示配置对标
|
## INI 与显示配置对标
|
||||||
|
|
||||||
@@ -45,10 +45,10 @@
|
|||||||
| `switchkins_postgui.hal` | PyVCP 到 halui MDI 的连接 | Web 需记录 `pyvcp.* -> halui.mdi-command-*` | 待 compare 检查 |
|
| `switchkins_postgui.hal` | PyVCP 到 halui MDI 的连接 | Web 需记录 `pyvcp.* -> halui.mdi-command-*` | 待 compare 检查 |
|
||||||
| `basic_sim.tcl` | 基础仿真 HAL | Web task/HAL runtime 等效模拟 joint/home/spindle/toolchange | 待 task-HAL 验收 |
|
| `basic_sim.tcl` | 基础仿真 HAL | Web task/HAL runtime 等效模拟 joint/home/spindle/toolchange | 待 task-HAL 验收 |
|
||||||
| `xyzbc-trt_cmds.hal` | 运行后生成 HAL | Web evidence 需记录等效展开 HAL nets | 待实现 |
|
| `xyzbc-trt_cmds.hal` | 运行后生成 HAL | Web evidence 需记录等效展开 HAL nets | 待实现 |
|
||||||
| `xyzbc-trt-gui.py` | Vismach 模型 | Web 3D pin/模型层级对标 | 待模型验收 |
|
| `xyzbc-trt-gui.py` | Vismach 模型 | Web 3D pin/模型层级对标 | 已完成 Web 端模型层级、evidence 和浏览器 smoke 验收 |
|
||||||
| `axis.py` | AXIS 主界面行为 | Web 操作面板对标 AXIS 关键行为 | 待 UI 验收 |
|
| `axis.py` | AXIS 主界面行为 | Web 操作面板对标 AXIS 关键行为 | 待 UI 验收 |
|
||||||
| `xyzbc-trt-kins.c` | 运动学真源 | WASM kinematics 使用 source-derived artifact | 待构建 artifact |
|
| `xyzbc-trt-kins.c` | 运动学真源 | WASM kinematics 使用 source-derived artifact | 待构建 artifact |
|
||||||
| `xyzbc-trt.tbl` | 工具表 | Web tool DB 读取 T/P/Z/D | 已有 staging,需 UI/tool-offset 验收 |
|
| `xyzbc-trt.tbl` | 工具表 | Web tool DB 读取 T/P/Z/D | Web evidence 已证明 T2/P2/Z10/D8 驱动 kinematics、path tool 和 Vismach tool-offset |
|
||||||
| `xyzbc.var` | 参数文件 | OPFS 保存/恢复参数 | 已有 staging,需运行后变更验证 |
|
| `xyzbc.var` | 参数文件 | OPFS 保存/恢复参数 | 已有 staging,需运行后变更验证 |
|
||||||
|
|
||||||
## HAL 与 switchkins 对标
|
## HAL 与 switchkins 对标
|
||||||
@@ -74,8 +74,8 @@
|
|||||||
| `z-offset = -15` | HALCMD sets | Web kinematics pin 默认值一致 |
|
| `z-offset = -15` | HALCMD sets | Web kinematics pin 默认值一致 |
|
||||||
| `x/y/z-rot-point = 0` | HALCMD setp | Web kinematics pin 默认值一致 |
|
| `x/y/z-rot-point = 0` | HALCMD setp | Web kinematics pin 默认值一致 |
|
||||||
| `conventional-directions = 0` | HALCMD setp | Web kinematics pin 默认值一致 |
|
| `conventional-directions = 0` | HALCMD setp | Web kinematics pin 默认值一致 |
|
||||||
| `table-x/saddle-y/spindle-z/tilt-b/rotate-c` | Vismach pins | Web 模型层级按这些反馈驱动 |
|
| `table-x/saddle-y/spindle-z/tilt-b/rotate-c` | Vismach pins | Web 模型层级按这些反馈驱动;`vismachEquivalent.pinValues/transforms` 可验收 |
|
||||||
| `tool-offset/x-offset/z-offset` | Vismach/kines pins | Web 刀具和模型偏置一致 |
|
| `tool-offset/x-offset/z-offset` | Vismach/kines pins | Web 刀具和模型偏置一致;T-034 已完成 Web tool table active offset 闭环,native 仍待重采集对比 |
|
||||||
|
|
||||||
## G-code、remap 与子程序对标
|
## G-code、remap 与子程序对标
|
||||||
|
|
||||||
@@ -112,6 +112,6 @@ native evidence、Web evidence、compare evidence 必须覆盖:
|
|||||||
1. WASM artifact 尚未构建,`wasm-port/build/wasm` 缺少 kinematics/core/tp/task-hal `.js/.wasm`。
|
1. WASM artifact 尚未构建,`wasm-port/build/wasm` 缺少 kinematics/core/tp/task-hal `.js/.wasm`。
|
||||||
2. Web evidence 还未记录完整 `startupSequence`、`halNets`、`kinematicsPins`、`axisJointLimits`。
|
2. Web evidence 还未记录完整 `startupSequence`、`halNets`、`kinematicsPins`、`axisJointLimits`。
|
||||||
3. Web UI 还需按 AXIS 等效面板补齐 jog、override、tool editor、Ngcgui 子程序入口。
|
3. Web UI 还需按 AXIS 等效面板补齐 jog、override、tool editor、Ngcgui 子程序入口。
|
||||||
4. Vismach 等效模型还需按 `xyzbc-trt-gui.py` 的 pin 和模型层级做验收。
|
4. Vismach 等效模型已按 `xyzbc-trt-gui.py` 的 pin 和模型层级完成 Web 端验收;`smoke:browser` 已覆盖 canvas 非空和 dataset,后续可补截图归档。
|
||||||
5. 刀具预览路径和执行路径 JSON 采集尚未实现。
|
5. 刀具预览路径和执行路径 JSON 采集尚未实现。
|
||||||
6. `boat-xyzbc.ngc` 和 Ngcgui 子程序的 Web 可执行验收尚未完成。
|
6. `boat-xyzbc.ngc` 和 Ngcgui 子程序的 Web 可执行验收尚未完成。
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"apiName": "xyzbc-trt-native-web-evidence-comparison",
|
"apiName": "xyzbc-trt-native-web-evidence-comparison",
|
||||||
"status": "fail",
|
"status": "fail",
|
||||||
"comparedAt": "2026-07-02T12:48:11.244Z",
|
"comparedAt": "2026-07-02T13:36:36.368Z",
|
||||||
"nativePath": "/home/mes123456/cnc_wams/web-rtcp-5axis-xyzbc-trt-sim-plan/working/evidence/native-xyzbc-trt-evidence.json",
|
"nativePath": "/home/mes123456/cnc_wams/web-rtcp-5axis-xyzbc-trt-sim-plan/working/evidence/native-xyzbc-trt-evidence.json",
|
||||||
"webPath": "/home/mes123456/cnc_wams/web-rtcp-5axis-xyzbc-trt-sim-plan/working/evidence/web-xyzbc-trt-evidence.json",
|
"webPath": "/home/mes123456/cnc_wams/web-rtcp-5axis-xyzbc-trt-sim-plan/working/evidence/web-xyzbc-trt-evidence.json",
|
||||||
"summary": {
|
"summary": {
|
||||||
"checkCount": 23,
|
"checkCount": 24,
|
||||||
"passCount": 18,
|
"passCount": 19,
|
||||||
"failCount": 5,
|
"failCount": 5,
|
||||||
"blockers": [],
|
"blockers": [],
|
||||||
"nativeStatus": "ok",
|
"nativeStatus": "ok",
|
||||||
@@ -107,6 +107,61 @@
|
|||||||
"toolTable": "xyzbc-trt.tbl"
|
"toolTable": "xyzbc-trt.tbl"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"category": "tool-table",
|
||||||
|
"requirement": "web tool table active offset drives kinematics, path, and Vismach",
|
||||||
|
"status": "pass",
|
||||||
|
"evidence": {
|
||||||
|
"toolRuntime": {
|
||||||
|
"activeToolNumber": 2,
|
||||||
|
"activePocket": 2,
|
||||||
|
"kinematicsToolOffsetZ": 10,
|
||||||
|
"pathTool": {
|
||||||
|
"id": 2,
|
||||||
|
"pocket": 2,
|
||||||
|
"length": 10,
|
||||||
|
"diameter": 8
|
||||||
|
},
|
||||||
|
"vismachToolOffset": 10,
|
||||||
|
"defaultActivationUsed": true
|
||||||
|
},
|
||||||
|
"toolOffsetClosure": {
|
||||||
|
"sourceToolTable": "configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzbc-trt.tbl",
|
||||||
|
"selectedProgramSourceRel": "configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzbc_switchkins.ngc",
|
||||||
|
"programToolCommands": [],
|
||||||
|
"activeToolOffset": {
|
||||||
|
"idx": 2,
|
||||||
|
"toolNumber": 2,
|
||||||
|
"pocket": 2,
|
||||||
|
"offset": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"z": 10,
|
||||||
|
"a": 0,
|
||||||
|
"b": 0,
|
||||||
|
"c": 0,
|
||||||
|
"u": 0,
|
||||||
|
"v": 0,
|
||||||
|
"w": 0
|
||||||
|
},
|
||||||
|
"diameter": 8,
|
||||||
|
"frontAngle": 0,
|
||||||
|
"backAngle": 0,
|
||||||
|
"orientation": 0
|
||||||
|
},
|
||||||
|
"kinematicsToolOffsetZ": 10,
|
||||||
|
"pathTool": {
|
||||||
|
"id": 2,
|
||||||
|
"pocket": 2,
|
||||||
|
"length": 10,
|
||||||
|
"diameter": 8
|
||||||
|
},
|
||||||
|
"vismachToolOffset": 10,
|
||||||
|
"closed": true,
|
||||||
|
"semanticBoundary": "tool_table_current_t_p_z_d_drives_kinematics_path_and_vismach"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"category": "pyvcp",
|
"category": "pyvcp",
|
||||||
"requirement": "web PyVCP XML staged",
|
"requirement": "web PyVCP XML staged",
|
||||||
@@ -317,6 +372,8 @@
|
|||||||
"zRotPoint": 0,
|
"zRotPoint": 0,
|
||||||
"conventionalDirections": 0,
|
"conventionalDirections": 0,
|
||||||
"toolOffsetSource": "motion.tooloffset.z",
|
"toolOffsetSource": "motion.tooloffset.z",
|
||||||
|
"toolOffsetValue": 10,
|
||||||
|
"toolOffsetToolNumber": 2,
|
||||||
"pins": [
|
"pins": [
|
||||||
"motion.switchkins-type",
|
"motion.switchkins-type",
|
||||||
"motion.analog-out-03",
|
"motion.analog-out-03",
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user