Rolling Element Bearing Fault Diagnosis滚动轴承故障诊断

英文地址https://ww2.mathworks.cn/help/predmaint/examples/Rolling-Element-Bearing-Fault-Diagnosis.html
这个例子展示了如何基于加速度信号对滚动轴承进行故障诊断,特别是在存在来自其他机器部件的强掩蔽信号的情况下。该实例将演示如何应用包络谱分析和频谱峰度来诊断轴承故障,并能够扩展到大数据应用。

问题总览

滚动轴承的局部故障可能发生在外圈、内圈、保持架或滚动部件上。当滚动元件撞击外圈或内圈的局部故障,或滚动元件上的故障撞击外圈或内圈[1]时,轴承和响应传感器之间的高频共振被激发。下图显示了一个滚动部件在内圈撞击一个局部故障。问题是如何检测和识别各种类型的故障。

image.png
机械故障预防技术(MFPT)挑战数据

MFPT质询数据[4]包含从不同故障条件下的机器上收集的23个数据集。前20组数据采集于轴承试验台,其中3组工况良好,3组外套圈故障为恒载,7组外套圈故障为各种载荷,7组内套圈故障为各种载荷。剩下的3组数据来自真实的机器:一个油泵轴承,一个中速轴承和一个行星轴承。故障位置未知。在本例中,只使用从具有已知条件的试验台收集的数据。

每个数据集包含加速度信号“gs”、采样率“sr”、轴转速“rate”、负载重量“load”,以及代表不同故障位置的四个关键频率:球通频率外圈(BPFO)、球通频率内圈(BPFI)、基本列车频率(FTF)和球自旋频率(BSF)。这是临界频率[1]的公式。

image.png

如图所示,d为球直径,d为节距直径。变量fr轴转速,n是滚动原件的数量,ϕ是轴承接触角[1]。

包络谱分析用于轴承诊断

在MFPT数据集中,轴向速度是恒定的,因此不需要将跟踪作为预处理步骤来消除轴向速度变化的影响。当滚动元件撞击外圈或内圈的局部故障时,或当滚动元件上的故障撞击外圈或内圈时,冲击将调制相应的临界频率,如BPFO、BPFI、FTF、BSF。因此,振幅解调产生的包络信号传递了原始信号频谱分析无法提供的更多诊断信息。以MFPT数据集中的内部race故障信号为例。

dataInner = load(fullfile(matlabroot, 'toolbox', 'predmaint', ...
    'predmaintdemos', 'bearingFaultDiagnosis', ...
    'train_data', 'InnerRaceFault_vload_1.mat'));

在时域内可视化原始的内圈故障数据

xInner = dataInner.bearing.gs;
fsInner = dataInner.bearing.sr;
tInner = (0:length(xInner)-1)/fsInner;
figure
plot(tInner, xInner)
xlabel('Time, (s)')
ylabel('Acceleration (g)')
title('Raw Signal: Inner Race Fault')
xlim([0 0.1])

image.png

在频域中可视化原始数据

figure
[pInner, fpInner] = pspectrum(xInner, fsInner);
pInner = 10*log10(pInner);
plot(fpInner, pInner)
xlabel('Frequency (Hz)')
ylabel('Power Spectrum (dB)')
title('Raw Signal: Inner Race Fault')
legend('Power Spectrum')

image.png

现在放大原始信号在低频范围的功率谱,以更近地观察BPFI及其前几次谐波的频率响应

figure
plot(fpInner, pInner)
ncomb = 10;
helperPlotCombs(ncomb, dataInner.BPFI)
xlabel('Frequency (Hz)')
ylabel('Power Spectrum (dB)')
title('Raw Signal: Inner Race Fault')
legend('Power Spectrum', 'BPFI Harmonics')
xlim([0 1000])
image.png

在BPFI及其谐波中看不到清晰的模式。原始信号的频率分析不能提供有用的诊断信息。从时域数据可以看出,原始信号的幅值被调制到一定的频率,调制的主频约为1/0.009 Hz≈111 Hz。已知滚动单元内圈局部故障即BPFI的频率为118.875 Hz。这表明轴承可能存在内圈故障

figure
subplot(2, 1, 1)
plot(tInner, xInner)
xlim([0.04 0.06])
title('Raw Signal: Inner Race Fault')
ylabel('Acceleration (g)')
annotation('doublearrow', [0.37 0.71], [0.8 0.8])
text(0.047, 20, ['0.009 sec \approx 1/BPFI, BPFI = ' num2str(dataInner.BPFI)])

