data_process_1121.py 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. ##################################################################
  4. #
  5. # Copyright (c) 2023 CICV, Inc. All Rights Reserved
  6. #
  7. ##################################################################
  8. """
  9. @Authors: yangzihao(yangzihao@china-icv.cn)
  10. @Data: 2023/11/27
  11. @Last Modified: 2023/11/27
  12. @Summary: Csv data process functions
  13. """
  14. import os
  15. import sys
  16. import numpy as np
  17. import pandas as pd
  18. from status_mapping import *
  19. from status_trigger import *
  20. # from status_mapping import acc_status_mapping, lka_status_mapping, ldw_status_mapping
  21. from data_quality import DataQuality, get_all_files, frame_loss_statistic
  22. from common import cal_velocity
  23. from data_info import CsvData
  24. import log
  25. class DataProcess(object):
  26. """
  27. The data process class. It is a template to get evaluation raw data and process the raw data.
  28. Attributes:
  29. """
  30. def __init__(self, data_path, config, case_name):
  31. # base info
  32. self.data_path = data_path
  33. self.case_name = case_name
  34. self.config = config
  35. # drive data
  36. self.ego_df = pd.DataFrame()
  37. self.object_df = pd.DataFrame()
  38. self.driver_ctrl_df = pd.DataFrame()
  39. self.vehicle_sys_df = pd.DataFrame()
  40. self.status_df = pd.DataFrame()
  41. # environment data
  42. self.lane_info_df = pd.DataFrame()
  43. self.road_mark_df = pd.DataFrame()
  44. self.road_pos_df = pd.DataFrame()
  45. self.traffic_light_df = pd.DataFrame()
  46. self.traffic_signal_df = pd.DataFrame()
  47. self.frame_rate = float()
  48. self.obj_data = {}
  49. self.ego_data = {}
  50. self.obj_id_list = {}
  51. self.car_info = {}
  52. self.report_info = {}
  53. self.driver_ctrl_data = {}
  54. self.status_trigger_dict = {}
  55. self._process()
  56. def _process(self):
  57. # self._signal_mapping()
  58. self._merge_csv()
  59. self._read_csv()
  60. self._invalid_detect()
  61. self._fill_missing_columns()
  62. # self._cal_frame_rate()
  63. # self._time_alignment()
  64. self.car_info = self._get_car_info(self.object_df)
  65. # self._compact_data()
  66. # self._abnormal_detect()
  67. # self._status_map(self.object_df)
  68. self._object_accel_get_from_egostate()
  69. self._object_df_process()
  70. self.status_trigger_dict = self._get_status_trigger_dict(self.status_df)
  71. self.report_info = self._get_report_info(self.obj_data[1])
  72. self.driver_ctrl_data = self._get_driver_ctrl_data(self.driver_ctrl_df)
  73. def _invalid_column_detect(self, df, csv_name): # head and tail detect
  74. """
  75. Detect the head of the csv whether begin with 0 or not.
  76. Returns:
  77. A dataframe, which 'time' column begin with 0.
  78. """
  79. logger = log.get_logger()
  80. for column in df.columns:
  81. if df[column].nunique() == 1:
  82. # if 9999.00 in df[column].values or "9999.00" in df[column].values:
  83. logger.warning(
  84. f"[case:{self.case_name}] SINGLE_CASE_EVAL: [{csv_name}] data '{column}' invalid WARNING!")
  85. def _csv_interpolate_by_frame(self, df):
  86. # df = pd.read_csv(input) # 读取CSV文件
  87. df['simFrame'] = pd.to_numeric(df['simFrame'], errors='coerce') # 转换simFrame列为数字类型
  88. df = df.sort_values(by='simFrame') # 根据simFrame列进行排序
  89. full_simFrame_series = pd.Series(range(df['simFrame'].min(), df['simFrame'].max() + 1)) # 构建一个包含连续simFrame的完整序列
  90. df = df.merge(full_simFrame_series.rename('simFrame'), how='right') # 使用merge方法将原始数据与完整序列合并,以填充缺失的simFrame行
  91. df = df.interpolate(method='linear') # 对其他列进行线性插值
  92. df['simFrame'] = df['simFrame'].astype(int) # 恢复simFrame列的数据类型为整数
  93. # df.to_csv(output, index=False) # 保存处理后的数据到新的CSV文件
  94. result = df.copy()
  95. return result
  96. def _cal_frame_rate(self):
  97. object_df = self.object_df.copy()
  98. ego_df = object_df[object_df['playerId'] == 1]
  99. df_filtered = ego_df[(ego_df['simTime'] > 0) & (ego_df['simTime'] <= 1)]
  100. self.frame_rate = df_filtered.shape[0]
  101. def _data_time_align(self, base_time, df):
  102. # 特判,如果输入的dataframe无数值,那么直接返回
  103. if df.empty:
  104. return df
  105. # FRAME_RATE = self.frame_rate
  106. time_diff = 1.0 / self.frame_rate
  107. # 创建一个新的递增的 simTime 序列,从 0 开始,步长为 0.01 (time_diff)
  108. new_sim_time_values = np.arange(0, base_time.max() + time_diff, time_diff)
  109. # 创建一个映射字典,将原始 simTime 值映射到新的 simTime 值
  110. original_to_new_sim_time = {original: round(new_sim_time_values[i], 2) for i, original in enumerate(base_time)}
  111. # 使用isin函数来过滤df,并筛选出simFrame大于0的数据
  112. filtered_df1 = df[df['simTime'].isin(base_time)]
  113. filtered_df2 = filtered_df1[filtered_df1['simFrame'] > 0]
  114. filtered_df = filtered_df2.reset_index(drop=True)
  115. # 使用映射字典来替换 filtered_df 中的 simTime 列
  116. filtered_df['simTime'] = filtered_df['simTime'].map(original_to_new_sim_time)
  117. # 同步更新simFrame
  118. filtered_df['simFrame'] = (filtered_df['simTime'] * self.frame_rate + 1).round().astype(int)
  119. return filtered_df
  120. @staticmethod
  121. def _speed_mps2kmph(df):
  122. df['speedX'] = df['speedX'] * 3.6 # m/s to km/h
  123. df['speedY'] = df['speedY'] * 3.6 # m/s to km/h
  124. df['speedZ'] = df['speedZ'] * 3.6 # m/s to km/h
  125. return df
  126. def _merge_csv(self):
  127. # read csv files
  128. df_ego = pd.read_csv(os.path.join(self.data_path, 'EgoState.csv')).drop_duplicates().dropna(how='all')
  129. df_object = pd.read_csv(os.path.join(self.data_path, 'ObjState.csv')).drop_duplicates() # 车辆行驶信息
  130. df_laneinfo = pd.read_csv(os.path.join(self.data_path, 'LaneInfo.csv')).drop_duplicates() # 曲率信息, 曲率加速度信息
  131. df_roadPos = pd.read_csv(os.path.join(self.data_path, 'RoadPos.csv')).drop_duplicates()
  132. df_status = pd.read_csv(os.path.join(self.data_path, 'VehState.csv'), index_col=False).drop_duplicates() # 状态机
  133. df_vehicleSys = pd.read_csv(os.path.join(self.data_path, 'VehicleSystems.csv')).drop_duplicates() # 车灯信息
  134. self.lane_info_df = df_laneinfo
  135. self.vehicle_sys_df = df_vehicleSys
  136. self.status_df = df_status
  137. self.obj_roadpos_merge = pd.merge(df_object, df_roadPos, on=['simTime', 'simFrame', 'playerId'], how='inner')
  138. self._invalid_detect_before_merge() # invalid detect
  139. # self._invalid_column_detect(df_laneinfo, 'LaneInfo.csv')
  140. # self._invalid_column_detect(df_object, 'ObjState.csv')
  141. # self._invalid_column_detect(df_vehicleSys, 'VehicleSystems.csv')
  142. # self._invalid_column_detect(df_status, 'VehState.csv')
  143. # df_ego['simTime'] = df_ego['simTime'].round(2) # EGO: km/h
  144. # df_object['simTime'] = df_object['simTime'].round(2) # OBJ: m/s, need unit conversion
  145. df_object = self._speed_mps2kmph(df_object) # m/s to km/h
  146. # base_time = df_ego['simTime'].unique()
  147. # df_ego = self._data_time_align(base_time, df_ego)
  148. # df_object = self._data_time_align(base_time, df_object)
  149. # df_laneinfo = self._data_time_align(base_time, df_laneinfo)
  150. # df_roadPos = self._data_time_align(base_time, df_roadPos)
  151. # df_status = self._data_time_align(base_time, df_status)
  152. # df_vehicleSys = self._data_time_align(base_time, df_vehicleSys)
  153. EGO_PLAYER_ID = 1
  154. # 合并 ego_df 和 obj_df
  155. df_ego['playerId'] = EGO_PLAYER_ID
  156. combined_df = pd.concat([df_object, df_ego]).drop_duplicates(subset=['simTime', 'simFrame', 'playerId'])
  157. df_object = combined_df.sort_values(
  158. by=['simTime', 'simFrame', 'playerId']).copy() # 按simTime/simFrame/playerId排序
  159. df_laneinfo['curvHor'] = df_laneinfo['curvHor'].round(3)
  160. df_laneinfo.rename(columns={"id": 'laneId'}, inplace=True)
  161. result = pd.merge(df_roadPos, df_laneinfo, how='inner', on=["simTime", "simFrame", "playerId", "laneId"])
  162. df_laneinfo_new = result[["simTime", "simFrame", "playerId", "curvHor", "curvHorDot"]].copy().drop_duplicates()
  163. # status mapping
  164. df_status = self._status_mapping(df_status)
  165. df_status = df_status[['simTime', 'ACC_status', 'Aeb_status', 'LKA_status', 'ICA_status', 'LDW_status',
  166. 'set_cruise_speed', 'set_headway_time']].copy()
  167. df_roadPos = df_roadPos[["simTime", "simFrame", "playerId", "laneOffset", "rollRel", "pitchRel", "roadId", "laneId"]].copy()
  168. # df merge
  169. df_vehicleSys = df_vehicleSys[['simTime', 'simFrame', 'lightMask', 'steering']].copy()
  170. merged_df = pd.merge(df_object, df_vehicleSys, on=["simTime", "simFrame"], how="left")
  171. merged_df1 = pd.merge(merged_df, df_laneinfo_new, on=["simTime", "simFrame", "playerId"], how="left")
  172. merged_df1 = pd.merge(merged_df1, df_roadPos, on=["simTime", "simFrame", "playerId"], how="left")
  173. merged_df2 = pd.merge_asof(merged_df1, df_status, on="simTime", direction='nearest')
  174. mg_df1 = merged_df2.drop_duplicates() # 去重
  175. mg_df1 = mg_df1[mg_df1.simFrame > 0].copy()
  176. mask_player1 = mg_df1['playerId'] == 1
  177. player1_road_lane = mg_df1.loc[mask_player1, ['simTime', 'roadId', 'laneId']]
  178. mask_player1 = (mg_df1['simTime'].isin(player1_road_lane['simTime'])) & \
  179. (mg_df1['roadId'].isin(player1_road_lane['roadId'])) & \
  180. (mg_df1['laneId'].isin(player1_road_lane['laneId']))
  181. mg_df = mg_df1.loc[mask_player1]
  182. mg_df.to_csv(os.path.join(self.data_path, 'merged_ObjState.csv'), index=False)
  183. print('The files are merged.')
  184. def _read_csv(self):
  185. """
  186. Read csv files to dataframe.
  187. Args:
  188. data_path: A str of the path of csv files
  189. Returns:
  190. No returns.
  191. """
  192. self.driver_ctrl_df = pd.read_csv(os.path.join(self.data_path, 'DriverCtrl.csv')).drop_duplicates()
  193. self.ego_df = pd.read_csv(os.path.join(self.data_path, 'EgoState.csv')).drop_duplicates()
  194. self.object_df = pd.read_csv(os.path.join(self.data_path, 'merged_ObjState.csv')).drop_duplicates(
  195. subset=['simTime', 'simFrame', 'playerId'])
  196. self.road_mark_df = pd.read_csv(os.path.join(self.data_path, 'RoadMark.csv')).drop_duplicates()
  197. self.road_pos_df = pd.read_csv(os.path.join(self.data_path, 'RoadPos.csv')).drop_duplicates()
  198. self.traffic_light_df = pd.read_csv(os.path.join(self.data_path, 'TrafficLight.csv')).drop_duplicates()
  199. self.traffic_signal_df = pd.read_csv(os.path.join(self.data_path, 'TrafficSign.csv')).drop_duplicates()
  200. def _invalid_detect_before_merge(self):
  201. # invalid detect
  202. self._invalid_column_detect(self.lane_info_df, 'LaneInfo.csv')
  203. # self._invalid_column_detect(self.object_df, 'ObjState.csv')
  204. self._invalid_column_detect(self.vehicle_sys_df, 'VehicleSystems.csv')
  205. self._invalid_column_detect(self.status_df, 'VehState.csv')
  206. def _invalid_detect(self):
  207. # invalid detect
  208. self._invalid_column_detect(self.ego_df, 'EgoState.csv')
  209. self._invalid_column_detect(self.object_df, 'ObjState.csv')
  210. self._invalid_column_detect(self.driver_ctrl_df, 'DriverCtrl.csv')
  211. self._invalid_column_detect(self.road_mark_df, 'RoadMark.csv')
  212. self._invalid_column_detect(self.road_pos_df, 'RoadPos.csv')
  213. self._invalid_column_detect(self.traffic_light_df, 'TrafficLight.csv')
  214. self._invalid_column_detect(self.traffic_signal_df, 'TrafficSign.csv')
  215. def _fill_missing_columns(self):
  216. pass
  217. def _time_alignment(self):
  218. base_time = self.ego_df['simTime'].unique()
  219. self.driver_ctrl_df = self._data_time_align(base_time, self.driver_ctrl_df)
  220. self.ego_df = self._data_time_align(base_time, self.ego_df)
  221. self.object_df = self._data_time_align(base_time, self.object_df)
  222. self.road_mark_df = self._data_time_align(base_time, self.road_mark_df)
  223. self.road_pos_df = self._data_time_align(base_time, self.road_pos_df)
  224. self.traffic_light_df = self._data_time_align(base_time, self.traffic_light_df)
  225. self.traffic_signal_df = self._data_time_align(base_time, self.traffic_signal_df)
  226. print("The data is aligned.")
  227. # interpolate data
  228. # self.driver_ctrl_df = self._csv_interpolate_by_frame(self.driver_ctrl_df)
  229. # self.ego_df = self._csv_interpolate_by_frame(self.ego_df)
  230. # self.object_df = self._csv_interpolate_by_frame(self.object_df)
  231. # self.road_mark_df = self._csv_interpolate_by_frame(self.road_mark_df)
  232. # self.road_pos_df = self._csv_interpolate_by_frame(self.road_pos_df)
  233. # self.traffic_light_df = self._csv_interpolate_by_frame(self.traffic_light_df)
  234. # self.traffic_signal_df = self._csv_interpolate_by_frame(self.traffic_signal_df)
  235. def _signal_mapping(self):
  236. pass
  237. # singal mapping
  238. # signal_json = r'./signal.json'
  239. # signal_dict = json2dict(signal_json)
  240. # df_objectstate = signal_name_map(df_objectstate, signal_dict, 'objectState')
  241. # df_roadmark = signal_name_map(df_roadmark, signal_dict, 'roadMark')
  242. # df_roadpos = signal_name_map(df_roadpos, signal_dict, 'roadPos')
  243. # df_trafficlight = signal_name_map(df_trafficlight, signal_dict, 'trafficLight')
  244. # df_trafficsignal = signal_name_map(df_trafficsignal, signal_dict, 'trafficSignal')
  245. # df_drivectrl = signal_name_map(df_drivectrl, signal_dict, 'driverCtrl')
  246. # df_laneinfo = signal_name_map(df_laneinfo, signal_dict, 'laneInfo')
  247. # df_status = signal_name_map(df_status, signal_dict, 'statusMachine')
  248. # df_vehiclesys = signal_name_map(df_vehiclesys, signal_dict, 'vehicleSys')
  249. def _get_car_info(self, df):
  250. """
  251. Args:
  252. df:
  253. Returns:
  254. """
  255. EGO_PLAYER_ID = 1
  256. first_row = df[df['playerId'] == EGO_PLAYER_ID].iloc[0].to_dict()
  257. # length = first_row['dimX']
  258. # width = first_row['dimY']
  259. # height = first_row['dimZ']
  260. # offset = first_row['offX']
  261. #
  262. # car_info = {
  263. # "length": length,
  264. # "width": width,
  265. # "height": height,
  266. # "offset": offset
  267. # }
  268. car_info = {
  269. "length": 4,
  270. "width": 2,
  271. "height": 2,
  272. "offset": 1
  273. }
  274. return car_info
  275. def _compact_data(self):
  276. """
  277. Extra necessary data from dataframes.
  278. Returns:
  279. """
  280. self.object_df = self.object_df[CsvData.OBJECT_INFO].copy()
  281. def _abnormal_detect(self): # head and tail detect
  282. """
  283. Detect the head of the csv whether begin with 0 or not.
  284. Returns:
  285. A dataframe, which 'time' column begin with 0.
  286. """
  287. pass
  288. def _unit_unified(self):
  289. pass
  290. def _object_accel_get_from_egostate(self):
  291. # 使用merge函数来合并两个DataFrame,基于simTime和playerId列
  292. # 我们使用how='left'来确保df_object中的所有行都被保留
  293. # 并且当在df_ego中找到匹配时,使用df_ego中的accel值
  294. merged = pd.merge(self.object_df, self.ego_df[['simTime', 'playerId', 'accelX']],
  295. on=['simTime', 'playerId'], how='left', suffixes=('', '_y'))
  296. merged = pd.merge(merged, self.ego_df[['simTime', 'playerId', 'accelY']],
  297. on=['simTime', 'playerId'], how='left', suffixes=('', '_y'))
  298. # 因为我们使用了suffixes参数来避免列名冲突(尽管在这个特定情况下可能不是必需的),
  299. # 但现在我们有一个名为'accel_y'的列,它包含了我们要更新的值
  300. # 如果不担心列名冲突,可以省略suffixes参数,并直接使用'accel'作为列名
  301. # 在这种情况下,你只需要选择正确的列来更新df_object
  302. # 更新df_object的accel列
  303. # 如果使用了suffixes参数,则使用'accel_y'
  304. # 如果没有使用suffixes参数,并且确信没有列名冲突,则直接使用'accel'
  305. self.object_df['accelX'] = merged['accelX_y'] # 如果使用了suffixes
  306. self.object_df['accelY'] = merged['accelY_y'] # 如果使用了suffixes
  307. def _object_df_process(self):
  308. """
  309. Process the data of object dataframe. Save the data groupby object_ID.
  310. Returns:
  311. No returns.
  312. """
  313. EGO_PLAYER_ID = 1
  314. data = self.object_df.copy()
  315. # calculate common parameters
  316. data['lat_v'] = data['speedY'] * 1
  317. data['lon_v'] = data['speedX'] * 1
  318. data['v'] = data.apply(lambda row: cal_velocity(row['lat_v'], row['lon_v']), axis=1)
  319. data['v'] = data['v'] # km/h
  320. # calculate acceleraton components
  321. data['lat_acc'] = data['accelY'] * 1
  322. data['lon_acc'] = data['accelX'] * 1
  323. data['accel'] = data.apply(lambda row: cal_velocity(row['lat_acc'], row['lon_acc']), axis=1)
  324. data = data.dropna(subset=['type'])
  325. data.reset_index(drop=True, inplace=True)
  326. self.object_df = data.copy()
  327. # calculate respective parameters
  328. for obj_id, obj_data in data.groupby("playerId"):
  329. self.obj_data[obj_id] = obj_data
  330. self.obj_data[obj_id]['time_diff'] = self.obj_data[obj_id]['simTime'].diff()
  331. self.obj_data[obj_id]['lat_acc_diff'] = self.obj_data[obj_id]['lat_acc'].diff()
  332. self.obj_data[obj_id]['lon_acc_diff'] = self.obj_data[obj_id]['lon_acc'].diff()
  333. self.obj_data[obj_id]['yawrate_diff'] = self.obj_data[obj_id]['speedH'].diff()
  334. self.obj_data[obj_id]['lat_acc_roc'] = self.obj_data[obj_id]['lat_acc_diff'] / self.obj_data[obj_id][
  335. 'time_diff']
  336. self.obj_data[obj_id]['lon_acc_roc'] = self.obj_data[obj_id]['lon_acc_diff'] / self.obj_data[obj_id][
  337. 'time_diff']
  338. self.obj_data[obj_id]['accelH'] = self.obj_data[obj_id]['yawrate_diff'] / self.obj_data[obj_id][
  339. 'time_diff']
  340. self.obj_data[obj_id]['lat_acc_roc'] = self.obj_data[obj_id]['lat_acc_roc'].replace([np.inf, -np.inf],
  341. [9999, -9999])
  342. self.obj_data[obj_id]['lon_acc_roc'] = self.obj_data[obj_id]['lon_acc_roc'].replace([np.inf, -np.inf],
  343. [9999, -9999])
  344. self.obj_data[obj_id]['accelH'] = self.obj_data[obj_id]['accelH'].replace([np.inf, -np.inf], [9999, -9999])
  345. # get object id list
  346. self.obj_id_list = list(self.obj_data.keys())
  347. self.ego_data = self.obj_data[EGO_PLAYER_ID]
  348. def _get_status_trigger_dict(self, status_df):
  349. # calculate ACC trigger time
  350. acc_trigger = ACCTrigger(status_df)
  351. acc_status_trigger = acc_trigger.ACC_active_time_statistics()
  352. # calculate LKA trigger time
  353. lka_trigger = LKATrigger(status_df)
  354. lka_status_trigger = lka_trigger.LKA_active_time_statistics()
  355. # calculate ICA trigger time
  356. ica_trigger = ICATrigger(status_df)
  357. ica_status_trigger = ica_trigger.ICA_active_time_statistics()
  358. # ica_status_trigger = {'ICA_active_time': []}
  359. return {
  360. "ACC": acc_status_trigger,
  361. "LKA": lka_status_trigger,
  362. "ICA": ica_status_trigger
  363. }
  364. def _mileage_cal(self, df1):
  365. """
  366. Calculate mileage of given df.
  367. Args:
  368. df1: A dataframe of driving data.
  369. Returns:
  370. mileage: A float of the mileage(meter) of the driving data.
  371. """
  372. df = df1.copy()
  373. # if 9999.00 in df['travelDist'].values or "9999.00" in df['travelDist'].values:
  374. if df['travelDist'].nunique() == 1:
  375. df['time_diff'] = df['simTime'].diff() # 计算时间间隔
  376. df['avg_speed'] = (df['v'] + df['v'].shift()) / 2 # 计算每个时间间隔的平均速度
  377. df['distance_increment'] = df['avg_speed'] * df['time_diff'] / 3.6 # 计算每个时间间隔的距离增量
  378. # 计算当前里程
  379. df['travelDist'] = df['distance_increment'].cumsum()
  380. df['travelDist'] = df['travelDist'].fillna(0)
  381. mile_start = df['travelDist'].iloc[0]
  382. mile_end = df['travelDist'].iloc[-1]
  383. mileage = round(mile_end - mile_start, 2)
  384. return mileage
  385. def _duration_cal(self, df):
  386. """
  387. Calculate duration of given df.
  388. Args:
  389. df: A dataframe of driving data.
  390. Returns:
  391. duration: A float of the duration(second) of the driving data.
  392. """
  393. time_start = df['simTime'].iloc[0]
  394. time_end = df['simTime'].iloc[-1]
  395. duration = time_end - time_start
  396. return duration
  397. def _get_report_info(self, df):
  398. """
  399. Get report infomation from dataframe.
  400. Args:
  401. df: A dataframe of driving data.
  402. Returns:
  403. report_info: A dict of report infomation.
  404. """
  405. mileage = self._mileage_cal(df)
  406. duration = self._duration_cal(df)
  407. report_info = {
  408. "mileage": mileage,
  409. "duration": duration
  410. }
  411. return report_info
  412. def _status_mapping(self, df):
  413. # df['Abpb_status'] = df['Abpb_status'].apply(lambda x: abpb_status_mapping(x))
  414. df['ACC_status'] = df['ACC_status'].apply(lambda x: acc_status_mapping(x))
  415. df['Aeb_status'] = df['Aeb_status'].apply(lambda x: aeb_status_mapping(x))
  416. # df['Awb_status'] = df['Awb_status'].apply(lambda x: ldw_status_mapping(x))
  417. # df['DOW_status'] = df['DOW_status'].apply(lambda x: ldw_status_mapping(x))
  418. # df['Eba_status'] = df['Eba_status'].apply(lambda x: ldw_status_mapping(x))
  419. # df['ELK_status'] = df['ELK_status'].apply(lambda x: ldw_status_mapping(x))
  420. # df['ESA_status'] = df['ESA_status'].apply(lambda x: ldw_status_mapping(x))
  421. # df['Fcw_status'] = df['Fcw_status'].apply(lambda x: ldw_status_mapping(x))
  422. df['ICA_status'] = df['ICA_status'].apply(lambda x: ica_status_mapping(x))
  423. # df['ISLC_status'] = df['ISLC_status'].apply(lambda x: ldw_status_mapping(x))
  424. # df['JA_status'] = df['JA_status'].apply(lambda x: ldw_status_mapping(x))
  425. df['LKA_status'] = df['LKA_status'].apply(lambda x: lka_status_mapping(x))
  426. df['LDW_status'] = df['LDW_status'].apply(lambda x: ldw_status_mapping(x))
  427. # df['NOA_status'] = df['NOA_status'].apply(lambda x: ldw_status_mapping(x))
  428. # df['RCW_status'] = df['RCW_status'].apply(lambda x: ldw_status_mapping(x))
  429. # df['TLC_status'] = df['TLC_status'].apply(lambda x: ldw_status_mapping(x))
  430. # df['FVSR_status'] = df['FVSR_status'].apply(lambda x: ldw_status_mapping(x))
  431. # df['BSD_status'] = df['BSD_status'].apply(lambda x: ldw_status_mapping(x))
  432. # df['RCTA_status'] = df['RCTA_status'].apply(lambda x: ldw_status_mapping(x))
  433. # df['FCTA_status'] = df['FCTA_status'].apply(lambda x: ldw_status_mapping(x))
  434. # df['ISA_status'] = df['ISA_status'].apply(lambda x: ldw_status_mapping(x))
  435. # df['TSR_status'] = df['TSR_status'].apply(lambda x: ldw_status_mapping(x))
  436. # df['AVM_status'] = df['AVM_status'].apply(lambda x: ldw_status_mapping(x))
  437. # df['PDC_status'] = df['PDC_status'].apply(lambda x: ldw_status_mapping(x))
  438. # df['APA_status'] = df['APA_status'].apply(lambda x: ldw_status_mapping(x))
  439. # df['MEB_status'] = df['MEB_status'].apply(lambda x: ldw_status_mapping(x))
  440. # df['RDA_status'] = df['RDA_status'].apply(lambda x: ldw_status_mapping(x))
  441. return df
  442. def _get_driver_ctrl_data(self, df):
  443. """
  444. Process and get drive ctrl information. Such as brake pedal, throttle pedal and steering wheel.
  445. Args:
  446. df: A dataframe of driver ctrl data.
  447. Returns:
  448. driver_ctrl_data: A dict of driver ctrl info.
  449. """
  450. time_list = df['simTime'].round(2).values.tolist()
  451. frame_list = df['simFrame'].values.tolist()
  452. max_brakePedal = df['brakePedal'].max()
  453. if max_brakePedal < 1:
  454. df['brakePedal'] = df['brakePedal'] * 100
  455. brakePedal_list = df['brakePedal'].values.tolist()
  456. max_throttlePedal = df['throttlePedal'].max()
  457. if max_throttlePedal < 1:
  458. df['throttlePedal'] = df['throttlePedal'] * 100
  459. throttlePedal_list = df['throttlePedal'].values.tolist()
  460. steeringWheel_list = df['steeringWheel'].values.tolist()
  461. driver_ctrl_data = {
  462. "time_list": time_list,
  463. "frame_list": frame_list,
  464. "brakePedal_list": brakePedal_list,
  465. "throttlePedal_list": throttlePedal_list,
  466. "steeringWheel_list": steeringWheel_list
  467. }
  468. return driver_ctrl_data
  469. class StatusTime(object):
  470. """
  471. # 调用方式:使用isin()方法来筛选DataFrame中simTime列与time_list中值一致的行
  472. filtered_df = df[df['simTime'].isin(self.status_time_dict['ACC_status'])]
  473. """
  474. def __init__(self, status_df):
  475. self.status_df = status_df
  476. self.status_list = []
  477. self.no_status_time_list = []
  478. self.status_time_dict = {}
  479. self._run()
  480. def _get_status_list(self):
  481. status_columns_list = self.status_df.columns.tolist()
  482. self.status_list = [x for x in status_columns_list if x not in ['simTime', 'simFrame']]
  483. def _get_no_status_time_list(self):
  484. # 筛选出所有状态机列值都为0的行
  485. filtered_rows = self.status_df[self.status_df[self.status_list].eq(0).all(axis=1)]
  486. # 将筛选后的simTime列的值作为列表输出
  487. self.no_status_time_list = filtered_rows['simTime'].tolist()
  488. def _get_status_time_dict(self):
  489. for status in self.status_list:
  490. status_time = self.status_df[self.status_df[status] != 0]['simTime'].values.tolist()
  491. self.status_time_dict[status] = status_time
  492. self.status_time_dict['no_status'] = self.no_status_time_list
  493. def _run(self):
  494. self._get_status_list()
  495. self._get_no_status_time_list()
  496. self._get_status_time_dict()