☰
Python实战:正面40%偏置碰撞测试数据分析与可视化
2026/10/5 20:11:15 网站建设 项目流程

前一段时间在做车辆模拟碰撞相关的数据分析时,一直想找一个能完整呈现“正面 40% 偏置碰撞”测试思路的练习案例。正好手头有一套模拟环境,可以复现一台 2005 年的老旧 SUV 在不同碰撞条件下产生的动态响应。本文就以《【BASA】2005 Bruckell VRV 正面40%碰撞测试》为场景,完整梳理从测试场景设定、数据采集,再到 Python 解析与可视化的一整套流程。

这篇文章比较适合对车辆碰撞安全、仿真测试数据分析和 Python 数据处理感兴趣的读者。如果你手头有类似的气囊标定数据、碰撞仿真输出或整车道路试验数据,也可以在阅读过程中对比这份思路。文章不会下任何“车辆安全性好坏”的结论,重点是把“如何分析一次碰撞测试结果”这件事讲清楚。

1. 什么是正面 40% 偏置碰撞测试

1.1 碰撞测试的基本分类

车辆碰撞测试按照碰撞形式可以简单分成三大类:正面碰撞、侧面碰撞和追尾碰撞。正面碰撞又可以继续细化成正面 100% 重叠刚性墙碰撞、正面 40% 偏置碰撞、正面 25% 小重叠碰撞等。

不同重叠率模拟的是不同的真实事故场景:

  • 100% 重叠刚性墙碰撞,用来模拟整车正面直接撞墙的工况,对车身纵梁、防火墙和约束系统考核比较全面。
  • 40% 偏置碰撞,模拟车头一侧约 40% 的宽度与对向车辆或障碍物发生重叠碰撞,这种工况对乘员舱结构强度要求更高。
  • 25% 小重叠碰撞,模拟车头外侧与树、护栏等刚性物体刮擦碰撞,对 A 柱、门槛梁和侧围结构压力比较大。

本文提到的“正面 40% 碰撞测试”,指的就是正面前方障碍物与车辆前端 40% 重叠的碰撞工况。这类试验对车辆结构侵入、假人伤害指标、安全带约束效果都有很强的区分度。

1.2 为什么 40% 偏置碰撞更值得关注

在实际交通事故中,两车正面相撞时很少是完整的车头对车头。驾驶员通常会下意识打方向避让,所以很多正面碰撞都伴随着一定偏置量。40% 偏置碰撞正是基于这种真实场景设计的。

从力学角度分析,车头右侧 40% 参与碰撞时,吸能区域不完整,碰撞力会通过左侧纵梁、副车架传递到乘员舱。如果车身结构设计不够好,防火墙、A 柱下段、门槛梁就会发生明显变形,进而挤压驾驶员腿部空间和仪表板区域。

所以 40% 偏置碰撞测试关注的核心指标不只是整车减速过程,还包括:

  • 乘员舱结构侵入量
  • A 柱是否发生弯折
  • 防火墙是否明显后移
  • 转向管柱是否发生位移
  • 门框变形是否影响车门开启

在模拟环境中,我们同样可以从这些维度去分析 Bruckell VRV 这台车的表现。

1.3 模拟碰撞测试的特点

在当前项目中,我们的碰撞测试是在车辆动力学模拟软件中完成的。相比真实物理碰撞试验,模拟测试有这些优点:

  1. 成本低,不需要制造实车样件,不需要报废整车。
  2. 可重复性高,同一参数可以反复运行,测试结果不会因环境波动产生差异。
  3. 参数调整方便,可以通过修改碰撞重叠率、初始速度、障碍物刚度等快速对比。
  4. 数据采集灵活,可以同时记录成百上千个通道的传感器数据,不担心传感器损坏或丢失。

当然,模拟测试也有局限性。它依赖车辆动力学模型、材料失效模型和接触算法,结果只能无限接近真实试验,不能完全替代法规认证。这也是本文反复强调的一点:模拟数据用于开发阶段横向对比和趋势分析,不要把它当成国家法规认证结果。

2. 测试场景与数据分析环境准备

2.1 BASA 项目与测试车辆信息

本次测试项目代号为“BASA”,可以理解为一套“基础整车安全分析”练习流程。测试对象是一台 2005 年款 Bruckell VRV,这是一台带有复古风格的家用 SUV 车型,轴距较长、车身较高,整备质量在同级车型中属于偏大的类型。

