☰
兰姆波与数据驱动:板状结构健康监测的Matlab实现
2026/10/16 7:14:38 网站建设 项目流程

如果你拆过一块服役多年的复合材料壁板,就会明白“看得见的地方”和“需要担心的地方”往往不是一回事。表面光洁不代表内部没有分层,铆钉孔周围的微小裂纹更是要到目视可见阶段才会被发现。这些年我一直在做结构健康监测相关项目,其中一个方向就是用兰姆波做板状结构的原位损伤检测:在若干选定位置贴压电传感器,用一发多收的方式扫过结构,再靠数据驱动模型把波形里的损伤信息翻译成位置和程度。整个过程用Matlab代码实现,也是今天这篇的主要内容。

这套思路的价值在于,不依赖昂贵的扫描设备,也不需要结构停机拆装,很适合实验室验证和工程样机预研。如果你正准备上手SHM课题,或者需要把兰姆波信号处理和机器学习组合起来,这篇文章可以帮你理清头绪——从为什么选兰姆波,到特征怎么提,再到Matlab代码怎么落地,一个环节都不落下。

1. 为什么是兰姆波:板状结构里的天然信使

1.1 板太薄,普通超声扫不动

常规超声检测靠的是纵波或横波在厚度方向上的反射,换能器贴着表面扫一遍,从回波时间判断缺陷深度。这套打法在几十毫米厚的锻件、焊缝上很成熟,但换到1到4毫米厚的机身壁板、舱门板、复材蒙皮上就不太灵了:板太薄,常规超声换能器的近场区比板厚还长,回波几乎分不出来。

兰姆波解决的是另一类问题。板件上下两个自由表面之间存在多次反射,声波会在板平面内被“夹着”往前跑,形成沿整个板厚截面传播的导波。这种波的特点是能沿着板面传播很远的距离,一个位置激励,另一个位置收到信号时,路径上任何一处截面变化都会影响波的传播。于是损伤检测的思路就变了:不需要把每个点都扫一遍,而是用少量收发位置覆盖一个面积区域,再根据接收波形的变化反推损伤在哪、损伤多严重。

我在做某块铝合金试验板时,一开始也试过普通超声C扫做“地面真值”,但C扫只能给出离线检测结果,而且设备架设耗时很长。真正让试验推进下去的,是改用了兰姆波一发多收的方案:同一块板上贴八个压电片,通过不同组合激励,几分钟就能采集一组覆盖全板面的信号,这个过程完全可以原位置完成,不需要拆结构。

1.2 模态和频段怎么选:频厚积的工程经验

兰姆波麻烦的一点是它不只有一种模式。对称模态S0和反对称模态A0是工程里最常遇到的两种,它们的传播速度、衰减特性、对损伤的敏感度都不一样。更麻烦的是频散:波的传播速度随频率变化,激励信号频率越宽、频厚积越大,波形就越容易在传播过程中被拉开拉散,后续特征提取的难度直线上升。

工程上的主流做法是把激励频段压到比较低的频厚积区间,让结构中同时存在的模态尽量少。频厚积的计算方式是中心频率乘以板厚,比如2毫米铝板配200kHz激励,频厚积就是0.4 MHz·mm,这个量级在大多数结构里能保持模态比较简单。我的一般操作是先做一次扫频实验:从50kHz到500kHz每25kHz激励一次,记录接收波形,直接看包络里出现了几个明显的波包。出现两个以上波包、且互相重叠分不开时,就把中心频率往下调,直到波形“干净”为止。

选模态还有一个实际经验:如果目标损伤是复合材料分层这类垂直于板面的破坏,优先观察A0模态,因为分层会显著改变局部弯曲刚度;如果关注的是表面裂纹或腐蚀减薄,S0模态的响应通常更直接。但不要执着于只保留单一模态,实际粘接的传感器很难做到完全抑制另一种模态,数据驱动模型本身也会利用这些模态混合带来的特征变化。

