efficient.py 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631
  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: xieguijin(xieguijin@china-icv.cn), yangzihao(yangzihao@china-icv.cn)
  10. @Data: 2023/08/03
  11. @Last Modified: 2023/08/03
  12. @Summary: Functionality metrics
  13. """
  14. import sys
  15. sys.path.append('../common')
  16. sys.path.append('../modules')
  17. sys.path.append('../results')
  18. import numpy as np
  19. import pandas as pd
  20. from data_info import DataInfoList
  21. from score_weight import cal_score_with_priority, cal_weight_from_80
  22. from common import score_grade, string_concatenate, replace_key_with_value, score_over_100
  23. class Efficient(object):
  24. """
  25. Class for achieving efficient metrics for autonomous driving.
  26. Attributes:
  27. df: Vehicle driving data, stored in dataframe format.
  28. """
  29. def __init__(self, data_processed, custom_data, scoreModel):
  30. self.eval_data = pd.DataFrame()
  31. self.data_processed = data_processed
  32. self.scoreModel = scoreModel
  33. self.data = data_processed.obj_data[1]
  34. self.mileage = data_processed.report_info['mileage']
  35. self.df = pd.DataFrame()
  36. self.config = data_processed.config
  37. efficient_config = self.config.config['efficient']
  38. self.efficient_config = efficient_config
  39. # common data
  40. self.bulitin_metric_list = self.config.builtinMetricList
  41. # dimension data
  42. self.weight_custom = efficient_config['weightCustom']
  43. self.metric_list = efficient_config['metric']
  44. self.type_list = efficient_config['type']
  45. self.type_name_dict = efficient_config['typeName']
  46. self.name_dict = efficient_config['name']
  47. self.unit_dict = efficient_config['unit']
  48. # custom metric data
  49. self.customMetricParam = efficient_config['customMetricParam']
  50. self.custom_metric_list = list(self.customMetricParam.keys())
  51. self.custom_data = custom_data
  52. self.custom_param_dict = {}
  53. # score data
  54. self.weight = efficient_config['weightDimension']
  55. self.weight_type_dict = efficient_config['typeWeight']
  56. self.weight_type_list = efficient_config['typeWeightList']
  57. self.weight_dict = efficient_config['weight']
  58. self.weight_list = efficient_config['weightList']
  59. self.priority_dict = efficient_config['priority']
  60. self.priority_list = efficient_config['priorityList']
  61. self.kind_dict = efficient_config['kind']
  62. self.optimal_dict = efficient_config['optimal']
  63. self.multiple_dict = efficient_config['multiple']
  64. self.kind_list = efficient_config['kindList']
  65. self.optimal_list = efficient_config['optimalList']
  66. self.multiple_list = efficient_config['multipleList']
  67. # metric data
  68. self.metric_dict = efficient_config['typeMetricDict']
  69. self.drive_metric_list = self.metric_dict['efficientDrive']
  70. self.stop_metric_list = self.metric_dict['efficientStop']
  71. # self.drive_metric_list = ["averageSpeed"]
  72. # self.stop_metric_list = ["stopDuration", "stopCount"]
  73. self._get_data()
  74. self._effi_param_cal()
  75. self.time_list = self.data['simTime'].values.tolist()
  76. self.value_dict = {}
  77. self.average_v = 0
  78. self.stop_count = 0
  79. self.stop_duration = 0
  80. self.pass_junction_time = 0
  81. self.score = 0
  82. def _get_data(self):
  83. """
  84. Get the data required for efficient evaluation according to efficient_INFO in DataInfoList.
  85. Parameters:
  86. df: Dataframe containing the vehicle running data.
  87. Returns:
  88. peak_valley: List of indices representing peaks and valleys.
  89. """
  90. efficient_info_list = DataInfoList.EFFICIENT_INFO
  91. self.df = self.data[efficient_info_list].copy()
  92. def _effi_param_cal(self):
  93. """
  94. """
  95. self.df = self.df[self.df['playerId'] == 1]
  96. # self.df = self.df[self.df['id'] == 1]
  97. # self.df['v'] = self.df.apply(lambda row: self.velocity(row['speed_x'], row['speed_y']), axis=1)
  98. # self.df['v'] = self.df.apply(lambda row: self.velocity(row['speedX'], row['speedY']), axis=1)
  99. def average_velocity(self):
  100. """
  101. 1.速度的平均值
  102. 2.平均速度 = 里程/时间
  103. 速度不为0为开始时间,速度为0为结束时间
  104. """
  105. self.average_v = self.df['v'].mean()
  106. def stop_duration_and_count(self):
  107. """
  108. 百公里停车次数
  109. 平均每次停车时长
  110. 驾照科目二考试判定为停车的标准:在考试项目区域内,汽车停顿2秒以上都算中途停车。
  111. """
  112. STOP_SPEED_THRESHOLD = 0.05
  113. STOP_TIME_THRESHOLD = 0.5 # 12.5帧
  114. stop_time_list = self.df[self.df['v'] <= STOP_SPEED_THRESHOLD]['simTime'].values.tolist()
  115. # stop_time_list = self.df[self.df['v'] == 0]['simTime'].values.tolist()
  116. stop_frame_list = self.df[self.df['v'] <= STOP_SPEED_THRESHOLD]['simFrame'].values.tolist()
  117. # stop_frame_list = self.df[self.df['v'] == 0]['simFrame'].values.tolist()
  118. FRAME_RANGE = 13
  119. stop_frame_group = []
  120. stop_time_group = []
  121. f1 = stop_frame_list[0] if stop_frame_list else 0
  122. t1 = stop_time_list[0] if stop_time_list else 0
  123. sum_stop_time = 0
  124. for i in range(1, len(stop_frame_list)):
  125. if stop_frame_list[i] - stop_frame_list[i - 1] != 1:
  126. f2 = stop_frame_list[i - 1]
  127. # 当帧数大于13时才确定为停车
  128. # 当时长大于0.5s才确定为停车
  129. if f2 - f1 >= FRAME_RANGE:
  130. t2 = stop_time_list[i - 1]
  131. stop_frame_group.append((f1, f2))
  132. stop_time_group.append((t1, t2))
  133. sum_stop_time += (t2 - t1)
  134. self.stop_count += 1
  135. # update f1, t1
  136. f1 = stop_frame_list[i]
  137. t1 = stop_time_list[i]
  138. f2 = stop_frame_list[-1] if stop_frame_list else 0
  139. # 如果最后一段的帧数差大于13,且停车统计列表中的最后一帧不为用例的最后一帧
  140. if f2 - f1 >= FRAME_RANGE and f2 != self.df['simFrame'].values.tolist()[-1]:
  141. t2 = stop_time_list[-1]
  142. stop_frame_group.append((f1, f2))
  143. stop_time_group.append((t1, t2))
  144. sum_stop_time += (t2 - t1)
  145. self.stop_count += 1
  146. self.stop_duration = sum_stop_time / self.stop_count if self.stop_count != 0 else 0
  147. # self.stop_count = self.stop_count / self.mileage * 1000000
  148. def pass_junction_time(self):
  149. pass
  150. def efficient_statistic(self):
  151. arr_effi = []
  152. self.average_velocity()
  153. self.stop_duration_and_count()
  154. if "averageSpeed" in self.metric_list:
  155. average_v = self.average_v
  156. arr_effi.append(average_v)
  157. self.value_dict["averageSpeed"] = average_v
  158. if "stopDuration" in self.metric_list:
  159. stop_duration = self.stop_duration
  160. arr_effi.append(stop_duration)
  161. self.value_dict["stopDuration"] = stop_duration
  162. if "stopCount" in self.metric_list:
  163. stop_count = self.stop_count
  164. arr_effi.append(stop_count)
  165. self.value_dict["stopCount"] = stop_count
  166. # arr_effi = [average_v, stop_count, stop_time]
  167. return arr_effi
  168. def custom_metric_param_parser(self, param_list):
  169. """
  170. param_dict = {
  171. "paramA" [
  172. {
  173. "kind": "-1",
  174. "optimal": "1",
  175. "multiple": ["0.5","5"],
  176. "spare1": null,
  177. "spare2": null
  178. }
  179. ]
  180. }
  181. """
  182. kind_list = []
  183. optimal_list = []
  184. multiple_list = []
  185. spare_list = []
  186. # spare1_list = []
  187. # spare2_list = []
  188. for i in range(len(param_list)):
  189. kind_list.append(int(param_list[i]['kind']))
  190. optimal_list.append(float(param_list[i]['optimal']))
  191. multiple_list.append([float(x) for x in param_list[i]['multiple']])
  192. spare_list.append([item["param"] for item in param_list[i]["spare"]])
  193. # spare1_list.append(param_list[i]['spare1'])
  194. # spare2_list.append(param_list[i]['spare2'])
  195. result = {
  196. "kind": kind_list,
  197. "optimal": optimal_list,
  198. "multiple": multiple_list,
  199. "spare": spare_list,
  200. # "spare1": spare1_list,
  201. # "spare2": spare2_list
  202. }
  203. return result
  204. def custom_metric_score(self, metric, value, param_list):
  205. """
  206. """
  207. param = self.custom_metric_param_parser(param_list)
  208. self.custom_param_dict[metric] = param
  209. score_model = self.scoreModel(param['kind'], param['optimal'], param['multiple'], np.array([value]))
  210. score_sub = score_model.cal_score()
  211. score = sum(score_sub) / len(score_sub)
  212. return score
  213. def effi_score(self):
  214. score_metric_dict = {}
  215. score_type_dict = {}
  216. arr_effi = self.efficient_statistic()
  217. print("\n[高效性表现及得分情况]")
  218. print("高效性各指标值:", [round(num, 2) for num in arr_effi])
  219. if arr_effi:
  220. arr_effi = np.array([arr_effi])
  221. score_model = self.scoreModel(self.kind_list, self.optimal_list, self.multiple_list, arr_effi)
  222. score_sub = score_model.cal_score()
  223. score_sub = list(map(lambda x: 80 if np.isnan(x) else x, score_sub))
  224. score_metric = [round(num, 2) for num in score_sub]
  225. metric_list = [x for x in self.metric_list if x in self.config.builtinMetricList]
  226. score_metric_dict = {key: value for key, value in zip(metric_list, score_metric)}
  227. for metric in self.custom_metric_list:
  228. value = self.custom_data[metric]['value']
  229. param_list = self.customMetricParam[metric]
  230. score = self.custom_metric_score(metric, value, param_list)
  231. score_metric_dict[metric] = round(score, 2)
  232. score_metric_dict = {key: score_metric_dict[key] for key in self.metric_list}
  233. score_metric = list(score_metric_dict.values())
  234. if self.weight_custom: # 自定义权重
  235. score_metric_with_weight_dict = {key: score_metric_dict[key] * self.weight_dict[key] for key in
  236. self.weight_dict}
  237. for type in self.type_list:
  238. type_score = sum(
  239. value for key, value in score_metric_with_weight_dict.items() if key in self.metric_dict[type])
  240. score_type_dict[type] = round(type_score, 2) if type_score < 100 else 100
  241. score_type_with_weight_dict = {key: score_type_dict[key] * self.weight_type_dict[key] for key in
  242. score_type_dict}
  243. score_efficient = sum(score_type_with_weight_dict.values())
  244. else: # 客观赋权
  245. self.weight_list = cal_weight_from_80(score_metric)
  246. self.weight_dict = {key: value for key, value in zip(self.metric_list, self.weight_list)}
  247. score_efficient = cal_score_with_priority(score_metric, self.weight_list, self.priority_list)
  248. for type in self.type_list:
  249. type_weight = sum(value for key, value in self.weight_dict.items() if key in self.metric_dict[type])
  250. for key, value in self.weight_dict.items():
  251. if key in self.metric_dict[type]:
  252. # self.weight_dict[key] = round(value / type_weight, 4)
  253. self.weight_dict[key] = value / type_weight
  254. type_score_metric = [value for key, value in score_metric_dict.items() if key in self.metric_dict[type]]
  255. type_weight_list = [value for key, value in self.weight_dict.items() if key in self.metric_dict[type]]
  256. type_priority_list = [value for key, value in self.priority_dict.items() if
  257. key in self.metric_dict[type]]
  258. type_score = cal_score_with_priority(type_score_metric, type_weight_list, type_priority_list)
  259. score_type_dict[type] = round(type_score, 2) if type_score < 100 else 100
  260. for key in self.weight_dict:
  261. self.weight_dict[key] = round(self.weight_dict[key], 4)
  262. score_type = list(score_type_dict.values())
  263. self.weight_type_list = cal_weight_from_80(score_type)
  264. self.weight_type_dict = {key: value for key, value in zip(self.type_list, self.weight_type_list)}
  265. score_efficient = round(score_efficient, 2)
  266. print("高效性各指标基准值:", self.optimal_list)
  267. print(f"高效性得分为:{score_efficient:.2f}分。")
  268. print(f"高效性各类型得分为:{score_type_dict}。")
  269. print(f"高效性各指标得分为:{score_metric_dict}。")
  270. return score_efficient, score_type_dict, score_metric_dict
  271. def effi_weight_distribution(self):
  272. # get weight distribution
  273. weight_distribution = {}
  274. weight_distribution["name"] = "高效性"
  275. if "efficientDrive" in self.type_list:
  276. drive_weight_indexes_dict = {key: f"{key}({value * 100:.2f}%)" for key, value in self.weight_dict.items() if
  277. key in self.drive_metric_list}
  278. weight_distribution_drive = {
  279. "driveWeight": f"行驶({self.weight_type_dict['efficientDrive'] * 100:.2f}%)",
  280. "indexes": drive_weight_indexes_dict
  281. }
  282. weight_distribution['efficientDrive'] = weight_distribution_drive
  283. if "efficientStop" in self.type_list:
  284. stop_weight_indexes_dict = {key: f"{key}({value * 100:.2f}%)" for key, value in self.weight_dict.items() if
  285. key in self.stop_metric_list}
  286. weight_distribution_stop = {
  287. "stopWeight": f"停车({self.weight_type_dict['efficientStop'] * 100:.2f}%)",
  288. "indexes": stop_weight_indexes_dict
  289. }
  290. weight_distribution['efficientStop'] = weight_distribution_stop
  291. return weight_distribution
  292. def _get_weight_distribution(self, dimension):
  293. # get weight distribution
  294. weight_distribution = {}
  295. weight_distribution["name"] = self.config.dimension_name[dimension]
  296. for type in self.type_list:
  297. type_weight_indexes_dict = {key: f"{self.name_dict[key]}({value * 100:.2f}%)" for key, value in
  298. self.weight_dict.items() if
  299. key in self.metric_dict[type]}
  300. weight_distribution_type = {
  301. "weight": f"{self.type_name_dict[type]}({self.weight_type_dict[type] * 100:.2f}%)",
  302. "indexes": type_weight_indexes_dict
  303. }
  304. weight_distribution[type] = weight_distribution_type
  305. return weight_distribution
  306. def report_statistic(self):
  307. """
  308. Returns:
  309. """
  310. # report_dict = {
  311. # "name": "高效性",
  312. # "weight": f"{self.weight * 100:.2f}%",
  313. # "weightDistribution": weight_distribution,
  314. # "score": score_efficient,
  315. # "level": grade_efficient,
  316. # 'score_type': score_type,
  317. # 'score_metric': score_metric,
  318. #
  319. # "description1": effi_description1,
  320. # "description2": effi_description2,
  321. # "description3": effi_description3,
  322. #
  323. # "efficientDrive": drive_dict,
  324. # "efficientStop": stop_dict,
  325. # }
  326. # brakePedal_list = self.data_processed.driver_ctrl_data['brakePedal_list']
  327. # throttlePedal_list = self.data_processed.driver_ctrl_data['throttlePedal_list']
  328. # steeringWheel_list = self.data_processed.driver_ctrl_data['steeringWheel_list']
  329. #
  330. # # common parameter calculate
  331. # brake_vs_time = self.zip_time_pairs(brakePedal_list, 100)
  332. # throttle_vs_time = self.zip_time_pairs(throttlePedal_list, 100)
  333. # steering_vs_time = self.zip_time_pairs(steeringWheel_list)
  334. report_dict = {
  335. "name": "高效性",
  336. "weight": f"{self.weight * 100:.2f}%",
  337. }
  338. # len_time = len(self.time_list)
  339. duration = self.time_list[-1]
  340. # duration_minute = round(duration / 60, 2)
  341. score_efficient, score_type_dict, score_metric_dict = self.effi_score()
  342. # get weight distribution
  343. report_dict["weightDistribution"] = self._get_weight_distribution("efficient")
  344. # score_efficient, score_metric = self.effi_score()
  345. score_efficient = int(score_efficient) if int(score_efficient) == score_efficient else round(score_efficient, 2)
  346. grade_efficient = score_grade(score_efficient)
  347. report_dict["score"] = score_efficient
  348. report_dict["level"] = grade_efficient
  349. # for description
  350. good_type_list = []
  351. bad_type_list = []
  352. good_metric_list = []
  353. bad_metric_list = []
  354. # str for description
  355. str_over_optimal = ""
  356. type_details_dict = {}
  357. for type in self.type_list:
  358. bad_type_list.append(type) if score_type_dict[type] < 80 else good_type_list.append(type)
  359. type_dict = {
  360. "name": f"{self.type_name_dict[type]}",
  361. }
  362. builtin_graph_dict = {}
  363. custom_graph_dict = {}
  364. score_type = score_type_dict[type]
  365. grade_type = score_grade(score_type)
  366. type_dict["score"] = score_type
  367. type_dict["level"] = grade_type
  368. type_dict_indexes = {}
  369. for metric in self.metric_dict[type]:
  370. bad_metric_list.append(metric) if score_metric_dict[metric] < 80 else good_metric_list.append(metric)
  371. if metric in self.bulitin_metric_list:
  372. # for indexes
  373. type_dict_indexes[metric] = {
  374. # "name": f"{self.name_dict[metric]}({self.unit_dict[metric]})",
  375. "name": f"{self.name_dict[metric]}",
  376. "score": score_metric_dict[metric],
  377. "value": f'{self.value_dict[metric]:.2f}',
  378. # "range": f"[0, {self.optimal_dict['averageSpeed']})",
  379. # "deviation": f"+{avv_deviation:.2f}%" if avv_deviation > 0 else f"{avv_deviation:.2f}%"
  380. }
  381. if self.kind_dict[metric] == -1:
  382. type_dict_indexes[metric]["range"] = f"[0, {self.optimal_dict[metric]}]"
  383. metric_over_optimal = ((self.value_dict[metric] - self.optimal_dict[metric]) /
  384. self.optimal_dict[
  385. metric]) * 100
  386. type_dict_indexes[metric][
  387. "deviation"] = f"+{metric_over_optimal:.2f}%" if metric_over_optimal > 0 else f"0%"
  388. elif self.kind_dict[metric] == 1:
  389. type_dict_indexes[metric]["range"] = f"[{self.optimal_dict[metric]}, inf)"
  390. metric_over_optimal = ((self.value_dict[metric] - self.optimal_dict[metric]) /
  391. self.optimal_dict[
  392. metric]) * 100
  393. type_dict_indexes[metric][
  394. "deviation"] = f"0%" if metric_over_optimal > 0 else f"{metric_over_optimal:.2f}%"
  395. elif self.kind_dict[metric] == 0:
  396. value = self.value_dict[metric]
  397. minn = self.optimal_dict[metric] * self.multiple_dict[metric][0]
  398. maxx = self.optimal_dict[metric] * self.multiple_dict[metric][1]
  399. type_dict_indexes[metric]["range"] = f"[{minn}, {maxx}]"
  400. if value < minn:
  401. metric_over_optimal = (value - minn) / minn * 100
  402. elif value > maxx:
  403. metric_over_optimal = (value - maxx) / maxx * 100
  404. else:
  405. metric_over_optimal = 0
  406. type_dict_indexes[metric][
  407. "deviation"] = f"+{metric_over_optimal:.2f}%" if metric_over_optimal > 0 else f"{metric_over_optimal:.2f}%"
  408. # metric_over_optimal = ((self.value_dict[metric] - self.optimal_dict[metric]) / self.optimal_dict[
  409. # metric]) * 100
  410. # type_dict_indexes[metric][
  411. # "deviation"] = f"+{metric_over_optimal:.2f}%" if metric_over_optimal > 0 else f"{metric_over_optimal:.2f}%"
  412. if score_metric_dict[metric] < 80:
  413. str_over_optimal += f'{self.name_dict[metric]}为{round(self.value_dict[metric], 2)}{self.unit_dict[metric]},超过合理范围{metric_over_optimal:.2f}%;'
  414. else:
  415. # for indexes
  416. type_dict_indexes[metric] = {
  417. # "name": f"{self.name_dict[metric]}({self.unit_dict[metric]})",
  418. "name": f"{self.name_dict[metric]}",
  419. "score": score_metric_dict[metric],
  420. "value": f'{self.custom_data[metric]["value"][0]:.2f}',
  421. # "range": f"[0, {self.optimal_dict['averageSpeed']})",
  422. # "deviation": f"+{avv_deviation}%" if avv_deviation > 0 else f"{avv_deviation}%"
  423. }
  424. value = self.custom_data[metric]["value"][0]
  425. optimal = self.custom_param_dict[metric]['optimal'][0]
  426. if self.custom_param_dict[metric]['kind'][0] == -1:
  427. type_dict_indexes[metric][
  428. "range"] = f"[0, {self.custom_param_dict[metric]['optimal'][0]}]"
  429. metric_over_optimal = (value - optimal) / optimal * 100
  430. type_dict_indexes[metric][
  431. "deviation"] = f"+{metric_over_optimal:.2f}%" if metric_over_optimal > 0 else f"0%"
  432. elif self.custom_param_dict[metric]['kind'][0] == 1:
  433. type_dict_indexes[metric][
  434. "range"] = f"[{self.custom_param_dict[metric]['optimal'][0]}, inf)"
  435. metric_over_optimal = (value - optimal) / optimal * 100
  436. type_dict_indexes[metric][
  437. "deviation"] = f"0%" if metric_over_optimal > 0 else f"{metric_over_optimal:.2f}%"
  438. elif self.custom_param_dict[metric]['kind'][0] == 0:
  439. minn = value * self.custom_param_dict[metric]['multiple'][0][0]
  440. maxx = value * self.custom_param_dict[metric]['multiple'][0][1]
  441. type_dict_indexes[metric]["range"] = f"[{minn}, {maxx}]"
  442. if value < minn:
  443. metric_over_optimal = (value - minn) / minn * 100
  444. elif value > maxx:
  445. metric_over_optimal = (value - maxx) / maxx * 100
  446. else:
  447. metric_over_optimal = 0
  448. type_dict_indexes[metric][
  449. "deviation"] = f"+{metric_over_optimal:.2f}%" if metric_over_optimal > 0 else f"{metric_over_optimal:.2f}%"
  450. # metric_over_optimal = ((self.custom_param_dict[metric]['optimal'][0] -
  451. # self.custom_data[metric]["value"][0]) /
  452. # self.custom_param_dict[metric]['optimal'][0]) * 100
  453. # type_dict_indexes[metric][
  454. # "deviation"] = f"+{metric_over_optimal:.2f}%" if metric_over_optimal > 0 else f"{metric_over_optimal:.2f}%"
  455. if score_metric_dict[metric] < 80:
  456. str_over_optimal += f'{self.name_dict[metric]}为{self.custom_data[metric]["value"][0]:.2f}{self.unit_dict[metric]},超过合理范围{metric_over_optimal:.2f}%;'
  457. custom_graph_dict[metric] = self.custom_data[metric]['reportData']
  458. # str_uncomf_over_optimal = str_uncomf_over_optimal[:-1] + ";"
  459. type_dict["indexes"] = type_dict_indexes
  460. type_dict["builtin"] = builtin_graph_dict
  461. type_dict["custom"] = custom_graph_dict
  462. type_details_dict[type] = type_dict
  463. report_dict["details"] = type_details_dict
  464. # efficient description
  465. str_over_optimal = str_over_optimal[:-1]
  466. if grade_efficient == '优秀':
  467. effi_description1 = '车辆行驶效率高;'
  468. elif grade_efficient == '良好':
  469. effi_description1 = '算法在本轮测试中的表现满足设计指标要求;'
  470. elif grade_efficient == '一般':
  471. str_ineffi_type = string_concatenate(bad_metric_list)
  472. effi_description1 = f'算法需要在{str_ineffi_type}指标上进一步优化。其中,{str_over_optimal};'
  473. elif grade_efficient == '较差':
  474. str_ineffi_type = string_concatenate(bad_metric_list)
  475. effi_description1 = f'需要提高算法在{str_ineffi_type}指标上的表现。其中,{str_over_optimal};'
  476. if not bad_metric_list:
  477. effi_description2 = '高效性在各个指标上的表现俱佳。'
  478. effi_description3 = "算法的规划控制能力良好,通行效率高。"
  479. else:
  480. str_effi_type = string_concatenate(good_metric_list)
  481. str_ineffi_type = string_concatenate(bad_metric_list)
  482. effi_description2 = f"{str_effi_type}指标表现良好,{str_ineffi_type}指标表现不佳。其中,{str_over_optimal}。"
  483. effi_description3 = "算法应该优化车辆的规划控制逻辑,提高算法的通行效率。"
  484. report_dict["description1"] = replace_key_with_value(effi_description1, self.name_dict)
  485. report_dict["description2"] = replace_key_with_value(effi_description2, self.name_dict)
  486. report_dict["description3"] = effi_description3
  487. # report_dict['commonData'] = {
  488. # "perData": [brake_vs_time, throttle_vs_time],
  489. # "angData": steering_vs_time,
  490. # }
  491. # report_dict = {
  492. # "name": "高效性",
  493. # "weight": f"{self.weight * 100:.2f}%",
  494. # "weightDistribution": weight_distribution,
  495. # "score": score_efficient,
  496. # "level": grade_efficient,
  497. # 'score_type': score_type,
  498. # 'score_metric': score_metric,
  499. #
  500. # "description1": effi_description1,
  501. # "description2": effi_description2,
  502. # "description3": effi_description3,
  503. #
  504. # "efficientDrive": drive_dict,
  505. # "efficientStop": stop_dict,
  506. # }
  507. return report_dict
  508. def get_eval_data(self):
  509. df = self.eval_data
  510. return df