Exemple #1
0
class LatControlPID():
    def __init__(self, CP):
        self.pid = LatPIDController(
            (CP.lateralTuning.pid.kpBP, CP.lateralTuning.pid.kpV),
            (CP.lateralTuning.pid.kiBP, CP.lateralTuning.pid.kiV),
            (CP.lateralTuning.pid.kdBP, CP.lateralTuning.pid.kdV),
            k_f=CP.lateralTuning.pid.kf,
            pos_limit=1.0,
            sat_limit=CP.steerLimitTimer)
        self.new_kf_tuned = CP.lateralTuning.pid.newKfTuned
        self.angle_steers_des = 0.

    def reset(self):
        self.pid.reset()

    def update(self, active, CS, CP, lat_plan):
        pid_log = log.ControlsState.LateralPIDState.new_message()
        pid_log.steeringAngleDeg = float(CS.steeringAngleDeg)
        pid_log.steeringRateDeg = float(CS.steeringRateDeg)

        if CS.vEgo < 0.3 or not active:
            output_steer = 0.0
            pid_log.active = False
            self.pid.reset()
        else:
            self.angle_steers_des = lat_plan.steeringAngleDeg  # get from MPC/LateralPlanner

            steers_max = get_steer_max(CP, CS.vEgo)
            self.pid.pos_limit = steers_max
            self.pid.neg_limit = -steers_max
            steer_feedforward = self.angle_steers_des  # feedforward desired angle
            if CP.steerControlType == car.CarParams.SteerControlType.torque:
                # TODO: feedforward something based on lat_plan.rateSteers
                steer_feedforward -= lat_plan.angleOffsetDeg  # subtract the offset, since it does not contribute to resistive torque
                if self.new_kf_tuned:
                    _c1, _c2, _c3 = 0.35189607550172824, 7.506201251644202, 69.226826411091
                    steer_feedforward *= _c1 * CS.vEgo**2 + _c2 * CS.vEgo + _c3
                else:
                    steer_feedforward *= CS.vEgo**2  # proportional to realigning tire momentum (~ lateral accel)
            deadzone = 0.0

            check_saturation = (
                CS.vEgo >
                10) and not CS.steeringRateLimited and not CS.steeringPressed
            output_steer = self.pid.update(self.angle_steers_des,
                                           CS.steeringAngleDeg,
                                           check_saturation=check_saturation,
                                           override=CS.steeringPressed,
                                           feedforward=steer_feedforward,
                                           speed=CS.vEgo,
                                           deadzone=deadzone)
            pid_log.active = True
            pid_log.p = self.pid.p
            pid_log.i = self.pid.i
            pid_log.f = self.pid.f
            pid_log.output = output_steer
            pid_log.saturated = bool(self.pid.saturated)

        return output_steer, float(self.angle_steers_des), pid_log
Exemple #2
0
 def __init__(self, CP):
     self.pid = LatPIDController(
         (CP.lateralTuning.pid.kpBP, CP.lateralTuning.pid.kpV),
         (CP.lateralTuning.pid.kiBP, CP.lateralTuning.pid.kiV),
         (CP.lateralTuning.pid.kdBP, CP.lateralTuning.pid.kdV),
         k_f=CP.lateralTuning.pid.kf,
         pos_limit=1.0,
         sat_limit=CP.steerLimitTimer)
     self.angle_steers_des = 0.
Exemple #3
0
 def __init__(self, CP):
     self.pid = LatPIDController(
         (CP.lateralTuning.pid.kpBP, CP.lateralTuning.pid.kpV),
         (CP.lateralTuning.pid.kiBP, CP.lateralTuning.pid.kiV),
         (CP.lateralTuning.pid.kdBP, CP.lateralTuning.pid.kdV),
         k_f=CP.lateralTuning.pid.kf,
         pos_limit=1.0,
         sat_limit=CP.steerLimitTimer)
     self.new_kf_tuned = CP.lateralTuning.pid.newKfTuned
     self.angle_steers_des = 0.
     self.mpc_frame = 0
     self.params = Params()
