123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159 |
- import pandas as pd
- import numpy as np
- from datetime import datetime
- from datetime import timedelta
- def get_bms_drive_timetable(df_bms,battery_mode):
- '''对df_bms进行处理,得到行车的时间表。'''
- #####################step1 先使用电流做充电状态的判断#############################################
- if battery_mode==0:#mode=0,电流为正代表放电
- condition_chrg=df_bms['bmspackcrnt']<0##根据电流,挑选充电状态
- df_bms.loc[condition_chrg,'bscsta']='chrg'
- condition_drive=df_bms['bmspackcrnt']>0.01##根据电流,挑选行驶状态
- df_bms.loc[condition_drive,'bscsta']='drive'
- df_bms.loc[~(condition_drive|condition_chrg),'bscsta']='idle'#静置状态
- else :#mode=1,电流为负代表放电
- condition_chrg=df_bms['bmspackcrnt']>0##根据电流,挑选充电状态
- df_bms.loc[condition_chrg,'bscsta']='chrg'
- condition_drive=df_bms['bmspackcrnt']<-0.01##根据电流,挑选行驶状态
- df_bms.loc[condition_drive,'bscsta']='drive'
- df_bms.loc[~(condition_drive|condition_chrg),'bscsta']='idle'#静置状态
- #####################step2 对drive进行debounce,进入时立即进入,退出时debounce,5分钟。##########
- index=0
- debounce_row=10#debounce判断持续10行
- debounce_time=300#debounce判断持续300秒
- #对上一步初步状态进行二次处理
- while index<(len(df_bms)-debounce_row):
- mode_0=df_bms.loc[index,'bscsta']
- mode_1=df_bms.loc[index+1,'bscsta']
- #如果发现了边界行,则进行debounce判断
- if (mode_0=='drive')&(mode_1!='drive'):#如果从drive变为idle
- accum_subtime=0#累计时间初始化
- for sub_index in range(debounce_row):#往下处理10行
- sub_time=df_bms.loc[index+sub_index,'deltatime']
- accum_subtime+=sub_time
- #如果累计时间不到300秒,则设置为drive
- if accum_subtime<debounce_time:
- df_bms.loc[index+sub_index,'bscsta']='drive'
- index=index+debounce_row#处理10行以后的数据
- #如果从idle变为drivemode,则将idle变为drive,包容前一行
- elif (mode_0!='drive')&(mode_1=='drive'):
- df_bms.loc[index,'bscsta']='drive'
- index=index+1
- else:
- index=index+1
- #######################step3 对drivemode的时间进行分段###########################################
- not_drive_flg=0#初始化
- #输出drivemode的时间段,包含开始时间、结束时间
- df_bms_drive_timetable_index=0
- df_bms_drive_timetable=pd.DataFrame([],columns={'drive_start_time','drive_end_time',
- 'gps_dist','predict_dist','drive_start_soc','drive_end_soc'})
- for index in range(len(df_bms)):
- temp_bscsta=df_bms.loc[index,'bscsta']
-
- if (temp_bscsta=='drive')&(not_drive_flg==0):
- drive_start_time=df_bms.loc[index,'time']
- not_drive_flg=1
- df_bms_drive_timetable.loc[df_bms_drive_timetable_index,'drive_start_time']=drive_start_time
- #startsoc
- drive_start_soc=df_bms.loc[index,'bmspacksoc']
- df_bms_drive_timetable.loc[df_bms_drive_timetable_index,'drive_start_soc']=drive_start_soc
- elif (temp_bscsta!='drive')&(not_drive_flg==1):
- drive_end_time=df_bms.loc[index,'time']
- not_drive_flg=0
- df_bms_drive_timetable.loc[df_bms_drive_timetable_index,'drive_end_time']=drive_end_time
- #endsoc
- drive_end_soc=df_bms.loc[index,'bmspacksoc']
- df_bms_drive_timetable.loc[df_bms_drive_timetable_index,'drive_end_soc']=drive_end_soc
- df_bms_drive_timetable_index+=1#index++
- #删除时间信息不齐全的行
- df_bms_drive_timetable=df_bms_drive_timetable.dropna(subset=['drive_end_time','drive_start_time'])
-
- return df_bms_drive_timetable
- def read_df_bms(path):
- '''从路径中读取df_bms,进行预处理'''
- df_bms=pd.read_csv(path, encoding='gbk')#编码方式gbk
- #筛选表头,重命名
- bms_columns=['时间戳','总电流[A]','总电压[V]','SOC[%]']
- df_bms=df_bms.loc[:,bms_columns].copy()
- df_bms.rename(columns = {"时间戳": "time", "总电流[A]": "bmspackcrnt",
- "总电压[V]": "bmspackvol", "SOC[%]": "bmspacksoc"},inplace=True)#表头替换
- #时间格式调整
- df_bms['time']=df_bms['time'].apply(lambda x:datetime.strptime(x,'%Y-%m-%d %H:%M:%S'))#时间格式调整
- #进行预处理
- df_bms=df_add_deltatime(df_bms)#增加deltatime列
- return df_bms
- def preprocess_Df_Bms(df_bms):
- '''对获得的df_bms,进行预处理'''
- #筛选表头,重命名
- bms_columns=['时间戳','总电流[A]','总电压[V]','SOC[%]']
- df_bms=df_bms.loc[:,bms_columns].copy()
- df_bms.rename(columns = {"时间戳": "time", "总电流[A]": "bmspackcrnt",
- "总电压[V]": "bmspackvol", "SOC[%]": "bmspacksoc"},inplace=True)#表头替换
- #删除空行
- df_bms=df_bms.dropna(subset=['time'])
- #删除时间重复的行,保留第一次出现的行
- df_bms=df_bms.drop_duplicates(subset=['time'],keep='first')
- #时间格式调整
- df_bms['time']=df_bms['time'].apply(lambda x:datetime.strptime(x,'%Y-%m-%d %H:%M:%S'))#时间格式调整
- #进行预处理
- df_bms=df_add_deltatime(df_bms)#增加deltatime列
- return df_bms
- def df_add_deltatime(df_in):
- '''Add a columns:deltatime,input df must have time column.'''
- for i in range(len(df_in)):
- #首行默认为0
- if i==0:
- df_in.loc[i,'deltatime']=0
- #从第二行开始,计算i行到i-1行,GPS距离之差
- else:
- time1=df_in.loc[i-1,'time']
- time2=df_in.loc[i,'time']
- deltatime=time_interval(time1,time2)#计算时间差,返回单位为秒。
- df_in.loc[i,'deltatime']=deltatime
- return df_in
- def time_interval(time1,time2):
- """
- Calculate the time interval between two times,
- return the seconds
- """
- deltatime=time2-time1
- return deltatime.seconds
- def cal_deltasoc(df_bms,start_time,end_time):
- '''输入开始时间和结束时间,返回deltasoc,此处将deltasoc*1既等效为unrecorded_odo.'''
- time_condition=(df_bms['time']>start_time)&(df_bms['time']<end_time)
- df_bms_sub=df_bms.loc[time_condition,:].copy()
- if len(df_bms_sub)>=2:
-
- df_bms_head=df_bms_sub.head(1).copy()#首行
- df_bms_startsoc=df_bms_head['bmspacksoc'].values[0]
- df_bms_tail=df_bms_sub.tail(1).copy()#尾行
- df_bms_endsoc=df_bms_tail['bmspacksoc'].values[0]
- delta_soc=df_bms_startsoc-df_bms_endsoc
-
- if delta_soc>0:
- #如果df_bms出现时间不连续,则先计算deltasoc,deltasoc每变化1,续驶里程增加1,
- unrecorded_odo=delta_soc*1
- #print('From '+str(start_time)+' to '+str(end_time)+' soc decrease: '+str(delta_soc))
- else:
- unrecorded_odo=0#如果deltasoc不大于0,说明在充电,或者静置不动
- #如果行数少于2,无法计算
- else:
- unrecorded_odo=0
- return unrecorded_odo
|