代码¶
PP 实现 — Welch PSD → 平均 → 峰值检测 → sqrt(PSD) 振型
int tiny_sysid_pp(const float *data, int n_ch, int n, float fs,
int fft_len, int n_modes, tiny_sysid_result_t *result)
{
// ── Step 1: 自动选择 Welch 分段长度 ──
// 目标 n/3 但不超过 512,向下取 2 的幂
int target_seg = (n < 128) ? n : (n / 3 < 512 ? n / 3 : 512);
int seg_len = 1;
while (seg_len * 2 <= target_seg && seg_len * 2 <= fft_len)
seg_len <<= 1;
if (seg_len < 32) seg_len = 32;
// ── Step 2: Welch 平均 PSD(每通道独立)──
int n_bins;
float *psd = malloc(n_ch * (fft_len / 2) * sizeof(float));
tiny_sysid_psd_welch(data, n_ch, n, seg_len, fft_len, fs, psd, &n_bins);
// ── Step 3: 所有通道 PSD 取平均 ──
float *psd_avg = malloc(n_bins * sizeof(float));
tiny_sysid_psd_average(psd, n_ch, n_bins, psd_avg);
// ── Step 4: 在平均 PSD 上检测峰值 ──
int peak_bins[n_modes], n_found = 0;
tiny_sysid_find_peaks(psd_avg, n_bins, n_modes, peak_bins, &n_found);
// ── Step 5: 提取振型 + 去重 ──
result->n_modes = n_found;
for (int m = 0; m < n_found; m++) {
int bin = peak_bins[m];
result->frequencies[m] = tiny_sysid_bin_to_freq(bin, fft_len, fs);
for (int ch = 0; ch < n_ch; ch++)
result->shapes[m][ch] = sqrtf(psd[ch * n_bins + bin]);
tiny_sysid_normalise_shape(result->shapes[m], n_ch);
}
tiny_sysid_dedup_modes(result, psd_avg);
result->success = 1;
return 0;
}
关键设计:
seg_len自动适配数据长度:30秒数据(1500点) → seglen=512;10秒(500点)→ seglen=128- 振型 = sqrt(PSD) 各通道在同一峰值处的相对幅度
- 峰值间最小间距 5 bins,避免频率靠得太近的误检