为了提取调制后的振幅,计算原始信号的包络线,并将其显示在底图上

subplot(2, 1, 2)
[pEnvInner, fEnvInner, xEnvInner, tEnvInner] = envspectrum(xInner, fsInner);
plot(tEnvInner, xEnvInner)
xlim([0.04 0.06])
xlabel('Time (s)')
ylabel('Acceleration (g)')
title('Envelope signal')

image.png

现在计算包络信号的功率谱,看看BPFI的频率响应及其谐波

figure
plot(fEnvInner, pEnvInner)
xlim([0 1000])
ncomb = 10;
helperPlotCombs(ncomb, dataInner.BPFI)
xlabel('Frequency (Hz)')
ylabel('Peak Amplitude')
title('Envelope Spectrum: Inner Race Fault')
legend('Envelope Spectrum', 'BPFI Harmonics')

image.png

envelope spectrum包络谱
BPFI Harmonics 内圈频率谐波

结果表明,大部分能量集中在BPFI及其谐波上。这表示轴承的内圈故障,与数据的故障类型匹配。

将包络谱分析应用于其它故障类型

现在对正常数据和外圈故障数据重复相同的包络谱分析。

dataNormal = load(fullfile(matlabroot, 'toolbox', 'predmaint', ...
    'predmaintdemos', 'bearingFaultDiagnosis', ...
    'train_data', 'baseline_1.mat'));
xNormal = dataNormal.bearing.gs;
fsNormal = dataNormal.bearing.sr;
tNormal = (0:length(xNormal)-1)/fsNormal;
[pEnvNormal, fEnvNormal] = envspectrum(xNormal, fsNormal);

figure
plot(fEnvNormal, pEnvNormal)
ncomb = 10;
helperPlotCombs(ncomb, [dataNormal.BPFO dataNormal.BPFI])
xlim([0 1000])
xlabel('Frequency (Hz)')
ylabel('Peak Amplitude')
title('Envelope Spectrum: Normal')
legend('Envelope Spectrum', 'BPFO Harmonics', 'BPFI Harmonics')
image.png

正如所料,正常轴承信号的包络谱在BPFO或BPFI处没有显示出任何显著的峰值

dataOuter = load(fullfile(matlabroot, 'toolbox', 'predmaint', ...
    'predmaintdemos', 'bearingFaultDiagnosis', ...
    'train_data', 'OuterRaceFault_2.mat'));
xOuter = dataOuter.bearing.gs;
fsOuter = dataOuter.bearing.sr;
tOuter = (0:length(xOuter)-1)/fsOuter;
[pEnvOuter, fEnvOuter, xEnvOuter, tEnvOuter] = envspectrum(xOuter, fsOuter);

figure
plot(fEnvOuter, pEnvOuter)
ncomb = 10;
helperPlotCombs(ncomb, dataOuter.BPFO)
xlim([0 1000])
xlabel('Frequency (Hz)')
ylabel('Peak Amplitude')
title('Envelope Spectrum: Outer Race Fault')
legend('Envelope Spectrum', 'BPFO Harmonics')
image.png

对于外圈故障信号,BPFO谐波也没有明显的峰值。包络谱分析不能区分外圈故障轴承和正常轴承吗?让我们回过头来看看不同条件下时域内的信号。首先,让我们再次在时域中形象化这些信号并计算它们的峰度。峰度是随机变量的第四个标准化矩。它描述了信号的冲动性或随机变量尾部的沉重。

figure
subplot(3, 1, 1)
kurtInner = kurtosis(xInner);
plot(tInner, xInner)
ylabel('Acceleration (g)')
title(['Inner Race Fault, kurtosis = ' num2str(kurtInner)])
xlim([0 0.1])

subplot(3, 1, 2)
kurtNormal = kurtosis(xNormal);
plot(tNormal, xNormal)
ylabel('Acceleration (g)')
title(['Normal, kurtosis = ' num2str(kurtNormal)])
xlim([0 0.1])

subplot(3, 1, 3)
kurtOuter = kurtosis(xOuter);
plot(tOuter, xOuter)
xlabel('Time (s)')
ylabel('Acceleration (g)')
title(['Outer Race Fault, kurtosis = ' num2str(kurtOuter)])
xlim([0 0.1])
image.png