Exemple #4
0
 def __init__(self, CP):
     self.kegman = kegman_conf(CP)
     self.deadzone = float(self.kegman.conf['deadzone'])
     self.pid = LatPIDController(
         (CP.lateralTuning.pid.kpBP, CP.lateralTuning.pid.kpV),
         (CP.lateralTuning.pid.kiBP, CP.lateralTuning.pid.kiV),
         (CP.lateralTuning.pid.kdBP, CP.lateralTuning.pid.kdV),
         k_f=CP.lateralTuning.pid.kf,
         pos_limit=1.0,
         neg_limit=-1.0,
         sat_limit=CP.steerLimitTimer)
     self.angle_steers_des = 0.
     self.mpc_frame = 0
Exemple #5
0
 def live_tune(self, CP):
     self.mpc_frame += 1
     if self.mpc_frame % 300 == 0:
         self.steerKpV = float(int(self.params.get('PidKp')) * 0.01)
         self.steerKiV = float(int(self.params.get('PidKi')) * 0.001)
         self.steerKdV = float(int(self.params.get('PidKd')) * 0.01)
         self.steerKf = float(int(self.params.get('PidKf')) * 0.00001)
         self.pid = LatPIDController(
             (CP.lateralTuning.pid.kpBP, [0.1, self.steerKpV]),
             (CP.lateralTuning.pid.kiBP, [0.01, self.steerKiV]),
             (CP.lateralTuning.pid.kdBP, [self.steerKdV]),
             k_f=self.steerKf,
             pos_limit=1.0)
         self.mpc_frame = 0
 def __init__(self, CP):
     self.pid = LatPIDController(
         (CP.lateralTuning.pid.kpBP, CP.lateralTuning.pid.kpV),
         (CP.lateralTuning.pid.kiBP, CP.lateralTuning.pid.kiV),
         (CP.lateralTuning.pid.kdBP, CP.lateralTuning.pid.kdV),
         k_f=CP.lateralTuning.pid.kf,
         pos_limit=1.0,
         neg_limit=-1.0,
         sat_limit=CP.steerLimitTimer)
     self.angle_steers_des = 0.
     self.angle_steers_des_last = 0.
     self.angle_steer_rate = [0.6, 1.0]
     self.angleBP = [10., 25.]
     self.angle_steer_new = 0.0
class LatControlPID():
  def __init__(self, CP):
    self.pid = LatPIDController((CP.lateralTuning.pid.kpBP, CP.lateralTuning.pid.kpV),
                                (CP.lateralTuning.pid.kiBP, CP.lateralTuning.pid.kiV),
                                (CP.lateralTuning.pid.kdBP, CP.lateralTuning.pid.kdV),
                                k_f=CP.lateralTuning.pid.kf, pos_limit=1.0, neg_limit=-1.0,
                                sat_limit=CP.steerLimitTimer)

  def reset(self):
    self.pid.reset()

  def update(self, active, CS, CP, VM, params, desired_curvature, desired_curvature_rate):
    pid_log = log.ControlsState.LateralPIDState.new_message()
    pid_log.steeringAngleDeg = float(CS.steeringAngleDeg)
    pid_log.steeringRateDeg = float(CS.steeringRateDeg)

    angle_steers_des_no_offset = math.degrees(VM.get_steer_from_curvature(-desired_curvature, CS.vEgo))
    angle_steers_des = angle_steers_des_no_offset + params.angleOffsetDeg

    if CS.vEgo < 0.3 or not active or not CS.lkasEnable:
      output_steer = 0.0
      pid_log.active = False
      self.pid.reset()
    else:
      steers_max = get_steer_max(CP, CS.vEgo)
      self.pid.pos_limit = steers_max
      self.pid.neg_limit = -steers_max

      # TODO: feedforward something based on lat_plan.rateSteers
      steer_feedforward = angle_steers_des_no_offset  # offset does not contribute to resistive torque
      steer_feedforward *= CS.vEgo**2  # proportional to realigning tire momentum (~ lateral accel)
      #_c1, _c2, _c3 = [0.35189607550172824, 7.506201251644202, 69.226826411091]
      #steer_feedforward *= _c1 * CS.vEgo ** 2 + _c2 * CS.vEgo + _c3

      deadzone = 0.0

      check_saturation = (CS.vEgo > 10) and not CS.steeringRateLimited and not CS.steeringPressed
      output_steer = self.pid.update(angle_steers_des, CS.steeringAngleDeg, check_saturation=check_saturation, override=CS.steeringPressed,
                                     feedforward=steer_feedforward, speed=CS.vEgo, deadzone=deadzone)
      pid_log.active = True
      pid_log.p = self.pid.p
      pid_log.i = self.pid.i
      pid_log.f = self.pid.f
      pid_log.output = output_steer
      pid_log.saturated = bool(self.pid.saturated)

    return output_steer, angle_steers_des, pid_log
