ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Matlab绘制NVH瀑布图全流程:从Workbench与Simcenter数据到Campbell图

Matlab绘制NVH瀑布图全流程:从Workbench与Simcenter数据到Campbell图 搞振动噪声的人迟早都要跟瀑布图打交道。不管是电机加速过程的阶次噪声还是变速箱在各档位下的共振带分布又或者是压缩机起停机时的瞬态响应手里握着一堆Workbench、Simcenter 3D的仿真结果最后想在一张图里讲清楚“频率随时间/转速怎么变、幅值有多少”最直观的做法就是用Matlab把瀑布图画出来。我之前帮同事处理过一组电机NVH数据ANSYS Workbench谐响应算了几十个频率点Simcenter 3D又导出一批时域响应两边数据格式还不一样频率轴一个密一个疏幅值单位一个用mm/s²一个用dB。折腾了一下午最终靠Matlab脚本把数据统一成三维矩阵用surf、waterfall、contourf各出了一版图。这个流程踩过不少坑今天就完整拆开讲讲从仿真软件导出什么数据、Matlab怎么读、三维矩阵怎么组织到瀑布图四种画法、工程级显示调优、转频线和阶次线叠加最后附上我实际踩过的坑和排查方法。这套内容适合两类人一类是刚接触NVH的仿真工程师对着导出的数据不知从哪下手另一类是已经会画简单瀑布图但想让图更专业、能直接放进报告里的朋友。只要你Matlab基础操作没问题照着下面的思路走基本半小时能出一张能看的图。1. 瀑布图是什么NVH分析为什么绕不开它1.1 从一堆仿真曲线到一眼看穿整个变速工况想象一个简单的工况电机从1000 rpm匀加速到6000 rpm整个过程持续5秒。如果你只看某一个转速下的频谱只能知道“这个转速下有哪些峰值频率”但共振不是只在一个转速点出现它跟激励频率、结构固有频率是否匹配有关。随着转速上升各个阶次的激励频率也在扫过结构固有频率某个转速下幅值突然蹿高就可能触发了共振。一张图能同时容纳三个维度信息就是瀑布图的核心价值横轴是频率纵轴是转速或时间高度颜色是响应幅值。这样一来横线是恒定频率的共振带斜线是随转速变化的阶次线共振带和阶次线的交点往往就是临界转速。没有瀑布图你得翻几十张频谱图肉眼对比有了瀑布图一眼扫过去全清楚了。1.2 先分清你画的到底是哪种瀑布图这里有个容易混淆的概念。工程里说的瀑布图其实至少有两种一种是把不同工况点比如不同转速、不同测点、不同阻尼比的频谱曲线在三维空间里等距排列用z方向高度表示幅值看起来像一排平行的“帘幕”这种在模态测试里很常见用来对比不同状态下频谱形状的变化。另一种是Campbell图也叫阶次瀑布图纵轴是转速或时间颜色/高度表示该时刻各频率分量的幅值电驱NVH、转子动力学、发动机噪声分析都用这种。它强调的是“频率成分随转速/时间如何演化”重点看斜线阶次线和竖线结构共振的交点。本文重点讲第二种因为Workbench的谐响应结果、Simcenter 3D的瞬态响应结果做完后最常需要的就是这种Map图。但画法本身是通用的理解了三维矩阵的组织方式两种瀑布图都能画。2. 仿真端的数据导出Workbench与Simcenter 3D的准备工作2.1 Workbench导出响应谱的两种常用姿势用ANSYS Workbench做振动分析最常遇到的情况是已经算完了谐响应Harmonic Response得到了某个节点或某个面上的位移/加速度/应力随频率变化的曲线。这时候导出数据要分两步走第一步选对结果对象。在Solution下插入Frequency Response选中你要监测的节点或者直接选一个面然后取平均值。建议多选几个关键节点因为实际共振点不一定在你最初猜的那个位置。我之前遇到过只看轴承座节点结果真正的共振在端盖边缘后来把几个候选节点的数据都导出来对比才发现之前漏了重要信息。第二步设置输出选项。在Frequency Response的Details面板里把Frequency Display设为Linear或Tabular然后在Worksheet里把结果复制出来或者右键导出为CSV/Excel格式。这里有个关键细节Workbench默认按“频率—实部—虚部”导出如果你要的是幅值记得在设置里把Solution Display改成Amplitude。如果是瞬态分析Transient Structural导出的就是每个时间步的位移/速度/加速度时域信号。这时候拿到的是时间序列要做FFT才能转成频谱工作量更大一点。但好处是时域数据包含了完整的启停过程做Campbell图的信息量比单纯的稳态谐响应更丰富后续处理的空间也大。2.2 Simcenter 3D的数据导出与单位陷阱Simcenter 3D以前叫NX Nastran在声振分析里用得非常多。做声学响应或振动响应分析后结果文件里可以提取节点或单元在某频率段内的响应谱。Simcenter 3D导出数据比Workbench稍微绕一点在Post-Processing里打开Response选Function-Export可以输出成CSV、TXT或者RPC格式。如果你后续还要用其他软件CSV和TXT是最稳妥的如果数据量巨大RPC格式更紧凑但Matlab直接读RPC需要额外工具包我一般建议直接导出CSV省得给自己找麻烦。单位问题一定要检查。Workbench默认用的单位制通常会在Quantity里标清楚但Simcenter 3D里你模型的单位制跟导出结果的单位可能不一致。我就遇到过模型用mm制建的结果加速度导出来是m/s²但频率轴是Hz幅值轴单位没标差点按mm/s²去读。建议导出后先看文件头部或者另存一份带单位说明的元数据养成习惯。另外Simcenter 3D的Frequency Response函数可以设置频率容差和干涉容差导出的频率点可能是非均匀分布的。这意味着你导出的两个文件频率轴大概率不一样后面Matlab里必须做重采样或者插值这一步躲不掉。2.3 数据落地规范决定后面省不省心我在处理仿真数据时有一个习惯先把数据落成一个统一的目录结构NVH_Data/ 01_1000rpm/ acc_node_1.csv acc_node_2.csv 02_1500rpm/ acc_node_1.csv 03_2000rpm/ ...文件命名里带上转速或时间信息后面Matlab批量读取时可以根据文件名自动提取工况参数不用人工一个个维护参数表。导出的CSV内部格式也尽量统一第一列频率第二列实部第三列虚部或者第一列频率第二列幅值。如果软件导出的格式不统一我建议在Matlab读取时做一个标准化函数统一字段名称而不是在仿真软件里反复调整导出设置。数据管理规范一点后面写脚本会省非常多时间。3. 用Matlab批量读数据整理成可绘图的三维矩阵3.1 不要手工导Excel用脚本批量读取很多人习惯从Workbench里把数据复制到Excel再手动在Matlab里xlsread。数据少还行一旦有几十个转速工况点手工操作不仅慢还容易串行。实际上Matlab有一套非常成熟的批量读取流程配合好点的文件命名规则可以做到全自动。下面是我常用的批量读取脚本片段% 批量读取NVH仿真导出的CSV文件 clear; clc; close all; % 设置数据目录 dataDir NVH_Data; fileList dir(fullfile(dataDir, *.csv)); % 预分配存储变量 freqData {}; ampData {}; rpmData []; for i 1:length(fileList) % 从文件名中提取转速例如 01_1000rpm_acc_node_1.csv - 1000 fileName fileList(i).name; tokens regexp(fileName, (\d)rpm, tokens); if isempty(tokens) continue; end rpm str2double(tokens{1}{1}); % 读取CSV raw readmatrix(fullfile(dataDir, fileName)); % 假设第一列是频率第二列是幅值 freq raw(:, 1); amp raw(:, 2); % 保存 freqData{end1} freq; %#okSAGROW ampData{end1} amp; %#okSAGROW rpmData(end1) rpm; %#okSAGROW end % 排序转速保证画图顺序正确 [rpmSorted, idx] sort(rpmData); freqData freqData(idx); ampData ampData(idx);注意readmatrix在R2019a之后才有如果你用旧版本Matlab改用csvread或者importdata都可以。另外dir返回的文件顺序不是按数字排序的所以一定要做一次sort否则画出来的图会出现转速乱跳的情况。文件是中文路径的话不同版本Matlab处理能力不同有时候会读出乱码或者报错。我的建议是所有目录和文件名尽量用英文省得折腾编码问题。3.2 频率轴不一致插值统一是必做步骤不同工况点的数据频率轴可能不一样因为仿真软件的频率分辨率、输出点数量是随频率或转速变化的。如果你直接把原始频率和幅值丢给surfMatlab要求X、Y、Z必须是网格点各个工况点的频率轴不一致根本构不成网格画出来要么报错要么图形很诡异。所以必须先定义一个统一的频率轴推荐用所有工况频率范围的并集或者直接指定一个你关心的频段。比如统一从0到2000 Hz步长1 Hz。然后把每个工况的幅值通过插值映射到这个统一频率轴上。% 定义统一的频率轴 freq_uniform 0:1:2000; % 根据实际需要调整 % 插值到统一频率轴 amp_interp zeros(length(rpmSorted), length(freq_uniform)); for i 1:length(rpmSorted) amp_interp(i, :) interp1(freqData{i}, ampData{i}, freq_uniform, linear, 0); end插值方法推荐linear精度对瀑布图足够了。如果数据点很密用spline会带来轻微的过冲可能在峰值附近出现假的小毛刺但如果数据点太少linear又会丢失峰值细节这时候需要结合原始仿真设置的频率步长来权衡。末端值设成0表示在某个转速下超出该工况实测范围之外的频率区间无响应。如果你手上的数据本身就是不均匀频率点也可以用griddata做更复杂的插值但常规情况下interp1就够了。3.3 三维矩阵的排列顺序画出来不花的前提拿到amp_interp矩阵后需要构建三个网格矩阵X是转速纵轴Y是频率横轴Z是幅值。注意surf/waterfall/pcolor这类函数的接受方式是X、Y、Z三个同尺寸的矩阵。% 构建网格矩阵 [X, Y] meshgrid(rpmSorted, freq_uniform); Z amp_interp;这里有个容易搞混的点amp_interp的行是转速列是频率但meshgrid(rpmSorted, freq_uniform)生成的第一维行对应freq_uniform第二维列对应rpmSorted所以转置一下才能对上。很多人画出来图花成一团就是这里行列搞反了。转置之后X(i,j)是某个频率的数值Y(i,j)是某个转速的数值Z(i,j)是对应的幅值。经常有人问为什么surf出来的坐标轴对不上80%以上的原因是矩阵顺序错了剩下的可能是数据没有排序。4. 四种瀑布图画法以及工程级显示设置的调优4.1 surf与mesh同套矩阵两种观察逻辑最直接的方式是用surf画彩色曲面图。面颜色代表幅值高低视觉冲击力最强适合在PPT和汇报里展示“哪里能量集中”。figure(Color, w); surf(X, Y, Z, EdgeColor, none, FaceAlpha, 0.95); xlabel(转速 (rpm)); ylabel(频率 (Hz)); zlabel(幅值 (mm/s^2)); view(45, 30); colormap(turbo); colorbar;view(45, 30)是我试过比较舒服的视角既能看出三维起伏又不至于把后端数据遮住太多。如果你想突出峰值可以试试view(90, 0)相当于俯视投影更像颜色图。surf的坑在于如果网格过密曲面太复杂旋转视角时会非常卡如果网格过疏共振带会变成一个一个的凸点看不出连续分布。建议转速方向至少20到50个点频率方向100到500个点就足够展示细节了再多只会拖慢渲染。如果文章或论文需要黑白打印surf的彩色填充会变成一片灰很难看清。这时候用mesh画线框图靠线条的疏密变化来表达幅值高低黑白打印后依然能读出来。figure(Color, w); mesh(X, Y, Z, EdgeColor, k, LineWidth, 0.5);mesh的视觉细节取决于网格多少太密会变成一团黑太疏又看不出变化。我通常先画surf做快速检查确定没问题后再用mesh出黑白版或者把两个都输出看场景用哪个。4.2 waterfall最经典的“瀑布”效果实现Matlab自带waterfall函数专门用来画这种沿一个方向排列的谱线。它的效果是一组等转速间隔的曲线沿频率方向排列看上去格外“工程”。很多专业NVH报告里的瀑布图就是这种风格。figure(Color, w); waterfall(X, Y, Z); xlabel(转速 (rpm)); ylabel(频率 (Hz)); zlabel(幅值); colormap(parula);waterfall默认只在X方向画线频率方向的连续性由颜色体现。如果希望每条频谱曲线更突出可以把转速间距设得稀疏一点。但waterfall有一个小问题当转速条数很多时前面的线会遮挡后面的谱峰导致局部亮点看不清。这时可以通过view(45, 50)稍微调高视角让后方暴露更多。这里有一个很多人不知道的细节waterfall画出来的线的颜色默认是随幅值变化的但如果你用quiver的方式去理解它X和Y的方向跟我们习惯的“频率在横轴、转速在纵轴”其实可以通过view来调整。如果发现转速方向跑到了左右水平方向可以交换X和Y或者用set(gca,YDir,reverse)调整视觉方向。4.3 pcolor/contourf俯视投影更适合定量判断三维视角的瀑布图适合讲故事但做定量判断——比如读出共振频率精确是多少、临界转速是多少——三维图并不方便因为视线有透视畸变很难直接从坐标轴上读准位置。这时候应该用俯视投影图。俯视图有两种常用画法pcolor和contourf。figure(Color, w); contourf(freq_uniform, rpmSorted, amp_interp, 40, LineStyle, none); xlabel(频率 (Hz)); ylabel(转速 (rpm)); colormap(turbo); colorbar;其实不需要构建三维网格矩阵直接用freq_uniform、rpmSorted和amp_interp就能画。这就是俯视图比三维图更简单方便的地方。contourf后面那个40是等值线的层级数层级越多颜色过渡越细腻但太多也会让颜色条读起来费劲。我一般先用40层看整体输出报告时换成20层视觉效果更干净。pcolor和contourf的区别是pcolor是逐格填色色块边界清晰但数据量太大时显得马赛克感很强contourf是对数据进行平滑插值后再填色视觉上更连续、更像专业NVH软件的Map图。所以做俯视图我推荐contourf为主pcolor只在数据点极少、想要强调“这是离散仿真结果”时才用。4.4 坐标轴视角、颜色映射与高清导出把三维图和俯视图弄出来后还要做一组统一的显示设置才能保证图能放进报告里不用再返工。坐标轴字号和方向仿真图的坐标轴标签尽量用中文不加单位不一定行业报告里常用英文或中文都可以但用户问的是可以直接复现的方法坐标轴设置用你习惯的语言就行。set(gca, FontName, Arial, FontSize, 11); grid on; box on;颜色映射推荐原因Matlab老版本默认的jet色彩映射虽然颜色鲜艳但有两个知名缺点——黄绿色段亮度太高容易把中等幅值区域显示得比实际更亮而且颜色顺序在色觉障碍的人眼里很难区分。现在Matlab已经默认parula另外我建议试试turbo它更接近jet的层次但亮度分布更均匀视觉上更清晰。导出图片时尽量避免直接print默认导出分辨率低、字体发虚。推荐用exportgraphics这是R2020a之后加入的函数可以指定分辨率exportgraphics(gcf, campbell_diagram.png, Resolution, 300);如果你还用旧版Matlab只能用print(gcf, -dpng, -r300, campbell_diagram.png)。打印导出最大的坑是尺寸默认的figure在导出后宽高比会和屏幕上看到的不一样字体、线条比例都变了。建议在figure创建时就用set(gcf, Position, [100 100 800 600])或者直接指定Unitscentimeters把尺寸定好再导出。还有一个细节如果你最终要把图放在Word或者Latex里背景色建议设成白色不要用默认灰色背景。5. 把瀑布图变成诊断图叠加转频、阶次线与共振带5.1 自动叠加转频线和倍频线瀑布图的横轴是频率纵轴是转速这就有了一个天然的好处转速和频率之间存在一个比例关系。对于旋转机械1阶激励频率等于转速除以60转速单位rpm频率单位Hz2阶、3阶同理。在俯视图或者三维图上叠加转频线马上就能看出“哪些峰值落在阶次线上哪些是独立的共振带”。% 在contourf图上叠加转频线和2倍转频线适用于俯视图 hold on; order1 rpmSorted / 60; order2 2 * rpmSorted / 60; plot(order1, rpmSorted, w--, LineWidth, 1.2); plot(order2, rpmSorted, w-., LineWidth, 1.2);在图上白色虚线表示1阶白色点划线表示2阶这样既能看到激励频率的变化趋势又能通过颜色带在白色线上的“亮斑”判断该阶次激励是否激发了结构共振。如果是电机噪声还要关注电磁力波的主阶次可能是某个极对数和槽数组合算出来的阶次不是简单的整数阶。有一个技巧如果噪声峰值恰好落在2阶线上说明该阶次激励与结构模态发生了共振耦合或者在某个转速下峰值出现在线上但前后都没有连续性说明该转速下存在稳健的模态参与。把这些亮斑和转速轴对应起来就能锁定临界转速值。5.2 用包络峰提取共振带定位临界转速叠加阶次线之后肉眼能看出来哪里有“亮斑”但写报告时需要定量结论。这时可以用包络峰值提取自动找出每个频率下幅值的最大值形成共振带包络线。% 提取每个频率点的最大幅值及对应转速 [maxAmp, idxMax] max(amp_interp, [], 1); rpm_at_max rpmSorted(idxMax); % 在三维图上用深色粗线标出共振带 hold on; plot3(rpm_at_max, freq_uniform, maxAmp, k-, LineWidth, 2);这行代码非常实用。它把每个频率下响应最强的那个转速点连起来形成一条脊线。如果瀑布图里有明确的共振带脊线会在那个频带附近形成连续的峰值走廊。再往下你还可以用findpeaks在某个转速切片里提取更精细的峰频把共振频率做统计这样报告里就能写“该结构在 340~360 Hz 区间存在明显共振转速在 2100 rpm 时响应最剧烈”。我建议用这个方式验证而不是只用肉眼。仿真数据本身是确定的峰值就是最大值没有噪声干扰所以包络法提取出来的是严格准确的共振走廊。5.3 阶次切片瀑布图之外的另一种常用视角瀑布图看全局但工程上还经常需要看“某一阶次随时间/转速的变化”。做法是在每个转速点以该阶次的转频为中心取一个窄频带内的能量积分或峰值得到order slice曲线。order 2; % 2阶切片 halfBandwidth 5; % 半带宽 Hz orderAmp zeros(size(rpmSorted)); for i 1:length(rpmSorted) centerFreq order * rpmSorted(i) / 60; idxBand find(abs(freq_uniform - centerFreq) halfBandwidth); if isempty(idxBand) orderAmp(i) 0; else orderAmp(i) max(amp_interp(i, idxBand)); end end figure(Color, w); plot(rpmSorted, orderAmp, LineWidth, 1.5); xlabel(转速 (rpm)); ylabel(2阶幅值 (mm/s^2));这条曲线可以清楚地看到该阶次随转速变化的趋势某段转速下陡增说明进入了该阶次对应的共振区某段转速下比较平缓说明结构响应以其他阶次为主。这里带宽的选择很重要带宽太窄频率分辨率不够可能漏掉峰值太宽又会把邻近阶次的能量混进来。一般取5~10 Hz具体看你的频率轴分辨率如果频率步长是1 Hz取±5 Hz就足够稳定了。这个阶次切片在电动驱动总成的NVH分析里很常用比如“2阶电磁噪声在3000 rpm附近有峰”这种结论就是靠order slice得到的。6. 常见问题与排查技巧实录6.1 画出来是乱线或麻布纹最常见的现象surf画出来像一团打结的蜘蛛网根本看不出趋势。这个问题的根源几乎都是数据矩阵没有按顺序排列或者插值矩阵的行列顺序搞反。先检查转速数据有没有sort过然后验证矩阵尺寸是否一致disp(size(X)); disp(size(Y)); disp(size(Z));三个矩阵必须完全一样。如果X和Y是通过meshgrid生成的但Z是原始转置过来的尺寸可能会差个维度。另外如果数据本身频率轴不均匀没有插值就硬画也会出现网格错乱。我之前有次数据是从Simcenter 3D导出的非均匀频率点忘了插值surf虽然没报错但画出来像被撕碎的布片插值之后立刻正常。6.2 转速轴方向反了或坐标轴比例失调仿真数据经常是从高转速往低转速记录比如先算6000 rpm再算1000 rpm。如果不排序瀑布图整体会倒过来转速轴大的在左边小的在右边看着很别扭。用sort之后就好了。如果surf画出来转速轴数值范围是1000到6000频率轴是0到2000Matlab会自动把X和Y轴的单位长度设成不一样图形会偏扁或偏长。这时可以用axis equal强制等比例但对于瀑布图未必合适因为频率和转速单位不同等比例通常会让图变得很丑。更推荐的做法是手动调整figure宽高比让长轴水平放置最终呈现效果会更协调。6.3 幅值跨度太大小信号被淹没仿真响应中共振峰值可能比背景高几个数量级。如果直接画线性幅值瀑布图会呈现“一座尖峰其他全是平地”。这时候有两个选择一是把幅值取对数或dB转换。振动噪声里常用20倍log10换算成dBamp_dB 20 * log10(amp eps);这样画出来的图更能展示较小幅值区域的细节共振带和阶次线都更清楚。但注意如果幅值里有0值或者负值需要先做处理加eps只是临时办法最好先检查数据有效性。二是对色彩映射做非线性变换比如在contourf里设定等值线级别为指数分布而不是线性分布levels logspace(log10(minAmp), log10(maxAmp), 30); contourf(freq_uniform, rpmSorted, amp_interp, levels, LineStyle, none);这会让颜色条更关注大峰值同时保留小信号的存在感。6.4 数据量大Matlab卡顿三维图的数据量一大比如转速点500个、频率点5000个surf会非常卡转个视角得等好几秒。这时我的经验是减少绘图点的数量但保留原始数据分析把矩阵做降采样画图用原始矩阵做定量计算。stepFreq 5; % 每5个点取1个 stepRpm 2; % 每2个转速取1个 plotFreq freq_uniform(1:stepFreq:end); plotRpm rpmSorted(1:stepRpm:end); plotZ amp_interp(1:stepRpm:end, 1:stepFreq:end); surf(plotRpm, plotFreq, plotZ);降采样只是显示层面的操作不影响最终定量结论。如果你真的需要在全分辨率下交互查看可以考虑用pcolor代替surf因为pcolor本质是平面贴图渲染效率高很多。这里整理一张常见问题速查表方便以后排查现象可能原因解决办法图形乱成蜘蛛网数据未排序或矩阵行列不匹配sort转速检查X/Y/Z尺寸一致频率轴对不上原始频率轴不一致先插值到统一频率轴转速方向反了数据从高到低排列用sort排序颜色一片蓝或一片红幅值量级差异过大用dB或对数等值线层级峰值不清晰网格过疏或视角不对增加层级数或调整view角度导出图片模糊分辨率不够用exportgraphics 300dpi卡顿严重数据点过多降采样画图原始数据全保留6.5 颜色区分度不高报告里看不清关键信息这个不算报错但很影响出图效果。如果你用的是jet色系黄绿段和暗红段的亮度差异不大打印成黑白后几乎分不出来。换成turbo或parula之后对比度会有明显提升。如果想让“峰值区域”更突出可以自己定义colormap。比如希望高幅值区域显示为黑色其他区域为灰色渐变可以在出图前用colormap(gca, [zeros(1,3); gray(255)])来做一段自定义映射。这种方法在某些技术报告中非常有用能让峰值区域非常醒目。做了这么多次瀑布图我最深的体会是拿到数据后不要急着画先花十分钟整理数据、统一单位、排序插值后面能省几小时返工的力气。尤其是从Workbench和Simcenter 3D导出的数据格式单位差异很大这两步做好了瀑布图基本就是水到渠成的事。最后分享一个小技巧如果你需要定期对不同的仿真结果出瀑布图可以把整套读取、插值、绘制封装成函数输入参数是数据目录和绘图选项输出是图。以后换一组数据一行命令就搞定了不用每次都从头重写脚本。这也是我这套流程里最值钱的部分。
返回列表