CMSAnalyst.py 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580
  1. import ast
  2. import json
  3. import math
  4. import numpy as np
  5. import pandas as pd
  6. from scipy.signal import hilbert
  7. from app.config import dataBase
  8. from app.database import get_engine
  9. from app.logger import logger
  10. class CMSAnalyst:
  11. def __init__(self, fmin, fmax, table_name, ids):
  12. # 从数据库获取原始数据
  13. self.datas = self._get_by_id(table_name, ids)
  14. self.datas = [df[['mesure_data', 'time_stamp', 'sampling_frequency', 'wind_turbine_number', 'rotational_speed',
  15. 'mesure_point_name']] for df in self.datas]
  16. # 只输入一个id,返回一个[df],所以拿到self.data[0]
  17. self.data_filter = self.datas[0]
  18. # 取数据列
  19. self.data = np.array(ast.literal_eval(self.data_filter['mesure_data'][0]))
  20. self.envelope_spectrum_m = self.data.shape[0]
  21. self.envelope_spectrum_n = 1
  22. # 设置分析参数
  23. self.fs = int(self.data_filter['sampling_frequency'].iloc[0])
  24. self.envelope_spectrum_t = np.arange(self.envelope_spectrum_m) / self.fs
  25. self.fmin = fmin if fmin is not None else 0
  26. self.fmax = fmax if fmax is not None else float('inf')
  27. self.envelope_spectrum_y = self._bandpass_filter(self.data)
  28. self.f, self.HP = self._calculate_envelope_spectrum(self.envelope_spectrum_y)
  29. # 设备信息
  30. self.wind_code = self.data_filter['wind_turbine_number'].iloc[0]
  31. self.rpm_Gen = self.data_filter['rotational_speed'].iloc[0]
  32. self.mesure_point_name = self.data_filter['mesure_point_name'].iloc[0]
  33. self.fn_Gen = round(self.rpm_Gen / 60, 2)
  34. self.CF = self.Characteristic_Frequency()
  35. self.CF = pd.DataFrame(self.CF, index=[0])
  36. n_rolls_m = self.CF['n_rolls'].iloc[0]
  37. d_rolls_m = self.CF['d_rolls'].iloc[0]
  38. D_diameter_m = self.CF['D_diameter'].iloc[0]
  39. theta_deg_m = self.CF['theta_deg'].iloc[0]
  40. self.bearing_frequencies = self.calculate_bearing_frequencies(n_rolls_m, d_rolls_m, D_diameter_m, theta_deg_m,
  41. self.rpm_Gen)
  42. self.bearing_frequencies = pd.DataFrame(self.bearing_frequencies, index=[0])
  43. # frequency_domain_analysis
  44. (
  45. self.frequency_domain_analysis_t,
  46. self.frequency_domain_analysis_f,
  47. self.frequency_domain_analysis_m,
  48. self.frequency_domain_analysis_mag,
  49. self.frequency_domain_analysis_Xrms,
  50. ) = self._calculate_spectrum(self.data)
  51. # time_domain_analysis
  52. self.time_domain_analysis_t = np.arange(self.data.shape[0]) / self.fs
  53. def _get_by_id(self, windcode, ids):
  54. df_res = []
  55. engine = get_engine(dataBase.DATA_DB)
  56. for id in ids:
  57. table_name = windcode + '_wave'
  58. lastday_df_sql = f"SELECT * FROM {table_name} where id = {id} "
  59. df = pd.read_sql(lastday_df_sql, engine)
  60. df_res.append(df)
  61. return df_res
  62. # envelope_spectrum_analysis 包络谱分析
  63. def _bandpass_filter(self, data):
  64. """带通滤波"""
  65. m = data.shape[0]
  66. ni = round(self.fmin * self.envelope_spectrum_m / self.fs + 1)
  67. if self.fmax == float('inf'):
  68. na = m
  69. else:
  70. na = round(self.fmax * m / self.fs + 1)
  71. col = 1
  72. y = np.zeros((self.envelope_spectrum_m, col))
  73. z = np.fft.fft(data)
  74. a = np.zeros(self.envelope_spectrum_m, dtype=complex)
  75. a[ni:na] = z[ni:na]
  76. a[self.envelope_spectrum_m - na + 1: self.envelope_spectrum_m - ni + 1] = z[
  77. self.envelope_spectrum_m - na + 1: self.envelope_spectrum_m - ni + 1
  78. ]
  79. z = np.fft.ifft(a)
  80. y[:, 0] = np.real(z)
  81. return y
  82. def _calculate_envelope_spectrum(self, y):
  83. """计算包络谱"""
  84. m, n = y.shape
  85. HP = np.zeros((m, n))
  86. col = 1
  87. for p in range(col):
  88. H = np.abs(hilbert(y[:, p] - np.mean(y[:, p])))
  89. HP[:, p] = np.abs(np.fft.fft(H - np.mean(H))) * 2 / m
  90. f = np.fft.fftfreq(m, d=1 / self.fs)
  91. return f, HP
  92. def envelope_spectrum(self):
  93. """绘制包络谱"""
  94. # 只取正频率部分
  95. positive_frequencies = self.f[: self.envelope_spectrum_m // 2]
  96. positive_HP = self.HP[: self.envelope_spectrum_m // 2, 0]
  97. x = positive_frequencies
  98. y = positive_HP
  99. title = "包络谱"
  100. xaxis = "频率(Hz)"
  101. yaxis = "加速度(m/s^2)"
  102. # 加速度均方根值(有效值)
  103. Xrms = np.sqrt(np.mean(y ** 2))
  104. rpm_Gen = round(self.rpm_Gen, 2)
  105. BPFI_1X = round(self.bearing_frequencies['BPFI'].iloc[0], 2)
  106. BPFO_1X = round(self.bearing_frequencies['BPFO'].iloc[0], 2)
  107. BSF_1X = round(self.bearing_frequencies['BSF'].iloc[0], 2)
  108. FTF_1X = round(self.bearing_frequencies['FTF'].iloc[0], 2)
  109. fn_Gen = round(self.fn_Gen, 2)
  110. _3P_1X = round(self.fn_Gen, 2) * 3
  111. result = {
  112. "fs": self.fs,
  113. "Xrms": round(Xrms, 2),
  114. "x": list(x),
  115. "y": list(y),
  116. "title": title,
  117. "xaxis": xaxis,
  118. "yaxis": yaxis,
  119. "rpm_Gen": round(rpm_Gen, 2), # 转速r/min
  120. "BPFI": [{"Xaxis": BPFI_1X, "val": "1BPFI"}, {"Xaxis": BPFI_1X * 2, "val": "2BPFI"},
  121. {"Xaxis": BPFI_1X * 3, "val": "3BPFI"}, {"Xaxis": BPFI_1X * 4, "val": "4BPFI"},
  122. {"Xaxis": BPFI_1X * 5, "val": "5BPFI"}, {"Xaxis": BPFI_1X * 6, "val": "6BPFI"}],
  123. "BPFO": [{"Xaxis": BPFO_1X, "val": "1BPFO"}, {"Xaxis": BPFO_1X * 2, "val": "2BPFO"},
  124. {"Xaxis": BPFO_1X * 3, "val": "3BPFO"}, {"Xaxis": BPFO_1X * 4, "val": "4BPFO"},
  125. {"Xaxis": BPFO_1X * 5, "val": "5BPFO"}, {"Xaxis": BPFO_1X * 6, "val": "6BPFO"}],
  126. "BSF": [{"Xaxis": BSF_1X, "val": "1BSF"}, {"Xaxis": BSF_1X * 2, "val": "2BSF"},
  127. {"Xaxis": BSF_1X * 3, "val": "3BSF"}, {"Xaxis": BSF_1X * 4, "val": "4BSF"},
  128. {"Xaxis": BSF_1X * 5, "val": "5BSF"}, {"Xaxis": BSF_1X * 6, "val": "6BSF"}],
  129. "FTF": [{"Xaxis": FTF_1X, "val": "1FTF"}, {"Xaxis": FTF_1X * 2, "val": "2FTF"},
  130. {"Xaxis": FTF_1X * 3, "val": "3FTF"}, {"Xaxis": FTF_1X * 4, "val": "4FTF"},
  131. {"Xaxis": FTF_1X * 5, "val": "5FTF"}, {"Xaxis": FTF_1X * 6, "val": "6FTF"}],
  132. "fn_Gen": [{"Xaxis": fn_Gen, "val": "1X"}, {"Xaxis": fn_Gen * 2, "val": "2X"},
  133. {"Xaxis": fn_Gen * 3, "val": "3X"}, {"Xaxis": fn_Gen * 4, "val": "4X"},
  134. {"Xaxis": fn_Gen * 5, "val": "5X"}, {"Xaxis": fn_Gen * 6, "val": "6X"}],
  135. "B3P": _3P_1X,
  136. }
  137. # result = json.dumps(result, ensure_ascii=False)
  138. return result
  139. # frequency_domain_analysis 频谱分析
  140. def _calculate_spectrum(self, data):
  141. """计算频谱"""
  142. m = data.shape[0]
  143. n = 1
  144. t = np.arange(m) / self.fs
  145. mag = np.zeros((m, n))
  146. Xrms = np.sqrt(np.mean(data ** 2)) # 加速度均方根值(有效值)
  147. # col=1
  148. # for p in range(col):
  149. mag = np.abs(np.fft.fft(data - np.mean(data))) * 2 / m
  150. f = np.fft.fftfreq(m, d=1 / self.fs)
  151. return t, f, m, mag, Xrms
  152. def frequency_domain(self):
  153. """绘制频域波形参数"""
  154. # 只取正频率部分
  155. positive_frequencies = self.frequency_domain_analysis_f[
  156. : self.frequency_domain_analysis_m // 2
  157. ]
  158. positive_mag = self.frequency_domain_analysis_mag[
  159. : self.frequency_domain_analysis_m // 2
  160. ]
  161. x = positive_frequencies
  162. y = positive_mag
  163. title = "频域信号"
  164. xaxis = "频率(Hz)"
  165. yaxis = "加速度(m/s^2)"
  166. Xrms = self.frequency_domain_analysis_Xrms
  167. rpm_Gen = round(self.rpm_Gen, 2)
  168. BPFI_1X = round(self.bearing_frequencies['BPFI'].iloc[0], 2)
  169. BPFO_1X = round(self.bearing_frequencies['BPFO'].iloc[0], 2)
  170. BSF_1X = round(self.bearing_frequencies['BSF'].iloc[0], 2)
  171. FTF_1X = round(self.bearing_frequencies['FTF'].iloc[0], 2)
  172. fn_Gen = round(self.fn_Gen, 2)
  173. _3P_1X = round(self.fn_Gen, 2) * 3
  174. result = {
  175. "fs": self.fs,
  176. "Xrms": round(Xrms, 2),
  177. "x": list(x),
  178. "y": list(y),
  179. "title": title,
  180. "xaxis": xaxis,
  181. "yaxis": yaxis,
  182. "rpm_Gen": round(rpm_Gen, 2), # 转速r/min
  183. "BPFI": [{"Xaxis": BPFI_1X, "val": "1BPFI"}, {"Xaxis": BPFI_1X * 2, "val": "2BPFI"},
  184. {"Xaxis": BPFI_1X * 3, "val": "3BPFI"}, {"Xaxis": BPFI_1X * 4, "val": "4BPFI"},
  185. {"Xaxis": BPFI_1X * 5, "val": "5BPFI"}, {"Xaxis": BPFI_1X * 6, "val": "6BPFI"}],
  186. "BPFO": [{"Xaxis": BPFO_1X, "val": "1BPFO"}, {"Xaxis": BPFO_1X * 2, "val": "2BPFO"},
  187. {"Xaxis": BPFO_1X * 3, "val": "3BPFO"}, {"Xaxis": BPFO_1X * 4, "val": "4BPFO"},
  188. {"Xaxis": BPFO_1X * 5, "val": "5BPFO"}, {"Xaxis": BPFO_1X * 6, "val": "6BPFO"}],
  189. "BSF": [{"Xaxis": BSF_1X, "val": "1BSF"}, {"Xaxis": BSF_1X * 2, "val": "2BSF"},
  190. {"Xaxis": BSF_1X * 3, "val": "3BSF"}, {"Xaxis": BSF_1X * 4, "val": "4BSF"},
  191. {"Xaxis": BSF_1X * 5, "val": "5BSF"}, {"Xaxis": BSF_1X * 6, "val": "6BSF"}],
  192. "FTF": [{"Xaxis": FTF_1X, "val": "1FTF"}, {"Xaxis": FTF_1X * 2, "val": "2FTF"},
  193. {"Xaxis": FTF_1X * 3, "val": "3FTF"}, {"Xaxis": FTF_1X * 4, "val": "4FTF"},
  194. {"Xaxis": FTF_1X * 5, "val": "5FTF"}, {"Xaxis": FTF_1X * 6, "val": "6FTF"}],
  195. "fn_Gen": [{"Xaxis": fn_Gen, "val": "1X"}, {"Xaxis": fn_Gen * 2, "val": "2X"},
  196. {"Xaxis": fn_Gen * 3, "val": "3X"}, {"Xaxis": fn_Gen * 4, "val": "4X"},
  197. {"Xaxis": fn_Gen * 5, "val": "5X"}, {"Xaxis": fn_Gen * 6, "val": "6X"}],
  198. "B3P": _3P_1X,
  199. }
  200. result = json.dumps(result, ensure_ascii=False)
  201. return result
  202. # time_domain_analysis 时域分析
  203. def time_domain(self):
  204. """绘制时域波形参数"""
  205. x = self.time_domain_analysis_t
  206. y = self.data
  207. rpm_Gen = self.rpm_Gen
  208. title = "时间域信号"
  209. xaxis = "时间(s)"
  210. yaxis = "加速度(m/s^2)"
  211. # 图片右侧统计量
  212. # 平均值
  213. mean_value = np.mean(y)
  214. # 最大值
  215. max_value = np.max(y)
  216. # 最小值
  217. min_value = np.min(y)
  218. # 加速度均方根值(有效值)
  219. Xrms = np.sqrt(np.mean(y ** 2))
  220. # 峰值(单峰最大值) # 峰值
  221. Xp = (max_value - min_value) / 2
  222. # 峰峰值
  223. Xpp = max_value - min_value
  224. # 峰值指标
  225. Cf = Xp / Xrms
  226. # 波形指标
  227. Sf = Xrms / mean_value
  228. # 脉冲指标
  229. If = Xp / np.mean(np.abs(y))
  230. # 方根幅值
  231. Xr = np.mean(np.sqrt(np.abs(y))) ** 2
  232. # 裕度指标
  233. Ce = Xp / Xr
  234. # 计算每个数据点的绝对值减去均值后的三次方,并求和
  235. sum_abs_diff_cubed_3 = np.mean((np.abs(y) - mean_value) ** 3)
  236. # 计算偏度指标
  237. Cw = sum_abs_diff_cubed_3 / (Xrms ** 3)
  238. # 计算每个数据点的绝对值减去均值后的四次方,并求和
  239. sum_abs_diff_cubed_4 = np.mean((np.abs(y) - mean_value) ** 4)
  240. # 计算峭度指标
  241. Cq = sum_abs_diff_cubed_4 / (Xrms ** 4)
  242. result = {
  243. "x": list(x),
  244. "y": list(y),
  245. "title": title,
  246. "xaxis": xaxis,
  247. "yaxis": yaxis,
  248. "fs": self.fs,
  249. "Xrms": round(Xrms, 2), # 有效值
  250. "mean_value": round(mean_value, 2), # 均值
  251. "max_value": round(max_value, 2), # 最大值
  252. "min_value": round(min_value, 2), # 最小值
  253. "Xp": round(Xp, 2), # 峰值
  254. "Xpp": round(Xpp, 2), # 峰峰值
  255. "Cf": round(Cf, 2), # 峰值指标
  256. "Sf": round(Sf, 2), # 波形因子
  257. "If": round(If, 2), # 脉冲指标
  258. "Ce": round(Ce, 2), # 裕度指标
  259. "Cw": round(Cw, 2), # 偏度指标
  260. "Cq": round(Cq, 2), # 峭度指标
  261. "rpm_Gen": round(rpm_Gen, 2), # 转速r/min
  262. }
  263. result = json.dumps(result, ensure_ascii=False)
  264. return result
  265. # trend_analysis 趋势图
  266. def trend_analysis(self):
  267. all_stats = []
  268. # 定义积分函数
  269. def _integrate(data, dt):
  270. return np.cumsum(data) * dt
  271. # 定义计算统计指标的函数
  272. def _calculate_stats(data):
  273. mean_value = np.mean(data)
  274. max_value = np.max(data)
  275. min_value = np.min(data)
  276. Xrms = np.sqrt(np.mean(data ** 2)) # 加速度均方根值(有效值)
  277. Xp = (max_value - min_value) / 2 # 峰值(单峰最大值) # 峰值
  278. Cf = Xp / Xrms # 峰值指标
  279. Sf = Xrms / mean_value # 波形指标
  280. If = Xp / np.mean(np.abs(data)) # 脉冲指标
  281. Xr = np.mean(np.sqrt(np.abs(data))) ** 2 # 方根幅值
  282. Ce = Xp / Xr # 裕度指标
  283. # 计算每个数据点的绝对值减去均值后的三次方,并求和
  284. sum_abs_diff_cubed_3 = np.mean((np.abs(data) - mean_value) ** 3)
  285. # 计算偏度指标
  286. Cw = sum_abs_diff_cubed_3 / (Xrms ** 3)
  287. # 计算每个数据点的绝对值减去均值后的四次方,并求和
  288. sum_abs_diff_cubed_4 = np.mean((np.abs(data) - mean_value) ** 4)
  289. # 计算峭度指标
  290. Cq = sum_abs_diff_cubed_4 / (Xrms ** 4)
  291. #
  292. return {
  293. "fs": self.fs, # 采样频率
  294. "Mean": round(mean_value, 2), # 平均值
  295. "Max": round(max_value, 2), # 最大值
  296. "Min": round(min_value, 2), # 最小值
  297. "Xrms": round(Xrms, 2), # 有效值
  298. "Xp": round(Xp, 2), # 峰值
  299. "If": round(If, 2), # 脉冲指标
  300. "Cf": round(Cf, 2), # 峰值指标
  301. "Sf": round(Sf, 2), # 波形指标
  302. "Ce": round(Ce, 2), # 裕度指标
  303. "Cw": round(Cw, 2), # 偏度指标
  304. "Cq": round(Cq, 2), # 峭度指标
  305. # velocity_rms :速度有效值
  306. # time_stamp:时间戳
  307. }
  308. for data in self.datas:
  309. fs = int(self.data_filter['sampling_frequency'].iloc[0])
  310. dt = 1 / fs
  311. time_stamp = data['time_stamp'][0]
  312. data = np.array(ast.literal_eval(data['mesure_data'][0]))
  313. velocity = _integrate(data, dt)
  314. velocity_rms = np.sqrt(np.mean(velocity ** 2))
  315. stats = _calculate_stats(data)
  316. # 速度有效值
  317. stats["velocity_rms"] = round(velocity_rms, 2)
  318. # 时间戳
  319. stats["time_stamp"] = str(time_stamp)
  320. all_stats.append(stats)
  321. all_stats = json.dumps(all_stats, ensure_ascii=False)
  322. return all_stats
  323. def Characteristic_Frequency(self):
  324. """提取轴承、齿轮等参数"""
  325. # 1、从测点名称中提取部件名称(计算特征频率的部件)
  326. str1 = self.mesure_point_name
  327. # 2、连接233的数据库'energy_show',从表'wind_engine_group'查找风机编号'engine_code'对应的机型编号'mill_type_code'
  328. engine_code = self.wind_code
  329. engine = get_engine(dataBase.PLATFORM_DB)
  330. df_sql2 = f"SELECT * FROM wind_engine_group WHERE engine_code = '{engine_code}'"
  331. df2 = pd.read_sql(df_sql2, engine)
  332. mill_type_code = df2['mill_type_code'].iloc[0]
  333. # 3、从相关的表中通过机型编号'mill_type_code'或者齿轮箱编号gearbox_code查找部件'brand'、'model'的参数信息
  334. # unit_bearings主轴承参数表 关键词"main_bearing"
  335. if 'main_bearing' in str1:
  336. logger.info("main_bearing")
  337. # df_sql3 = f"SELECT * FROM {'unit_bearings'} where mill_type_code = {'mill_type_code'} "
  338. df_sql3 = f"SELECT * FROM unit_bearings WHERE mill_type_code = '{mill_type_code}' "
  339. df3 = pd.read_sql(df_sql3, engine)
  340. if df3.empty:
  341. logger.info("警告: 没有找到有效的机型信息")
  342. if 'front' in str1:
  343. brand = 'front_bearing' + '_brand'
  344. model = 'front_bearing' + '_model'
  345. front_has_value = not pd.isna(df3[brand].iloc[0]) and not pd.isna(df3[model].iloc[0])
  346. if not front_has_value:
  347. logger.info("警告: 没有找到有效的品牌信息")
  348. elif 'rear' in str1:
  349. brand = 'rear_bearing' + '_brand'
  350. model = 'rear_bearing' + '_model'
  351. end_has_value = not pd.isna(df3[brand].iloc[0]) and not pd.isna(df3[model].iloc[0])
  352. if not end_has_value:
  353. logger.info("警告: 没有找到有效的品牌信息")
  354. else:
  355. # 当没有指定 front 或 end 时,自动选择有值的轴承信息
  356. front_brand_col = 'front_bearing_brand'
  357. front_model_col = 'front_bearing_model'
  358. rear_brand_col = 'rear_bearing_brand'
  359. rear_model_col = 'rear_bearing_model'
  360. # 检查 front_bearing 是否有值
  361. front_has_value = not pd.isna(df3[front_brand_col].iloc[0]) and not pd.isna(
  362. df3[front_model_col].iloc[0])
  363. # 检查 end_bearing 是否有值
  364. end_has_value = not pd.isna(df3[rear_brand_col].iloc[0]) and not pd.isna(df3[rear_model_col].iloc[0])
  365. # 根据检查结果选择合适的列
  366. if front_has_value and end_has_value:
  367. # 如果两者都有值,默认选择 front
  368. brand = front_brand_col
  369. model = front_model_col
  370. elif front_has_value:
  371. brand = front_brand_col
  372. model = front_model_col
  373. elif end_has_value:
  374. brand = rear_brand_col
  375. model = rear_model_col
  376. else:
  377. # 如果两者都没有有效值,设置默认值或抛出异常
  378. logger.info("警告: 没有找到有效的轴承信息")
  379. brand = front_brand_col # 默认使用 front
  380. model = front_model_col # 默认使用 front
  381. _brand = df3[brand].iloc[0]
  382. _model = df3[model].iloc[0]
  383. logger.info(f"brand = {_brand}, model = {_model}")
  384. # unit_dynamo 发电机参数表 关键词generator stator
  385. elif 'generator' in str1 or 'stator' in str1:
  386. logger.info("generator or 'stator'")
  387. df_sql3 = f"SELECT * FROM unit_dynamo WHERE mill_type_code = '{mill_type_code}' "
  388. df3 = pd.read_sql(df_sql3, engine)
  389. if 'non' in str1:
  390. brand = 'non_drive_end_bearing' + '_brand'
  391. model = 'non_drive_end_bearing' + '_model'
  392. else:
  393. brand = 'drive_end_bearing' + '_brand'
  394. model = 'drive_end_bearing' + '_model'
  395. _brand = df3[brand].iloc[0]
  396. _model = df3[model].iloc[0]
  397. logger.info(f"brand = {_brand}, model = {_model}")
  398. # 齿轮箱区分行星轮/平行轮 和 轴承两个表
  399. elif 'gearbox' in str1:
  400. logger.info("gearbox")
  401. # 根据mill_type_code从unit_gearbox表中获得gearbox_code
  402. df_sql3 = f"SELECT * FROM unit_gearbox WHERE mill_type_code = '{mill_type_code}' "
  403. df3 = pd.read_sql(df_sql3, engine)
  404. gearbox_code = df3['code'].iloc[0]
  405. logger.info(gearbox_code)
  406. # 如果是行星轮/平行轮 则从unit_gearbox_structure 表中取数据
  407. if 'planet' in str1 or 'sun' in str1:
  408. logger.info("'planet' or 'sun' ")
  409. gearbox_structure = 1 if 'planet' in str1 else 2
  410. planetary_gear_grade = 1
  411. if 'first' in str1:
  412. planetary_gear_grade = 1
  413. elif 'second' in str1:
  414. planetary_gear_grade = 2
  415. elif 'third' in str1:
  416. planetary_gear_grade = 3
  417. df_sql33 = f"""
  418. SELECT bearing_brand, bearing_model
  419. FROM unit_gearbox_structure
  420. WHERE gearbox_code = '{gearbox_code}'
  421. AND gearbox_structure = '{gearbox_structure}'
  422. AND planetary_gear_grade = '{planetary_gear_grade}'
  423. """
  424. df33 = pd.read_sql(df_sql33, engine)
  425. if df33.empty:
  426. logger.info("unit_gearbox_structure没有该测点的参数")
  427. else:
  428. brand = 'bearing' + '_brand'
  429. model = 'bearing' + '_model'
  430. logger.info(brand)
  431. _brand = df33[brand].iloc[0]
  432. _model = df33[model].iloc[0]
  433. has_value = not pd.isna(df33[brand].iloc[0]) and not pd.isna(df33[model].iloc[0])
  434. if has_value:
  435. logger.info(_brand)
  436. logger.info(_model)
  437. else:
  438. logger.info("警告: 没有找到有效的轴承信息")
  439. # 如果是齿轮箱轴承 则从unit_gearbox_bearings 表中取数据
  440. elif 'shaft' in str1 or 'input' in str1:
  441. logger.info("'shaft'or'input'")
  442. # df_sql33 = f"SELECT * FROM unit_gearbox_bearings WHERE gearbox_code = '{gearbox_code}' "
  443. # df33 = pd.read_sql(df_sql33, Engine33)
  444. # 高速轴 低速中间轴 取bearing_rs/gs均可
  445. parallel_wheel_grade = 1
  446. if 'low_speed' in str1:
  447. parallel_wheel_grade = 1
  448. elif 'low_speed_intermediate' in str1:
  449. parallel_wheel_grade = 2
  450. elif 'high_speed' in str1:
  451. parallel_wheel_grade = 3
  452. df_sql33 = f"""
  453. SELECT bearing_rs_brand, bearing_rs_model, bearing_gs_brand, bearing_gs_model
  454. FROM unit_gearbox_bearings
  455. WHERE gearbox_code = '{gearbox_code}'
  456. AND parallel_wheel_grade = '{parallel_wheel_grade}'
  457. """
  458. df33 = pd.read_sql(df_sql33, engine)
  459. if not df33.empty:
  460. if 'high_speed' in str1 or 'low_speed_intermediate' in str1:
  461. rs_brand = 'bearing_rs' + '_brand'
  462. rs_model = 'bearing_rs' + '_model'
  463. gs_brand = 'bearing_gs' + '_brand'
  464. gs_model = 'bearing_gs' + '_model'
  465. rs_has_value = not pd.isna(df33[rs_brand].iloc[0]) and not pd.isna(df33[rs_model].iloc[0])
  466. gs_has_value = not pd.isna(df33[gs_brand].iloc[0]) and not pd.isna(df33[gs_model].iloc[0])
  467. if rs_has_value and gs_has_value:
  468. brand = rs_brand
  469. model = rs_model
  470. elif rs_has_value:
  471. brand = rs_brand
  472. model = rs_model
  473. elif gs_has_value:
  474. brand = gs_brand
  475. model = gs_model
  476. else:
  477. logger.info("警告: 没有找到有效的品牌信息")
  478. brand = rs_brand
  479. model = rs_model
  480. # 低速轴 取bearing_model
  481. elif 'low_speed' in str1:
  482. brand = 'bearing' + '_brand'
  483. model = 'bearing' + '_model'
  484. else:
  485. logger.info("警告: 没有找到有效的轴承信息")
  486. logger.info(f"brand = {brand}")
  487. _brand = df33[brand].iloc[0]
  488. _model = df33[model].iloc[0]
  489. logger.info(f"brand = {_brand}, model = {_model}")
  490. # 4、从表'unit_dict_brand_model'中通过'_brand'、'_model'查找部件的参数信息
  491. df_sql4 = f"SELECT * FROM unit_dict_brand_model where manufacture = %s AND model_number = %s"
  492. params = [(_brand, _model)]
  493. df4 = pd.read_sql(df_sql4, engine, params=params)
  494. n_rolls = df4['rolls_number'].iloc[0]
  495. d_rolls = df4['rolls_diameter'].iloc[0]
  496. D_diameter = df4['circle_diameter'].iloc[0]
  497. theta_deg = df4['theta_deg'].iloc[0]
  498. result = {
  499. "type": 'bearing',
  500. "n_rolls": round(n_rolls, 2),
  501. "d_rolls": round(d_rolls, 2),
  502. "D_diameter": round(D_diameter, 2),
  503. "theta_deg": round(theta_deg, 2),
  504. }
  505. return result
  506. def calculate_bearing_frequencies(self, n, d, D, theta_deg, rpm):
  507. """
  508. 计算轴承各部件特征频率
  509. 参数:
  510. n (int): 滚动体数量
  511. d (float): 滚动体直径(单位:mm)
  512. D (float): 轴承节圆直径(滚动体中心圆直径,单位:mm)
  513. theta_deg (float): 接触角(单位:度)
  514. rpm (float): 转速(转/分钟)
  515. 返回:
  516. dict: 包含各特征频率的字典(单位:Hz)
  517. """
  518. # 转换角度为弧度
  519. theta = math.radians(theta_deg)
  520. # 转换直径单位为米(保持单位一致性,实际计算中比值抵消单位影响)
  521. # 注意:由于公式中使用的是比值,单位可以保持mm不需要转换
  522. ratio = d / D
  523. # 基础频率计算(转/秒)
  524. f_r = rpm / 60.0
  525. # 计算各特征频率
  526. BPFI = n / 2 * (1 + ratio * math.cos(theta)) * f_r # 内圈故障频率
  527. BPFO = n / 2 * (1 - ratio * math.cos(theta)) * f_r # 外圈故障频率
  528. BSF = (D / (2 * d)) * (1 - (ratio ** 2) * (math.cos(theta) ** 2)) * f_r # 滚动体故障频率
  529. FTF = 0.5 * (1 - ratio * math.cos(theta)) * f_r # 保持架故障频率
  530. return {
  531. "BPFI": round(BPFI, 2),
  532. "BPFO": round(BPFO, 2),
  533. "BSF": round(BSF, 2),
  534. "FTF": round(FTF, 2),
  535. }