efficient.py 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751
  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 os
  15. import sys
  16. sys.path.append('../common')
  17. sys.path.append('../modules')
  18. sys.path.append('../results')
  19. import numpy as np
  20. import pandas as pd
  21. from data_info import DataInfoList
  22. from score_weight import cal_score_with_priority, cal_weight_from_80
  23. from common import score_grade, string_concatenate, replace_key_with_value
  24. import matplotlib.pyplot as plt
  25. threshold = 0.2
  26. class Efficient(object):
  27. """
  28. Class for achieving efficient metrics for autonomous driving.
  29. Attributes:
  30. df: Vehicle driving data, stored in dataframe format.
  31. """
  32. def __init__(self, data_processed, scoreModel, resultPath):
  33. self.eval_data = pd.DataFrame()
  34. self.data_processed = data_processed
  35. self.scoreModel = scoreModel
  36. self.resultPath = resultPath
  37. # self.data = data_processed.obj_data[1]
  38. self.data = data_processed.ego_df
  39. self.mileage = data_processed.report_info['mileage']
  40. self.df = pd.DataFrame()
  41. self.speed_dict = dict()
  42. self.config = data_processed.config
  43. efficient_config = self.config.config['efficient']
  44. print("efficient_config1 is", efficient_config)
  45. self.efficient_config = efficient_config
  46. # common data
  47. self.bulitin_metric_list = self.config.builtinMetricList
  48. # dimension data
  49. self.weight_custom = efficient_config['weightCustom']
  50. self.metric_list = efficient_config['metric']
  51. self.type_list = efficient_config['type']
  52. self.type_name_dict = efficient_config['typeName']
  53. self.name_dict = efficient_config['name']
  54. self.unit_dict = efficient_config['unit']
  55. # custom metric data
  56. self.customMetricParam = efficient_config['customMetricParam']
  57. self.custom_metric_list = list(self.customMetricParam.keys())
  58. # self.custom_data = custom_data
  59. self.custom_param_dict = {}
  60. # score data
  61. self.weight = efficient_config['weightDimension']
  62. self.weight_type_dict = efficient_config['typeWeight']
  63. self.weight_type_list = efficient_config['typeWeightList']
  64. self.weight_dict = efficient_config['weight']
  65. print("self.weight_dict is", self.weight_dict)
  66. self.weight_list = efficient_config['weightList']
  67. self.priority_dict = efficient_config['priority']
  68. self.priority_list = efficient_config['priorityList']
  69. self.kind_dict = efficient_config['kind']
  70. self.optimal_dict = efficient_config['optimal']
  71. self.multiple_dict = efficient_config['multiple']
  72. self.kind_list = efficient_config['kindList']
  73. print("efficient_config['optimalList'] is", efficient_config['optimalList'])
  74. self.optimal_list = efficient_config['optimalList']
  75. self.multiple_list = efficient_config['multipleList']
  76. # metric data
  77. self.metric_dict = efficient_config['typeMetricDict']
  78. self.drive_metric_list = self.metric_dict['efficientDrive']
  79. self.stop_metric_list = self.metric_dict['efficientStop']
  80. # self.drive_metric_list = ["averageSpeed"]
  81. # self.stop_metric_list = ["stopDuration", "stopCount"]
  82. self._get_data()
  83. self._effi_param_cal()
  84. self.time_list = self.data['simTime'].values.tolist()
  85. self.speed_list = list()
  86. self.value_dict = {}
  87. self.average_v = 0
  88. self.stop_count = 0
  89. self.stop_duration = 0
  90. self.sum_stop_time = 0
  91. self.start_stop_time = []
  92. self.obstacle_stop_count = 0
  93. self.obstacle_stop_time = 0
  94. self.obstacle_stop_duration = []
  95. self.obstacle_start_stop_time = []
  96. self.pass_junction_time = 0
  97. self.score = 0
  98. def _get_data(self):
  99. """
  100. Get the data required for efficient evaluation according to efficient_INFO in DataInfoList.
  101. Parameters:
  102. df: Dataframe containing the vehicle running data.
  103. Returns:
  104. peak_valley: List of indices representing peaks and valleys.
  105. """
  106. efficient_info_list = DataInfoList.EFFICIENT_INFO
  107. self.df = self.data[efficient_info_list].copy()
  108. def _effi_param_cal(self):
  109. """
  110. """
  111. self.df = self.df[self.df['playerId'] == 1]
  112. # self.df = self.df[self.df['id'] == 1]
  113. # self.df['v'] = self.df.apply(lambda row: self.velocity(row['speed_x'], row['speed_y']), axis=1)
  114. # self.df['v'] = self.df.apply(lambda row: self.velocity(row['speedX'], row['speedY']), axis=1)
  115. def _cal_max_min_avg(self, num_list):
  116. maxx = max(num_list) if num_list else "-"
  117. minn = min(num_list) if num_list else "-"
  118. avg = sum(num_list) / len(num_list) if num_list else "-"
  119. result = {
  120. "max": maxx,
  121. "min": minn,
  122. "avg": avg
  123. }
  124. return result
  125. def average_velocity(self):
  126. """
  127. 1.速度的平均值
  128. 2.平均速度 = 里程/时间
  129. 速度不为0为开始时间,速度为0为结束时间
  130. """
  131. self.average_v = self.df['v'].mean()
  132. self.speed_list = self.df['v'].values.tolist()
  133. self.speed_dict = self._cal_max_min_avg(self.df['v'].dropna().values.tolist())
  134. def stop_duration_and_count(self):
  135. """
  136. 百公里停车次数
  137. 平均每次停车时长
  138. 驾照科目二考试判定为停车的标准:在考试项目区域内,汽车停顿2秒以上都算中途停车。
  139. """
  140. stop_v_threshold = 0.01
  141. stop_time_threshold = 0.5 # 12.5帧
  142. without_obstacle = self.df[self.df['obstacle'] == 0].copy()
  143. stop_time_list = without_obstacle[without_obstacle['v'] <= stop_v_threshold]['simTime'].values.tolist()
  144. # stop_time_list = self.df[self.df['v'] == 0]['simTime'].values.tolist()
  145. stop_frame_list = without_obstacle[without_obstacle['v'] <= stop_v_threshold]['simFrame'].values.tolist()
  146. # stop_frame_list = self.df[self.df['v'] == 0]['simFrame'].values.tolist()
  147. stop_frame_group = []
  148. stop_time_group = []
  149. f1 = stop_frame_list[0] if stop_frame_list else 0
  150. t1 = stop_time_list[0] if stop_time_list else 0
  151. sum_stop_time = 0
  152. for i in range(1, len(stop_frame_list)):
  153. if stop_frame_list[i] - stop_frame_list[i - 1] != 1:
  154. f2 = stop_frame_list[i - 1]
  155. # 当帧数大于13时才确定为停车
  156. # 当时长大于0.5s才确定为停车
  157. if f2 - f1 >= 13:
  158. t2 = stop_time_list[i - 1]
  159. stop_frame_group.append((f1, f2))
  160. stop_time_group.append((t1, t2))
  161. self.start_stop_time.append(str("{:.02f}".format(t1)) + 's')
  162. sum_stop_time += (t2 - t1)
  163. self.stop_count += 1
  164. # update f1, t1
  165. f1 = stop_frame_list[i]
  166. t1 = stop_time_list[i]
  167. f2 = stop_frame_list[-1] if stop_frame_list else 0
  168. # 如果最后一段的帧数差大于13,且停车统计列表中的最后一帧不为用例的最后一帧
  169. if f2 - f1 >= 13 and f2 != self.df['simFrame'].values.tolist()[-1]:
  170. t2 = stop_time_list[-1]
  171. stop_frame_group.append((f1, f2))
  172. stop_time_group.append((t1, t2))
  173. self.start_stop_time.append(str(":.02f".format(t1)) + 's')
  174. sum_stop_time += (t2 - t1)
  175. self.stop_count += 1
  176. self.sum_stop_time = sum_stop_time
  177. self.stop_duration = sum_stop_time / self.stop_count if self.stop_count != 0 else 0
  178. # self.stop_count = self.stop_count / self.mileage * 1000000
  179. def obstacle_stop_duration_and_count(self):
  180. time_list = self.data[(self.data["obstacle"] == 1) & (abs(self.data["lon_v"]) < 0.01)]["simTime"].tolist()
  181. # 确保时间列表至少有两个元素
  182. if len(time_list) < 2:
  183. return [] # 或者可以抛出一个异常,因为没有足够的数据来比较
  184. # 初始化变量
  185. start_time = time_list[0] # 当前连续时间段的起始时间
  186. intervals = [] # 存储超过阈值的时间段信息
  187. # 遍历时间列表(从第二个元素开始)
  188. for i in range(1, len(time_list)):
  189. # 计算当前元素与前一个元素的差值
  190. difference = time_list[i] - time_list[i - 1]
  191. # 如果差值超过阈值,则记录前一个时间段的信息
  192. if difference > threshold:
  193. # 注意:这里我们返回的是前一个时间段的起始和终止时间(以及它们的差值)
  194. # 但按照题目要求,我们只返回差值
  195. # 终止时间是前一个元素,即 time_list[i-1]
  196. # 起始时间是之前记录的 start_time
  197. interval_length = time_list[i - 1] - start_time
  198. intervals.append((start_time, time_list[i - 1], interval_length))
  199. # 更新起始时间为当前元素,以便开始记录下一个时间段
  200. start_time = time_list[i]
  201. # 处理最后一个时间段(如果它存在且没有因为超过阈值而被记录)
  202. if time_list[-1] != start_time:
  203. # 注意:这里我们假设列表的最后一个元素之后没有更多的元素来比较
  204. # 因此,我们总是将最后一个元素视为前一个时间段的终止时间
  205. interval_length = time_list[-1] - start_time
  206. intervals.append((start_time, time_list[-1], interval_length))
  207. self.obstacle_stop_count = len(intervals)
  208. for start, end, length in intervals:
  209. self.obstacle_start_stop_time.append(str("{:.02f}".format(start)) + 's')
  210. self.obstacle_stop_duration.append(length)
  211. # 如果只需要差值,可以只返回差值的列表
  212. # return [interval[2] for interval in intervals]
  213. print("self.obstacle_start_stop_time is", self.obstacle_start_stop_time)
  214. self.obstacle_stop_time = sum(self.obstacle_stop_duration)/self.obstacle_stop_count if self.obstacle_stop_count > 0 else 0
  215. def efficient_statistic(self):
  216. arr_effi = []
  217. self.average_velocity()
  218. self.stop_duration_and_count()
  219. self.obstacle_stop_duration_and_count()
  220. if "averageSpeed" in self.metric_list:
  221. average_v = self.average_v
  222. arr_effi.append(average_v)
  223. self.value_dict["averageSpeed"] = average_v
  224. if "stopDuration" in self.metric_list:
  225. stop_duration = self.stop_duration
  226. arr_effi.append(stop_duration)
  227. self.value_dict["stopDuration"] = stop_duration
  228. if "obstaclestopDuration" in self.metric_list:
  229. obstacle_stop_duration = self.obstacle_stop_time
  230. arr_effi.append(obstacle_stop_duration)
  231. self.value_dict["obstaclestopDuration"] = obstacle_stop_duration
  232. if "stopCount" in self.metric_list:
  233. stop_count = self.stop_count
  234. arr_effi.append(stop_count)
  235. self.value_dict["stopCount"] = stop_count
  236. # arr_effi = [average_v, stop_count, stop_time]
  237. return arr_effi
  238. def custom_metric_param_parser(self, param_list):
  239. """
  240. param_dict = {
  241. "paramA" [
  242. {
  243. "kind": "-1",
  244. "optimal": "1",
  245. "multiple": ["0.5","5"],
  246. "spare1": null,
  247. "spare2": null
  248. }
  249. ]
  250. }
  251. """
  252. kind_list = []
  253. optimal_list = []
  254. multiple_list = []
  255. spare_list = []
  256. # spare1_list = []
  257. # spare2_list = []
  258. for i in range(len(param_list)):
  259. kind_list.append(int(param_list[i]['kind']))
  260. optimal_list.append(float(param_list[i]['optimal']))
  261. multiple_list.append([float(x) for x in param_list[i]['multiple']])
  262. spare_list.append([item["param"] for item in param_list[i]["spare"]])
  263. # spare1_list.append(param_list[i]['spare1'])
  264. # spare2_list.append(param_list[i]['spare2'])
  265. result = {
  266. "kind": kind_list,
  267. "optimal": optimal_list,
  268. "multiple": multiple_list,
  269. "spare": spare_list,
  270. # "spare1": spare1_list,
  271. # "spare2": spare2_list
  272. }
  273. return result
  274. def custom_metric_score(self, metric, value, param_list):
  275. """
  276. """
  277. param = self.custom_metric_param_parser(param_list)
  278. self.custom_param_dict[metric] = param
  279. score_model = self.scoreModel(param['kind'], param['optimal'], param['multiple'], np.array([value]))
  280. score_sub = score_model.cal_score()
  281. score = sum(score_sub) / len(score_sub)
  282. return score
  283. def effi_score(self):
  284. arr_effi = self.efficient_statistic()
  285. print("\n[高效性表现及得分情况]")
  286. print("高效性各指标值:", [round(num, 2) for num in arr_effi])
  287. arr_effi = np.array([arr_effi])
  288. print("self.optimal_list is", self.optimal_list)
  289. print("arr_effi is", arr_effi)
  290. score_model = self.scoreModel(self.kind_list, self.optimal_list, self.multiple_list, arr_effi)
  291. score_sub = score_model.cal_score()
  292. score_sub = list(map(lambda x: 80 if np.isnan(x) else x, score_sub))
  293. score_metric = [round(num, 2) for num in score_sub]
  294. metric_list = [x for x in self.metric_list if x in self.config.builtinMetricList]
  295. print("metric_list is", metric_list)
  296. score_metric_dict = {key: value for key, value in zip(metric_list, score_metric)}
  297. print("score_metric_dict is", score_metric_dict)
  298. # custom_metric_list = list(self.customMetricParam.keys())
  299. # for metric in custom_metric_list:
  300. # value = self.custom_data[metric]['value']
  301. # param_list = self.customMetricParam[metric]
  302. # score = self.custom_metric_score(metric, value, param_list)
  303. # score_metric_dict[metric] = round(score, 2)
  304. #
  305. # score_metric_dict = {key: score_metric_dict[key] for key in self.metric_list}
  306. # score_metric = list(score_metric_dict.values())
  307. score_type_dict = {}
  308. if self.weight_custom: # 自定义权重
  309. score_metric_with_weight_dict = {key: score_metric_dict[key] * self.weight_dict[key] for key in
  310. self.weight_dict}
  311. for type in self.type_list:
  312. type_score = sum(
  313. value for key, value in score_metric_with_weight_dict.items() if key in self.metric_dict[type])
  314. score_type_dict[type] = round(type_score, 2)
  315. score_type_with_weight_dict = {key: score_type_dict[key] * self.weight_type_dict[key] for key in
  316. score_type_dict}
  317. score_efficient = sum(score_type_with_weight_dict.values())
  318. else: # 客观赋权
  319. self.weight_list = cal_weight_from_80(score_metric)
  320. self.weight_dict = {key: value for key, value in zip(self.metric_list, self.weight_list)}
  321. score_efficient = cal_score_with_priority(score_metric, self.weight_list, self.priority_list)
  322. for type in self.type_list:
  323. type_weight = sum(value for key, value in self.weight_dict.items() if key in self.metric_dict[type])
  324. self.weight_dict = {key: round(value / type_weight, 4) for key, value in self.weight_dict.items() if
  325. key in self.metric_dict[type]}
  326. type_score_metric = [value for key, value in score_metric_dict.items() if key in self.metric_dict[type]]
  327. type_weight_list = [value for key, value in self.weight_dict.items() if key in self.metric_dict[type]]
  328. type_priority_list = [value for key, value in self.priority_dict.items() if
  329. key in self.metric_dict[type]]
  330. type_score = cal_score_with_priority(type_score_metric, type_weight_list, type_priority_list)
  331. score_type_dict[type] = round(type_score, 2)
  332. score_efficient = round(score_efficient, 2)
  333. print("高效性各指标基准值:", self.optimal_list)
  334. print(f"高效性得分为:{score_efficient:.2f}分。")
  335. print(f"高效性各类型得分为:{score_type_dict}。")
  336. print(f"高效性各指标得分为:{score_metric_dict}。")
  337. return score_efficient, score_type_dict, score_metric_dict
  338. def effi_weight_distribution(self):
  339. # get weight distribution
  340. weight_distribution = {}
  341. weight_distribution["name"] = "高效性"
  342. if "efficientDrive" in self.type_list:
  343. drive_weight_indexes_dict = {key: f"{key}({value * 100:.2f}%)" for key, value in self.weight_dict.items() if
  344. key in self.drive_metric_list}
  345. weight_distribution_drive = {
  346. "driveWeight": f"行驶({self.weight_type_dict['efficientDrive'] * 100:.2f}%)",
  347. "indexes": drive_weight_indexes_dict
  348. }
  349. weight_distribution['efficientDrive'] = weight_distribution_drive
  350. if "efficientStop" in self.type_list:
  351. stop_weight_indexes_dict = {key: f"{key}({value * 100:.2f}%)" for key, value in self.weight_dict.items() if
  352. key in self.stop_metric_list}
  353. weight_distribution_stop = {
  354. "stopWeight": f"停车({self.weight_type_dict['efficientStop'] * 100:.2f}%)",
  355. "indexes": stop_weight_indexes_dict
  356. }
  357. weight_distribution['efficientStop'] = weight_distribution_stop
  358. return weight_distribution
  359. def _get_weight_distribution(self, dimension):
  360. # get weight distribution
  361. weight_distribution = {}
  362. weight_distribution["name"] = self.config.dimension_name[dimension]
  363. for type in self.type_list:
  364. type_weight_indexes_dict = {key: f"{self.name_dict[key]}({value * 100:.2f}%)" for key, value in
  365. self.weight_dict.items() if
  366. key in self.metric_dict[type]}
  367. weight_distribution_type = {
  368. "weight": f"{self.type_name_dict[type]}({self.weight_type_dict[type] * 100:.2f}%)",
  369. "indexes": type_weight_indexes_dict
  370. }
  371. weight_distribution[type] = weight_distribution_type
  372. return weight_distribution
  373. def report_statistic(self):
  374. """
  375. Returns:
  376. """
  377. # report_dict = {
  378. # "name": "高效性",
  379. # "weight": f"{self.weight * 100:.2f}%",
  380. # "weightDistribution": weight_distribution,
  381. # "score": score_efficient,
  382. # "level": grade_efficient,
  383. # 'score_type': score_type,
  384. # 'score_metric': score_metric,
  385. #
  386. # "description1": effi_description1,
  387. # "description2": effi_description2,
  388. # "description3": effi_description3,
  389. #
  390. # "efficientDrive": drive_dict,
  391. # "efficientStop": stop_dict,
  392. # }
  393. # brakePedal_list = self.data_processed.driver_ctrl_data['brakePedal_list']
  394. # throttlePedal_list = self.data_processed.driver_ctrl_data['throttlePedal_list']
  395. # steeringWheel_list = self.data_processed.driver_ctrl_data['steeringWheel_list']
  396. #
  397. # # common parameter calculate
  398. # brake_vs_time = self.zip_time_pairs(brakePedal_list, 100)
  399. # throttle_vs_time = self.zip_time_pairs(throttlePedal_list, 100)
  400. # steering_vs_time = self.zip_time_pairs(steeringWheel_list)
  401. report_dict = {
  402. "name": "高效性",
  403. "weight": f"{self.weight * 100:.2f}%",
  404. }
  405. # len_time = len(self.time_list)
  406. # duration = self.time_list[-1]
  407. # duration_minute = round(duration / 60, 2)
  408. score_efficient, score_type_dict, score_metric_dict = self.effi_score()
  409. print("score_metric_dict is", score_metric_dict)
  410. # get weight distribution
  411. # report_dict["weightDistribution"] = self._get_weight_distribution("efficient")
  412. # score_efficient, score_metric = self.effi_score()
  413. score_efficient = int(score_efficient) if int(score_efficient) == score_efficient else round(score_efficient, 2)
  414. grade_efficient = score_grade(score_efficient)
  415. report_dict["score"] = score_efficient
  416. report_dict["level"] = grade_efficient
  417. # for description
  418. # good_type_list = []
  419. # bad_type_list = []
  420. # good_metric_list = []
  421. # bad_metric_list = []
  422. # str for description
  423. # str_over_optimal = ""
  424. # type_details_dict = {}
  425. # for type in self.type_list:
  426. # bad_type_list.append(type) if score_type_dict[type] < 80 else good_type_list.append(type)
  427. #
  428. # type_dict = {
  429. # "name": type,
  430. # }
  431. #
  432. # builtin_graph_dict = {}
  433. # custom_graph_dict = {}
  434. #
  435. # score_type = score_type_dict[type]
  436. # grade_type = score_grade(score_type)
  437. # type_dict["score"] = score_type
  438. # type_dict["level"] = grade_type
  439. #
  440. # type_dict_indexes = {}
  441. # for metric in self.metric_dict[type]:
  442. # bad_metric_list.append(metric) if score_metric_dict[metric] < 80 else good_metric_list.append(metric)
  443. #
  444. # if metric in self.bulitin_metric_list:
  445. # # for indexes
  446. # type_dict_indexes[metric] = {
  447. # "name": f"{self.name_dict[metric]}({self.unit_dict[metric]})",
  448. # "score": score_metric_dict[metric],
  449. # "value": f'{self.value_dict[metric]:.2f}',
  450. # # "range": f"[0, {self.optimal_dict['averageSpeed']})",
  451. # # "deviation": f"+{avv_deviation:.2f}%" if avv_deviation > 0 else f"{avv_deviation:.2f}%"
  452. # }
  453. #
  454. # if self.kind_dict[metric] == -1:
  455. # type_dict_indexes[metric]["range"] = f"[0, {self.optimal_dict[metric]}]"
  456. # metric_over_optimal = ((self.value_dict[metric] - self.optimal_dict[metric]) /
  457. # self.optimal_dict[
  458. # metric]) * 100
  459. # type_dict_indexes[metric][
  460. # "deviation"] = f"+{metric_over_optimal:.2f}%" if metric_over_optimal > 0 else f"0%"
  461. #
  462. # elif self.kind_dict[metric] == 1:
  463. # type_dict_indexes[metric]["range"] = f"[{self.optimal_dict[metric]}, inf)"
  464. # metric_over_optimal = ((self.value_dict[metric] - self.optimal_dict[metric]) /
  465. # self.optimal_dict[
  466. # metric]) * 100
  467. # type_dict_indexes[metric][
  468. # "deviation"] = f"0%" if metric_over_optimal > 0 else f"{metric_over_optimal:.2f}%"
  469. #
  470. # elif self.kind_dict[metric] == 0:
  471. # value = self.value_dict[metric]
  472. # minn = self.optimal_dict[metric] * self.multiple_dict[metric][0]
  473. # maxx = self.optimal_dict[metric] * self.multiple_dict[metric][1]
  474. #
  475. # type_dict_indexes[metric]["range"] = f"[{minn}, {maxx}]"
  476. #
  477. # if value < minn:
  478. # metric_over_optimal = (value - minn) / minn * 100
  479. # elif value > maxx:
  480. # metric_over_optimal = (value - maxx) / maxx * 100
  481. # else:
  482. # metric_over_optimal = 0
  483. #
  484. # type_dict_indexes[metric][
  485. # "deviation"] = f"+{metric_over_optimal:.2f}%" if metric_over_optimal > 0 else f"{metric_over_optimal:.2f}%"
  486. #
  487. # # metric_over_optimal = ((self.value_dict[metric] - self.optimal_dict[metric]) / self.optimal_dict[
  488. # # metric]) * 100
  489. # # type_dict_indexes[metric][
  490. # # "deviation"] = f"+{metric_over_optimal:.2f}%" if metric_over_optimal > 0 else f"{metric_over_optimal:.2f}%"
  491. #
  492. # if score_metric_dict[metric] < 80:
  493. # str_over_optimal += f'{self.name_dict[metric]}为{round(self.value_dict[metric], 2)}{self.unit_dict[metric]},超过合理范围{metric_over_optimal}%;'
  494. #
  495. # else:
  496. # # for indexes
  497. # type_dict_indexes[metric] = {
  498. # "name": f"{self.name_dict[metric]}({self.unit_dict[metric]})",
  499. # "score": score_metric_dict[metric],
  500. # "value": f'{self.custom_data[metric]["value"][0]:.2f}',
  501. # # "range": f"[0, {self.optimal_dict['averageSpeed']})",
  502. # # "deviation": f"+{avv_deviation}%" if avv_deviation > 0 else f"{avv_deviation}%"
  503. # }
  504. #
  505. # value = self.custom_data[metric]["value"][0]
  506. # optimal = self.custom_param_dict[metric]['optimal'][0]
  507. #
  508. # if self.custom_param_dict[metric]['kind'][0] == -1:
  509. # type_dict_indexes[metric][
  510. # "range"] = f"[0, {self.custom_param_dict[metric]['optimal'][0]}]"
  511. #
  512. # metric_over_optimal = (value - optimal) / optimal * 100
  513. # type_dict_indexes[metric][
  514. # "deviation"] = f"+{metric_over_optimal:.2f}%" if metric_over_optimal > 0 else f"0%"
  515. #
  516. # elif self.custom_param_dict[metric]['kind'][0] == 1:
  517. # type_dict_indexes[metric][
  518. # "range"] = f"[{self.custom_param_dict[metric]['optimal'][0]}, inf)"
  519. #
  520. # metric_over_optimal = (value - optimal) / optimal * 100
  521. # type_dict_indexes[metric][
  522. # "deviation"] = f"0%" if metric_over_optimal > 0 else f"{metric_over_optimal:.2f}%"
  523. #
  524. # elif self.custom_param_dict[metric]['kind'][0] == 0:
  525. # minn = value * self.custom_param_dict[metric]['multiple'][0][0]
  526. # maxx = value * self.custom_param_dict[metric]['multiple'][0][1]
  527. #
  528. # type_dict_indexes[metric]["range"] = f"[{minn}, {maxx}]"
  529. #
  530. # if value < minn:
  531. # metric_over_optimal = (value - minn) / minn * 100
  532. # elif value > maxx:
  533. # metric_over_optimal = (value - maxx) / maxx * 100
  534. # else:
  535. # metric_over_optimal = 0
  536. #
  537. # type_dict_indexes[metric][
  538. # "deviation"] = f"+{metric_over_optimal:.2f}%" if metric_over_optimal > 0 else f"{metric_over_optimal:.2f}%"
  539. #
  540. # # metric_over_optimal = ((self.custom_param_dict[metric]['optimal'][0] -
  541. # # self.custom_data[metric]["value"][0]) /
  542. # # self.custom_param_dict[metric]['optimal'][0]) * 100
  543. # # type_dict_indexes[metric][
  544. # # "deviation"] = f"+{metric_over_optimal:.2f}%" if metric_over_optimal > 0 else f"{metric_over_optimal:.2f}%"
  545. #
  546. # if score_metric_dict[metric] < 80:
  547. # str_over_optimal += f'{self.name_dict[metric]}为{self.custom_data[metric]["value"][0]:.2f}{self.unit_dict[metric]},超过合理范围{metric_over_optimal}%;'
  548. #
  549. # custom_graph_dict[metric] = self.custom_data[metric]['reportData']
  550. #
  551. # # str_uncomf_over_optimal = str_uncomf_over_optimal[:-1] + ";"
  552. # type_dict["indexes"] = type_dict_indexes
  553. # type_dict["builtin"] = builtin_graph_dict
  554. # type_dict["custom"] = custom_graph_dict
  555. #
  556. # type_details_dict[type] = type_dict
  557. # report_dict["details"] = type_details_dict
  558. # efficient description
  559. # str_over_optimal = str_over_optimal[:-1]
  560. # if grade_efficient == '优秀':
  561. # effi_description1 = '机器人行驶效率高;'
  562. # elif grade_efficient == '良好':
  563. # effi_description1 = '机器人在本轮测试中的表现满足设计指标要求;'
  564. # elif grade_efficient == '一般':
  565. # str_ineffi_type = string_concatenate(bad_metric_list)
  566. # effi_description1 = f'机器人需要在{str_ineffi_type}指标上进一步优化。其中,{str_over_optimal};'
  567. # elif grade_efficient == '较差':
  568. # str_ineffi_type = string_concatenate(bad_metric_list)
  569. # effi_description1 = f'需要提高机器人在{str_ineffi_type}指标上的表现。其中,{str_over_optimal};'
  570. #
  571. # if not bad_metric_list:
  572. # effi_description2 = '高效性在各个指标上的表现俱佳'
  573. # effi_description3 = "机器人的规划控制能力良好,通行效率高"
  574. # else:
  575. # str_effi_type = string_concatenate(good_metric_list)
  576. # str_ineffi_type = string_concatenate(bad_metric_list)
  577. #
  578. # effi_description2 = f"{str_effi_type}指标表现良好,{str_ineffi_type}指标表现不佳。其中,{str_over_optimal}"
  579. # effi_description3 = "应该优化机器人的规划控制逻辑,提高机器人的通行效率"
  580. # report_dict["description1"] = replace_key_with_value(effi_description1, self.name_dict)
  581. # report_dict["description2"] = replace_key_with_value(effi_description2, self.name_dict)
  582. # report_dict["description3"] = effi_description3
  583. description = f"· 在高效性方面,得分{score_efficient:.2f}分,表现{grade_efficient}。"
  584. if self.stop_count > 0:
  585. description += f"出现{self.stop_count}次无障碍物停止,需重点优化。" if score_efficient < 80 else f"出现{self.stop_count}次无障碍物停止,需注意。"
  586. else:
  587. description += f"平均速度{self.speed_dict['avg']:.02f}m/s,未出现无障碍物停止,表现{grade_efficient}。"
  588. report_dict["description"] = description
  589. str_temp_stop = "、".join(self.start_stop_time)
  590. description1 = f"次数:{self.stop_count}次\n"
  591. if self.stop_count == 0:
  592. description1 += "无障碍物时没有发生停车行为"
  593. else:
  594. description1 += (f"在{str_temp_stop}时刻发生无障碍物停车行为\n"
  595. f"停止总时长为{self.sum_stop_time:.02f}s,平均停止时长为{self.stop_duration:.02f}s")
  596. str_temp_obstaclestop = "、".join(self.obstacle_start_stop_time)
  597. description2 = f"次数:{self.obstacle_stop_count}次\n"
  598. if self.stop_count == 0:
  599. description2 += "没有发生遇到障碍物停止情况"
  600. else:
  601. description2 += (f"在{str_temp_obstaclestop}时刻发生遇障停止行为\n"
  602. f"停止总时长为{sum(self.obstacle_stop_duration):.02f}s,平均停止时长为{self.obstacle_stop_time:.02f}s")
  603. description3 = f"最大值:{self.speed_dict['max']:.4f}m/s;" \
  604. f"最小值:{self.speed_dict['min']:.4f}m/s;" \
  605. f"平均值:{self.speed_dict['avg']:.4f}m/s"
  606. stopDuration_index = {
  607. "weight": self.weight_dict['stopDuration'],
  608. "score": score_metric_dict['stopDuration'],
  609. "description": description1
  610. }
  611. obstaclestopDuration_index = {
  612. "weight": self.weight_dict['obstaclestopDuration'],
  613. "score": score_metric_dict['obstaclestopDuration'],
  614. "description": description2
  615. }
  616. averageSpeed_index = {
  617. "weight": self.weight_dict['averageSpeed'],
  618. "score": score_metric_dict['averageSpeed'],
  619. "description": description3
  620. }
  621. # report_dict["description1"] = description1
  622. # report_dict["description2"] = description2
  623. indexes_dict = {
  624. "efficientDrive": stopDuration_index,
  625. "averageSpeed": averageSpeed_index,
  626. "obstaclestopDuration": obstaclestopDuration_index
  627. }
  628. report_dict["indexes"] = indexes_dict
  629. # plt.figure(figsize=(12, 3))
  630. # plt.plot(self.time_list, self.speed_list, label='Speed')
  631. #
  632. # plt.xlabel('Time(s)')
  633. # plt.ylabel('Speed(m/s)')
  634. # plt.legend()
  635. #
  636. # # 调整布局,消除空白边界
  637. # plt.tight_layout()
  638. #
  639. # plt.savefig(os.path.join(self.resultPath, "Speed.png"))
  640. # plt.close()
  641. print(report_dict)
  642. return report_dict
  643. def get_eval_data(self):
  644. df = self.eval_data
  645. return df