diff --git a/coverage/xyzac-panel-button-parity.report.json b/coverage/xyzac-panel-button-parity.report.json index 0088769..f3a1118 100644 --- a/coverage/xyzac-panel-button-parity.report.json +++ b/coverage/xyzac-panel-button-parity.report.json @@ -43,12 +43,13 @@ "line_count": 4711, "preview_segments": 4684, "fixed_tick_samples": 3000, - "execution_line": 147, - "execution_trace_entries": 145, + "execution_line": 337, + "execution_trace_entries": 335, "motion_authority": "wasm", + "running_queue_gaps": 0, "motion_delta_snapshots": 0, "ledger_audit_window": 32, - "output_sha256": "c97caef2ea5cf3841e1238ec443d0eebadad8cb0048af829111c06e99c9fcdd7" + "output_sha256": "c97b5fbb43a6e81a8ee15272bf71aa75ec0ba79be28a34f30b4221d50251c77d" }, "native_tests": { "wasm_build": "passed", @@ -56,7 +57,7 @@ }, "published_browser_smoke": { "url": "https://49.232.250.35:58010/", - "release": "20260902-linuxcnc-wasm-switchkins-r7", + "release": "20260902-linuxcnc-wasm-continuous-r10", "status": "verified", "startup_pause_resume_stop": "verified", "pause_tick": 140, @@ -64,15 +65,23 @@ "stop_state": "IDLE", "browser_errors": 0, "output_sha256": "bdf705473e6cda94d721aa23329257adf4a68b705add7650da5cc47012ab70b0", + "continuous_runtime": { + "sampled_running_frames": 33, + "queue_gaps": 0, + "first_running": {"current_line": 62, "queue_depth": 3, "velocity": 20, "active_id": 16}, + "last_running": {"current_line": 69, "queue_depth": 2, "velocity": 16.6666666667, "active_id": 17}, + "screenshot_sha256": "c93fd23e648e49bfa9359af245372f03f3fccee123497909f3dcc005f5a59749", + "browser_errors": 0 + }, "screenshot_sha256": { "authority": "e58205228a04b386c7b7514bf03c71df7b53f66f2d9ebe2292931b36ef0edb55", "running": "7fc474d0cb31a0fdd4afb198061e9812c753684e3d2963cc004ec4483c5c4990", "switchkins": "920b85ad7fd6451dfb134255ffdcc4f03a7aa615ebf486c63cde8582e17af195" }, "resource_sha256": { - "index-DEinWp01.js": "79f5e933909fc631186db9b5091b6239f30c1ade612bb908a4ab9fcf79965343", - "sim-worker-entry-7q53Ew6x.js": "e5c239104d6676f242ea45cb3ddaf78a379aaaecaca5ff26031dee1ba9496e7c", - "linuxcnc-sim-core-CJilJ2YZ.wasm": "13e2746899b0cac5cf91189c00a6174160202f8e632b53c5701e9664335c97cf" + "index-Byst0JhC.js": "26d3f21f496c8223218761ba641dab8b4f36fd18892f260c7bf5b5cfa83cafec", + "sim-worker-entry-BTVfbu6g.js": "adf2ac5621ba388408f31ceab4bbcbfa6ba2923577d8eb69aa79ea54f3be0134", + "linuxcnc-sim-core-B2786u4k.wasm": "3163f5ff63c5f3e1d2c07d1d948fce328bf3ad919eee188e432f7ba57468fc71" }, "authority_dom": { "data-axis-authority": "linuxcnc-wasm-worker", diff --git a/doc-rtcp/xyzac-panel-button-parity-test-report.md b/doc-rtcp/xyzac-panel-button-parity-test-report.md index 05acbd4..db6317a 100644 --- a/doc-rtcp/xyzac-panel-button-parity-test-report.md +++ b/doc-rtcp/xyzac-panel-button-parity-test-report.md @@ -129,13 +129,20 @@ source_length: 200509 line_count: 4711 preview_segments: 4684 fixed_tick_samples: 3000 -execution_line: 147 -execution_trace_entries: 145 +execution_line: 337 +execution_trace_entries: 335 motion_authority: wasm motion_delta_snapshots: 0 ledger_audit_window: 32 +running_queue_gaps: 0 (excluding the initial startup tick) ``` +## 长距离连续性判定 + +`3D_Chips.ngc` 第 17 行设置 `G64 P.1`,后续是大量连续短段。对标 LinuxCNC source TP 时,正常表现是 TP 在当前段运行期间持续保留前瞻队列;G64 不应在普通同模式段之间出现人为的零速度空队列 tick。此前 Worker 在等待当前段完全结束后才入队下一段,造成截图中可见的短暂停顿,这不是源 LinuxCNC 的合理结果。 + +已修复为:同一运动学模式的下一段可在当前 TC 活动时进入 source TP;M428/M429/M430 模式变化仍由 WASM Task/TP 同步边界约束;队列容量由 `sim_linuxcnc_tp_queue_capacity` 读取,按真实 `TP_DEFAULT_QUEUE_SIZE` 限流。1000 tick 连续性回归中,除启动第 1 tick 外 `program_status=running && queue_depth=0` 的次数为 `0`;第 82 行附近仍保持 31 段前瞻队列。 + ## 当前未闭合项 以下项目仍明确记录为 `blocked_by_abi`,没有伪造通过: @@ -163,6 +170,26 @@ bash -n run-5axis-rtcp.sh 本轮结果:WASM 构建通过,原生 CTest 22/22 通过,XYZAC 聚合按钮测试通过,3D_Chips 固定 tick 长程序测试通过。Jog Speed、Max Velocity、Spindle Override 已改为 WASM TP/IO 状态和命令;前端运行态不再使用 React 默认值。发布站点 UI 运行/暂停/恢复/停止也已在 Chromium 仿真环境执行;Safari 和真实物理断电不属于本项目范围。 +本轮连续性修复后,`3D_Chips.ngc` 3000 tick 执行到第 337 行,`running_queue_gaps=0`;这证明长距离运行中的中间停顿已不再由 Worker 队列饥饿制造。 + +发布站点 r10 连续性验证: + +```text +url: https://49.232.250.35:58010/ +release: 20260902-linuxcnc-wasm-continuous-r10 +resource_sha256: index-Byst0JhC.js 26d3f21f496c8223218761ba641dab8b4f36fd18892f260c7bf5b5cfa83cafec + sim-worker-entry-BTVfbu6g.js adf2ac5621ba388408f31ceab4bbcbfa6ba2923577d8eb69aa79ea54f3be0134 + linuxcnc-sim-core-B2786u4k.wasm 3163f5ff63c5f3e1d2c07d1d948fce328bf3ad919eee188e432f7ba57468fc71 +3D_Chips.ngc: loaded -> POWER -> HOME ALL -> RUNNING +sampled_running_frames: 33 +queue_gaps: 0 +first_running: current_line=62, queue_depth=3, velocity=20, active_id=16 +last_running: current_line=69, queue_depth=2, velocity=16.6666666667, active_id=17 +browser_errors: 0 +screenshot: /tmp/published-r10-continuous.png +screenshot_sha256: c93fd23e648e49bfa9359af245372f03f3fccee123497909f3dcc005f5a59749 +``` + 发布站点 r5 浏览器冒烟: ```text @@ -178,7 +205,7 @@ and view controls: clicked with no browser errors output_sha256: bdf705473e6cda94d721aa23329257adf4a68b705add7650da5cc47012ab70b0 ``` -发布站点 r6(本轮 WASM authority 版本)浏览器验收: +发布站点 r6(历史 WASM authority 版本)浏览器验收: ```text url: https://49.232.250.35:58010/ @@ -194,6 +221,8 @@ screenshots: /tmp/published-r6-authority.png (e58205228a04b386c7b7514bf03c71df7b /tmp/published-r6-running.png (7fc474d0cb31a0fdd4afb198061e9812c753684e3d2963cc004ec4483c5c4990) ``` +当前发布资源为 r10;r6 资源 hash 仅作为历史记录保留。 + 发布站点 r7(IDENTITY/TCP: XYZAC/USERK 切换版本)浏览器验收: ```text @@ -214,10 +243,12 @@ panel_button_test_output 9bddcd8b0219925e00598e081dc7a4ed0f4868e8822a21f0ccd08d8 button_constraints_output 5b6f4ce1dec03764dcb234793ff96fc2f04d15ab954620a44dbb1210ec64a5a5 feed_authority_output deab4a51ee0e56d4f8134efba4b7a97a2b88f37d9165cf730207f71886df8526 3d_chips_test_output c97caef2ea5cf3841e1238ec443d0eebadad8cb0048af829111c06e99c9fcdd7 +3d_chips_no_gap_output c97b5fbb43a6e81a8ee15272bf71aa75ec0ba79be28a34f30b4221d50251c77d wasm_io_source 1cb066d185dd2c5bbf435e022c2518483bd44962e5a0303248757b2da51740f7 wasm_io_c_source 09bce1430d6f71702ca0b3bf29ac50db377a6f232ce0d1a9b2c1eaac7ea2162e panel_button_test_source 80782fc1f85f88beb48ec3dfaf638a93f2edb912e694840199dbff504477fe74 switchkins_direct_test_output 24e6cb8ec1195a97f71294b49217db0cbc0d7c3ecfa4bc8aa244ba3921c816a7 +panel_r10_output 9bddcd8b0219925e00598e081dc7a4ed0f4868e8822a21f0ccd08d8e9d355d45 ``` 报告对应提交前工作树保留了既有 coverage 大文件和 LinuxCNC 子模块改动;本轮提交包含 WASM TP/IO/HOME authority、无 JS JOG 运动计算、前端 pending 投影、长程序快照性能修正、聚合测试和本报告。 diff --git a/wasm-core/CMakeLists.txt b/wasm-core/CMakeLists.txt index 000241f..53d555d 100644 --- a/wasm-core/CMakeLists.txt +++ b/wasm-core/CMakeLists.txt @@ -308,6 +308,6 @@ if(EMSCRIPTEN) string(REPLACE "_sim_device_init" "_sim_device_io_size','_sim_device_init" _sim_module_link_flags "${_sim_module_link_flags}") string(REPLACE "_sim_motion_step','_sim_motion_read_state" "_sim_motion_step','_sim_motion_set_profile','_sim_motion_set_lookahead','_sim_motion_set_feed_override','_sim_motion_peek','_sim_motion_read_state" _sim_module_link_flags "${_sim_module_link_flags}") string(REPLACE "_sim_motion_state_hash','_sim_motion_canonical" "_sim_motion_state_hash','_sim_motion_plan_hash','_sim_motion_canonical" _sim_module_link_flags "${_sim_module_link_flags}") - string(REPLACE "_sim_motion_init" "_sim_motion_init','_sim_linuxcnc_tp_size','_sim_linuxcnc_tp_init','_sim_linuxcnc_tp_reset','_sim_linuxcnc_tp_set_profile','_sim_linuxcnc_tp_set_feed_override','_sim_linuxcnc_tp_set_velocity_scale','_sim_linuxcnc_tp_set_jog_scale','_sim_linuxcnc_tp_set_axis_limit','_sim_linuxcnc_tp_jog','_sim_linuxcnc_tp_velocity_scale','_sim_linuxcnc_tp_velocity_limit','_sim_linuxcnc_tp_jog_scale','_sim_linuxcnc_tp_jog_velocity','_sim_linuxcnc_tp_feed_override','_sim_linuxcnc_tp_set_dynamics','_sim_linuxcnc_tp_set_paused','_sim_linuxcnc_tp_abort','_sim_linuxcnc_tp_set_position','_sim_linuxcnc_tp_set_goal_position','_sim_linuxcnc_tp_add_line','_sim_linuxcnc_tp_add_circle','_sim_linuxcnc_tp_step','_sim_linuxcnc_tp_idle','_sim_linuxcnc_tp_read_state','_sim_linuxcnc_tp_queue_depth','_sim_linuxcnc_tp_queue_segment','_sim_linuxcnc_tp_restore_progress','_sim_linuxcnc_tp_state_hash','_sim_linuxcnc_tp_canonical" _sim_module_link_flags "${_sim_module_link_flags}") + string(REPLACE "_sim_motion_init" "_sim_motion_init','_sim_linuxcnc_tp_size','_sim_linuxcnc_tp_queue_capacity','_sim_linuxcnc_tp_init','_sim_linuxcnc_tp_reset','_sim_linuxcnc_tp_set_profile','_sim_linuxcnc_tp_set_feed_override','_sim_linuxcnc_tp_set_velocity_scale','_sim_linuxcnc_tp_set_jog_scale','_sim_linuxcnc_tp_set_axis_limit','_sim_linuxcnc_tp_jog','_sim_linuxcnc_tp_velocity_scale','_sim_linuxcnc_tp_velocity_limit','_sim_linuxcnc_tp_jog_scale','_sim_linuxcnc_tp_jog_velocity','_sim_linuxcnc_tp_feed_override','_sim_linuxcnc_tp_set_dynamics','_sim_linuxcnc_tp_set_paused','_sim_linuxcnc_tp_abort','_sim_linuxcnc_tp_set_position','_sim_linuxcnc_tp_set_goal_position','_sim_linuxcnc_tp_add_line','_sim_linuxcnc_tp_add_circle','_sim_linuxcnc_tp_step','_sim_linuxcnc_tp_idle','_sim_linuxcnc_tp_read_state','_sim_linuxcnc_tp_queue_depth','_sim_linuxcnc_tp_queue_segment','_sim_linuxcnc_tp_restore_progress','_sim_linuxcnc_tp_state_hash','_sim_linuxcnc_tp_canonical" _sim_module_link_flags "${_sim_module_link_flags}") set_target_properties(sim_core_module PROPERTIES LINK_FLAGS "${_sim_module_link_flags}") endif() diff --git a/wasm-core/include/sim_linuxcnc_tp.h b/wasm-core/include/sim_linuxcnc_tp.h index dffc782..1f9e044 100644 --- a/wasm-core/include/sim_linuxcnc_tp.h +++ b/wasm-core/include/sim_linuxcnc_tp.h @@ -18,6 +18,7 @@ typedef struct sim_linuxcnc_tp_segment { } sim_linuxcnc_tp_segment; uint32_t sim_linuxcnc_tp_size(void); +uint32_t sim_linuxcnc_tp_queue_capacity(const sim_linuxcnc_tp *planner); int32_t sim_linuxcnc_tp_init(sim_linuxcnc_tp *planner, double cycle_time, double velocity_limit, double acceleration_limit); int32_t sim_linuxcnc_tp_reset(sim_linuxcnc_tp *planner); diff --git a/wasm-core/src/sim_linuxcnc_tp.c b/wasm-core/src/sim_linuxcnc_tp.c index 8e7b75f..0dacba9 100644 --- a/wasm-core/src/sim_linuxcnc_tp.c +++ b/wasm-core/src/sim_linuxcnc_tp.c @@ -130,6 +130,7 @@ static uint64_t hash_bytes(const unsigned char *bytes, size_t length) { } uint32_t sim_linuxcnc_tp_size(void) { return (uint32_t)sizeof(sim_linuxcnc_tp); } +uint32_t sim_linuxcnc_tp_queue_capacity(const sim_linuxcnc_tp *planner) { return planner == NULL || !planner->initialized ? 0u : (uint32_t)TP_DEFAULT_QUEUE_SIZE; } int32_t sim_linuxcnc_tp_init(sim_linuxcnc_tp *planner, double cycle_time, double velocity_limit, double acceleration_limit) { if (planner == NULL || !isfinite(cycle_time) || cycle_time <= 0.0 || cycle_time > 60.0 || !isfinite(velocity_limit) || velocity_limit <= 0.0 || !isfinite(acceleration_limit) || acceleration_limit <= 0.0) return -1200; diff --git a/wasm-core/tests/sim_linuxcnc_tp_test.c b/wasm-core/tests/sim_linuxcnc_tp_test.c index 46b9c13..332fcbc 100644 --- a/wasm-core/tests/sim_linuxcnc_tp_test.c +++ b/wasm-core/tests/sim_linuxcnc_tp_test.c @@ -18,6 +18,7 @@ int main(void) { sim_posemath_pose second = pose(20, 20, 10); assert(planner != NULL); assert(sim_linuxcnc_tp_init(planner, 0.001, 35.0, 300.0) == 0); + assert(sim_linuxcnc_tp_queue_capacity(planner) > 0); assert(sim_linuxcnc_tp_set_position(planner, &origin) == 0); assert(sim_linuxcnc_tp_set_profile(planner, 0, 0.0) == 0); assert(sim_linuxcnc_tp_add_line(planner, &first, 20.0, 300.0, 16, 1) == 0); diff --git a/web/react/src/App.tsx b/web/react/src/App.tsx index 3b7f5d2..5bbe496 100644 --- a/web/react/src/App.tsx +++ b/web/react/src/App.tsx @@ -465,7 +465,7 @@ export function App() { const allHomed = homedAxes.length >= 5 && homedAxes.slice(0, 5).every(Boolean); const xyzacCommand = (kind: string, payload: Record = {}, action?: string) => { void dispatch(kind, payload, true, action ?? null).then(() => { if (kind === "VISUAL_CLEAR") setPlotCleared(true); }).catch(() => undefined); }; const position = xyzacView.pose ? `X${Number(xyzacView.pose.x).toFixed(3)} Y${Number(xyzacView.pose.y).toFixed(3)} Z${Number(xyzacView.pose.z).toFixed(3)} A${Number(xyzacView.pose.a).toFixed(3)} C${Number(xyzacView.pose.c).toFixed(3)}` : "WASM state pending"; - return
+ return
AXIS AXISLinuxCNC Web/WASM
{state.status.toUpperCase()}{taskState}
{ setProgramText(DEFAULT_PROGRAM); setProgramPath(PROGRAM_PATH); setPlotCleared(false); }} /> execute("PROGRAM_STEP")} /> execute(programPaused ? "PROGRAM_RESUME" : "PROGRAM_PAUSE")} /> setZoom((value) => Math.min(2, value + .2))} /> setZoom((value) => Math.max(.5, value - .2))} /> { setView("z"); setRightTab("preview"); }} /> { setView("z2"); setRightTab("preview"); }} /> { setView("x"); setRightTab("preview"); }} /> { setView("y"); setRightTab("preview"); }} /> { setView("y2"); setRightTab("preview"); }} /> { setView("p"); setRightTab("preview"); }} /> setRotateMode((value) => !value)} /> xyzacCommand("VISUAL_CLEAR", {}, "vismachClear")} />
diff --git a/web/worker/sim-session.mjs b/web/worker/sim-session.mjs index 4d7a83a..5fdeb79 100644 --- a/web/worker/sim-session.mjs +++ b/web/worker/sim-session.mjs @@ -1552,7 +1552,12 @@ export class SimSession { // planner queue. Let the motion phase consume one segment // before reading another source line instead of converting // normal planner backpressure into a program fault. - if (this.wasmMotion.read().state.queue_depth >= this.wasmMotion.queueCapacity) return; + // TP_DEFAULT_QUEUE_SIZE includes the active TC slot. Leave + // one slot available for the active segment before appending + // another lookahead TC; the upstream queue otherwise rejects + // the boundary insertion even though its reported depth is + // one below the configured capacity. + if (this.wasmMotion.read().state.queue_depth >= this.wasmMotion.queueCapacity - 1) return; if (this.pendingXyzacMotion) { const pendingMode = Number(this.pendingXyzacMotion.kinematics_mode ?? 0); if (this.xyzacAppendDeferredOnActive) return; @@ -1562,7 +1567,14 @@ export class SimSession { : Number(queueState.active_id ?? 0) === this.xyzacDeferredBlockedActiveId; const deferredSwitchMotion = this.xyzacDeferredPhysicalSwitchMode !== null && pendingMode === this.xyzacDeferredPhysicalSwitchMode && this.xyzacQueuedLookaheadTargetId === 0 && deferredControlReady; const queuedLookaheadReady = deferredSwitchMotion || (this.xyzacAllowQueuedLookahead && this.xyzacLastServoActiveId === this.xyzacQueuedLookaheadTargetId); - if (queueState.queue_depth !== 0 && !queuedLookaheadReady) return; + // Same-mode segments may be queued while the current TC is + // active. LinuxCNC TP needs that lookahead to blend G64 + // paths; withholding it until the queue drains creates a + // real zero-velocity servo sample between long runs. A + // kinematics-mode change remains synchronized below and is + // deliberately deferred until its existing TC boundary. + const pendingModeChanged = pendingMode !== this.xyzacLastEnqueuedKinematicsMode; + if (queueState.queue_depth !== 0 && pendingModeChanged && !queuedLookaheadReady) return; if (queuedLookaheadReady && !deferredSwitchMotion && this.xyzacAllowQueuedLookahead) { // The next segment is appended after the first servo // sample of the now-active target, matching LinuxCNC's diff --git a/web/worker/test_xyzac_3d_chips.mjs b/web/worker/test_xyzac_3d_chips.mjs index 94bbfb9..82d5a85 100644 --- a/web/worker/test_xyzac_3d_chips.mjs +++ b/web/worker/test_xyzac_3d_chips.mjs @@ -46,6 +46,7 @@ const run = send("PROGRAM_RUN"); assert.equal(run.kind, "COMMAND_RESULT"); let stepped = null; let executionTraceEntries = 0; +let runningQueueGaps = 0; // The first long Z feed is planned at the configured LinuxCNC TP limit. Give // the fixed-tick simulation enough servo time to complete it before checking // that the interpreter has advanced beyond the historical line-82 boundary. @@ -55,6 +56,7 @@ for (let cycle = 0; cycle < cyclesToRun; cycle += 1) { stepped = send("SIM_STEP", { cycles: 1, response: "motion_delta" }); assert.equal(stepped.kind, "COMMAND_RESULT"); executionTraceEntries += stepped.payload.execution_trace.length; + if (cycle > 0 && stepped.payload.program.program_status === "running" && Number(stepped.payload.wasm_motion.state.queue_depth) === 0) runningQueueGaps += 1; } assert.equal(stepped.kind, "COMMAND_RESULT"); assert.equal(stepped.payload.program.program_status, "running"); @@ -65,6 +67,7 @@ assert.equal(stepped.payload.motion_authority, "wasm"); assert.equal(Object.hasOwn(stepped.payload.xyzac_ledger.entries.at(-1), "response"), false); assert.equal(session.timeline.snapshots.snapshots.size, 0); assert.equal(session.ledger.audit({ maxEntries: 32 }).entries.length, 32); +assert.equal(runningQueueGaps, 0); console.log(JSON.stringify({ schema: "xyzac-3d-chips-program.v1", @@ -77,6 +80,7 @@ console.log(JSON.stringify({ cycles: cyclesToRun, execution_line: stepped.payload.program.current_line, execution_trace: executionTraceEntries, + running_queue_gaps: runningQueueGaps, motion_authority: stepped.payload.motion_authority, motion_delta_snapshots: session.timeline.snapshots.snapshots.size, ledger_audit_window: session.ledger.audit({ maxEntries: 32 }).entries.length, diff --git a/web/worker/wasm-linuxcnc-tp.mjs b/web/worker/wasm-linuxcnc-tp.mjs index 4d51329..a9a15e7 100644 --- a/web/worker/wasm-linuxcnc-tp.mjs +++ b/web/worker/wasm-linuxcnc-tp.mjs @@ -17,11 +17,11 @@ function toPose(values) { return Object.fromEntries(["x", "y", "z", "a", "b", "c export class WasmLinuxcncTp { constructor(core, { cycleTime = 0.001, velocityLimit = 35, accelerationLimit = 300, limits = {} } = {}) { this.core = core; - this.available = ["sim_linuxcnc_tp_size", "sim_linuxcnc_tp_init", "sim_linuxcnc_tp_read_state", "sim_linuxcnc_tp_step", "sim_linuxcnc_tp_idle", "sim_linuxcnc_tp_add_line", "sim_linuxcnc_tp_set_profile", "sim_linuxcnc_tp_set_feed_override", "sim_linuxcnc_tp_set_velocity_scale", "sim_linuxcnc_tp_set_jog_scale", "sim_linuxcnc_tp_set_axis_limit", "sim_linuxcnc_tp_jog", "sim_linuxcnc_tp_velocity_scale", "sim_linuxcnc_tp_velocity_limit", "sim_linuxcnc_tp_jog_scale", "sim_linuxcnc_tp_jog_velocity", "sim_linuxcnc_tp_feed_override", "sim_linuxcnc_tp_set_dynamics", "sim_linuxcnc_tp_set_paused", "sim_linuxcnc_tp_abort", "sim_linuxcnc_tp_set_goal_position", "sim_linuxcnc_tp_queue_depth", "sim_linuxcnc_tp_queue_segment", "sim_linuxcnc_tp_restore_progress"].every((name) => typeof core?.[`_${name}`] === "function" || typeof core?.[name] === "function"); + this.available = ["sim_linuxcnc_tp_size", "sim_linuxcnc_tp_queue_capacity", "sim_linuxcnc_tp_init", "sim_linuxcnc_tp_read_state", "sim_linuxcnc_tp_step", "sim_linuxcnc_tp_idle", "sim_linuxcnc_tp_add_line", "sim_linuxcnc_tp_set_profile", "sim_linuxcnc_tp_set_feed_override", "sim_linuxcnc_tp_set_velocity_scale", "sim_linuxcnc_tp_set_jog_scale", "sim_linuxcnc_tp_set_axis_limit", "sim_linuxcnc_tp_jog", "sim_linuxcnc_tp_velocity_scale", "sim_linuxcnc_tp_velocity_limit", "sim_linuxcnc_tp_jog_scale", "sim_linuxcnc_tp_jog_velocity", "sim_linuxcnc_tp_feed_override", "sim_linuxcnc_tp_set_dynamics", "sim_linuxcnc_tp_set_paused", "sim_linuxcnc_tp_abort", "sim_linuxcnc_tp_set_goal_position", "sim_linuxcnc_tp_queue_depth", "sim_linuxcnc_tp_queue_segment", "sim_linuxcnc_tp_restore_progress"].every((name) => typeof core?.[`_${name}`] === "function" || typeof core?.[name] === "function"); this.cycleTime = cycleTime; this.velocityLimit = velocityLimit; this.accelerationLimit = accelerationLimit; - this.queueCapacity = 2000; + this.queueCapacity = 0; this.planner = 0; this.posePointer = 0; this.centerPointer = 0; @@ -47,6 +47,8 @@ export class WasmLinuxcncTp { if (![this.planner, this.posePointer, this.centerPointer, this.normalPointer, this.statePointer].every(Boolean)) throw new Error("linuxcnc_tp_allocation_failed"); const result = call(core, "sim_linuxcnc_tp_init", "number", ["number", "number", "number", "number"], [this.planner, cycleTime, velocityLimit, accelerationLimit]); if (result !== 0) throw new Error(`linuxcnc_tp_init_${result}`); + this.queueCapacity = Number(call(core, "sim_linuxcnc_tp_queue_capacity", "number", ["number"], [this.planner])); + if (!Number.isSafeInteger(this.queueCapacity) || this.queueCapacity < 1) throw new Error("linuxcnc_tp_queue_capacity_invalid"); this.setPosition({ x: 0, y: 0, z: 0, a: 0, b: 0, c: 0, u: 0, v: 0, w: 0 }); this.setProfile(0); for (const [axis, limit] of Object.entries(limits)) {