123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277 |
- import pandas as pd
- import numpy as np
- from LIB.BACKEND.DataPreProcess import DataPreProcess
- import os
- import math
- import datetime
- import time
- def cal_mileage(sn,data_gps,data_bms):
-
- #将时间戳由 "%Y-%m-%d %H:%M:%S" 切换为 sec
- def timeconvert(df_in,column_name):
- df=df_in.copy()
- df.index=range(len(df))
- time=df[column_name]
- timeInSeries=[]
-
- time2=datetime.datetime.strptime(time[0],"%Y-%m-%d %H:%M:%S")
- for k in range(len(time)):
- time1=datetime.datetime.strptime(time[k],"%Y-%m-%d %H:%M:%S")
- t=(time1-time2)
- timeInSeries.append(t.days*86400+t.seconds)
- df.loc[:,'相对时间[s]']=pd.DataFrame(timeInSeries,columns=['相对时间[s]'])
- return df
- data_bms=timeconvert(data_bms,'时间戳')
- #计算累积能量
- def cal_accumKwh(df_in):
- I=df_in['总电流[A]'].values
- V=df_in['总电压[V]'].values
- t=df_in['相对时间[s]'].values
- accumAh=[0.0]
- for k in range(1,len(I)):
- accumAh_temp=(t[k]-t[k-1])*((I[k]+I[k-1])/(2*3600))*(V[k]+V[k-1])/2/1000
- accumAh.append(accumAh[-1]+accumAh_temp)
- df_in.loc[:,'累积能量[Kwh]']=accumAh
- return(df_in)
- data_bms=cal_accumKwh(data_bms)
- #合并两张表格
- df_bms=data_bms.copy()
- df_gps=data_gps.copy()
- df_bms.set_index(["时间戳"], inplace=True)
- df_gps.set_index(["时间戳"], inplace=True)
- df_temp = df_bms.append(df_gps)
- df_temp=df_temp.sort_index(ascending=True)
- df_temp.loc[:,'时间']=df_temp.index
- df_temp.index=[k for k in range(len(df_temp))]
- df_sheetCat=df_temp.copy()
- df_sheetCat=timeconvert(df_sheetCat,'时间')
- df_sheetCat=df_sheetCat.rename(columns={'时间':'时间戳'})
- 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)
- #数据整理
- df1=df_sheetCat.copy()
- #如果前后data_status均不为none,但是本次为none,则将本次data_status设置为与上次相同。
- data_status=df1['data_status'].values
- for k in range(1,len(data_status)-1):
- if data_status[k-1]!='none' and data_status[k+1]!='none':
- df1.loc[k,'data_status']=data_status[k-1]
- #如果前后两次电流值均不为nan,则将总电流[A]、总电压[V]、SOC[%]设置为与前次相同。
- data_current=df1['总电流[A]'].values
- for k in range(1,len(data_current)-1):
- if not math.isnan(data_current[k-1]) and not math.isnan(data_current[k+1]) and math.isnan(data_current[k]):
- df1.loc[k,'总电流[A]']=df1.loc[k-1,'总电流[A]']
- df1.loc[k,'总电压[V]']=df1.loc[k-1,'总电压[V]']
- df1.loc[k,'SOC[%]']=df1.loc[k-1,'SOC[%]']
- #如果前后两次能量均不是NAN,但是本次为NAN,则将上次的能量指赋值给本次
- AccumEnergy=df1['累积能量[Kwh]'].values
- for k in range(1,len(AccumEnergy)-1):
- if not math.isnan(AccumEnergy[k-1]) and not math.isnan(AccumEnergy[k+1]) and math.isnan(AccumEnergy[k]):
- df1.loc[k,'累积能量[Kwh]']=AccumEnergy[k-1]
- #删除一些无用列,获取用于计算的数据
- df_input=df1[['时间戳','总电流[A]', '总电压[V]','SOC[%]','相对时间[s]', '累积能量[Kwh]','纬度', '经度','data_status']]
- #筛选出有经纬度信息的数据
- df_gpsOnly=df_input[df_input['纬度']>0]
- #根据经纬度获取两点之间的距离
- def cal_dis_meters(radius,latitude1, longitude1,latitude2, longitude2):
- radLat1 = (math.pi/180)*latitude1
- radLat2 = (math.pi/180)*latitude2
- radLng1 = (math.pi/180)*longitude1
- radLng2= (math.pi/180)*longitude2
- 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
- return d
- #根据gps数据计算△距离1和△距离2
- #△距离1:直接根据两次的经度和纬度计算得到的马氏距离
- #△距离2:当两次上报经纬度的时间间隔<60sec时,如果车辆为行驶状态则使用两次的经纬度求得的马氏距离,
- #如果车辆不为行驶状态,则为0.
- index_list=df_gpsOnly.index
- pos_list=df_gpsOnly[['纬度','经度']].values
- time_list=df_input['相对时间[s]'].values
- Energy_list=df_input['累积能量[Kwh]'].values
- for k in range(1,len(pos_list)):
- latitude1=pos_list[k-1][0]
- longitude1=pos_list[k-1][1]
- latitude2=pos_list[k][0]
- longitude2=pos_list[k][1]
- dlt_odo=cal_dis_meters(6378.137,latitude1, longitude1,latitude2, longitude2)
- df_gpsOnly.loc[index_list[k],'△距离1']=dlt_odo
- if time_list[index_list[k]]-time_list[index_list[k-1]]<60:#两次上传GPS数据时间间隔小于60sec
- if df_gpsOnly.loc[index_list[k],'data_status']=='drive' :
- df_gpsOnly.loc[index_list[k],'△距离2']=dlt_odo
- elif df_gpsOnly.loc[index_list[k],'data_status']=='none' :
- df_gpsOnly.loc[index_list[k],'△距离2']=dlt_odo
- else:
- df_gpsOnly.loc[index_list[k],'△距离2']=0
- #如果某一段数据中有gps数据但是没有bms数据,里程按照gps数据计算,但是到有gps数据之后,发现累积能量变化不大于0,因此需要将这期间的里程均设置为0km
- df_gpsOnly_copy=df_gpsOnly.copy()
- df_gpsOnly_copy.index=[i for i in range(len(df_gpsOnly))]
- df_bmsOnly=df_gpsOnly_copy[df_gpsOnly_copy['总电压[V]']>0]
- energy2=df_bmsOnly['累积能量[Kwh]'].values
- df_bmsOnly_index=df_bmsOnly.index.values
- for k in range(1,len(df_bmsOnly)):
- if not (energy2[k]-energy2[k-1]>0):
- for n in range(df_bmsOnly_index[k-1],df_bmsOnly_index[k]+1):
- df_gpsOnly_copy.loc[n,'△距离2']=0
- dis2=df_gpsOnly_copy['△距离2'].values
- relatedTime=df_gpsOnly_copy['相对时间[s]'].values
- nan_flag=0
- for k in range(1,len(dis2)):
- if math.isnan(dis2[k]) and (not math.isnan(dis2[k-1])): #本次△距离2为NAN但是上次不为NAN
- nan_flag=1
- ###平均能耗计算
- st_time=relatedTime[k]-600 #10min之前的时刻点
- df2=df_gpsOnly_copy[df_gpsOnly_copy['相对时间[s]']>=st_time]
- df_temp2=df2[df2['相对时间[s]']<=relatedTime[k]]
- df_temp2=df_temp2[['相对时间[s]','累积能量[Kwh]','△距离2']]
- df_temp3=df_temp2.dropna(axis=0,how='any')
- if len(df_temp3)>5:
- # st_time=relatedTime[k-1]-600 #10min之前的时刻点
- # df2=df_gpsOnly_copy[df_gpsOnly_copy['相对时间[s]']>=st_time]
- # df_temp2=df2[df2['相对时间[s]']<=relatedTime[k]]
-
- energy=df_temp3['累积能量[Kwh]'].values
- dis_temp=df_temp3['△距离2'].values
- # dis_temp_delet_nan=dis_temp[np.logical_not(np.isnan(dis_temp))]
- df_gpsOnly_copy.loc[k,'△能量[Kwh]']=energy[-1]-energy[0]
- df_gpsOnly_copy.loc[k,'累积距离[km]']=dis_temp[1:-1].sum()
- if energy[-1]-energy[0]>0:
- df_gpsOnly_copy.loc[k,'能耗[km/kwh]']=min(max(df_gpsOnly_copy.loc[k,'累积距离[km]']/df_gpsOnly_copy.loc[k,'△能量[Kwh]'],25),50)
- else:
- if dis_temp[1:-1].sum()>0:
- df_gpsOnly_copy.loc[k,'能耗[km/kwh]']=30
- else:
- df_gpsOnly_copy.loc[k,'能耗[km/kwh]']=0
- else:
- df_temp2=df_gpsOnly_copy[df_gpsOnly_copy['相对时间[s]']<=relatedTime[k]]
- df_energyPerKm=df_gpsOnly_copy[df_gpsOnly_copy['能耗[km/kwh]']>0]
- df_energyPerKm.index=[i for i in range(len(df_energyPerKm))]
- total_num=len(df_energyPerKm)
- #统计最近10次的平均能耗,用于补充dis2前后都为nan时刻处的能耗及距离,
- ##如果不足10次按照实际次数统计
- if total_num>10:
- energycost_acc=0
- for i in range(10):
- energycost_acc=energycost_acc+df_energyPerKm.loc[total_num-i-1,'能耗[km/kwh]']
- avg_energyCost=min(max(energycost_acc/10,25),50)
- df_gpsOnly_copy.loc[k,'△能量[Kwh]']=1
- df_gpsOnly_copy.loc[k,'累积距离[km]']=avg_energyCost
- df_gpsOnly_copy.loc[k,'能耗[km/kwh]']=avg_energyCost
- elif total_num>0:
- avg_energyCost=min(max(df_energyPerKm['能耗[km/kwh]'].values.mean(),25),50)
- df_gpsOnly_copy.loc[k,'△能量[Kwh]']=1
- df_gpsOnly_copy.loc[k,'累积距离[km]']=avg_energyCost
- df_gpsOnly_copy.loc[k,'能耗[km/kwh]']=avg_energyCost
- else:
- df_gpsOnly_copy.loc[k,'△能量[Kwh]']=df_gpsOnly_copy.loc[k-1,'△能量[Kwh]']
- df_gpsOnly_copy.loc[k,'累积距离[km]']=df_gpsOnly_copy.loc[k-1,'累积距离[km]']
- df_gpsOnly_copy.loc[k,'能耗[km/kwh]']=df_gpsOnly_copy.loc[k-1,'能耗[km/kwh]']
-
-
- ####行驶里程估计
- energy1=df_temp2['累积能量[Kwh]'].values
- if energy1[-1]-energy1[-2]>0:
- gps_dis=df_gpsOnly_copy.loc[k,'△距离1']
- delta_t=df_gpsOnly_copy.loc[k,'相对时间[s]']-df_gpsOnly_copy.loc[k-1,'相对时间[s]']
- vehspd=gps_dis*3600/delta_t
- if vehspd>30:
- df_gpsOnly_copy.loc[k,'△距离3[km]']=(energy1[-1]-energy1[-2])*df_gpsOnly_copy.loc[k,'能耗[km/kwh]']
- else:
- df_gpsOnly_copy.loc[k,'△距离3[km]']=max((energy1[-1]-energy1[-2])*df_gpsOnly_copy.loc[k,'能耗[km/kwh]'],gps_dis)
- else:
- df_gpsOnly_copy.loc[k,'△距离3[km]']=0
- df_gpsOnly_copy.loc[k,'△距离2']=df_gpsOnly_copy.loc[k,'△距离3[km]']
-
- elif math.isnan(dis2[k]) and (math.isnan(dis2[k-1])) and nan_flag==1: #本次△距离为NAN上次也为NAN
- df_energyPerKm=df_gpsOnly_copy[df_gpsOnly_copy['能耗[km/kwh]']>0]
- df_energyPerKm.index=[i for i in range(len(df_energyPerKm))]
- total_num=len(df_energyPerKm)
- #统计最近10次的平均能耗,用于补充dis2前后都为nan时刻处的能耗及距离,
- ##如果不足10次按照实际次数统计
- if total_num>10:
- energycost_acc=0
- for i in range(10):
- energycost_acc=energycost_acc+df_energyPerKm.loc[total_num-i-1,'能耗[km/kwh]']
- avg_energyCost=min(max(energycost_acc/10,25),50)
- df_gpsOnly_copy.loc[k,'△能量[Kwh]']=1
- df_gpsOnly_copy.loc[k,'累积距离[km]']=avg_energyCost
- df_gpsOnly_copy.loc[k,'能耗[km/kwh]']=avg_energyCost
- elif total_num>0:
- avg_energyCost=min(max(df_energyPerKm['能耗[km/kwh]'].values.mean(),25),50)
- df_gpsOnly_copy.loc[k,'△能量[Kwh]']=1
- df_gpsOnly_copy.loc[k,'累积距离[km]']=avg_energyCost
- df_gpsOnly_copy.loc[k,'能耗[km/kwh]']=avg_energyCost
- else:
- df_gpsOnly_copy.loc[k,'△能量[Kwh]']=df_gpsOnly_copy.loc[k-1,'△能量[Kwh]']
- df_gpsOnly_copy.loc[k,'累积距离[km]']=df_gpsOnly_copy.loc[k-1,'累积距离[km]']
- df_gpsOnly_copy.loc[k,'能耗[km/kwh]']=df_gpsOnly_copy.loc[k-1,'能耗[km/kwh]']
-
- ##计算行驶里程
- delta_energy=df_gpsOnly_copy.loc[k,'累积能量[Kwh]']-df_gpsOnly_copy.loc[k-1,'累积能量[Kwh]']
- if delta_energy>0:
- gps_dis=df_gpsOnly_copy.loc[k,'△距离1']
- delta_t=df_gpsOnly_copy.loc[k,'相对时间[s]']-df_gpsOnly_copy.loc[k-1,'相对时间[s]']
- vehspd=gps_dis*3600/delta_t
- if vehspd>30:
- df_gpsOnly_copy.loc[k,'△距离3[km]']=delta_energy*df_gpsOnly_copy.loc[k,'累积距离[km]']/df_gpsOnly_copy.loc[k,'△能量[Kwh]']
- else:
- df_gpsOnly_copy.loc[k,'△距离3[km]']=max(delta_energy*df_gpsOnly_copy.loc[k,'累积距离[km]']/df_gpsOnly_copy.loc[k,'△能量[Kwh]'],gps_dis)
- else:
- df_gpsOnly_copy.loc[k,'△距离3[km]']=0
-
- df_gpsOnly_copy.loc[k,'△距离2']=df_gpsOnly_copy.loc[k,'△距离3[km]']
- else:
- df_gpsOnly_copy.loc[k,'△能量[Kwh]']=1
- df_gpsOnly_copy.loc[k,'累积距离[km]']=25
- df_gpsOnly_copy.loc[k,'能耗[km/kwh]']=25
- df_gpsOnly_copy.loc[k,'△距离3[km]']=df_gpsOnly_copy.loc[k,'△距离2']
- ###############输出计算结果##################
- ############################################
- df_gpsOnly_copy.loc[0,'累积里程[km]']=0
- df_gpsOnly_copy.loc[0,'日期']=str(df_gpsOnly_copy.loc[0,'时间戳'])[0:10]
- for k in range(1,len(df_gpsOnly_copy)):
- df_dis_temp=df_gpsOnly_copy['△距离3[km]'].values[0:k+1]
- df_dis_temp1=df_dis_temp[np.logical_not(np.isnan(df_dis_temp))]
- if len(df_dis_temp1)>0:
- df_gpsOnly_copy.loc[k,'累积里程[km]']=df_dis_temp1.sum()
- else:
- df_gpsOnly_copy.loc[k,'累积里程[km]']=df_gpsOnly_copy.loc[k-1,'累积里程[km]']
- df_gpsOnly_copy.loc[k,'日期']=str(df_gpsOnly_copy.loc[k,'时间戳'])[0:10]
- datetime1=np.unique(df_gpsOnly_copy['日期'].values)
- df_result=pd.DataFrame(index=datetime1)
- list_result=[]
- list_day_odo=[]
- for k in range(len(datetime1)):
- df_day=df_gpsOnly_copy[df_gpsOnly_copy['日期']==datetime1[k]]
- odo_day=df_day['累积里程[km]'].values
- df_result.loc[datetime1[k],'累积里程[km]']=odo_day[-1]-odo_day[0]
- df_day['累积里程[km]']=odo_day-odo_day[0]
- list_day_odo.extend(odo_day-odo_day[0])
- list_result.append([datetime1[k],df_day])
- df_gpsOnly_copy.loc[:,'每日累积里程[km]']=list_day_odo
- #删除一些无用列,获取用于计算的数据
- df_output=df_gpsOnly_copy[['时间戳','data_status','SOC[%]','每日累积里程[km]']]
- #添加sn
- df_output['sn'] = sn
- return df_output
|