text: #!/usr/bin/env python
  
  #
  # This work is licensed under the terms of the MIT license.
  # For a copy, see <https://opensource.org/licenses/MIT>.
  
  """
  Collection of traffic scenarios where the ego vehicle (hero)
  is making a right turn
  """
  
  from __future__ import print_function
  
  import sys
  
  import py_trees
  
  import carla
  from agents.navigation.local_planner import RoadOption
  
  from srunner.scenariomanager.carla_data_provider import CarlaDataProvider
  from srunner.scenariomanager.scenarioatomics.atomic_behaviors import (ActorTransformSetter,
                                                                        ActorDestroy,
                                                                        StopVehicle,
                                                                        SyncArrival,
                                                                        WaypointFollower, TrafficLightManipulator)
  from srunner.scenariomanager.scenarioatomics.atomic_criteria import CollisionTest
  from srunner.scenariomanager.scenarioatomics.atomic_trigger_conditions import DriveDistance, InTriggerDistanceToLocation
  from srunner.scenarios.basic_scenario import BasicScenario
  from srunner.tools.scenario_helper import (get_geometric_linear_intersection,
                                             get_crossing_point,
                                             generate_target_waypoint)
  
  
  class SignalizedJunctionRightTurn(BasicScenario):
  
      """
      Implementation class for Hero
      Vehicle turning right at signalized junction scenario,
      Traffic Scenario 09.
  
      This is a single ego vehicle scenario
      """
  
      def __init__(self, world, ego_vehicles, config, randomize=False, debug_mode=False, criteria_enable=True,
                   timeout=80):
          """
          Setup all relevant parameters and create scenario
          """
          self._target_vel = 6.9
          self._brake_value = 0.5
          self._ego_distance = 40
          self._traffic_light = None
          self._other_actor_transform = None
          # Timeout of scenario in seconds
          self.timeout = timeout
          super(SignalizedJunctionRightTurn, self).__init__("HeroActorTurningRightAtSignalizedJunction",
                                                            ego_vehicles,
                                                            config,
                                                            world,
                                                            debug_mode,
                                                            criteria_enable=criteria_enable)
  
          self._traffic_light = CarlaDataProvider.get_next_traffic_light(self.ego_vehicles[0], False)
          if self._traffic_light is None:
              print("No traffic light for the given location of the ego vehicle found")
              sys.exit(-1)
          self._traffic_light.set_state(carla.TrafficLightState.Red)
          self._traffic_light.set_red_time(self.timeout)
          # other vehicle's traffic light
          traffic_light_other = CarlaDataProvider.get_next_traffic_light(self.other_actors[0], False)
          if traffic_light_other is None:
              print("No traffic light for the given location of the other vehicle found")
              sys.exit(-1)
          traffic_light_other.set_state(carla.TrafficLightState.Green)
          traffic_light_other.set_green_time(self.timeout)
  
      def _initialize_actors(self, config):
          """
          Custom initialization
          """
          self._other_actor_transform = config.other_actors[0].transform
          first_vehicle_transform = carla.Transform(
              carla.Location(config.other_actors[0].transform.location.x,
                             config.other_actors[0].transform.location.y,
                             config.other_actors[0].transform.location.z - 500),
              config.other_actors[0].transform.rotation)
          first_vehicle = CarlaDataProvider.request_new_actor(config.other_actors[0].model, first_vehicle_transform)
          first_vehicle.set_simulate_physics(enabled=False)
          self.other_actors.append(first_vehicle)
  
      def _create_behavior(self):
          """
          Hero vehicle is turning right in an urban area,
          at a signalized intersection, while other actor coming straight
          from left.The hero actor may turn right either before other actor
          passes intersection or later, without any collision.
          After 80 seconds, a timeout stops the scenario.
          """
  
          location_of_collision_dynamic = get_geometric_linear_intersection(self.ego_vehicles[0], self.other_actors[0])
          crossing_point_dynamic = get_crossing_point(self.other_actors[0])
          sync_arrival = SyncArrival(
              self.other_actors[0], self.ego_vehicles[0], location_of_collision_dynamic)
          sync_arrival_stop = InTriggerDistanceToLocation(self.other_actors[0], crossing_point_dynamic, 5)
  
          sync_arrival_parallel = py_trees.composites.Parallel(
              "Synchronize arrival times",
              policy=py_trees.common.ParallelPolicy.SUCCESS_ON_ONE)
          sync_arrival_parallel.add_child(sync_arrival)
          sync_arrival_parallel.add_child(sync_arrival_stop)
  
          # Selecting straight path at intersection
          target_waypoint = generate_target_waypoint(
              CarlaDataProvider.get_map().get_waypoint(self.other_actors[0].get_location()), 0)
          # Generating waypoint list till next intersection
          plan = []
          wp_choice = target_waypoint.next(1.0)
          while not wp_choice[0].is_intersection:
              target_waypoint = wp_choice[0]
              plan.append((target_waypoint, RoadOption.LANEFOLLOW))
              wp_choice = target_waypoint.next(1.0)
  
          move_actor = WaypointFollower(self.other_actors[0], self._target_vel, plan=plan)
          waypoint_follower_end = InTriggerDistanceToLocation(
              self.other_actors[0], plan[-1][0].transform.location, 10)
  
          move_actor_parallel = py_trees.composites.Parallel(
              policy=py_trees.common.ParallelPolicy.SUCCESS_ON_ONE)
          move_actor_parallel.add_child(move_actor)
          move_actor_parallel.add_child(waypoint_follower_end)
  
          #manipulate traffic light
          manipulate_traffic_light = TrafficLightManipulator(self.ego_vehicles[0], "S7right")
          move_actor_parallel.add_child(manipulate_traffic_light)
  
          # stop other actor
          stop = StopVehicle(self.other_actors[0], self._brake_value)
          # end condition
          end_condition = DriveDistance(self.ego_vehicles[0], self._ego_distance)
  
          # Behavior tree
          sequence = py_trees.composites.Sequence()
          sequence.add_child(ActorTransformSetter(self.other_actors[0], self._other_actor_transform))
          sequence.add_child(sync_arrival_parallel)
          sequence.add_child(move_actor_parallel)
          sequence.add_child(stop)
          sequence.add_child(end_condition)
          sequence.add_child(ActorDestroy(self.other_actors[0]))
  
          return sequence
  
      def _create_test_criteria(self):
          """
          A list of all test criteria will be created that is later used
          in parallel behavior tree.
          """
          criteria = []
  
          collison_criteria = CollisionTest(self.ego_vehicles[0])
          criteria.append(collison_criteria)
  
          return criteria
  
      def __del__(self):
          self._traffic_light = None
          self.remove_all_actors()
  