241 lines
6.6 KiB
Markdown
241 lines
6.6 KiB
Markdown
# 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`
|
||
|