由于车辆年款较老,车身结构设计更多强调舒适性和实用性,对轻量化高强钢的使用比例并不高。在碰撞安全分析中,老旧车型往往更容易暴露结构吸能不足、A 柱变形偏大等问题。这也是我们选择这台车作为分析样本的原因之一。

下表整理了本次模拟分析的基本参数:

参数项设定值
测试车辆2005 Bruckell VRV
碰撞类型正面 40% 偏置碰撞
碰撞重叠率40%
试验质量整备质量 + 驾驶员模拟质量
碰撞速度以测试场景实际设定为准
地面条件干燥平整沥青路面
温度环境常温 20℃ 左右

需要特别说明:以上参数是模拟场景中使用的预设值,真实测试标准会严格按照法规要求执行。这里只是展示分析思路,参数本身需要根据你自己的软件版本和场景设定来调整。

2.2 数据分析软件清单

在做碰撞测试数据分析之前,首先确认电脑里的基础环境:

  • 操作系统:Windows 10/11 或 Ubuntu 20.04+ 均可
  • Python 版本:Python 3.8 及以上
  • 编辑器:VS Code、PyCharm 或 Jupyter Notebook 任选
  • 核心依赖库:pandas、numpy、matplotlib、scipy

如果还没有安装这些库,可以在终端中执行下面的命令:

pip install pandas numpy matplotlib scipy

如果你使用的是 Anaconda,也可以使用 conda 安装:

conda install pandas numpy matplotlib scipy

安装完成之后,可以通过一条命令检查版本是否正常:

python -m pip list | findstr pandas

这里先不粘贴具体的版本号,因为每个人的环境不同。只要 pandas、numpy、matplotlib 能正常导入,就可以继续往下操作。

2.3 数据文件组织方式

一次典型的碰撞测试会生成多个数据文件,包括车辆轨迹、姿态、速度和加速度波形等。建议在项目目录中按下列方式组织文件:

BASA-2005-VRV/ ├── data/ │ ├── crash_40_overlap/ │ │ ├── telemetry.csv │ │ ├── vehicle_state.csv │ │ └── intrusion_points.json │ └── readme.md ├── scripts/ │ ├── load_data.py │ ├── speed_analysis.py │ ├── acceleration_analysis.py │ └── intrusion_analysis.py └── output/ └── figures/

这样的目录结构好处很明显:原始数据、处理脚本和输出图表彼此隔离,不容易出现误改数据文件的问题。尤其是当你手头有多组碰撞工况对比的时候,建议每一组工况单独建一个数据文件夹。

3. 碰撞测试结果的关键分析指标

3.1 车辆速度变化曲线

碰撞过程最直观的表现就是速度变化。车辆从初始速度逐步降到零,整个过程一般在几十毫秒到上百毫秒内完成。

速度曲线主要关注三个信息:

  1. 碰撞初始速度:决定了碰撞能量的大小。
  2. 速度归零时间点:反映了碰撞吸能的持续时间。
  3. 速度曲线的斜率:斜率越陡,说明碰撞越剧烈。

如果速度曲线在短时间内发生剧烈跳变,往往意味着车身结构没有充分参与吸能,或者是传感器数据本身存在噪声。

3.2 加速度与碰撞强度

加速度是碰撞测试中最重要的物理量之一。车辆在碰撞过程中的加速度变化,直接反映了乘员受到的惯性载荷大小。

碰撞加速度通常用 g 表示,1g 约等于 9.8 m/s²。加速度值越大,乘员受到的冲击越强烈。

分析加速度时,一般会使用滤波处理后的波形。滤波的作用是去掉高频噪声,保留与车辆结构响应相关的低频成分。常见的滤波方式包括 SAE J211 标准滤波和低通滤波。

在实际代码中,我们可以先计算原始加速度数据,再用 scipy 的 butterworth 滤波器做平滑处理。后面的演示代码会具体展示。

3.3 乘员舱侵入量

除了整车的速度、加速度,车身局部变形量同样是判断碰撞结果的重要指标。乘员舱侵入量主要指 A 柱、防火墙、地板、转向管柱、踏板等区域相对乘员舱原始位置的位移。

侵入量越大,乘员被结构挤压的风险越高。尤其对老旧 SUV 来说,防火墙刚度不足时,碰撞后制动踏板和转向管柱会向驾驶员方向移动,这是非常危险的。