1.3 稀疏阵列的“选定位置”该怎么定

标题里强调“选定位置”,这个表述很有讲究。兰姆波检测不需要像相控阵那样密布几十上百个阵元,我用得最多的是六到八个压电片的稀疏阵列。位置怎么选直接决定数据质量,我的原则有三条:

第一,覆盖所有重点监测区域,保证至少有一条传播路径穿过最关心的部位。比如铆钉孔附近、开口角区、蒙皮与加强筋交界处,都是裂纹高发区,必须让几条激励-接收路径“扫过”这些位置。第二,传感器不要贴在结构不连续位置的正上方,比如加强筋边缘、开口边缘,这些位置的局部散射太强,会让健康信号的基线都乱成一团。第三,相邻路径不要靠得太近,否则提供的信息高度冗余,数据驱动模型的输入会丧失独立性。

我在一块600mm见方的模拟壁板上布过九个位置的传感器,中间一个作为激励,其余八个作为接收。每个激励位置对应八条接收路径,轮流激励就能得到丰富的“路径-响应”组合。这里的思路和图像处理类似:单条路径是低分辨率的投影,多条路径合在一起才能反推出损伤的空间分布。

2. 数据驱动方法的设计起点:先定义“损伤”在信号里长什么样

2.1 为什么阈值法在实验室灵、上结构就失效

很多刚接触SHM的人会先尝试一个最简单的方案:记录健康状态下的信号作为基线,然后每来一个新信号就和基线做差,差幅超过阈值就判定为损伤。这个方案在实验室安静环境下确实能跑通,但一到实际结构上就问题频出。

问题出在“差幅”本身不可靠:结构受载状态变化、环境温度变化、传感器粘接层老化,都会让接收波形的幅值和相位发生显著变化。有一次我在同一天早中晚三个时段采集同一块板的信号,不做任何损伤,差分信号的最大幅值竟然比一个几毫米人工缺陷引起的差分幅值还要大。如果只看单条路径的幅值差,误报几乎不可避免。

数据驱动方法的核心并不是抛弃对物理的理解,而是把“损伤会引起什么变化”这个判断,转交给统计模型来处理。模型输入的不只是单一的幅值差,而是大量经过物理筛选的特征组合,比如波形包络的变化形状、多个传播路径上的响应模式、频段能量分布的转移。这样一来,单条路径上的随机波动就不会轻易触发报警,因为模型学到的是多个特征联合出现的损伤模式。

2.2 可操作的特征组合

特征提取是整个流程中最能体现经验的部分。我常用的特征分成四类,每一类都对应着兰姆波对损伤的不同响应机制:

特征类别特征名称物理含义
时域幅值峰值幅值、均方根、峰值到达时间损伤导致能量衰减和传播路径速度变化
波形相关性与基线信号的互相关系数、皮尔逊系数波形畸变程度,损伤引起的散射和反射
频域分布谱质心、谱距、频带能量比损伤对不同频率成分的选择性衰减
时频分析小波包各频带能量占比非平稳波包的局部特征变化

实际提取时要注意一个细节:每个接收通道都要用自己的健康基线做归一化,不能把所有通道放在同一个量纲下。原因很简单,不同路径的传播距离不一样,幅值本身就有天然差异,如果不分别归一化,模型学到的主要是“路径的固有差异”,而不是“该路径上的损伤变化”。

损伤指数(DI)是另一个常用工具,最简单的定义是DI = 1 - ρ,其中ρ是当前信号和基线信号在某个时窗内的相关系数。DI接近0表示信号没变,接近1表示波形完全变了。这个指数可以作为定位模型的输入之一,但我不建议只用DI,因为它丢掉了波形里很多细节信息。把DI和到达时间偏移、谱能量比等特征拼在一起,效果会好很多。

2.3 标签怎么打:定位和定量都需要“带答案的数据”

数据驱动模型必须有标签,这是整个项目里最累但最不能省的一步。定位模型的标签是损伤的平面坐标,定量模型的标签是损伤程度的度量值。

