Preserve RTCP compensation across rotary jog stops
This commit is contained in:
86
scripts/test_trt_rtcp_jog_browser.mjs
Normal file
86
scripts/test_trt_rtcp_jog_browser.mjs
Normal file
@@ -0,0 +1,86 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { mkdir, writeFile } from "node:fs/promises";
|
||||
import { pathToFileURL } from "node:url";
|
||||
import { buildXyzacMachine, buildXyzbcMachine } from "../web/react/src/xyzac-machine-model.ts";
|
||||
|
||||
const { chromium } = await import(pathToFileURL(process.env.PLAYWRIGHT_MODULE).href);
|
||||
const output = new URL("../coverage/trt-parametric/", import.meta.url);
|
||||
await mkdir(output, { recursive: true });
|
||||
const browser = await chromium.launch({ executablePath: "/usr/bin/google-chrome", headless: true, args: ["--no-sandbox", "--use-angle=swiftshader", "--enable-unsafe-swiftshader"] });
|
||||
const page = await browser.newPage({ viewport: { width: 1440, height: 1000 } });
|
||||
const errors = []; page.on("pageerror", (error) => errors.push(error.message));
|
||||
const control = (id) => page.locator(`[data-axis-control="${id}"]`);
|
||||
const machine = page.locator(".xyzac-machine-view");
|
||||
const report = { report_id: "trt-rtcp-jog-browser-v1", status: "running", machines: [] };
|
||||
const sample = () => machine.evaluate((element) => ({
|
||||
joints: JSON.parse(element.dataset.xyzacJoints), offsets: JSON.parse(element.dataset.xyzacOffsets),
|
||||
tick: Number(element.dataset.xyzacTick), rendered_tick: Number(element.dataset.xyzacRenderedTick), tool_tip: JSON.parse(element.dataset.xyzacToolTip),
|
||||
}));
|
||||
const rendered = () => page.waitForFunction(() => {
|
||||
const e = document.querySelector(".xyzac-machine-view"); return e && e.dataset.xyzacTick === e.dataset.xyzacRenderedTick;
|
||||
});
|
||||
const jog = async (axis, delta, index) => {
|
||||
await control(`manual-axis-${axis}`).check();
|
||||
const before = await sample();
|
||||
const button = await control("manual-jog-positive").boundingBox();
|
||||
await page.mouse.move(button.x + button.width / 2, button.y + button.height / 2); await page.mouse.down();
|
||||
await page.waitForFunction(({ index, initial, delta }) => {
|
||||
const e = document.querySelector(".xyzac-machine-view");
|
||||
return JSON.parse(e.dataset.xyzacJoints)[index] >= initial + delta;
|
||||
}, { index, initial: before.joints[index], delta });
|
||||
await rendered(); const moving = await sample();
|
||||
await page.mouse.up();
|
||||
await page.waitForFunction(() => document.querySelector(".command-status")?.textContent?.includes("JOG_STOP acknowledged") || [...document.querySelectorAll("span")].some((s) => s.textContent === "JOG_STOP acknowledged"));
|
||||
await rendered();
|
||||
return { axis, before, moving, stopped: await sample() };
|
||||
};
|
||||
try {
|
||||
await page.goto(process.env.XYZAC_PANEL_URL ?? "http://127.0.0.1:5174/");
|
||||
await page.waitForFunction(() => document.querySelector("main")?.dataset.axisProgramLoading === "false");
|
||||
for (const coordinates of ["XYZAC", "XYZBC"]) {
|
||||
if (coordinates === "XYZBC") {
|
||||
await control("toolbar-power").click();
|
||||
await page.waitForFunction(() => !document.querySelector('.trt-geometry input[aria-label="x-rot-point"]').disabled);
|
||||
await control("machine-type-select").selectOption({ label: "XYZBC TRT" });
|
||||
await page.waitForFunction(() => document.querySelector(".xyzac-machine-view")?.dataset.xyzacModelId === "xyzbc-trt" && document.querySelector("main")?.dataset.axisProgramLoading === "false");
|
||||
}
|
||||
await control("toolbar-power").click(); await control("manual-home-all").click();
|
||||
await page.waitForFunction(() => !document.querySelector('[data-axis-control="switchkins-1"]').disabled);
|
||||
// Move off the rotary centre before enabling TCP, to make C compensation visible.
|
||||
await jog("x", 4, 0); await jog("y", 3, 1);
|
||||
await control("switchkins-1").click();
|
||||
await page.waitForFunction(() => document.querySelector('[data-axis-control="switchkins-1"]').getAttribute("aria-pressed") === "true");
|
||||
await rendered();
|
||||
const initial = await sample();
|
||||
const model = coordinates === "XYZAC" ? buildXyzacMachine() : buildXyzbcMachine();
|
||||
model.update(initial); model.machine.updateMatrixWorld(true);
|
||||
const target = model.workOrigin.worldToLocal(model.toolTip.getWorldPosition(model.workOrigin.position.clone()));
|
||||
const rows = [];
|
||||
for (const axis of [coordinates[3].toLowerCase(), "c", coordinates[3].toLowerCase(), "c"]) {
|
||||
const row = await jog(axis, 2, axis === "c" ? 4 : 3);
|
||||
assert.equal(await control("switchkins-1").getAttribute("aria-pressed"), "true");
|
||||
assert.ok(row.stopped.joints.slice(0, 3).some((v, i) => Math.abs(v - row.before.joints[i]) > 1e-5), `${coordinates} ${axis}: missing visible XYZ compensation`);
|
||||
for (const phase of ["moving", "stopped"]) {
|
||||
const state = row[phase]; model.update(state); model.machine.updateMatrixWorld(true);
|
||||
const point = model.workOrigin.localToWorld(target.clone());
|
||||
const tip = model.toolTip.getWorldPosition(target.clone());
|
||||
state.tcp_error = tip.distanceTo(point);
|
||||
assert.ok(state.tcp_error < 1e-7, `${coordinates} ${axis} ${phase}: ${state.tcp_error}`);
|
||||
if (phase === "stopped") state.tool_tip.forEach((v, i) => assert.ok(Math.abs(v - tip.toArray()[i]) < 1e-7, "rendered tool tip must match the Worker joints"));
|
||||
}
|
||||
rows.push(row);
|
||||
}
|
||||
await page.screenshot({ path: new URL(`rtcp-jog-${coordinates.toLowerCase()}.png`, output).pathname, fullPage: true });
|
||||
model.dispose(); report.machines.push({ coordinates, rows });
|
||||
}
|
||||
assert.deepEqual(errors, []); report.status = "verified";
|
||||
} catch (error) {
|
||||
report.status = "failed"; report.error = String(error.stack ?? error);
|
||||
await page.screenshot({ path: new URL("rtcp-jog-failure.png", output).pathname, fullPage: true });
|
||||
throw error;
|
||||
} finally {
|
||||
report.browser_errors = errors;
|
||||
await writeFile(new URL("rtcp-jog-browser.report.json", output), JSON.stringify(report, null, 2) + "\n");
|
||||
await browser.close();
|
||||
}
|
||||
console.log(JSON.stringify({ report_id: report.report_id, status: report.status, machines: report.machines.map((m) => ({ coordinates: m.coordinates, jogs: m.rows.length, max_tcp_error: Math.max(...m.rows.flatMap((r) => [r.moving.tcp_error, r.stopped.tcp_error])) })), browser_errors: errors }));
|
||||
Reference in New Issue
Block a user