在模拟软件中,我们可以直接输出几个关键测量点在碰撞前后的坐标,然后在 Python 中计算空间位移量。

4. 基于 Python 的碰撞数据读取方法

4.1 读取 CSV 遥测文件

碰撞测试软件导出的数据格式并不统一,常见的包括 CSV、Excel、JSON 甚至二进制格式。为了演示,假设我们已经导出了一份 telemetry.csv 文件,里面包含时间戳、速度、加速度等字段。

下面是一段读取并预览数据的代码:

# 文件路径:scripts/load_data.py import pandas as pd # 读取碰撞过程遥测数据 df = pd.read_csv('../data/crash_40_overlap/telemetry.csv') # 查看数据列名 print("数据列名:") print(df.columns.tolist()) # 查看前 5 行 print("\n前 5 行数据预览:") print(df.head()) # 查看数据基本统计信息 print("\n数据统计信息:") print(df.describe())

运行后,你会看到类似下面的输出结构:

数据列名: ['time', 'speed_kmh', 'accel_x_g', 'accel_y_g', 'accel_z_g'] 前 5 行数据预览: time speed_kmh accel_x_g accel_y_g accel_z_g 0 0.00 35.40 -0.02 0.01 1.00 1 0.02 ...

注意:不同模拟软件导出的列名可能不同,如果直接复制这段代码发现 KeyError,不用紧张,先用 print(df.columns) 查看字段名,再去改列名即可。

4.2 时间轴对齐与空值处理

碰撞数据经常会出现两种问题:一是时间戳不连续,二是某些传感器在某段时间内无数据。直接分析会导致曲线突变或中断,因此需要先对时间轴进行检查和处理。

# 文件路径:scripts/load_data.py import numpy as np import pandas as pd df = pd.read_csv('../data/crash_40_overlap/telemetry.csv') # 检查是否存在空值 print("每列空值数量:") print(df.isnull().sum()) # 如果存在空值,可以选择删除或插值 # 碰撞数据中短时间缺失采用线性插值比较合理 if df.isnull().sum().sum() > 0: df = df.interpolate(method='linear', limit_direction='both') # 检查时间列是否单调递增 time_diff = np.diff(df['time'].values) if (time_diff <= 0).any(): print("警告:时间轴存在非递增时刻,需要排序") df = df.sort_values(by='time').reset_index(drop=True) print("数据清洗完成,总记录数:", len(df))

这里选用线性插值而不是删除缺失行,是因为碰撞过程非常短,任何瞬间的缺失都可能影响后续峰值的判断。当然,如果数据缺失过多,整段传感器的可靠性就得打问号了。

4.3 JSON 格式侵入点数据读取

侵入量数据有时会以 JSON 格式保存,因为里面通常包含多个测量点的三维坐标。下面演示如何读取并转换成 DataFrame:

# 文件路径:scripts/load_data.py import json import pandas as pd # 读取侵入点数据 with open('../data/crash_40_overlap/intrusion_points.json', 'r', encoding='utf-8') as f: intrusion_data = json.load(f) # 将每个测量点转换为行记录 records = [] for point_name, info in intrusion_data.items(): records.append({ 'point': point_name, 'initial_x': info['initial']['x'], 'initial_y': info['initial']['y'], 'initial_z': info['initial']['z'], 'final_x': info['final']['x'], 'final_y': info['final']['y'], 'final_z': info['final']['z'], }) df_points = pd.DataFrame(records) # 计算合位移 df_points['displacement'] = ( (df_points['final_x'] - df_points['initial_x']) ** 2 + (df_points['final_y'] - df_points['initial_y']) ** 2 + (df_points['final_z'] - df_points['initial_z']) ** 2 ) ** 0.5 print(df_points.sort_values(by='displacement', ascending=False))

这段代码会输出每个测量点在碰撞前后的三维位移量。对我们分析碰撞侵入情况非常关键。

5. 碰撞数据分析与可视化实战

5.1 速度曲线分析

车辆碰撞的过程中,车速从初始碰撞速度逐渐下降。为了观察速度变化的整体趋势,我们可以绘制散点或折线图。

