NOTES¶
PP — Peak Picking: Find Sharp Peaks in the Spectrum
The simplest frequency-domain method. Computes auto-PSD per channel, averages them, finds local maxima as modal frequencies, uses sqrt(PSD) as mode shapes.
Intuition¶
Core Idea¶
Imagine a bridge swaying gently in the wind. If you place an accelerometer and record data, in the frequency domain some frequencies will have much larger amplitudes—these peaks correspond to the structure's natural frequencies.
PP does exactly this: finds the prominent peaks in the spectrum.
Why It Works¶
Ambient excitation (wind, traffic) has a roughly flat spectrum (white noise). The structure acts as a filter—amplifying input at its natural frequencies. So the output spectrum peaks are the structure's modes.
Strengths & Weaknesses¶
- Strength: fastest (~50 ms for 5ch×3000), simple implementation, great for quick scans
- Weakness:
- Can't separate closely-spaced modes (< 2 bins apart)
- No damping estimate
- Depends on averaged PSD quality
Algorithm¶
1. Welch-averaged PSD per channel
├─ segments with 50% overlap
├─ Hann window → FFT → power spectrum
└─ average all segments → channel PSD
2. Average across channels → psd_avg[]
3. Peak detection
├─ local maxima (larger than ±2 neighbors)
├─ noise floor = 25th percentile
├─ SNR threshold: psd[k] > 4× noise floor
├─ sort by amplitude descending
└─ min distance ≥ 5 bins
4. Mode shapes: sqrt(psd[ch][peak_bin]) → normalize
Design Deep Dive¶
1. Welch Segment Averaging¶
Why not the periodogram (single FFT on all data)? Single-frame FFT has high variance. Welch averages overlapping segments, trading resolution for variance reduction:
| Strategy | Segments | Resolution | Variance reduction |
|---|---|---|---|
| Periodogram | 1 | \(f_s / N\) | 1× |
| Welch 50% overlap | ~3 | \(f_s / seg\_len\) | ~3× |
| More segments | more | worse | more |
Implementation choice:
-n/3: guarantees ≥3 segments (50% overlap → (n-seg)/seg + 1 ≥ 3) - 512 cap: ESP32 512-pt FFT ~0.8ms, 1024-pt ~1.8ms. Cap at 512 keeps pipeline < 50ms - Power-of-2: required by tiny_fft 2. Hann Window¶
Pre-computed as static array in tiny_sysid_common.c. Hann has 2× main lobe width vs rectangular (sidelobes -31dB), the standard choice for PSD estimation. Hamming gives lower sidelobes but slightly wider main lobe, hurting close-mode resolution.
3. Peak Detection Strategy¶
±2 bins (vs ±1): more conservative. Well-separated modes span 3-5 bins. Noise floor = 25th percentile (not median or minimum): - Minimum → unstable, too sensitive to spectral nulls - Median → inflated when many modes fill the spectrum - 25th percentile → robust: assume ≥75% of bins are noise-free
4. ESP32 Resource Usage¶
- PSD buffer: 5ch × 1024 bins = 20 KB → SRAM fits
- FFT buffer (reusable): 2048 floats = 8 KB
- Total: 5ch × 3seg × 0.4ms = ~6ms → PP < 10ms total
Key Parameters¶
| Parameter | Default | Description |
|---|---|---|
| seg_len | min(N/3, 512) power-of-2 | Segment length |
| overlap | 50% | Segment overlap |
| window | Hann | Window function |
| SNR threshold | 4× noise_floor | Peak detection |
When to Use PP¶
- Quick frequency scan on first look at data
- Very short data (≥ 500 samples = 10s)
- Reference for more accurate methods