class_docstr: BasicAgent implements an agent that navigates the scene.
  This agent respects traffic lights and other vehicles, but ignores stop signs.
  It has several functions available to specify the route that the agent must follow,
  as well as to change its parameters in case a different driving mode is desired.
class_docstr_tok: ["BasicAgent","implements","an","agent","that","navigates","the","scene",".","This","agent","respects","traffic","lights","and","other","vehicles",",","but","ignores","stop","signs",".","It","has","several","functions","available","to","specify","the","route","that","the","agent","must","follow",",","as","well","as","to","change","its","parameters","in","case","a","different","driving","mode","is","desired","."]
docstr: Method to check if there is a vehicle in front of the agent blocking its path.
  
      :param vehicle_list (list of carla.Vehicle): list contatining vehicle objects.
          If None, all vehicle in the scene are used
      :param max_distance: max freespace to check for obstacles.
          If None, the base threshold value is used
docstr_tok: ["Method","to","check","if","there","is","a","vehicle","in","front","of","the","agent","blocking","its","path",".",":","param","vehicle_list","(","list","of","carla.Vehicle",")",":","list","contatining","vehicle","objects",".","If","None",",","all","vehicle","in","the","scene","are","used",":","param","max_distance",":","max","freespace","to","check","for","obstacles",".","If","None",",","the","base","threshold","value","is","used"]
code: def _vehicle_obstacle_detected(
      self,
      vehicle_list=None,
      max_distance=None,
      up_angle_th=90,
      low_angle_th=0,
      lane_offset=0,
  ):
      """
      Method to check if there is a vehicle in front of the agent blocking its path.
  
          :param vehicle_list (list of carla.Vehicle): list contatining vehicle objects.
              If None, all vehicle in the scene are used
          :param max_distance: max freespace to check for obstacles.
              If None, the base threshold value is used
      """
  
      def get_route_polygon():
          route_bb = []
          extent_y = self._vehicle.bounding_box.extent.y
          r_ext = extent_y + self._offset
          l_ext = -extent_y + self._offset
          r_vec = ego_transform.get_right_vector()
          p1 = ego_location + carla.Location(
              r_ext * r_vec.x, r_ext * r_vec.y
          )
          p2 = ego_location + carla.Location(
              l_ext * r_vec.x, l_ext * r_vec.y
          )
          route_bb.extend([[p1.x, p1.y, p1.z], [p2.x, p2.y, p2.z]])
  
          for wp, _ in self._local_planner.get_plan():
              if (
                  ego_location.distance(wp.transform.location)
                  > max_distance
              ):
                  break
  
              r_vec = wp.transform.get_right_vector()
              p1 = wp.transform.location + carla.Location(
                  r_ext * r_vec.x, r_ext * r_vec.y
              )
              p2 = wp.transform.location + carla.Location(
                  l_ext * r_vec.x, l_ext * r_vec.y
              )
              route_bb.extend([[p1.x, p1.y, p1.z], [p2.x, p2.y, p2.z]])
  
          # Two points don't create a polygon, nothing to check
          if len(route_bb) < 3:
              return None
  
          return Polygon(route_bb)
  
      if self._ignore_vehicles:
          return (False, None, -1)
  
      if not vehicle_list:
          vehicle_list = self._world.get_actors().filter("*vehicle*")
  
      if not max_distance:
          max_distance = self._base_vehicle_threshold
  
      ego_transform = self._vehicle.get_transform()
      ego_location = ego_transform.location
      ego_wpt = self._map.get_waypoint(ego_location)
  
      # Get the right offset
      if ego_wpt.lane_id < 0 and lane_offset != 0:
          lane_offset *= -1
  
      # Get the transform of the front of the ego
      ego_front_transform = ego_transform
      ego_front_transform.location += carla.Location(
          self._vehicle.bounding_box.extent.x
          * ego_transform.get_forward_vector()
      )
  
      opposite_invasion = (
          abs(self._offset) + self._vehicle.bounding_box.extent.y
          > ego_wpt.lane_width / 2
      )
      use_bbs = (
          self._use_bbs_detection
          or opposite_invasion
          or ego_wpt.is_junction
      )
  
      # Get the route bounding box
      route_polygon = get_route_polygon()
  
      for target_vehicle in vehicle_list:
          if target_vehicle.id == self._vehicle.id:
              continue
  
          target_transform = target_vehicle.get_transform()
          if (
              target_transform.location.distance(ego_location)
              > max_distance
          ):
              continue
  
          target_wpt = self._map.get_waypoint(
              target_transform.location, lane_type=carla.LaneType.Any
          )
  
          # General approach for junctions and vehicles invading other lanes due to the offset
          if (use_bbs or target_wpt.is_junction) and route_polygon:
              target_bb = target_vehicle.bounding_box
              target_vertices = target_bb.get_world_vertices(
                  target_vehicle.get_transform()
              )
              target_list = [[v.x, v.y, v.z] for v in target_vertices]
              target_polygon = Polygon(target_list)
  
              if route_polygon.intersects(target_polygon):
                  return (
                      True,
                      target_vehicle,
                      compute_distance(
                          target_vehicle.get_location(), ego_location
                      ),
                  )
  
          # Simplified approach, using only the plan waypoints (similar to TM)
          else:
              if (
                  target_wpt.road_id != ego_wpt.road_id
                  or target_wpt.lane_id != ego_wpt.lane_id + lane_offset
              ):
                  next_wpt = self._local_planner.get_incoming_waypoint_and_direction(
                      steps=3
                  )[
                      0
                  ]
                  if not next_wpt:
                      continue
                  if (
                      target_wpt.road_id != next_wpt.road_id
                      or target_wpt.lane_id
                      != next_wpt.lane_id + lane_offset
                  ):
                      continue
  
              target_forward_vector = (
                  target_transform.get_forward_vector()
              )
              target_extent = target_vehicle.bounding_box.extent.x
              target_rear_transform = target_transform
              target_rear_transform.location -= carla.Location(
                  x=target_extent * target_forward_vector.x,
                  y=target_extent * target_forward_vector.y,
              )
  
              if is_within_distance(
                  target_rear_transform,
                  ego_front_transform,
                  max_distance,
                  [low_angle_th, up_angle_th],
              ):
                  return (
                      True,
                      target_vehicle,
                      compute_distance(
                          target_transform.location,
                          ego_transform.location,
                      ),
                  )
  
      return (False, None, -1)
  
imports: import carla
  from shapely.geometry import Polygon
  from agents.navigation.local_planner import LocalPlanner, RoadOption
  from agents.navigation.global_route_planner import GlobalRoutePlanner
  from agents.tools.misc import get_speed, is_within_distance, get_trafficlight_trigger_location, compute_distance
label_desc: Use image node_id 18 for calling the BasicAgent obj's underlying member method code with example usage: obj._vehicle_obstacle_detected(vehicle_list, max_distance, up_angle_th, low_angle_th, lane_offset) and returns: False,  None,  unknown, Polygon, False,  None,  unknown, None, True,  target_vehicle,  compute_distance, True,  target_vehicle,  compute_distance