制备训练样本时,我会在试验板上加工一批人工缺陷,例如用电火花打出的不同深度凹坑、用刀片切割的槽口、用敲击法制造的复合材料分层。每个缺陷都要记录两个关键值:位置坐标和严重程度。损伤程度尽量用连续物理量定义,凹坑用深度毫米数,分层用面积平方毫米,切割槽口用长度毫米。

每次损伤加工完,马上采集一轮数据:所有激励位置轮流激励,所有接收通道记录响应。一个损伤点可以得到一组“路径特征矩阵”。为了减少偶然误差,同一个损伤状态至少重复采集三次,并且每次采集前都重新保存结构当前状态。这里有一个很容易犯的错误:为了省事,在同一个损伤状态下连续采集十次信号。这样做出来的样本高度相关,模型的验证结果会虚高,换一个新损伤状态就露馅。

正确的做法是让训练样本覆盖尽可能多的“损伤位置×损伤程度”组合。比如八个损伤位置、每个位置做三档深度,就能得到二十四个带标签的状态,每状态多次采样后,样本量就基本够用了。不要贪多追求几百个损伤状态,时间成本扛不住,二十个左右精心设计的损伤状态,配上一个稳定的特征提取流程,已经能训练出效果不错的定位和定量模型。

3. 定位与定量评估的核心算法路径

3.1 三步流水线:检测、定位、定量

很多教程喜欢端到端地亮出一个深度学习模型,输入波形、输出损伤图。这种方案在论文里好看,在工程里却难用,因为一旦输出结果不对,几乎无法排查是数据问题、特征问题还是模型问题。

我习惯把任务拆成三个步骤:先回答“有没有损伤”,再回答“损伤在哪里”,最后回答“损伤有多严重”。检测环节是一个二分类问题,用正常状态和任意损伤状态的数据训练;只有通过检测门槛的信号才进入定位环节;定位模型的输出为坐标估计,坐标被确认落在结构范围内后,再由定量模型给出严重程度估计。每步模型都比较简单,可以单独验证,一旦某个环节出错,能快速定位到原因。

这个拆法的另一个好处是可以在中途设置人工干预点。比如定位模型对某个新样本输出了一个落在传感器位置附近的坐标,我可以立刻意识到这可能是误报而不是真实的边缘损伤,因为真实损伤一般不会恰好出现在传感器正下方。这种可解释性在工程交付里非常重要。

3.2 定位模型怎么训练和验证

定位模型的输入是各条路径提取到的损伤特征,比如各通道的DI值、峰值到达时间偏移量、频带能量变化比。输出是损伤的平面坐标。坐标需要先归一化到0到1范围,否则模型会对数值较大的坐标分量产生隐性加权。

我在Matlab里最常用的定位模型是集成回归树,也就是TreeBagger或者fitrensemble。选它的原因很实际:样本量通常只有几十到上百条,深层网络在这点数据上容易陷入过拟合;而随机森林天然适应混合尺度特征,不需要太精细的特征工程,训练速度也快。

训练时务必采用“按损伤点划分”的交叉验证策略。假如八个损伤位置,每次留出一个位置的样本不参与训练,模型在其他七个位置上训练,然后预测留下来这个位置的坐标。这样评价出来的定位误差才真实反映“遇到未见过的损伤位置”时的推广能力,而不是模型记住训练位置后返回的虚高分数。

3.3 程度评估:直接回归剩余寿命不现实

损伤定量评估比定位更困难,因为同一位置的损伤,影响波形的方式可能非常相似。我在实践中发现,一上来就直接回归“剩余寿命”是个不切实际的目标:剩余寿命不仅取决于损伤尺寸,还取决于载荷谱、材料状态、环境影响,这些信息在监测系统里根本拿不到。

