Add AC/BC RTCP programs and 3D machine manager
This commit is contained in:
@@ -683,11 +683,19 @@ export class SimSession {
|
||||
const joints = Array.isArray(current.state.joint_commanded) && current.state.joint_commanded.length === 5
|
||||
? [...current.state.joint_commanded]
|
||||
: [...this.xyzacKinematics.snapshot().joints];
|
||||
const selected = this.xyzacKinematics.select(mode, joints);
|
||||
// A switchkins button changes the coordinate interpretation of the
|
||||
// stopped machine. Preserve the physical joint sample and recompute
|
||||
// only the coordinate pose in the new kinematics. `select()` converts
|
||||
// the old pose back into the target mode, which changes joints and makes
|
||||
// an idle M429/M428 button appear to move the machine.
|
||||
const selected = this.xyzacKinematics.selectPhysical(mode, joints);
|
||||
if (selected.status !== "verified") return selected;
|
||||
this.xyzacProgramKinematicsMode = mode;
|
||||
if (typeof this.wasmMotion.setActiveKinematicsTag === "function") this.wasmMotion.setActiveKinematicsTag(mode);
|
||||
if (selected.pose && typeof this.wasmMotion.setPosition === "function") this.wasmMotion.setPosition(selected.pose);
|
||||
if (selected.pose && typeof this.wasmMotion.setPosition === "function") this.wasmMotion.setPosition(selected.pose, mode);
|
||||
if (selected.pose && this.xyzacProgram) {
|
||||
const synchronized = this.xyzacProgram.synchronizePosition(selected.pose);
|
||||
if (synchronized.status !== "verified") return synchronized;
|
||||
}
|
||||
return { ...selected, kinematics: this.xyzacKinematics.snapshot(), wasm_motion: this.wasmMotion.read() };
|
||||
}
|
||||
|
||||
@@ -1457,22 +1465,27 @@ export class SimSession {
|
||||
});
|
||||
}
|
||||
if (Number.isSafeInteger(input.simulation_tick) && input.simulation_tick >= this.tick) this.tick = input.simulation_tick;
|
||||
const pausedStep = input.kind === "SIM_STEP" && this.xyzacProgram && (this.task.state.state === "PAUSED" || this.xyzacProgram.snapshot().status === 3);
|
||||
const eventTick = input.kind === "SIM_STEP" && Number.isSafeInteger(input.payload?.cycles) && !pausedStep
|
||||
? this.tick + input.payload.cycles : this.tick;
|
||||
try {
|
||||
this.timeline.appendEvent(input.seq, eventTick, input.kind, input.payload ?? {});
|
||||
} catch (error) {
|
||||
if (text(input.operation_id)) this.operations.delete(input.operation_id);
|
||||
return this.error(input, "event_log", String(error?.message ?? error));
|
||||
}
|
||||
const coreEventResult = appendCoreEvent(this.core, input.seq, eventTick, input.kind, input.payload ?? {});
|
||||
if (coreEventResult !== 0) {
|
||||
if (text(input.operation_id)) this.operations.delete(input.operation_id);
|
||||
return this.error(input, "event_log", "core_event_append_failed");
|
||||
// SIM_STEP may stop partway through its requested cycles. Record its
|
||||
// actual end tick, never a future tick that poisons subsequent commands.
|
||||
let eventRecorded = false;
|
||||
const recordEvent = () => {
|
||||
if (eventRecorded) return;
|
||||
this.timeline.appendEvent(input.seq, this.tick, input.kind, input.payload ?? {});
|
||||
eventRecorded = true;
|
||||
const result = appendCoreEvent(this.core, input.seq, this.tick, input.kind, input.payload ?? {});
|
||||
if (result !== 0) throw new Error("core_event_append_failed");
|
||||
};
|
||||
if (input.kind !== "SIM_STEP") {
|
||||
try { recordEvent(); }
|
||||
catch (error) {
|
||||
if (text(input.operation_id)) this.operations.delete(input.operation_id);
|
||||
return this.error(input, "event_log", String(error?.message ?? error));
|
||||
}
|
||||
}
|
||||
|
||||
const finish = (response, status = "verified") => {
|
||||
try { recordEvent(); }
|
||||
catch (error) { return this.error(input, "event_log", String(error?.message ?? error)); }
|
||||
if (text(input.operation_id) && OPERATION_KINDS.has(input.kind)) {
|
||||
const operation = this.operations.get(input.operation_id);
|
||||
if (operation) {
|
||||
@@ -2174,8 +2187,26 @@ export class SimSession {
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
return finish(this.error(input, "scheduler", String(error?.message ?? error)), "failed");
|
||||
// The scheduler may have consumed a partial task cycle. Align all
|
||||
// transport clocks to that attempted tick and leave motion stopped.
|
||||
this.tick = this.scheduler.tick;
|
||||
this.task.setTick(this.tick);
|
||||
call(this.core, "sim_protocol_set_tick", this.tick);
|
||||
if (this.xyzacProgram) {
|
||||
this.wasmMotion.abort();
|
||||
this.pendingXyzacMotion = null;
|
||||
if (this.xyzacProgram.snapshot().status === 2) this.xyzacProgram.abort();
|
||||
if (this.task.state.state === "RUNNING") this.task.transition("STOPPED");
|
||||
}
|
||||
const reason = String(error?.message ?? error);
|
||||
const limit = reason === "motion_joint_limit";
|
||||
return finish(this.envelope("ERROR", input, {
|
||||
status: limit ? "blocked" : "error", code: limit ? "motion_limit" : "scheduler",
|
||||
message_key: limit ? "关节到达限位,运动已停止;可反向 Jog" : reason,
|
||||
reason, motion_stopped: Boolean(this.xyzacProgram), completed_cycles: this.scheduler.last_cycles,
|
||||
}), "failed");
|
||||
}
|
||||
recordEvent();
|
||||
const program = this.xyzacProgram ? this.xyzacProgram.snapshot() : this.program.loaded ? this.program.snapshot() : null;
|
||||
const execution_trace = program_steps
|
||||
.map((step) => ({
|
||||
@@ -2730,6 +2761,10 @@ export class SimSession {
|
||||
})();
|
||||
if (jog.status !== "verified") {
|
||||
const code = jog.code === "linuxcnc_tp_jog_-1217" ? "motion_limit_range" : jog.code === "linuxcnc_tp_jog_-1215" ? "motion_jog_nonfinite" : jog.code;
|
||||
if (code === "motion_limit_range") return finish(this.envelope("ERROR", input, {
|
||||
status: "blocked", code: "motion_limit", message_key: code,
|
||||
reason: "Jog 超出行程范围;请反向移动或减小增量", command: input.kind,
|
||||
}), "failed");
|
||||
return finish(this.error(input, "motion_queue", code), "failed");
|
||||
}
|
||||
return finish(this.envelope("COMMAND_RESULT", input, { status: "verified", command: input.kind, motion: this.wasmMotionProjection(), wasm_motion: this.wasmMotion.read(), motion_authority: "wasm", operation_id: input.operation_id ?? null }), "verified");
|
||||
|
||||
Reference in New Issue
Block a user