4. Signal processing for correlation
Before any correlation metric is computed, the test and simulation signals must be placed on a common numerical footing. CORA, like most objective rating methods, compares two time histories sample by sample after a defined preprocessing chain. If that chain is applied inconsistently — a different filter on each side, mismatched sample rates, a residual time offset, or a unit mismatch — the resulting score reflects the preprocessing, not the physical fidelity of the model. This chapter treats the four preprocessing operations that dominate correlation quality: filtering, resampling, time alignment, and unit consistency. The goal is a defensible, reproducible preprocessing recipe that can be documented and re-applied to every channel in a crash model.
Why preprocessing dominates the score
Crash signals are broadband and transient. An acceleration pulse at the B-pillar contains energy from a few hertz (occupant-coupled structural modes) up to several kilohertz (local shell ringing and sensor resonance). CORA evaluates magnitude and phase similarity in defined frequency bands, so the spectral content that reaches the metric matters directly. A 300 Hz low-pass on the test channel but a 1 kHz low-pass on the simulation channel will systematically penalize the simulation in the high band, even when the underlying physics agrees. Similarly, a 2 ms time offset on a 60 g, 40 ms pulse produces a large magnitude error at the pulse flanks. Preprocessing is therefore not cosmetic housekeeping; it is part of the measurement definition.
Filtering: one filter, applied to both sides
The governing rule is that the same filter — same type, order, cutoff, and phase response — must be applied to both the test and the simulation channel. Two practical conventions are common:
- Butterworth low-pass, zero-phase (filtfilt). Applied forward and backward, giving zero net phase shift and an effective order of twice the design order. This is the preferred choice for correlation because it does not introduce a relative delay between the two signals. A typical crash correlation setting is a 4th-order Butterworth at 300–1000 Hz, chosen to sit above the structural band of interest but below sensor resonance.
- SAE J211 / CFC digital filters. Channel Frequency Class filters (CFC 60, CFC 180, CFC 600, CFC 1000) are specified for occupant and vehicle crash data. When the test data has already been filtered to a CFC class, the simulation must be filtered with the same class before comparison, not left raw.
A reproducible implementation in Python, applied identically to both arrays, looks like this:
from scipy.signal import butter, filtfilt
import numpy as np
def lowpass(x, fs, fc, order=4):
b, a = butter(order, fc / (fs / 2.0), btype='low')
return filtfilt(b, a, x)
# same fc, same order, same fs on both channels
test_f = lowpass(test_acc, fs=10000, fc=600)
sim_f = lowpass(sim_acc, fs=10000, fc=600)
Two failure symptoms are worth recognizing. First, if the filtered test signal shows a visible lag relative to the raw signal, a causal (single-pass) filter was used; switch to zero-phase filtering. Second, if the simulation's high-frequency content vanishes but the test's does not, the cutoff frequencies differ — verify fc and fs on both calls. Always record the filter type, order, cutoff, and whether zero-phase was used in the correlation report.
Resampling: a shared time base
Test data is typically acquired at 10–100 kHz; explicit simulation output may be written at 10 kHz or at the solver's stable time step. CORA requires both signals on the same time vector. Resample the higher-rate signal down to the common rate, or resample both to a defined common rate, but never upsample a coarse simulation to a fine test rate and treat the interpolated points as independent evidence.
Choose the common rate to preserve the band of interest. If the correlation band extends to 1 kHz, a common rate of at least 5–10 kHz is appropriate (Nyquist plus margin). Use band-limited interpolation rather than linear interpolation, because linear interpolation attenuates high frequencies and introduces its own error:
from scipy.signal import resample_poly
from math import gcd
def common_rate(fs_a, fs_b, target):
# resample both to 'target' using polyphase filtering
up_a, down_a = target // gcd(fs_a, target), fs_a // gcd(fs_a, target)
up_b, down_b = target // gcd(fs_b, target), fs_b // gcd(fs_b, target)
return (resample_poly(a, up_a, down_a),
resample_poly(b, up_b, down_b))
After resampling, confirm that the number of samples and the time span match. A common defect is an off-by-one sample at the end of the record, which shifts the final samples and corrupts the tail of the correlation window.
Time alignment: removing the residual offset
Even with synchronized triggers, test and simulation rarely share an exact time origin. The simulation's t=0 may be the start of the solver step, while the test's t=0 is the trigger instant; rig compliance and sensor delays add further offset. Time alignment estimates and removes this residual shift before scoring.
A robust method is cross-correlation of the two filtered signals to find the lag that maximizes similarity, then shifting the simulation by that lag:
from scipy.signal import correlate, correlation_lags
def align(test, sim, fs):
c = correlate(test - test.mean(), sim - sim.mean(), mode='full')
lags = correlation_lags(len(test), len(sim), mode='full')
lag_s = lags[np.argmax(c)] / fs
return lag_s # shift sim by -lag_s to align to test
For crash pulses, cross-correlation on the raw acceleration can be biased by the dominant pulse; a more stable estimate uses the onset of the pulse (first crossing of a threshold such as 5 g) or the peak of the cross-correlation of the velocity obtained by integrating acceleration. Report the applied shift in milliseconds; a shift larger than roughly one sample period at the correlation bandwidth should be investigated, because it may indicate a modeling or triggering error rather than a benign offset.
Unit consistency: g versus m/s², and the integration trap
Acceleration may be recorded in g, m/s², or mm/s²; displacement in mm or m; rotation in degrees or radians. A factor-of-9.81 error is the most common unit defect and produces a magnitude score near zero while the curve shapes look plausible. Normalize units at ingestion, before filtering and resampling, and store the unit alongside each channel.
Unit errors compound through integration. If velocity or displacement is derived by integrating acceleration, the unit of the result depends on the acceleration unit and the time unit:
# acceleration in m/s^2, time in s -> velocity in m/s
v = np.cumsum(a) * dt
# acceleration in g -> convert first
a_ms2 = a_g * 9.80665
v = np.cumsum(a_ms2) * dt
Integration also accumulates drift, so a high-pass or detrending step is usually applied to the integrated velocity before comparison. Apply the same detrending to both sides. A symptom of a unit mismatch is a constant ratio between test and simulation amplitudes across the whole record; a symptom of drift is a growing divergence in velocity or displacement that is absent in acceleration.
Documenting the preprocessing recipe
Because preprocessing choices materially change the score, they must be recorded per channel and reproduced exactly on re-runs. A compact, fillable record for each correlated channel keeps the workflow auditable:
| Field | Example value | Purpose |
|---|---|---|
| Channel / sensor | B-pillar lower, X-axis | Identifies the physical quantity |
| Test unit → SI | g → m/s² (×9.80665) | Prevents magnitude bias |
| Filter | Butterworth, order 4, fc 600 Hz, filtfilt | Defines comparable spectral content |
| Common sample rate | 10 kHz, polyphase resample | Shared time base |
| Time shift Δt | +1.8 ms applied to simulation | Removes residual offset |
| Integration / detrend | cumtrapz, high-pass 5 Hz on velocity | Controls drift for derived channels |
With units normalized, a single zero-phase filter applied to both sides, a shared resampled time base, and one justified time shift per event, the CORA score becomes a measure of model fidelity rather than of preprocessing inconsistency. The next step — interpreting the magnitude and phase sub-scores band by band — only becomes meaningful once this foundation is stable.