Upload project files
This commit is contained in:
140
kdl-wasm/web/app/virtual-controller.js
Normal file
140
kdl-wasm/web/app/virtual-controller.js
Normal file
@@ -0,0 +1,140 @@
|
||||
(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();
|
||||
})();
|
||||
Reference in New Issue
Block a user