Files
cnc_wams/web-rtcp-5axis-sim-plan/working1/02-repair-plan.md

241 lines
6.6 KiB
Markdown
Raw 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.
# 02 修复总体方案
生成时间2026-06-22
## 1. 修复原则
1. 不用 JavaScript 重写 LinuxCNC 运动学语义。
2. RTCP/TCP frame 必须优先来自 LinuxCNC source-derived kinematics WASM。
3. 视觉层只能消费 runtime frame、canonical motion、task/HAL feedback不生成 G-code/CNC 语义。
4. JOG/HOME/DRO 必须明确坐标系,不允许 task-local 坐标无标记覆盖 UI work pose。
5. 每项修复必须新增或更新测试,先复现问题,再验证修复。
## 2. 修复优先级
| 优先级 | 问题 | 原因 |
| --- | --- | --- |
| P0 | D1 RTCP/运动学边界自动挂接 | 影响语义边界可信度,且修复面较集中 |
| P0 | D2 3D 预览可见性 | 影响产品第一视觉和核心仿真价值 |
| P1 | D3 HOME/JOG 坐标连续性 | 影响手动操作正确性,需谨慎处理坐标系 |
## 3. D1 修复方案
### 目标状态
页面稳定加载后无需手动调用,自动达到:
```text
state.sourceMode=source-derived-kinematics-wasm
state.frameSourceMode=source-derived-kinematics-wasm
state.rtcpFrame.semanticBoundary=linuxcnc_kinematics_wasm_c_abi
data-rtcp-diagnostic="kinematics-ready" -> ready
data-rtcp-diagnostic="boundary" -> linuxcnc_kinematics_wasm_c_abi
```
### 推荐设计
把“期望使用的 frame source”和“当前已经解析出的 frame source”分开
```text
desiredFrameSourceMode: source-derived-kinematics-wasm | fixture-ui-only
frameSourceMode: 当前 rtcpFrame.sourceMode
```
或者在不新增字段的情况下,至少保证 `setState()` 不用异步 runtime 的临时 fixture frame 覆盖 kinematics 请求状态。
推荐更清晰的做法:
1. 新增 `desiredFrameSourceMode`
2. `ATTACH_KINEMATICS_RUNTIME` 成功后设置:
```js
desiredFrameSourceMode: "source-derived-kinematics-wasm"
```
3. `buildFrameForState()` 对 async worker 不直接降级修改 desired state只生成临时 fixture frame并标记
```text
asyncFrameRefreshPending=true
```
4. `scheduleAsyncKinematicsRefresh()` 判断:
```js
state.kinematicsRuntime?.loaded &&
state.desiredFrameSourceMode === "source-derived-kinematics-wasm"
```
而不是依赖已经被 fixture 覆盖的 `frameSourceMode`
5. `refreshAsyncKinematicsFrame()` 成功后写入:
```js
sourceMode: "source-derived-kinematics-wasm"
frameSourceMode: "source-derived-kinematics-wasm"
desiredFrameSourceMode: "source-derived-kinematics-wasm"
```
### 防回退要求
任何以下动作后都不能把 frame 永久退回 fixture
```text
ATTACH_INI_CONFIG
SET_PROFILE
MACHINE_FILE_STAGING_COMPLETE
TASK_HAL_STATUS_APPLIED
LOAD_PROGRAM
LOAD_LINUXCNC_GCODE_SOURCE
HOME/JOG/RUN/STEP
```
如果某次 frame 刷新失败,应显示错误并保留 retry 能力,不能静默永久降级。
## 4. D2 修复方案
### 目标状态
首屏不加载任何用户程序时也必须可见:
```text
机床基准/工作台
XYZ 坐标轴
旋转轴标识
刀具/TCP marker
预览路径或占位路径
```
WebGL 不可用时2D fallback 也必须绘制清晰的轴线、路径和 TCP 点。
### 推荐设计
1. 修复 `updateToolpathPreview()` 中未定义变量风险:
```js
const toolPosition = executionToolPosition(state, previewPoints);
const fitPoints = collectFitPoints(previewPoints, executedPoints, currentSegmentPoints, toolPosition);
const fitKey = buildFitKey(...);
```
2.`createScene()` 中加入常驻机床模型:
```text
machineRoot
tableGroup
rotaryA/rotaryB/rotaryC visual rings
toolHolder
axisHelper
grid/reference plane
```
3. 增加单独函数:
```js
createMachineReferenceModel()
updateMachineReferenceModel(preview, state)
```
4. `renderFallbackPreview()` 中绘制:
```text
灰色工作台矩形
绿色/红色/蓝色 XYZ 轴
青色 TCP 点
亮色刀路 polyline
明显的 fallback 标签和点数
```
5. `exposePreviewDataset()` 必须稳定输出:
```text
data-three-ready=true
data-three-renderer=webgl | 2d-fallback
data-three-scene-objects > 0
data-three-path-points > 0 或 data-three-tool-execution-marker=true
```
### 可见性门槛
自动化测试应检查 canvas 像素,不只检查 DOM
```text
nonBlackRatio > 0.02
averageLuminance > 5
```
## 5. D3 修复方案
### 目标状态
HOME 后执行 JOG
```text
after HOME: X=43, Y=-32.15, Z=-11.306
after JOG X+: X=44, Y=-32.15, Z=-11.306
after JOG Y-: X=44, Y=-33.15, Z=-11.306
```
实际增量以 `state.machine.jogIncrement` 为准。
### 推荐设计
必须明确 task/HAL status 中 `ui.axisPose` 的坐标系。
推荐新增字段:
```js
ui.axisPoseFrame = "work" | "machine" | "task-local" | "joint-local"
ui.axisPoseDelta = { x, y, z, a, b, c } // JOG 增量可选
```
处理规则:
1. 如果 `axisPoseFrame === "work"`,可直接覆盖 UI work pose。
2. 如果 `axisPoseFrame === "task-local"` 且本次 motion type 是 JOG优先使用 `axisPoseDelta` 加到当前 state.axisPose。
3. 如果没有 frame 标记,不允许直接覆盖非零 UI pose必须保守保留旧 pose 或走 fallback 增量。
4. HOME 命令要把 task/HAL runtime 的参考 pose 与 UI HOME pose 同步,或者返回 `axisPoseFrame="work"`
### 短期修复方案
如果 task/HAL runtime 暂时不能增加 frame 元数据,可在 store 层先做保护:
```text
当 status motion type 为 JOG 且 ui.axisPose 接近局部原点时,
不要整体覆盖 state.axisPose
改用本次 JOG action 的 axis/direction/increment 计算 UI pose。
```
为了实现这点store 需要在发送 task/HAL JOG 命令时记录 pending jog context
```js
pendingJogCommand: { axis, direction, increment, basePose }
```
收到 `TASK_HAL_STATUS_APPLIED` 后:
```js
axisPose = {
...pendingJogCommand.basePose,
[axis]: pendingJogCommand.basePose[axis] + direction * increment
}
```
这是短期 UI 连续性修复;长期仍应让 runtime 明确坐标系。
## 6. 风险控制
| 风险 | 控制方式 |
| --- | --- |
| D1 修复导致 fixture fallback 不可用 | 保留 fallback但作为显式错误/降级状态,不覆盖 desired frame source |
| D2 加机床模型影响性能 | 常驻模型低面数,路径点仍受 `MAX_TOOLPATH_POINTS` 限制 |
| D3 坐标修复与真实 task/HAL 状态冲突 | 用 `axisPoseFrame` 标记,避免无标记状态直接覆盖 |
| 测试只在 headless 下通过 | 同时跑本地浏览器截图和 headless pixel 检查 |
## 7. 建议提交拆分
1. `fix: keep desired LinuxCNC kinematics frame source across async refresh`
2. `fix: render visible five-axis preview model and fallback scene`
3. `fix: preserve work-pose continuity for task-hal jog feedback`
4. `test: add browser regression for kinematics auto-refresh preview and jog continuity`