# 文件路径:scripts/speed_analysis.py import matplotlib.pyplot as plt import pandas as pd # 读取数据 df = pd.read_csv('../data/crash_40_overlap/telemetry.csv') # 截取碰撞时间段,比如碰撞前 0.1 秒到碰撞后 0.3 秒 mask = (df['time'] >= -0.1) & (df['time'] <= 0.3) df_crash = df[mask].copy() # 将速度单位从 km/h 换算成 m/s df_crash['speed_mps'] = df_crash['speed_kmh'] / 3.6 # 绘制速度曲线 plt.figure(figsize=(10, 5), dpi=120) plt.plot(df_crash['time'], df_crash['speed_kmh'], label='Vehicle Speed (km/h)', color='#E74C3C', linewidth=2) plt.axhline(y=0, color='gray', linestyle='--', linewidth=0.8) plt.xlabel('Time (s)') plt.ylabel('Speed (km/h)') plt.title('2005 Bruckell VRV - Frontal 40% Overlap Crash Speed') plt.grid(alpha=0.3) plt.legend() plt.tight_layout() plt.savefig('../output/figures/speed_curve.png', dpi=150) plt.show()

这段代码的关键点在于先过滤出碰撞时间段,再绘图。如果不做时间段裁剪,画出来的曲线会被前后很长一段匀速或减速过程压扁,碰撞阶段的细节就看不清楚了。

5.2 加速度波形计算与滤波

加速度信号通常比较“毛躁”,直接画原图会看到很多高频抖振。为了观察趋势,需要先滤波。

使用巴特沃斯低通滤波器是常见选择。下面的代码实现了 100Hz 低通滤波,并绘制碰撞过程中的纵向加速度曲线:

# 文件路径:scripts/acceleration_analysis.py import numpy as np import pandas as pd import matplotlib.pyplot as plt from scipy.signal import butter, filtfilt # 读取数据 df = pd.read_csv('../data/crash_40_overlap/telemetry.csv') # 定义低通滤波函数 def lowpass_filter(data, cutoff_hz, sample_rate_hz, order=4): nyquist = 0.5 * sample_rate_hz normal_cutoff = cutoff_hz / nyquist b, a = butter(order, normal_cutoff, btype='low', analog=False) return filtfilt(b, a, data) # 根据时间列估算采样率 dt = np.median(np.diff(df['time'].values)) sample_rate = 1.0 / dt print(f"估算采样率:{sample_rate:.0f} Hz") # 截取碰撞时间段 mask = (df['time'] >= 0.0) & (df['time'] <= 0.2) df_crash = df[mask].copy() # 对纵向加速度进行低通滤波 filtered_accel = lowpass_filter(df_crash['accel_x_g'].values, cutoff_hz=100, sample_rate_hz=sample_rate) # 绘制原始与滤波后加速度对比 plt.figure(figsize=(12, 6), dpi=120) plt.plot(df_crash['time'], df_crash['accel_x_g'], alpha=0.3, label='Original Accel X', color='#BDC3C7') plt.plot(df_crash['time'], filtered_accel, label='Filtered Accel X (100Hz)', color='#2980B9', linewidth=2) plt.axhline(y=0, color='gray', linestyle='--', linewidth=0.8) plt.axhline(y=np.min(filtered_accel), color='#E74C3C', linestyle=':', linewidth=1.5) plt.text(df_crash['time'].iloc[-1], np.min(filtered_accel), f"Peak: {np.min(filtered_accel):.2f} g", ha='right', va='bottom', color='#E74C3C') plt.xlabel('Time (s)') plt.ylabel('Acceleration (g)') plt.title('BASA - Bruckell VRV Frontal 40% Overlap Longitudinal Acceleration') plt.grid(alpha=0.3) plt.legend() plt.tight_layout() plt.savefig('../output/figures/acceleration_curve.png', dpi=150) plt.show() # 输出峰值信息 print(f"滤波后纵向加速度最大负向峰值:{np.min(filtered_accel):.2f} g")

峰值加速度所在的时间点,对应乘员受到最大惯性载荷的时刻。可以把该时间点与前面速度曲线归零的时间点做对比,从而判断碰撞峰值的发生时机是否合理。

5.3 侵入量变化趋势图

侵入量分析主要是横向对比。我们可以把各测量点的时域侵入过程画出来,考察车门框、防火墙、门槛梁是否存在过大位移。

