Complete XYZAC LinuxCNC WASM parity and smooth 3D preview

This commit is contained in:
2026-08-28 06:24:50 +08:00
parent e8fe323aab
commit 1a7995fa9b
181 changed files with 36854 additions and 215 deletions

View File

@@ -5,17 +5,18 @@ import { isOptionalSourceKey } from "./linuxcnc-source-semantics.mjs";
export const SIMULATION_CASE_SCHEMA = "simulation-case-bundle.v1";
const RESOURCE_KEYS = new Set([
"HAL", "HALFILE", "TOOLTABLE", "TOOL_TABLE", "VARFILE", "PARAMETER_FILE", "OPEN_FILE",
"HAL", "HALFILE", "POSTGUI_HALFILE", "TOOLTABLE", "TOOL_TABLE", "VARFILE", "PARAMETER_FILE", "OPEN_FILE",
"PROGRAM", "PROGRAMS", "PYTHON", "PYTHONFILE", "VCP", "VCPFILE", "CLPFILE",
"CLASSICLADDER", "INTRO_GRAPHIC",
"PYVCP", "NGCGUI_SUBFILE", "INTRO_GRAPHIC", "SUBROUTINE_PATH", "REMAP",
]);
const MANIFEST = new Set(SIM_FILE_INDEX);
const PRELOADED_HAL_COMPONENTS = Object.freeze(["corexykins", "lineardeltakins", "motmod", "pid", "rotarydeltakins", "stepgen", "trivkins", "tpmod", "homemod"]);
const PRELOADED_HAL_COMPONENTS = Object.freeze(["corexykins", "lineardeltakins", "motmod", "pid", "rotarydeltakins", "stepgen", "trivkins", "xyzac-trt-kins", "xyzbc-trt-kins", "tpmod", "homemod"]);
const CASE_KINEMATICS = Object.freeze({
"linuxcnc/configs/sim/axis/corexy/corexy_by_kins.ini": Object.freeze({ type: "corexy", path_mode: "kins" }),
"linuxcnc/configs/sim/axis/corexy/corexy_by_hal.ini": Object.freeze({ type: "corexy", path_mode: "hal" }),
"linuxcnc/configs/sim/axis/ldelta.ini": Object.freeze({ type: "lineardelta", path_mode: "kins" }),
"linuxcnc/configs/sim/axis/rdelta.ini": Object.freeze({ type: "rotarydelta", path_mode: "kins" }),
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt.ini": Object.freeze({ type: "xyzac-trt", path_mode: "wasm", coordinates: "XYZAC", joint_count: 5, max_linear_velocity: 35, switchkins: { 0: "identity", 1: "xyzac", 2: "userk" }, offsets: { x_rot_point: 0, y_offset: 20, z_offset: 10, tool_offset: 0 } }),
});
const RUNTIME_FIXTURES = Object.freeze({
"linuxcnc/configs/sim/axis/minimal_xyz.ini": Object.freeze({
@@ -42,6 +43,12 @@ const RUNTIME_FIXTURES = Object.freeze({
with: "HALFILE = xz_both_auto_cmds.hal",
reason: "LinuxCNC basic_sim.tcl generated XZ BOTH AUTO HAL command fixture",
}),
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt.ini": Object.freeze({
generated_hal: "linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt-headless_cmds.hal",
replace: "HALFILE = LIB:basic_sim.tcl",
with: "HALFILE = xyzac-trt-headless_cmds.hal",
reason: "LinuxCNC basic_sim.tcl generated XYZAC HAL command fixture",
}),
});
function clone(value) { return structuredClone(value); }
@@ -82,6 +89,10 @@ function candidates(source, raw, key = null, section = null) {
const libraryPath = normalize(`linuxcnc/lib/hallib/${name}`);
return libraryPath ? [libraryPath] : [];
}
if (["NGCGUI_SUBFILE", "REMAP"].includes(String(key).toUpperCase())) {
const subroutine = normalize(`${dirname(source)}/remap_subs/${first}`);
if (subroutine) return [subroutine];
}
if (["HAL", "HALFILE"].includes(String(key).toUpperCase()) && !first.includes("/") && !first.startsWith("linuxcnc/")) {
const halCandidates = [normalize(`${dirname(source)}/${first}`), `linuxcnc/lib/hallib/${first}`].filter(Boolean);
const indexed = halCandidates.filter(inManifest);
@@ -128,6 +139,16 @@ function resourceReferences(source, content) {
const line = rawLine.split("#", 1)[0].trim();
const sectionMatch = line.match(/^\[([^\]]+)\]$/);
if (sectionMatch) { section = sectionMatch[1].trim(); continue; }
if (section === "RS274NGC" && /^SUBROUTINE_PATH\s*=\s*/i.test(line)) {
const directory = normalize(`${dirname(source)}/${line.split("=", 2)[1].trim()}`);
for (const candidate of SIM_FILE_INDEX.filter((path) => directory && path.startsWith(`${directory}/`) && path.endsWith(".ngc"))) references.push({ path: candidate, key: "SUBROUTINE_PATH", section, source });
continue;
}
if (section === "RS274NGC" && /^REMAP\s*=\s*/i.test(line)) {
const name = /ngc=([^\s]+)/i.exec(line)?.[1];
if (name) { const candidate = normalize(`${dirname(source)}/remap_subs/${name}.ngc`); if (candidate) references.push({ path: candidate, key: "REMAP", section, source }); }
continue;
}
const assignment = line.match(/^([^=:#]+?)\s*(?:=|:)\s*(.*)$/);
if (assignment && RESOURCE_KEYS.has(assignment[1].trim().toUpperCase())) {
const key = assignment[1].trim().toUpperCase();
@@ -236,6 +257,7 @@ export function toWorkerConfiguration(bundle) {
optional_missing: clone(bundle.optional_missing ?? []),
runtime_fixtures: clone(bundle.runtime_fixtures ?? []),
...(bundle.entrypoint === "linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.ini" ? { home_limits: { z: [-240, 100] } } : {}),
...(bundle.entrypoint === "linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt.ini" ? { home_limits: { joint_count: 5, kinematics_type: 2, coordinates: "XYZAC", x: [-200, 200], y: [-100, 100], z: [-120, 120], a: [-100, 50], c: [-36000, 36000] } } : {}),
...(CASE_KINEMATICS[bundle.entrypoint] ? { kinematics: clone(CASE_KINEMATICS[bundle.entrypoint]) } : {}),
};
}