object_crash_vehicle.py 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  1. #!/usr/bin/env python
  2. # This work is licensed under the terms of the MIT license.
  3. # For a copy, see <https://opensource.org/licenses/MIT>.
  4. """
  5. Object crash without prior vehicle action scenario:
  6. The scenario realizes the user controlled ego vehicle
  7. moving along the road and encountering a cyclist ahead.
  8. """
  9. from __future__ import print_function
  10. import math
  11. import py_trees
  12. import carla
  13. from srunner.scenariomanager.carla_data_provider import CarlaDataProvider
  14. from srunner.scenariomanager.scenarioatomics.atomic_behaviors import (ActorTransformSetter,
  15. ActorDestroy,
  16. AccelerateToVelocity,
  17. HandBrakeVehicle,
  18. KeepVelocity,
  19. StopVehicle)
  20. from srunner.scenariomanager.scenarioatomics.atomic_criteria import CollisionTest
  21. from srunner.scenariomanager.scenarioatomics.atomic_trigger_conditions import (InTriggerDistanceToLocationAlongRoute,
  22. InTimeToArrivalToVehicle,
  23. DriveDistance)
  24. from srunner.scenariomanager.timer import TimeOut
  25. from srunner.scenarios.basic_scenario import BasicScenario
  26. from srunner.tools.scenario_helper import get_location_in_distance_from_wp
  27. class StationaryObjectCrossing(BasicScenario):
  28. """
  29. This class holds everything required for a simple object crash
  30. without prior vehicle action involving a vehicle and a cyclist.
  31. The ego vehicle is passing through a road and encounters
  32. a stationary cyclist.
  33. This is a single ego vehicle scenario
  34. """
  35. def __init__(self, world, ego_vehicles, config, randomize=False, debug_mode=False, criteria_enable=True,
  36. timeout=60):
  37. """
  38. Setup all relevant parameters and create scenario
  39. """
  40. self._wmap = CarlaDataProvider.get_map()
  41. self._reference_waypoint = self._wmap.get_waypoint(config.trigger_points[0].location)
  42. # ego vehicle parameters
  43. self._ego_vehicle_distance_driven = 40
  44. # other vehicle parameters
  45. self._other_actor_target_velocity = 10
  46. # Timeout of scenario in seconds
  47. self.timeout = timeout
  48. super(StationaryObjectCrossing, self).__init__("Stationaryobjectcrossing",
  49. ego_vehicles,
  50. config,
  51. world,
  52. debug_mode,
  53. criteria_enable=criteria_enable)
  54. def _initialize_actors(self, config):
  55. """
  56. Custom initialization
  57. """
  58. _start_distance = 40
  59. lane_width = self._reference_waypoint.lane_width
  60. location, _ = get_location_in_distance_from_wp(self._reference_waypoint, _start_distance)
  61. waypoint = self._wmap.get_waypoint(location)
  62. offset = {"orientation": 270, "position": 90, "z": 0.4, "k": 0.2}
  63. position_yaw = waypoint.transform.rotation.yaw + offset['position']
  64. orientation_yaw = waypoint.transform.rotation.yaw + offset['orientation']
  65. offset_location = carla.Location(
  66. offset['k'] * lane_width * math.cos(math.radians(position_yaw)),
  67. offset['k'] * lane_width * math.sin(math.radians(position_yaw)))
  68. location += offset_location
  69. location.z += offset['z']
  70. self.transform = carla.Transform(location, carla.Rotation(yaw=orientation_yaw))
  71. static = CarlaDataProvider.request_new_actor('static.prop.container', self.transform)
  72. static.set_simulate_physics(True)
  73. self.other_actors.append(static)
  74. def _create_behavior(self):
  75. """
  76. Only behavior here is to wait
  77. """
  78. lane_width = self.ego_vehicles[0].get_world().get_map().get_waypoint(
  79. self.ego_vehicles[0].get_location()).lane_width
  80. lane_width = lane_width + (1.25 * lane_width)
  81. # leaf nodes
  82. actor_stand = TimeOut(15)
  83. actor_removed = ActorDestroy(self.other_actors[0])
  84. end_condition = DriveDistance(self.ego_vehicles[0], self._ego_vehicle_distance_driven)
  85. # non leaf nodes
  86. root = py_trees.composites.Parallel(
  87. policy=py_trees.common.ParallelPolicy.SUCCESS_ON_ONE)
  88. scenario_sequence = py_trees.composites.Sequence()
  89. # building tree
  90. root.add_child(scenario_sequence)
  91. scenario_sequence.add_child(ActorTransformSetter(self.other_actors[0], self.transform))
  92. scenario_sequence.add_child(actor_stand)
  93. scenario_sequence.add_child(actor_removed)
  94. scenario_sequence.add_child(end_condition)
  95. return root
  96. def _create_test_criteria(self):
  97. """
  98. A list of all test criteria will be created that is later used
  99. in parallel behavior tree.
  100. """
  101. criteria = []
  102. collision_criterion = CollisionTest(self.ego_vehicles[0])
  103. criteria.append(collision_criterion)
  104. return criteria
  105. def __del__(self):
  106. """
  107. Remove all actors upon deletion
  108. """
  109. self.remove_all_actors()
  110. class DynamicObjectCrossing(BasicScenario):
  111. """
  112. This class holds everything required for a simple object crash
  113. without prior vehicle action involving a vehicle and a cyclist/pedestrian,
  114. The ego vehicle is passing through a road,
  115. And encounters a cyclist/pedestrian crossing the road.
  116. This is a single ego vehicle scenario
  117. """
  118. def __init__(self, world, ego_vehicles, config, randomize=False,
  119. debug_mode=False, criteria_enable=True, adversary_type=False, timeout=60):
  120. """
  121. Setup all relevant parameters and create scenario
  122. """
  123. self._wmap = CarlaDataProvider.get_map()
  124. self._reference_waypoint = self._wmap.get_waypoint(config.trigger_points[0].location)
  125. # ego vehicle parameters
  126. self._ego_vehicle_distance_driven = 40
  127. # other vehicle parameters
  128. self._other_actor_target_velocity = 5
  129. self._other_actor_max_brake = 1.0
  130. self._time_to_reach = 10
  131. self._adversary_type = adversary_type # flag to select either pedestrian (False) or cyclist (True)
  132. self._walker_yaw = 0
  133. self._num_lane_changes = 1
  134. self.transform = None
  135. self.transform2 = None
  136. self.timeout = timeout
  137. self._trigger_location = config.trigger_points[0].location
  138. # Total Number of attempts to relocate a vehicle before spawning
  139. self._number_of_attempts = 20
  140. # Number of attempts made so far
  141. self._spawn_attempted = 0
  142. self._ego_route = CarlaDataProvider.get_ego_vehicle_route()
  143. super(DynamicObjectCrossing, self).__init__("DynamicObjectCrossing",
  144. ego_vehicles,
  145. config,
  146. world,
  147. debug_mode,
  148. criteria_enable=criteria_enable)
  149. def _calculate_base_transform(self, _start_distance, waypoint):
  150. lane_width = waypoint.lane_width
  151. # Patches false junctions
  152. if self._reference_waypoint.is_junction:
  153. stop_at_junction = False
  154. else:
  155. stop_at_junction = True
  156. location, _ = get_location_in_distance_from_wp(waypoint, _start_distance, stop_at_junction)
  157. waypoint = self._wmap.get_waypoint(location)
  158. offset = {"orientation": 270, "position": 90, "z": 0.6, "k": 1.0}
  159. position_yaw = waypoint.transform.rotation.yaw + offset['position']
  160. orientation_yaw = waypoint.transform.rotation.yaw + offset['orientation']
  161. offset_location = carla.Location(
  162. offset['k'] * lane_width * math.cos(math.radians(position_yaw)),
  163. offset['k'] * lane_width * math.sin(math.radians(position_yaw)))
  164. location += offset_location
  165. location.z = self._trigger_location.z + offset['z']
  166. return carla.Transform(location, carla.Rotation(yaw=orientation_yaw)), orientation_yaw
  167. def _spawn_adversary(self, transform, orientation_yaw):
  168. self._time_to_reach *= self._num_lane_changes
  169. if self._adversary_type is False:
  170. self._walker_yaw = orientation_yaw
  171. self._other_actor_target_velocity = 3 + (0.4 * self._num_lane_changes)
  172. walker = CarlaDataProvider.request_new_actor('walker.*', transform)
  173. adversary = walker
  174. else:
  175. self._other_actor_target_velocity = self._other_actor_target_velocity * self._num_lane_changes
  176. first_vehicle = CarlaDataProvider.request_new_actor('vehicle.diamondback.century', transform)
  177. first_vehicle.set_simulate_physics(enabled=False)
  178. adversary = first_vehicle
  179. return adversary
  180. def _spawn_blocker(self, transform, orientation_yaw):
  181. """
  182. Spawn the blocker prop that blocks the vision from the egovehicle of the jaywalker
  183. :return:
  184. """
  185. # static object transform
  186. shift = 0.9
  187. x_ego = self._reference_waypoint.transform.location.x
  188. y_ego = self._reference_waypoint.transform.location.y
  189. x_cycle = transform.location.x
  190. y_cycle = transform.location.y
  191. x_static = x_ego + shift * (x_cycle - x_ego)
  192. y_static = y_ego + shift * (y_cycle - y_ego)
  193. spawn_point_wp = self.ego_vehicles[0].get_world().get_map().get_waypoint(transform.location)
  194. self.transform2 = carla.Transform(carla.Location(x_static, y_static,
  195. spawn_point_wp.transform.location.z + 0.3),
  196. carla.Rotation(yaw=orientation_yaw + 180))
  197. static = CarlaDataProvider.request_new_actor('static.prop.vendingmachine', self.transform2)
  198. static.set_simulate_physics(enabled=False)
  199. return static
  200. def _initialize_actors(self, config):
  201. """
  202. Custom initialization
  203. """
  204. # cyclist transform
  205. _start_distance = 12
  206. # We start by getting and waypoint in the closest sidewalk.
  207. waypoint = self._reference_waypoint
  208. while True:
  209. wp_next = waypoint.get_right_lane()
  210. self._num_lane_changes += 1
  211. if wp_next is None or wp_next.lane_type == carla.LaneType.Sidewalk:
  212. break
  213. elif wp_next.lane_type == carla.LaneType.Shoulder:
  214. # Filter Parkings considered as Shoulders
  215. if wp_next.lane_width > 2:
  216. _start_distance += 1.5
  217. waypoint = wp_next
  218. break
  219. else:
  220. _start_distance += 1.5
  221. waypoint = wp_next
  222. while True: # We keep trying to spawn avoiding props
  223. try:
  224. self.transform, orientation_yaw = self._calculate_base_transform(_start_distance, waypoint)
  225. first_vehicle = self._spawn_adversary(self.transform, orientation_yaw)
  226. blocker = self._spawn_blocker(self.transform, orientation_yaw)
  227. break
  228. except RuntimeError as r:
  229. # We keep retrying until we spawn
  230. print("Base transform is blocking objects ", self.transform)
  231. _start_distance += 0.4
  232. self._spawn_attempted += 1
  233. if self._spawn_attempted >= self._number_of_attempts:
  234. raise r
  235. # Now that we found a possible position we just put the vehicle to the underground
  236. disp_transform = carla.Transform(
  237. carla.Location(self.transform.location.x,
  238. self.transform.location.y,
  239. self.transform.location.z - 500),
  240. self.transform.rotation)
  241. prop_disp_transform = carla.Transform(
  242. carla.Location(self.transform2.location.x,
  243. self.transform2.location.y,
  244. self.transform2.location.z - 500),
  245. self.transform2.rotation)
  246. first_vehicle.set_transform(disp_transform)
  247. blocker.set_transform(prop_disp_transform)
  248. first_vehicle.set_simulate_physics(enabled=False)
  249. blocker.set_simulate_physics(enabled=False)
  250. self.other_actors.append(first_vehicle)
  251. self.other_actors.append(blocker)
  252. def _create_behavior(self):
  253. """
  254. After invoking this scenario, cyclist will wait for the user
  255. controlled vehicle to enter trigger distance region,
  256. the cyclist starts crossing the road once the condition meets,
  257. then after 60 seconds, a timeout stops the scenario
  258. """
  259. root = py_trees.composites.Parallel(
  260. policy=py_trees.common.ParallelPolicy.SUCCESS_ON_ONE, name="OccludedObjectCrossing")
  261. lane_width = self._reference_waypoint.lane_width
  262. lane_width = lane_width + (1.25 * lane_width * self._num_lane_changes)
  263. dist_to_trigger = 12 + self._num_lane_changes
  264. # leaf nodes
  265. if self._ego_route is not None:
  266. start_condition = InTriggerDistanceToLocationAlongRoute(self.ego_vehicles[0],
  267. self._ego_route,
  268. self.transform.location,
  269. dist_to_trigger)
  270. else:
  271. start_condition = InTimeToArrivalToVehicle(self.ego_vehicles[0],
  272. self.other_actors[0],
  273. self._time_to_reach)
  274. actor_velocity = KeepVelocity(self.other_actors[0],
  275. self._other_actor_target_velocity,
  276. name="walker velocity")
  277. actor_drive = DriveDistance(self.other_actors[0],
  278. 0.5 * lane_width,
  279. name="walker drive distance")
  280. actor_start_cross_lane = AccelerateToVelocity(self.other_actors[0],
  281. 1.0,
  282. self._other_actor_target_velocity,
  283. name="walker crossing lane accelerate velocity")
  284. actor_cross_lane = DriveDistance(self.other_actors[0],
  285. lane_width,
  286. name="walker drive distance for lane crossing ")
  287. actor_stop_crossed_lane = StopVehicle(self.other_actors[0],
  288. self._other_actor_max_brake,
  289. name="walker stop")
  290. ego_pass_machine = DriveDistance(self.ego_vehicles[0],
  291. 5,
  292. name="ego vehicle passed prop")
  293. actor_remove = ActorDestroy(self.other_actors[0],
  294. name="Destroying walker")
  295. static_remove = ActorDestroy(self.other_actors[1],
  296. name="Destroying Prop")
  297. end_condition = DriveDistance(self.ego_vehicles[0],
  298. self._ego_vehicle_distance_driven,
  299. name="End condition ego drive distance")
  300. # non leaf nodes
  301. scenario_sequence = py_trees.composites.Sequence()
  302. keep_velocity_other = py_trees.composites.Parallel(
  303. policy=py_trees.common.ParallelPolicy.SUCCESS_ON_ONE, name="keep velocity other")
  304. keep_velocity = py_trees.composites.Parallel(
  305. policy=py_trees.common.ParallelPolicy.SUCCESS_ON_ONE, name="keep velocity")
  306. # building tree
  307. root.add_child(scenario_sequence)
  308. scenario_sequence.add_child(ActorTransformSetter(self.other_actors[0], self.transform,
  309. name='TransformSetterTS3walker'))
  310. scenario_sequence.add_child(ActorTransformSetter(self.other_actors[1], self.transform2,
  311. name='TransformSetterTS3coca', physics=False))
  312. scenario_sequence.add_child(HandBrakeVehicle(self.other_actors[0], True))
  313. scenario_sequence.add_child(start_condition)
  314. scenario_sequence.add_child(HandBrakeVehicle(self.other_actors[0], False))
  315. scenario_sequence.add_child(keep_velocity)
  316. scenario_sequence.add_child(keep_velocity_other)
  317. scenario_sequence.add_child(actor_stop_crossed_lane)
  318. scenario_sequence.add_child(actor_remove)
  319. scenario_sequence.add_child(static_remove)
  320. scenario_sequence.add_child(end_condition)
  321. keep_velocity.add_child(actor_velocity)
  322. keep_velocity.add_child(actor_drive)
  323. keep_velocity_other.add_child(actor_start_cross_lane)
  324. keep_velocity_other.add_child(actor_cross_lane)
  325. keep_velocity_other.add_child(ego_pass_machine)
  326. return root
  327. def _create_test_criteria(self):
  328. """
  329. A list of all test criteria will be created that is later used
  330. in parallel behavior tree.
  331. """
  332. criteria = []
  333. collision_criterion = CollisionTest(self.ego_vehicles[0])
  334. criteria.append(collision_criterion)
  335. return criteria
  336. def __del__(self):
  337. """
  338. Remove all actors upon deletion
  339. """
  340. self.remove_all_actors()