# 文件路径:scripts/intrusion_analysis.py import json import matplotlib.pyplot as plt import numpy as np # 读取侵入点数据 with open('../data/crash_40_overlap/intrusion_points.json', 'r', encoding='utf-8') as f: intrusion_data = json.load(f) # 初始化图表 plt.figure(figsize=(12, 6), dpi=120) # 每个测量点都包含时域位移信息 for point_name, info in intrusion_data.items(): if 'series' not in info: continue time_series = np.array(info['series']['time']) displacement_series = np.array(info['series']['displacement']) plt.plot(time_series, displacement_series, linewidth=1.5, label=point_name) plt.xlabel('Time (s)') plt.ylabel('Intrusion Displacement (mm)') plt.title('BASA - Key Cabin Points Intrusion Timeline') plt.grid(alpha=0.3) plt.legend(loc='upper left') plt.tight_layout() plt.savefig('../output/figures/intrusion_timeline.png', dpi=150) plt.show()

绘制侵入量时间历程的好处是:我们可以判断变形是发生在碰撞瞬间,还是在碰撞后期依然持续增大。如果在车辆速度归零之后侵入量还在增长,说明结构存在“压溃后继续蠕变”的情况。

5.4 多工况对比思路

实际数据分析中,单次测试结果并不能说明问题。横向对比是很常用的手段,比如对比 40% 偏置碰撞与 100% 正面碰撞的加速度峰值。

你可以把多组数据放在同一个 DataFrame 中管理,然后用分组统计的方式计算峰值:

# 文件路径:scripts/multi_case_compare.py import pandas as pd # 假设已有多个工况的文件列表 file_list = [ ('40%_overlap', 'data/crash_40_overlap/telemetry.csv'), ('100%_frontal', 'data/crash_100_frontal/telemetry.csv'), ] rows = [] for case_name, file_path in file_list: df = pd.read_csv(file_path) # 只统计碰撞后 0~0.2 秒的数据 df_crash = df[(df['time'] >= 0.0) & (df['time'] <= 0.2)] peak_g = df_crash['accel_x_g'].min() rows.append({'case': case_name, 'peak_accel_g': round(peak_g, 2)}) summary = pd.DataFrame(rows) print(summary)

这种横向对比输出非常适合用来快速观察不同工况的差异。

6. 常见报错与排查清单

在做碰撞数据分析的过程中,有一些高频问题经常出现。下面整理成表格,方便大家排查。

问题现象常见原因解决思路
读取 CSV 后提示 Column not found软件导出的列名与代码不一致先打印 columns 字段,确认实际列名
时间轴不连续导致曲线断裂模拟帧率波动或导出丢帧使用 np.diff 检查时间间隔,做重采样处理
加速度曲线噪声非常大未进行滤波或采样率过高使用巴特沃斯低通滤波器,选择合适截止频率
速度曲线碰撞后没有归零数据导出范围被截断检查导出时间范围,延长碰撞后记录时间
JSON 文件读取为字符串json.load 前没有正确打开文件检查文件编码,使用 utf-8 打开
matplotlib 中文乱码系统缺少中文字体绘图时设置 rc 参数指定中文字体
峰值加速度数值偏大原始信号包含高频噪声检查滤波截止频率和滤波器阶数
侵入量曲线不平滑测量点接触算法抖动使用滑动平均或增加数据导出频率

6.1 JSON 文件编码问题详解

Windows 系统下导出的 JSON 文件经常使用 UTF-8 编码,但也可能有部分工具使用 GBK。如果直接读取报编码错误,可以改成:

with open(file_path, 'r', encoding='utf-8-sig') as f: data = json.load(f)

utf-8-sig 会自动去除带 BOM 的文件头,适合大多数从 Windows 导出的文件。

6.2 滤波器参数如何选择

SAE J211 是汽车碰撞试验中比较常用的滤波标准,不同通道对应不同频率等级。例如:

  • 车身结构加速度通道通常使用 CFC 60
  • 假人头部加速度通道使用 CFC 1000
  • 假人颈部力通道使用 CFC 1000

本文只是 Python 演示,采用了简化的 100Hz 低通滤波思路。实际工程中应该严格按照对应法规标准来滤波。模拟数据对比时,要保证多组数据使用完全相同的滤波参数,否则结果没有可比性。

7. 碰撞测试项目中的工程建议

7.1 数据命名与版本管理

一次整车级别的碰撞分析会涉及非常多的数据文件。如果不做数据命名规范,过两周再回来看完全不知道每个文件对应什么工况。

建议命名规则:

日期_车辆代号_碰撞类型_速度_重复次数

例如:

20250104_BruckellVRV_F40_64kmh_run01.csv

