feat(runtime): 完善 FANUC 命令参数与状态通道重连

* 在 FanucCommandProtocol/Client 中补齐速度倍率、TCP 位姿和
  IO 的封包/解析,并引入 FanucIoTypes 字符串到枚举映射
* FanucControllerRuntime 在非仿真模式下接入真机命令通道,本地
  缓存仅作为兜底,TCP 操作扩展为 7 维 Pose
* FanucStateClient 增加帧超时检测、退避自动重连和诊断状态接口,
  超时或重连期间不再把陈旧帧当作当前机器人状态
* FanucStateProtocol 锁定 90B 帧字段为 pose[6]、joint[6]、
  external_axes[3] 和 raw_tail_words[4],并保留状态字诊断槽位
* ICspPlanner 增加 global_scale > 1.0 失败判定,self-adapt-icsp
  内部禁用该判定以保留补点重试链路
* 同步更新 README/AGENTS/计划文档的 todo 状态和实现说明
This commit is contained in:
2026-04-27 00:18:50 +08:00
parent 390d066ece
commit 69fa3edd89
18 changed files with 1631 additions and 122 deletions

View File

@@ -5,6 +5,7 @@
当前 `flyshot-replacement` 项目已完成:
- 三条 FANUC 通信链路的二进制协议编解码(`FanucCommandProtocol``FanucStateProtocol``FanucJ519Protocol`
- 抓包样本验证的协议测试5 个 FanucProtocolTests 全部通过)
- TCP 10012 的 `Get/SetSpeedRatio``Get/SetTCP``Get/SetIO` 参数命令封包、响应解析和本地模拟器测试
- HTTP 兼容层控制器和状态监控页
- 轨迹规划与飞拍触发编排层
@@ -64,9 +65,9 @@ FanucCommandProtocol / FanucStateProtocol / FanucJ519Protocol (已有,不改
- `ResetRobotAsync()``PackEmptyCommand(0x2100)`
- `GetProgramStatusAsync(string name)``PackProgramCommand(0x2003, name)`
- `StartProgramAsync(string name)``PackProgramCommand(0x2102, name)`
- `GetTcpAsync()` / `SetTcpAsync()`待解析请求/响应体格式
- `GetSpeedRatioAsync()` / `SetSpeedRatioAsync()`同上
- `GetIoAsync()` / `SetIoAsync()`同上
- `GetTcpAsync()` / `SetTcpAsync()`已按 `tcp_id + f32[7] pose` 字段布局实现
- `GetSpeedRatioAsync()` / `SetSpeedRatioAsync()`已按 `ratio_int / 100.0``ratio_int_0_100` 字段布局实现
- `GetIoAsync()` / `SetIoAsync()`已按 `io_type / io_index / f32 io_value` 字段布局实现
**测试**`tests/Flyshot.Core.Tests/FanucCommandClientTests.cs`
-`TcpListener` 本地模拟控制器,验证帧收发与解析
@@ -80,11 +81,17 @@ FanucCommandProtocol / FanucStateProtocol / FanucJ519Protocol (已有,不改
- 内部启动后台 `Task` 循环 `ReadAsync(FanucStateProtocol.StateFrameLength)`
- 每收到一帧调用 `FanucStateProtocol.ParseFrame()`
- 将解析结果写入线程安全的最新状态缓存
- `GetLatestSnapshot()` — 返回最近一次解析的状态帧
- 单帧接收超时后标记状态陈旧,不再把旧帧当作当前位姿/关节状态使用
- EOF、坏帧、Socket 异常或超时后关闭当前连接,并按退避策略自动重连 TCP 10010
- `GetLatestFrame()` — 返回最近一次解析的状态帧
- `GetStatus()` — 返回连接阶段、陈旧状态、最近异常和重连次数
- `Disconnect()` — 取消后台循环并关闭连接
**测试**`tests/Flyshot.Core.Tests/FanucStateClientTests.cs`
-`TcpListener` 本地发送抓包样本 hex验证后台循环能正确解析
-`TcpListener` 本地发送抓包样本 hex验证后台循环能正确解析
- 用本地模拟控制器验证无状态帧超时、EOF 后退避重连和重连后的继续收帧。
- `FanucStateProtocol` 已用 `j519 协议.pcap` 中多条 90B 样本锁定 `pose[6]``joint[6]``external_axes[3]``raw_tail_words[4]`
- 尾部状态字当前只作为 `ControllerStateSnapshot.stateTailWords` 诊断字段保留,不从 `[2,0,0,1]` 推断使能或运动状态。
### Phase 3: UDP 60015 J519 运动客户端
@@ -138,7 +145,7 @@ dotnet test tests/Flyshot.Server.IntegrationTests/Flyshot.Server.IntegrationTest
1. **真机连接风险**:第一版 Socket 实现可能有超时/重连问题。`FanucControllerRuntime` 保留 `_simulationMode` 路径,仿真模式下仍走内存桩。
2. **性能风险**:同步接口内部阻塞 Socket 可能影响 HTTP 并发。若实测有问题,后续将 `IControllerRuntime` 改为 async。
3. **协议字段不完整风险**TCP 10012 `GetTcp`/`SetTcp`/`GetIo`/`SetIo` 请求/响应体格式尚未完全逆向。先实现已知字段,留 TODO 标记待验证
3. **现场验证风险**TCP 10012 参数命令已按逆向结论实现,但仍需在真实 R30iB 控制柜上确认默认 `tcp_id=1`、IO 类型/地址和错误码语义
## 关键文件清单

View File

@@ -171,7 +171,7 @@ public sealed class ControllerClientTrajectoryOrchestrator
}
```
- [ ] **Step 4: Run tests to verify they pass**
- [x] **Step 4: Run tests to verify they pass**
Run: `dotnet test tests/Flyshot.Core.Tests/Flyshot.Core.Tests.csproj --filter ControllerClientTrajectoryOrchestrator -v minimal -m:1 -nodeReuse:false`
Expected: PASS.
@@ -209,7 +209,7 @@ public void ControllerClientCompatService_ExecuteTrajectory_RejectsThreeTeachPoi
}
```
- [ ] **Step 2: Run test to verify it fails**
- [x] **Step 2: Run test to verify it fails**
Run: `dotnet test tests/Flyshot.Core.Tests/Flyshot.Core.Tests.csproj --filter ControllerClientCompatService_ExecuteTrajectory_RejectsThreeTeachPointsAfterPlanningIsIntroduced -v minimal -m:1 -nodeReuse:false`
Expected: FAIL because current service still treats ordinary execution as "move to last waypoint".
@@ -239,12 +239,12 @@ public sealed class ControllerClientCompatService : IControllerClientCompatServi
}
```
- [ ] **Step 4: Run focused tests to verify green**
- [x] **Step 4: Run focused tests to verify green**
Run: `dotnet test tests/Flyshot.Core.Tests/Flyshot.Core.Tests.csproj --filter "ControllerClientCompatService|ControllerClientTrajectoryOrchestrator|FanucControllerRuntime" -v minimal -m:1 -nodeReuse:false`
Expected: PASS.
- [ ] **Step 5: Run integration verification**
- [x] **Step 5: Run integration verification**
Run: `dotnet test tests/Flyshot.Server.IntegrationTests/Flyshot.Server.IntegrationTests.csproj -v minimal -m:1 -nodeReuse:false`
Expected: PASS, with existing HTTP compatibility tests still green.