Exemple #8
0
    def __init__(self, CP):
        self.pid = LatPIDController(
            (CP.lateralTuning.pid.kpBP, CP.lateralTuning.pid.kpV),
            (CP.lateralTuning.pid.kiBP, CP.lateralTuning.pid.kiV),
            (CP.lateralTuning.pid.kdBP, CP.lateralTuning.pid.kdV),
            k_f=CP.lateralTuning.pid.kf,
            pos_limit=1.0,
            neg_limit=-1.0,
            sat_limit=CP.steerLimitTimer)
        self.new_kf_tuned = CP.lateralTuning.pid.newKfTuned
        self.mpc_frame = 0
        self.params = Params()

        self.live_tune_enabled = self.params.get_bool("OpkrLiveTune")
        self.dead_zone = float(
            Decimal(self.params.get("IgnoreZone", encoding="utf8")) *
            Decimal('0.1'))
Exemple #9
0
 def live_tune(self, CP):
     self.mpc_frame += 1
     if self.mpc_frame % 300 == 0:
         self.steerKpV = float(
             Decimal(self.params.get("PidKp", encoding="utf8")) *
             Decimal('0.01'))
         self.steerKiV = float(
             Decimal(self.params.get("PidKi", encoding="utf8")) *
             Decimal('0.001'))
         self.steerKdV = float(
             Decimal(self.params.get("PidKd", encoding="utf8")) *
             Decimal('0.01'))
         self.steerKf = float(
             Decimal(self.params.get("PidKf", encoding="utf8")) *
             Decimal('0.00001'))
         self.pid = LatPIDController(
             (CP.lateralTuning.pid.kpBP, [0.1, self.steerKpV]),
             (CP.lateralTuning.pid.kiBP, [0.01, self.steerKiV]),
             (CP.lateralTuning.pid.kdBP, [self.steerKdV]),
             k_f=self.steerKf,
             pos_limit=1.0)
         self.mpc_frame = 0
class LatControlPID():
    def __init__(self, CP):
        self.kegman = kegman_conf(CP)
        self.deadzone = float(self.kegman.conf['deadzone'])
        self.pid = LatPIDController(
            (CP.lateralTuning.pid.kpBP, CP.lateralTuning.pid.kpV),
            (CP.lateralTuning.pid.kiBP, CP.lateralTuning.pid.kiV),
            (CP.lateralTuning.pid.kdBP, CP.lateralTuning.pid.kdV),
            k_f=CP.lateralTuning.pid.kf,
            pos_limit=1.0,
            neg_limit=-1.0,
            sat_limit=CP.steerLimitTimer)
        self.angle_steers_des = 0.
        self.angle_steers_des_last = 0.
        self.mpc_frame = 0

    def reset(self):
        self.pid.reset()

    def live_tune(self, CP):
        self.mpc_frame += 1
        if self.mpc_frame % 300 == 0:
            # live tuning through /data/openpilot/tune.py overrides interface.py settings
            self.kegman = kegman_conf()
            if self.kegman.conf['tuneGernby'] == "1":
                #self.steerKpV = [float(self.kegman.conf['Kp'])]
                #self.steerKiV = [float(self.kegman.conf['Ki'])]
                #self.steerKf = float(self.kegman.conf['Kf'])
                #self.pid = PIController((CP.lateralTuning.pid.kpBP, self.steerKpV),
                #                    (CP.lateralTuning.pid.kiBP, self.steerKiV),
                #                    k_f=self.steerKf, pos_limit=1.0)
                self.deadzone = float(self.kegman.conf['deadzone'])

            self.mpc_frame = 0

    def update(self, active, CS, CP, path_plan):
        self.live_tune(CP)

        pid_log = log.ControlsState.LateralPIDState.new_message()
        pid_log.steerAngle = float(CS.steeringAngle)
        pid_log.steerRate = float(CS.steeringRate)

        if CS.vEgo < 0.3 or not active:
            output_steer = 0.0
            pid_log.active = False
            self.pid.reset()
        else:
            self.angle_steers_des = path_plan.angleSteers  # get from MPC/PathPlanner
            check_pingpong = abs(self.angle_steers_des -
                                 self.angle_steers_des_last) > 3.0
            if CS.vEgo < 10.0 and check_pingpong:
                self.angle_steers_des = path_plan.angleSteers * 0.3
            elif CS.vEgo < 15.0 and check_pingpong:
                self.angle_steers_des = path_plan.angleSteers * 0.45
            elif CS.vEgo < 20.0 and check_pingpong:
                self.angle_steers_des = path_plan.angleSteers * 0.6
            elif CS.vEgo < 25.0 and check_pingpong:
                self.angle_steers_des = path_plan.angleSteers * 0.8

            steers_max = get_steer_max(CP, CS.vEgo)
            self.pid.pos_limit = steers_max
            self.pid.neg_limit = -steers_max
            steer_feedforward = self.angle_steers_des  # feedforward desired angle
            self.angle_steers_des_last = self.angle_steers_des
            if CP.steerControlType == car.CarParams.SteerControlType.torque:
                # TODO: feedforward something based on path_plan.rateSteers
                steer_feedforward -= path_plan.angleOffset  # subtract the offset, since it does not contribute to resistive torque
                steer_feedforward *= CS.vEgo**2  # proportional to realigning tire momentum (~ lateral accel)

            deadzone = self.deadzone

            check_saturation = (
                CS.vEgo >
                10) and not CS.steeringRateLimited and not CS.steeringPressed
            output_steer = self.pid.update(self.angle_steers_des,
                                           CS.steeringAngle,
                                           check_saturation=check_saturation,
                                           override=CS.steeringPressed,
                                           feedforward=steer_feedforward,
                                           speed=CS.vEgo,
                                           deadzone=deadzone)
            pid_log.active = True
            pid_log.p = self.pid.p
            pid_log.i = self.pid.i
            pid_log.f = self.pid.f
            pid_log.output = output_steer
            pid_log.saturated = bool(self.pid.saturated)

        return output_steer, float(self.angle_steers_des), pid_log