这样可以避免文件重名、覆盖和漏算。开发中用到 Git 管理时,还要注意不要把上百 MB 的数据文件直接提交到代码仓库,建议采取数据文件与脚本分离的方式。

7.2 数据采集与备份策略

碰撞模拟虽然不会像真实试验那样一次撞毁几台车,但运行时如果忘记导出数据或软件崩溃,同样会导致数据丢失。

建议:

  1. 运行前检查输出路径是否存在。
  2. 每个工况运行完成后立即备份到独立目录。
  3. 碰撞关键通道建议使用冗余记录。
  4. 数据处理脚本输出统一存放,不要覆盖原始数据。

7.3 结果评价的安全边界

这里必须强调一点:模拟碰撞数据只能用于研发阶段的参数趋势分析,不能直接用来申报或证明某款车满足法规安全要求。不同软件版本、不同车辆模型参数之间的差异,可能导致结果偏差很大。

我们在公开平台讨论 Bruckell VRV 这类模拟测试时,也应该保持严谨的态度。不要使用“某车不安全”“某车垃圾”等绝对化表述。因为:

  1. 车辆型号属于虚构游戏车型,不是真实品牌车辆。
  2. 模拟测试中驾驶员模型、约束系统模型都做了一定简化。
  3. 一次碰撞测试结果无法代表车辆在真实复杂事故中的所有表现。

从数据分析的角度看,我们要关注的是方法流程是否规范、数据处理是否合理、结论是否可复现。

7.4 报告输出的最小要素

一份完整的碰撞数据分析报告,至少需要包含以下内容:

  • 测试目的与工况说明
  • 车辆参数与模型版本信息
  • 数据通道列表与采样率说明
  • 滤波方法与处理参数
  • 关键结果图表
  • 量化指标统计表
  • 异常数据说明
  • 结论与局限性分析

这样写出来的分析报告才具备可追溯性,也方便他人复核。

8. 完整脚本整合与运行

为了方便你直接复现,这里提供一份整合后的分析主脚本。把下面代码保存到 scripts/main_analysis.py,然后在项目根目录执行即可。

