Files
KDL_WORK/kdl-wasm/web/app/virtual-controller.js
2026-06-28 08:20:33 +08:00

141 lines
4.5 KiB
JavaScript

(function () {
const root = document.querySelector(".workbench");
const fields = new Map(
Array.from(document.querySelectorAll("[data-field]")).map((item) => [item.dataset.field, item])
);
const tabButtons = Array.from(document.querySelectorAll("[data-tab]"));
const sources = {
grl: "proc main()\n run_path pick_place\nend",
abb: "MODULE A120Smoke\n PROC main()\n MoveJ home,v100,fine,tool0;\n ENDPROC\nENDMODULE",
fanuc: "/PROG A120SMOKE\n/MN\n 1:J P[1] 40% FINE ;\n/END",
kuka: "DEF A120SMOKE()\n PTP HOME\nEND"
};
const state = {
command: "ready",
mode: "auto",
motors: "on",
pc: 0,
joints: [0, 0, 0, 0, 0, 0],
tcp: [0, 0, 580, 0, 0, 0],
di1: false,
do1: false,
wait: "none",
queue: [],
trace: ["ready"],
diagnostics: ["ready"],
report: "A120-REPORT",
tab: "grl"
};
function formatArray(values) {
return `[${values.map((value) => Number(value).toFixed(value % 1 === 0 ? 0 : 2)).join(", ")}]`;
}
function setField(name, value) {
const item = fields.get(name);
if (item) item.textContent = value;
}
function render() {
root?.setAttribute("data-last-command", state.command);
root?.setAttribute("data-running", String(state.command === "running"));
setField("state", state.command);
setField("mode", state.mode);
setField("motors", state.motors);
setField("pc", `main:${state.pc}`);
setField("joints", formatArray(state.joints));
setField("tcp", formatArray(state.tcp));
setField("log", state.trace.at(-1) ?? "ready");
setField("diagnostics", state.diagnostics.at(-1) ?? "ready");
setField("io", `do[1]=${state.do1}, di[1]=${state.di1}`);
setField("wait", state.wait);
setField("queue", state.queue.length ? state.queue.join(" -> ") : "empty");
setField("trace", `${state.trace.length} events`);
setField("reports", state.report);
setField("editor", sources[state.tab]);
for (const button of tabButtons) {
button.setAttribute("aria-pressed", String(button.dataset.tab === state.tab));
}
}
function pushTrace(message) {
state.trace.push(message);
state.diagnostics.push(message);
}
function advanceProgram(stepSize) {
state.pc = Math.min(state.pc + stepSize, 4);
state.joints = state.joints.map((value, index) => Number((value + (index + 1) * 1.5 * stepSize).toFixed(2)));
state.tcp = [
Number((state.tcp[0] + 12 * stepSize).toFixed(2)),
Number((state.tcp[1] + 4 * stepSize).toFixed(2)),
state.tcp[2],
state.tcp[3],
state.tcp[4],
state.tcp[5]
];
}
function handleCommand(command) {
state.command = command === "run" ? "running" : command;
if (command === "load") {
state.pc = 0;
state.queue = ["movej home", "run_path pick_place"];
state.wait = "none";
pushTrace("program loaded");
} else if (command === "run") {
advanceProgram(2);
state.do1 = true;
state.wait = state.di1 ? "satisfied" : "waiting di[1]";
state.queue = state.di1 ? ["movel place"] : ["wait di[1]", "movel place"];
pushTrace(state.di1 ? "running path" : "waiting for di[1]");
} else if (command === "pause") {
pushTrace("program paused");
} else if (command === "step") {
state.command = "paused";
advanceProgram(1);
pushTrace(`stepped to main:${state.pc}`);
} else if (command === "stop") {
state.queue = [];
pushTrace("program stopped");
} else if (command === "reset") {
state.command = "ready";
state.pc = 0;
state.joints = [0, 0, 0, 0, 0, 0];
state.tcp = [0, 0, 580, 0, 0, 0];
state.do1 = false;
state.wait = "none";
state.queue = [];
pushTrace("controller reset");
} else if (command === "export") {
state.report = "A120-REPORT exported";
pushTrace("delivery package exported");
}
render();
}
for (const button of document.querySelectorAll("[data-command]")) {
button.addEventListener("click", () => handleCommand(button.dataset.command ?? "ready"));
}
for (const button of tabButtons) {
button.addEventListener("click", () => {
state.tab = button.dataset.tab ?? "grl";
pushTrace(`${state.tab.toUpperCase()} source selected`);
render();
});
}
document.querySelector("[data-io='di1']")?.addEventListener("click", () => {
state.di1 = !state.di1;
state.wait = state.di1 ? "satisfied" : "waiting di[1]";
pushTrace(`di[1]=${state.di1}`);
render();
});
render();
})();