拆分仿真测试程序目录
结论:将内置 G-code 测试程序从 simulation-app.js 移入 runtime/ui/simulation/programs/,建立一程序一模块的目录化程序库,并保持页面 API 与验证 gate 兼容。
This commit is contained in:
@@ -26,6 +26,9 @@ toolhead over the executed toolpath.
|
||||
The current UI direction is the AXIS-style simulation shell in
|
||||
`docs/axis-style-simulation-implementation.md`; Phase 1 is implemented in
|
||||
`runtime/ui/simulation/index.html`.
|
||||
Built-in simulation test programs live under
|
||||
`runtime/ui/simulation/programs/` and are exported by
|
||||
`runtime/ui/simulation/programs/index.js`.
|
||||
|
||||
The project release gate for the current scope is:
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ Browser JavaScript must not implement:
|
||||
The current simulation page already has:
|
||||
|
||||
- LinuxCNC interpreter WASM execution through `createLinuxCncInterpSdk()`;
|
||||
- selectable test programs;
|
||||
- selectable test programs under `runtime/ui/simulation/programs/`;
|
||||
- canonical output rendering;
|
||||
- program-line rendering;
|
||||
- motion table;
|
||||
@@ -134,6 +134,17 @@ Upgrade the G-code pane and execution controls:
|
||||
- highlight active G-code line and current motion row;
|
||||
- show run status, source program, motion count, and current frame.
|
||||
|
||||
Built-in test programs must live in:
|
||||
|
||||
```text
|
||||
runtime/ui/simulation/programs/
|
||||
```
|
||||
|
||||
Each program should have its own module and be exported through
|
||||
`runtime/ui/simulation/programs/index.js`. The simulation renderer should keep
|
||||
importing the inventory through the program index rather than embedding G-code
|
||||
fixtures in `simulation-app.js`.
|
||||
|
||||
Validation:
|
||||
|
||||
- browser smoke runs at least one linear program, one arc program, and one
|
||||
|
||||
14
wasm-port/runtime/ui/simulation/programs/arc-g2-g3.js
Normal file
14
wasm-port/runtime/ui/simulation/programs/arc-g2-g3.js
Normal file
@@ -0,0 +1,14 @@
|
||||
export const arcG2G3Program = {
|
||||
id: "arc-g2-g3",
|
||||
label: "G2/G3 arc path",
|
||||
category: "Arc",
|
||||
text: [
|
||||
"G90 G17 G0 X0 Y0 Z0",
|
||||
"G91.1",
|
||||
"G2 X1 Y1 I1 J0 F80",
|
||||
"G3 X0 Y0 I0 J-1",
|
||||
"M2",
|
||||
"",
|
||||
].join("\n"),
|
||||
expectedMotionTypes: ["STRAIGHT_TRAVERSE", "ARC_FEED"],
|
||||
};
|
||||
16
wasm-port/runtime/ui/simulation/programs/drill-g81.js
Normal file
16
wasm-port/runtime/ui/simulation/programs/drill-g81.js
Normal file
@@ -0,0 +1,16 @@
|
||||
export const drillG81Program = {
|
||||
id: "drill-g81",
|
||||
label: "G81 drill pattern",
|
||||
category: "Cycle",
|
||||
text: [
|
||||
"G90 G17 G0 X0 Y0 Z1",
|
||||
"G81 X0.5 Y0.5 Z-0.25 R0.1 F20",
|
||||
"X1.0 Y0.5",
|
||||
"X1.0 Y1.0",
|
||||
"G80",
|
||||
"G0 X0 Y0 Z1",
|
||||
"M2",
|
||||
"",
|
||||
].join("\n"),
|
||||
expectedMotionTypes: ["STRAIGHT_TRAVERSE", "STRAIGHT_FEED"],
|
||||
};
|
||||
15
wasm-port/runtime/ui/simulation/programs/incremental-loop.js
Normal file
15
wasm-port/runtime/ui/simulation/programs/incremental-loop.js
Normal file
@@ -0,0 +1,15 @@
|
||||
export const incrementalLoopProgram = {
|
||||
id: "incremental-loop",
|
||||
label: "Incremental loop",
|
||||
category: "Modal",
|
||||
text: [
|
||||
"G90 G17 G0 X0 Y0 Z0",
|
||||
"G91 G1 X0.5 Y0 F60",
|
||||
"G1 X0 Y0.5",
|
||||
"G1 X-0.5 Y0",
|
||||
"G90 G0 X0 Y0 Z0",
|
||||
"M2",
|
||||
"",
|
||||
].join("\n"),
|
||||
expectedMotionTypes: ["STRAIGHT_TRAVERSE", "STRAIGHT_FEED"],
|
||||
};
|
||||
28
wasm-port/runtime/ui/simulation/programs/index.js
Normal file
28
wasm-port/runtime/ui/simulation/programs/index.js
Normal file
@@ -0,0 +1,28 @@
|
||||
import { arcG2G3Program } from "./arc-g2-g3.js";
|
||||
import { drillG81Program } from "./drill-g81.js";
|
||||
import { incrementalLoopProgram } from "./incremental-loop.js";
|
||||
import { pocketZProgram } from "./pocket-z.js";
|
||||
import { squareLinearProgram } from "./square-linear.js";
|
||||
|
||||
export const SIMULATION_TEST_PROGRAMS = [
|
||||
squareLinearProgram,
|
||||
pocketZProgram,
|
||||
incrementalLoopProgram,
|
||||
arcG2G3Program,
|
||||
drillG81Program,
|
||||
];
|
||||
|
||||
export const DEFAULT_SIMULATION_PROGRAM_ID = SIMULATION_TEST_PROGRAMS[0].id;
|
||||
export const DEFAULT_SIMULATION_PROGRAM = SIMULATION_TEST_PROGRAMS[0].text;
|
||||
|
||||
export function getSimulationTestPrograms() {
|
||||
return SIMULATION_TEST_PROGRAMS.map((program) => ({ ...program }));
|
||||
}
|
||||
|
||||
export function getSimulationTestProgram(programId = DEFAULT_SIMULATION_PROGRAM_ID) {
|
||||
const program = SIMULATION_TEST_PROGRAMS.find(({ id }) => id === programId);
|
||||
if (!program) {
|
||||
throw new Error(`unknown simulation test program: ${programId}`);
|
||||
}
|
||||
return program;
|
||||
}
|
||||
17
wasm-port/runtime/ui/simulation/programs/pocket-z.js
Normal file
17
wasm-port/runtime/ui/simulation/programs/pocket-z.js
Normal file
@@ -0,0 +1,17 @@
|
||||
export const pocketZProgram = {
|
||||
id: "pocket-z",
|
||||
label: "Pocket with Z moves",
|
||||
category: "Linear",
|
||||
text: [
|
||||
"G90 G17 G0 X0 Y0 Z1",
|
||||
"G1 Z-0.25 F40",
|
||||
"G1 X2 Y0 F120",
|
||||
"G1 X2 Y1",
|
||||
"G1 X0 Y1",
|
||||
"G1 X0 Y0",
|
||||
"G0 Z1",
|
||||
"M2",
|
||||
"",
|
||||
].join("\n"),
|
||||
expectedMotionTypes: ["STRAIGHT_TRAVERSE", "STRAIGHT_FEED"],
|
||||
};
|
||||
15
wasm-port/runtime/ui/simulation/programs/square-linear.js
Normal file
15
wasm-port/runtime/ui/simulation/programs/square-linear.js
Normal file
@@ -0,0 +1,15 @@
|
||||
export const squareLinearProgram = {
|
||||
id: "square-linear",
|
||||
label: "Square contour",
|
||||
category: "Linear",
|
||||
text: [
|
||||
"G90 G17 G0 X0 Y0 Z0",
|
||||
"G1 X1 Y0 Z0 F100",
|
||||
"G1 X1 Y1 Z0",
|
||||
"G1 X0 Y1 Z0",
|
||||
"G1 X0 Y0 Z0",
|
||||
"M2",
|
||||
"",
|
||||
].join("\n"),
|
||||
expectedMotionTypes: ["STRAIGHT_TRAVERSE", "STRAIGHT_FEED"],
|
||||
};
|
||||
@@ -1,87 +1,19 @@
|
||||
import { createLinuxCncInterpSdk } from "../../sdk/src/index.js";
|
||||
import {
|
||||
DEFAULT_SIMULATION_PROGRAM,
|
||||
DEFAULT_SIMULATION_PROGRAM_ID,
|
||||
SIMULATION_TEST_PROGRAMS,
|
||||
getSimulationTestProgram,
|
||||
getSimulationTestPrograms,
|
||||
} from "./programs/index.js";
|
||||
|
||||
export const SIMULATION_TEST_PROGRAMS = [
|
||||
{
|
||||
id: "square-linear",
|
||||
label: "Square contour",
|
||||
category: "Linear",
|
||||
text: [
|
||||
"G90 G17 G0 X0 Y0 Z0",
|
||||
"G1 X1 Y0 Z0 F100",
|
||||
"G1 X1 Y1 Z0",
|
||||
"G1 X0 Y1 Z0",
|
||||
"G1 X0 Y0 Z0",
|
||||
"M2",
|
||||
"",
|
||||
].join("\n"),
|
||||
expectedMotionTypes: ["STRAIGHT_TRAVERSE", "STRAIGHT_FEED"],
|
||||
},
|
||||
{
|
||||
id: "pocket-z",
|
||||
label: "Pocket with Z moves",
|
||||
category: "Linear",
|
||||
text: [
|
||||
"G90 G17 G0 X0 Y0 Z1",
|
||||
"G1 Z-0.25 F40",
|
||||
"G1 X2 Y0 F120",
|
||||
"G1 X2 Y1",
|
||||
"G1 X0 Y1",
|
||||
"G1 X0 Y0",
|
||||
"G0 Z1",
|
||||
"M2",
|
||||
"",
|
||||
].join("\n"),
|
||||
expectedMotionTypes: ["STRAIGHT_TRAVERSE", "STRAIGHT_FEED"],
|
||||
},
|
||||
{
|
||||
id: "incremental-loop",
|
||||
label: "Incremental loop",
|
||||
category: "Modal",
|
||||
text: [
|
||||
"G90 G17 G0 X0 Y0 Z0",
|
||||
"G91 G1 X0.5 Y0 F60",
|
||||
"G1 X0 Y0.5",
|
||||
"G1 X-0.5 Y0",
|
||||
"G90 G0 X0 Y0 Z0",
|
||||
"M2",
|
||||
"",
|
||||
].join("\n"),
|
||||
expectedMotionTypes: ["STRAIGHT_TRAVERSE", "STRAIGHT_FEED"],
|
||||
},
|
||||
{
|
||||
id: "arc-g2-g3",
|
||||
label: "G2/G3 arc path",
|
||||
category: "Arc",
|
||||
text: [
|
||||
"G90 G17 G0 X0 Y0 Z0",
|
||||
"G91.1",
|
||||
"G2 X1 Y1 I1 J0 F80",
|
||||
"G3 X0 Y0 I0 J-1",
|
||||
"M2",
|
||||
"",
|
||||
].join("\n"),
|
||||
expectedMotionTypes: ["STRAIGHT_TRAVERSE", "ARC_FEED"],
|
||||
},
|
||||
{
|
||||
id: "drill-g81",
|
||||
label: "G81 drill pattern",
|
||||
category: "Cycle",
|
||||
text: [
|
||||
"G90 G17 G0 X0 Y0 Z1",
|
||||
"G81 X0.5 Y0.5 Z-0.25 R0.1 F20",
|
||||
"X1.0 Y0.5",
|
||||
"X1.0 Y1.0",
|
||||
"G80",
|
||||
"G0 X0 Y0 Z1",
|
||||
"M2",
|
||||
"",
|
||||
].join("\n"),
|
||||
expectedMotionTypes: ["STRAIGHT_TRAVERSE", "STRAIGHT_FEED"],
|
||||
},
|
||||
];
|
||||
|
||||
export const DEFAULT_SIMULATION_PROGRAM_ID = SIMULATION_TEST_PROGRAMS[0].id;
|
||||
export const DEFAULT_SIMULATION_PROGRAM = SIMULATION_TEST_PROGRAMS[0].text;
|
||||
export {
|
||||
DEFAULT_SIMULATION_PROGRAM,
|
||||
DEFAULT_SIMULATION_PROGRAM_ID,
|
||||
SIMULATION_TEST_PROGRAMS,
|
||||
getSimulationTestProgram,
|
||||
getSimulationTestPrograms,
|
||||
};
|
||||
|
||||
const AXES = ["x", "y", "z", "a", "b", "c", "u", "v", "w"];
|
||||
const PLANE_AXIS_MAP = {
|
||||
@@ -383,18 +315,6 @@ export function renderSimulationState(documentRef, state) {
|
||||
renderSimulationPlaybackFrame(documentRef, state, state.motion.length - 1);
|
||||
}
|
||||
|
||||
export function getSimulationTestPrograms() {
|
||||
return SIMULATION_TEST_PROGRAMS.map((program) => ({ ...program }));
|
||||
}
|
||||
|
||||
export function getSimulationTestProgram(programId = DEFAULT_SIMULATION_PROGRAM_ID) {
|
||||
const program = SIMULATION_TEST_PROGRAMS.find(({ id }) => id === programId);
|
||||
if (!program) {
|
||||
throw new Error(`unknown simulation test program: ${programId}`);
|
||||
}
|
||||
return program;
|
||||
}
|
||||
|
||||
export async function runRealBrowserSimulation({
|
||||
documentRef = document,
|
||||
programId = DEFAULT_SIMULATION_PROGRAM_ID,
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { readdirSync } from "node:fs";
|
||||
import { dirname, resolve } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
import {
|
||||
DEFAULT_SIMULATION_PROGRAM,
|
||||
@@ -10,12 +13,24 @@ import {
|
||||
getSimulationTestPrograms,
|
||||
parseLinuxCncCanonicalMotion,
|
||||
} from "../../../runtime/ui/simulation/simulation-app.js";
|
||||
import {
|
||||
SIMULATION_TEST_PROGRAMS as directoryPrograms,
|
||||
} from "../../../runtime/ui/simulation/programs/index.js";
|
||||
|
||||
const programs = getSimulationTestPrograms();
|
||||
const root = resolve(dirname(fileURLToPath(import.meta.url)), "../../..");
|
||||
const programDir = resolve(root, "runtime/ui/simulation/programs");
|
||||
const programFiles = readdirSync(programDir).filter((file) => file.endsWith(".js") && file !== "index.js");
|
||||
|
||||
assert.equal(DEFAULT_SIMULATION_PROGRAM_ID, "square-linear");
|
||||
assert.equal(getSimulationTestProgram(DEFAULT_SIMULATION_PROGRAM_ID).text, DEFAULT_SIMULATION_PROGRAM);
|
||||
assert.ok(programs.length >= 5, "real simulation program inventory should cover multiple examples");
|
||||
assert.equal(programFiles.length, programs.length, "each simulation test program should live in its own programs/*.js file");
|
||||
assert.deepEqual(
|
||||
directoryPrograms.map(({ id }) => id),
|
||||
programs.map(({ id }) => id),
|
||||
"simulation-app should re-export the directory-backed program inventory",
|
||||
);
|
||||
|
||||
for (const program of programs) {
|
||||
assert.ok(program.id, "program id should be present");
|
||||
|
||||
Reference in New Issue
Block a user