carla_data_provider.py 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823
  1. #!/usr/bin/env python
  2. # Copyright (c) 2018-2020 Intel Corporation
  3. #
  4. # This work is licensed under the terms of the MIT license.
  5. # For a copy, see <https://opensource.org/licenses/MIT>.
  6. """
  7. This module provides all frequently used data from CARLA via
  8. local buffers to avoid blocking calls to CARLA
  9. """
  10. from __future__ import print_function
  11. import math
  12. import re
  13. from numpy import random
  14. from six import iteritems
  15. import carla
  16. def calculate_velocity(actor):
  17. """
  18. Method to calculate the velocity of a actor
  19. """
  20. velocity_squared = actor.get_velocity().x**2
  21. velocity_squared += actor.get_velocity().y**2
  22. return math.sqrt(velocity_squared)
  23. class CarlaDataProvider(object): # pylint: disable=too-many-public-methods
  24. """
  25. This class provides access to various data of all registered actors
  26. It buffers the data and updates it on every CARLA tick
  27. Currently available data:
  28. - Absolute velocity
  29. - Location
  30. - Transform
  31. Potential additions:
  32. - Acceleration
  33. In addition it provides access to the map and the transform of all traffic lights
  34. """
  35. _actor_velocity_map = {}
  36. _actor_location_map = {}
  37. _actor_transform_map = {}
  38. _traffic_light_map = {}
  39. _carla_actor_pool = {}
  40. _global_osc_parameters = {}
  41. _client = None
  42. _world = None
  43. _map = None
  44. _sync_flag = False
  45. _spawn_points = None
  46. _spawn_index = 0
  47. _blueprint_library = None
  48. _ego_vehicle_route = None
  49. _traffic_manager_port = 8000
  50. _random_seed = 2000
  51. _rng = random.RandomState(_random_seed)
  52. @staticmethod
  53. def register_actor(actor):
  54. """
  55. Add new actor to dictionaries
  56. If actor already exists, throw an exception
  57. """
  58. if actor in CarlaDataProvider._actor_velocity_map:
  59. raise KeyError(
  60. "Vehicle '{}' already registered. Cannot register twice!".format(actor.id))
  61. else:
  62. CarlaDataProvider._actor_velocity_map[actor] = 0.0
  63. if actor in CarlaDataProvider._actor_location_map:
  64. raise KeyError(
  65. "Vehicle '{}' already registered. Cannot register twice!".format(actor.id))
  66. else:
  67. CarlaDataProvider._actor_location_map[actor] = None
  68. if actor in CarlaDataProvider._actor_transform_map:
  69. raise KeyError(
  70. "Vehicle '{}' already registered. Cannot register twice!".format(actor.id))
  71. else:
  72. CarlaDataProvider._actor_transform_map[actor] = None
  73. @staticmethod
  74. def update_osc_global_params(parameters):
  75. """
  76. updates/initializes global osc parameters.
  77. """
  78. CarlaDataProvider._global_osc_parameters.update(parameters)
  79. @staticmethod
  80. def get_osc_global_param_value(ref):
  81. """
  82. returns updated global osc parameter value.
  83. """
  84. return CarlaDataProvider._global_osc_parameters.get(ref.replace("$", ""))
  85. @staticmethod
  86. def register_actors(actors):
  87. """
  88. Add new set of actors to dictionaries
  89. """
  90. for actor in actors:
  91. CarlaDataProvider.register_actor(actor)
  92. @staticmethod
  93. def on_carla_tick():
  94. """
  95. Callback from CARLA
  96. """
  97. for actor in CarlaDataProvider._actor_velocity_map:
  98. if actor is not None and actor.is_alive:
  99. CarlaDataProvider._actor_velocity_map[actor] = calculate_velocity(actor)
  100. for actor in CarlaDataProvider._actor_location_map:
  101. if actor is not None and actor.is_alive:
  102. CarlaDataProvider._actor_location_map[actor] = actor.get_location()
  103. for actor in CarlaDataProvider._actor_transform_map:
  104. if actor is not None and actor.is_alive:
  105. CarlaDataProvider._actor_transform_map[actor] = actor.get_transform()
  106. world = CarlaDataProvider._world
  107. if world is None:
  108. print("WARNING: CarlaDataProvider couldn't find the world")
  109. @staticmethod
  110. def get_velocity(actor):
  111. """
  112. returns the absolute velocity for the given actor
  113. """
  114. for key in CarlaDataProvider._actor_velocity_map:
  115. if key.id == actor.id:
  116. return CarlaDataProvider._actor_velocity_map[key]
  117. # We are intentionally not throwing here
  118. # This may cause exception loops in py_trees
  119. print('{}.get_velocity: {} not found!' .format(__name__, actor))
  120. return 0.0
  121. @staticmethod
  122. def get_location(actor):
  123. """
  124. returns the location for the given actor
  125. """
  126. for key in CarlaDataProvider._actor_location_map:
  127. if key.id == actor.id:
  128. return CarlaDataProvider._actor_location_map[key]
  129. # We are intentionally not throwing here
  130. # This may cause exception loops in py_trees
  131. print('{}.get_location: {} not found!' .format(__name__, actor))
  132. return None
  133. @staticmethod
  134. def get_transform(actor):
  135. """
  136. returns the transform for the given actor
  137. """
  138. for key in CarlaDataProvider._actor_transform_map:
  139. if key.id == actor.id:
  140. return CarlaDataProvider._actor_transform_map[key]
  141. # We are intentionally not throwing here
  142. # This may cause exception loops in py_trees
  143. print('{}.get_transform: {} not found!' .format(__name__, actor))
  144. return None
  145. @staticmethod
  146. def set_client(client):
  147. """
  148. Set the CARLA client
  149. """
  150. CarlaDataProvider._client = client
  151. @staticmethod
  152. def get_client():
  153. """
  154. Get the CARLA client
  155. """
  156. return CarlaDataProvider._client
  157. @staticmethod
  158. def set_world(world):
  159. """
  160. Set the world and world settings
  161. """
  162. CarlaDataProvider._world = world
  163. CarlaDataProvider._sync_flag = world.get_settings().synchronous_mode
  164. CarlaDataProvider._map = world.get_map()
  165. CarlaDataProvider._blueprint_library = world.get_blueprint_library()
  166. CarlaDataProvider.generate_spawn_points()
  167. CarlaDataProvider.prepare_map()
  168. @staticmethod
  169. def get_world():
  170. """
  171. Return world
  172. """
  173. return CarlaDataProvider._world
  174. @staticmethod
  175. def get_map(world=None):
  176. """
  177. Get the current map
  178. """
  179. if CarlaDataProvider._map is None:
  180. if world is None:
  181. if CarlaDataProvider._world is None:
  182. raise ValueError("class member \'world'\' not initialized yet")
  183. else:
  184. CarlaDataProvider._map = CarlaDataProvider._world.get_map()
  185. else:
  186. CarlaDataProvider._map = world.get_map()
  187. return CarlaDataProvider._map
  188. @staticmethod
  189. def is_sync_mode():
  190. """
  191. @return true if syncronuous mode is used
  192. """
  193. return CarlaDataProvider._sync_flag
  194. @staticmethod
  195. def find_weather_presets():
  196. """
  197. Get weather presets from CARLA
  198. """
  199. rgx = re.compile('.+?(?:(?<=[a-z])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])|$)')
  200. name = lambda x: ' '.join(m.group(0) for m in rgx.finditer(x))
  201. presets = [x for x in dir(carla.WeatherParameters) if re.match('[A-Z].+', x)]
  202. return [(getattr(carla.WeatherParameters, x), name(x)) for x in presets]
  203. @staticmethod
  204. def prepare_map():
  205. """
  206. This function set the current map and loads all traffic lights for this map to
  207. _traffic_light_map
  208. """
  209. if CarlaDataProvider._map is None:
  210. CarlaDataProvider._map = CarlaDataProvider._world.get_map()
  211. # Parse all traffic lights
  212. CarlaDataProvider._traffic_light_map.clear()
  213. for traffic_light in CarlaDataProvider._world.get_actors().filter('*traffic_light*'):
  214. if traffic_light not in CarlaDataProvider._traffic_light_map.keys():
  215. CarlaDataProvider._traffic_light_map[traffic_light] = traffic_light.get_transform()
  216. else:
  217. raise KeyError(
  218. "Traffic light '{}' already registered. Cannot register twice!".format(traffic_light.id))
  219. @staticmethod
  220. def annotate_trafficlight_in_group(traffic_light):
  221. """
  222. Get dictionary with traffic light group info for a given traffic light
  223. """
  224. dict_annotations = {'ref': [], 'opposite': [], 'left': [], 'right': []}
  225. # Get the waypoints
  226. ref_location = CarlaDataProvider.get_trafficlight_trigger_location(traffic_light)
  227. ref_waypoint = CarlaDataProvider.get_map().get_waypoint(ref_location)
  228. ref_yaw = ref_waypoint.transform.rotation.yaw
  229. group_tl = traffic_light.get_group_traffic_lights()
  230. for target_tl in group_tl:
  231. if traffic_light.id == target_tl.id:
  232. dict_annotations['ref'].append(target_tl)
  233. else:
  234. # Get the angle between yaws
  235. target_location = CarlaDataProvider.get_trafficlight_trigger_location(target_tl)
  236. target_waypoint = CarlaDataProvider.get_map().get_waypoint(target_location)
  237. target_yaw = target_waypoint.transform.rotation.yaw
  238. diff = (target_yaw - ref_yaw) % 360
  239. if diff > 330:
  240. continue
  241. elif diff > 225:
  242. dict_annotations['right'].append(target_tl)
  243. elif diff > 135.0:
  244. dict_annotations['opposite'].append(target_tl)
  245. elif diff > 30:
  246. dict_annotations['left'].append(target_tl)
  247. return dict_annotations
  248. @staticmethod
  249. def get_trafficlight_trigger_location(traffic_light): # pylint: disable=invalid-name
  250. """
  251. Calculates the yaw of the waypoint that represents the trigger volume of the traffic light
  252. """
  253. def rotate_point(point, angle):
  254. """
  255. rotate a given point by a given angle
  256. """
  257. x_ = math.cos(math.radians(angle)) * point.x - math.sin(math.radians(angle)) * point.y
  258. y_ = math.sin(math.radians(angle)) * point.x - math.cos(math.radians(angle)) * point.y
  259. return carla.Vector3D(x_, y_, point.z)
  260. base_transform = traffic_light.get_transform()
  261. base_rot = base_transform.rotation.yaw
  262. area_loc = base_transform.transform(traffic_light.trigger_volume.location)
  263. area_ext = traffic_light.trigger_volume.extent
  264. point = rotate_point(carla.Vector3D(0, 0, area_ext.z), base_rot)
  265. point_location = area_loc + carla.Location(x=point.x, y=point.y)
  266. return carla.Location(point_location.x, point_location.y, point_location.z)
  267. @staticmethod
  268. def update_light_states(ego_light, annotations, states, freeze=False, timeout=1000000000):
  269. """
  270. Update traffic light states
  271. """
  272. reset_params = []
  273. for state in states:
  274. relevant_lights = []
  275. if state == 'ego':
  276. relevant_lights = [ego_light]
  277. else:
  278. relevant_lights = annotations[state]
  279. for light in relevant_lights:
  280. prev_state = light.get_state()
  281. prev_green_time = light.get_green_time()
  282. prev_red_time = light.get_red_time()
  283. prev_yellow_time = light.get_yellow_time()
  284. reset_params.append({'light': light,
  285. 'state': prev_state,
  286. 'green_time': prev_green_time,
  287. 'red_time': prev_red_time,
  288. 'yellow_time': prev_yellow_time})
  289. light.set_state(states[state])
  290. if freeze:
  291. light.set_green_time(timeout)
  292. light.set_red_time(timeout)
  293. light.set_yellow_time(timeout)
  294. return reset_params
  295. @staticmethod
  296. def reset_lights(reset_params):
  297. """
  298. Reset traffic lights
  299. """
  300. for param in reset_params:
  301. param['light'].set_state(param['state'])
  302. param['light'].set_green_time(param['green_time'])
  303. param['light'].set_red_time(param['red_time'])
  304. param['light'].set_yellow_time(param['yellow_time'])
  305. @staticmethod
  306. def get_next_traffic_light(actor, use_cached_location=True):
  307. """
  308. returns the next relevant traffic light for the provided actor
  309. """
  310. if not use_cached_location:
  311. location = actor.get_transform().location
  312. else:
  313. location = CarlaDataProvider.get_location(actor)
  314. waypoint = CarlaDataProvider.get_map().get_waypoint(location)
  315. # Create list of all waypoints until next intersection
  316. list_of_waypoints = []
  317. while waypoint and not waypoint.is_intersection:
  318. list_of_waypoints.append(waypoint)
  319. waypoint = waypoint.next(2.0)[0]
  320. # If the list is empty, the actor is in an intersection
  321. if not list_of_waypoints:
  322. return None
  323. relevant_traffic_light = None
  324. distance_to_relevant_traffic_light = float("inf")
  325. for traffic_light in CarlaDataProvider._traffic_light_map:
  326. if hasattr(traffic_light, 'trigger_volume'):
  327. tl_t = CarlaDataProvider._traffic_light_map[traffic_light]
  328. transformed_tv = tl_t.transform(traffic_light.trigger_volume.location)
  329. distance = carla.Location(transformed_tv).distance(list_of_waypoints[-1].transform.location)
  330. if distance < distance_to_relevant_traffic_light:
  331. relevant_traffic_light = traffic_light
  332. distance_to_relevant_traffic_light = distance
  333. return relevant_traffic_light
  334. @staticmethod
  335. def set_ego_vehicle_route(route):
  336. """
  337. Set the route of the ego vehicle
  338. @todo extend ego_vehicle_route concept to support multi ego_vehicle scenarios
  339. """
  340. CarlaDataProvider._ego_vehicle_route = route
  341. @staticmethod
  342. def get_ego_vehicle_route():
  343. """
  344. returns the currently set route of the ego vehicle
  345. Note: Can be None
  346. """
  347. return CarlaDataProvider._ego_vehicle_route
  348. @staticmethod
  349. def generate_spawn_points():
  350. """
  351. Generate spawn points for the current map
  352. """
  353. spawn_points = list(CarlaDataProvider.get_map(CarlaDataProvider._world).get_spawn_points())
  354. CarlaDataProvider._rng.shuffle(spawn_points)
  355. CarlaDataProvider._spawn_points = spawn_points
  356. CarlaDataProvider._spawn_index = 0
  357. @staticmethod
  358. def create_blueprint(model, rolename='scenario', color=None, actor_category="car", safe=False):
  359. """
  360. Function to setup the blueprint of an actor given its model and other relevant parameters
  361. """
  362. _actor_blueprint_categories = {
  363. 'car': 'vehicle.tesla.model3',
  364. 'van': 'vehicle.volkswagen.t2',
  365. 'truck': 'vehicle.carlamotors.carlacola',
  366. 'trailer': '',
  367. 'semitrailer': '',
  368. 'bus': 'vehicle.volkswagen.t2',
  369. 'motorbike': 'vehicle.kawasaki.ninja',
  370. 'bicycle': 'vehicle.diamondback.century',
  371. 'train': '',
  372. 'tram': '',
  373. 'pedestrian': 'walker.pedestrian.0001',
  374. }
  375. # Set the model
  376. try:
  377. blueprints = CarlaDataProvider._blueprint_library.filter(model)
  378. blueprints_ = []
  379. if safe:
  380. for bp in blueprints:
  381. if bp.id.endswith('firetruck') or bp.id.endswith('ambulance') \
  382. or int(bp.get_attribute('number_of_wheels')) != 4:
  383. # Two wheeled vehicles take much longer to render + bicicles shouldn't behave like cars
  384. continue
  385. blueprints_.append(bp)
  386. else:
  387. blueprints_ = blueprints
  388. blueprint = CarlaDataProvider._rng.choice(blueprints_)
  389. except ValueError:
  390. # The model is not part of the blueprint library. Let's take a default one for the given category
  391. bp_filter = "vehicle.*"
  392. new_model = _actor_blueprint_categories[actor_category]
  393. if new_model != '':
  394. bp_filter = new_model
  395. print("WARNING: Actor model {} not available. Using instead {}".format(model, new_model))
  396. blueprint = CarlaDataProvider._rng.choice(CarlaDataProvider._blueprint_library.filter(bp_filter))
  397. # Set the color
  398. if color:
  399. if not blueprint.has_attribute('color'):
  400. print(
  401. "WARNING: Cannot set Color ({}) for actor {} due to missing blueprint attribute".format(
  402. color, blueprint.id))
  403. else:
  404. default_color_rgba = blueprint.get_attribute('color').as_color()
  405. default_color = '({}, {}, {})'.format(default_color_rgba.r, default_color_rgba.g, default_color_rgba.b)
  406. try:
  407. blueprint.set_attribute('color', color)
  408. except ValueError:
  409. # Color can't be set for this vehicle
  410. print("WARNING: Color ({}) cannot be set for actor {}. Using instead: ({})".format(
  411. color, blueprint.id, default_color))
  412. blueprint.set_attribute('color', default_color)
  413. else:
  414. if blueprint.has_attribute('color') and rolename != 'hero':
  415. color = CarlaDataProvider._rng.choice(blueprint.get_attribute('color').recommended_values)
  416. blueprint.set_attribute('color', color)
  417. # Make pedestrians mortal
  418. if blueprint.has_attribute('is_invincible'):
  419. blueprint.set_attribute('is_invincible', 'false')
  420. # Set the rolename
  421. if blueprint.has_attribute('role_name'):
  422. blueprint.set_attribute('role_name', rolename)
  423. return blueprint
  424. @staticmethod
  425. def handle_actor_batch(batch, tick=True):
  426. """
  427. Forward a CARLA command batch to spawn actors to CARLA, and gather the responses.
  428. Returns list of actors on success, none otherwise
  429. """
  430. sync_mode = CarlaDataProvider.is_sync_mode()
  431. actors = []
  432. if CarlaDataProvider._client:
  433. responses = CarlaDataProvider._client.apply_batch_sync(batch, sync_mode and tick)
  434. else:
  435. raise ValueError("class member \'client'\' not initialized yet")
  436. # Wait (or not) for the actors to be spawned properly before we do anything
  437. if not tick:
  438. pass
  439. elif sync_mode:
  440. CarlaDataProvider._world.tick()
  441. else:
  442. CarlaDataProvider._world.wait_for_tick()
  443. actor_ids = [r.actor_id for r in responses if not r.error]
  444. for r in responses:
  445. if r.error:
  446. print("WARNING: Not all actors were spawned")
  447. break
  448. actors = list(CarlaDataProvider._world.get_actors(actor_ids))
  449. return actors
  450. @staticmethod
  451. def request_new_actor(model, spawn_point, rolename='scenario', autopilot=False,
  452. random_location=False, color=None, actor_category="car",
  453. safe_blueprint=False, tick=True):
  454. """
  455. This method tries to create a new actor, returning it if successful (None otherwise).
  456. """
  457. blueprint = CarlaDataProvider.create_blueprint(model, rolename, color, actor_category, safe_blueprint)
  458. if random_location:
  459. actor = None
  460. while not actor:
  461. spawn_point = CarlaDataProvider._rng.choice(CarlaDataProvider._spawn_points)
  462. actor = CarlaDataProvider._world.try_spawn_actor(blueprint, spawn_point)
  463. else:
  464. # slightly lift the actor to avoid collisions with ground when spawning the actor
  465. # DO NOT USE spawn_point directly, as this will modify spawn_point permanently
  466. _spawn_point = carla.Transform(carla.Location(), spawn_point.rotation)
  467. _spawn_point.location.x = spawn_point.location.x
  468. _spawn_point.location.y = spawn_point.location.y
  469. _spawn_point.location.z = spawn_point.location.z + 0.2
  470. actor = CarlaDataProvider._world.try_spawn_actor(blueprint, _spawn_point)
  471. if actor is None:
  472. print("WARNING: Cannot spawn actor {} at position {}".format(model, spawn_point.location))
  473. return None
  474. # De/activate the autopilot of the actor if it belongs to vehicle
  475. if autopilot:
  476. if actor.type_id.startswith('vehicle.'):
  477. actor.set_autopilot(autopilot, CarlaDataProvider._traffic_manager_port)
  478. else:
  479. print("WARNING: Tried to set the autopilot of a non vehicle actor")
  480. # Wait for the actor to be spawned properly before we do anything
  481. if not tick:
  482. pass
  483. elif CarlaDataProvider.is_sync_mode():
  484. CarlaDataProvider._world.tick()
  485. else:
  486. CarlaDataProvider._world.wait_for_tick()
  487. CarlaDataProvider._carla_actor_pool[actor.id] = actor
  488. CarlaDataProvider.register_actor(actor)
  489. return actor
  490. @staticmethod
  491. def request_new_actors(actor_list, safe_blueprint=False, tick=True):
  492. """
  493. This method tries to series of actor in batch. If this was successful,
  494. the new actors are returned, None otherwise.
  495. param:
  496. - actor_list: list of ActorConfigurationData
  497. """
  498. SpawnActor = carla.command.SpawnActor # pylint: disable=invalid-name
  499. PhysicsCommand = carla.command.SetSimulatePhysics # pylint: disable=invalid-name
  500. FutureActor = carla.command.FutureActor # pylint: disable=invalid-name
  501. ApplyTransform = carla.command.ApplyTransform # pylint: disable=invalid-name
  502. SetAutopilot = carla.command.SetAutopilot # pylint: disable=invalid-name
  503. SetVehicleLightState = carla.command.SetVehicleLightState # pylint: disable=invalid-name
  504. batch = []
  505. CarlaDataProvider.generate_spawn_points()
  506. for actor in actor_list:
  507. # Get the blueprint
  508. blueprint = CarlaDataProvider.create_blueprint(
  509. actor.model, actor.rolename, actor.color, actor.category, safe_blueprint)
  510. # Get the spawn point
  511. transform = actor.transform
  512. if actor.random_location:
  513. if CarlaDataProvider._spawn_index >= len(CarlaDataProvider._spawn_points):
  514. print("No more spawn points to use")
  515. break
  516. else:
  517. _spawn_point = CarlaDataProvider._spawn_points[CarlaDataProvider._spawn_index] # pylint: disable=unsubscriptable-object
  518. CarlaDataProvider._spawn_index += 1
  519. else:
  520. _spawn_point = carla.Transform()
  521. _spawn_point.rotation = transform.rotation
  522. _spawn_point.location.x = transform.location.x
  523. _spawn_point.location.y = transform.location.y
  524. if blueprint.has_tag('walker'):
  525. # On imported OpenDRIVE maps, spawning of pedestrians can fail.
  526. # By increasing the z-value the chances of success are increased.
  527. map_name = CarlaDataProvider._map.name.split("/")[-1]
  528. if not map_name.startswith('OpenDrive'):
  529. _spawn_point.location.z = transform.location.z + 0.2
  530. else:
  531. _spawn_point.location.z = transform.location.z + 0.8
  532. else:
  533. _spawn_point.location.z = transform.location.z + 0.2
  534. # Get the command
  535. command = SpawnActor(blueprint, _spawn_point)
  536. command.then(SetAutopilot(FutureActor, actor.autopilot, CarlaDataProvider._traffic_manager_port))
  537. if actor.args is not None and 'physics' in actor.args and actor.args['physics'] == "off":
  538. command.then(ApplyTransform(FutureActor, _spawn_point)).then(PhysicsCommand(FutureActor, False))
  539. elif actor.category == 'misc':
  540. command.then(PhysicsCommand(FutureActor, True))
  541. if actor.args is not None and 'lights' in actor.args and actor.args['lights'] == "on":
  542. command.then(SetVehicleLightState(FutureActor, carla.VehicleLightState.All))
  543. batch.append(command)
  544. actors = CarlaDataProvider.handle_actor_batch(batch, tick)
  545. for actor in actors:
  546. if actor is None:
  547. continue
  548. CarlaDataProvider._carla_actor_pool[actor.id] = actor
  549. CarlaDataProvider.register_actor(actor)
  550. return actors
  551. @staticmethod
  552. def request_new_batch_actors(model, amount, spawn_points, autopilot=False,
  553. random_location=False, rolename='scenario',
  554. safe_blueprint=False, tick=True):
  555. """
  556. Simplified version of "request_new_actors". This method also create several actors in batch.
  557. Instead of needing a list of ActorConfigurationData, an "amount" parameter is used.
  558. This makes actor spawning easier but reduces the amount of configurability.
  559. Some parameters are the same for all actors (rolename, autopilot and random location)
  560. while others are randomized (color)
  561. """
  562. SpawnActor = carla.command.SpawnActor # pylint: disable=invalid-name
  563. SetAutopilot = carla.command.SetAutopilot # pylint: disable=invalid-name
  564. FutureActor = carla.command.FutureActor # pylint: disable=invalid-name
  565. CarlaDataProvider.generate_spawn_points()
  566. batch = []
  567. for i in range(amount):
  568. # Get vehicle by model
  569. blueprint = CarlaDataProvider.create_blueprint(model, rolename, safe=safe_blueprint)
  570. if random_location:
  571. if CarlaDataProvider._spawn_index >= len(CarlaDataProvider._spawn_points):
  572. print("No more spawn points to use. Spawned {} actors out of {}".format(i + 1, amount))
  573. break
  574. else:
  575. spawn_point = CarlaDataProvider._spawn_points[CarlaDataProvider._spawn_index] # pylint: disable=unsubscriptable-object
  576. CarlaDataProvider._spawn_index += 1
  577. else:
  578. try:
  579. spawn_point = spawn_points[i]
  580. except IndexError:
  581. print("The amount of spawn points is lower than the amount of vehicles spawned")
  582. break
  583. if spawn_point:
  584. batch.append(SpawnActor(blueprint, spawn_point).then(
  585. SetAutopilot(FutureActor, autopilot,
  586. CarlaDataProvider._traffic_manager_port)))
  587. actors = CarlaDataProvider.handle_actor_batch(batch, tick)
  588. for actor in actors:
  589. if actor is None:
  590. continue
  591. CarlaDataProvider._carla_actor_pool[actor.id] = actor
  592. CarlaDataProvider.register_actor(actor)
  593. return actors
  594. @staticmethod
  595. def get_actors():
  596. """
  597. Return list of actors and their ids
  598. Note: iteritems from six is used to allow compatibility with Python 2 and 3
  599. """
  600. return iteritems(CarlaDataProvider._carla_actor_pool)
  601. @staticmethod
  602. def actor_id_exists(actor_id):
  603. """
  604. Check if a certain id is still at the simulation
  605. """
  606. if actor_id in CarlaDataProvider._carla_actor_pool:
  607. return True
  608. return False
  609. @staticmethod
  610. def get_hero_actor():
  611. """
  612. Get the actor object of the hero actor if it exists, returns none otherwise.
  613. """
  614. for actor_id in CarlaDataProvider._carla_actor_pool:
  615. if CarlaDataProvider._carla_actor_pool[actor_id].attributes['role_name'] == 'hero':
  616. return CarlaDataProvider._carla_actor_pool[actor_id]
  617. return None
  618. @staticmethod
  619. def get_actor_by_id(actor_id):
  620. """
  621. Get an actor from the pool by using its ID. If the actor
  622. does not exist, None is returned.
  623. """
  624. if actor_id in CarlaDataProvider._carla_actor_pool:
  625. return CarlaDataProvider._carla_actor_pool[actor_id]
  626. print("Non-existing actor id {}".format(actor_id))
  627. return None
  628. @staticmethod
  629. def remove_actor_by_id(actor_id):
  630. """
  631. Remove an actor from the pool using its ID
  632. """
  633. if actor_id in CarlaDataProvider._carla_actor_pool:
  634. CarlaDataProvider._carla_actor_pool[actor_id].destroy()
  635. CarlaDataProvider._carla_actor_pool[actor_id] = None
  636. CarlaDataProvider._carla_actor_pool.pop(actor_id)
  637. else:
  638. print("Trying to remove a non-existing actor id {}".format(actor_id))
  639. @staticmethod
  640. def remove_actors_in_surrounding(location, distance):
  641. """
  642. Remove all actors from the pool that are closer than distance to the
  643. provided location
  644. """
  645. for actor_id in CarlaDataProvider._carla_actor_pool.copy():
  646. if CarlaDataProvider._carla_actor_pool[actor_id].get_location().distance(location) < distance:
  647. CarlaDataProvider._carla_actor_pool[actor_id].destroy()
  648. CarlaDataProvider._carla_actor_pool.pop(actor_id)
  649. # Remove all keys with None values
  650. CarlaDataProvider._carla_actor_pool = dict({k: v for k, v in CarlaDataProvider._carla_actor_pool.items() if v})
  651. @staticmethod
  652. def get_traffic_manager_port():
  653. """
  654. Get the port of the traffic manager.
  655. """
  656. return CarlaDataProvider._traffic_manager_port
  657. @staticmethod
  658. def set_traffic_manager_port(tm_port):
  659. """
  660. Set the port to use for the traffic manager.
  661. """
  662. CarlaDataProvider._traffic_manager_port = tm_port
  663. @staticmethod
  664. def cleanup():
  665. """
  666. Cleanup and remove all entries from all dictionaries
  667. """
  668. DestroyActor = carla.command.DestroyActor # pylint: disable=invalid-name
  669. batch = []
  670. for actor_id in CarlaDataProvider._carla_actor_pool.copy():
  671. actor = CarlaDataProvider._carla_actor_pool[actor_id]
  672. if actor is not None and actor.is_alive:
  673. batch.append(DestroyActor(actor))
  674. if CarlaDataProvider._client:
  675. try:
  676. CarlaDataProvider._client.apply_batch_sync(batch)
  677. except RuntimeError as e:
  678. if "time-out" in str(e):
  679. pass
  680. else:
  681. raise e
  682. CarlaDataProvider._actor_velocity_map.clear()
  683. CarlaDataProvider._actor_location_map.clear()
  684. CarlaDataProvider._actor_transform_map.clear()
  685. CarlaDataProvider._traffic_light_map.clear()
  686. CarlaDataProvider._map = None
  687. CarlaDataProvider._world = None
  688. CarlaDataProvider._sync_flag = False
  689. CarlaDataProvider._ego_vehicle_route = None
  690. CarlaDataProvider._carla_actor_pool = {}
  691. CarlaDataProvider._client = None
  692. CarlaDataProvider._spawn_points = None
  693. CarlaDataProvider._spawn_index = 0
  694. CarlaDataProvider._rng = random.RandomState(CarlaDataProvider._random_seed)