结果表明,内圈故障信号具有较大的冲动性,使得包络谱分析能够有效地捕获故障信号在BPFI处的特征。对于外环故障信号,BPFO处的调幅值略显明显,但被强噪声掩盖。正常信号不显示任何调幅。在BPFO处进行幅度调制提取脉冲信号(或提高信噪比)是包络谱分析前的一个关键预处理步骤。下一节将介绍峰度图和光谱峰度,提取峰度最高的信号,并对滤波后的信号进行包络谱分析。

峰图和光谱峰度用于波段选择

峰度图和频谱峰度计算在频带内的局部峰度。它们是定位具有最高峰度(或最高信噪比)[2]的频带的强大工具。在确定峰度最高的频段后,可以对原始信号进行带通滤波,获得更强的脉冲信号进行包络谱分析。

level = 9;
figure
kurtogram(xOuter, fsOuter, level)
image.png

峰度图表明,以2.67 kHz为中心,带宽为0.763 kHz的频带峰度最高,为2.71。现在使用最优窗口长度所建议的kurtogram来计算光谱峰度。

figure
wc = 128;
pkurtosis(xOuter, fsOuter, wc)
image.png

为了使光谱图上的频带可视化,计算光谱图并将光谱峰度放在一边。另一种解释谱峰度的方法是,高谱峰度值表示对应频率下功率的高方差,这使得谱峰度成为定位信号[3]非平稳分量的有用工具。

helperSpectrogramAndSpectralKurtosis(xOuter, fsOuter, level)
image.png

通过对中心频率和带宽建议的信号进行带通滤波,可以增强峰度,恢复外环故障的调制幅值。

[~, ~, ~, fc, ~, BW] = kurtogram(xOuter, fsOuter, level);

bpf = designfilt('bandpassfir', 'FilterOrder', 200, 'CutoffFrequency1', fc-BW/2, ...
    'CutoffFrequency2', fc+BW/2, 'SampleRate', fsOuter);
xOuterBpf = filter(bpf, xOuter);
[pEnvOuterBpf, fEnvOuterBpf, xEnvOuterBpf, tEnvBpfOuter] = envspectrum(xOuter, fsOuter, ...
    'FilterOrder', 200, 'Band', [fc-BW/2 fc+BW/2]);

figure
subplot(2, 1, 1)
plot(tOuter, xOuter, tEnvOuter, xEnvOuter)
ylabel('Acceleration (g)')
title(['Raw Signal: Outer Race Fault, kurtosis = ', num2str(kurtOuter)])
xlim([0 0.1])
legend('Signal', 'Envelope')

subplot(2, 1, 2)
kurtOuterBpf = kurtosis(xOuterBpf);
plot(tOuter, xOuterBpf, tEnvBpfOuter, xEnvOuterBpf)
ylabel('Acceleration (g)')
xlim([0 0.1])
xlabel('Time (s)')
title(['Bandpass Filtered Signal: Outer Race Fault, kurtosis = ', num2str(kurtOuterBpf)])
legend('Signal', 'Envelope')
image.png

可以看出,带通滤波后峰度值增大。现在在频域中形象化包络信号。

figure
plot(fEnvOuterBpf, pEnvOuterBpf);
ncomb = 10;
helperPlotCombs(ncomb, dataOuter.BPFO)
xlim([0 1000])
xlabel('Frequency (Hz)')
ylabel('Peak Amplitude')
title('Envelope Spectrum of Bandpass Filtered Signal: Outer Race Fault ')
legend('Envelope Spectrum', 'BPFO Harmonics')
image.png

结果表明,通过对原始信号进行带通滤波,利用峰度和频谱峰度所建议的频带,包络谱分析能够较好地揭示BPFO的故障特征及其谐波特征。

Batch Process

现在,让我们使用文件集成数据存储将该算法应用于一批训练数据。工具箱中提供了数据集的有限部分。将数据集复制到当前文件夹,并启用写入权限:

copyfile(...
    fullfile(matlabroot, 'toolbox', 'predmaint', 'predmaintdemos', ...
    'bearingFaultDiagnosis'), ...
    'RollingElementBearingFaultDiagnosis-Data-master')
fileattrib(fullfile('RollingElementBearingFaultDiagnosis-Data-master', 'train_data', '*.mat'), '+w')
fileattrib(fullfile('RollingElementBearingFaultDiagnosis-Data-master', 'test_data', '*.mat'), '+w')

