Files
cnc_wams/web-rtcp-5axis-sim-plan/working1/03-implementation-steps.md

489 lines
9.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 03 程序修复详细步骤
生成时间2026-06-22
本文档面向实际编码人员,按问题给出具体修改步骤。执行前建议先创建修复分支。
```bash
git status --short
git switch -c fix/web-rtcp-5axis-working1
```
## 1. D1自动挂接 LinuxCNC kinematics frame
### Step 1.1 增加期望 frame source 状态
文件:
```text
web-rtcp-5axis-sim-plan/app/src/state/store.js
```
`initialState` 增加字段:
```js
desiredFrameSourceMode: "fixture-ui-only",
```
保留现有:
```js
sourceMode
frameSourceMode
```
三者语义:
```text
desiredFrameSourceMode: 用户/运行时希望使用的 frame 来源
frameSourceMode: 当前 rtcpFrame 实际来源
sourceMode: UI 总体展示来源,可继续跟当前 frame source 同步
```
### Step 1.2 修改 ATTACH_KINEMATICS_RUNTIME
位置:
```text
store.js -> case "ATTACH_KINEMATICS_RUNTIME"
```
runtime loaded 时设置:
```js
desiredFrameSourceMode: "source-derived-kinematics-wasm",
```
runtime missing 时设置:
```js
desiredFrameSourceMode: "fixture-ui-only",
```
不要只依赖 `sourceMode` / `frameSourceMode`
### Step 1.3 修改 buildFrameForState
当前逻辑大意:
```js
const requestedSourceMode = state.frameSourceMode || state.sourceMode;
...
if (requestedSourceMode === "source-derived-kinematics-wasm") {
if (runtime loaded && !async) {
...
} else {
sourceMode = "fixture-ui-only";
}
}
```
建议改为:
```js
const requestedSourceMode =
state.desiredFrameSourceMode ||
state.frameSourceMode ||
state.sourceMode;
```
async runtime 已加载但尚未返回 frame 时,可以临时生成 fixture frame但必须带上可诊断原因不要覆盖 desired source。
### Step 1.4 修改 setState 写回策略
当前 `setState()` 中:
```js
sourceMode: frame.sourceMode,
frameSourceMode: frame.sourceMode,
```
建议改为:
```js
sourceMode: frame.sourceMode,
frameSourceMode: frame.sourceMode,
desiredFrameSourceMode: next.desiredFrameSourceMode || frame.sourceMode,
```
关键点:不要因为临时 fixture frame 把 `desiredFrameSourceMode` 变成 fixture。
### Step 1.5 修改 scheduleAsyncKinematicsRefresh
当前 guard 不应依赖已解析 frame source
```js
if (state.frameSourceMode !== "source-derived-kinematics-wasm") return null;
```
改为:
```js
if (state.desiredFrameSourceMode !== "source-derived-kinematics-wasm") return null;
if (!state.kinematicsRuntime?.loaded) return null;
if (!isAsyncKinematicsRuntime(state.kinematicsRuntime)) return null;
```
如果当前 frame 已经 ready 且 activeLine/axisPose/kinsType 未变化,可继续跳过刷新。
### Step 1.6 修改 refreshAsyncKinematicsFrame 成功写回
成功后确保:
```js
sourceMode: "source-derived-kinematics-wasm",
frameSourceMode: "source-derived-kinematics-wasm",
desiredFrameSourceMode: "source-derived-kinematics-wasm",
```
失败时:
```js
operatorMessage: `LinuxCNC kinematics refresh failed: ${error.message}`
```
并保留 retry 能力。
### Step 1.7 修改 main.js 初始化顺序
文件:
```text
web-rtcp-5axis-sim-plan/app/src/main.js
```
`attachDefaultKinematicsRuntime()` 已调用:
```js
await store.refreshKinematicsFrame(...)
```
修复后保留该调用,并在 profile/INI 变更订阅中runtime attach 完成后再次刷新:
```js
await attachDefaultKinematicsRuntime(...)
await store.refreshKinematicsFrame({ operatorMessage: "..." })
```
注意避免无限刷新。可通过 `asyncFrameRefreshSequence` 或 readiness 状态判断。
### Step 1.8 D1 测试
新增或更新测试:
```text
web-rtcp-5axis-sim-plan/tests/browser/gmoccapy_shell_smoke.html
```
或新增:
```text
web-rtcp-5axis-sim-plan/tests/browser/kinematics_auto_refresh_smoke.html
```
断言:
```js
await waitUntil(() => window.webRtcp5AxisSimulation.getState().sourceMode === "source-derived-kinematics-wasm")
assertText('[data-rtcp-diagnostic="boundary"]', 'linuxcnc_kinematics_wasm_c_abi')
assertText('[data-rtcp-diagnostic="kinematics-ready"]', 'ready')
```
## 2. D2修复 3D 预览可见性
### Step 2.1 修复 updateToolpathPreview 未定义变量
文件:
```text
web-rtcp-5axis-sim-plan/app/src/visualization/five-axis-scene.js
```
`updateToolpathPreview(preview, state)` 中补齐:
```js
const toolPosition = executionToolPosition(state, previewPoints);
const fitPoints = collectFitPoints(previewPoints, executedPoints, currentSegmentPoints, toolPosition);
const fitKey = [
previewPoints.length,
executedPoints.length,
currentSegmentPoints.length,
previewSourceMode(state),
state.programExecutionMotionIndex || 0,
state.programExecutionSampleIndex || 0,
].join(":");
```
确保 `updateToolExecutionMarker()` 使用同一个 `toolPosition`
### Step 2.2 增加常驻机床参考模型
新增函数:
```js
function createMachineReferenceModel() { ... }
function updateMachineReferenceModel(preview, state) { ... }
```
推荐对象:
```text
grid/table base: dark gray plane/box
X axis: red line
Y axis: green line
Z axis: blue line
rotary ring: cyan/yellow ring
tool holder: small cylinder/cone
TCP marker: existing sphere
```
`createScene()` 中:
```js
const machineModel = createMachineReferenceModel();
scene.add(machineModel.root);
```
在 preview 对象中保存:
```js
machineModel
```
`updateToolpathPreview()` 中:
```js
updateMachineReferenceModel(preview, state);
```
### Step 2.3 提高 fallback 可见性
`renderFallbackPreview()` 中,路径为空也要绘制:
```text
工作台矩形
XYZ 坐标轴
旋转中心
TCP 点
```
要求颜色和尺寸足够明显,避免黑底上不可见。
### Step 2.4 强化 canvas dataset
`exposePreviewDataset()` 已存在,修复后确保任意路径都稳定输出:
```text
data-three-ready="true"
data-three-renderer
data-three-scene-objects
data-three-path-points
data-three-tool-execution-marker
```
如果 fallback
```text
data-three-fallback-reason
```
如果 WebGL
```text
data-three-renderer="webgl"
```
### Step 2.5 D2 测试
新增 pixel 检查:
```js
const stats = canvasPixelStats(canvas)
assert(stats.nonBlackRatio > 0.02)
assert(stats.averageLuminance > 5)
```
同时检查:
```js
Number(canvas.dataset.threeSceneObjects) > 0
canvas.dataset.threeReady === "true"
```
建议覆盖 desktop 和 mobile viewport。
## 3. D3修复 HOME/JOG 坐标连续性
### Step 3.1 记录 pending JOG 上下文
文件:
```text
web-rtcp-5axis-sim-plan/app/src/state/store.js
```
`initialState` 增加:
```js
pendingJogCommand: null,
```
`case "JOG"` 的 task/HAL runtime 分支,发送命令前记录:
```js
setState({
pendingJogCommand: {
axis,
direction,
increment,
basePose: state.axisPose,
createdAtLine: state.activeLine,
},
operatorMessage: `task/HAL jog ${axis.toUpperCase()} ...`,
})
```
注意现有代码直接调用 `runTaskHalCommandSequence()`,需要避免两次 setState 引发顺序混乱。可把 pending context 作为 `runTaskHalCommandSequence()` 的 options 传入,最终在 command started patch 中写入。
### Step 3.2 给 task/HAL status 增加坐标系元数据
文件:
```text
web-rtcp-5axis-sim-plan/app/src/runtime/linuxcnc-task-hal-runtime.js
```
`ui` 对象中增加:
```js
axisPoseFrame: "task-local",
```
如果 runtime 能确定是 work pose则写
```js
axisPoseFrame: "work",
```
如果能计算增量,增加:
```js
axisPoseDelta: { x, y, z, a, b, c }
```
短期不能准确判断时,不要伪装成 work。
### Step 3.3 修改 applyTaskHalStatusPatch
当前:
```js
const axisPose = clampAxisPoseToProfile({
...state.axisPose,
...ui.axisPose,
}, state.profile);
```
改为单独函数:
```js
const axisPose = resolveTaskHalAxisPose(state, status);
```
建议实现:
```js
function resolveTaskHalAxisPose(state, status) {
const ui = status?.ui || {};
if (ui.axisPoseFrame === "work") {
return clampAxisPoseToProfile({ ...state.axisPose, ...ui.axisPose }, state.profile);
}
if (ui.axisPoseDelta) {
return addAxisDelta(state.axisPose, ui.axisPoseDelta, state.profile);
}
if (state.pendingJogCommand && isJogStatus(status)) {
const { axis, direction, increment, basePose } = state.pendingJogCommand;
return clampAxisPoseToProfile({
...basePose,
[axis]: Number(basePose[axis] || 0) + direction * increment,
}, state.profile);
}
if (!ui.axisPoseFrame && wouldResetNonZeroPoseToLocalZero(state.axisPose, ui.axisPose)) {
return state.axisPose;
}
return clampAxisPoseToProfile({ ...state.axisPose, ...ui.axisPose }, state.profile);
}
```
### Step 3.4 清理 pending JOG
`TASK_HAL_STATUS_APPLIED` 后,如果使用了 pending JOG
```js
pendingJogCommand: null
```
如果 command failed
```js
pendingJogCommand: null
```
### Step 3.5 HOME 同步
HOME 成功后UI 和 task/HAL runtime 必须同一坐标基准。短期可在 HOME fallback patch 中明确:
```js
axisPose: initialAxisPose
```
task/HAL HOME status 如果返回局部原点,不能覆盖 `initialAxisPose`,除非 status 标记 `axisPoseFrame="work"`
### Step 3.6 D3 测试
新增测试步骤:
```js
power on
manual
home
capture X/Y/Z
jog X+
assert X === previousX + jogIncrement
assert Y/Z unchanged
jog Y-
assert Y === previousY - jogIncrement
assert X/Z unchanged
```
同时验证 DRO 文本:
```js
document.querySelector('[data-region="dro"]').textContent
```
## 4. 本地验证命令
建议按顺序执行:
```bash
npm --prefix web-rtcp-5axis-sim-plan/app run build
node web-rtcp-5axis-sim-plan/tests/node/verify_rtcp_store.mjs
node web-rtcp-5axis-sim-plan/tests/node/verify_five_axis_session.mjs
node web-rtcp-5axis-sim-plan/tests/node/verify_linuxcnc_kinematics_runtime.mjs
node web-rtcp-5axis-sim-plan/tests/node/verify_linuxcnc_task_hal_runtime.mjs
```
如果项目已有 browser smoke
```bash
web-rtcp-5axis-sim-plan/tests/browser/verify_gmoccapy_shell_browser.sh
```
修复后再执行 QA 站点测试脚本或新增等价本地测试。