务实的做法是把定量问题分成两种:如果训练样本里损伤程度是连续变化的,就做一个回归模型,输出值为损伤尺寸或深度;如果样本只能做到“轻微、中等、严重”这种分级,就做一个有序分类模型。回归模型常用高斯过程回归或带正则化的神经网络,分类模型则优先用随机森林的多分类版本。

定量模型同样可以采用留一损伤点交叉验证,但要额外关注同一个损伤位置、不同损伤程度之间的区分情况。我用过一个简单有效的校验方式:把某一位置不同深度的样本分别预测,看预测值是否和真实深度保持单调关系。如果模型把最深损伤预测得比中等损伤还轻,那说明模型学到的是位置相关特征,而不是程度相关特征,这个模型不能用于定量。

3.4 数据不够怎么办:混合仿真与迁移策略

小样本是数据驱动SHM绕不开的现实。我常用的补救方法有三个。第一是子窗采样扩增,把每个接收信号划分成多个时间窗,分别提取特征,再按照窗口位置组织成多个样本。这样一条原始信号能衍生出多条训练数据,代价是相邻样本相关性略有增加。第二是加噪扩增,在提取特征之后,对特征矩阵施加一定比例的高斯噪声,迫使模型学会容忍测量波动。第三是模拟数据预训练,用有限元仿真生成不同损伤位置下的兰姆波信号,在仿真数据上做预训练,再用实测数据微调。不过仿真和实测之间的频散、衰减差异很大,这一步我通常只用来初始化网络前半部分或者验证特征有效性,直接替代实测数据并不可靠。

最后提醒一句:数据驱动不是“样本多就能忽略物理”。即使在数据增强之后,样本覆盖范围之外的外推预测依然不可信。定位模型只能学习到训练损伤位置分布区域的响应模式,如果结构上一个完全没训练过的新区域出现损伤,模型给出的结果可能只是一个看似合理、实际毫无意义的坐标。所以传感器的布设范围,就是模型的信任边界。

4. Matlab实现:从激励信号到损伤分布图

4.1 激励信号与数据读取的代码骨架

激励信号不能直接上一段连续正弦波,因为连续正弦波的频谱是一条窄线,无法在接收端分辨“从哪开始传播”的时刻。工程标准做法是产生一个汉宁窗调制的猝发信号,几个周期的正弦波被窗函数包住,中心频率集中,旁瓣低,激励出的兰姆波波包比较干净。

fs = 10e6; % 采样率 10 MHz,取决于采集卡 fc = 200e3; % 中心频率 200 kHz nCycles = 5; % 正弦波周期数 t = 0:1/fs: nCycles/fc; burst = sin(2*pi*fc*t) .* (0.5 - 0.5*cos(2*pi*fc*t/nCycles));

激励信号通过功率放大器接到激励压电片上,同时采集所有接收通道的响应。数据保存为每行一个通道的矩阵。读取时建议一次性读入全部路径数据,不要每次循环单独读文件,Matlab的文件I/O是性能瓶颈,一次性读入能省下不少时间。

4.2 特征提取函数

特征提取的核心是“基线差分加包络”。原始响应里占据主要能量的是直达波,损伤引起的散射信号往往混在直达波之后,直接看原始信号很难识别。先把当前信号与健康基线相减,得到差分信号,损伤引起的散射成分就被放大了。再用希尔伯特变换取包络,方便提取峰值和到达时间。

