Add AC/BC RTCP programs and 3D machine manager

This commit is contained in:
2026-09-20 12:31:12 +08:00
parent 1c1e5f9672
commit 8aab531b02
363 changed files with 53213 additions and 58 deletions

View File

@@ -72,11 +72,14 @@ export class WasmLinuxcncTp {
if (blending !== 0) throw new Error(`linuxcnc_tp_blend_${blending}`);
}
setPosition(value) {
setPosition(value, kinematicsMode = this.activeTag) {
if (!this.available) return this.read();
this.core.HEAPF64.set(poseArray(value), this.posePointer / 8);
const result = call(this.core, "sim_linuxcnc_tp_set_position", "number", ["number", "number"], [this.planner, this.posePointer]);
if (result !== 0) throw new Error(`linuxcnc_tp_set_position_${result}`);
// Publish the pose and its coordinate interpretation together. Reading
// between these updates would inverse-solve an old pose in a new mode.
this.activeTag = Number(kinematicsMode);
return this.read();
}
@@ -112,7 +115,20 @@ export class WasmLinuxcncTp {
setAxisLimit(axis, minimum, maximum) { if (!this.available) return this.read(); const result = call(this.core, "sim_linuxcnc_tp_set_axis_limit", "number", ["number", "number", "number", "number"], [this.planner, Number(axis), Number(minimum), Number(maximum)]); if (result !== 0) throw new Error(`linuxcnc_tp_axis_limit_${result}`); return this.read(); }
jog(axis, direction, increment, tag = 0) {
if (!this.available) return { status: "blocked", code: "linuxcnc_tp_unavailable" };
const result = call(this.core, "sim_linuxcnc_tp_jog", "number", ["number", "number", "number", "number", "number"], [this.planner, Number(axis), Number(direction), Number(increment), Number(tag)]);
const coordinate = "xyzabcuvw"[axis];
// Identity and rotary coordinates map directly to physical joints. Apply
// both INI constraints to the native jog target without changing normal
// coordinate limits (RTCP XYZ has a different physical interpretation).
const jointLimit = this.kinematics?.options?.limits?.[coordinate];
const directJoint = this.activeTag !== 1 || axis >= 3;
let savedLimits = null;
if (directJoint && jointLimit) {
savedLimits = [0, 1].map((maximum) => call(this.core, "sim_linuxcnc_tp_axis_limit", "number", ["number", "number", "number"], [this.planner, axis, maximum]));
this.setAxisLimit(axis, Math.max(savedLimits[0], jointLimit[0]), Math.min(savedLimits[1], jointLimit[1]));
}
let result;
try { result = call(this.core, "sim_linuxcnc_tp_jog", "number", ["number", "number", "number", "number", "number"], [this.planner, Number(axis), Number(direction), Number(increment), Number(tag)]); }
finally { if (savedLimits) this.setAxisLimit(axis, ...savedLimits); }
if (result !== 0) return { status: "error", code: `linuxcnc_tp_jog_${result}` };
// The native jog tag is a segment ID, not a kinematics mode. Replace any
// earlier program-line mapping with this jog's current coordinate frame.
@@ -187,9 +203,27 @@ export class WasmLinuxcncTp {
step() {
if (!this.available) return { status: "blocked", code: "linuxcnc_tp_unavailable" };
if (this.controls.paused) return { status: "error", code: "linuxcnc_tp_paused" };
const before = this.read().state;
const result = call(this.core, "sim_linuxcnc_tp_step", "number", ["number"], [this.planner]);
if (result !== 0) return { status: "error", code: `linuxcnc_tp_step_${result}` };
const state = this.read();
let state;
try {
state = this.read();
if (this.kinematics && state.status === "verified") {
const checked = this.kinematics.forward(state.state.joint_commanded);
if (checked.status !== "verified") throw new Error(checked.code);
}
} catch (error) {
// Native IK/FK rejects a physical joint limit. Keep the last valid
// servo position, discard the unsafe remainder, and permit retreat.
if (!String(error?.message).endsWith("_-702")) throw error;
call(this.core, "sim_linuxcnc_tp_abort", "number", ["number"], [this.planner]);
this.segmentTags.clear(); this.lastActiveId = 0; this.queueDepthOverride = null;
this.executionState = 3;
const stopped = this.setPosition(before.position, before.active_tag);
this.kinematics.forward(stopped.state.joint_commanded);
throw new Error("motion_joint_limit");
}
if (state.status === "verified") {
const targetJoints = this.commandedJoints(state.state.position, state.state.active_tag);
state.state.joint_commanded = targetJoints;