对于完整的数据集,请转到这个链接https://github.com/mathworks/rollingelementbearingfaultdiagnostics - data,以zip文件的形式下载整个存储库,并将其保存在与活动脚本相同的目录中。使用以下命令解压缩文件:

if exist('RollingElementBearingFaultDiagnosis-Data-master.zip', 'file')
    unzip('RollingElementBearingFaultDiagnosis-Data-master.zip')
end

本例中的结果是从完整的数据集生成的。整个数据集包含一个包含14个mat文件的训练数据集(2个normal, 4个inner race fault, 7个outer race fault)和一个包含6个mat文件的测试数据集(1个normal, 2个inner race fault, 3个outer race fault)。通过将函数句柄分配给ReadFcn和WriteToMemberFcn,文件集成数据存储将能够导航到文件中,以所需的格式检索数据。例如,MFPT数据具有存储振动信号gs、采样率sr等的结构轴承。不返回轴承结构本身,而是编写readmfpt支座函数,使文件集成数据存储返回轴承数据结构内部的振动信号gs。

fileLocation = fullfile('.', 'RollingElementBearingFaultDiagnosis-Data-master', 'train_data');
fileExtension = '.mat';
ensembleTrain = fileEnsembleDatastore(fileLocation, fileExtension);
ensembleTrain.ReadFcn = @readMFPTBearing;
ensembleTrain.DataVariables = ["gs", "sr", "rate", "load", "BPFO", "BPFI", "FTF", "BSF"];
ensembleTrain.ConditionVariables = ["Label", "FileName"];
ensembleTrain.WriteToMemberFcn = @writeMFPTBearing;
ensembleTrain.SelectedVariables = ["gs", "sr", "rate", "load", "BPFO", "BPFI", "FTF", "BSF", "Label", "FileName"]
image.png
ensembleTrainTable = tall(ensembleTrain)
image.png

从分析的最后一部分可以看出,BPFO和BPFI处的带通滤波包络谱振幅是轴承故障诊断的两个条件指标。因此,下一步就是从所有的训练数据中提取这两个状态指标。使算法更加健壮,设置一个窄带(带宽= 10Δf,Δf功率谱的频率分辨率)周围BPFO BPFI,然后找到最大振幅在这个狭窄的区间。该算法包含在下面的bearingFeatureExtraction函数中。注意,在示例的其余部分中,BPFI和BPFO周围的包络频谱振幅称为“BPFIAmplitude”和“BPFOAmplitude”。

% To process the data in parallel, use the following code
% ppool = gcp;
% n = numpartitions(ensembleTrain, ppool);
% parfor ct = 1:n
%     subEnsembleTrain = partition(ensembleTrain, n, ct);
%     reset(subEnsembleTrain);
%     while hasdata(subEnsembleTrain)
%         bearingFeatureExtraction(subEnsembleTrain);
%     end
% end
ensembleTrain.DataVariables = [ensembleTrain.DataVariables; "BPFIAmplitude"; "BPFOAmplitude"];
reset(ensembleTrain)
while hasdata(ensembleTrain)
    bearingFeatureExtraction(ensembleTrain)
end

一旦将新的条件指示器添加到文件集成数据存储中,指定SelectedVariables从文件集成数据存储中读取相关数据,并创建一个包含提取的条件指示器的特征表。

ensembleTrain.SelectedVariables = ["BPFIAmplitude", "BPFOAmplitude", "Label"];
featureTableTrain = tall(ensembleTrain);
featureTableTrain = gather(featureTableTrain);
image.png
image.png

image.png
featureTableTrain
image.png

可视化已创建的特性表

figure
gscatter(featureTableTrain.BPFIAmplitude, featureTableTrain.BPFOAmplitude, featureTableTrain.Label, [], 'ox+')
xlabel('BPFI Amplitude')
ylabel('BPFO Amplitude')
image.png

BPFI幅值与BPFO幅值的相对值可以作为判断不同故障类型的有效指标。这里创建了一个新特性,即两个现有特性的日志比率,并以按不同故障类型分组的直方图显示。