Exemple #11
0
class LatControlPID():
    def __init__(self, CP):
        self.pid = LatPIDController(
            (CP.lateralTuning.pid.kpBP, CP.lateralTuning.pid.kpV),
            (CP.lateralTuning.pid.kiBP, CP.lateralTuning.pid.kiV),
            (CP.lateralTuning.pid.kdBP, CP.lateralTuning.pid.kdV),
            k_f=CP.lateralTuning.pid.kf,
            pos_limit=1.0,
            sat_limit=CP.steerLimitTimer)
        self.new_kf_tuned = CP.lateralTuning.pid.newKfTuned
        self.angle_steers_des = 0.
        self.mpc_frame = 0
        self.params = Params()

    def reset(self):
        self.pid.reset()

    # live tune referred to kegman's
    def live_tune(self, CP):
        self.mpc_frame += 1
        if self.mpc_frame % 300 == 0:
            self.steerKpV = float(int(self.params.get('PidKp')) * 0.01)
            self.steerKiV = float(int(self.params.get('PidKi')) * 0.001)
            self.steerKdV = float(int(self.params.get('PidKd')) * 0.01)
            self.steerKf = float(int(self.params.get('PidKf')) * 0.00001)
            self.pid = LatPIDController(
                (CP.lateralTuning.pid.kpBP, [0.1, self.steerKpV]),
                (CP.lateralTuning.pid.kiBP, [0.01, self.steerKiV]),
                (CP.lateralTuning.pid.kdBP, [self.steerKdV]),
                k_f=self.steerKf,
                pos_limit=1.0)
            self.mpc_frame = 0

    def update(self, active, CS, CP, path_plan):
        if int(self.params.get('OpkrLiveTune')) == 1:
            self.live_tune(CP)

        pid_log = log.ControlsState.LateralPIDState.new_message()
        pid_log.steerAngle = float(CS.steeringAngle)
        pid_log.steerRate = float(CS.steeringRate)

        if CS.vEgo < 0.3 or not active:
            output_steer = 0.0
            pid_log.active = False
            self.pid.reset()
        else:
            self.angle_steers_des = path_plan.angleSteers  # get from MPC/PathPlanner

            steers_max = get_steer_max(CP, CS.vEgo)
            self.pid.pos_limit = steers_max
            self.pid.neg_limit = -steers_max
            steer_feedforward = self.angle_steers_des  # feedforward desired angle
            if CP.steerControlType == car.CarParams.SteerControlType.torque:
                # TODO: feedforward something based on path_plan.rateSteers
                steer_feedforward -= path_plan.angleOffset  # subtract the offset, since it does not contribute to resistive torque
                if self.new_kf_tuned:
                    _c1, _c2, _c3 = 0.35189607550172824, 7.506201251644202, 69.226826411091
                    steer_feedforward *= _c1 * CS.vEgo**2 + _c2 * CS.vEgo + _c3
                else:
                    steer_feedforward *= CS.vEgo**2  # proportional to realigning tire momentum (~ lateral accel)
            deadzone = float(int(self.params.get('IgnoreZone')) * 0.1)

            check_saturation = (
                CS.vEgo >
                10) and not CS.steeringRateLimited and not CS.steeringPressed
            output_steer = self.pid.update(self.angle_steers_des,
                                           CS.steeringAngle,
                                           check_saturation=check_saturation,
                                           override=CS.steeringPressed,
                                           feedforward=steer_feedforward,
                                           speed=CS.vEgo,
                                           deadzone=deadzone)
            pid_log.active = True
            pid_log.p = self.pid.p
            pid_log.i = self.pid.i
            pid_log.f = self.pid.f
            pid_log.output = output_steer
            pid_log.saturated = bool(self.pid.saturated)

        return output_steer, float(self.angle_steers_des), pid_log
