feat: complete working8 pause semantics

This commit is contained in:
wangdequan
2026-07-07 10:27:02 -04:00
parent 83402c506e
commit 4ba45b2ec5
987 changed files with 340641 additions and 65 deletions

View File

@@ -52,10 +52,20 @@ function send(command) {
);
}
function sendMotion(command) {
return withCString(JSON.stringify(command), (commandPtr) =>
assert.equal(runtime._lcmot_write_command_json(commandPtr), 0, command.type),
);
}
function status() {
return readJson((outPtr, outLen) => runtime._lctask_read_status_json(outPtr, outLen));
}
function motionStatus() {
return readJson((outPtr, outLen) => runtime._lcmot_read_status_json(outPtr, outLen));
}
function events() {
return readJson((outPtr, outLen) => runtime._lctask_read_events_json(outPtr, outLen)).events;
}
@@ -70,7 +80,12 @@ assert.equal(
0,
);
const program = ["G0 X1 Y2 Z-3 A10 C20", "G1 X2 Y3 Z-4 A11 C21"].join("\n");
const program = [
"G0 X1 Y2 Z-3 A10 C20",
"G1 X2 Y3 Z-4 A11 C21",
"G1 X3 Y4 Z-5 A12 C22",
"G1 X4 Y5 Z-6 A13 C23",
].join("\n");
assert.equal(
withCString("programs/task-hal-smoke.ngc", (pathPtr) =>
withCString(program, (textPtr) => runtime._lctask_stage_file(pathPtr, textPtr)),
@@ -85,7 +100,7 @@ assert.equal(
send({ type: "EMC_TASK_SET_STATE", state: "ON" });
send({ type: "EMC_TASK_SET_MODE", mode: "AUTO" });
send({ type: "EMC_TASK_PLAN_RUN", line: 0 });
assert.equal(runtime._lctask_run_cycles(10000000, 1000000, 2), 0);
assert.equal(runtime._lctask_run_cycles(10000000, 1000000, 1), 0);
let snapshot = status();
assert.equal(snapshot.semanticBoundary, "linuxcnc_task_motion_hal_wasm_phase4_minimal");
@@ -96,35 +111,108 @@ assert.equal(snapshot.nativeTaskReady, false);
assert.equal(snapshot.nativeHalSyncReady, false);
assert.equal(snapshot.task.state, "ON");
assert.equal(snapshot.task.mode, "AUTO");
assert.equal(snapshot.task.openedLineCount, 2);
assert.equal(snapshot.task.nextProgramLine, 2);
assert.equal(snapshot.motionStatus.motion.programLine, 2);
assert.equal(snapshot.motionStatus.axis.x, 2);
assert.equal(snapshot.motionStatus.axis.z, -4);
assert.equal(snapshot.halSnapshot.pins["motion.program-line"].value, 2);
assert.equal(snapshot.halSnapshot.pins["joint.0.motor-pos-cmd"].value, 2);
assert.equal(snapshot.task.openedLineCount, 4);
assert.equal(snapshot.task.nextProgramLine, 1);
assert.equal(snapshot.task.interpState, "READING");
assert.equal(snapshot.task.interpResumeState, "READING");
assert.equal(snapshot.motionStatus.motion.programLine, 1);
assert.equal(snapshot.motionStatus.axis.x, 1);
assert.equal(snapshot.motionStatus.axis.z, -3);
assert.equal(snapshot.halSnapshot.pins["motion.program-line"].value, 1);
assert.equal(snapshot.halSnapshot.pins["joint.0.motor-pos-cmd"].value, 1);
send({ type: "EMC_TASK_PLAN_PAUSE" });
snapshot = status();
assert.equal(snapshot.task.interpState, "PAUSED");
assert.equal(snapshot.task.interpResumeState, "READING");
assert.equal(snapshot.task.taskPaused, true);
assert.equal(snapshot.task.singleStepping, false);
assert.equal(snapshot.motionStatus.motion.paused, true);
assert.equal(snapshot.motionStatus.motion.currentVel, 0);
const pausedTaskLine = snapshot.task.nextProgramLine;
const pausedMotionLine = snapshot.motionStatus.motion.programLine;
const pausedMotionId = snapshot.motionStatus.motion.motionId;
const pausedQueueDepth = snapshot.motionStatus.commandQueueDepth;
const pausedAxis = { ...snapshot.motionStatus.axis };
assert.equal(runtime._lctask_run_cycles(10000000, 1000000, 20), 0);
snapshot = status();
assert.equal(snapshot.task.interpState, "PAUSED");
assert.equal(snapshot.task.interpResumeState, "READING");
assert.equal(snapshot.task.nextProgramLine, pausedTaskLine);
assert.equal(snapshot.motionStatus.motion.paused, true);
assert.equal(snapshot.motionStatus.motion.programLine, pausedMotionLine);
assert.equal(snapshot.motionStatus.motion.motionId, pausedMotionId);
assert.equal(snapshot.motionStatus.commandQueueDepth, pausedQueueDepth);
assert.deepEqual(snapshot.motionStatus.axis, pausedAxis);
send({ type: "EMC_TASK_PLAN_RESUME" });
assert.equal(runtime._lctask_run_cycles(10000000, 1000000, 1), 0);
snapshot = status();
assert.equal(snapshot.task.interpState, "READING");
assert.equal(snapshot.task.interpResumeState, "READING");
assert.equal(snapshot.task.taskPaused, false);
assert.equal(snapshot.motionStatus.motion.paused, false);
assert.equal(snapshot.motionStatus.motion.programLine, 2);
send({ type: "EMC_TASK_PLAN_PAUSE" });
send({ type: "EMC_TASK_PLAN_STEP" });
assert.equal(runtime._lctask_run_cycles(10000000, 1000000, 1), 0);
snapshot = status();
assert.equal(snapshot.task.interpState, "PAUSED");
assert.equal(snapshot.task.interpResumeState, "READING");
assert.equal(snapshot.task.taskPaused, true);
assert.equal(snapshot.task.singleStepping, false);
assert.equal(snapshot.motionStatus.motion.paused, true);
assert.equal(snapshot.motionStatus.motion.stepping, false);
assert.equal(snapshot.motionStatus.motion.programLine, 3);
assert.equal(snapshot.motionStatus.motion.motionId, pausedMotionId + 2);
send({ type: "EMC_TASK_PLAN_RESUME" });
assert.equal(runtime._lctask_run_cycles(10000000, 1000000, 1), 0);
snapshot = status();
assert.equal(snapshot.motionStatus.motion.paused, false);
assert.equal(snapshot.motionStatus.motion.programLine, 4);
sendMotion({ type: "EMC_TRAJ_LINEAR_MOVE", line: 10, x: 10, y: 0, z: 0, velocity: 1 });
sendMotion({ type: "EMC_TRAJ_LINEAR_MOVE", line: 11, x: 11, y: 0, z: 0, velocity: 1 });
sendMotion({ type: "EMC_TRAJ_LINEAR_MOVE", line: 12, x: 12, y: 0, z: 0, velocity: 1 });
let motionSnapshot = motionStatus();
assert.equal(motionSnapshot.commandQueueDepth, 3);
const queuedProgramLine = motionSnapshot.motion.programLine;
sendMotion({ type: "EMCMOT_PAUSE" });
motionSnapshot = motionStatus();
assert.equal(motionSnapshot.motion.paused, true);
assert.equal(motionSnapshot.commandQueueDepth, 3);
assert.equal(runtime._lcmot_step_servo(1000000, 20), 0);
motionSnapshot = motionStatus();
assert.equal(motionSnapshot.motion.programLine, queuedProgramLine);
assert.equal(motionSnapshot.commandQueueDepth, 3);
sendMotion({ type: "EMCMOT_STEP" });
assert.equal(runtime._lcmot_step_servo(1000000, 1), 0);
motionSnapshot = motionStatus();
assert.equal(motionSnapshot.motion.programLine, 10);
assert.equal(motionSnapshot.commandQueueDepth, 2);
assert.equal(motionSnapshot.motion.paused, true);
assert.equal(motionSnapshot.motion.stepping, false);
sendMotion({ type: "EMCMOT_RESUME" });
assert.equal(runtime._lcmot_step_servo(1000000, 2), 0);
motionSnapshot = motionStatus();
assert.equal(motionSnapshot.motion.paused, false);
assert.equal(motionSnapshot.motion.programLine, 12);
assert.equal(motionSnapshot.commandQueueDepth, 0);
send({ type: "EMC_TASK_PLAN_EXECUTE", mdi: "M428" });
assert.equal(runtime._lctask_run_cycles(10000000, 1000000, 1), 0);
snapshot = status();
assert.equal(snapshot.motionStatus.motion.switchkinsType, 1);
assert.equal(snapshot.halSnapshot.pins["motion.switchkins-type"].value, 1);
const xBeforeJog = snapshot.motionStatus.axis.x;
send({ type: "EMC_JOG_INCR", axis: "X", distance: 0.25, velocity: 60 });
assert.equal(runtime._lctask_run_cycles(10000000, 1000000, 1), 0);
snapshot = status();
assert.equal(snapshot.motionStatus.axis.x, 2.25);
assert.equal(snapshot.motionStatus.axis.x, xBeforeJog + 0.25);
assert.equal(snapshot.motionStatus.motion.teleopMode, 1);
send({ type: "EMC_TASK_ABORT" });
@@ -146,3 +234,6 @@ console.log("linuxcnc_task_runtime_smoke=ok");
console.log("task_status_from_linuxcnc_runtime=ok");
console.log("task_commands_drive_motion_runtime=ok");
console.log("mdi_jog_task_motion_hal_sync=ok");
console.log("pause_freezes_motion_queue=ok");
console.log("resume_restores_interp_resume_state=ok");
console.log("step_returns_to_paused=ok");

View File

@@ -74,6 +74,13 @@ try {
"tp_queue_final_depth=0",
"tp_queue_final_pos_near_end=1",
"tp_queue_final_pos=1,1,0",
"tp_pause_rc=0",
"tp_resume_rc=0",
"tp_paused_velocity_zero=1",
"tp_paused_position_frozen=1",
"tp_resume_done=1",
"tp_pause_resume_final_depth=0",
"tp_pause_resume_final_pos_near_end=1",
].join("\n"),
);
} finally {
@@ -161,3 +168,4 @@ try {
}
console.log("tp_wasm_node_smoke=ok");
console.log("tp_pause_resume_smoke=ok");