metrics_log.py 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428
  1. #!/usr/bin/env python
  2. # Copyright (c) 2020 Computer Vision Center (CVC) at the Universitat Autonoma de
  3. # Barcelona (UAB).
  4. #
  5. # This work is licensed under the terms of the MIT license.
  6. # For a copy, see <https://opensource.org/licenses/MIT>.
  7. """
  8. Support class of the MetricsManager to query the information available
  9. to the metrics.
  10. It also provides a series of functions to help the user querry
  11. specific information
  12. """
  13. import fnmatch
  14. from srunner.metrics.tools.metrics_parser import MetricsParser
  15. class MetricsLog(object): # pylint: disable=too-many-public-methods
  16. """
  17. Utility class to query the log.
  18. """
  19. def __init__(self, recorder):
  20. """
  21. Initializes the log class and parses it to extract the dictionaries.
  22. """
  23. # Parse the information
  24. parser = MetricsParser(recorder)
  25. self._simulation, self._actors, self._frames = parser.parse_recorder_info()
  26. ### Functions used to get general info of the simulation ###
  27. def get_actor_collisions(self, actor_id):
  28. """
  29. Returns a dict where the keys are the frame number and the values,
  30. a list of actor ids the actor collided with.
  31. Args:
  32. actor_id (int): ID of the actor.
  33. """
  34. actor_collisions = {}
  35. for i, frame in enumerate(self._frames):
  36. collisions = frame["events"]["collisions"]
  37. if actor_id in collisions:
  38. actor_collisions.update({i: collisions[actor_id]})
  39. return actor_collisions
  40. def get_total_frame_count(self):
  41. """
  42. Returns an int with the total amount of frames the simulation lasted.
  43. """
  44. return self._simulation["total_frames"]
  45. def get_elapsed_time(self, frame):
  46. """
  47. Returns a float with the elapsed time of a specific frame.
  48. """
  49. return self._frames[frame]["frame"]["elapsed_time"]
  50. def get_delta_time(self, frame):
  51. """
  52. Returns a float with the delta time of a specific frame.
  53. """
  54. return self._frames[frame]["frame"]["delta_time"]
  55. def get_platform_time(self, frame):
  56. """
  57. Returns a float with the platform time time of a specific frame.
  58. """
  59. return self._frames[frame]["frame"]["platform_time"]
  60. ### Functions used to get info about the actors ###
  61. def get_ego_vehicle_id(self):
  62. """
  63. Returns the id of the ego vehicle.
  64. """
  65. return self.get_actor_ids_with_role_name("hero")[0]
  66. def get_actor_ids_with_role_name(self, role_name):
  67. """
  68. Returns a list of actor ids that match the given role_name.
  69. Args:
  70. role_name (str): string with the desired role_name to filter the actors.
  71. """
  72. actor_list = []
  73. for actor_id in self._actors:
  74. actor = self._actors[actor_id]
  75. if "role_name" in actor and actor["role_name"] == role_name:
  76. actor_list.append(actor_id)
  77. return actor_list
  78. def get_actor_ids_with_type_id(self, type_id):
  79. """
  80. Returns a list of actor ids that match the given type_id, matching fnmatch standard.
  81. Args:
  82. type_id (str): string with the desired type id to filter the actors.
  83. """
  84. actor_list = []
  85. for actor_id in self._actors:
  86. actor = self._actors[actor_id]
  87. if "type_id" in actor and fnmatch.fnmatch(actor["type_id"], type_id):
  88. actor_list.append(actor_id)
  89. return actor_list
  90. def get_actor_attributes(self, actor_id):
  91. """
  92. Returns a dictionary with all the attributes of an actor.
  93. Args:
  94. actor_id (int): ID of the actor.
  95. """
  96. if actor_id in self._actors:
  97. return self._actors[actor_id]
  98. return None
  99. def get_actor_bounding_box(self, actor_id):
  100. """
  101. Returns the bounding box of the specified actor
  102. Args:
  103. actor_id (int): Id of the actor
  104. """
  105. if actor_id in self._actors:
  106. if "bounding_box" in self._actors[actor_id]:
  107. return self._actors[actor_id]["bounding_box"]
  108. return None
  109. return None
  110. def get_traffic_light_trigger_volume(self, traffic_light_id):
  111. """
  112. Returns the trigger volume of the specified traffic light
  113. Args:
  114. actor_id (int): Id of the traffic light
  115. """
  116. if traffic_light_id in self._actors:
  117. if "trigger_volume" in self._actors[traffic_light_id]:
  118. return self._actors[traffic_light_id]["trigger_volume"]
  119. return None
  120. return None
  121. def get_actor_alive_frames(self, actor_id):
  122. """
  123. Returns a tuple with the first and last frame an actor was alive.
  124. It is important to note that frames start at 1, not 0.
  125. Args:
  126. actor_id (int): Id of the actor
  127. """
  128. if actor_id in self._actors:
  129. actor_info = self._actors[actor_id]
  130. first_frame = actor_info["created"]
  131. if "destroyed" in actor_info:
  132. last_frame = actor_info["destroyed"] - 1
  133. else:
  134. last_frame = self.get_total_frame_count()
  135. return first_frame, last_frame
  136. return None, None
  137. ### Functions used to get the actor states ###
  138. def _get_actor_state(self, actor_id, state, frame):
  139. """
  140. Given an actor id, returns the specific variable of that actor at a given frame.
  141. Returns None if the actor_id or the state are missing.
  142. Args:
  143. actor_id (int): Id of the actor to be checked.
  144. frame: (int): frame number of the simulation.
  145. attribute (str): name of the actor's attribute to be returned.
  146. """
  147. frame_state = self._frames[frame - 1]["actors"]
  148. # Check if the actor exists
  149. if actor_id in frame_state:
  150. # Check if the state exists
  151. if state not in frame_state[actor_id]:
  152. return None
  153. state_info = frame_state[actor_id][state]
  154. return state_info
  155. return None
  156. def _get_all_actor_states(self, actor_id, state, first_frame=None, last_frame=None):
  157. """
  158. Given an actor id, returns a list of the specific variable of that actor during
  159. a frame interval. Some elements might be None.
  160. By default, first_frame and last_frame are the start and end of the simulation, respectively.
  161. Args:
  162. actor_id (int): ID of the actor.
  163. attribute: name of the actor's attribute to be returned.
  164. first_frame (int): First frame checked. By default, 0.
  165. last_frame (int): Last frame checked. By default, max number of frames.
  166. """
  167. if first_frame is None:
  168. first_frame = 1
  169. if last_frame is None:
  170. last_frame = self.get_total_frame_count()
  171. state_list = []
  172. for frame_number in range(first_frame, last_frame + 1):
  173. state_info = self._get_actor_state(actor_id, state, frame_number)
  174. state_list.append(state_info)
  175. return state_list
  176. def _get_states_at_frame(self, frame, state, actor_list=None):
  177. """
  178. Returns a dict where the keys are the frame number, and the values are the
  179. carla.Transform of the actor at the given frame.
  180. By default, all actors will be considered.
  181. """
  182. states = {}
  183. actor_info = self._frames[frame]["actors"]
  184. for actor_id in actor_info:
  185. if not actor_list:
  186. _state = self._get_actor_state(actor_id, state, frame)
  187. if _state:
  188. states.update({actor_id: _state})
  189. elif actor_id in actor_list:
  190. _state = self._get_actor_state(actor_id, state, frame)
  191. states.update({actor_id: _state})
  192. return states
  193. # Transforms
  194. def get_actor_transform(self, actor_id, frame):
  195. """
  196. Returns the transform of the actor at a given frame.
  197. """
  198. return self._get_actor_state(actor_id, "transform", frame)
  199. def get_all_actor_transforms(self, actor_id, first_frame=None, last_frame=None):
  200. """
  201. Returns a list with all the transforms of the actor at the frame interval.
  202. """
  203. return self._get_all_actor_states(actor_id, "transform", first_frame, last_frame)
  204. def get_actor_transforms_at_frame(self, frame, actor_list=None):
  205. """
  206. Returns a dictionary {int - carla.Transform} with the actor ID and transform
  207. at a given frame of all the actors at actor_list.
  208. """
  209. return self._get_states_at_frame(frame, "transform", actor_list)
  210. # Velocities
  211. def get_actor_velocity(self, actor_id, frame):
  212. """
  213. Returns the velocity of the actor at a given frame.
  214. """
  215. return self._get_actor_state(actor_id, "velocity", frame)
  216. def get_all_actor_velocities(self, actor_id, first_frame=None, last_frame=None):
  217. """
  218. Returns a list with all the velocities of the actor at the frame interval.
  219. """
  220. return self._get_all_actor_states(actor_id, "velocity", first_frame, last_frame)
  221. def get_actor_velocities_at_frame(self, frame, actor_list=None):
  222. """
  223. Returns a dictionary {int - carla.Vector3D} with the actor ID and velocity
  224. at a given frame of all the actors at actor_list.
  225. """
  226. return self._get_states_at_frame(frame, "velocity", actor_list)
  227. # Angular velocities
  228. def get_actor_angular_velocity(self, actor_id, frame):
  229. """
  230. Returns the angular velocity of the actor at a given frame.
  231. """
  232. return self._get_actor_state(actor_id, "angular_velocity", frame)
  233. def get_all_actor_angular_velocities(self, actor_id, first_frame=None, last_frame=None):
  234. """
  235. Returns a list with all the angular velocities of the actor at the frame interval.
  236. """
  237. return self._get_all_actor_states(actor_id, "angular_velocity", first_frame, last_frame)
  238. def get_actor_angular_velocities_at_frame(self, frame, actor_list=None):
  239. """
  240. Returns a dictionary {int - carla.Vector3D} with the actor ID and angular velocity
  241. at a given frame of all the actors at actor_list.
  242. """
  243. return self._get_states_at_frame(frame, "angular_velocity", actor_list)
  244. # Acceleration
  245. def get_actor_acceleration(self, actor_id, frame):
  246. """
  247. Returns the acceleration of the actor at a given frame.
  248. """
  249. return self._get_actor_state(actor_id, "acceleration", frame)
  250. def get_all_actor_accelerations(self, actor_id, first_frame=None, last_frame=None):
  251. """
  252. Returns a list with all the accelerations of the actor at the frame interval.
  253. """
  254. return self._get_all_actor_states(actor_id, "acceleration", first_frame, last_frame)
  255. def get_actor_accelerations_at_frame(self, frame, actor_list=None):
  256. """
  257. Returns a dictionary {int - carla.Vector3D} with the actor ID and angular velocity
  258. at a given frame of all the actors at actor_list.
  259. """
  260. return self._get_states_at_frame(frame, "acceleration", actor_list)
  261. # Controls
  262. def get_vehicle_control(self, vehicle_id, frame):
  263. """
  264. Returns the control of the vehicle at a given frame.
  265. """
  266. return self._get_actor_state(vehicle_id, "control", frame)
  267. def get_vehicle_physics_control(self, vehicle_id, frame):
  268. """
  269. Returns the carla.VehiclePhysicsControl of a vehicle at a given frame.
  270. Returns None if the id can't be found.
  271. """
  272. for i in range(frame - 1, -1, -1): # Go backwards from the frame until 0
  273. physics_info = self._frames[i]["events"]["physics_control"]
  274. if vehicle_id in physics_info:
  275. return physics_info[vehicle_id]
  276. return None
  277. def get_walker_speed(self, walker_id, frame):
  278. """
  279. Returns the speed of the walker at a specific frame.
  280. """
  281. return self._get_actor_state(walker_id, "speed", frame)
  282. # Traffic lights
  283. def get_traffic_light_state(self, traffic_light_id, frame):
  284. """
  285. Returns the state of the traffic light at a specific frame.
  286. """
  287. return self._get_actor_state(traffic_light_id, "state", frame)
  288. def is_traffic_light_frozen(self, traffic_light_id, frame):
  289. """
  290. Returns whether or not the traffic light is frozen at a specific frame.
  291. """
  292. return self._get_actor_state(traffic_light_id, "frozen", frame)
  293. def get_traffic_light_elapsed_time(self, traffic_light_id, frame):
  294. """
  295. Returns the elapsed time of the traffic light at a specific frame.
  296. """
  297. return self._get_actor_state(traffic_light_id, "elapsed_time", frame)
  298. def get_traffic_light_state_time(self, traffic_light_id, state, frame):
  299. """
  300. Returns the state time of the traffic light at a specific frame.
  301. Returns None if the id can't be found.
  302. """
  303. for i in range(frame - 1, -1, -1): # Go backwards from the frame until 0
  304. state_times_info = self._frames[i]["events"]["traffic_light_state_time"]
  305. if traffic_light_id in state_times_info:
  306. states = state_times_info[traffic_light_id]
  307. if state in states:
  308. return state_times_info[traffic_light_id][state]
  309. return None
  310. # Vehicle lights
  311. def get_vehicle_lights(self, vehicle_id, frame):
  312. """
  313. Returns the vehicle lights of the vehicle at a specific frame.
  314. """
  315. return self._get_actor_state(vehicle_id, "lights", frame)
  316. def is_vehicle_light_active(self, light, vehicle_id, frame):
  317. """
  318. Returns the elapsed time of the traffic light at a specific frame.
  319. """
  320. lights = self.get_vehicle_lights(vehicle_id, frame)
  321. if light in lights:
  322. return True
  323. return False
  324. # Scene lights
  325. def get_scene_light_state(self, light_id, frame):
  326. """
  327. Returns the state of the scene light at a specific frame.
  328. Returns None if the id can't be found.
  329. """
  330. for i in range(frame - 1, -1, -1): # Go backwards from the frame until 0
  331. scene_lights_info = self._frames[i]["events"]["scene_lights"]
  332. if light_id in scene_lights_info:
  333. return scene_lights_info[light_id]
  334. return None