class_docstr: PIDLateralController implements lateral control using a PID.
docstr: Estimate the steering angle of the vehicle based on the PID equations
  
      :param waypoint: target waypoint
      :param vehicle_transform: current transform of the vehicle
      :return: steering control in the range [-1, 1]
docstr_tok: ["Estimate","the","steering","angle","of","the","vehicle","based","on","the","PID","equations",":","param","waypoint",":","target","waypoint",":","param","vehicle_transform",":","current","transform","of","the","vehicle",":","return",":","steering","control","in","the","range","[","-1",",","1","]"]
code: def _pid_control(self, waypoint, vehicle_transform):
      """
      Estimate the steering angle of the vehicle based on the PID equations
  
          :param waypoint: target waypoint
          :param vehicle_transform: current transform of the vehicle
          :return: steering control in the range [-1, 1]
      """
      # Get the ego's location and forward vector
      ego_loc = vehicle_transform.location
      v_vec = vehicle_transform.get_forward_vector()
      v_vec = np.array([v_vec.x, v_vec.y, 0.0])
  
      # Get the vector vehicle-target_wp
      if self._offset != 0:
          # Displace the wp to the side
          w_tran = waypoint.transform
          r_vec = w_tran.get_right_vector()
          w_loc = w_tran.location + carla.Location(
              x=self._offset * r_vec.x, y=self._offset * r_vec.y
          )
      else:
          w_loc = waypoint.transform.location
  
      w_vec = np.array([w_loc.x - ego_loc.x, w_loc.y - ego_loc.y, 0.0])
  
      wv_linalg = np.linalg.norm(w_vec) * np.linalg.norm(v_vec)
      if wv_linalg == 0:
          _dot = 1
      else:
          _dot = math.acos(
              np.clip(np.dot(w_vec, v_vec) / (wv_linalg), -1.0, 1.0)
          )
      _cross = np.cross(v_vec, w_vec)
      if _cross[2] < 0:
          _dot *= -1.0
  
      self._e_buffer.append(_dot)
      if len(self._e_buffer) >= 2:
          _de = (self._e_buffer[-1] - self._e_buffer[-2]) / self._dt
          _ie = sum(self._e_buffer) * self._dt
      else:
          _de = 0.0
          _ie = 0.0
  
      return np.clip(
          (self._k_p * _dot) + (self._k_d * _de) + (self._k_i * _ie),
          -1.0,
          1.0,
      )
  
imports: from collections import deque
  import math
  import numpy
  import carla
  from agents.tools.misc import get_speed
label_desc: Use image node_id 4 for calling the PIDLateralController obj's underlying member method code with example usage: obj._pid_control(waypoint, vehicle_transform) and returns: np