4. Validate Airbag Deployment Timing Against Injury Risk Curves

Why Deployment Timing Must Be Judged Against Injury Curves

An airbag deployment time extracted from an Event Data Recorder (EDR) is only a number until it is placed on the same time axis as the occupant's loading response. The diagnostic question is not "did the airbag fire?" but "did it fire early enough that the bag was fully inflated and venting before the occupant's head and chest reached the interior, and late enough that the occupant was not still moving forward into a deploying bag?" Answering that requires three aligned datasets: the EDR deployment command time, the vehicle deceleration pulse (from which occupant kinematics are derived), and the injury risk curves (HIC15 for head, Nij for neck, chest deflection/acceleration for thorax).

This case builds a reproducible comparison workflow: extract the deployment time, anchor it to the crash pulse, compute the occupant's forward excursion over time, and overlay the injury-risk curves to determine whether the deployment fell inside the mitigation window or outside it (late deployment or out-of-position exposure).

Step 1 — Extract and Normalize the EDR Deployment Time

EDRs typically report a deployment command time (the algorithm's fire signal) and sometimes a deployment time referenced to the crash pulse start. These are not the same instant, and mixing them is the most common source of a false "late deployment" flag. Normalize everything to t = 0 at the crash pulse onset (the first sample where longitudinal deceleration exceeds the recording threshold, commonly 1–2 g).

# EDR fields (example values, illustrative only)
edr = {
    "pulse_start_offset_ms": 0,      # reference origin
    "deployment_command_ms": 18,     # algorithm fire signal, relative to pulse start
    "bag_full_inflation_ms": 35,     # from inflator spec / OEM data
    "recording_rate_hz": 1000,
}

t_deploy = edr["deployment_command_ms"] / 1000.0        # 0.018 s
t_full   = (edr["deployment_command_ms"] +
            edr["bag_full_inflation_ms"]) / 1000.0       # 0.053 s
print(f"deploy command @ {t_deploy*1000:.0f} ms, full inflation @ {t_full*1000:.0f} ms")

If the EDR reports deployment relative to a different anchor (e.g., "time to deploy" measured from algorithm enable), reconcile the anchor explicitly before proceeding. A 5–10 ms anchor error is enough to shift a borderline case across the mitigation boundary.

Step 2 — Derive Occupant Forward Excursion from the Crash Pulse

The occupant's forward displacement relative to the vehicle interior is driven by the deceleration pulse and the restraint coupling. A first-order estimate integrates the vehicle velocity change and applies an occupant-coupling factor k (0 < k ≤ 1) representing how much of the vehicle deceleration the occupant has "caught up" with at a given time — before belt/airbag loading, the occupant continues forward at near pre-impact velocity.

import numpy as np

# Example crash pulse: deceleration in g, 1 kHz, first 120 ms
t = np.arange(0, 0.120, 0.001)
a_g = np.clip(28 * np.exp(-((t - 0.045) / 0.030)**2), 0, None)  # illustrative bell pulse
a = a_g * 9.81                                                  # m/s^2

v_vehicle = np.cumsum(a) * 0.001          # m/s, vehicle velocity change
v_occupant = v_vehicle * 0.15             # occupant lags: only 15% coupled early
excursion = np.cumsum(v_vehicle - v_occupant) * 0.001  # m, forward travel

# Find when occupant head reaches the airbag module plane (~0.30 m forward)
reach_idx = np.argmax(excursion >= 0.30)
print(f"occupant reaches bag plane @ {t[reach_idx]*1000:.0f} ms")

The coupling factor is a modeling assumption and must be stated as such; it is refined once belt-force or seat-track data are available. The point of the exercise is the relative ordering of three events: deployment command, full inflation, and occupant arrival at the bag plane.

Step 3 — Overlay Injury Risk Curves and Read the Window

HIC15 and Nij are computed from the occupant's head and neck response, which itself depends on when the bag is loaded. The diagnostic overlay compares the deployment envelope (command → full inflation → venting) against the injury-onset envelope (the time at which HIC15 and Nij begin to rise steeply). The mitigation window is the interval in which the bag is inflated and venting before injury-onset loading begins.

EventTime (ms, example)Interpretation
Crash pulse onset (t=0)0Reference origin
Deployment command18Algorithm fire signal
Bag full inflation53Bag ready to cushion
Occupant reaches bag plane62First contact with inflated bag
HIC15 onset (steep rise)70Injury loading begins
Nij onset (steep rise)74Neck loading begins

In this example the bag is fully inflated (53 ms) and venting before the occupant arrives (62 ms) and before injury onset (70–74 ms): the deployment is inside the mitigation window. If full inflation occurred after occupant arrival, the case is flagged as late deployment; if the occupant was already forward of the bag plane at command time (e.g., unbelted, out-of-position), it is flagged as out-of-position exposure regardless of timing.

Do not treat a deployment command earlier than the injury-onset time as automatically "good." An early command with a slow inflator can still produce late full inflation, and an out-of-position occupant can be injured by the deploying bag itself. Always compare the full-inflation time, not just the command time, against occupant arrival.
Deployment Envelope vs. Injury-Onset Envelope Example case: bag fully inflated before occupant arrival and injury onset → inside mitigation window Time from crash pulse onset (ms) Response / risk (normalized) 0 20 40 60 80 100 120 mitigation window command 18 full inflation 53 occupant arrival 62 HIC₁₅ Nij deployment envelope injury-onset curves

Flagging Logic and Verification

Encode the comparison as an explicit decision so the diagnosis is auditable rather than a visual impression:

def classify(t_deploy, t_full, t_arrival, t_hic_onset, t_nij_onset):
    injury_onset = min(t_hic_onset, t_nij_onset)
    if t_arrival < t_full:
        return "OUT_OF_POSITION" if t_arrival < t_deploy else "LATE_DEPLOYMENT"
    if t_full <= t_arrival and t_full <= injury_onset:
        return "INSIDE_WINDOW"
    return "LATE_DEPLOYMENT"

print(classify(0.018, 0.053, 0.062, 0.070, 0.074))  # -> INSIDE_WINDOW

Verification criteria: (1) all times share the same origin and units; (2) the occupant-arrival estimate is monotonic and consistent with the pulse integral; (3) the classification is stable under a ±5 ms perturbation of the deployment time — if it flips, report the case as borderline rather than asserting a definitive flag. Typical failure symptoms: a "late deployment" flag that disappears once the anchor is corrected (anchor error), or an "inside window" result that contradicts a high HIC15 (coupling factor too low, occupant modeled as arriving too late).

Keep the deployment command, full-inflation, occupant-arrival, and injury-onset times in a single table per case. The four numbers, plus the classification, form a compact audit record that can be re-checked when inflator specs or occupant models are updated.