maneuver_opposite_direction.py 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  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. Vehicle Maneuvering In Opposite Direction:
  6. Vehicle is passing another vehicle in a rural area, in daylight, under clear
  7. weather conditions, at a non-junction and encroaches into another
  8. vehicle traveling in the opposite direction.
  9. """
  10. from six.moves.queue import Queue # pylint: disable=relative-import,bad-option-value
  11. import math # pylint: disable=wrong-import-order
  12. import py_trees
  13. import carla
  14. from srunner.scenariomanager.carla_data_provider import CarlaDataProvider
  15. from srunner.scenariomanager.scenarioatomics.atomic_behaviors import (ActorTransformSetter,
  16. ActorDestroy,
  17. ActorSource,
  18. ActorSink,
  19. WaypointFollower)
  20. from srunner.scenariomanager.scenarioatomics.atomic_criteria import CollisionTest
  21. from srunner.scenariomanager.scenarioatomics.atomic_trigger_conditions import DriveDistance
  22. from srunner.scenarios.basic_scenario import BasicScenario
  23. from srunner.tools.scenario_helper import get_waypoint_in_distance
  24. class ManeuverOppositeDirection(BasicScenario):
  25. """
  26. "Vehicle Maneuvering In Opposite Direction" (Traffic Scenario 06)
  27. This is a single ego vehicle scenario
  28. """
  29. def __init__(self, world, ego_vehicles, config, randomize=False, debug_mode=False, criteria_enable=True,
  30. obstacle_type='barrier', timeout=120):
  31. """
  32. Setup all relevant parameters and create scenario
  33. obstacle_type -> flag to select type of leading obstacle. Values: vehicle, barrier
  34. """
  35. self._world = world
  36. self._map = CarlaDataProvider.get_map()
  37. self._first_vehicle_location = 50
  38. self._second_vehicle_location = self._first_vehicle_location + 60
  39. self._ego_vehicle_drive_distance = self._second_vehicle_location * 2
  40. self._start_distance = self._first_vehicle_location * 0.9
  41. self._opposite_speed = 5.56 # m/s
  42. self._source_gap = 40 # m
  43. self._reference_waypoint = self._map.get_waypoint(config.trigger_points[0].location)
  44. self._source_transform = None
  45. self._sink_location = None
  46. self._blackboard_queue_name = 'ManeuverOppositeDirection/actor_flow_queue'
  47. self._queue = py_trees.blackboard.Blackboard().set(self._blackboard_queue_name, Queue())
  48. self._obstacle_type = obstacle_type
  49. self._first_actor_transform = None
  50. self._second_actor_transform = None
  51. self._third_actor_transform = None
  52. # Timeout of scenario in seconds
  53. self.timeout = timeout
  54. super(ManeuverOppositeDirection, self).__init__(
  55. "ManeuverOppositeDirection",
  56. ego_vehicles,
  57. config,
  58. world,
  59. debug_mode,
  60. criteria_enable=criteria_enable)
  61. def _initialize_actors(self, config):
  62. """
  63. Custom initialization
  64. """
  65. first_actor_waypoint, _ = get_waypoint_in_distance(self._reference_waypoint, self._first_vehicle_location)
  66. second_actor_waypoint, _ = get_waypoint_in_distance(self._reference_waypoint, self._second_vehicle_location)
  67. second_actor_waypoint = second_actor_waypoint.get_left_lane()
  68. first_actor_transform = carla.Transform(
  69. first_actor_waypoint.transform.location,
  70. first_actor_waypoint.transform.rotation)
  71. if self._obstacle_type == 'vehicle':
  72. first_actor_model = 'vehicle.nissan.micra'
  73. else:
  74. first_actor_transform.rotation.yaw += 90
  75. first_actor_model = 'static.prop.streetbarrier'
  76. second_prop_waypoint = first_actor_waypoint.next(2.0)[0]
  77. position_yaw = second_prop_waypoint.transform.rotation.yaw + 90
  78. offset_location = carla.Location(
  79. 0.50 * second_prop_waypoint.lane_width * math.cos(math.radians(position_yaw)),
  80. 0.50 * second_prop_waypoint.lane_width * math.sin(math.radians(position_yaw)))
  81. second_prop_transform = carla.Transform(
  82. second_prop_waypoint.transform.location + offset_location, first_actor_transform.rotation)
  83. second_prop_actor = CarlaDataProvider.request_new_actor(first_actor_model, second_prop_transform)
  84. second_prop_actor.set_simulate_physics(True)
  85. first_actor = CarlaDataProvider.request_new_actor(first_actor_model, first_actor_transform)
  86. first_actor.set_simulate_physics(True)
  87. second_actor = CarlaDataProvider.request_new_actor('vehicle.audi.tt', second_actor_waypoint.transform)
  88. self.other_actors.append(first_actor)
  89. self.other_actors.append(second_actor)
  90. if self._obstacle_type != 'vehicle':
  91. self.other_actors.append(second_prop_actor)
  92. self._source_transform = second_actor_waypoint.transform
  93. sink_waypoint = second_actor_waypoint.next(1)[0]
  94. while not sink_waypoint.is_intersection:
  95. sink_waypoint = sink_waypoint.next(1)[0]
  96. self._sink_location = sink_waypoint.transform.location
  97. self._first_actor_transform = first_actor_transform
  98. self._second_actor_transform = second_actor_waypoint.transform
  99. self._third_actor_transform = second_prop_transform
  100. def _create_behavior(self):
  101. """
  102. The behavior tree returned by this method is as follows:
  103. The ego vehicle is trying to pass a leading vehicle in the same lane
  104. by moving onto the oncoming lane while another vehicle is moving in the
  105. opposite direction in the oncoming lane.
  106. """
  107. # Leaf nodes
  108. actor_source = ActorSource(
  109. ['vehicle.audi.tt', 'vehicle.tesla.model3', 'vehicle.nissan.micra'],
  110. self._source_transform, self._source_gap, self._blackboard_queue_name)
  111. actor_sink = ActorSink(self._sink_location, 10)
  112. ego_drive_distance = DriveDistance(self.ego_vehicles[0], self._ego_vehicle_drive_distance)
  113. waypoint_follower = WaypointFollower(
  114. self.other_actors[1], self._opposite_speed,
  115. blackboard_queue_name=self._blackboard_queue_name, avoid_collision=True)
  116. # Non-leaf nodes
  117. parallel_root = py_trees.composites.Parallel(policy=py_trees.common.ParallelPolicy.SUCCESS_ON_ONE)
  118. # Building tree
  119. parallel_root.add_child(ego_drive_distance)
  120. parallel_root.add_child(actor_source)
  121. parallel_root.add_child(actor_sink)
  122. parallel_root.add_child(waypoint_follower)
  123. scenario_sequence = py_trees.composites.Sequence()
  124. scenario_sequence.add_child(ActorTransformSetter(self.other_actors[0], self._first_actor_transform))
  125. scenario_sequence.add_child(ActorTransformSetter(self.other_actors[1], self._second_actor_transform))
  126. scenario_sequence.add_child(ActorTransformSetter(self.other_actors[2], self._third_actor_transform))
  127. scenario_sequence.add_child(parallel_root)
  128. scenario_sequence.add_child(ActorDestroy(self.other_actors[0]))
  129. scenario_sequence.add_child(ActorDestroy(self.other_actors[1]))
  130. scenario_sequence.add_child(ActorDestroy(self.other_actors[2]))
  131. return scenario_sequence
  132. def _create_test_criteria(self):
  133. """
  134. A list of all test criteria will be created that is later used
  135. in parallel behavior tree.
  136. """
  137. criteria = []
  138. collision_criterion = CollisionTest(self.ego_vehicles[0])
  139. criteria.append(collision_criterion)
  140. return criteria
  141. def __del__(self):
  142. """
  143. Remove all actors upon deletion
  144. """
  145. self.remove_all_actors()