简介:ITD分解(瞬时时间差分)是机械故障诊断中常用的信号处理技术,能从复杂的振动或状态信号中分离出携带故障特征的不同分量,广泛用于旋转机械、轴承等设备的早期异常识别。这一MATLAB代码包面向故障诊断与信号处理学习者,提供了完整的ITD分解演示程序,涵盖基函数分解、极值点提取等核心算法模块,并通过示例脚本连贯展示从原始信号到分解结果的完整流程;代码紧凑、无冗余依赖,便于逐行理解算法逻辑并快速改造。压缩包共5个文件,全部为.m脚本,整体仅4KB,非常适合在MATLAB环境中直接阅读和运行;通过运行示例,可直观观察信号被逐层拆解的效果,进一步印证ITD处理思想。配合widevcb相关策略,可明显改善宽频带信号的分解效果,增强故障特征的可辨识度。目前已有452人学习,适合作为ITD理论入门、故障特征提取实验或相关课题二次开发的基础工具,也能帮助工程人员减少设备停机时间、提升维护效率。
1. ITD分解是干什么的:故障信号诊断为什么要盯上这个解压包
拿到的这个ITD分解.zip,解开之后核心就一件事:把一段非线性、非平稳的故障信号,拆成若干个单分量的“旋转成分”,让轴承故障、齿轮断齿、断路器机械动作这类冲击特征从噪声里显形出来。ITD 全称是固有时间尺度分解,和 EMD 是同类方法,但它用“基线信号”代替包络均值,不靠样条拟合,因此比 EMD 快,也少很多包络过冲的毛病。对于做故障信号分解的工程师,它尤其适合处理振动信号里冲击成分密集、噪声底较厚的场景。这篇笔记按我实际跑通这类代码包的路径来写:先从原理上明白 ITD 拆了什么,再讲怎么把 zip 里的代码和数据跑起来,最后把参数调节、踩坑和结果验证一次说清楚。适合手里有故障数据、想找出故障特征频率,但还不想一头扎进论文公式里的工程师。
2. 从EMD到ITD:故障信号分解换一种切分方式,好在哪
2.1 ITD的原理拆解:基线信号和PRC分量是怎么来的
ITD 的思路可以压缩成一句话:把一个信号反复拆成“基线”和“余量”两层,然后对基线继续拆。假设原始信号是 x(t),第一次分解得到 x(t) = L(t) + H(t)。这里的 L(t) 叫基线信号,它由信号的局部极值点通过分段线性插值构造;H(t) 就是第一个固有旋转分量,也就是包里的 PRC(Proper Rotation Component)。
关键差别在于 EMD 的包络均值需要先做三次样条包络再求平均,而 ITD 直接把这些极值点用直线连起来当基线。别小看这个差别:直线插值没有样条的“过冲”,也不会在信号突变时产生包络交叉,计算量大幅下降。更重要的是,振动故障信号的冲击成分在时域上就是极值点的突变,用极值直接构造基线,等于把冲击和低频趋势从第一层就分开。
分解是递归进行的。拿到 L(t) 后,把它当作新的信号再重复同样的操作,得到第二个 PRC 和第二条基线。不断往下,直到基线变成单调趋势,或极值点数量少到无法继续分割。最终结果是一组 PRC,频率从高到低排列,加上最后一个趋势项。
有一点容易忽略:ITD 要求每个 PRC 的局部极值点严格正负交替。如果两个最大值中间没有最小值,线性连线就会失真,这个我们后面在坑里详细说。初次接触时,可以把 ITD 理解为一个“自适应的、基于极值点的带通滤波器组”,它不预设频带,而是根据信号自身的时间尺度去切分。
2.2 同场竞技:ITD、EMD、VMD谁更适合冲击类故障
我经常被问到:已经有 EMD,有 VMD,为什么还要用 ITD?这个问题不能只看论文里的对比图,得看你的实际用途。下表是我在处理滚动轴承和断路器振动信号时的直观对比:
| 方法 | 计算速度 | 端点效应 | 模态混叠风险 | 参数依赖 | 适合场景 |
|---|---|---|---|---|---|
| EMD | 慢,样条拟合迭代多 | 严重 | 高,冲击下尤甚 | 少 | 探索性分析,不追求实时 |
| VMD | 中等 | 较轻 | 可控 | 模态数K、惩罚因子α | 频带较稳定的信号 |
| ITD | 快,线性插值无迭代拟合 | 中等,需延拓 | 比EMD低,比VMD高 | 层数、停止条件 | 冲击特征、在线诊断 |
EMD 的问题在于包络拟合对极值点分布极敏感,一旦信号中出现强冲击,包络会出现局部畸变,导致一个冲击被劈到两个相邻模态里。VMD 的好处是频带清晰,但必须先预设模态数 K,故障信号里冲击的频带其实随时间变化,K 设错了结果就差很多。ITD 的定位恰好在这两者之间:它是自适应的,不需要预设频带数(通过停止条件控制层数),又因为用了线性基线,速度比 EMD 快一个量级,非常适合需要快速迭代的故障诊断场景。
2.3 把ITD写成最小可跑的MATLAB函数
下载的 zip 里,核心函数通常封装得比较复杂,逻辑都在子函数里。如果你只想验证 ITD 的效果,或者想改参数,可以先写一个教学版跑通思想。下面这段是我常用的最小实现:
function [PRCs, trend] = itd_decompose(x, max_layers) % 简化版固有时间尺度分解 % 输入: x 一维信号向量, max_layers 最大分解层数 % 输出: PRCs 每列一个旋转分量, trend 单调趋势项 x = x(:); PRCs = zeros(numel(x), 0); residue = x; for k = 1:max_layers % 1. 检测局部极值点,并保证极大极小严格交替 max_idx = find(islocalmax(residue)); min_idx = find(islocalmin(residue)); loc = sort([max_idx; min_idx]); if length(loc) < 3 trend = residue; % 极值点不足,无法继续分解 break; end % 2. 用极值点做分段线性插值,得到基线信号 val = residue(loc); L = interp1(loc, val, 1:numel(residue), 'linear', 'extrap'); % 3. 本层PRC是原信号减基线 h = residue - L; PRCs(:, end+1) = h; %#ok<AGROW> residue = L; % 对基线继续分解 end trend = residue; end代码逻辑分三步:找极值、线性插值构造基线、原信号减基线得到 PRC。参数说明:max_layers直接控制最多分解几层,设太大会在后期噪声段上继续拆,常见取值 5 ~ 8 层;islocalmax和islocalmin是 MATLAB 2017b 以后自带的数值函数,不需要额外工具箱。需要说明的是,这个教学版没有做极值交替校验,如果你观察到某个 PRC 里极大值旁直接跟了另一个极大值,说明需要补校验逻辑,这正是真实代码包里子函数在干的事。
3. 把ITD分解.zip跑起来:文件定位、最小启动与输出读法
3.1 解压后先干三件事:找入口、找数据、找参数
拿到这个 ITD 分解的 zip,常见的做法是解压后先不要急着运行,先看目录里有什么。一般来说包里至少会有一个主分解函数(名字里带itd的 .m 文件)、一个 demo 或测试脚本、一个示例数据文件,以及一份 README 或注释文档。示例数据文件名里有widevcb,我推测它是一段和真空断路器机械动作相关的宽频振动信号,但具体采集工况以包内说明为准。你拿到包后第一步是确认三件事:入口是哪个脚本、示例数据加载后是什么变量、主函数需要哪几个参数。
小程序最容易踩的坑是路径:zip 解压后直接双击脚本,MATLAB 当前工作目录不对,就会报Undefined function or variable。我一般会先建一个文件夹专门放解压内容,然后右键设置当前文件夹,或者用命令行cd进去,再跑,避免变量被工作区里已有同名变量污染。
3.2 最小启动流程:从demo脚本到第一张分解图
假设包内有一个demo_ITD.m测试脚本。在命令行里这样起步:
cd ITD分解 ls -la matlab -nodisplay -nosplash -nodesktop -r "run('demo_ITD.m');"这段命令适用于 Linux 或 macOS 下通过命令行跑 MATLAB。-nodisplay和-nosplash是为了不弹窗口,适合批量调试;-r让 MATLAB 启动后直接执行脚本。如果是 Windows,双击 demo 脚本即可,但也要先确认当前文件夹在解压目录下。
跑起来之后,脚本通常会画出原始信号和分解后的 PRC 波形。如果你的信号采样率是 20 kHz,一个 PRC 图画出来在 0.1 秒内有多个冲击峰,说明分解初步有效。如果只有一条近乎平坦的线,大概率是参数层数设太浅,或者输入信号已经被人为滤波过度。
3.3 输出怎么读:PRC、趋势项和瞬时特征的分工
ITD 的输出结构很固定:一组 PRC 加一个趋势项。PRC1 频率最高,通常包含齿轮啮合频率、轴承外圈通过频率这类高频冲击;越往后频率越低;最后一个趋势项基本是直流或缓变趋势。故障诊断时,我们关注的是故障特征频率所在的那个 PRC,而不是所有分量。
举例:滚动轴承外圈故障,理论故障特征频率是 BPFO,振动冲击会以 BPFO 为间隔重复出现。这个特征可能在 PRC2 或 PRC3 里表现得最明显,因为在原始信号里它被强的转频成分淹没。你可以在每个 PRC 的时域波形里数一数冲击间隔,换算成频率,看是否和 BPFO 一致,这是最原始的验证方法。
3.4 示例数据widevcb到底怎么用
widevcb这个变量名在包里很可能是一个 mat 文件。你可以在命令行里这样查看:
load('widevcb.mat'); % 假设文件名如此 whoswhos会显示工作区里的变量名、大小和类型。常见情况是数据以结构体形式保存,例如data.signal和data.fs,也可能是两个独个向量。我一般会先绘制原始信号的前 1 秒,感受冲击周期和噪声底。如果数据量很大(比如采样率 200 kHz、十几秒),建议先截取一段做分解,否则整个序列分解会非常慢。也不要直接对原始数据做 ITD,先去掉均值和趋势大分量,能让 PRC 更集中。
4. ITD的三个必调参数:噪声容限、端点处理和停止条件
4.1 噪声容限:决定的是“伪分量”还是“微弱故障特征”
真实 ITD 算法在构造基线之前,会先判断某个极值点是不是真实的转折点,而不是噪声引起的毛刺。这个判断用到的阈值就是噪声容限。容限设太低,噪声锯齿也会被当成极值点,基线跟着噪声走,分解出的高频 PRC 会像白噪声;设太高,会把真实弱冲击当成噪声滤掉,小损伤的故障特征就丢了。
这个参数在包里可能叫noise_tolerance、alpha或sigma。我调试它的方法是:先设一个较高的容限,看分解出的 PRC 是否稳定;再逐步降低容限,直到某个 PRC 的包络谱里出现规则的故障特征频率峰。如果降容限后没有新增有意义的分量,而是多出一堆噪声分量,就说明已经过了临界点。轴承微弱早期故障,容限通常比默认值小 20% ~ 30%,但纯粹的经验值不可照搬,要和包络谱互相验证。
4.2 端点效应抑制:镜像延拓和特征波延拓怎么选
ITD 和 EMD 一样,在信号两端最不可靠。因为极值点插值在端点外推时没有数据约束,基线的端部很容易上扬或下垂,产生假冲击。包内的完整代码大概率会在极值点序列两端延拓后再插值,常见两种延拓方式:
- 镜像延拓:把信号端点附近的波形关于端点做镜像,构造出额外的极值点,适合平稳段较长的信号。
- 特征波延拓:取端点附近一个周期长度的波形作为模板,复制到两端,适合周期冲击明显的故障信号。
我的选择习惯是:如果原始信号是连续旋转机械(轴承、齿轮),用特征波延拓;如果是瞬态动作信号(断路器合分闸),用镜像延拓。因为瞬态信号本身只有一段冲击,镜像延拓保留了冲击形状,不会额外引入一个“假的周期”。这个参数调好以后,端点处的 PRC 振幅应自然衰减到内部水平的量级,而不是端点处冒出一个尖峰。
4.3 停止条件与最大层数:别把过分解当成高精度
加大max_layers并不是让分解更精细,反而会让算法在噪声段继续生掰出没有物理意义的分量。我见过有人把最大层数设到 12,结果 PRC8 以后的波形幅值只有原始信号的 0.1%,全是噪声。判断停止条件是否合适的标准是:最后一个非趋势分区里,极值点数量是否还足够多,以及该分区的能量占比是否低于总能量的 1%。
包里的实现通常在三个地方设停止条件:迭代层数上限、基线单调性判断、PRC 能量比例下界。如果你看到代码里有if energy_ratio < 0.01这样的判断,别把它改得太小,否则会有大量伪 PRC 进入输出。对于大多数机械故障信号,6 层已经足够:前 4 层覆盖故障冲击相关高频,第 5 层接近转频,第 6 层以后基本是趋势项。
给一个可落地的调参建议:先固定噪声容限,用 3 层跑出第一个结果,观察冲击是否清晰;若清晰,再加到 6 层看是否出现新信息;每加一层,都要对比新 PRC 的频谱和上一层的频谱是否高度重叠,如果是,说明那两层本不该被拆开,应减少层数。
5. ITD分解避坑指南:四类高频踩坑记录与现场修复
5.1 现象:分解出的PRC比原来还多,高频分量像白噪声
这是我第一次跑 ITD 时最直观的翻车现场:输入是一段 8 秒的轴承振动信号,输出却有 9 个 PRC,前两个 PRC 波形和随机噪声没有区别。原因不是算法坏了,而是噪声容限设得过低,大量由随机噪声造成的局部极值点进入了基线提取,ITD 把噪声当成真正的振荡模式拆了出来。
解决:先检查噪声容限参数,调回默认值再逐步收紧;同时确认信号在传入 ITD 前没有高频干扰。如果你不想动原信号,也可以只保留能量占比超过 1% 的 PRC,把噪声分量从结果里剔除。判断标准是:有效 PRC 的包络谱里应该能找到明确的陡峭峰,而噪声 PRC 的频谱是宽而平的。
5.2 现象:冲击特征在相邻PRC之间来回跳
更绕的坑是模态混叠:同一组冲击在 PRC1 里出现几个,又在 PRC2 里出现几个,单独看每个 PRC 都不完整。原因在于极值点检测没有做严格极大极小交替校验。若极值序列中连续出现两个极大值点,它们之间的基线会被抬高,真实冲击会被拦腰截断,能量分配到了两个相邻分量里。
解决:在代码里增加极值交替过滤,检测到两个相同类型的连续极值点时,保留幅值更大的那个,不然就改变基线插值方式。如果不想改造包内函数,可以先用一个带通滤波器把信号限制在故障特征频率附近,再送 ITD,减少高频干扰对极值点分布的影响。
5.3 现象:端点处出现大振幅,包络谱出现低频假峰
花两天时间调参,后来发现 PRC 两端各出现一大段大幅正弦状振荡,做包络谱后低频处冒出一个不存在的峰值,就是这个坑。根因在端点延拓:信号较短时,端点外推的基线近似线性直冲,和信号真实走势严重背离,导致首尾 PRC 被污染。
解决:所有结果分析都要把首尾各 1/10 长度丢掉,或者在做 ITD 前给信号两端加一个对称窗,相当于人为抑制端点权重。但加窗别用矩形窗,用正弦窗更平滑。还有一个补救办法:取数据时故意在两端各多采 2000 点,分解完只保留中间段,等于是把端点污染段“预切除”。这是我推荐的做法,比任何延拓算法都省心。
5.4 现象:循环到一半报“数组越界”,换台机器结果就变
运行中出现Index exceeds array bounds是 ITD 代码里最常见的运行时错误。原因通常是残差信号的极值点数量小于插值节点数,或者分解后期信号长度不足,某个子函数还在按初始点数分配数组。不同 MATLAB 版本对空数组的容错行为不一样,所以换台机器后错误报法还会变化,非常玄学。
解决:在每次循环开头检查极值点数量,少于 5 个就强制停止;同时在插值行前后打印当前极值点数和信号长度,定位是哪一个子函数越界。如果是迭代次数过多导致残差为纯线性斜率,也需要单独判断并跳出循环。这个修复不是投机取巧,是 ITD 这类递归分解的刚性约束。
6. 用好ITD的最后一公里:包络谱验证与分量自动筛选
6.1 对PRC做包络谱,把故障特征频率量化出来
时域上看出冲击只是主观感受,最终录进报告里的一定是故障特征频率的谱峰。有了 ITD 的 PRC 后,下一步对选定的分量做希尔伯特包络解调,再对包络做 FFT。下面这段代码我通常直接接力在分解后面:
% 对第2个PRC做包络谱,定位故障特征频率 p = PRCs(:, 2); env = abs(hilbert(p)); % 希尔伯特包络 f = (0:length(env)-1) / length(env) * fs; plot(f(1:fs/2), abs(fft(env(1:fs/2)))); xlabel('频率 (Hz)'); ylabel('幅值'); % 对照理论特征频率,例如BPFO = 123.4 Hz,看谱峰是否对齐逻辑说明:hilbert求解析信号并取绝对值得到包络,包络的 FFT 峰值出现在调制频率处,也就是故障特征频。plot只画到奈奎斯特频率的一半,因为机械信号能关心的频带就在这段。参数说明:p选择哪个 PRC 需要预判,一般从第一个分量开始逐个看,直到找到谱峰最尖锐的那个。
6.2 按能量占比自动筛选有效PRC,不再靠肉眼挑分量
挑 PRC 靠肉眼很不现实,数据一多就累。我维护了一个自动筛选逻辑:计算每个 PRC 的能量占全部分量总能量的比例,按从高到低累加,直到累计能量占比达到 90%,这部分 PRC 视为有效分量,其余丢弃。然后再在有效分量里找包络谱峰值最突出的那一个,作为诊断依据。这个技巧让批量跑几百组数据时不需要人工介入,也顺便解决了噪声容限没调到最佳时产生的伪分量干扰。
放在整条 ITD 信号分析流程里,我最终沉淀下来的习惯是:先给定保守的 6 层分解,自动筛能量占比,再对有效分量做包络谱,把谱峰和理论故障特征频率对照,误差在 1% 以内就下结论。这套流程我用了很久,最大的体会是分解阶段不用追求绝对正确,只要保留住真实冲击,剩下的交给包络谱验证。任何把 ITD 当成黑匣子的用法都会在故障诊断时翻车,但如果你每次结果都留一层检查,坏参数永远不会骗你太久。希望帮到你。
本文还有配套的精品资源,点击获取