同步五轴仿真文档和验证证据

This commit is contained in:
2026-06-26 09:45:39 -04:00
parent d5d96a8e5c
commit 8df191faa5
188 changed files with 19504 additions and 42 deletions

View File

@@ -856,6 +856,9 @@ export function createSimulationStore(seed = {}) {
}
break;
case "TASK_HAL_SESSION_READY":
if (action.session?.programSourceRel && action.session.programSourceRel !== state.machineFileStaging?.selectedGcodeSourceRel) {
break;
}
setState({
taskHalSession: action.session,
taskHalFallbackReason: null,
@@ -898,6 +901,12 @@ export function createSimulationStore(seed = {}) {
operatorMessage: action.operatorMessage || state.operatorMessage,
});
break;
case "TASK_HAL_PROGRAM_STOPPED":
setState(createStoppedProgramStatePatch(state, {
reason: action.reason || "stopped",
operatorMessage: action.operatorMessage || "task/HAL program stopped",
}));
break;
case "TASK_HAL_COMMAND_FAILED":
setState({
taskHalFallbackReason: action.error,
@@ -1243,9 +1252,21 @@ export function createSimulationStore(seed = {}) {
stopTaskHalStatusLoop(action.type === "ABORT" ? "aborted" : "stopped", {
operatorMessage: action.type === "ABORT" ? "task/HAL abort requested" : "task/HAL stop requested",
});
setState(createStoppedProgramStatePatch(state, {
reason: action.type === "ABORT" ? "aborted" : "stopped",
operatorMessage: action.type === "ABORT" ? "task abort requested" : "program stop requested",
}));
runTaskHalCommandSequence([
{ type: "EMC_TASK_ABORT" },
], { operatorMessage: action.type === "ABORT" ? "task/HAL abort complete" : "task/HAL program stopped" }).catch(() => {});
], { operatorMessage: action.type === "ABORT" ? "task/HAL abort complete" : "task/HAL program stopped" })
.then(() => {
dispatch({
type: "TASK_HAL_PROGRAM_STOPPED",
reason: action.type === "ABORT" ? "aborted" : "stopped",
operatorMessage: action.type === "ABORT" ? "task/HAL abort complete" : "task/HAL program stopped",
});
})
.catch(() => {});
break;
}
setState({
@@ -1304,8 +1325,8 @@ export function createSimulationStore(seed = {}) {
{ type: "EMC_TASK_PLAN_RESUME" },
], {
operatorMessage: "task/HAL program resumed",
}).then(() => {
if (state.runState === "running" || state.machine.interpState === "reading") {
}).then((status) => {
if (shouldContinueTaskHalStatusLoop(state, status)) {
startTaskHalStatusLoop({
operatorMessage: "task/HAL status loop resumed",
});
@@ -1337,7 +1358,9 @@ export function createSimulationStore(seed = {}) {
}
if (state.taskHalRuntime?.loaded) {
stopTaskHalStatusLoop("step", { operatorMessage: "task/HAL step requested" });
runTaskHalCommandSequence([], {
runTaskHalCommandSequence([
{ type: "EMC_TASK_PLAN_STEP" },
], {
taskCycles: 1,
operatorMessage: "task/HAL stepped one cycle",
}).catch(() => {});
@@ -1412,6 +1435,20 @@ export function createSimulationStore(seed = {}) {
break;
}
if (state.taskHalRuntime?.loaded) {
setState({
machine: {
...state.machine,
mode: "manual",
allHomed: true,
interpState: "idle",
interpResumeState: "idle",
taskPaused: false,
},
runState: "idle",
axisPose: initialAxisPose,
programRuntimeFeedback: null,
operatorMessage: "task/HAL home requested",
});
runTaskHalCommandSequence([
{ type: "EMC_JOINT_HOME", joint: -1 },
], {
@@ -1421,6 +1458,7 @@ export function createSimulationStore(seed = {}) {
allHomed: true,
},
}).catch(() => {});
break;
}
setState({
machine: {
@@ -1705,6 +1743,7 @@ export function createSimulationStore(seed = {}) {
if (!state.taskHalRuntime?.loaded || !state.machineFileStaging?.save?.files?.length) {
return null;
}
stopTaskHalStatusLoop("session-initialize", { notify: false });
const preserveMachine = {
powerOn: state.machine.powerOn,
estopActive: state.machine.estopActive,
@@ -1719,6 +1758,9 @@ export function createSimulationStore(seed = {}) {
save: state.machineFileStaging.save,
selectedProgramRel: state.machineFileStaging.selectedGcodeSourceRel,
});
if (session.programSourceRel && session.programSourceRel !== state.machineFileStaging.selectedGcodeSourceRel) {
return null;
}
await state.taskHalRuntime.resetSession?.();
await state.taskHalRuntime.initSession({
profileId: session.profileId,
@@ -1746,6 +1788,9 @@ export function createSimulationStore(seed = {}) {
...deriveTaskHalCyclePeriods(state),
taskCycles: 1,
});
if (session.programSourceRel && session.programSourceRel !== state.machineFileStaging.selectedGcodeSourceRel) {
return null;
}
dispatch({ type: "TASK_HAL_SESSION_READY", session });
const status = await state.taskHalRuntime.readStatus();
dispatch({
@@ -2345,11 +2390,12 @@ function applyTaskHalStatusPatch(state, status, operatorMessage, {
: rawTaskState;
const taskMode = normalizeLinuxCncTaskMode(preserveMachine?.mode || ui.taskMode || task.mode || state.machine.mode);
const interpState = normalizeTaskHalInterpState(ui.interpState || task.interpState);
const allHomed = Boolean(preserveMachine?.allHomed ?? state.machine.allHomed);
const activeLine = state.programStartLine + Math.max(Number(ui.activeLine || 1) - 1, 0);
const kinsType = resolveTaskHalKinsType(state, status, activeLine);
const axisPose = resolveTaskHalAxisPose(state, status);
const currentVelocity = Number.isFinite(ui.currentVelocity) && ui.currentVelocity > 0
? ui.currentVelocity
const currentVelocity = Number.isFinite(ui.currentVelocity)
? Math.max(ui.currentVelocity, 0)
: state.feed.currentVelocity;
const paused = interpState === "paused" || motion.paused === true;
const aborted = motion.aborted === true;
@@ -2400,7 +2446,8 @@ function applyTaskHalStatusPatch(state, status, operatorMessage, {
interpState,
interpResumeState: paused ? state.machine.interpResumeState || "reading" : interpState,
taskPaused: paused,
allHomed: Boolean(preserveMachine?.allHomed ?? state.machine.allHomed),
allHomed,
noForceHoming: Boolean(state.machine.noForceHoming),
},
runState,
taskHalStatusLoop: loopSequence === null
@@ -2440,6 +2487,33 @@ function shouldContinueTaskHalStatusLoop(state = {}, status = {}) {
return !aborted && !paused && !complete && (interpState === "reading" || taskMode === "mdi");
}
function createStoppedProgramStatePatch(state, {
reason = "stopped",
operatorMessage = "program stopped",
} = {}) {
return {
machine: {
...state.machine,
interpState: "idle",
interpResumeState: "idle",
taskPaused: false,
},
runState: reason === "aborted" ? "stopped" : reason,
taskHalStatusLoop: {
...state.taskHalStatusLoop,
active: false,
sequence: Number(state.taskHalStatusLoop?.sequence || 0) + 1,
stopReason: reason,
lastStatusAt: new Date().toISOString(),
},
feed: {
...state.feed,
currentVelocity: 0,
},
operatorMessage,
};
}
function resolveTaskHalKinsType(state, status, activeLine) {
const ui = status?.ui || {};
const numeric = Number(ui.switchkinsType);