代码¶
FDD 实现 — CPSD → 每频点 SVD → SV1 谱 → 左奇异向量振型
int tiny_sysid_fdd(const float *data, int n_ch, int n, float fs,
int fft_len, int n_modes, tiny_sysid_result_t *result)
{
// ── Step 1: Welch 平均 CPSD 矩阵 ──
int stride = n_ch * n_ch, n_bins;
float *G = malloc((fft_len / 2) * stride * sizeof(float));
tiny_sysid_cpsd_welch(data, n_ch, n, seg_len, fft_len, fs, G, &n_bins);
// ── Step 2: 每频点 SVD(幂迭代求主奇异值/向量)──
for (int k = 0; k < n_bins; k++) {
float sigma;
tiny_sysid_svd_dominant(G + k * stride, n_ch, &sigma, u);
sv1_spectrum[k] = sigma;
memcpy(mode_shapes + k * n_ch, u, n_ch * sizeof(float));
}
// ── Step 3: SV1 谱峰值检测 ──
// 同 PP,但在 SV1 谱上而非平均 PSD 上
tiny_sysid_find_peaks(sv1_spectrum, n_bins, n_modes, peak_bins, &n_found);
// ── Step 4: 提取振型(SVD 左奇异向量)──
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);
memcpy(result->shapes[m], mode_shapes + bin * n_ch, n_ch * sizeof(float));
tiny_sysid_normalise_shape(result->shapes[m], n_ch);
}
tiny_sysid_dedup_modes(result, sv1_spectrum);
result->success = 1;
return 0;
}
FDD vs PP 核心区别:
- PP:auto-PSD → 平均 → sqrt(PSD) 振型
- FDD:CPSD → SVD → 左奇异向量振型(SVD 自动降噪)