diff --git a/docs/linuxcnc-axis-web-control-panel-source-logic.md b/docs/linuxcnc-axis-web-control-panel-source-logic.md index 4e6c57d..3cbd70e 100644 --- a/docs/linuxcnc-axis-web-control-panel-source-logic.md +++ b/docs/linuxcnc-axis-web-control-panel-source-logic.md @@ -825,9 +825,10 @@ machine/operation values remain on the main element as data attributes for browser diagnostics; no control command or gate changes with this layout. Home Joint, the numeric joint selector and Home All are rendered in the Manual tab's action area; the standalone Machine sequence heading is not rendered. -The XYZAC position summary and preview HUD display only X/Y/Z/A/C; J0-J4 -position readouts are omitted. Numeric homing target selection and canonical -joint data remain available to the existing control logic. +The XYZAC position summary and both preview HUDs display X/Y/Z/A/C together +with the five authoritative J0-J4 position readouts. Numeric homing target +selection and canonical joint data remain available to the existing control +logic. ```text HOME(all/joint) diff --git a/web/react/src/XyzacMachineView.tsx b/web/react/src/XyzacMachineView.tsx index 56f10f2..4c90dbb 100644 --- a/web/react/src/XyzacMachineView.tsx +++ b/web/react/src/XyzacMachineView.tsx @@ -189,7 +189,7 @@ export function XyzacMachineView({ visual, toolpath, view = "p", zoom = 1, rotat {controllerButton("rotateUp", "Rotate upward", undefined, "\u2b06")}{controllerButton("rotateDown", "Rotate downward", undefined, "\u2b07")} {controllerButton("reset", "Reset machine view", undefined, "\u21ba")}{controllerButton("tool", "Tool close-up", "tool_axis_z.gif")} -
{visual.authoritative ? `XYZAC TRT\n${visual.joints.map((value, index) => `${["X", "Y", "Z", "A", "C"][index]} ${value.toFixed(3)}`).join("\n")}${showVelocity ? `\nV ${Number(visual.velocityMmMin ?? 0).toFixed(1)}` : ""}` : "XYZAC TRT\nWASM state pending"}
+
{visual.authoritative ? `XYZAC TRT\n${visual.joints.map((value, index) => `${["X", "Y", "Z", "A", "C"][index]} ${value.toFixed(3)}`).join("\n")}\n${visual.joints.map((value, index) => `J${index} ${value.toFixed(3)}`).join("  ")}${showVelocity ? `\nV ${Number(visual.velocityMmMin ?? 0).toFixed(1)}` : ""}` : "XYZAC TRT\nWASM state pending"}
; } diff --git a/web/react/src/XyzacToolPreview.tsx b/web/react/src/XyzacToolPreview.tsx index 17b6df5..7abd252 100644 --- a/web/react/src/XyzacToolPreview.tsx +++ b/web/react/src/XyzacToolPreview.tsx @@ -404,7 +404,7 @@ export function XyzacToolPreview({ visual, view = "p", zoom = 1, rotateMode = fa element.dataset.xyzacLimitsVisible = String(limitGrid.visible); element.dataset.xyzacExtentsVisible = String(extents.visible); element.dataset.xyzacOffset = JSON.stringify(offset); - if (hudRef.current) hudRef.current.textContent = `TOOL PREVIEW\nX ${Number(renderedPose.x).toFixed(3)} Y ${Number(renderedPose.y).toFixed(3)} Z ${Number(renderedPose.z).toFixed(3)}\nA ${Number(renderedPose.a).toFixed(3)} C ${Number(renderedPose.c).toFixed(3)}`; + if (hudRef.current) hudRef.current.textContent = `TOOL PREVIEW\nX ${Number(renderedPose.x).toFixed(3)} Y ${Number(renderedPose.y).toFixed(3)} Z ${Number(renderedPose.z).toFixed(3)}\nA ${Number(renderedPose.a).toFixed(3)} C ${Number(renderedPose.c).toFixed(3)}\nJ0 ${Number(renderedJoints[0] ?? 0).toFixed(3)} J1 ${Number(renderedJoints[1] ?? 0).toFixed(3)} J2 ${Number(renderedJoints[2] ?? 0).toFixed(3)}\nJ3 ${Number(renderedJoints[3] ?? 0).toFixed(3)} J4 ${Number(renderedJoints[4] ?? 0).toFixed(3)}`; if (layer.showVelocity && hudRef.current) hudRef.current.textContent += `\nV ${Number(state.velocityMmMin ?? 0).toFixed(1)} mm/min`; controls.mouseButtons.LEFT = rotateRef.current ? THREE.MOUSE.ROTATE : THREE.MOUSE.PAN; controls.update(); renderer.render(scene, camera); frame = requestAnimationFrame(render); @@ -417,7 +417,7 @@ export function XyzacToolPreview({ visual, view = "p", zoom = 1, rotateMode = fa const helixCount = visual.toolpath.filter((segment) => (segment as { kind?: string }).kind === "helix").length; const sampleCount = visual.toolpath.reduce((count, segment) => count + (Array.isArray((segment as { samples?: unknown[] }).samples) ? (segment as { samples: unknown[] }).samples.length : 0), 0); const controllerButton = (action: string, label: string, glyph: string) => ["zoomIn", "zoomOut"].includes(action) ? null : ; - return
{controllerButton("zoomIn", "Zoom in", "+")}{controllerButton("zoomOut", "Zoom out", "-")}
{visual.authoritative ? `TOOL PREVIEW\nX ${Number(pose.x).toFixed(3)}  Y ${Number(pose.y).toFixed(3)}  Z ${Number(pose.z).toFixed(3)}\nA ${Number(pose.a).toFixed(3)}  C ${Number(pose.c).toFixed(3)}` : "TOOL PREVIEW\nWASM state pending"}
; + return
{controllerButton("zoomIn", "Zoom in", "+")}{controllerButton("zoomOut", "Zoom out", "-")}
{visual.authoritative ? `TOOL PREVIEW\nX ${Number(pose.x).toFixed(3)}  Y ${Number(pose.y).toFixed(3)}  Z ${Number(pose.z).toFixed(3)}\nA ${Number(pose.a).toFixed(3)}  C ${Number(pose.c).toFixed(3)}\nJ0 ${Number(visual.joints[0] ?? 0).toFixed(3)}  J1 ${Number(visual.joints[1] ?? 0).toFixed(3)}  J2 ${Number(visual.joints[2] ?? 0).toFixed(3)}\nJ3 ${Number(visual.joints[3] ?? 0).toFixed(3)}  J4 ${Number(visual.joints[4] ?? 0).toFixed(3)}` : "TOOL PREVIEW\nWASM state pending"}
; } export function XyzacToolPreviewFromSnapshot({ snapshot, ...props }: Omit & { snapshot: XyzacVisualSource | null | undefined }) { diff --git a/web/react/src/XyzacTrtPanel.tsx b/web/react/src/XyzacTrtPanel.tsx index fdc54a3..0bb2009 100644 --- a/web/react/src/XyzacTrtPanel.tsx +++ b/web/react/src/XyzacTrtPanel.tsx @@ -24,7 +24,7 @@ export function XyzacManualPanel({ view }: { view: XyzacPanelView }) { return
XYZAC authority{view.kinematics?.linear_units ?? "mm"} / {view.kinematics?.angular_units ?? "deg"}
- {axes.map((axis) =>
{axis.toUpperCase()}{pose ? Number(pose[axis] ?? Number.NaN).toFixed(axis === "a" || axis === "c" ? 3 : 4) : "-"}
)} + {axes.map((axis, index) =>
{axis.toUpperCase()}{pose ? Number(pose[axis] ?? Number.NaN).toFixed(axis === "a" || axis === "c" ? 3 : 4) : "-"}J{index} {view.joints.length === 5 ? Number(view.joints[index]).toFixed(4) : "-"}
)}
Tool {view.kinematics ? Number(view.kinematics.offsets.tool_offset).toFixed(3) : "-"}Y offset {view.kinematics ? Number(view.kinematics.offsets.y_offset).toFixed(3) : "-"}Z offset {view.kinematics ? Number(view.kinematics.offsets.z_offset).toFixed(3) : "-"}
; diff --git a/web/react/src/test_xyzac_threejs.mjs b/web/react/src/test_xyzac_threejs.mjs index e03070b..835731d 100644 --- a/web/react/src/test_xyzac_threejs.mjs +++ b/web/react/src/test_xyzac_threejs.mjs @@ -5,6 +5,8 @@ import * as THREE from "three"; import { buildXyzacMachine } from "./xyzac-machine-model.ts"; const source = await readFile(new URL("./XyzacMachineView.tsx", import.meta.url), "utf8") + await readFile(new URL("./xyzac-machine-model.ts", import.meta.url), "utf8"); +const panelSource = await readFile(new URL("./XyzacTrtPanel.tsx", import.meta.url), "utf8"); +const toolSource = await readFile(new URL("./XyzacToolPreview.tsx", import.meta.url), "utf8"); const adapter = await readFile(new URL("./xyzac-visual-adapter.ts", import.meta.url), "utf8"); const snapshot = { schema: "axis-panel-snapshot.v1", @@ -45,6 +47,11 @@ assert.deepEqual(XYZAC_MACHINE_GROUPS, ["xyzac-machine", "table-x", "saddle-y", for (const token of ["table-x", "saddle-y", "spindle-z", "tilt-a", "rotate-c", "tool-offset", "tableX.position.x = -tableXJoint * MM", "saddle.position.z = -saddleYJoint * MM", "zslide.position.y = (200 - spindleZJoint) * MM", "tilt.rotation.x = -tiltAJoint * DEG", "rotate.rotation.y = -rotateCJoint * DEG", "tool.position.y = -state.offsets.tool_offset * MM", "data-xyzac-tick", "data-xyzac-state-hash", "data-xyzac-active-segment", "data-xyzac-joints", "data-xyzac-offsets"]) assert.ok(source.includes(token), token); for (const forbidden of [/accept\s*\(/, /postMessage\s*\(/, /_sim_/, /_malloc/, /navigator\.storage/, /HAL_SET/, /KINEMATICS_SELECT/]) assert.equal(forbidden.test(source), false, String(forbidden)); assert.ok(adapter.includes("source: \"linuxcnc-wasm-worker\"")); +for (const token of ["J0", "J1", "J2", "J3", "J4"]) { + assert.ok(panelSource.includes("J{index}"), "panel joint label template"); + assert.ok(toolSource.includes(token), `tool preview ${token}`); + assert.ok(source.includes("J${index}"), "machine preview joint label template"); +} const model = buildXyzacMachine(); const original = structuredClone(visual); const zero = { joints: [0, 0, 0, 0, 0], offsets: { x_rot_point: 0, y_offset: 20, z_offset: 10, tool_offset: 0 } };