[关闭]
@chendbdb 2026-08-05T08:28:35.000000Z 字数 4715 阅读 3

摆动量去趋势值逻辑与算法说明

软件使用说明书 沥青试验仪 沥青


1. 文档目的

摆动量测量时,设备可能无法保持完全水平。随着设备运动,横向或纵向传感器的读数可能持续增大或持续减小,形成近似线性的基线漂移。

如果直接使用传感器实际值计算峰值,斜面造成的缓慢偏移也会被当成摆动量,导致峰值越来越大。当前程序通过实时拟合线性趋势,并从实际值中减去该趋势,得到真正用于摆动分析的“去趋势值”。

本文说明当前 Android 程序中去趋势值的计算方法、数据流程、峰值处理、图表显示和日志记录逻辑。


2. 相关概念

2.1 实际值

本文中的“实际值”不是 Modbus 寄存器中的原始整数,而是传感器值经过协议换算和标定后的测量值,单位为 mm

横向和纵向分别使用独立的标定配置:

2.2 趋势值

趋势值表示由安装斜面或缓慢漂移造成的线性基线。程序使用本次测量从开始到当前时刻的全部采样点,拟合一条直线:

其中:

2.3 去趋势值

去趋势值是实际值减去趋势预测值:

其中:

若实际值只包含稳定的线性增长或线性下降,去趋势值应接近 0;若线性趋势上叠加了摆动,去趋势值会保留该摆动部分。


3. 线性趋势拟合算法

3.1 最小二乘法

程序使用普通最小二乘法拟合直线。对于 个采样点:

斜率计算公式为:

截距计算公式为:

得到 后,任意采样点的去趋势值为:

3.2 在线增量计算

程序不会在每次新增数据时重新遍历全部采样点计算斜率,而是持续保存以下累计量:

新增一个采样点时,只需更新上述累计量,即可重新计算当前斜率和截距。因此,单次斜率更新的时间复杂度为

核心实现位于:

  1. app/src/main/java/com/ttaozi/record/utils/LinearTrendCorrector.java

3.3 横向和纵向独立拟合

横向与纵向使用两个互不影响的 LinearTrendCorrector

  1. trendCorrector1 横向摆动量
  2. trendCorrector2 纵向摆动量

这样可以处理以下情况:


4. 斜率单位

拟合时,相对时间由毫秒转换为秒,因此算法内部斜率单位为:

  1. mm/s

为了便于现场观察,界面和 TXT 日志将斜率乘以 60,显示为:

  1. mm/min

换算公式:

正斜率表示数值随时间上升,负斜率表示数值随时间下降。


5. 完整数据处理流程

flowchart TD A[读取横向与纵向 Modbus 数据] --> B[协议换算] B --> C[应用传感器标定] C --> D[得到横向/纵向实际值] D --> E[计算相对时间] E --> F1[横向在线线性拟合] E --> F2[纵向在线线性拟合] F1 --> G1[横向实际值 - 横向趋势值] F2 --> G2[纵向实际值 - 纵向趋势值] G1 --> H[更新去趋势值、斜率和峰值] G2 --> H H --> I[更新两张折线图] H --> J[写入本次测量 TXT 日志]

SwingMeasurementActivity.updateData12() 中,主要处理顺序如下:

  1. 将横向、纵向读取值分别进行标定;
  2. 记录当前毫秒时间戳;
  3. 计算本次测量开始后的相对时间;
  4. 将横向实际值加入横向趋势拟合器;
  5. 将纵向实际值加入纵向趋势拟合器;
  6. 获取两个方向的当前斜率;
  7. 使用当前趋势线计算两个方向的去趋势值;
  8. 更新峰值、文本框和折线图;
  9. 将当前数据写入本次测量日志。

6. 图表显示逻辑

界面包含两张独立折线图。

6.1 横向图

6.2 纵向图

两张图同时显示实际值和去趋势值,可直观看到:

为了保持页面刷新速度,图表仅重新计算和显示最近 30 个采样点。趋势斜率本身仍使用本次测量开始后的全部采样数据计算。

图表数据标签固定显示两位小数;左侧文本框按照“读取设置”中的精度显示。


7. 峰值计算逻辑

7.1 实时峰值

实时峰值不使用实际值,而使用去趋势值的绝对值:

横向和纵向分别维护各自的最大绝对值。

这意味着持续上升或下降的线性偏移不会直接累加到摆动峰值中。

7.2 停止和保存时的最终峰值

实时测量过程中,斜率会随着新增采样点逐渐变化。因此,早期数据计算时采用的趋势线可能与最终趋势线略有不同。

为保证最终结果一致,点击“停止”或“保存”时,程序会:

  1. 使用本次测量最终得到的横向和纵向趋势线;
  2. 重新校正本次测量的全部历史采样点;
  3. 重新计算全部去趋势值的最大绝对值;
  4. 将结果作为最终横向峰值和纵向峰值。

最终峰值计算位于:

  1. SwingMeasurementActivity.recalculateFinalPeaks()