featureTableTrain.IOLogRatio = log(featureTableTrain.BPFIAmplitude./featureTableTrain.BPFOAmplitude);
figure
hold on
histogram(featureTableTrain.IOLogRatio(featureTableTrain.Label=="Inner Race Fault"), 'BinWidth', 0.5)
histogram(featureTableTrain.IOLogRatio(featureTableTrain.Label=="Outer Race Fault"), 'BinWidth', 0.5)
histogram(featureTableTrain.IOLogRatio(featureTableTrain.Label=="Normal"), 'BinWidth', 0.5)
plot([-1.5 -1.5 NaN 0.5 0.5], [0 3 NaN 0 3], 'k--')
hold off
ylabel('Count')
xlabel('log(BPFIAmplitude/BPFOAmplitude)')
legend('Inner Race Fault', 'Outer Race Fault', 'Normal', 'Classification Boundary')
image.png

image.png

使用测试数据集进行验证

现在,让我们将工作流应用到一个测试数据集中,并验证上一节中获得的分类器。测试数据包括1个正常数据集、2个内圈故障数据集和3个外圈故障数据集。

fileLocation = fullfile('.', 'RollingElementBearingFaultDiagnosis-Data-master', 'test_data');
fileExtension = '.mat';
ensembleTest = fileEnsembleDatastore(fileLocation, fileExtension);
ensembleTest.ReadFcn = @readMFPTBearing;
ensembleTest.DataVariables = ["gs", "sr", "rate", "load", "BPFO", "BPFI", "FTF", "BSF"];
ensembleTest.ConditionVariables = ["Label", "FileName"];
ensembleTest.WriteToMemberFcn = @writeMFPTBearing;
ensembleTest.SelectedVariables = ["gs", "sr", "rate", "load", "BPFO", "BPFI", "FTF", "BSF", "Label", "FileName"]
image.png
ensembleTest.DataVariables = [ensembleTest.DataVariables; "BPFIAmplitude"; "BPFOAmplitude"];
reset(ensembleTest)
while hasdata(ensembleTest)
    bearingFeatureExtraction(ensembleTest)
end
ensembleTest.SelectedVariables = ["BPFIAmplitude", "BPFOAmplitude", "Label"];
featureTableTest = tall(ensembleTest);
featureTableTest = gather(featureTableTest);
image.png
featureTableTest.IOLogRatio = log(featureTableTest.BPFIAmplitude./featureTableTest.BPFOAmplitude);

figure
hold on
histogram(featureTableTrain.IOLogRatio(featureTableTrain.Label=="Inner Race Fault"), 'BinWidth', 0.5)
histogram(featureTableTrain.IOLogRatio(featureTableTrain.Label=="Outer Race Fault"), 'BinWidth', 0.5)
histogram(featureTableTrain.IOLogRatio(featureTableTrain.Label=="Normal"), 'BinWidth', 0.5)

histogram(featureTableTest.IOLogRatio(featureTableTest.Label=="Inner Race Fault"), 'BinWidth', 0.1)
histogram(featureTableTest.IOLogRatio(featureTableTest.Label=="Outer Race Fault"), 'BinWidth', 0.1)
histogram(featureTableTest.IOLogRatio(featureTableTest.Label=="Normal"), 'BinWidth', 0.1)
plot([-1.5 -1.5 NaN 0.5 0.5], [0 3 NaN 0 3], 'k--')
hold off
ylabel('Count')
xlabel('log(BPFIAmplitude/BPFOAmplitude)')
legend('Inner Race Fault - Train', 'Outer Race Fault - Train', 'Normal - Train', ...
    'Inner Race Fault - Test', 'Outer Race Fault - Test', 'Normal - Test', ...
    'Classification Boundary')
image.png

测试数据集的BPFI和BPFO振幅的对数比与训练数据集的对数比分布一致。最后一节得到的朴素分类器在测试数据集上达到了很好的精度,需要注意的是单特征通常不足以得到一个很好的泛化分类器。通过将数据分成多个部分(创建更多的数据点),提取多个诊断相关特征,根据特征的重要程度选择子集,使用Classification Learner App在Statistics &中训练各种分类器,可以得到更加复杂的分类器机器学习工具。有关此工作流的详细信息,请参考示例“使用Simulink生成故障数据”。

总结

这个例子展示了如何使用kurtogram,频谱峰度和包络谱来识别不同类型的滚动轴承故障。将该算法应用于磁盘上的一批数据集,表明带通滤波包络谱在BPFI和BPFO处的振幅是轴承诊断的两个重要条件指标。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,607评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,047评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,496评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,405评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,400评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,479评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,883评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,535评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,743评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,544评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,612评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,309评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,881评论 3 306
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,891评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,136评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,783评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,316评论 2 342

推荐阅读更多精彩内容