1.命名并实体化一切非自解释的概念
这是算法设计的核心原则之一。可以进一步归结为:你不可让逻辑匿名地裸露出来。你必须命名一切你知晓的概念,并且通过注释、适当的代码粒度管理,命名,妥善封装这些概念,比如:
def isShartNotPlacedCenterized(arFreq, arValue, baseFreqOfShaft, arZeroDbValue):
errorSpan = 0.15
ratio = arFreq[0]/baseFreqOfShaft
ratio = np.abs(ratio - 2)/2;
if(ratio<=errorSpan):
score = gp_vibration_helper.gp_getdbValuebyRawValue(arValue[0], arZeroDbValue);
return (True, score);
else:
return (False, 0);
上面的写法是错误的。正确的写法是:
'''
功能说明:轴不对中判定
版本:V1.0.20240410
机制:轴不对中,二倍频谱线明显增强
ParamIn:(arFreq, arValue, baseFreqOfShaft, arZeroDbValue)
arFreq 低通滤波后的频谱中前N条最高幅度谱线的频率值
arValue 低通滤波后的频谱中前N条最高幅度谱线的幅值
baseFreqOfShart 轴频
arZeroDbValue 用作db输出的系统最高幅值点
ParamOut:(hasError, errorValue)
hasError 有此类故障范围True,否则False
score 故障严重程度,[-40,0],单位db
'''
def isShartNotPlacedCenterized(arFreq, arValue, baseFreqOfShaft, arZeroDbValue):
isflag2xFreqAppeared = gp_vibration_helper.gp_IsSignalAppear(arFreq[0], 2*baseFreqOfShaft);
if(isflag2xFreqAppeared):
dbOfSignal = gp_vibration_helper.gp_getdbValuebyRawValue(arValue[0], arZeroDbValue);
if(dbOfSignal>=-40):
return (True, dbOfSignal);
return (False, 0);
2.在进行任何探索性工作前必须构建好桩模块
比如:在进行轴承振动分析时,你很快会在构建代码的过程中,遇到一堆问题,比如:
- 包络计算
- 频点计算
- db坐标与线性坐标转换
- 功率谱密度、功率谱、与幅度谱
- 频谱泄露
- 窗函数
- 相关性分析
这个列表是无穷尽的,明白吗。如果一路走下去,你会迷失在这个知识网络里,单独拉出任何一个项点,都是10小时,甚至更多时间的阅读和仿真工作量。比如:
使用 FFT 获得功率频谱密度估计- MATLAB & Simulink- MathWorks 中国
这个时候,哪怕你做错,也必须按照错的,做完,留下类似#TODO标记,然后快速构建好整套系统,然后再回头重构。
重构这个词源自一个已经可以工作的版本。没有这个版本的存在,你的工作是未完成,得0分。一个小学生过来把接口封装好,人家领5元钱走人,你一分都不该发——你没有提供应有的服务。
你确实清楚,此时的理解是不完备的,甚至写下来就是错的;或者误差很大,无法在工程上输出稳定结果。但是,即使是错误,也值得记录下来。因为它代表着一个随时可以拿起作为参照的凝固的理解。比如这个对于轴振动故障的一份完整示例:
import numpy as np
import sys
import gp_vibration_helper
'''
功能说明:
isShartNotPlacedCenterized
功能:轴不对中判定
版本:V1.0.20240410
机制:轴不对中,二倍频谱线明显增强
ParamIn:(arFreq, arValue, baseFreqOfShaft, arZeroDbValue)
arFreq 低通滤波后的频谱中前N条最高幅度谱线的频率值
arValue 低通滤波后的频谱中前N条最高幅度谱线的幅值
baseFreqOfShart 轴频
arZeroDbValue 用作db输出的系统最高幅值点
ParamOut:(hasError, errorValue)
hasError 有此类故障范围True,否则False
score 故障严重程度,[-40,0],单位db
'''
def isShartNotPlacedCenterized(arFreq, arValue, baseFreqOfShaft, arZeroDbValue):
isflag2xFreqAppeared = gp_vibration_helper.gp_IsSignalAppear(arFreq[0], 2*baseFreqOfShaft);
if(isflag2xFreqAppeared):
dbOfSignal = gp_vibration_helper.gp_getdbValuebyRawValue(arValue[0], arZeroDbValue);
if(dbOfSignal>=-40):
return (True, dbOfSignal);
return (False, 0);
'''
isShartNotPlacedCenterized
功能:轴不平衡判定,
机制:轴不平衡,一倍频谱线明显增强
版本:V1.0.20240410
ParamIn:(arFreq, arValue, baseFreqOfShaft, arZeroDbValue)
arFreq 低通滤波后的频谱中前N条最高幅度谱线的频率值
arValue 低通滤波后的频谱中前N条最高幅度谱线的幅值
baseFreqOfShart 轴频
arZeroDbValue 用作db输出的系统最高幅值点
ParamOut:(hasError, errorValue)
hasError 有此类故障范围True,否则False
score 故障严重程度,[-40,0],单位db
'''
def isShartLoadNotCenterized(arFreq, arValue, baseFreqOfShart, arZeroDbValue):
isflag2xFreqAppeared = gp_vibration_helper.gp_IsSignalAppear(arFreq[0], baseFreqOfShaft);
if(isflag2xFreqAppeared):
dbOfSignal = gp_vibration_helper.gp_getdbValuebyRawValue(arValue[0], arZeroDbValue);
if(dbOfSignal>=-40):
return (True, dbOfSignal);
return (False, 0);
'''
gpGetShaft_HealthScore
功能:轴故障判定
机制:返回不对中,不平衡的判断结果[百分制]
版本:V1.0.20240410
ParamIn:(fft_abs_array, scaleOfFreq, baseFreqOfShaft)
fft_abs_array 原始振动加速度采样值的幅度值序列,单位幅度
scaleOfFreq 加速度序列的档位,单位Hz
baseFreqOfShart 轴频
ParamOut:(scoreOfShaftLoad, scoreOfShartCenter)
scoreOfShaftLoad 轴平衡健康度[0,100]
scoreOfShartCenter 轴对中健康度[0,100]
'''
def gpGetShaft_HealthTestResult(dbView_fftOfVirbation, scaleOfFreq, baseFreqOfShaft):
(arFreq, arValue) = gp_vibration_helper.gp_getdbValuebyRawValue(dbView_fftOfVirbation, scaleOfFreq, baseFreqOfShaft)
if(arValue[0]<-40): #小于40db健康
return (100, 100)
maxValueInFullFreqRange = np.max(dbView_fftOfVirbation);
(errLoad, dbLoad) = isShartLoadNotCenterized(arFreq, arValue, baseFreqOfShaft, maxValueInFullFreqRange);
(errCenter, dbCenter) = isShartLoadNotCenterized(arFreq, arValue, baseFreqOfShaft, maxValueInFullFreqRange);
scoreOfShartLoad = 100;
scoreOfShartCenter = 100;
if(errLoad):
errorPercent = 100/40*(dbLoad-(-40.0))
scoreOfShaftLoad = 100 - errorPercent;
if(errCenter):
errorPercent = 100/40*(dbCenter-(-40.0))
scoreOfShartCenter = 100 - errorPercent;
return (scoreOfShartLoad, scoreOfShartCenter);
它不对,不够准确,但是这是你现阶段的一份可能输出物,这就够了。
【待续...】