2026-06-16-diagnostics-ui-logging-design.md 5.9 KB

诊断工具 / UI数据显示 / 操作日志 — 设计文档

日期:2026-06-16 背景:4 号舱对焦失败排查中发现需要更好的诊断与可观测性。本设计涵盖三个独立子系统。

总览

# 子系统 目标
1 诊断工具 + 测试数据目录规范 扩展 WellSpacing 支持 Z 清晰度曲线扫描;所有诊断输出统一到 TestData/
2 UI 数据显示调整 删除 CalibWindow 底部冗余孔位数据;预览画面参数显示更详细
3 操作日志系统 界面所有点击操作落盘记录,便于事后分析定位

三者相对独立,可分别实现。下面分述。


子系统 1:诊断工具扩展 + TestData 目录规范

1.1 目录规范

  • 新建 TestData/(加入主工程 csproj 的 Compile Remove 排除,避免被编译)。
  • 所有诊断工具(WellSpacing 等)输出写到 TestData/<工具名>_<时间戳>/
  • calib_result/ 仅保留程序正式标定产物(house*_well*_标定后.bmp + calibration 存图),不再混入诊断文件。

1.2 WellSpacing 扩展:Z 清晰度曲线模式

现状:WellSpacing 已能逐 well 移动+拍照+检测+存图(固定 Z)。 新增一个模式:对指定 well 做 Z 清晰度曲线扫描,定位真实焦面。

  • 用法:WellSpacing.exe zcurve <COM> <相机idx> <well号> [zLo=20000] [zHi=120000] [zStep=2000] [曝光=60]
  • 行为:移到该 well 的 EEPROM 水平位置 → 从 zLo 到 zHi 按 zStep 逐层:
    • 移动到 z(绝对)→ 丢弃一帧 → 抓帧
    • 算清晰度(中央40% ROI),同时记录该帧灰度均值(验证亮度归一化是否带偏)
    • 存图到 TestData/zcurve_w<well>_<时间戳>/z<值>_s<分数>.bmp
    • 控制台打印一行:z=<值> 原始梯度=<sumSq/n> 亮度均值=<mean> 归一化分=<score>
  • 输出末尾打印曲线峰值位置,便于人工判断真实焦面 Z。
  • 目的:用真实数据回答"4号舱焦面在哪""mean²归一化是否把暗的低Z层评高",为后续是否改 Sharpness 提供依据。

保留 WellSpacing 现有的"逐 well 拍照"模式(默认无 zcurve 参数时跑原逻辑),只是输出目录改到 TestData/。


子系统 2:UI 数据显示调整

2.1 删除 CalibWindow 底部冗余区

  • 删除 CalibWindow.xaml:29-34 的底部 Border(TxtCurParams / TxtCurStep)。
  • 同步删除 CalibWindow.xaml.cs 中对这两个控件的引用(SetCurrentInfo 里对 TxtCurParams.Text/TxtCurStep.Text 的赋值)。
  • Grid 第 2 行(Height="120")一并移除,网格区(well 4x4)占满下方空间。

2.2 预览画面参数显示更详细

现状:SetCurrentInfo(param, step) 把"步骤+偏移"写到当前 well 格的标题(cap)上。 增强:每个 well 格标题在标定中实时显示更完整参数,至少包含:

  • 当前步骤(粗对焦/居中/曝光/精对焦 + 进度)
  • well 号、Z 当前值、水平位置、曝光值、清晰度分、圆偏移 X/Y、是否完整圆

实现:扩展 SetCurrentInfo 的入参,或新增重载传入结构化数据(well/z/h/exp/score/offsetX/offsetY/complete),在 well 格标题用多行格式显示。调用方 MainWindow.Calib.csOnStep 回调补齐这些字段。

主窗口 MainWindow.xaml 预览浮层(TxtScore/TxtZ/TxtFps)保留——那是手动测试用,不在本次删除范围。


子系统 3:操作日志系统

3.1 方式(已确认:甲 — 统一入口集中记录)

  • 给现有 MainWindow.Log() 增加落盘能力。
  • 每个按钮 Click 处理函数开头加一行 LogAction(...),显式记录"操作名 + 关键参数"。
  • 操作执行后,在产生/修改数据处记录结果(如移动后的位置、设置的曝光值、标定结果)。

3.2 文件组织(已确认:每次启动一个文件)

  • 目录:Logs/(加入 csproj 排除)。
  • 文件名:Logs/<yyyy-MM-dd_HHmmss>.log,程序启动时创建,本次运行所有日志写入同一文件。

3.3 日志格式

纯文本,每行一条,制表分隔,便于阅读和事后 grep:

HH:mm:ss.fff  [级别]  [类别]  消息
  • 级别:INFO / ACTION / DATA / WARN / ERROR
  • 类别:UI / MOTOR / CAMERA / CALIB / SERIAL
  • 示例:

    16:45:30.123  [ACTION] [UI]     点击"一键全自动初始化" wells=[1,2,3] 舱=4
    16:45:31.456  [DATA]   [MOTOR]  well1 读EEPROM 水平=71500 Z零点=...
    16:45:33.789  [DATA]   [CALIB]  well1 粗对焦 coarseZ=90000 峰比=1.04
    16:45:40.012  [WARN]   [CALIB]  well1 对焦峰弱(ratio=1.04)
    

3.4 实现要点

  • 新增一个轻量 FileLogger 类(静态或单例):启动时按时间戳建文件,提供 Info/Action/Data/Warn/Error(category, msg) 方法,线程安全(lock 写入),自动 flush。
  • MainWindow.Log(msg) 内部同时:① 追加到界面 TxtLog(现有行为)② 调 FileLogger 落盘。
  • 各按钮 Click 开头加 LogAction;关键数据点(移动结果、标定参数、异常)加 LogData/LogWarn
  • CalibrationEngine 已有的 Log?.Invoke(...) 回调天然会流入 FileLogger(因为它接的就是 MainWindow.Log),标定过程数据自动入库。

3.5 记录覆盖范围

界面所有按钮:扫描、连接/断开、转well、开/关光源、抓帧、实时预览、存图、设曝光/增益、Z 正反转/复位/绝对移动、水平正反转/复位、Z扫描、停止、全选/全不选、一键自动初始化。 每条记录"点击了什么 + 当时的输入参数 + 执行结果/产生的数据"。


实现顺序建议

  1. 子系统 3(日志)——最先做,后续两项的调试都能受益于日志。
  2. 子系统 1(诊断工具)——用来定位 4 号舱焦面问题。
  3. 子系统 2(UI)——纯界面调整,独立。

不在本次范围

  • 不改 Sharpness 清晰度算法本身(先用诊断工具 1.2 取证,确认后另行设计)。
  • 不改 CalibrationEngine 对焦逻辑(同上,待诊断数据)。
  • 不改主窗口预览浮层(保留)。