|
|
|
|
@@ -230,6 +230,7 @@ const initialState = {
|
|
|
|
|
taskHalExecutionPending: false,
|
|
|
|
|
taskHalExecutionSequence: 0,
|
|
|
|
|
taskHalStatusLoop: createTaskHalStatusLoopState(),
|
|
|
|
|
taskHalPauseLock: null,
|
|
|
|
|
taskHalFallbackReason: null,
|
|
|
|
|
pendingJogCommand: null,
|
|
|
|
|
interpreterExecutionPending: false,
|
|
|
|
|
@@ -1147,6 +1148,7 @@ export function createSimulationStore(seed = {}) {
|
|
|
|
|
setState({
|
|
|
|
|
taskHalFallbackReason: action.error,
|
|
|
|
|
taskHalExecutionPending: false,
|
|
|
|
|
taskHalPauseLock: null,
|
|
|
|
|
taskHalStatusLoop: {
|
|
|
|
|
...state.taskHalStatusLoop,
|
|
|
|
|
active: false,
|
|
|
|
|
@@ -1269,50 +1271,34 @@ export function createSimulationStore(seed = {}) {
|
|
|
|
|
setState({ operatorMessage: gate.operatorMessage });
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
const turningOff = state.machine.taskState === "on" || state.machine.powerOn;
|
|
|
|
|
const turningOn = state.machine.taskState === "estop-reset";
|
|
|
|
|
if (state.taskHalRuntime?.loaded) {
|
|
|
|
|
const nextMachine = createPowerToggleMachinePatch(state.machine, turningOn);
|
|
|
|
|
setState({
|
|
|
|
|
machine: {
|
|
|
|
|
...state.machine,
|
|
|
|
|
powerOn: !turningOff,
|
|
|
|
|
estopActive: false,
|
|
|
|
|
taskState: turningOff ? "estop-reset" : "on",
|
|
|
|
|
manualPanel: "manual",
|
|
|
|
|
interpState: "idle",
|
|
|
|
|
interpResumeState: "idle",
|
|
|
|
|
taskPaused: false,
|
|
|
|
|
},
|
|
|
|
|
runState: turningOff ? "powered-off" : "idle",
|
|
|
|
|
kinsType: turningOff ? "identity" : state.kinsType,
|
|
|
|
|
rtcpState: turningOff ? "off" : state.rtcpState,
|
|
|
|
|
feed: turningOff ? { ...state.feed, currentVelocity: 0 } : state.feed,
|
|
|
|
|
coolant: turningOff ? { ...state.coolant, flood: false, mist: false } : state.coolant,
|
|
|
|
|
spindle: turningOff ? stoppedSpindleState(state.spindle) : state.spindle,
|
|
|
|
|
operatorMessage: turningOff ? "task/HAL machine power off" : "task/HAL machine power on",
|
|
|
|
|
machine: nextMachine,
|
|
|
|
|
runState: turningOn ? "idle" : "powered-off",
|
|
|
|
|
kinsType: turningOn ? state.kinsType : "identity",
|
|
|
|
|
rtcpState: turningOn ? state.rtcpState : "off",
|
|
|
|
|
feed: turningOn ? state.feed : { ...state.feed, currentVelocity: 0 },
|
|
|
|
|
coolant: turningOn ? state.coolant : { ...state.coolant, flood: false, mist: false },
|
|
|
|
|
spindle: turningOn ? state.spindle : stoppedSpindleState(state.spindle),
|
|
|
|
|
operatorMessage: turningOn ? "task/HAL machine power on" : "task/HAL machine power off",
|
|
|
|
|
});
|
|
|
|
|
runTaskHalCommandSequence([
|
|
|
|
|
{ type: "EMC_TASK_SET_STATE", state: turningOff ? "ESTOP_RESET" : "ON" },
|
|
|
|
|
], { operatorMessage: turningOff ? "task/HAL machine power off" : "task/HAL machine power on" }).catch(() => {});
|
|
|
|
|
{ type: "EMC_TASK_SET_STATE", state: turningOn ? "ON" : "OFF" },
|
|
|
|
|
], { operatorMessage: turningOn ? "task/HAL machine power on" : "task/HAL machine power off" }).catch(() => {});
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
const nextMachine = createPowerToggleMachinePatch(state.machine, turningOn);
|
|
|
|
|
setState({
|
|
|
|
|
machine: {
|
|
|
|
|
...state.machine,
|
|
|
|
|
powerOn: !turningOff,
|
|
|
|
|
estopActive: false,
|
|
|
|
|
taskState: turningOff ? "estop-reset" : "on",
|
|
|
|
|
manualPanel: "manual",
|
|
|
|
|
interpState: "idle",
|
|
|
|
|
interpResumeState: "idle",
|
|
|
|
|
taskPaused: false,
|
|
|
|
|
},
|
|
|
|
|
runState: turningOff ? "powered-off" : "idle",
|
|
|
|
|
kinsType: turningOff ? "identity" : state.kinsType,
|
|
|
|
|
rtcpState: turningOff ? "off" : state.rtcpState,
|
|
|
|
|
feed: turningOff ? { ...state.feed, currentVelocity: 0 } : state.feed,
|
|
|
|
|
coolant: turningOff ? { ...state.coolant, flood: false, mist: false } : state.coolant,
|
|
|
|
|
spindle: turningOff ? stoppedSpindleState(state.spindle) : state.spindle,
|
|
|
|
|
operatorMessage: turningOff ? "machine power off" : "machine power on",
|
|
|
|
|
machine: nextMachine,
|
|
|
|
|
runState: turningOn ? "idle" : "powered-off",
|
|
|
|
|
kinsType: turningOn ? state.kinsType : "identity",
|
|
|
|
|
rtcpState: turningOn ? state.rtcpState : "off",
|
|
|
|
|
feed: turningOn ? state.feed : { ...state.feed, currentVelocity: 0 },
|
|
|
|
|
coolant: turningOn ? state.coolant : { ...state.coolant, flood: false, mist: false },
|
|
|
|
|
spindle: turningOn ? state.spindle : stoppedSpindleState(state.spindle),
|
|
|
|
|
operatorMessage: turningOn ? "machine power on" : "machine power off",
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
@@ -1633,6 +1619,7 @@ export function createSimulationStore(seed = {}) {
|
|
|
|
|
taskPaused: false,
|
|
|
|
|
},
|
|
|
|
|
runState: "running",
|
|
|
|
|
taskHalPauseLock: null,
|
|
|
|
|
operatorMessage: "task/HAL program run requested",
|
|
|
|
|
});
|
|
|
|
|
runValidatedTaskHalProgramRun().catch(() => {});
|
|
|
|
|
@@ -1658,6 +1645,7 @@ export function createSimulationStore(seed = {}) {
|
|
|
|
|
taskPaused: false,
|
|
|
|
|
},
|
|
|
|
|
runState: playback.complete ? "complete" : "running",
|
|
|
|
|
taskHalPauseLock: null,
|
|
|
|
|
...playbackPatch,
|
|
|
|
|
programLineExecution: createProgramLineExecutionPatch(state.programLineExecution, playback.runtimeFeedback, {
|
|
|
|
|
status: playback.complete ? "done" : "running",
|
|
|
|
|
@@ -1718,6 +1706,7 @@ export function createSimulationStore(seed = {}) {
|
|
|
|
|
taskPaused: false,
|
|
|
|
|
},
|
|
|
|
|
runState: "stopped",
|
|
|
|
|
taskHalPauseLock: null,
|
|
|
|
|
feed: {
|
|
|
|
|
...state.feed,
|
|
|
|
|
currentVelocity: 0,
|
|
|
|
|
@@ -1766,19 +1755,24 @@ export function createSimulationStore(seed = {}) {
|
|
|
|
|
stopTaskHalStatusLoop("paused", { operatorMessage: "task/HAL pause requested" });
|
|
|
|
|
const pausedMachine = {
|
|
|
|
|
...state.machine,
|
|
|
|
|
mode: programControlModeForMachine(state.machine),
|
|
|
|
|
manualPanel: null,
|
|
|
|
|
interpResumeState: state.machine.interpState === "paused"
|
|
|
|
|
? state.machine.interpResumeState
|
|
|
|
|
: state.machine.interpState || "reading",
|
|
|
|
|
interpState: "paused",
|
|
|
|
|
taskPaused: true,
|
|
|
|
|
};
|
|
|
|
|
const pauseLock = createTaskHalPauseLock(state, "task-hal-plan-pause");
|
|
|
|
|
setState({
|
|
|
|
|
machine: pausedMachine,
|
|
|
|
|
runState: "paused",
|
|
|
|
|
taskHalPauseLock: pauseLock,
|
|
|
|
|
feed: {
|
|
|
|
|
...state.feed,
|
|
|
|
|
currentVelocity: 0,
|
|
|
|
|
},
|
|
|
|
|
programRuntimeFeedback: zeroProgramRuntimeVelocity(state.programRuntimeFeedback),
|
|
|
|
|
operatorMessage: "task/HAL pause requested",
|
|
|
|
|
});
|
|
|
|
|
runTaskHalCommandSequence([
|
|
|
|
|
@@ -1789,9 +1783,12 @@ export function createSimulationStore(seed = {}) {
|
|
|
|
|
}).catch(() => {});
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
const pauseLock = createTaskHalPauseLock(state, "fixture-plan-pause");
|
|
|
|
|
setState({
|
|
|
|
|
machine: {
|
|
|
|
|
...state.machine,
|
|
|
|
|
mode: programControlModeForMachine(state.machine),
|
|
|
|
|
manualPanel: null,
|
|
|
|
|
interpResumeState: state.machine.interpState === "paused"
|
|
|
|
|
? state.machine.interpResumeState
|
|
|
|
|
: state.machine.interpState,
|
|
|
|
|
@@ -1799,6 +1796,12 @@ export function createSimulationStore(seed = {}) {
|
|
|
|
|
taskPaused: true,
|
|
|
|
|
},
|
|
|
|
|
runState: "paused",
|
|
|
|
|
taskHalPauseLock: pauseLock,
|
|
|
|
|
feed: {
|
|
|
|
|
...state.feed,
|
|
|
|
|
currentVelocity: 0,
|
|
|
|
|
},
|
|
|
|
|
programRuntimeFeedback: zeroProgramRuntimeVelocity(state.programRuntimeFeedback),
|
|
|
|
|
operatorMessage: "program paused",
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
@@ -1806,17 +1809,16 @@ export function createSimulationStore(seed = {}) {
|
|
|
|
|
case "PAUSE_RESUME":
|
|
|
|
|
{
|
|
|
|
|
const interpState = state.machine?.interpState || state.linuxCncTaskPolicy?.interpState || "idle";
|
|
|
|
|
const taskMode = state.machine?.mode || state.linuxCncTaskPolicy?.taskMode || "manual";
|
|
|
|
|
const taskIsRunning = state.runState === "running" || state.runState === "stepping";
|
|
|
|
|
if (state.machine?.taskPaused === true || interpState === "paused" || state.runState === "paused") {
|
|
|
|
|
if (taskMode === "auto" || taskMode === "mdi") {
|
|
|
|
|
dispatch({ type: "RESUME" });
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
setState({ operatorMessage: "resume blocked: task mode must be auto or MDI" });
|
|
|
|
|
const taskMode = normalizeLinuxCncTaskMode(state.machine?.mode);
|
|
|
|
|
if (taskMode !== "auto" && taskMode !== "mdi") {
|
|
|
|
|
setState({ operatorMessage: "pause blocked: task mode must be auto or MDI" });
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if ((taskMode === "auto" || taskMode === "mdi") && (interpState !== "idle" || taskIsRunning)) {
|
|
|
|
|
if (state.machine?.taskPaused === true || interpState === "paused" || state.runState === "paused") {
|
|
|
|
|
dispatch({ type: "RESUME", source: "pauseresume" });
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (interpState !== "idle") {
|
|
|
|
|
dispatch({ type: "PAUSE", source: "pauseresume" });
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
@@ -1836,6 +1838,8 @@ export function createSimulationStore(seed = {}) {
|
|
|
|
|
: state.machine.interpResumeState || "reading";
|
|
|
|
|
const resumedMachine = {
|
|
|
|
|
...state.machine,
|
|
|
|
|
mode: programControlModeForMachine(state.machine),
|
|
|
|
|
manualPanel: null,
|
|
|
|
|
interpState: resumeState,
|
|
|
|
|
interpResumeState: resumeState,
|
|
|
|
|
taskPaused: false,
|
|
|
|
|
@@ -1843,6 +1847,7 @@ export function createSimulationStore(seed = {}) {
|
|
|
|
|
setState({
|
|
|
|
|
machine: resumedMachine,
|
|
|
|
|
runState: resumeState === "reading" ? "running" : "idle",
|
|
|
|
|
taskHalPauseLock: null,
|
|
|
|
|
operatorMessage: "task/HAL resume requested",
|
|
|
|
|
});
|
|
|
|
|
runTaskHalCommandSequence([
|
|
|
|
|
@@ -1865,11 +1870,14 @@ export function createSimulationStore(seed = {}) {
|
|
|
|
|
setState({
|
|
|
|
|
machine: {
|
|
|
|
|
...state.machine,
|
|
|
|
|
mode: programControlModeForMachine(state.machine),
|
|
|
|
|
manualPanel: null,
|
|
|
|
|
interpState: resumeState,
|
|
|
|
|
interpResumeState: resumeState,
|
|
|
|
|
taskPaused: false,
|
|
|
|
|
},
|
|
|
|
|
runState: resumeState === "reading" ? "running" : "idle",
|
|
|
|
|
taskHalPauseLock: null,
|
|
|
|
|
operatorMessage: "program resumed",
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
@@ -1906,6 +1914,7 @@ export function createSimulationStore(seed = {}) {
|
|
|
|
|
setState({
|
|
|
|
|
machine: steppedMachine,
|
|
|
|
|
runState: "stepping",
|
|
|
|
|
taskHalPauseLock: null,
|
|
|
|
|
...playbackPatch,
|
|
|
|
|
programElapsedSeconds: playback.timing.elapsedSeconds,
|
|
|
|
|
programRemainingSeconds: playback.timing.remainingSeconds,
|
|
|
|
|
@@ -1946,6 +1955,7 @@ export function createSimulationStore(seed = {}) {
|
|
|
|
|
taskPaused: true,
|
|
|
|
|
},
|
|
|
|
|
runState: "stepping",
|
|
|
|
|
taskHalPauseLock: null,
|
|
|
|
|
...playbackPatch,
|
|
|
|
|
programElapsedSeconds: playback.timing.elapsedSeconds,
|
|
|
|
|
programRemainingSeconds: playback.timing.remainingSeconds,
|
|
|
|
|
@@ -2602,49 +2612,17 @@ export function createSimulationStore(seed = {}) {
|
|
|
|
|
}
|
|
|
|
|
if (state.taskHalRuntime?.loaded) {
|
|
|
|
|
await initializeTaskHalSession({ openProgram: true });
|
|
|
|
|
await runTaskHalCommandSequence([
|
|
|
|
|
{ type: "EMC_TASK_SET_STATE", state: "ON" },
|
|
|
|
|
{ type: "EMC_JOINT_HOME", joint: -1 },
|
|
|
|
|
{ type: "EMC_TASK_SET_MODE", mode: "AUTO" },
|
|
|
|
|
], {
|
|
|
|
|
taskCycles: 3,
|
|
|
|
|
operatorMessage: "RUN ready: power on, homed, auto mode",
|
|
|
|
|
allowFixtureSession: false,
|
|
|
|
|
preserveMachine: {
|
|
|
|
|
powerOn: true,
|
|
|
|
|
estopActive: false,
|
|
|
|
|
taskState: "on",
|
|
|
|
|
mode: "auto",
|
|
|
|
|
manualPanel: null,
|
|
|
|
|
allHomed: true,
|
|
|
|
|
},
|
|
|
|
|
setState({
|
|
|
|
|
operatorMessage: state.machine.powerOn && state.machine.allHomed
|
|
|
|
|
? "RUN ready: program opened; press Run"
|
|
|
|
|
: "RUN setup ready: reset ESTOP, power on, Home All, then Run",
|
|
|
|
|
});
|
|
|
|
|
const tcpKinsType = tcpKinsTypeForProfile(state.profile);
|
|
|
|
|
if (tcpKinsType) {
|
|
|
|
|
dispatch({ type: "SET_KINS_TYPE", kinsType: tcpKinsType });
|
|
|
|
|
}
|
|
|
|
|
return state;
|
|
|
|
|
}
|
|
|
|
|
const tcpKinsType = tcpKinsTypeForProfile(state.profile);
|
|
|
|
|
setState({
|
|
|
|
|
machine: {
|
|
|
|
|
...state.machine,
|
|
|
|
|
powerOn: true,
|
|
|
|
|
estopActive: false,
|
|
|
|
|
taskState: "on",
|
|
|
|
|
mode: "auto",
|
|
|
|
|
manualPanel: null,
|
|
|
|
|
allHomed: true,
|
|
|
|
|
interpState: "idle",
|
|
|
|
|
interpResumeState: "idle",
|
|
|
|
|
taskPaused: false,
|
|
|
|
|
},
|
|
|
|
|
runState: "idle",
|
|
|
|
|
kinsType: tcpKinsType || "identity",
|
|
|
|
|
rtcpState: tcpKinsType ? "on" : "off",
|
|
|
|
|
operatorMessage: tcpKinsType
|
|
|
|
|
? "RUN ready: power on, homed, auto mode"
|
|
|
|
|
: "RUN ready: power on, homed, auto mode; TCP unavailable for this reference profile",
|
|
|
|
|
operatorMessage: state.machine.powerOn && state.machine.allHomed
|
|
|
|
|
? "RUN ready: program opened; press Run"
|
|
|
|
|
: "RUN setup ready: reset ESTOP, power on, Home All, then Run",
|
|
|
|
|
});
|
|
|
|
|
return state;
|
|
|
|
|
};
|
|
|
|
|
@@ -2657,6 +2635,19 @@ export function createSimulationStore(seed = {}) {
|
|
|
|
|
await waitForStatePredicate((nextState) => nextState.machineFileStaging?.selectedGcodeSourceRel === sourceRel);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
const runGateState = {
|
|
|
|
|
...state,
|
|
|
|
|
machine: {
|
|
|
|
|
...state.machine,
|
|
|
|
|
mode: "auto",
|
|
|
|
|
manualPanel: null,
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
const runGate = gateLinuxCncTaskAction(runGateState, { type: "RUN" });
|
|
|
|
|
if (!runGate.allowed) {
|
|
|
|
|
setState({ operatorMessage: runGate.operatorMessage });
|
|
|
|
|
return state;
|
|
|
|
|
}
|
|
|
|
|
const tcpKinsType = tcpKinsTypeForProfile(state.profile);
|
|
|
|
|
if (state.taskHalRuntime?.loaded) {
|
|
|
|
|
if (
|
|
|
|
|
@@ -2679,17 +2670,14 @@ export function createSimulationStore(seed = {}) {
|
|
|
|
|
setState({
|
|
|
|
|
machine: {
|
|
|
|
|
...state.machine,
|
|
|
|
|
powerOn: true,
|
|
|
|
|
estopActive: false,
|
|
|
|
|
taskState: "on",
|
|
|
|
|
mode: "auto",
|
|
|
|
|
manualPanel: null,
|
|
|
|
|
allHomed: true,
|
|
|
|
|
interpState: "reading",
|
|
|
|
|
interpResumeState: "reading",
|
|
|
|
|
taskPaused: false,
|
|
|
|
|
},
|
|
|
|
|
runState: "running",
|
|
|
|
|
taskHalPauseLock: null,
|
|
|
|
|
operatorMessage: "RUN ready: motion plan source ready; preparing task/HAL session",
|
|
|
|
|
});
|
|
|
|
|
const expectedProgramPath = expectedTaskHalProgramPathForState(state);
|
|
|
|
|
@@ -2733,7 +2721,6 @@ export function createSimulationStore(seed = {}) {
|
|
|
|
|
});
|
|
|
|
|
const status = await runTaskHalCommandSequence([
|
|
|
|
|
{ type: "EMC_TASK_SET_STATE", state: "ON" },
|
|
|
|
|
{ type: "EMC_JOINT_HOME", joint: -1 },
|
|
|
|
|
{ type: "EMC_TASK_SET_MODE", mode: "AUTO" },
|
|
|
|
|
{ type: "EMC_TASK_PLAN_RUN", line: 0 },
|
|
|
|
|
], {
|
|
|
|
|
@@ -2755,8 +2742,15 @@ export function createSimulationStore(seed = {}) {
|
|
|
|
|
return state;
|
|
|
|
|
}
|
|
|
|
|
const policy = createLinuxCncTaskPolicyStatus(state);
|
|
|
|
|
if (policy.taskMode !== "auto" || !policy.allHomed || policy.taskState !== "on") {
|
|
|
|
|
await runReadySequence();
|
|
|
|
|
if (policy.taskMode !== "auto") {
|
|
|
|
|
setState({
|
|
|
|
|
machine: {
|
|
|
|
|
...state.machine,
|
|
|
|
|
mode: "auto",
|
|
|
|
|
manualPanel: null,
|
|
|
|
|
},
|
|
|
|
|
operatorMessage: "mode auto",
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
dispatch({ type: "RUN" });
|
|
|
|
|
return state;
|
|
|
|
|
@@ -3778,27 +3772,38 @@ function applyTaskHalStatusPatch(state, status, operatorMessage, {
|
|
|
|
|
const ui = status?.ui || {};
|
|
|
|
|
const task = status?.task || {};
|
|
|
|
|
const motion = status?.motionStatus?.motion || {};
|
|
|
|
|
const pauseLock = state.taskHalPauseLock?.active === true ? state.taskHalPauseLock : null;
|
|
|
|
|
const rawTaskState = normalizeTaskHalTaskState(ui.taskState || task.state);
|
|
|
|
|
const taskState = preserveMachine?.powerOn && rawTaskState === "estop-reset"
|
|
|
|
|
? "on"
|
|
|
|
|
: rawTaskState;
|
|
|
|
|
const taskMode = normalizeLinuxCncTaskMode(preserveMachine?.mode || ui.taskMode || task.mode || state.machine.mode);
|
|
|
|
|
const taskMode = pauseLock
|
|
|
|
|
? programControlModeForMachine(state.machine)
|
|
|
|
|
: normalizeLinuxCncTaskMode(preserveMachine?.mode || ui.taskMode || task.mode || state.machine.mode);
|
|
|
|
|
const manualPanel = taskMode === "manual"
|
|
|
|
|
? (preserveMachine?.manualPanel || state.machine.manualPanel || "manual")
|
|
|
|
|
: null;
|
|
|
|
|
const interpState = Object.hasOwn(preserveMachine || {}, "interpState")
|
|
|
|
|
? normalizeTaskHalInterpState(preserveMachine.interpState)
|
|
|
|
|
: normalizeTaskHalInterpState(ui.interpState || task.interpState);
|
|
|
|
|
const interpState = pauseLock
|
|
|
|
|
? "paused"
|
|
|
|
|
: Object.hasOwn(preserveMachine || {}, "interpState")
|
|
|
|
|
? normalizeTaskHalInterpState(preserveMachine.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 = preserveAxisPose
|
|
|
|
|
? clampAxisPoseToProfile({ ...state.axisPose, ...preserveAxisPose }, state.profile)
|
|
|
|
|
: resolveTaskHalAxisPose(state, status);
|
|
|
|
|
const currentVelocity = Number.isFinite(ui.currentVelocity)
|
|
|
|
|
? Math.max(ui.currentVelocity, 0)
|
|
|
|
|
: state.feed.currentVelocity;
|
|
|
|
|
const paused = interpState === "paused" || motion.paused === true;
|
|
|
|
|
const paused = Boolean(pauseLock) || interpState === "paused" || motion.paused === true;
|
|
|
|
|
const axisPose = pauseLock?.axisPose
|
|
|
|
|
? clampAxisPoseToProfile(pauseLock.axisPose, state.profile)
|
|
|
|
|
: paused
|
|
|
|
|
? clampAxisPoseToProfile(state.axisPose, state.profile)
|
|
|
|
|
: preserveAxisPose
|
|
|
|
|
? clampAxisPoseToProfile({ ...state.axisPose, ...preserveAxisPose }, state.profile)
|
|
|
|
|
: resolveTaskHalAxisPose(state, status);
|
|
|
|
|
const currentVelocity = paused
|
|
|
|
|
? 0
|
|
|
|
|
: Number.isFinite(ui.currentVelocity)
|
|
|
|
|
? Math.max(ui.currentVelocity, 0)
|
|
|
|
|
: state.feed.currentVelocity;
|
|
|
|
|
const aborted = motion.aborted === true;
|
|
|
|
|
const openedProgramLineCount = Number(task.openedSourceLineCount || task.openedLineCount || 1);
|
|
|
|
|
const programComplete = interpState === "idle" && Number(task.nextProgramLine || 0) >= openedProgramLineCount;
|
|
|
|
|
@@ -3819,7 +3824,13 @@ function applyTaskHalStatusPatch(state, status, operatorMessage, {
|
|
|
|
|
const shouldTrackProgramPlayback = runState === "running"
|
|
|
|
|
|| runState === "mdi"
|
|
|
|
|
|| (runState === "complete" && (state.runState === "running" || state.runState === "mdi" || state.runState === "complete"));
|
|
|
|
|
const taskHalSampleIndex = shouldTrackProgramPlayback
|
|
|
|
|
const taskHalSampleIndex = pauseLock
|
|
|
|
|
? clampNumber(
|
|
|
|
|
pauseLock.sampleIndex,
|
|
|
|
|
0,
|
|
|
|
|
Math.max(Number(state.programAxisPreviewPath?.samples?.length || state.programAxisPreviewPath?.sampleCount || 1) - 1, 0),
|
|
|
|
|
)
|
|
|
|
|
: shouldTrackProgramPlayback
|
|
|
|
|
? resolveRuntimeSampleIndexForTaskHalPose(state, axisPose, activeLine, runtimeFeedback.sampleIndex)
|
|
|
|
|
: clampNumber(
|
|
|
|
|
state.programExecutionSampleIndex || 0,
|
|
|
|
|
@@ -3829,7 +3840,17 @@ function applyTaskHalStatusPatch(state, status, operatorMessage, {
|
|
|
|
|
const idleRuntimeFeedback = {
|
|
|
|
|
...runtimeFeedback,
|
|
|
|
|
sampleIndex: taskHalSampleIndex,
|
|
|
|
|
motionIndex: Number(state.programExecutionMotionIndex || runtimeFeedback.motionIndex || 0),
|
|
|
|
|
motionIndex: pauseLock
|
|
|
|
|
? Number(pauseLock.motionIndex || 0)
|
|
|
|
|
: Number(state.programExecutionMotionIndex || runtimeFeedback.motionIndex || 0),
|
|
|
|
|
...(paused ? {
|
|
|
|
|
axisPose,
|
|
|
|
|
tcp: {
|
|
|
|
|
x: Number(state.tcpPose?.x ?? axisPose.x ?? 0),
|
|
|
|
|
y: Number(state.tcpPose?.y ?? axisPose.y ?? 0),
|
|
|
|
|
z: Number(state.tcpPose?.z ?? axisPose.z ?? 0),
|
|
|
|
|
},
|
|
|
|
|
} : {}),
|
|
|
|
|
};
|
|
|
|
|
const taskHalPlaybackPatch = shouldTrackProgramPlayback
|
|
|
|
|
? applyProgramPlaybackUiPatch(state, {
|
|
|
|
|
@@ -3837,11 +3858,15 @@ function applyTaskHalStatusPatch(state, status, operatorMessage, {
|
|
|
|
|
axisPose,
|
|
|
|
|
kinsType,
|
|
|
|
|
rtcpState: rtcpStateFromKinsType(kinsType),
|
|
|
|
|
motionIndex: runtimeFeedback.motionIndex,
|
|
|
|
|
motionIndex: pauseLock ? Number(pauseLock.motionIndex || 0) : runtimeFeedback.motionIndex,
|
|
|
|
|
sampleIndex: taskHalSampleIndex,
|
|
|
|
|
runtimeFeedback: {
|
|
|
|
|
...runtimeFeedback,
|
|
|
|
|
sampleIndex: taskHalSampleIndex,
|
|
|
|
|
motionIndex: pauseLock ? Number(pauseLock.motionIndex || 0) : runtimeFeedback.motionIndex,
|
|
|
|
|
axisPose,
|
|
|
|
|
currentVelocityMmPerMin: paused ? 0 : runtimeFeedback.currentVelocityMmPerMin,
|
|
|
|
|
requestedVelocityMmPerMin: paused ? 0 : runtimeFeedback.requestedVelocityMmPerMin,
|
|
|
|
|
},
|
|
|
|
|
preferRuntimeAxisPose: true,
|
|
|
|
|
})
|
|
|
|
|
@@ -3879,6 +3904,7 @@ function applyTaskHalStatusPatch(state, status, operatorMessage, {
|
|
|
|
|
return {
|
|
|
|
|
taskHalStatus: status,
|
|
|
|
|
taskHalExecutionPending: false,
|
|
|
|
|
taskHalPauseLock: pauseLock ? { ...pauseLock, lastStatusAt: new Date().toISOString() } : state.taskHalPauseLock,
|
|
|
|
|
taskHalFallbackReason: null,
|
|
|
|
|
pendingJogCommand: null,
|
|
|
|
|
...taskHalPlaybackPatch,
|
|
|
|
|
@@ -3939,6 +3965,57 @@ function isTaskHalRunPausedByOperator(state = {}) {
|
|
|
|
|
|| state.machine?.taskPaused === true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function programControlModeForMachine(machine = {}) {
|
|
|
|
|
return machine.mode === "mdi" ? "mdi" : "auto";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function createPowerToggleMachinePatch(machine = {}, turningOn = false) {
|
|
|
|
|
return {
|
|
|
|
|
...machine,
|
|
|
|
|
powerOn: turningOn,
|
|
|
|
|
estopActive: false,
|
|
|
|
|
taskState: turningOn ? "on" : "off",
|
|
|
|
|
manualPanel: "manual",
|
|
|
|
|
allHomed: turningOn ? Boolean(machine.allHomed) : false,
|
|
|
|
|
interpState: "idle",
|
|
|
|
|
interpResumeState: "idle",
|
|
|
|
|
taskPaused: false,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function createTaskHalPauseLock(state = {}, source = "pause") {
|
|
|
|
|
return {
|
|
|
|
|
apiName: "web-rtcp-5axis-task-hal-pause-lock",
|
|
|
|
|
active: true,
|
|
|
|
|
source,
|
|
|
|
|
createdAt: new Date().toISOString(),
|
|
|
|
|
runState: "paused",
|
|
|
|
|
interpState: "paused",
|
|
|
|
|
sampleIndex: Number(state.programExecutionSampleIndex || 0),
|
|
|
|
|
motionIndex: Number(state.programExecutionMotionIndex || 0),
|
|
|
|
|
activeLine: Number(state.activeLine || state.programStartLine || 1),
|
|
|
|
|
axisPose: clampAxisPoseToProfile(state.axisPose || initialAxisPose, state.profile),
|
|
|
|
|
tcpPose: {
|
|
|
|
|
x: Number(state.tcpPose?.x || 0),
|
|
|
|
|
y: Number(state.tcpPose?.y || 0),
|
|
|
|
|
z: Number(state.tcpPose?.z || 0),
|
|
|
|
|
},
|
|
|
|
|
semanticBoundary: "linuxcnc_axis_task_pauseresume_freezes_task_hal_status_until_resume",
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function zeroProgramRuntimeVelocity(feedback) {
|
|
|
|
|
if (!feedback) return feedback;
|
|
|
|
|
return {
|
|
|
|
|
...feedback,
|
|
|
|
|
currentVelocityMmPerMin: 0,
|
|
|
|
|
requestedVelocityMmPerMin: 0,
|
|
|
|
|
distanceToGo: 0,
|
|
|
|
|
dtg: feedback.dtg ? { ...feedback.dtg, x: 0, y: 0, z: 0 } : feedback.dtg,
|
|
|
|
|
activeDepth: 0,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function createStoppedProgramStatePatch(state, {
|
|
|
|
|
reason = "stopped",
|
|
|
|
|
operatorMessage = "program stopped",
|
|
|
|
|
@@ -3951,6 +4028,7 @@ function createStoppedProgramStatePatch(state, {
|
|
|
|
|
taskPaused: false,
|
|
|
|
|
},
|
|
|
|
|
runState: reason === "aborted" ? "stopped" : reason,
|
|
|
|
|
taskHalPauseLock: null,
|
|
|
|
|
taskHalStatusLoop: {
|
|
|
|
|
...state.taskHalStatusLoop,
|
|
|
|
|
active: false,
|
|
|
|
|
@@ -4058,6 +4136,10 @@ function createTaskHalRuntimeFeedback(state, status, axisPose, activeLine) {
|
|
|
|
|
const motion = status?.motionStatus?.motion || {};
|
|
|
|
|
const halProgramLine = Number(status?.halSnapshot?.pins?.["motion.program-line"]?.value || 0);
|
|
|
|
|
const motionProgramLine = Number(motion.programLine || 0);
|
|
|
|
|
const interpState = normalizeTaskHalInterpState(ui.interpState || status?.task?.interpState);
|
|
|
|
|
const paused = interpState === "paused" || motion.paused === true;
|
|
|
|
|
const currentVelocity = paused ? 0 : Number(ui.currentVelocity || 0);
|
|
|
|
|
const requestedVelocity = paused ? 0 : Number(motion.requestedVel || 0) * 60;
|
|
|
|
|
return {
|
|
|
|
|
apiName: "web-rtcp-5axis-program-runtime-feedback",
|
|
|
|
|
sourceMode: "linuxcnc-task-motion-hal-wasm",
|
|
|
|
|
@@ -4072,8 +4154,8 @@ function createTaskHalRuntimeFeedback(state, status, axisPose, activeLine) {
|
|
|
|
|
type: Number(motion.motionType || 0) === 3 ? "JOG" : "TASK_MOTION",
|
|
|
|
|
timeSeconds: Number(ui.taskCycle || 0) * 0.01,
|
|
|
|
|
axisPose,
|
|
|
|
|
currentVelocityMmPerMin: Number(ui.currentVelocity || 0),
|
|
|
|
|
requestedVelocityMmPerMin: Number(motion.requestedVel || 0) * 60,
|
|
|
|
|
currentVelocityMmPerMin: currentVelocity,
|
|
|
|
|
requestedVelocityMmPerMin: requestedVelocity,
|
|
|
|
|
distanceToGo: motion.inPosition === true ? 0 : 1,
|
|
|
|
|
dtg: { x: 0, y: 0, z: 0 },
|
|
|
|
|
queueDepth: Number(ui.motionQueueDepth || status?.motionStatus?.commandQueueDepth || 0),
|
|
|
|
|
|