mileage.py 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. import pandas as pd
  2. import numpy as np
  3. from LIB.BACKEND.DataPreProcess import DataPreProcess
  4. import os
  5. import math
  6. import datetime
  7. import time
  8. def cal_mileage(sn,data_gps,data_bms):
  9. #将时间戳由 "%Y-%m-%d %H:%M:%S" 切换为 sec
  10. def timeconvert(df_in,column_name):
  11. df=df_in.copy()
  12. df.index=range(len(df))
  13. time=df[column_name]
  14. timeInSeries=[]
  15. time2=datetime.datetime.strptime(time[0],"%Y-%m-%d %H:%M:%S")
  16. for k in range(len(time)):
  17. time1=datetime.datetime.strptime(time[k],"%Y-%m-%d %H:%M:%S")
  18. t=(time1-time2)
  19. timeInSeries.append(t.days*86400+t.seconds)
  20. df.loc[:,'相对时间[s]']=pd.DataFrame(timeInSeries,columns=['相对时间[s]'])
  21. return df
  22. data_bms=timeconvert(data_bms,'时间戳')
  23. #计算累积能量
  24. def cal_accumKwh(df_in):
  25. I=df_in['总电流[A]'].values
  26. V=df_in['总电压[V]'].values
  27. t=df_in['相对时间[s]'].values
  28. accumAh=[0.0]
  29. for k in range(1,len(I)):
  30. accumAh_temp=(t[k]-t[k-1])*((I[k]+I[k-1])/(2*3600))*(V[k]+V[k-1])/2/1000
  31. accumAh.append(accumAh[-1]+accumAh_temp)
  32. df_in.loc[:,'累积能量[Kwh]']=accumAh
  33. return(df_in)
  34. data_bms=cal_accumKwh(data_bms)
  35. #合并两张表格
  36. df_bms=data_bms.copy()
  37. df_gps=data_gps.copy()
  38. df_bms.set_index(["时间戳"], inplace=True)
  39. df_gps.set_index(["时间戳"], inplace=True)
  40. df_temp = df_bms.append(df_gps)
  41. df_temp=df_temp.sort_index(ascending=True)
  42. df_temp.loc[:,'时间']=df_temp.index
  43. df_temp.index=[k for k in range(len(df_temp))]
  44. df_sheetCat=df_temp.copy()
  45. df_sheetCat=timeconvert(df_sheetCat,'时间')
  46. df_sheetCat=df_sheetCat.rename(columns={'时间':'时间戳'})
  47. df_sheetCat=DataPreProcess.data_split_by_status(DataPreProcess,df_sheetCat, drive_interval_threshold=120, charge_interval_threshold=300, drive_stand_threshold=120, charge_stand_threshold=300)
  48. #数据整理
  49. df1=df_sheetCat.copy()
  50. #如果前后data_status均不为none,但是本次为none,则将本次data_status设置为与上次相同。
  51. data_status=df1['data_status'].values
  52. for k in range(1,len(data_status)-1):
  53. if data_status[k-1]!='none' and data_status[k+1]!='none':
  54. df1.loc[k,'data_status']=data_status[k-1]
  55. #如果前后两次电流值均不为nan,则将总电流[A]、总电压[V]、SOC[%]设置为与前次相同。
  56. data_current=df1['总电流[A]'].values
  57. for k in range(1,len(data_current)-1):
  58. if not math.isnan(data_current[k-1]) and not math.isnan(data_current[k+1]) and math.isnan(data_current[k]):
  59. df1.loc[k,'总电流[A]']=df1.loc[k-1,'总电流[A]']
  60. df1.loc[k,'总电压[V]']=df1.loc[k-1,'总电压[V]']
  61. df1.loc[k,'SOC[%]']=df1.loc[k-1,'SOC[%]']
  62. #如果前后两次能量均不是NAN,但是本次为NAN,则将上次的能量指赋值给本次
  63. AccumEnergy=df1['累积能量[Kwh]'].values
  64. for k in range(1,len(AccumEnergy)-1):
  65. if not math.isnan(AccumEnergy[k-1]) and not math.isnan(AccumEnergy[k+1]) and math.isnan(AccumEnergy[k]):
  66. df1.loc[k,'累积能量[Kwh]']=AccumEnergy[k-1]
  67. #删除一些无用列,获取用于计算的数据
  68. df_input=df1[['时间戳','总电流[A]', '总电压[V]','SOC[%]','相对时间[s]', '累积能量[Kwh]','纬度', '经度','data_status']]
  69. #筛选出有经纬度信息的数据
  70. df_gpsOnly=df_input[df_input['纬度']>0]
  71. #根据经纬度获取两点之间的距离
  72. def cal_dis_meters(radius,latitude1, longitude1,latitude2, longitude2):
  73. radLat1 = (math.pi/180)*latitude1
  74. radLat2 = (math.pi/180)*latitude2
  75. radLng1 = (math.pi/180)*longitude1
  76. radLng2= (math.pi/180)*longitude2
  77. d=2*math.asin(math.sqrt(math.pow(math.sin((radLat1-radLat2)/2.0),2)+math.cos(radLat1)*math.cos(radLat2)*math.pow(math.sin((radLng1-radLng2)/2.0),2)))*radius
  78. return d
  79. #根据gps数据计算△距离1和△距离2
  80. #△距离1:直接根据两次的经度和纬度计算得到的马氏距离
  81. #△距离2:当两次上报经纬度的时间间隔<60sec时,如果车辆为行驶状态则使用两次的经纬度求得的马氏距离,
  82. #如果车辆不为行驶状态,则为0.
  83. index_list=df_gpsOnly.index
  84. pos_list=df_gpsOnly[['纬度','经度']].values
  85. time_list=df_input['相对时间[s]'].values
  86. Energy_list=df_input['累积能量[Kwh]'].values
  87. for k in range(1,len(pos_list)):
  88. latitude1=pos_list[k-1][0]
  89. longitude1=pos_list[k-1][1]
  90. latitude2=pos_list[k][0]
  91. longitude2=pos_list[k][1]
  92. dlt_odo=cal_dis_meters(6378.137,latitude1, longitude1,latitude2, longitude2)
  93. df_gpsOnly.loc[index_list[k],'△距离1']=dlt_odo
  94. if time_list[index_list[k]]-time_list[index_list[k-1]]<60:#两次上传GPS数据时间间隔小于60sec
  95. if df_gpsOnly.loc[index_list[k],'data_status']=='drive' :
  96. df_gpsOnly.loc[index_list[k],'△距离2']=dlt_odo
  97. elif df_gpsOnly.loc[index_list[k],'data_status']=='none' :
  98. df_gpsOnly.loc[index_list[k],'△距离2']=dlt_odo
  99. else:
  100. df_gpsOnly.loc[index_list[k],'△距离2']=0
  101. #如果某一段数据中有gps数据但是没有bms数据,里程按照gps数据计算,但是到有gps数据之后,发现累积能量变化不大于0,因此需要将这期间的里程均设置为0km
  102. df_gpsOnly_copy=df_gpsOnly.copy()
  103. df_gpsOnly_copy.index=[i for i in range(len(df_gpsOnly))]
  104. df_bmsOnly=df_gpsOnly_copy[df_gpsOnly_copy['总电压[V]']>0]
  105. energy2=df_bmsOnly['累积能量[Kwh]'].values
  106. df_bmsOnly_index=df_bmsOnly.index.values
  107. for k in range(1,len(df_bmsOnly)):
  108. if not (energy2[k]-energy2[k-1]>0):
  109. for n in range(df_bmsOnly_index[k-1],df_bmsOnly_index[k]+1):
  110. df_gpsOnly_copy.loc[n,'△距离2']=0
  111. dis2=df_gpsOnly_copy['△距离2'].values
  112. relatedTime=df_gpsOnly_copy['相对时间[s]'].values
  113. nan_flag=0
  114. for k in range(1,len(dis2)):
  115. if math.isnan(dis2[k]) and (not math.isnan(dis2[k-1])): #本次△距离2为NAN但是上次不为NAN
  116. nan_flag=1
  117. ###平均能耗计算
  118. st_time=relatedTime[k]-600 #10min之前的时刻点
  119. df2=df_gpsOnly_copy[df_gpsOnly_copy['相对时间[s]']>=st_time]
  120. df_temp2=df2[df2['相对时间[s]']<=relatedTime[k]]
  121. df_temp2=df_temp2[['相对时间[s]','累积能量[Kwh]','△距离2']]
  122. df_temp3=df_temp2.dropna(axis=0,how='any')
  123. if len(df_temp3)>5:
  124. # st_time=relatedTime[k-1]-600 #10min之前的时刻点
  125. # df2=df_gpsOnly_copy[df_gpsOnly_copy['相对时间[s]']>=st_time]
  126. # df_temp2=df2[df2['相对时间[s]']<=relatedTime[k]]
  127. energy=df_temp3['累积能量[Kwh]'].values
  128. dis_temp=df_temp3['△距离2'].values
  129. # dis_temp_delet_nan=dis_temp[np.logical_not(np.isnan(dis_temp))]
  130. df_gpsOnly_copy.loc[k,'△能量[Kwh]']=energy[-1]-energy[0]
  131. df_gpsOnly_copy.loc[k,'累积距离[km]']=dis_temp[1:-1].sum()
  132. if energy[-1]-energy[0]>0:
  133. df_gpsOnly_copy.loc[k,'能耗[km/kwh]']=min(max(df_gpsOnly_copy.loc[k,'累积距离[km]']/df_gpsOnly_copy.loc[k,'△能量[Kwh]'],25),50)
  134. else:
  135. if dis_temp[1:-1].sum()>0:
  136. df_gpsOnly_copy.loc[k,'能耗[km/kwh]']=30
  137. else:
  138. df_gpsOnly_copy.loc[k,'能耗[km/kwh]']=0
  139. else:
  140. df_temp2=df_gpsOnly_copy[df_gpsOnly_copy['相对时间[s]']<=relatedTime[k]]
  141. df_energyPerKm=df_gpsOnly_copy[df_gpsOnly_copy['能耗[km/kwh]']>0]
  142. df_energyPerKm.index=[i for i in range(len(df_energyPerKm))]
  143. total_num=len(df_energyPerKm)
  144. #统计最近10次的平均能耗,用于补充dis2前后都为nan时刻处的能耗及距离,
  145. ##如果不足10次按照实际次数统计
  146. if total_num>10:
  147. energycost_acc=0
  148. for i in range(10):
  149. energycost_acc=energycost_acc+df_energyPerKm.loc[total_num-i-1,'能耗[km/kwh]']
  150. avg_energyCost=min(max(energycost_acc/10,25),50)
  151. df_gpsOnly_copy.loc[k,'△能量[Kwh]']=1
  152. df_gpsOnly_copy.loc[k,'累积距离[km]']=avg_energyCost
  153. df_gpsOnly_copy.loc[k,'能耗[km/kwh]']=avg_energyCost
  154. elif total_num>0:
  155. avg_energyCost=min(max(df_energyPerKm['能耗[km/kwh]'].values.mean(),25),50)
  156. df_gpsOnly_copy.loc[k,'△能量[Kwh]']=1
  157. df_gpsOnly_copy.loc[k,'累积距离[km]']=avg_energyCost
  158. df_gpsOnly_copy.loc[k,'能耗[km/kwh]']=avg_energyCost
  159. else:
  160. df_gpsOnly_copy.loc[k,'△能量[Kwh]']=df_gpsOnly_copy.loc[k-1,'△能量[Kwh]']
  161. df_gpsOnly_copy.loc[k,'累积距离[km]']=df_gpsOnly_copy.loc[k-1,'累积距离[km]']
  162. df_gpsOnly_copy.loc[k,'能耗[km/kwh]']=df_gpsOnly_copy.loc[k-1,'能耗[km/kwh]']
  163. ####行驶里程估计
  164. energy1=df_temp2['累积能量[Kwh]'].values
  165. if energy1[-1]-energy1[-2]>0:
  166. gps_dis=df_gpsOnly_copy.loc[k,'△距离1']
  167. delta_t=df_gpsOnly_copy.loc[k,'相对时间[s]']-df_gpsOnly_copy.loc[k-1,'相对时间[s]']
  168. vehspd=gps_dis*3600/delta_t
  169. if vehspd>30:
  170. df_gpsOnly_copy.loc[k,'△距离3[km]']=(energy1[-1]-energy1[-2])*df_gpsOnly_copy.loc[k,'能耗[km/kwh]']
  171. else:
  172. df_gpsOnly_copy.loc[k,'△距离3[km]']=max((energy1[-1]-energy1[-2])*df_gpsOnly_copy.loc[k,'能耗[km/kwh]'],gps_dis)
  173. else:
  174. df_gpsOnly_copy.loc[k,'△距离3[km]']=0
  175. df_gpsOnly_copy.loc[k,'△距离2']=df_gpsOnly_copy.loc[k,'△距离3[km]']
  176. elif math.isnan(dis2[k]) and (math.isnan(dis2[k-1])) and nan_flag==1: #本次△距离为NAN上次也为NAN
  177. df_energyPerKm=df_gpsOnly_copy[df_gpsOnly_copy['能耗[km/kwh]']>0]
  178. df_energyPerKm.index=[i for i in range(len(df_energyPerKm))]
  179. total_num=len(df_energyPerKm)
  180. #统计最近10次的平均能耗,用于补充dis2前后都为nan时刻处的能耗及距离,
  181. ##如果不足10次按照实际次数统计
  182. if total_num>10:
  183. energycost_acc=0
  184. for i in range(10):
  185. energycost_acc=energycost_acc+df_energyPerKm.loc[total_num-i-1,'能耗[km/kwh]']
  186. avg_energyCost=min(max(energycost_acc/10,25),50)
  187. df_gpsOnly_copy.loc[k,'△能量[Kwh]']=1
  188. df_gpsOnly_copy.loc[k,'累积距离[km]']=avg_energyCost
  189. df_gpsOnly_copy.loc[k,'能耗[km/kwh]']=avg_energyCost
  190. elif total_num>0:
  191. avg_energyCost=min(max(df_energyPerKm['能耗[km/kwh]'].values.mean(),25),50)
  192. df_gpsOnly_copy.loc[k,'△能量[Kwh]']=1
  193. df_gpsOnly_copy.loc[k,'累积距离[km]']=avg_energyCost
  194. df_gpsOnly_copy.loc[k,'能耗[km/kwh]']=avg_energyCost
  195. else:
  196. df_gpsOnly_copy.loc[k,'△能量[Kwh]']=df_gpsOnly_copy.loc[k-1,'△能量[Kwh]']
  197. df_gpsOnly_copy.loc[k,'累积距离[km]']=df_gpsOnly_copy.loc[k-1,'累积距离[km]']
  198. df_gpsOnly_copy.loc[k,'能耗[km/kwh]']=df_gpsOnly_copy.loc[k-1,'能耗[km/kwh]']
  199. ##计算行驶里程
  200. delta_energy=df_gpsOnly_copy.loc[k,'累积能量[Kwh]']-df_gpsOnly_copy.loc[k-1,'累积能量[Kwh]']
  201. if delta_energy>0:
  202. gps_dis=df_gpsOnly_copy.loc[k,'△距离1']
  203. delta_t=df_gpsOnly_copy.loc[k,'相对时间[s]']-df_gpsOnly_copy.loc[k-1,'相对时间[s]']
  204. vehspd=gps_dis*3600/delta_t
  205. if vehspd>30:
  206. df_gpsOnly_copy.loc[k,'△距离3[km]']=delta_energy*df_gpsOnly_copy.loc[k,'累积距离[km]']/df_gpsOnly_copy.loc[k,'△能量[Kwh]']
  207. else:
  208. df_gpsOnly_copy.loc[k,'△距离3[km]']=max(delta_energy*df_gpsOnly_copy.loc[k,'累积距离[km]']/df_gpsOnly_copy.loc[k,'△能量[Kwh]'],gps_dis)
  209. else:
  210. df_gpsOnly_copy.loc[k,'△距离3[km]']=0
  211. df_gpsOnly_copy.loc[k,'△距离2']=df_gpsOnly_copy.loc[k,'△距离3[km]']
  212. else:
  213. df_gpsOnly_copy.loc[k,'△能量[Kwh]']=1
  214. df_gpsOnly_copy.loc[k,'累积距离[km]']=25
  215. df_gpsOnly_copy.loc[k,'能耗[km/kwh]']=25
  216. df_gpsOnly_copy.loc[k,'△距离3[km]']=df_gpsOnly_copy.loc[k,'△距离2']
  217. ###############输出计算结果##################
  218. ############################################
  219. df_gpsOnly_copy.loc[0,'累积里程[km]']=0
  220. df_gpsOnly_copy.loc[0,'日期']=str(df_gpsOnly_copy.loc[0,'时间戳'])[0:10]
  221. for k in range(1,len(df_gpsOnly_copy)):
  222. df_dis_temp=df_gpsOnly_copy['△距离3[km]'].values[0:k+1]
  223. df_dis_temp1=df_dis_temp[np.logical_not(np.isnan(df_dis_temp))]
  224. if len(df_dis_temp1)>0:
  225. df_gpsOnly_copy.loc[k,'累积里程[km]']=df_dis_temp1.sum()
  226. else:
  227. df_gpsOnly_copy.loc[k,'累积里程[km]']=df_gpsOnly_copy.loc[k-1,'累积里程[km]']
  228. df_gpsOnly_copy.loc[k,'日期']=str(df_gpsOnly_copy.loc[k,'时间戳'])[0:10]
  229. datetime1=np.unique(df_gpsOnly_copy['日期'].values)
  230. df_result=pd.DataFrame(index=datetime1)
  231. list_result=[]
  232. list_day_odo=[]
  233. for k in range(len(datetime1)):
  234. df_day=df_gpsOnly_copy[df_gpsOnly_copy['日期']==datetime1[k]]
  235. odo_day=df_day['累积里程[km]'].values
  236. df_result.loc[datetime1[k],'累积里程[km]']=odo_day[-1]-odo_day[0]
  237. df_day['累积里程[km]']=odo_day-odo_day[0]
  238. list_day_odo.extend(odo_day-odo_day[0])
  239. list_result.append([datetime1[k],df_day])
  240. df_gpsOnly_copy.loc[:,'每日累积里程[km]']=list_day_odo
  241. #删除一些无用列,获取用于计算的数据
  242. df_output=df_gpsOnly_copy[['时间戳','data_status','SOC[%]','每日累积里程[km]']]
  243. #添加sn
  244. df_output['sn'] = sn
  245. return df_output