feat(analyze): 新增 Ploss/Qfod 分析命令

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Scottxjw
2026-08-14 15:36:29 +08:00
parent b88c07356e
commit 0667e2e9b8
8 changed files with 686 additions and 0 deletions

View File

@@ -12,6 +12,7 @@
| `aggregate` | 从本地库汇总生成发布库 | local.db → release.db |
| `export` | 导出发布库到 CSV | release.db → CSV |
| `clean` | 清理本地库数据(软删除) | 只写 local.db |
| `analyze` | 独立分析Ploss 余量/delta_p、Qfod 标定阈值 | log → 控制台报告 |
---
@@ -71,6 +72,26 @@ dotnet run clean --all --confirm
---
### 2.5 analyze
```bash
# Ploss 余量 / delta_p 分析(单文件,直接解析日志,不依赖本地库)
dotnet run analyze --type ploss --file <log>
# Qfod 标定阈值(两个文件:纯手机 / 手机+异物)
dotnet run analyze --type qfod --pure <纯手机.log> --foreign <手机+异物.log>
```
- `analyze` 为**独立分析**,不进入 `parse → aggregate` 发布管线,也不写任何文件(仅控制台报告)。
- Ploss 口径以实体语义为准Field9=ploss、Field10=threshold、Field12=FOD 标志):
- FOD 报警 = `Field12 == 1`
- 安全余量 `Margin = Threshold Ploss > 2000`
- 恒等式校验 `delta_p = Tx Rx pow_loss Ploss`(仅两行格式)
- delta_p 反解(两行格式且 FOD=1`delta_p' = DeltaP + 2001 + Ploss Threshold`,控制台输出重写后的 header 行
- Qfod 标定阈值:`Threshold = (纯手机 ΔQ 最大值 + 手机+异物 ΔQ 最小值) / 2`。因现无法自动区分两个日志文件,需显式传入 `--pure`/`--foreign`
---
## 3. 典型工作流
```bash

View File

@@ -0,0 +1,114 @@
# Ploss 分析delta_p 与安全余量判定)
> 本文档单独记录 Ploss 分析的分析口径与判定条件。
> 内容独立于既有需求文档 `docs/requirement/WCT数据需求分析.md`,不与原文档合并。
---
## 1. 核心口径
Ploss 两行日志格式:
```text
pow_loss = 2200, delta_p = 2500
FOD-> (16 个字段)
```
- **header 行**直接记录固件当前使用的 `pow_loss` / `delta_p`
- **FOD-> 行**记录 16 个字段,其中包含 Ploss功率损耗计算值、Threshold阈值、触发次数、FOD 结果等。
**权威字段语义**(以实体 `PlossRecord` 注释为准):
| 字段 | 语义 |
|------|------|
| Field9 | ploss - 功率损耗计算值 |
| Field10 | threshold - 阈值 |
| Field11 | 触发次数 |
| Field12 | FOD 结果标志 |
---
## 2. 判定条件
### 2.1 FOD 报警判定
**直接看 FOD 结果标志 == 1**。固件已完成判定Ploss>Threshold → 计数累积 → 满限置位),分析无需重建该逻辑。
### 2.2 delta_p 恒等式
```
delta_p = Tx Rx pow_loss Ploss
```
能量守恒恒等式,固件即用此公式计算 Ploss故必然满足可用于校验。
### 2.3 安全余量判定
```
Field10 Field9 = Threshold Ploss > 2000
```
正常充电时安全余量需大于 2000余量不足≤2000即异物或异常信号。
### 2.4 delta_p 调整反解(使余量 > 2000
当 FOD=1余量不足可依据 2.2 恒等式与 2.3 余量判定,反解出使余量严格 `> 2000`(整数即 `≥ 2001`)所需的 delta_p
```
margin = Threshold Ploss
delta_p' = DeltaP + (2001 margin)
= DeltaP + 2001 + Ploss Threshold
```
- `DeltaP`header 行记录的原始 delta_p
- `delta_p'`:调整后的新 delta_p
- 将 header 行重写为 `pow_loss = <原值>, delta_p = <delta_p'>` 后,按恒等式 Ploss 下降 `2001 margin`,余量达到 2001。
> **注意**:此反解仅在两行格式(有 header下有意义旧单行格式无 headerPowLoss/DeltaP 为 null无法调整 delta_p。
**测试数据字段位置**(与实体语义错位,以实体语义为准):
| 文件 | ploss | threshold | FOD 标志 |
|------|-------|-----------|----------|
| 实体语义(真实固件) | Field9 | Field10 | Field12 |
| ploss_test 实测 | Field8 | Field9 | Field11 |
| ploss_legacy 实测 | Field10 | Field11 | Field13 |
**ploss_test 中 14 条 FOD=1 行的计算结果**(新余量校验 = 2001
| 行号 | pow_loss | DeltaP | ploss | threshold | margin | delta_p' |
|------|----------|--------|-------|-----------|--------|----------|
| 247 | 2200 | 2500 | 798 | 1000 | 202 | 4299 |
| 259 | 2000 | 2200 | 760 | 750 | 10 | 4211 |
| 519 | 2200 | 2500 | 1308 | 1000 | 308 | 4809 |
| 527 | 3000 | 3500 | 1355 | 1250 | 105 | 5606 |
| 567 | 2200 | 2500 | 674 | 1000 | 326 | 4175 |
| 957 | 2000 | 2200 | 736 | 750 | 14 | 4187 |
| 1129 | 1000 | 500 | 123 | 350 | 227 | 2274 |
| 1265 | 2000 | 2200 | 497 | 750 | 253 | 3948 |
| 1533 | 3000 | 3500 | 1474 | 1250 | 224 | 5725 |
| 2157 | 2200 | 2500 | 361 | 1000 | 639 | 3862 |
| 2379 | 1000 | 500 | 397 | 350 | 47 | 2548 |
| 2413 | 3000 | 3500 | 955 | 1250 | 295 | 5206 |
| 2477 | 2000 | 2200 | 363 | 750 | 387 | 3814 |
| 2575 | 1000 | 500 | 560 | 350 | 210 | 2711 |
新 delta_p 范围 **2274 ~ 5725**(原 500 ~ 3500
> **局限**:示例日志为生成的测试数据,恒等式 `delta_p = Tx Rx pow_loss Ploss` 在数据中不成立(穷举全部字段组合均无法一致满足),故表中 delta_p' 为"若恒等式成立则应写入的目标值",无法用数据本身验证。真实固件数据(恒等式成立)下此公式精确成立。
---
## 3. 实测佐证
示例日志自动生成的测试数据按语义threshold ploss计算安全余量
| 格式 | 正常行 margin>2000 比例 | FOD 行 margin>2000 比例 |
|---|---|---|
| 两行 ploss_test | 917/1486 (61.7%) | 0/14 (0%) |
| 旧版 ploss_legacy | 361/593 (60.9%) | 0/7 (0%) |
FOD 行安全余量全部 ≤ 2000可区分正常/异物。
> 说明:示例日志为生成的测试数据,其字段位置与实体语义存在错位;**以实体语义为准**
> Field9=ploss、Field10=threshold

View File

@@ -0,0 +1,79 @@
# Qfod 标定分析Q值 → 标定 ΔQ 阈值)
> 本文档单独记录 Qfod 标定分析的分析口径、阶段区分限制与交付方式。
> 内容独立于既有需求文档 `docs/requirement/WCT数据需求分析.md`,不与原文档合并。
---
## 1. 核心口径
Q 值由日志直接记录,日志格式 `X#:Q A->B C D E F`
| 字段 | 名称 | 说明 |
|------|------|------|
| X | ChargerIndex | 充电器索引0, 1 |
| A | CoilIndex | 线圈索引0, 1, 2 |
| B | ΔQ (DeltaQ) | Q 值变化量 |
| C | CurrentQ | 当前 Q 值 |
| D | RawQ | 原始 Q 值 |
| E | FodType | 异物类型编码 |
**关键点**:「纯手机」与「手机+异物」分别对应**两个日志文件(两个测试场景)**
- 日志文件 A纯手机充电
- 日志文件 B手机 + 异物
标定分析需**先区分这两个日志文件**,再计算标定 ΔQ 阈值。
---
## 2. 标定 ΔQ 阈值计算
1. 分别从两个日志文件提取 ΔQ
- 文件 A纯手机取该文件 ΔQ **最大值**示例25
- 文件 B手机+异物):取该文件 ΔQ **最小值**示例40
2. 计算标定阈值:`Threshold = (25 + 40) / 2 = 32`
---
## 3. 分析步骤
1. 提取日志中 `#Q` 开头的行
2. 绘制 ΔQ 时序曲线,叠加 Y=Threshold 水平线
3. 验证余量:纯手机最高点 vs 阈值、有异物最低点 vs 阈值
---
## 4. 文件区分方式(现状与后续计划)
### 4.1 当前限制
暂无可自动区分「纯手机」/「手机+异物」两个日志文件的可靠依据,因此**当前版本无法自动计算标定 ΔQ 阈值**。
### 4.2 后续计划
日志文件将写清楚所对应的场景(文件名 Purpose 段或文件内标记),届时据此区分两个文件再计算标定阈值。
**待办**:定义日志文件区分标识,解析时识别并关联配对的两个场景。
---
## 5. 交付方式
- 标定 ΔQ 阈值属**独立分析****不进入发布库聚合**(发布库现有 Q值/Q基值 列仍为 CurrentQ/RawQ 全量平均,保持不变)。
- 计划通过**新建 CLI 分析命令**`analyze-qfod`)承载/输出,命令**尚未实现**。
---
## 6. 实测佐证
`data/test_input/singleMold-v1.0-hex2_1-iPhone15-qfod_test-20260710-1.log`(示例日志含 Phase 标记):
| Phase | 含义 | ΔQ 范围 | FOD Type(E) |
|---|---|---|---|
| 1 正常充电 | 纯手机 | 20~30均值 24.9 | 0 |
| 2 异物检测 | 手机+异物 | 35~55均值 44.6 | 1/2/3 |
| 3 边界值 | 临界区 | 30~35均值 32.5 | — |
| 4 负数 | 异常 | -25~0 | — |
> 说明:示例日志为生成的测试数据,仅作 ΔQ 数值区间的参考;真实数据中「纯手机」与「手机+异物」分属两个日志文件。