8. 开始、清零和停止行为

8.1 点击开始

开始新一次测量时会清空:

因此,每次“开始→停止”都是一次独立的趋势拟合过程。

8.2 点击清零

清零会向摆动量设备发送清零命令,同时重置当前页面中的趋势累计量、图表和峰值。若清零时仍处于测量状态,后续采样会从新的基线重新建立趋势。

8.3 点击停止

停止测量后会:


9. TXT 日志中的去趋势数据

每次测量创建一个独立日志文件。每行格式为:

  1. 毫秒时间戳:横向去趋势值,横向实际值,横向斜率,纵向去趋势值,纵向实际值,纵向斜率

示例:

  1. 1754352000123:1.250000,10.500000,-0.750000,-2.500000,20.250000,0.500000

字段说明:

序号 字段 单位 说明
1 毫秒时间戳 ms Unix 时间戳,精确到毫秒
2 横向去趋势值 mm 横向实际值减去横向趋势值
3 横向实际值 mm 协议换算并标定后的横向值
4 横向斜率 mm/min 当前横向线性趋势斜率
5 纵向去趋势值 mm 纵向实际值减去纵向趋势值
6 纵向实际值 mm 协议换算并标定后的纵向值
7 纵向斜率 mm/min 当前纵向线性趋势斜率

日志数值保留 6 位小数。日志记录的是每个时刻基于当时实时趋势线得到的结果,因此可以用于分析斜率随测量过程逐渐稳定的情况。

典型日志目录为:

  1. /storage/emulated/0/Android/data/com.ttaozi.record/files/Documents/log/

10. 计算示例

假设横向实际值可近似表示为:

其中:

对应界面斜率为:

在第 20 秒时,趋势值为:

如果传感器实际值为 2.5 mm,则去趋势值为:

因此,峰值计算使用 0.3 mm,而不是包含斜面偏移的 2.5 mm


11. 初始采样阶段的特点

第 1 个采样点

只有一个采样点时无法确定斜率,程序将斜率设为 0,截距设为第一个实际值,因此首个去趋势值为 0。

第 2 个采样点

两个点可以确定一条直线,这两个点通常都会落在拟合线上,因此去趋势值可能仍接近 0。

后续采样点

随着样本增加,实际摆动不再能全部被一条直线解释,去趋势值开始体现真实摆动,斜率也逐渐稳定。

因此,测量刚开始时斜率和去趋势值出现短暂变化属于正常现象,不代表传感器异常。


12. 算法适用范围与注意事项

当前算法假设基线偏移近似为线性趋势,适合处理:

需要注意:

  1. 如果基线明显弯曲、分段变化或突然跳变,单条直线无法完全消除偏移;
  2. 极端异常点会影响最小二乘斜率,应优先检查传感器通信和机械冲击;
  3. 如果真正需要测量的运动本身就是持续线性变化,该部分会被算法视为趋势并剔除;
  4. 测量时间过短时样本不足,斜率容易受单个摆动点影响;
  5. 横向和纵向独立拟合,不会把一个方向的变化补偿到另一个方向。

13. 核心伪代码

  1. 开始测量:
  2. 重置横向趋势拟合器
  3. 重置纵向趋势拟合器
  4. 清空实际值、时间、峰值和图表
  5. 每次采样:
  6. timestamp = 当前 Unix 毫秒时间戳
  7. relativeTime = timestamp - 测量开始时间
  8. horizontalActual = 标定(横向传感器值)
  9. verticalActual = 标定(纵向传感器值)
  10. horizontalTrend = 横向拟合器.add(relativeTime, horizontalActual)
  11. verticalTrend = 纵向拟合器.add(relativeTime, verticalActual)
  12. horizontalCorrected = horizontalActual - 横向趋势预测值
  13. verticalCorrected = verticalActual - 纵向趋势预测值
  14. 横向实时峰值 = max(横向实时峰值, abs(horizontalCorrected))
  15. 纵向实时峰值 = max(纵向实时峰值, abs(verticalCorrected))
  16. 更新文本和折线图
  17. 写入 TXT 日志
  18. 停止或保存:
  19. 使用最终横向趋势重新校正全部横向历史点
  20. 使用最终纵向趋势重新校正全部纵向历史点
  21. 重新计算最终横向和纵向峰值

14. 代码位置

功能 文件
在线线性拟合与去趋势计算 app/src/main/java/com/ttaozi/record/utils/LinearTrendCorrector.java
摆动量采集、图表和峰值处理 app/src/main/java/com/ttaozi/record/activity/SwingMeasurementActivity.java
TXT 日志写入与解析 app/src/main/java/com/ttaozi/record/utils/SwingMeasurementLogWriter.java
去趋势算法单元测试 app/src/test/java/com/ttaozi/record/LinearTrendCorrectorTest.java
日志格式单元测试 app/src/test/java/com/ttaozi/record/SwingMeasurementLogWriterTest.java
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注