2. 设备传感器数据模拟器

任务说明

本案例需要构建一个设备传感器数据模拟器,用于生成工业设备(以旋转机械为例)的振动、温度和转速三类传感器的时间序列数据。该模拟器需支持配置采样频率、设备健康状态(正常/退化/故障),并输出带时间戳的结构化数据,为后续PHM数据管道提供稳定、可重复的测试数据源。

实现方案

采用Python实现一个类SensorDataSimulator,核心逻辑包括:

  • 基于numpy生成确定性随机序列(固定随机种子保证可复现);
  • 振动信号叠加正弦基频与高斯噪声,退化/故障状态额外引入幅值增长与冲击分量;
  • 温度信号采用缓慢漂移模型,故障时叠加阶跃偏移;
  • 转速信号在正常状态保持恒定,退化状态线性缓降,故障状态加入随机波动;
  • 输出为pandas.DataFrame,包含timestamp、vibration、temperature、rpm四列。

代码实现

import numpy as np
import pandas as pd
from datetime import datetime, timedelta

class SensorDataSimulator:
    def __init__(self, sample_rate_hz=100, duration_sec=10, seed=42):
        self.sample_rate = sample_rate_hz
        self.duration = duration_sec
        self.seed = seed
        self.n_samples = sample_rate_hz * duration_sec
        self.rng = np.random.default_rng(seed)

    def _generate_vibration(self, health_state):
        t = np.arange(self.n_samples) / self.sample_rate
        base_freq = 30.0  # Hz
        if health_state == 'normal':
            amp = 1.0
            noise = 0.1
            signal = amp * np.sin(2 * np.pi * base_freq * t)
        elif health_state == 'degraded':
            amp = 1.5
            noise = 0.2
            # 幅值缓增 + 2倍频分量
            trend = np.linspace(1.0, 1.8, self.n_samples)
            signal = amp * trend * np.sin(2 * np.pi * base_freq * t) \
                     + 0.5 * trend * np.sin(2 * np.pi * 2 * base_freq * t)
        else:  # fault
            amp = 2.0
            noise = 0.3
            # 冲击分量:每0.5秒一次衰减振荡
            impact = np.zeros_like(t)
            impact_interval = 0.5
            for start in np.arange(0, self.duration, impact_interval):
                idx = int(start * self.sample_rate)
                if idx < self.n_samples:
                    impact_len = min(int(0.05 * self.sample_rate), self.n_samples - idx)
                    tt = np.arange(impact_len) / self.sample_rate
                    impact[idx:idx+impact_len] = 3.0 * np.exp(-tt * 50) * np.sin(2 * np.pi * 200 * tt)
            signal = amp * np.sin(2 * np.pi * base_freq * t) + impact
        noise_arr = self.rng.normal(0, noise, self.n_samples)
        return signal + noise_arr

    def _generate_temperature(self, health_state):
        base_temp = 65.0  # 摄氏度
        drift = np.linspace(0, 2, self.n_samples)  # 缓慢上升
        noise = self.rng.normal(0, 0.3, self.n_samples)
        temp = base_temp + drift + noise
        if health_state == 'degraded':
            temp += 5.0
        elif health_state == 'fault':
            temp += 12.0
        return temp

    def _generate_rpm(self, health_state):
        base_rpm = 1500.0
        if health_state == 'normal':
            rpm = np.full(self.n_samples, base_rpm)
        elif health_state == 'degraded':
            rpm = np.linspace(base_rpm, base_rpm * 0.9, self.n_samples)
        else:  # fault
            rpm = base_rpm + self.rng.normal(0, 30, self.n_samples)
        return rpm

    def generate(self, health_state='normal', start_time=None):
        if health_state not in ('normal', 'degraded', 'fault'):
            raise ValueError("health_state must be 'normal', 'degraded', or 'fault'")
        if start_time is None:
            start_time = datetime.now().replace(microsecond=0)
        timestamps = [start_time + timedelta(seconds=i / self.sample_rate)
                      for i in range(self.n_samples)]
        df = pd.DataFrame({
            'timestamp': timestamps,
            'vibration': self._generate_vibration(health_state),
            'temperature': self._generate_temperature(health_state),
            'rpm': self._generate_rpm(health_state)
        })
        return df

# 使用示例
if __name__ == '__main__':
    sim = SensorDataSimulator(sample_rate_hz=100, duration_sec=5, seed=42)
    df_normal = sim.generate('normal')
    df_fault = sim.generate('fault')
    print("正常状态数据形状:", df_normal.shape)
    print("故障状态数据形状:", df_fault.shape)
    print("\n正常状态前3行:")
    print(df_normal.head(3).to_string(index=False))
    print("\n故障状态前3行:")
    print(df_fault.head(3).to_string(index=False))

落地与验证

运行方式:将代码保存为sensor_simulator.py,在Python 3.8+环境中执行python sensor_simulator.py。依赖库为numpy和pandas,可通过pip install numpy pandas安装。

验证方法:

  1. 程序正常退出且无异常抛出;
  2. 输出DataFrame行数等于sample_rate * duration(本例为500行);
  3. 正常状态振动幅值约在±1.5范围内,故障状态振动幅值明显增大且包含冲击尖峰;
  4. 正常状态温度约65~67°C,故障状态温度约77°C以上;
  5. 正常状态转速恒为1500,故障状态转速在1500±3σ范围内波动。

判定标准:满足上述5项观测条件即视为模拟器功能正确。由于固定了随机种子,多次运行结果完全一致,保证数据可复现性。

传感器数据模拟器逻辑结构 输入配置 采样率: 100 Hz 时长: 5~10 s 随机种子: 42 健康状态 normal (正常) degraded (退化) fault (故障) 信号生成核心 振动: 正弦基频 + 噪声 + 冲击(故障) 温度: 漂移 + 噪声 + 偏移(故障) 转速: 恒定/缓降/随机波动 输出 DataFrame timestamp | vibration | temperature | rpm 验证观测点 ① 行数 = 采样率×时长 ② 振动幅值随状态增大 ③ 温度偏移: 故障>退化>正常 ④ 转速模式区分状态 配置参数 状态选择 数据生成