# 文件路径:scripts/main_analysis.py """ BASA - 2005 Bruckell VRV 正面 40% 碰撞测试数据分析示例 仅用于模拟环境数据分析学习,不代表真实车辆安全评价。 """ import json import numpy as np import pandas as pd import matplotlib.pyplot as plt from scipy.signal import butter, filtfilt # ========== 全局配置 ========== DATA_DIR = '../data/crash_40_overlap' OUTPUT_DIR = '../output/figures' # ========== 1. 读取遥测数据 ========== telemetry_path = f'{DATA_DIR}/telemetry.csv' df = pd.read_csv(telemetry_path) # 数据清洗与排序 if df.isnull().sum().sum() > 0: df = df.interpolate(method='linear', limit_direction='both') time_diff = np.diff(df['time'].values) if (time_diff <= 0).any(): df = df.sort_values(by='time').reset_index(drop=True) # ========== 2. 读取侵入点数据 ========== intrusion_path = f'{DATA_DIR}/intrusion_points.json' with open(intrusion_path, 'r', encoding='utf-8-sig') as f: intrusion_data = json.load(f) def lowpass_filter(data, cutoff_hz, sample_rate_hz, order=4): nyquist = 0.5 * sample_rate_hz normal_cutoff = cutoff_hz / nyquist b, a = butter(order, normal_cutoff, btype='low', analog=False) return filtfilt(b, a, data) # ========== 3. 计算碰撞阶段统计指标 ========== df_crash = df[(df['time'] >= 0.0) & (df['time'] <= 0.2)].copy() dt = np.median(np.diff(df['time'].values)) sample_rate = 1.0 / dt filtered_accel = lowpass_filter(df_crash['accel_x_g'].values, cutoff_hz=100, sample_rate_hz=sample_rate) peak_accel = np.min(filtered_accel) speed_min = df_crash['speed_kmh'].min() print('碰撞阶段分析结果:') print(f'估算采样率: {sample_rate:.0f} Hz') print(f'滤波后纵向峰值加速度: {peak_accel:.2f} g') print(f'碰撞阶段最低速度: {speed_min:.2f} km/h') # ========== 4. 侵入点位移统计 ========== print('\n关键测量点侵入量统计:') for point_name, info in intrusion_data.items(): initial = info.get('initial', {}) final = info.get('final', {}) displacement = ( (final['x'] - initial['x']) ** 2 + (final['y'] - initial['y']) ** 2 + (final['z'] - initial['z']) ** 2 ) ** 0.5 print(f'{point_name}: {displacement:.2f} mm') # ========== 5. 绘制关键图表 ========== fig, axes = plt.subplots(2, 2, figsize=(14, 10), dpi=120) # 子图1:速度曲线 ax = axes[0][0] df_full_time = df[(df['time'] >= -0.1) & (df['time'] <= 0.3)] ax.plot(df_full_time['time'], df_full_time['speed_kmh'], color='#E74C3C', linewidth=2) ax.set_xlabel('Time (s)') ax.set_ylabel('Speed (km/h)') ax.set_title('Vehicle Speed vs Time') ax.grid(alpha=0.3) # 子图2:加速度曲线 ax = axes[0][1] ax.plot(df_crash['time'], df_crash['accel_x_g'], alpha=0.3, color='#BDC3C7') ax.plot(df_crash['time'], filtered_accel, color='#2980B9', linewidth=2) ax.axhline(y=peak_accel, color='#E74C3C', linestyle=':') ax.set_xlabel('Time (s)') ax.set_ylabel('Acceleration (g)') ax.set_title('Longitudinal Acceleration (Filtered)') ax.grid(alpha=0.3) # 子图3:侵入量时间历程 ax = axes[1][0] for point_name, info in intrusion_data.items(): if 'series' not in info: continue series_time = np.array(info['series']['time']) series_disp = np.array(info['series']['displacement']) ax.plot(series_time, series_disp, linewidth=1.5, label=point_name) ax.set_xlabel('Time (s)') ax.set_ylabel('Displacement (mm)') ax.set_title('Key Points Intrusion Timeline') ax.grid(alpha=0.3) ax.legend(fontsize=8) # 子图4:侵入量条形图 ax = axes[1][1] points = [] disp_values = [] for point_name, info in intrusion_data.items(): initial = info.get('initial', {}) final = info.get('final', {}) displacement = ( (final['x'] - initial['x']) ** 2 + (final['y'] - initial['y']) ** 2 + (final['z'] - initial['z']) ** 2 ) ** 0.5 points.append(point_name) disp_values.append(displacement) ax.bar(points, disp_values, color='#16A085') ax.set_xlabel('Measure Points') ax.set_ylabel('Total Displacement (mm)') ax.set_title('Final Intrusion by Measure Point') plt.setp(ax.get_xticklabels(), rotation=30, ha='right') plt.tight_layout() plt.savefig(f'{OUTPUT_DIR}/basa_summary.png', dpi=150) plt.show() print('\n图表已输出到', OUTPUT_DIR)

执行方式:

cd scripts python main_analysis.py

如果你使用 Jupyter Notebook,也可以直接按单元格拆分运行。这样更容易观察每一步的数据形状和中间结果。

9. 总结与下一步学习建议

通过这次《【BASA】2005 Bruckell VRV 正面40%碰撞测试》的数据分析,我们完整走了一遍“场景理解 - 数据读取 - 数据清洗 - 速度分析 - 加速度分析 - 侵入量分析 - 可视化呈现”的项目流程。

从技术层面可以掌握这几个关键点:

  • 正面 40% 偏置碰撞测试的基本原理和分析维度
  • 碰撞数据常见的 CSV、JSON 文件读取和处理方法
  • 速度曲线、加速度波形、侵入量数据在 Python 中的可视化方式
  • 低通滤波在加速度信号处理中的应用
  • 多工况对比分析的基本思路
  • 模拟碰撞数据的局限性和工程合规边界

如果你是刚开始接触车辆数据分析,建议下一步从这几件事入手:

  1. 多跑几个不同速度、不同重叠率的碰撞场景,把数据放在同一套脚本里做横向对比。
  2. 尝试加入假人模型,重点关注头部加速度、胸部压缩量和颈部受力等伤害指标。
  3. 继续学习信号处理知识,深入理解不同滤波频率对结果的影响。

模拟环境中一次碰撞的完整数据,往往隐藏着大量值得挖掘的信息。先把数据读取和清洗这一步做扎实,后续不管是做结构优化、约束系统标定,还是生成评测报告,都会顺手很多。

如果文章里这段代码和排查思路对你有帮助,可以先收藏备用。后面有更多实战数据再继续补充分析细节。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询