class LatControlPID():
    def __init__(self, CP):
        self.pid = LatPIDController(
            (CP.lateralTuning.pid.kpBP, CP.lateralTuning.pid.kpV),
            (CP.lateralTuning.pid.kiBP, CP.lateralTuning.pid.kiV),
            (CP.lateralTuning.pid.kdBP, CP.lateralTuning.pid.kdV),
            k_f=CP.lateralTuning.pid.kf,
            pos_limit=1.0,
            neg_limit=-1.0,
            sat_limit=CP.steerLimitTimer)
        self.angle_steers_des = 0.
        self.angle_steers_des_last = 0.
        self.angle_steer_rate = [0.6, 1.0]
        self.angleBP = [10., 25.]
        self.angle_steer_new = 0.0

    def reset(self):
        self.pid.reset()

    def update(self, active, CS, CP, path_plan):
        pid_log = log.ControlsState.LateralPIDState.new_message()
        pid_log.steerAngle = float(CS.steeringAngle)
        pid_log.steerRate = float(CS.steeringRate)

        if CS.vEgo < 0.3 or not active:
            output_steer = 0.0
            pid_log.active = False
            self.pid.reset()
        else:
            self.angle_steers_des = path_plan.angleSteers  # get from MPC/PathPlanner
            self.angle_steer_new = interp(CS.vEgo, self.angleBP,
                                          self.angle_steer_rate)
            check_pingpong = abs(self.angle_steers_des -
                                 self.angle_steers_des_last) > 4.0
            if check_pingpong:
                self.angle_steers_des = path_plan.angleSteers * self.angle_steer_new

            steers_max = get_steer_max(CP, CS.vEgo)
            self.pid.pos_limit = steers_max
            self.pid.neg_limit = -steers_max
            steer_feedforward = self.angle_steers_des  # feedforward desired angle
            if CP.steerControlType == car.CarParams.SteerControlType.torque:
                # TODO: feedforward something based on path_plan.rateSteers
                steer_feedforward -= path_plan.angleOffset  # subtract the offset, since it does not contribute to resistive torque
                #steer_feedforward *= CS.vEgo**2  # proportional to realigning tire momentum (~ lateral accel)
                _c1, _c2, _c3 = [
                    0.35189607550172824, 7.506201251644202, 69.226826411091
                ]
                steer_feedforward *= _c1 * CS.vEgo**2 + _c2 * CS.vEgo + _c3
            deadzone = 0.0

            check_saturation = (
                CS.vEgo >
                10) and not CS.steeringRateLimited and not CS.steeringPressed
            output_steer = self.pid.update(self.angle_steers_des,
                                           CS.steeringAngle,
                                           check_saturation=check_saturation,
                                           override=CS.steeringPressed,
                                           feedforward=steer_feedforward,
                                           speed=CS.vEgo,
                                           deadzone=deadzone)
            pid_log.active = True
            pid_log.p = self.pid.p
            pid_log.i = self.pid.i
            pid_log.f = self.pid.f
            pid_log.output = output_steer
            pid_log.saturated = bool(self.pid.saturated)

            self.angle_steers_des_last = self.angle_steers_des

        return output_steer, float(self.angle_steers_des), pid_log
