SOC_pre_vltV.py 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512
  1. import pandas as pd
  2. import numpy as np
  3. import peakbotm
  4. from scipy.signal import savgol_filter as svflter
  5. from scipy import interpolate
  6. import os
  7. import joblib
  8. class cell_chracter:
  9. def __init__(self, df_bms, df_param, cellvolt_name, celltemp_name): #参数初始化
  10. self.df_bms=pd.DataFrame(df_bms)
  11. self.bmstime= pd.to_datetime(df_bms['time'], format='%Y-%m-%d %H:%M:%S')
  12. self.cellvolt_list=cellvolt_name
  13. self.celltemp_name=celltemp_name
  14. self.capty = float(df_param['capacity'])
  15. np_chrg_ocv = df_param['charge_ocv_v']
  16. np_chrg_soc = df_param['charge_ocv_soc']
  17. np_dschrg_ocv = df_param['discharge_ocv_v']
  18. np_dschrg_soc = df_param['discharge_ocv_soc']
  19. np_ocv = (np.array(np_chrg_ocv) + np.array(np_dschrg_ocv))/2
  20. np_soc = (np.array(np_chrg_soc) + np.array(np_dschrg_soc))/2
  21. self.LookTab_OCV = np_ocv
  22. self.LookTab_SOC = np_soc
  23. abs_model_file=f"{os.path.dirname(os.path.abspath(__file__))}/model/V_1_0_0/"
  24. self.Dnn_predict = joblib.load(abs_model_file + 'Dnnmodel.pkl')
  25. self.inputnorm_x = joblib.load(abs_model_file + 'normorlized_x')
  26. self.inputnorm_y = joblib.load(abs_model_file + 'normorlized_y')
  27. # self.Dnn_predict = dnn_predict
  28. # self.inputnorm_x = input_norm_x
  29. # self.inputnorm_y = input_norm_y
  30. def states_cal(self):
  31. def soc_cal_ncm(df_data_temp):
  32. data_ori_temp = df_data_temp.copy()
  33. data_ori_delNan = data_ori_temp.dropna(axis = 0, subset = ["pack_crnt", "pack_soc"])#删除电压、电流、bms状态值为Nan值所在行"CellVoltage",
  34. data_ori_delnone = data_ori_delNan.drop(data_ori_delNan[(data_ori_delNan['pack_soc'] == "") | (data_ori_delNan['pack_crnt'] == "")].index)#删除电压、电流、bms状态值为空值所在行(data_ori_delNan['CellVoltage'] == "") |
  35. data_ori = data_ori_delnone.fillna(method ='backfill', inplace = False , axis = 0)
  36. celltemp_name = self.celltemp_name#电芯温度数量
  37. #---------------------------------充电过程判断--------------------------------------
  38. def clean_dead_value(series, num_dead_thresh):
  39. slide_list = [series.index[0]]
  40. slide_list_all = []
  41. for i in range(series.index[0],series.index[-1]):
  42. j = i + 1
  43. diff = series[j] - series[i]
  44. if diff == 0:
  45. slide_list.append(j)
  46. else:
  47. slide_list.clear()
  48. slide_list.append(j)
  49. if len(slide_list) >= num_dead_thresh:
  50. target_list = slide_list.copy()
  51. slide_list_all.append(target_list)
  52. index= [] # 将找到的满足条件的index合并
  53. for i in range(len(slide_list_all) - 1):
  54. if set(slide_list_all[i]) < set(slide_list_all[i + 1]):
  55. index.append(i)
  56. m = {i: element for i, element in enumerate(slide_list_all)}
  57. [m.pop(i) for i in index]
  58. return list(m.values())
  59. df_data_chrg_chek = data_ori.copy()
  60. df_data_chrg_chek.reset_index(drop = True, inplace = True)
  61. df_data_chrg_chek['crnt_flg'] = 0
  62. df_data_chrg_chek.loc[df_data_chrg_chek['pack_crnt'] > 0, 'crnt_flg'] = 1
  63. df_data_chrg_chek.loc[df_data_chrg_chek['pack_crnt'] < 0, 'crnt_flg'] = -1
  64. df_data_chrg_chek['sts_flg'] = 2
  65. df_sts_chrg = pd.DataFrame(columns=list(df_data_chrg_chek.columns))
  66. df_crnt_flg = df_data_chrg_chek['crnt_flg']
  67. num_dead_thresh = 15#判断连续多少个数据为阈值
  68. indexs_to_delelte = clean_dead_value(df_crnt_flg, num_dead_thresh)#获得连续数据所在的行
  69. rest_num = len(indexs_to_delelte)
  70. if rest_num > 0:#仅有一个连续数据时
  71. for splice_item in range(0, rest_num):#rest_num
  72. df_data_temp = df_data_chrg_chek.iloc[indexs_to_delelte[splice_item][0]:indexs_to_delelte[splice_item][-1]]#获得电流连续数据
  73. df_data_temp.reset_index(drop = True, inplace = True)
  74. df_soc_temp = df_data_temp['pack_soc']
  75. delta_soc = round((df_soc_temp.iloc[-1] - df_soc_temp.iloc[0]), 3)
  76. df_time_temp = pd.to_datetime(df_data_temp['time'])
  77. delta_time = (df_time_temp.iloc[-1] - df_time_temp.iloc[0])/pd.Timedelta(1, 'hours')
  78. if all(df_data_temp['crnt_flg'] == 0):#静置判断
  79. if delta_time > 0.17:
  80. df_data_temp['sts_flg'] = 0
  81. df_sts_chrg = df_sts_chrg.append(df_data_temp)
  82. df_sts_chrg.reset_index(drop = True, inplace = True)
  83. elif all(df_data_temp['crnt_flg'] == -1):#充电判断
  84. if (delta_time >= 0.03) and delta_soc >= 30:
  85. df_data_temp['sts_flg'] = 1
  86. df_sts_chrg = df_sts_chrg.append(df_data_temp)
  87. df_sts_chrg.reset_index(drop = True, inplace = True)
  88. elif all(df_data_temp['crnt_flg'] == 1):#充电判断
  89. if (delta_time >= 0.03) and delta_soc >= 30:
  90. df_data_temp['sts_flg'] = 1
  91. df_sts_chrg = df_sts_chrg.append(df_data_temp)
  92. df_sts_chrg.reset_index(drop = True, inplace = True)
  93. df_dschrg = pd.concat([df_data_chrg_chek, df_sts_chrg, df_sts_chrg]).drop_duplicates(subset = ['time', 'pack_soc'], keep = False)
  94. data_temp = pd.concat([df_dschrg, df_sts_chrg])
  95. data_temp.sort_values(by = 'time', inplace = True)
  96. data_temp.reset_index(drop = True, inplace = True)
  97. df_chrg_temp = data_temp.loc[data_temp['sts_flg'] == 1]
  98. df_chrg_temp.reset_index(inplace = True, drop = True)
  99. SOC_pre_cal = pd.DataFrame(columns = ['sn', 'time', 'soc_ori', 'soc_pre', 'soc_error', 'odo', 'method', 'battery_type'])
  100. data_temp_rest = data_temp[abs(data_temp['pack_crnt']) > 0.02*self.capty]
  101. np_dschrg_time = pd.to_datetime(data_temp_rest['time'])
  102. dff_dschrg_time = np.diff(np_dschrg_time)/pd.Timedelta(1, 'min')#放电过程前后时间差
  103. rest_dschrg_pos = np.where(dff_dschrg_time > 120)#筛选前后时间差大于30min的位置及时间点,判断为两次放电
  104. if (len(rest_dschrg_pos[0]) > 0):
  105. df_celvlt = data_temp_rest[self.cellvolt_list]
  106. df_celvlt_min = df_celvlt.min(axis = 1)
  107. df_celvlt_max = df_celvlt.max(axis = 1)
  108. LookTab_OCV = self.LookTab_OCV
  109. LookTab_SOC = self.LookTab_SOC
  110. for item_rest in rest_dschrg_pos[0]:
  111. if (abs(data_temp_rest['pack_crnt'].iloc[item_rest + 1]) < 0.03*self.capty) and (abs(data_temp_rest['pack_crnt'].iloc[item_rest + 1]) > 0.1):
  112. min_volt = min(LookTab_OCV)
  113. max_volt = max(LookTab_OCV)
  114. soc_interplt = interpolate.interp1d(LookTab_OCV, LookTab_SOC, kind = 'linear')#OCV-SOC插值函数
  115. df_celvlt_min[df_celvlt_min < min_volt] = min_volt + 0.0005
  116. df_celvlt_max[df_celvlt_max > max_volt] = max_volt - 0.0005
  117. cellvltmin = df_celvlt_min[item_rest + 1]
  118. cellvltmax = df_celvlt_max[item_rest + 1]
  119. SOC_now = data_temp_rest['pack_soc'].iloc[item_rest + 1]
  120. SOC_min = round(soc_interplt(cellvltmin)[0], 1)
  121. SOC_max = round(soc_interplt(cellvltmax)[0], 1)
  122. if SOC_min < 30:
  123. SOC_cal = 0.8*SOC_min + 0.2*SOC_max
  124. SOC_del = abs(SOC_cal - SOC_now)
  125. SOC_real = str([SOC_max, SOC_min, SOC_cal])
  126. method = 1
  127. elif SOC_max > 90:
  128. SOC_cal = 0.8*SOC_max + 0.2*SOC_min
  129. SOC_del = abs(SOC_cal - SOC_now)
  130. SOC_real = str([SOC_max, SOC_min, SOC_cal])
  131. method = 2
  132. else:
  133. SOC_cal = 0.5*(SOC_max + SOC_min)
  134. SOC_del = abs(SOC_cal - SOC_now)
  135. SOC_real = str([SOC_max, SOC_min, SOC_cal])
  136. method = 3
  137. if SOC_del > 5:
  138. time_pre = data_temp_rest['time'].iloc[item_rest + 1]
  139. odo_now = data_temp_rest['odo'].iloc[item_rest + 1]
  140. SOC_pre_cal.loc[len(SOC_pre_cal)] = [data_temp_rest['sn'].iloc[0], time_pre, SOC_now, SOC_real, SOC_del, odo_now, method, 'NCM']
  141. return SOC_pre_cal
  142. def soc_cal_lfp(df_data_temp):
  143. data_ori_temp = df_data_temp.copy()
  144. data_ori_delNan = data_ori_temp.dropna(axis = 0, subset = ["pack_crnt", "pack_soc"])#删除电压、电流、bms状态值为Nan值所在行"CellVoltage",
  145. data_ori_delnone = data_ori_delNan.drop(data_ori_delNan[(data_ori_delNan['pack_soc'] == "") | (data_ori_delNan['pack_crnt'] == "")].index)#删除电压、电流、bms状态值为空值所在行(data_ori_delNan['CellVoltage'] == "") |
  146. data_ori = data_ori_delnone.fillna(method ='backfill', inplace = False , axis = 0)
  147. itemsn = data_ori['sn'].iloc[0]
  148. def clean_dead_value(series, num_dead_thresh):
  149. slide_list = [series.index[0]]
  150. slide_list_all = []
  151. for i in range(series.index[0],series.index[-1]):
  152. j = i + 1
  153. diff = series[j] - series[i]
  154. if diff == 0:
  155. slide_list.append(j)
  156. else:
  157. slide_list.clear()
  158. slide_list.append(j)
  159. if len(slide_list) >= num_dead_thresh:
  160. target_list = slide_list.copy()
  161. slide_list_all.append(target_list)
  162. index= [] # 将找到的满足条件的index合并
  163. for i in range(len(slide_list_all) - 1):
  164. if set(slide_list_all[i]) < set(slide_list_all[i + 1]):
  165. index.append(i)
  166. m = {i: element for i, element in enumerate(slide_list_all)}
  167. [m.pop(i) for i in index]
  168. return list(m.values())
  169. df_data_chrg_chek = data_ori.copy()
  170. df_data_chrg_chek.reset_index(drop = True, inplace = True)
  171. df_data_chrg_chek['crnt_flg'] = 0
  172. df_data_chrg_chek.loc[df_data_chrg_chek['pack_crnt'] > 0, 'crnt_flg'] = 1
  173. df_data_chrg_chek.loc[df_data_chrg_chek['pack_crnt'] < 0, 'crnt_flg'] = -1
  174. df_data_chrg_chek['sts_flg'] = 2
  175. df_sts_chrg = pd.DataFrame(columns=list(df_data_chrg_chek.columns))
  176. df_crnt_flg = df_data_chrg_chek['crnt_flg']
  177. num_dead_thresh = 15#判断连续多少个数据为阈值
  178. indexs_to_delelte = clean_dead_value(df_crnt_flg, num_dead_thresh)#获得连续数据所在的行
  179. rest_num = len(indexs_to_delelte)
  180. if rest_num > 0:#仅有一个连续数据时
  181. for splice_item in range(0, rest_num):#rest_num
  182. df_data_temp = df_data_chrg_chek.iloc[indexs_to_delelte[splice_item][0]:indexs_to_delelte[splice_item][-1]]#获得电流连续数据
  183. df_data_temp.reset_index(drop = True, inplace = True)
  184. if len(df_data_temp) > 10:
  185. df_soc_temp = df_data_temp['pack_soc']
  186. delta_soc = round((df_soc_temp.iloc[-1] - df_soc_temp.iloc[0]), 3)
  187. df_time_temp = pd.to_datetime(df_data_temp['time'])
  188. delta_time = (df_time_temp.iloc[-1] - df_time_temp.iloc[0])/pd.Timedelta(1, 'hours')
  189. if all(df_data_temp['crnt_flg'] == 0):#静置判断
  190. if delta_time > 0.17:
  191. df_data_temp['sts_flg'] = 0
  192. df_sts_chrg = df_sts_chrg.append(df_data_temp)
  193. df_sts_chrg.reset_index(drop = True, inplace = True)
  194. elif all(df_data_temp['crnt_flg'] == -1):#充电判断
  195. if (delta_time >= 0.03) and delta_soc >= 30:
  196. df_data_temp['sts_flg'] = 1
  197. df_sts_chrg = df_sts_chrg.append(df_data_temp)
  198. df_sts_chrg.reset_index(drop = True, inplace = True)
  199. elif all(df_data_temp['crnt_flg'] == 1):#充电判断
  200. if (delta_time >= 0.03) and delta_soc >= 30:
  201. df_data_temp['sts_flg'] = 1
  202. df_sts_chrg = df_sts_chrg.append(df_data_temp)
  203. df_sts_chrg.reset_index(drop = True, inplace = True)
  204. df_dschrg = pd.concat([df_data_chrg_chek, df_sts_chrg, df_sts_chrg]).drop_duplicates(subset = ['time', 'pack_soc'], keep = False)
  205. data_temp = pd.concat([df_dschrg, df_sts_chrg])
  206. data_temp.sort_values(by = 'time', inplace = True)
  207. data_temp.reset_index(inplace = True, drop = True)
  208. celltemp_name = self.celltemp_name#电芯温度数量
  209. #---------------------------------充电过程判断--------------------------------------
  210. df_chrg_temp = data_temp.loc[data_temp['sts_flg'] == 1]
  211. df_chrg_temp.reset_index(inplace = True, drop = True)
  212. df_chracter_ofc = pd.DataFrame()
  213. SOC_rlt_final = pd.DataFrame()
  214. SOC_pre_cal = pd.DataFrame(columns = ['sn', 'time', 'soc_ori', 'soc_pre', 'soc_error', 'odo', 'method'])
  215. SOC_pre_cal_dnn = pd.DataFrame(columns = ['sn', 'time', 'soc_ori', 'soc_pre', 'soc_error', 'odo', 'method'])
  216. data_temp_rest = data_temp[abs(data_temp['pack_crnt']) > 0.02*self.capty]
  217. np_dschrg_time = pd.to_datetime(data_temp_rest['time'])
  218. dff_dschrg_time = np.diff(np_dschrg_time)/pd.Timedelta(1, 'min')#放电过程前后时间差
  219. rest_dschrg_pos = np.where(dff_dschrg_time > 120)#筛选前后时间差大于30min的位置及时间点,判断为两次放电
  220. if (len(rest_dschrg_pos[0]) > 0):
  221. df_celvlt = data_temp_rest[self.cellvolt_list]
  222. df_celvlt_min = df_celvlt.min(axis = 1)
  223. df_celvlt_max = df_celvlt.max(axis = 1)
  224. LookTab_OCV = self.LookTab_OCV
  225. LookTab_SOC = self.LookTab_SOC
  226. ocv_interplt = interpolate.interp1d(LookTab_SOC, LookTab_OCV, kind = 'linear')#OCV-SOC插值函数
  227. ocv_pre_val = ocv_interplt(25)
  228. for item_rest in rest_dschrg_pos[0]:
  229. if (abs(data_temp_rest['pack_crnt'].iloc[item_rest + 1]) < 0.02*self.capty) and (abs(data_temp_rest['pack_crnt'].iloc[item_rest + 1]) > 0.3) and\
  230. (df_celvlt_min.iloc[item_rest + 1] < ocv_pre_val) and (df_celvlt_min.iloc[item_rest + 1] > 2):
  231. min_volt = min(LookTab_OCV)
  232. soc_interplt = interpolate.interp1d(LookTab_OCV, LookTab_SOC, kind = 'linear')#OCV-SOC插值函数
  233. df_celvlt_min[df_celvlt_min < min_volt] = min_volt + 0.0005
  234. cellvltmin = df_celvlt_min[item_rest + 1]
  235. cellvltmax = df_celvlt_max[item_rest + 1]
  236. SOC_now = data_temp_rest['pack_soc'].iloc[item_rest + 1]
  237. SOC_min = round(soc_interplt(cellvltmin)[0], 1)
  238. SOC_max = round(soc_interplt(cellvltmax)[0], 1)
  239. if SOC_min < 30:
  240. SOC_cal = 0.8*SOC_min + 0.2*SOC_max
  241. SOC_del = abs(SOC_cal - SOC_now)
  242. SOC_real = str([SOC_max, SOC_min, SOC_cal])
  243. method = 2
  244. elif SOC_max > 90:
  245. SOC_cal = 0.8*SOC_max + 0.2*SOC_min
  246. SOC_del = abs(SOC_cal - SOC_now)
  247. SOC_real = str([SOC_max, SOC_min, SOC_cal])
  248. method = 2
  249. else:
  250. SOC_cal = 0.5*(SOC_max + SOC_min)
  251. SOC_del = abs(SOC_cal - SOC_now)
  252. SOC_real = str([SOC_max, SOC_min, SOC_cal])
  253. method = 0
  254. if SOC_del > 5:
  255. time_pre = data_temp_rest['time'].iloc[item_rest + 1]
  256. odo_now = data_temp_rest['odo'].iloc[item_rest + 1]
  257. SOC_pre_cal.loc[len(SOC_pre_cal)] = [itemsn, time_pre, SOC_now, SOC_real, SOC_del, odo_now, method]
  258. #------------------------------------DNN方法估计SOC
  259. if not df_chrg_temp.empty:
  260. para_lvbo = 7
  261. chrgr_time = pd.to_datetime(df_chrg_temp['time'])
  262. delta_time = (np.diff(chrgr_time)/pd.Timedelta(1, 'min'))#计算时间差的分钟数
  263. pos = np.where(delta_time > 10)#充电数据分段,大于10min时,认为是两个充电过程
  264. dvsocchrcter = []
  265. splice_num = []
  266. if len(pos[0]) >= 1:
  267. pos_ful_tem = np.insert(pos, 0, 0)
  268. pos_len = len(pos_ful_tem)
  269. data_len = len(chrgr_time)
  270. pos_ful = np.insert(pos_ful_tem, pos_len, data_len-1)
  271. for item in range(0,len(pos_ful)-1):
  272. splice_num.extend(item*np.ones(pos_ful[item +1]-pos_ful[item]))
  273. splice_num = np.insert(splice_num, 0, 0)
  274. else:
  275. splice_num = np.zeros(len(chrgr_time))
  276. pos_ful = np.array([0])
  277. if len(splice_num) > 0:
  278. df_chrg_temp['chrgr_rest'] = splice_num
  279. chrgr_splice_num = np.unique(df_chrg_temp['chrgr_rest'])#判断有几段充电数据
  280. if len(chrgr_splice_num) > 0:#特征参数中增加一列,电压微分中波峰到满充位置电量,进行SOH计算
  281. for item_chrgr in chrgr_splice_num:
  282. df_chrgr_splice_data = df_chrg_temp.loc[(df_chrg_temp['chrgr_rest'] == item_chrgr)]
  283. df_chrgr_splice_data.reset_index(inplace = True, drop = True)
  284. df_soc_temp = df_chrgr_splice_data['pack_soc']
  285. df_time_temp = pd.to_datetime(df_chrgr_splice_data['time'])
  286. delta_soc = round((df_soc_temp.iloc[-1] - df_soc_temp.iloc[0]), 3)
  287. if (df_soc_temp.iloc[0] < 40) and (len(df_soc_temp) > 30):
  288. delta_time = round((df_time_temp.iloc[-1] - df_time_temp.iloc[0])/pd.Timedelta(1, 'hours'), 3)
  289. rate_chrg = round(delta_soc/(100*delta_time), 2)
  290. df_celvlt_max = df_chrgr_splice_data['cell_volt_max']
  291. df_crnt = abs(df_chrgr_splice_data['pack_crnt'])
  292. df_soc = df_chrgr_splice_data['pack_soc']
  293. if (df_celvlt_max.iloc[-1] > 3.55) and (df_crnt.iloc[-1] < 0.1*self.capty) and (df_soc.iloc[-1] < 95):
  294. SOC_now = df_soc.iloc[-1]
  295. SOC_real = 100
  296. SOC_del = 100 - SOC_now
  297. method = 3
  298. time_pre = df_chrgr_splice_data['time'].iloc[-1]
  299. odo_now = df_chrgr_splice_data['odo'].iloc[0]
  300. if SOC_del > 5:
  301. SOC_pre_cal.loc[len(SOC_pre_cal)] = [itemsn, time_pre, SOC_now, SOC_pre_cal, SOC_del, odo_now, method]
  302. df_celvltdff = df_celvlt_max.diff()
  303. df_celvltdff.fillna(method ='bfill', inplace = True , axis = 0)
  304. df_celvltdff.reset_index(inplace = True, drop = True)
  305. df_celvltdffsmth = svflter(df_celvltdff, para_lvbo, 3)
  306. df_time_temp = pd.to_datetime(df_chrgr_splice_data['time'])
  307. np_dff_time = np.diff(df_time_temp)/pd.Timedelta(1, 'hours')
  308. np_dff_time_new = np.append(np_dff_time, 0)
  309. np_chrg_ah = np.multiply(np.array(np_dff_time_new),-1*np.array(df_chrgr_splice_data['pack_crnt']))
  310. chrg_ahlst = [sum(np_chrg_ah[:i]) for i in range(1, len(np_chrg_ah)+1)]
  311. df_chrg_ah = pd.DataFrame(chrg_ahlst)
  312. df_chrg_ah.columns = ['chrgah']
  313. df_data_tem = df_chrgr_splice_data[['time','sn', 'pack_crnt','pack_volt','pack_soc', 'odo', 'cell_volt_max',
  314. 'cell_temp_max', 'cell_temp_min']]
  315. df_data = pd.concat([df_data_tem, df_chrg_ah], axis = 1)
  316. df_data.rename(columns = {'cell_temp_max':'max_T', 'cell_temp_min':'min_T', 'odo':'odo', 'cell_volt_max':'frst'}, inplace = True)
  317. df_data.drop(df_data[(df_data[['max_T', 'min_T']] < -30).any(axis = 1) | (df_data[['max_T', 'min_T']] > 125).any(axis = 1)].index, inplace = True)
  318. df_data.drop(df_data[(df_data['frst'] < 2) | (df_data['frst'] > 5)].index, inplace = True)
  319. df_data.reset_index(drop = True, inplace = True)
  320. datalen = len(df_data)
  321. diff_vlt = df_data['frst'].diff()
  322. # 使用 cumsum() 函数标记下降区域
  323. down_regions = (diff_vlt >= 0).cumsum()
  324. # 使用 groupby() 和 transform() 函数计算每个区域的长度
  325. region_sizes = down_regions.groupby(down_regions).transform('size')
  326. # 使用 where() 函数删除连续3次以上下降位置的数据
  327. data_series_filtered = df_data.where(region_sizes < 10)
  328. nan_elements = data_series_filtered.isna()
  329. # 使用 np.where() 函数查找所有 NaN 元素的位置
  330. nan_indices = np.where(nan_elements == True)[0]
  331. if len(nan_indices)>0:
  332. last_num = nan_indices[-1]
  333. else:
  334. last_num = 0
  335. df_data_real = df_data.iloc[last_num:]
  336. df_data_real.reset_index(drop= True, inplace=True)
  337. df_dataana = df_data_real.loc[(df_data_real['pack_soc'] > 30) & (df_data_real['pack_soc'] < 80)]
  338. df_dataana.reset_index(drop = True, inplace = True)
  339. if (len(df_dataana) > 20):# and (rate_chrg <= 0.95)
  340. def dats_interp(input1, input2, datalen):
  341. cap_frst = list(np.linspace(input1.iloc[0], input1.iloc[-1], datalen, endpoint = False))#len(df_dataana['chrgah'])
  342. fuc_inter = interpolate.interp1d(input1, input2, kind = 'nearest')#定义差值函数
  343. vlt_splce_temp = list(fuc_inter(cap_frst))
  344. return vlt_splce_temp
  345. crntabs = list(abs(df_dataana['pack_crnt']))
  346. df_dataana['abscrnt'] = crntabs
  347. crntnum = df_dataana.loc[:,'abscrnt'].value_counts() #统计电芯数量这一列每个元素出现的个数
  348. crntmaxNums = int(crntnum.idxmax())
  349. df_data_cal = df_dataana.loc[(abs(df_dataana['pack_crnt']) > crntmaxNums-4) & (abs(df_dataana['pack_crnt']) < crntmaxNums+4)]
  350. df_data_cal = df_data_cal.iloc[3:-2]
  351. df_data_cal.reset_index(drop= True, inplace=True)
  352. if (len(df_data_cal) > 10):# and (all(abs(dff_soc) < 2))and (crntmaxNums/self.capty < 0.95)
  353. rate_end = round(abs(df_data['pack_crnt'].iloc[-1])/self.capty, 3)
  354. df_data_cal['frst'] = svflter(df_data_cal['frst'], para_lvbo, 3)
  355. split_len = int(1.2*(df_data_cal['pack_soc'].iloc[-1] - df_data_cal['pack_soc'].iloc[0]))
  356. if split_len > 10:
  357. cap_frst = list(np.linspace(df_data_cal['chrgah'].iloc[0], df_data_cal['chrgah'].iloc[-1], split_len, endpoint = False))#len(df_dataana['chrgah'])
  358. vlt_splce_temp = dats_interp(df_data_cal['chrgah'], df_data_cal['frst'], split_len)
  359. soc_splt = dats_interp(df_data_cal['chrgah'], df_data_cal['pack_soc'], split_len)
  360. crnt_splt = dats_interp(df_data_cal['chrgah'], df_data_cal['pack_crnt'], split_len)
  361. maxt_splt = dats_interp(df_data_cal['chrgah'], df_data_cal['max_T'], split_len)
  362. mint_splt = dats_interp(df_data_cal['chrgah'], df_data_cal['min_T'], split_len)
  363. odo_splt = [df_data_cal['odo'].iloc[0]]*split_len
  364. time_splt = dats_interp(df_data_cal['chrgah'], df_data_cal['time'], split_len)
  365. pkvlt_splt_temp = dats_interp(df_data_cal['chrgah'], df_data_cal['pack_volt'], split_len)
  366. pkvlt_splt = svflter(pkvlt_splt_temp, para_lvbo, 3)
  367. vlt_splce = svflter(vlt_splce_temp, para_lvbo, 3)
  368. np_dff_vlt = np.diff(vlt_splce)
  369. np_dff_cap = np.diff(cap_frst)
  370. np_dff_dv_dq_temp = np.divide(np_dff_vlt, np_dff_cap)
  371. np_dff_dv_dq = np.insert(np_dff_dv_dq_temp, 0, np_dff_dv_dq_temp[0])
  372. df_dvdq_data = pd.DataFrame()
  373. df_dvdq_data['pack_soc'] = soc_splt
  374. df_dvdq_data['pack_crnt'] = crnt_splt
  375. df_dvdq_data['frst'] = vlt_splce
  376. df_dvdq_data['max_T'] = maxt_splt
  377. df_dvdq_data['min_T'] = mint_splt
  378. df_dvdq_data['odo'] = odo_splt
  379. df_dvdq_data['chrgah'] = cap_frst
  380. df_dvdq_data['pack_volt'] = pkvlt_splt
  381. df_dvdq_data['time'] = pd.to_datetime(time_splt)#, utc=True, unit='ms').tz_convert('Asia/Shanghai')
  382. df_dvdq_data['dffsoc'] = df_dvdq_data['pack_soc'].diff()
  383. df_dvdq_data['dffah'] = df_dvdq_data['chrgah'].diff()
  384. df_dvdq_data['dv_dq'] = np_dff_dv_dq
  385. df_dvdq_data['fr_vlt_dvdq'] = vlt_splce#电压
  386. df_dvdq_data.fillna(method = 'bfill', inplace = True , axis = 0)
  387. delta_soc = df_dvdq_data['pack_soc'].iloc[-1] - df_dvdq_data['pack_soc'].iloc[0]
  388. if all(df_dvdq_data['dffsoc'] < 3) and delta_soc > 10:
  389. df_dvdq_data['df_dq_lvb'] = svflter(df_dvdq_data['dv_dq'], para_lvbo, 3, mode = 'nearest')#
  390. df_data = df_dvdq_data.copy()#loc[(df_dataana['pack_soc'] > 30) & (df_dataana['pack_soc'] < 70)]
  391. df_data.reset_index(drop = True, inplace = True)
  392. dvsocchrcter = []
  393. if len(df_data) > 10:
  394. cellvltname = ['fr_vlt_dvdq']#, 'send', 'thrd'
  395. cellvltahname = ['df_dq_lvb']#, 'dffsendvlt', 'dffthdvlt'
  396. maxsoc = 0
  397. for itemnum in range(0, 1):
  398. snchrcter = []
  399. np_vlt_ori = np.array(df_data[cellvltahname[itemnum]])#dffminvlt
  400. np_vltori_smth = svflter(np_vlt_ori, para_lvbo, 3)
  401. rcoumax, peak_indexmax, rcoumin, peak_indexmin = peakbotm.find_peak_triangleNum(np_vltori_smth, 7)#, rcoumin, peak_indexmin
  402. if (len(peak_indexmax) > 0) and (len(peak_indexmin) > 0):
  403. peak_fst = np_vltori_smth[peak_indexmax[0]]
  404. botm_fst = np_vltori_smth[peak_indexmin[0]]
  405. pkbtmratfst = botm_fst/peak_fst
  406. else:
  407. peak_fst = -1
  408. if (peak_fst>0):#and (botm_fst>0) and (abs(pkbtmratfst) >= 0.2) and (abs(pkbtmratfst) <= 0.8)
  409. maxindex = peak_indexmax[0]
  410. maxsoc = np.array(df_data['pack_soc'])[maxindex]
  411. snchrcter.append(itemsn)
  412. snchrcter.append(np.array(df_data['time'])[maxindex])#df_data.loc[0, 'time']
  413. snchrcter.append(np.array(df_data[cellvltname[itemnum]])[maxindex])#电压
  414. snchrcter.append(maxsoc)
  415. snchrcter.append(pkbtmratfst)
  416. snchrcter.append(np.array(df_data['max_T'])[maxindex])#最大电芯温度
  417. snchrcter.append(np.array(df_data['min_T'])[maxindex])#最大电芯温度
  418. snchrcter.append(round(np.array(df_data['pack_crnt'])[maxindex]/self.capty, 3))#倍率
  419. snchrcter.append(df_data['odo'].iloc[0])#里程
  420. snchrcter.append(np.array(df_data['pack_volt'])[maxindex])#里程
  421. dvsocchrcter.append(snchrcter)
  422. df_chracter_ofc= pd.DataFrame(dvsocchrcter)#各电芯的电压微分特征值
  423. peak_pos = abs(maxsoc - df_dvdq_data['pack_soc'].iloc[0])
  424. if (not df_chracter_ofc.empty) and (peak_pos > 3):
  425. setcolumns = ['sn', 'time', 'frstvlt', 'soc_ori', 'pkbtmfst', 'frstmaxT', 'frstminT', 'rate', 'odo', 'pack_vlt']
  426. df_chracter_ofc.columns = setcolumns
  427. df_chracter_ofc['rate'] = np.abs(df_chracter_ofc['rate'])
  428. else:
  429. df_chracter_ofc = pd.DataFrame()
  430. if (not df_chracter_ofc.empty):
  431. DataArray = df_chracter_ofc.values
  432. Y = DataArray[:, 3]#SOC值
  433. X = DataArray[:, [2,5,6,7,8,9]] #电压、峰谷比,温度,rate,odo4,
  434. X = np.array(X)#转化为array,自变量
  435. Y = np.array(Y)#转化为array,因变量soc
  436. paraminput_x = self.inputnorm_x.fit_transform(X)
  437. Soc_ori = np.array(Y)
  438. SOC_pre_dnn_ori = self.Dnn_predict.predict(paraminput_x)
  439. SOC_pre = self.inputnorm_y.inverse_transform(SOC_pre_dnn_ori.reshape(-1, 1)).reshape(-1)
  440. SOC_error = (SOC_pre - Soc_ori)
  441. SOC_error_abs = abs(SOC_error)
  442. # if max(SOC_error_abs) > 5:
  443. df_chracter_ofc['soc_pre'] = SOC_pre
  444. df_chracter_ofc['soc_error'] = SOC_error.astype('float')
  445. df_chracter_ofc['soc_pre'] = df_chracter_ofc['soc_pre'].round(3)
  446. df_chracter_ofc['soc_error'] = df_chracter_ofc['soc_error'].round(3)
  447. df_soc_rlt = df_chracter_ofc[(df_chracter_ofc['soc_pre'] < 60) & (df_chracter_ofc['soc_pre'] > 35) &
  448. (df_chracter_ofc['soc_ori'] < 60) & (df_chracter_ofc['soc_ori'] > 35)]
  449. df_soc_rlt.reset_index(drop = True, inplace = True)
  450. if not df_soc_rlt.empty:
  451. SOC_rlt = df_soc_rlt[['sn', 'time', 'soc_ori', 'soc_pre', 'soc_error', 'frstvlt', 'pkbtmfst', 'frstmaxT',
  452. 'frstminT', 'rate', 'odo']]
  453. SOC_rlt['soc_pre'] = SOC_rlt['soc_pre'].round(1)
  454. SOC_rlt['soc_error'] = SOC_rlt['soc_error'].round(1)
  455. # SOC_clms = ['frstsoc', 'SOC_pre', 'SOC_error', 'frstvlt', 'pkbtmfst', 'frstmaxT', 'frstminT', 'rate']
  456. # df_cellname = SOC_rlt.groupby(['time'])['cellname'].apply(list)
  457. # cellname = df_cellname.values[0]
  458. # namenum = 'cellnum:' + str(list(map(int, [i[12:] for i in cellname])))
  459. # SOC_rltlst = []
  460. # SOC_rltlst.append(self.sn)
  461. # SOC_rltlst.append(namenum)
  462. # SOC_rltlst.append(SOC_rlt['time'].iloc[0])
  463. # for itemsoc in SOC_clms:
  464. # df_cellname = SOC_rlt.groupby(['time'])[itemsoc].apply(list)
  465. # cellname = df_cellname.values[0]
  466. # SOC_rltlst.append(str(cellname))
  467. # SOC_rltlst.append(SOC_rlt['odo'].iloc[0])
  468. # SOC_rlt_final = pd.DataFrame(SOC_rltlst).T
  469. # SOC_rlt_final.columns = ['sn', 'cellname', 'time', 'soc_ori', 'soc_pre', 'soc_error', 'frstvlt', 'pkbtmfst', 'frstmaxT', 'frstminT', 'rate', 'odo']
  470. SOC_pre_cal_dnn = SOC_rlt[['sn', 'time', 'soc_ori', 'soc_pre', 'soc_error', 'odo']]
  471. SOC_pre_cal_dnn['method'] = 1
  472. df_soc_rlt_con = pd.concat([SOC_pre_cal, SOC_pre_cal_dnn])
  473. df_soc_rlt_con.reset_index(drop = True, inplace = True)
  474. if not df_soc_rlt_con.empty:
  475. df_soc_rlt_con['battery_type'] = 'lfp'
  476. soc_pre_method = list(df_soc_rlt_con['method'])
  477. if 3 in soc_pre_method:
  478. SOC_out = df_soc_rlt_con[(df_soc_rlt_con['method'] == 3)]
  479. elif 2 in soc_pre_method:
  480. SOC_out = df_soc_rlt_con[(df_soc_rlt_con['method'] == 2)]
  481. elif 1 in soc_pre_method:
  482. SOC_out = df_soc_rlt_con[(df_soc_rlt_con['method'] == 1)]
  483. else:
  484. SOC_out = pd.DataFrame()
  485. else:
  486. SOC_out = pd.DataFrame()
  487. return SOC_out #SOC_rlt_final, SOH_rlt_final
  488. # SOC_rlt = pd.DataFrame(columns = ['sn', 'time', 'soc_ori', 'soc_pre', 'soc_error', 'odo', 'method', 'battery_type'])
  489. df_data = self.df_bms.copy()
  490. df_data = df_data.loc[:, ~df_data.columns.duplicated()]
  491. if max(self.LookTab_OCV) > 4:
  492. SOC_rlt = soc_cal_ncm(df_data)#df_data.groupby('sn').apply(soc_cal_ncm)
  493. else:
  494. SOC_rlt = soc_cal_lfp(df_data)#df_data.groupby('sn').apply(soc_cal_lfp)
  495. if not SOC_rlt.empty:
  496. SOC_rlt.rename(columns={"soc_ori":"soc", "soc_pre":"soc_real", "soc_error":"soc_delta"}, inplace = True)
  497. SOC_rlt.drop(columns=['battery_type'], inplace = True)
  498. fillna = len(SOC_rlt)*[np.nan]
  499. SOC_rlt['soc_max'] = fillna
  500. SOC_rlt['soc_min'] = fillna
  501. SOC_rlt['cell_soc_delta'] = fillna
  502. return SOC_rlt
  503. else:
  504. return pd.DataFrame(columns = ['sn', 'time', 'soc_max', 'soc_min', 'soc', 'soc_real', 'soc_delta',
  505. 'odo', 'method', 'cell_soc_delta'])