Add INI-driven XYZAC and XYZBC parametric machine design

This commit is contained in:
2026-09-17 19:16:48 +08:00
parent 9232f29027
commit e4600b34e3
31 changed files with 2359 additions and 29 deletions

View File

@@ -3,6 +3,7 @@ import { runtimeResourceFixture } from "./resource-resolver.mjs";
import { SIM_CASE_CATALOG, SIM_FILE_INDEX, SIM_HAL_COMPONENTS } from "./sim-case-catalog.mjs";
import { isOptionalSourceKey } from "./linuxcnc-source-semantics.mjs";
import { MACHINE_DEFINITIONS, machineDefinition } from "./machine-definitions.mjs";
import { readTrtGeometry } from "./trt-geometry.mjs";
export const SIMULATION_CASE_SCHEMA = "simulation-case-bundle.v1";
const RESOURCE_KEYS = new Set([
@@ -17,8 +18,8 @@ const CASE_KINEMATICS = Object.freeze({
"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, axis_linear_velocity_limit: 20, max_acceleration: 300, max_jerk: 1000000000, servo_cycle_time: 0.001, task_cycle_time: 0.01, cycle_time: 0.001, switchkins: { 0: "identity", 1: "xyzac", 2: "userk" }, offsets: { x_rot_point: 0, y_offset: 20, z_offset: 10, tool_offset: 0 } }),
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzbc-trt.ini": Object.freeze({ type: "xyzbc-trt", path_mode: "wasm", coordinates: "XYZBC", joint_count: 5, max_linear_velocity: 35, axis_linear_velocity_limit: 20, axis_angular_velocity_limit: 30, max_acceleration: 300, max_jerk: 1000000000, servo_cycle_time: 0.001, task_cycle_time: 0.01, cycle_time: 0.001, switchkins: { 0: "identity", 1: "xyzbc", 2: "userk" }, offsets: { x_rot_point: 0, y_rot_point: 0, z_rot_point: 0, x_offset: -20, y_offset: 0, z_offset: -15, tool_offset: 0 } }),
"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, axis_linear_velocity_limit: 20, max_acceleration: 300, max_jerk: 1000000000, servo_cycle_time: 0.001, task_cycle_time: 0.01, cycle_time: 0.001, switchkins: { 0: "identity", 1: "xyzac", 2: "userk" } }),
"linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzbc-trt.ini": Object.freeze({ type: "xyzbc-trt", path_mode: "wasm", coordinates: "XYZBC", joint_count: 5, max_linear_velocity: 35, axis_linear_velocity_limit: 20, axis_angular_velocity_limit: 30, max_acceleration: 300, max_jerk: 1000000000, servo_cycle_time: 0.001, task_cycle_time: 0.01, cycle_time: 0.001, switchkins: { 0: "identity", 1: "xyzbc", 2: "userk" } }),
});
const RUNTIME_FIXTURES = Object.freeze({
"linuxcnc/configs/sim/axis/minimal_xyz.ini": Object.freeze({
@@ -130,7 +131,7 @@ function inManifest(path) {
function responseUrl(baseUrl, path) { return `${String(baseUrl ?? "").replace(/\/$/, "")}/${path}`.replace(/^\//, "/"); }
async function fetchText(fetchImpl, baseUrl, path) {
const response = await fetchImpl(responseUrl(baseUrl, path));
const response = await fetchImpl(responseUrl(baseUrl, path), { cache: "no-store" });
if (!response?.ok) return null;
return response.text();
}
@@ -241,6 +242,7 @@ export async function loadSimulationCase({ path, fetchImpl = globalThis.fetch, b
else { files[visualSource] = content; fetched.push(visualSource); }
}
}
const sourceIni = files[catalog.path];
const fixture = RUNTIME_FIXTURES[catalog.path];
if (fixture) {
if (!inManifest(fixture.generated_hal)) missing.push(fixture.generated_hal);
@@ -267,6 +269,7 @@ export async function loadSimulationCase({ path, fetchImpl = globalThis.fetch, b
};
return {
...clone(unsigned),
source_ini: sourceIni,
catalog,
halManifest: [...new Set([...SIM_HAL_COMPONENTS, ...PRELOADED_HAL_COMPONENTS])].sort().map((component) => ({ component })),
status: missing.length ? "blocked" : "ready",
@@ -276,6 +279,8 @@ export async function loadSimulationCase({ path, fetchImpl = globalThis.fetch, b
export function toWorkerConfiguration(bundle) {
if (!bundle || bundle.schema !== SIMULATION_CASE_SCHEMA) throw new Error("simulation_case_bundle_invalid");
const kinematics = CASE_KINEMATICS[bundle.entrypoint] ? clone(CASE_KINEMATICS[bundle.entrypoint]) : null;
if (machineDefinition(bundle.entrypoint)) kinematics.offsets = readTrtGeometry(bundle).offsets;
return {
entrypoint: bundle.entrypoint,
files: clone(bundle.files),
@@ -285,7 +290,7 @@ export function toWorkerConfiguration(bundle) {
runtime_fixtures: clone(bundle.runtime_fixtures ?? []),
...(bundle.entrypoint === "linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.ini" ? { home_limits: { z: [-240, 100] } } : {}),
...(machineDefinition(bundle.entrypoint) ? { home_limits: { joint_count: 5, kinematics_type: machineDefinition(bundle.entrypoint).kinematics_type, coordinates: machineDefinition(bundle.entrypoint).coordinates, ...machineDefinition(bundle.entrypoint).joint_limits } } : {}),
...(CASE_KINEMATICS[bundle.entrypoint] ? { kinematics: clone(CASE_KINEMATICS[bundle.entrypoint]) } : {}),
...(kinematics ? { kinematics } : {}),
};
}