Exemple #13
0
class LatControlPID():
    def __init__(self, CP):
        self.pid = LatPIDController(
            (CP.lateralTuning.pid.kpBP, CP.lateralTuning.pid.kpV),
            (CP.lateralTuning.pid.kiBP, CP.lateralTuning.pid.kiV),
            (CP.lateralTuning.pid.kdBP, CP.lateralTuning.pid.kdV),
            k_f=CP.lateralTuning.pid.kf,
            pos_limit=1.0,
            neg_limit=-1.0,
            sat_limit=CP.steerLimitTimer)
        self.new_kf_tuned = CP.lateralTuning.pid.newKfTuned
        self.mpc_frame = 0
        self.params = Params()

        self.live_tune_enabled = self.params.get_bool("OpkrLiveTune")
        self.dead_zone = float(
            Decimal(self.params.get("IgnoreZone", encoding="utf8")) *
            Decimal('0.1'))

    def reset(self):
        self.pid.reset()

    # live tune referred to kegman's
    def live_tune(self, CP):
        self.mpc_frame += 1
        if self.mpc_frame % 300 == 0:
            self.steerKpV = float(
                Decimal(self.params.get("PidKp", encoding="utf8")) *
                Decimal('0.01'))
            self.steerKiV = float(
                Decimal(self.params.get("PidKi", encoding="utf8")) *
                Decimal('0.001'))
            self.steerKdV = float(
                Decimal(self.params.get("PidKd", encoding="utf8")) *
                Decimal('0.01'))
            self.steerKf = float(
                Decimal(self.params.get("PidKf", encoding="utf8")) *
                Decimal('0.00001'))
            self.pid = LatPIDController(
                (CP.lateralTuning.pid.kpBP, [0.1, self.steerKpV]),
                (CP.lateralTuning.pid.kiBP, [0.01, self.steerKiV]),
                (CP.lateralTuning.pid.kdBP, [self.steerKdV]),
                k_f=self.steerKf,
                pos_limit=1.0)
            self.mpc_frame = 0

    def update(self, active, CS, CP, VM, params, desired_curvature,
               desired_curvature_rate):
        if self.live_tune_enabled:
            self.live_tune(CP)

        pid_log = log.ControlsState.LateralPIDState.new_message()
        pid_log.steeringAngleDeg = float(CS.steeringAngleDeg)
        pid_log.steeringRateDeg = float(CS.steeringRateDeg)

        angle_steers_des_no_offset = math.degrees(
            VM.get_steer_from_curvature(-desired_curvature, CS.vEgo))
        angle_steers_des = angle_steers_des_no_offset + params.angleOffsetDeg

        if CS.vEgo < 0.3 or not active:
            output_steer = 0.0
            pid_log.active = False
            self.pid.reset()
        else:
            steers_max = get_steer_max(CP, CS.vEgo)
            self.pid.pos_limit = steers_max
            self.pid.neg_limit = -steers_max

            # TODO: feedforward something based on lat_plan.rateSteers
            steer_feedforward = angle_steers_des_no_offset  # offset does not contribute to resistive torque
            if self.new_kf_tuned:
                _c1, _c2, _c3 = 0.35189607550172824, 7.506201251644202, 69.226826411091
                steer_feedforward *= _c1 * CS.vEgo**2 + _c2 * CS.vEgo + _c3
            else:
                steer_feedforward *= CS.vEgo**2  # proportional to realigning tire momentum (~ lateral accel)
            deadzone = self.dead_zone

            check_saturation = (
                CS.vEgo >
                10) and not CS.steeringRateLimited and not CS.steeringPressed
            output_steer = self.pid.update(angle_steers_des,
                                           CS.steeringAngleDeg,
                                           check_saturation=check_saturation,
                                           override=CS.steeringPressed,
                                           feedforward=steer_feedforward,
                                           speed=CS.vEgo,
                                           deadzone=deadzone)
            pid_log.active = True
            pid_log.p = self.pid.p
            pid_log.i = self.pid.i
            pid_log.f = self.pid.f
            pid_log.output = output_steer
            pid_log.saturated = bool(self.pid.saturated)

        return output_steer, angle_steers_des, pid_log