function features = extractFeatures(signal, baseline, fs) diffSig = signal - baseline; % 去掉直达背景 diffEnv = abs(hilbert(diffSig)); % 差分信号包络 [peakAmp, peakIdx] = max(diffEnv); % 峰值幅值与位置 corrCoeff = corrcoef(signal, baseline); % 波形相关性 di = 1 - corrCoeff(1,2); % 损伤指数 DI spec = abs(fft(diffSig)); % 频谱 specC = sum((0:length(spec)-1)'.*spec) / sum(spec); % 谱质心 features = [peakAmp, peakIdx/fs, di, specC]; end

这里有一个小技巧:提取峰值位置时先设定一个时间门限,比如只分析激励后0.1毫秒到1毫秒之间,避开激励信号本身的前沿以及可能混入的电磁串扰。门限范围根据板边尺寸估计最大传播时间来确定,超出最大时间的包络峰值大概率来自边界反射。

4.3 训练定位模型与绘制损伤热图

特征矩阵准备好之后,训练TreeBagger只需要几行代码,但划分训练集和验证集时一定要按“损伤状态”分组,不能随机打乱样本。下面的示例按损伤点编号分组,某个编号的全部样本留作验证,其余训练:

rng(42); model = TreeBagger(200, featTrain, coordTrain, 'Method', 'regression', ... 'NumPredictorsToSample', 'all', 'MinLeafSize', 3); coordPred = predict(model, featVal); locErr = sqrt(sum((coordPred - coordVal).^2, 2));

绘图时我喜欢把预测误差画成彩色热力图叠加在板件轮廓上。用scatteredInterpolant先把离散的损伤点预测误差插值成网格场,再用imagesc显示。这个图在项目汇报时很直观,非专业人士也能一眼看出哪些区域监测效果好、哪些区域预测漂移大。

F = scatteredInterpolant(truePos(:,1), truePos(:,2), locErr, 'linear'); [Xg, Yg] = meshgrid(0:10:600, 0:10:600); ErrG = F(Xg, Yg); imagesc(ErrG); axis equal; colorbar;

4.4 跑一把的真实时间开销

整个流程的时间成本分布很不均匀。特征提取是主要耗时环节,一个状态有八条路径,每条路径要算包络和频谱,如果采集了三十个状态,每个状态三次重复,总共九十组数据,Matlab单循环处理大概需要十几分钟。训练模型反而很快,TreeBagger两百棵树几秒就能结束。

如果数据量再翻几倍,建议用parfor并行处理各通道特征提取。需要注意预先声明输出数组,避免每次循环追加数组导致内存反复分配。还有另一个容易踩的坑:hilbert变换之后取绝对值得到的包络仍有高频抖动,可以在包络上再做一次低通滤波,否则峰值定位会不稳定。

5. 实测验证中最容易翻车的几个环节

5.1 温度漂移带来的基线失配

这是我在项目里遇到的头号工程问题,不是模型算法问题,而是数据采集环节就失真了。兰姆波的传播速度随温度变化,典型趋势是温度升高、声速略有下降,波的到达时间整体后移,波形相位也跟着旋转。温度差几度带来的信号变化量,可能超过一个轻微损伤造成的变化。

应对措施我总结成了几条,都是实践过的有效方案:

问题影响有效对策
温度导致声速变化到达时间偏移,DI增大采集前记录温度,并用温度-到达时间线性模型修正
温度导致压电灵敏度变化幅值波动每个通道用自身基线幅值归一化
温度和损伤耦合差分信号无法区分来源用多个路径联合判断,避免单路径决策
昼夜温差大基线失效快缩短参考基线更新周期,建议不超过数小时

有几个项目为了追求“纯数据驱动”,把温度通道也作为特征直接放进模型。如果训练数据覆盖的温度范围足够宽,这确实有效,但需要额外增加温度传感器和多样化的采集时段。我一开始只用实验室内稳定温度环境验证算法,后来走到工程实测时才补上温度修正这一步,白白返工了一次,这个教训很值得记下来。

5.2 传感器粘接的一致性问题

压电片的粘接质量对信号稳定性的影响,常常被初学者低估。同一种压电片,用不同的粘接胶、不同的压力和时间固化,激发的幅值能差百分之三十以上。更麻烦的是,同一批次粘接的传感器经过几十次温度循环之后,胶层状态还会细微变化。

我的粘接标准流程是:表面用砂纸打磨到粗糙度适当,酒精清洁后,用固化胶在压电片背面涂覆,贴上后用小夹具施加恒定压力,室温固化至少24小时再开始采集数据。贴完不代表就能直接投入监测,必须先检查每个传感器的电容值和谐振阻抗,用阻抗分析仪确认一致性。电容值偏差超过百分之十的传感器,趁早重新粘贴,省得后期数据出现不明原因异常。

每次测量之前还要做一个“传感器自检”:激励端发射一次标准猝发信号,接收端检查直达波幅值。如果某通道幅值比历史记录突然掉了一半,多半是胶层开裂或线缆接触不良,此时先别处理数据,把硬件修好再说。

5.3 边界反射与局部几何的干扰

兰姆波遇到板边缘、加强筋、开口都会产生反射和模式转换,这些后续波包会“污染”接收信号。软件上常用的抑制手段是开时间窗,只保留直达波和主散射波所在的时间范围,把明显晚到的边界反射截掉。时间窗的起点设在激励结束之后,终点按板面最大对角长度除以最慢模态速度估算,超出这个时间的基本都来自边界反射。

但时间窗不是万能的。如果结构上有加强筋,即使直达波时间范围内,也可能混入经过加强筋反射的波包。我在设计布点时就要求接收路径尽量避开加强筋正对方向,实在避不开的路径,就用健康状态的盲特征聚类方法处理:在训练时对大量健康状态提取特征,计算均值协方差,然后把后续差异大于统计阈值的路径标记出来人工复核。这个方法不能消除干扰,但能防止干扰被无限放大。

5.4 模型过拟合的三个报警信号

最后聊过拟合。小样本模型最容易出现的现象是训练误差很低,验证误差却高得离谱。我有三个快速判断信号,出现任何一个都要警惕:

第一,训练集的定位误差在2毫米以内,但留一验证误差超过20毫米,这是典型的记住样本。第二,给训练样本加百分之五的噪声,预测结果出现剧烈变化,说明模型边缘响应不稳定。第三,只删除一个损伤位置的所有样本,模型对余下样本的表现立刻大幅下降,说明模型对特定位置过度敏感。

一旦发现这些信号,优先做特征降维而不是换更复杂的网络。随机森林的变量重要性排序会告诉我哪些特征其实没有贡献,去掉这些特征,往往验证误差反而会下降。高压环境下,模型尺寸越小越稳,这个定律在SHM小样本场景里特别应验。

6. 从代码到样机,我习惯长期遵守的几条习惯

6.1 永远先做单路径重复性实验

任何复杂的数据驱动流程,都应该从“两个传感器、一条路径”开始验证。先在安静条件下采集几十次信号,计算峰值和相关系数的波动范围,确定系统的重复性底线。如果单路径重复性都做不好,后面布多少传感器、提多少特征都是白搭。我见过很多项目一上来就追求满板传感器布阵,最后卡在数据质量上无法推进,根源就是少了这一步。

重复性实验还能帮我确定激励电压、信号平均次数的合理值。采集卡噪声比较大时,可以每个状态连续采集十次信号做时域平均,信噪比能提升不少。但要记住,平均只能抑制随机噪声,无法消除温度漂移和粘接层变化的系统性误差。

6.2 数据文件命名与元数据记录

这是整个项目里最不起眼却最救命的习惯。每个数据文件都按统一规则命名,例如“板编号_损伤位置_损伤深度_序号_温度.mat”,同时用单独的说明文档记录每次实验的传感器配置、激励参数、增益、采集时间。没有这些元数据,几个月后回看数据时,你可能连“这个损伤在哪个位置”都要靠猜。

有一次我为了赶进度,把两组不同激励增益的实验数据混在一起处理,特征提取时完全没察觉,模型训练结束后验证误差高得离谱。排查了两天才发现是某次采集中途调了增益而没有记录,那之后我要求所有实验的量化采集参数必须在文件名的固定字段里体现。类似的坑你踩过一次就会明白,元数据不是可有可无的形式,而是数据驱动项目里的第一等资产。

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

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

立即咨询