Example #1
0
    def update(self, CC, CS):
        actuators = CC.actuators
        hud_control = CC.hudControl
        pcm_cancel_cmd = CC.cruiseControl.cancel

        # gas and brake
        if self.CP.enableGasInterceptor and CC.longActive:
            MAX_INTERCEPTOR_GAS = 0.5
            # RAV4 has very sensitive gas pedal
            if self.CP.carFingerprint in (CAR.RAV4, CAR.RAV4H, CAR.HIGHLANDER,
                                          CAR.HIGHLANDERH):
                PEDAL_SCALE = interp(
                    CS.out.vEgo,
                    [0.0, MIN_ACC_SPEED, MIN_ACC_SPEED + PEDAL_TRANSITION],
                    [0.15, 0.3, 0.0])
            elif self.CP.carFingerprint in (CAR.COROLLA, ):
                PEDAL_SCALE = interp(
                    CS.out.vEgo,
                    [0.0, MIN_ACC_SPEED, MIN_ACC_SPEED + PEDAL_TRANSITION],
                    [0.3, 0.4, 0.0])
            else:
                PEDAL_SCALE = interp(
                    CS.out.vEgo,
                    [0.0, MIN_ACC_SPEED, MIN_ACC_SPEED + PEDAL_TRANSITION],
                    [0.4, 0.5, 0.0])
            # offset for creep and windbrake
            pedal_offset = interp(CS.out.vEgo,
                                  [0.0, 2.3, MIN_ACC_SPEED + PEDAL_TRANSITION],
                                  [-.4, 0.0, 0.2])
            pedal_command = PEDAL_SCALE * (actuators.accel + pedal_offset)
            interceptor_gas_cmd = clip(pedal_command, 0., MAX_INTERCEPTOR_GAS)
        else:
            interceptor_gas_cmd = 0.
        pcm_accel_cmd = clip(actuators.accel, CarControllerParams.ACCEL_MIN,
                             CarControllerParams.ACCEL_MAX)

        # steer torque
        new_steer = int(round(actuators.steer * CarControllerParams.STEER_MAX))
        apply_steer = apply_toyota_steer_torque_limits(
            new_steer, self.last_steer, CS.out.steeringTorqueEps,
            CarControllerParams)
        self.steer_rate_limited = new_steer != apply_steer

        # Cut steering while we're in a known fault state (2s)
        if not CC.latActive or CS.steer_state in (9, 25):
            apply_steer = 0
            apply_steer_req = 0
        else:
            apply_steer_req = 1

        # TODO: probably can delete this. CS.pcm_acc_status uses a different signal
        # than CS.cruiseState.enabled. confirm they're not meaningfully different
        if not CC.enabled and CS.pcm_acc_status:
            pcm_cancel_cmd = 1

        # on entering standstill, send standstill request
        if CS.out.standstill and not self.last_standstill and self.CP.carFingerprint not in NO_STOP_TIMER_CAR:
            self.standstill_req = True
        if CS.pcm_acc_status != 8:
            # pcm entered standstill or it's disabled
            self.standstill_req = False

        self.last_steer = apply_steer
        self.last_standstill = CS.out.standstill

        can_sends = []

        # *** control msgs ***
        # print("steer {0} {1} {2} {3}".format(apply_steer, min_lim, max_lim, CS.steer_torque_motor)

        # toyota can trace shows this message at 42Hz, with counter adding alternatively 1 and 2;
        # sending it at 100Hz seem to allow a higher rate limit, as the rate limit seems imposed
        # on consecutive messages
        can_sends.append(
            create_steer_command(self.packer, apply_steer, apply_steer_req,
                                 self.frame))
        if self.frame % 2 == 0 and self.CP.carFingerprint in TSS2_CAR:
            can_sends.append(
                create_lta_steer_command(self.packer, 0, 0, self.frame // 2))

        # LTA mode. Set ret.steerControlType = car.CarParams.SteerControlType.angle and whitelist 0x191 in the panda
        # if self.frame % 2 == 0:
        #   can_sends.append(create_steer_command(self.packer, 0, 0, self.frame // 2))
        #   can_sends.append(create_lta_steer_command(self.packer, actuators.steeringAngleDeg, apply_steer_req, self.frame // 2))

        # we can spam can to cancel the system even if we are using lat only control
        if (self.frame % 3 == 0
                and self.CP.openpilotLongitudinalControl) or pcm_cancel_cmd:
            lead = hud_control.leadVisible or CS.out.vEgo < 12.  # at low speed we always assume the lead is present so ACC can be engaged

            # Lexus IS uses a different cancellation message
            if pcm_cancel_cmd and self.CP.carFingerprint in (CAR.LEXUS_IS,
                                                             CAR.LEXUS_RC):
                can_sends.append(create_acc_cancel_command(self.packer))
            elif self.CP.openpilotLongitudinalControl:
                can_sends.append(
                    create_accel_command(self.packer, pcm_accel_cmd,
                                         pcm_cancel_cmd, self.standstill_req,
                                         lead, CS.acc_type))
                self.accel = pcm_accel_cmd
            else:
                can_sends.append(
                    create_accel_command(self.packer, 0, pcm_cancel_cmd, False,
                                         lead, CS.acc_type))

        if self.frame % 2 == 0 and self.CP.enableGasInterceptor and self.CP.openpilotLongitudinalControl:
            # send exactly zero if gas cmd is zero. Interceptor will send the max between read value and gas cmd.
            # This prevents unexpected pedal range rescaling
            can_sends.append(
                create_gas_interceptor_command(self.packer,
                                               interceptor_gas_cmd,
                                               self.frame // 2))
            self.gas = interceptor_gas_cmd

        # ui mesg is at 1Hz but we send asap if:
        # - there is something to display
        # - there is something to stop displaying
        fcw_alert = hud_control.visualAlert == VisualAlert.fcw
        steer_alert = hud_control.visualAlert in (VisualAlert.steerRequired,
                                                  VisualAlert.ldw)

        send_ui = False
        if ((fcw_alert or steer_alert) and not self.alert_active) or \
           (not (fcw_alert or steer_alert) and self.alert_active):
            send_ui = True
            self.alert_active = not self.alert_active
        elif pcm_cancel_cmd:
            # forcing the pcm to disengage causes a bad fault sound so play a good sound instead
            send_ui = True

        if self.frame % 100 == 0 or send_ui:
            can_sends.append(
                create_ui_command(self.packer, steer_alert, pcm_cancel_cmd,
                                  hud_control.leftLaneVisible,
                                  hud_control.rightLaneVisible,
                                  hud_control.leftLaneDepart,
                                  hud_control.rightLaneDepart, CC.enabled))

        if self.frame % 100 == 0 and self.CP.enableDsu:
            can_sends.append(create_fcw_command(self.packer, fcw_alert))

        # *** static msgs ***
        for addr, cars, bus, fr_step, vl in STATIC_DSU_MSGS:
            if self.frame % fr_step == 0 and self.CP.enableDsu and self.CP.carFingerprint in cars:
                can_sends.append(make_can_msg(addr, vl, bus))

        new_actuators = actuators.copy()
        new_actuators.steer = apply_steer / CarControllerParams.STEER_MAX
        new_actuators.accel = self.accel
        new_actuators.gas = self.gas

        self.frame += 1
        return new_actuators, can_sends
Example #2
0
    def update(self, enabled, CS, frame, actuators, pcm_cancel_cmd, hud_alert,
               left_line, right_line, lead, left_lane_depart,
               right_lane_depart):

        # *** compute control surfaces ***

        # gas and brake

        apply_gas = clip(actuators.gas, 0., 1.)

        if CS.CP.enableGasInterceptor:
            # send only negative accel if interceptor is detected. otherwise, send the regular value
            # +0.06 offset to reduce ABS pump usage when OP is engaged
            apply_accel = 0.06 - actuators.brake
        else:
            apply_accel = actuators.gas - actuators.brake

        apply_accel, self.accel_steady = accel_hysteresis(
            apply_accel, self.accel_steady, enabled)
        apply_accel = clip(apply_accel * ACCEL_SCALE, ACCEL_MIN, ACCEL_MAX)

        # steer torque
        new_steer = int(round(actuators.steer * SteerLimitParams.STEER_MAX))
        apply_steer = apply_toyota_steer_torque_limits(
            new_steer, self.last_steer, CS.out.steeringTorqueEps,
            SteerLimitParams)
        self.steer_rate_limited = new_steer != apply_steer

        # only cut torque when steer state is a known fault
        if CS.steer_state in [9, 25]:
            self.last_fault_frame = frame

        # Cut steering for 2s after fault
        if not enabled or (frame - self.last_fault_frame < 200):
            apply_steer = 0
            apply_steer_req = 0
        else:
            apply_steer_req = 1

        self.steer_angle_enabled, self.ipas_reset_counter = \
          ipas_state_transition(self.steer_angle_enabled, enabled, CS.ipas_active, self.ipas_reset_counter)
        #print("{0} {1} {2}".format(self.steer_angle_enabled, self.ipas_reset_counter, CS.ipas_active))

        # steer angle
        if self.steer_angle_enabled and CS.ipas_active:
            apply_angle = actuators.steerAngle
            angle_lim = interp(CS.out.vEgo, ANGLE_MAX_BP, ANGLE_MAX_V)
            apply_angle = clip(apply_angle, -angle_lim, angle_lim)

            # windup slower
            if self.last_angle * apply_angle > 0. and abs(apply_angle) > abs(
                    self.last_angle):
                angle_rate_lim = interp(CS.out.vEgo, ANGLE_DELTA_BP,
                                        ANGLE_DELTA_V)
            else:
                angle_rate_lim = interp(CS.out.vEgo, ANGLE_DELTA_BP,
                                        ANGLE_DELTA_VU)

            apply_angle = clip(apply_angle, self.last_angle - angle_rate_lim,
                               self.last_angle + angle_rate_lim)
        else:
            apply_angle = CS.out.steeringAngle

        if not enabled and CS.pcm_acc_status:
            # send pcm acc cancel cmd if drive is disabled but pcm is still on, or if the system can't be activated
            pcm_cancel_cmd = 1

        # on entering standstill, send standstill request
        if CS.out.standstill and not self.last_standstill:
            self.standstill_req = True
        if CS.pcm_acc_status != 8:
            # pcm entered standstill or it's disabled
            self.standstill_req = False

        self.last_steer = apply_steer
        self.last_angle = apply_angle
        self.last_accel = apply_accel
        self.last_standstill = CS.out.standstill

        can_sends = []

        #*** control msgs ***
        #print("steer {0} {1} {2} {3}".format(apply_steer, min_lim, max_lim, CS.steer_torque_motor)

        # toyota can trace shows this message at 42Hz, with counter adding alternatively 1 and 2;
        # sending it at 100Hz seem to allow a higher rate limit, as the rate limit seems imposed
        # on consecutive messages
        if Ecu.fwdCamera in self.fake_ecus:
            if self.angle_control:
                can_sends.append(
                    create_steer_command(self.packer, 0., 0, frame))
            else:
                can_sends.append(
                    create_steer_command(self.packer, apply_steer,
                                         apply_steer_req, frame))

        if self.angle_control:
            can_sends.append(
                create_ipas_steer_command(self.packer, apply_angle,
                                          self.steer_angle_enabled, Ecu.apgs
                                          in self.fake_ecus))
        elif Ecu.apgs in self.fake_ecus:
            can_sends.append(create_ipas_steer_command(self.packer, 0, 0,
                                                       True))

        # we can spam can to cancel the system even if we are using lat only control
        if (frame % 3 == 0 and CS.CP.openpilotLongitudinalControl) or (
                pcm_cancel_cmd and Ecu.fwdCamera in self.fake_ecus):
            lead = lead or CS.out.vEgo < 12.  # at low speed we always assume the lead is present do ACC can be engaged

            # Lexus IS uses a different cancellation message
            if pcm_cancel_cmd and CS.CP.carFingerprint == CAR.LEXUS_IS:
                can_sends.append(create_acc_cancel_command(self.packer))
            elif CS.CP.openpilotLongitudinalControl:
                can_sends.append(
                    create_accel_command(self.packer, apply_accel,
                                         pcm_cancel_cmd, self.standstill_req,
                                         lead))
            else:
                can_sends.append(
                    create_accel_command(self.packer, 0, pcm_cancel_cmd, False,
                                         lead))

        if (frame % 2 == 0) and (CS.CP.enableGasInterceptor):
            # send exactly zero if apply_gas is zero. Interceptor will send the max between read value and apply_gas.
            # This prevents unexpected pedal range rescaling
            can_sends.append(
                create_gas_command(self.packer, apply_gas, frame // 2))

        # ui mesg is at 100Hz but we send asap if:
        # - there is something to display
        # - there is something to stop displaying
        alert_out = process_hud_alert(hud_alert)
        steer, fcw = alert_out

        if (any(alert_out) and not self.alert_active) or \
           (not any(alert_out) and self.alert_active):
            send_ui = True
            self.alert_active = not self.alert_active
        else:
            send_ui = False

        # disengage msg causes a bad fault sound so play a good sound instead
        if pcm_cancel_cmd:
            send_ui = True

        if (frame % 100 == 0 or send_ui) and Ecu.fwdCamera in self.fake_ecus:
            can_sends.append(
                create_ui_command(self.packer, steer, pcm_cancel_cmd,
                                  left_line, right_line, left_lane_depart,
                                  right_lane_depart))

        if frame % 100 == 0 and Ecu.dsu in self.fake_ecus:
            can_sends.append(create_fcw_command(self.packer, fcw))

        #*** static msgs ***

        for (addr, ecu, cars, bus, fr_step, vl) in STATIC_MSGS:
            if frame % fr_step == 0 and ecu in self.fake_ecus and self.car_fingerprint in cars:
                can_sends.append(make_can_msg(addr, vl, bus))

        return can_sends
Example #3
0
    def update(self, enabled, active, CS, frame, actuators, pcm_cancel_cmd,
               hud_alert, left_line, right_line, lead, left_lane_depart,
               right_lane_depart):

        # *** compute control surfaces ***

        # gas and brake
        interceptor_gas_cmd = 0.
        pcm_accel_cmd = actuators.accel

        if CS.CP.enableGasInterceptor:
            # handle hysteresis when around the minimum acc speed
            if CS.out.vEgo < MIN_ACC_SPEED:
                self.use_interceptor = True
            elif CS.out.vEgo > MIN_ACC_SPEED + PEDAL_HYST_GAP:
                self.use_interceptor = False

            if self.use_interceptor and active:
                # only send negative accel when using interceptor. gas handles acceleration
                # +0.18 m/s^2 offset to reduce ABS pump usage when OP is engaged
                MAX_INTERCEPTOR_GAS = interp(CS.out.vEgo, [0.0, MIN_ACC_SPEED],
                                             [0.2, 0.5])
                interceptor_gas_cmd = clip(actuators.accel / PEDAL_SCALE, 0.,
                                           MAX_INTERCEPTOR_GAS)
                pcm_accel_cmd = 0.18 - max(0, -actuators.accel)

        pcm_accel_cmd, self.accel_steady = accel_hysteresis(
            pcm_accel_cmd, self.accel_steady, enabled)
        pcm_accel_cmd = clip(pcm_accel_cmd, CarControllerParams.ACCEL_MIN,
                             CarControllerParams.ACCEL_MAX)

        # steer torque
        new_steer = int(round(actuators.steer * CarControllerParams.STEER_MAX))
        apply_steer = apply_toyota_steer_torque_limits(
            new_steer, self.last_steer, CS.out.steeringTorqueEps,
            CarControllerParams)
        self.steer_rate_limited = new_steer != apply_steer

        # Cut steering while we're in a known fault state (2s)
        if not enabled or CS.steer_state in [9, 25]:
            apply_steer = 0
            apply_steer_req = 0
        else:
            apply_steer_req = 1

        # TODO: probably can delete this. CS.pcm_acc_status uses a different signal
        # than CS.cruiseState.enabled. confirm they're not meaningfully different
        if not enabled and CS.pcm_acc_status:
            pcm_cancel_cmd = 1

        # on entering standstill, send standstill request
        if CS.out.standstill and not self.last_standstill and CS.CP.carFingerprint not in NO_STOP_TIMER_CAR:
            self.standstill_req = True
        if CS.pcm_acc_status != 8:
            # pcm entered standstill or it's disabled
            self.standstill_req = False

        self.last_steer = apply_steer
        self.last_accel = pcm_accel_cmd
        self.last_standstill = CS.out.standstill

        can_sends = []

        #*** control msgs ***
        #print("steer {0} {1} {2} {3}".format(apply_steer, min_lim, max_lim, CS.steer_torque_motor)

        # toyota can trace shows this message at 42Hz, with counter adding alternatively 1 and 2;
        # sending it at 100Hz seem to allow a higher rate limit, as the rate limit seems imposed
        # on consecutive messages
        can_sends.append(
            create_steer_command(self.packer, apply_steer, apply_steer_req,
                                 frame))
        if frame % 2 == 0 and CS.CP.carFingerprint in TSS2_CAR:
            can_sends.append(
                create_lta_steer_command(self.packer, 0, 0, frame // 2))

        # LTA mode. Set ret.steerControlType = car.CarParams.SteerControlType.angle and whitelist 0x191 in the panda
        # if frame % 2 == 0:
        #   can_sends.append(create_steer_command(self.packer, 0, 0, frame // 2))
        #   can_sends.append(create_lta_steer_command(self.packer, actuators.steeringAngleDeg, apply_steer_req, frame // 2))

        # we can spam can to cancel the system even if we are using lat only control
        if (frame % 3 == 0
                and CS.CP.openpilotLongitudinalControl) or pcm_cancel_cmd:
            lead = lead or CS.out.vEgo < 12.  # at low speed we always assume the lead is present do ACC can be engaged

            # Lexus IS uses a different cancellation message
            if pcm_cancel_cmd and CS.CP.carFingerprint == CAR.LEXUS_IS:
                can_sends.append(create_acc_cancel_command(self.packer))
            elif CS.CP.openpilotLongitudinalControl:
                can_sends.append(
                    create_accel_command(self.packer, pcm_accel_cmd,
                                         pcm_cancel_cmd, self.standstill_req,
                                         lead, CS.acc_type))
            else:
                can_sends.append(
                    create_accel_command(self.packer, 0, pcm_cancel_cmd, False,
                                         lead, CS.acc_type))

        if frame % 2 == 0 and CS.CP.enableGasInterceptor:
            # send exactly zero if gas cmd is zero. Interceptor will send the max between read value and gas cmd.
            # This prevents unexpected pedal range rescaling
            can_sends.append(
                create_gas_command(self.packer, interceptor_gas_cmd,
                                   frame // 2))

        # ui mesg is at 100Hz but we send asap if:
        # - there is something to display
        # - there is something to stop displaying
        fcw_alert = hud_alert == VisualAlert.fcw
        steer_alert = hud_alert in [VisualAlert.steerRequired, VisualAlert.ldw]

        send_ui = False
        if ((fcw_alert or steer_alert) and not self.alert_active) or \
           (not (fcw_alert or steer_alert) and self.alert_active):
            send_ui = True
            self.alert_active = not self.alert_active
        elif pcm_cancel_cmd:
            # forcing the pcm to disengage causes a bad fault sound so play a good sound instead
            send_ui = True

        if (frame % 100 == 0 or send_ui):
            can_sends.append(
                create_ui_command(self.packer, steer_alert, pcm_cancel_cmd,
                                  left_line, right_line, left_lane_depart,
                                  right_lane_depart))

        if frame % 100 == 0 and CS.CP.enableDsu:
            can_sends.append(create_fcw_command(self.packer, fcw_alert))

        #*** static msgs ***

        for (addr, cars, bus, fr_step, vl) in STATIC_DSU_MSGS:
            if frame % fr_step == 0 and CS.CP.enableDsu and CS.CP.carFingerprint in cars:
                can_sends.append(make_can_msg(addr, vl, bus))

        return can_sends
Example #4
0
  def update(self, enabled, active, CS, frame, actuators, pcm_cancel_cmd, hud_alert,
             left_line, right_line, lead, left_lane_depart, right_lane_depart):

    # gas and brake
    if CS.CP.enableGasInterceptor and active:
      MAX_INTERCEPTOR_GAS = 0.5
      # RAV4 has very sensitive gas pedal
      if CS.CP.carFingerprint in (CAR.RAV4, CAR.RAV4H, CAR.HIGHLANDER, CAR.HIGHLANDERH):
        PEDAL_SCALE = interp(CS.out.vEgo, [0.0, MIN_ACC_SPEED, MIN_ACC_SPEED + PEDAL_TRANSITION], [0.15, 0.3, 0.0])
      elif CS.CP.carFingerprint in (CAR.COROLLA,):
        PEDAL_SCALE = interp(CS.out.vEgo, [0.0, MIN_ACC_SPEED, MIN_ACC_SPEED + PEDAL_TRANSITION], [0.3, 0.4, 0.0])
      else:
        PEDAL_SCALE = interp(CS.out.vEgo, [0.0, MIN_ACC_SPEED, MIN_ACC_SPEED + PEDAL_TRANSITION], [0.4, 0.5, 0.0])
      # offset for creep and windbrake
      pedal_offset = interp(CS.out.vEgo, [0.0, 2.3, MIN_ACC_SPEED + PEDAL_TRANSITION], [-.4, 0.0, 0.2])
      pedal_command = PEDAL_SCALE * (actuators.accel + pedal_offset)
      interceptor_gas_cmd = clip(pedal_command, 0., MAX_INTERCEPTOR_GAS)
    else:
      interceptor_gas_cmd = 0.
    pcm_accel_cmd = clip(actuators.accel, CarControllerParams.ACCEL_MIN, CarControllerParams.ACCEL_MAX)

    # steer torque
    new_steer = int(round(actuators.steer * CarControllerParams.STEER_MAX))
    apply_steer = apply_toyota_steer_torque_limits(new_steer, self.last_steer, CS.out.steeringTorqueEps, CarControllerParams)
    self.steer_rate_limited = new_steer != apply_steer

    # TODO: probably can delete this. CS.pcm_acc_status uses a different signal
    # than CS.cruiseState.enabled. confirm they're not meaningfully different
    if not enabled and CS.pcm_acc_status:
      pcm_cancel_cmd = 1

    # on entering standstill, send standstill request
    if CS.out.standstill and not self.last_standstill and CS.CP.carFingerprint not in NO_STOP_TIMER_CAR:
      self.standstill_req = True
    if CS.pcm_acc_status != 8:
      # pcm entered standstill or it's disabled
      self.standstill_req = False

    self.last_steer = apply_steer
    self.last_standstill = CS.out.standstill

    can_sends = []

    if CS.CP.steerControlType == car.CarParams.SteerControlType.angle:
      can_sends.append(create_steer_command(self.packer, 0, 0, frame))
      # On TSS2 cars, the LTA and STEER_TORQUE_SENSOR messages use relative steering angle signals that start
      # at 0 degrees, so we need to offset the commanded angle as well.
      # Also need to pulse steer_req to prevent 5 second steering lockout in some cases
      steer_req = active  # TODO(thinh): Check and cut out steering while we are in a known fault state
      percentage = interp(abs(CS.out.steeringTorque), [50, 100], [100, 0])
      commanded_angle = interp(percentage, [-10, 100], [CS.out.steeringAngleDeg + CS.out.steeringAngleOffsetDeg,
                    actuators.steeringAngleDeg + CS.out.steeringAngleOffsetDeg])
      can_sends.append(create_lta_steer_command(self.packer, commanded_angle, steer_req, frame))
    else:
      # Cut steering while we're in a known fault state (2s)
      if not active or CS.steer_state in (9, 25):
        apply_steer = 0
        apply_steer_req = 0
      else:
        apply_steer_req = 1
      # toyota can trace shows this message at 42Hz, with counter adding alternatively 1 and 2;
      # sending it at 100Hz seem to allow a higher rate limit, as the rate limit seems imposed
      # on consecutive messages
      can_sends.append(create_steer_command(self.packer, apply_steer, apply_steer_req, frame))
      if frame % 2 == 0 and CS.CP.carFingerprint in TSS2_CAR:
        can_sends.append(create_lta_steer_command(self.packer, 0, 0, frame // 2))

    # we can spam can to cancel the system even if we are using lat only control
    if (frame % 3 == 0 and CS.CP.openpilotLongitudinalControl) or pcm_cancel_cmd:
      lead = lead or CS.out.vEgo < 12.    # at low speed we always assume the lead is present so ACC can be engaged

      # Lexus IS uses a different cancellation message
      if pcm_cancel_cmd and CS.CP.carFingerprint in (CAR.LEXUS_IS, CAR.LEXUS_RC):
        can_sends.append(create_acc_cancel_command(self.packer))
      elif CS.CP.openpilotLongitudinalControl:
        can_sends.append(create_accel_command(self.packer, pcm_accel_cmd, pcm_cancel_cmd, self.standstill_req, lead, CS.acc_type, CS.distance_btn))
        self.accel = pcm_accel_cmd
      else:
        can_sends.append(create_accel_command(self.packer, 0, pcm_cancel_cmd, False, lead, CS.acc_type, CS.distance_btn))

    if frame % 2 == 0 and CS.CP.enableGasInterceptor and CS.CP.openpilotLongitudinalControl:
      # send exactly zero if gas cmd is zero. Interceptor will send the max between read value and gas cmd.
      # This prevents unexpected pedal range rescaling
      can_sends.append(create_gas_interceptor_command(self.packer, interceptor_gas_cmd, frame // 2))
      self.gas = interceptor_gas_cmd

    # ui mesg is at 1Hz but we send asap if:
    # - there is something to display
    # - there is something to stop displaying
    fcw_alert = hud_alert == VisualAlert.fcw
    steer_alert = hud_alert in (VisualAlert.steerRequired, VisualAlert.ldw)

    send_ui = False
    if ((fcw_alert or steer_alert) and not self.alert_active) or \
       (not (fcw_alert or steer_alert) and self.alert_active):
      send_ui = True
      self.alert_active = not self.alert_active
    elif pcm_cancel_cmd:
      # forcing the pcm to disengage causes a bad fault sound so play a good sound instead
      send_ui = True

    if (frame % 100 == 0 or send_ui):
      can_sends.append(create_ui_command(self.packer, steer_alert, pcm_cancel_cmd, left_line, right_line, left_lane_depart, right_lane_depart, enabled))

    if frame % 100 == 0 and CS.CP.enableDsu:
      can_sends.append(create_fcw_command(self.packer, fcw_alert))

    # *** static msgs ***
    for (addr, cars, bus, fr_step, vl) in STATIC_DSU_MSGS:
      if frame % fr_step == 0 and CS.CP.enableDsu and CS.CP.carFingerprint in cars:
        can_sends.append(make_can_msg(addr, vl, bus))

    new_actuators = actuators.copy()
    new_actuators.steer = apply_steer / CarControllerParams.STEER_MAX
    new_actuators.accel = self.accel
    new_actuators.gas = self.gas

    return new_actuators, can_sends
  def update(self, enabled, CS, frame, actuators,
             pcm_cancel_cmd, hud_alert, forwarding_camera, left_line,
             right_line, lead, left_lane_depart, right_lane_depart):

    # *** compute control surfaces ***

    # gas and brake

    apply_gas = clip(actuators.gas, 0., 1.)

    if CS.CP.enableGasInterceptor:
      # send only negative accel if interceptor is detected. otherwise, send the regular value
      # +0.06 offset to reduce ABS pump usage when OP is engaged
      apply_accel = 0.06 - actuators.brake
    else:
      apply_accel = actuators.gas - actuators.brake

    apply_accel, self.accel_steady = accel_hysteresis(apply_accel, self.accel_steady, enabled)
    apply_accel = clip(apply_accel * ACCEL_SCALE, ACCEL_MIN, ACCEL_MAX)
    
    if CS.CP.enableGasInterceptor:
      if CS.pedal_gas > 15.0:
        apply_accel = max(apply_accel, 0.06)
      if CS.brake_pressed:
        apply_gas = 0.0
        apply_accel = min(apply_accel, 0.00)
    else:
      if CS.pedal_gas > 0.0:
        apply_accel = max(apply_accel, 0.0)
      if CS.brake_pressed and CS.v_ego > 1:
        apply_accel = min(apply_accel, 0.0)
      
    # steer torque
    apply_steer = int(round(actuators.steer * SteerLimitParams.STEER_MAX))
    
    # only cut torque when steer state is a known fault
    if CS.steer_state in [9, 25] and self.last_steer > 0:
      self.last_fault_frame = frame

    # Cut steering for 1s after fault
    if not enabled or (frame - self.last_fault_frame < 100):
      apply_steer = 0
      apply_steer_req = 0
    else:
      apply_steer_req = 1

    if not enabled and right_lane_depart and CS.v_ego > 12.5 and not CS.right_blinker_on:
      apply_steer = self.last_steer + 3
      apply_steer = min(apply_steer , 800)
      #print "right"
      #print apply_steer
      apply_steer_req = 1
      
    if not enabled and left_lane_depart and CS.v_ego > 12.5 and not CS.left_blinker_on:
      apply_steer = self.last_steer - 3
      apply_steer = max(apply_steer , -800)
      #print "left"
      #print apply_steer
      apply_steer_req = 1
      
    if abs(CS.angle_steers) > 100 or abs(CS.angle_steers_rate) > 100:
      apply_steer = 0
      apply_steer_req = 0
      
    apply_steer = apply_toyota_steer_torque_limits(apply_steer, self.last_steer, CS.steer_torque_motor, SteerLimitParams)
    
    if apply_steer == 0 and self.last_steer == 0:
      apply_steer_req = 0
    
    self.steer_angle_enabled, self.ipas_reset_counter = \
      ipas_state_transition(self.steer_angle_enabled, enabled, CS.ipas_active, self.ipas_reset_counter)
    #print("{0} {1} {2}".format(self.steer_angle_enabled, self.ipas_reset_counter, CS.ipas_active))

    # steer angle
    if self.steer_angle_enabled and CS.ipas_active:
      apply_angle = actuators.steerAngle
      angle_lim = interp(CS.v_ego, ANGLE_MAX_BP, ANGLE_MAX_V)
      apply_angle = clip(apply_angle, -angle_lim, angle_lim)

      # windup slower
      if self.last_angle * apply_angle > 0. and abs(apply_angle) > abs(self.last_angle):
        angle_rate_lim = interp(CS.v_ego, ANGLE_DELTA_BP, ANGLE_DELTA_V)
      else:
        angle_rate_lim = interp(CS.v_ego, ANGLE_DELTA_BP, ANGLE_DELTA_VU)

      apply_angle = clip(apply_angle, self.last_angle - angle_rate_lim, self.last_angle + angle_rate_lim)
    else:
      apply_angle = CS.angle_steers

    if not enabled and CS.pcm_acc_status:
      # send pcm acc cancel cmd if drive is disabled but pcm is still on, or if the system can't be activated
      pcm_cancel_cmd = 1

    # on entering standstill, send standstill request
    if CS.standstill and not self.last_standstill:
      self.standstill_req = True
    if CS.pcm_acc_status != 8:
      # pcm entered standstill or it's disabled
      self.standstill_req = False

    self.last_steer = apply_steer
    self.last_angle = apply_angle
    self.last_accel = apply_accel
    self.last_standstill = CS.standstill

    can_sends = []

    #*** control msgs ***
    #print("steer {0} {1} {2} {3}".format(apply_steer, min_lim, max_lim, CS.steer_torque_motor)

    # toyota can trace shows this message at 42Hz, with counter adding alternatively 1 and 2;
    # sending it at 100Hz seem to allow a higher rate limit, as the rate limit seems imposed
    # on consecutive messages
    if ECU.CAM in self.fake_ecus:
      if self.angle_control:
        can_sends.append(create_steer_command(self.packer, 0., 0, frame))
      else:
        can_sends.append(create_steer_command(self.packer, apply_steer, apply_steer_req, frame))

    if self.angle_control:
      can_sends.append(create_ipas_steer_command(self.packer, apply_angle, self.steer_angle_enabled,
                                                 ECU.APGS in self.fake_ecus))
    elif ECU.APGS in self.fake_ecus:
      can_sends.append(create_ipas_steer_command(self.packer, 0, 0, True))

    # accel cmd comes from DSU, but we can spam can to cancel the system even if we are using lat only control
    if (frame % 3 == 0 and ECU.DSU in self.fake_ecus) or (pcm_cancel_cmd and ECU.CAM in self.fake_ecus):
      lead = lead or CS.v_ego < 12.    # at low speed we always assume the lead is present do ACC can be engaged

      # Lexus IS uses a different cancellation message
      if pcm_cancel_cmd and CS.CP.carFingerprint == CAR.LEXUS_IS:
        can_sends.append(create_acc_cancel_command(self.packer))
      elif ECU.DSU in self.fake_ecus:
        can_sends.append(create_accel_command(self.packer, apply_accel, pcm_cancel_cmd, self.standstill_req, lead))
      else:
        can_sends.append(create_accel_command(self.packer, 0, pcm_cancel_cmd, False, lead))

    if (frame % 2 == 0) and (CS.CP.enableGasInterceptor):
        # send exactly zero if apply_gas is zero. Interceptor will send the max between read value and apply_gas.
        # This prevents unexpected pedal range rescaling
        can_sends.append(create_gas_command(self.packer, apply_gas, frame//2))

    if frame % 10 == 0 and ECU.CAM in self.fake_ecus and not forwarding_camera:
      for addr in TARGET_IDS:
        can_sends.append(create_video_target(frame//10, addr))

    # ui mesg is at 100Hz but we send asap if:
    # - there is something to display
    # - there is something to stop displaying
    alert_out = process_hud_alert(hud_alert)
    steer, fcw = alert_out

    if (any(alert_out) and not self.alert_active) or \
       (not any(alert_out) and self.alert_active):
      send_ui = True
      self.alert_active = not self.alert_active
    else:
      send_ui = False

    # disengage msg causes a bad fault sound so play a good sound instead
    if pcm_cancel_cmd:
      send_ui = True

    if (frame % 100 == 0 or send_ui) and ECU.CAM in self.fake_ecus:
      can_sends.append(create_ui_command(self.packer, steer, pcm_cancel_cmd, left_line, right_line, left_lane_depart, right_lane_depart))

    if frame % 100 == 0 and ECU.DSU in self.fake_ecus and self.car_fingerprint not in TSS2_CAR:
      can_sends.append(create_fcw_command(self.packer, fcw))

    #*** static msgs ***

    for (addr, ecu, cars, bus, fr_step, vl) in STATIC_MSGS:
      if frame % fr_step == 0 and ecu in self.fake_ecus and self.car_fingerprint in cars and not (ecu == ECU.CAM and forwarding_camera):
        # special cases
        if fr_step == 5 and ecu == ECU.CAM and bus == 1:
          cnt = (((frame // 5) % 7) + 1) << 5
          vl = bytes([cnt]) + vl
        elif addr in (0x489, 0x48a) and bus == 0:
          # add counter for those 2 messages (last 4 bits)
          cnt = ((frame // 100) % 0xf) + 1
          if addr == 0x48a:
            # 0x48a has a 8 preceding the counter
            cnt += 1 << 7
          vl += bytes([cnt])

        can_sends.append(make_can_msg(addr, vl, bus, False))

    return can_sends
    def update(self, enabled, CS, frame, actuators, pcm_cancel_cmd, hud_alert,
               left_line, right_line, lead, left_lane_depart,
               right_lane_depart):

        # *** compute control surfaces ***

        # gas and brake

        apply_gas = clip(actuators.gas, 0., 1.)

        if CS.CP.enableGasInterceptor:
            # send only negative accel if interceptor is detected. otherwise, send the regular value
            # +0.06 offset to reduce ABS pump usage when OP is engaged
            apply_accel = 0.06 - actuators.brake
        else:
            apply_accel = actuators.gas - actuators.brake

        apply_accel, self.accel_steady = accel_hysteresis(
            apply_accel, self.accel_steady, enabled)
        apply_accel = clip(apply_accel * CarControllerParams.ACCEL_SCALE,
                           CarControllerParams.ACCEL_MIN,
                           CarControllerParams.ACCEL_MAX)

        # steer torque
        new_steer = int(round(actuators.steer * CarControllerParams.STEER_MAX))
        apply_steer = apply_toyota_steer_torque_limits(
            new_steer, self.last_steer, CS.out.steeringTorqueEps,
            CarControllerParams)
        self.steer_rate_limited = new_steer != apply_steer

        # Cut steering while we're in a known fault state (2s)
        if not enabled or CS.steer_state in [9, 25]:
            apply_steer = 0
            apply_steer_req = 0
        else:
            apply_steer_req = 1

        if not enabled and CS.pcm_acc_status:
            # send pcm acc cancel cmd if drive is disabled but pcm is still on, or if the system can't be activated
            pcm_cancel_cmd = 1

        # on entering standstill, send standstill request
        if CS.out.standstill and not self.last_standstill and CS.CP.carFingerprint not in NO_STOP_TIMER_CAR:
            self.standstill_req = True
        if CS.pcm_acc_status != 8:
            # pcm entered standstill or it's disabled
            self.standstill_req = False

        self.last_steer = apply_steer
        self.last_accel = apply_accel
        self.last_standstill = CS.out.standstill

        can_sends = []

        #*** control msgs ***
        #print("steer {0} {1} {2} {3}".format(apply_steer, min_lim, max_lim, CS.steer_torque_motor)

        # toyota can trace shows this message at 42Hz, with counter adding alternatively 1 and 2;
        # sending it at 100Hz seem to allow a higher rate limit, as the rate limit seems imposed
        # on consecutive messages
        if Ecu.fwdCamera in self.fake_ecus:
            can_sends.append(
                create_steer_command(self.packer, apply_steer, apply_steer_req,
                                     frame))

            # LTA mode. Set ret.steerControlType = car.CarParams.SteerControlType.angle and whitelist 0x191 in the panda
            # if frame % 2 == 0:
            #   can_sends.append(create_steer_command(self.packer, 0, 0, frame // 2))
            #   can_sends.append(create_lta_steer_command(self.packer, actuators.steeringAngleDeg, apply_steer_req, frame // 2))

        # we can spam can to cancel the system even if we are using lat only control
        if (frame % 3 == 0 and CS.CP.openpilotLongitudinalControl) or (
                pcm_cancel_cmd and Ecu.fwdCamera in self.fake_ecus):
            lead = lead or CS.out.vEgo < 12.  # at low speed we always assume the lead is present do ACC can be engaged

            # Lexus IS uses a different cancellation message
            if pcm_cancel_cmd and CS.CP.carFingerprint == CAR.LEXUS_IS:
                can_sends.append(create_acc_cancel_command(self.packer))
            elif CS.CP.openpilotLongitudinalControl:
                can_sends.append(
                    create_accel_command(self.packer, apply_accel,
                                         pcm_cancel_cmd, self.standstill_req,
                                         lead))
            else:
                can_sends.append(
                    create_accel_command(self.packer, 0, pcm_cancel_cmd, False,
                                         lead))

        if (frame % 2 == 0) and (CS.CP.enableGasInterceptor):
            # send exactly zero if apply_gas is zero. Interceptor will send the max between read value and apply_gas.
            # This prevents unexpected pedal range rescaling
            can_sends.append(
                create_gas_command(self.packer, apply_gas, frame // 2))

        # ui mesg is at 100Hz but we send asap if:
        # - there is something to display
        # - there is something to stop displaying
        fcw_alert = hud_alert == VisualAlert.fcw
        steer_alert = hud_alert == VisualAlert.steerRequired

        send_ui = False
        if ((fcw_alert or steer_alert) and not self.alert_active) or \
           (not (fcw_alert or steer_alert) and self.alert_active):
            send_ui = True
            self.alert_active = not self.alert_active
        elif pcm_cancel_cmd:
            # forcing the pcm to disengage causes a bad fault sound so play a good sound instead
            send_ui = True

        if (frame % 100 == 0 or send_ui) and Ecu.fwdCamera in self.fake_ecus:
            can_sends.append(
                create_ui_command(self.packer, steer_alert, pcm_cancel_cmd,
                                  left_line, right_line, left_lane_depart,
                                  right_lane_depart))

        if frame % 100 == 0 and Ecu.dsu in self.fake_ecus:
            can_sends.append(create_fcw_command(self.packer, fcw_alert))

        #*** static msgs ***

        for (addr, ecu, cars, bus, fr_step, vl) in STATIC_MSGS:
            if frame % fr_step == 0 and ecu in self.fake_ecus and CS.CP.carFingerprint in cars:
                can_sends.append(make_can_msg(addr, vl, bus))

        return can_sends
Example #7
0
    def update(self, enabled, CS, frame, actuators, pcm_cancel_cmd, hud_alert,
               left_line, right_line, lead, left_lane_depart,
               right_lane_depart):

        # dp
        if frame % 500 == 0:
            modified = get_last_modified()
            if self.dp_last_modified != modified:
                self.dragon_lane_departure_warning = False if params.get(
                    "DragonToyotaLaneDepartureWarning",
                    encoding='utf8') == "0" else True
                self.dragon_toyota_sng_mod = True if params.get(
                    "DragonToyotaSnGMod", encoding='utf8') == "1" else False

                self.dragon_lat_ctrl, \
                self.dragon_enable_steering_on_signal, \
                self.dragon_blinker_off_timer = common_controller_update()

                self.dp_last_modified = modified

        # *** compute control surfaces ***

        # gas and brake

        apply_gas = clip(actuators.gas, 0., 1.)

        if CS.CP.enableGasInterceptor:
            # send only negative accel if interceptor is detected. otherwise, send the regular value
            # +0.06 offset to reduce ABS pump usage when OP is engaged
            apply_accel = 0.06 - actuators.brake
        else:
            apply_accel = actuators.gas - actuators.brake

        apply_accel, self.accel_steady = accel_hysteresis(
            apply_accel, self.accel_steady, enabled)
        apply_accel = clip(apply_accel * ACCEL_SCALE, ACCEL_MIN, ACCEL_MAX)

        # steer torque
        new_steer = int(round(actuators.steer * SteerLimitParams.STEER_MAX))
        apply_steer = apply_toyota_steer_torque_limits(
            new_steer, self.last_steer, CS.out.steeringTorqueEps,
            SteerLimitParams)
        self.steer_rate_limited = new_steer != apply_steer

        # only cut torque when steer state is a known fault
        if CS.steer_state in [9, 25]:
            self.last_fault_frame = frame

        # # Cut steering for 2s after fault
        if not enabled:  # or (frame - self.last_fault_frame < 200):
            apply_steer = 0
            apply_steer_req = 0
        else:
            apply_steer_req = 1

        if not enabled and CS.pcm_acc_status:
            # send pcm acc cancel cmd if drive is disabled but pcm is still on, or if the system can't be activated
            pcm_cancel_cmd = 1

        # on entering standstill, send standstill request
        if not self.dragon_toyota_sng_mod and CS.out.standstill and not self.last_standstill:
            self.standstill_req = True
        if CS.pcm_acc_status != 8:
            # pcm entered standstill or it's disabled
            self.standstill_req = False

        self.last_steer = apply_steer
        self.last_accel = apply_accel
        self.last_standstill = CS.out.standstill

        # dp
        blinker_on = CS.out.leftBlinker or CS.out.rightBlinker
        if not enabled:
            self.blinker_end_frame = 0
        if self.last_blinker_on and not blinker_on:
            self.blinker_end_frame = frame + self.dragon_blinker_off_timer
        apply_steer_req = common_controller_ctrl(
            enabled, self.dragon_lat_ctrl,
            self.dragon_enable_steering_on_signal, blinker_on
            or frame < self.blinker_end_frame, apply_steer_req)
        self.last_blinker_on = blinker_on

        can_sends = []

        #*** control msgs ***
        #print("steer {0} {1} {2} {3}".format(apply_steer, min_lim, max_lim, CS.steer_torque_motor)

        # toyota can trace shows this message at 42Hz, with counter adding alternatively 1 and 2;
        # sending it at 100Hz seem to allow a higher rate limit, as the rate limit seems imposed
        # on consecutive messages
        if Ecu.fwdCamera in self.fake_ecus:
            can_sends.append(
                create_steer_command(self.packer, apply_steer, apply_steer_req,
                                     frame))

        # we can spam can to cancel the system even if we are using lat only control
        if (frame % 3 == 0 and CS.CP.openpilotLongitudinalControl) or (
                pcm_cancel_cmd and Ecu.fwdCamera in self.fake_ecus):
            lead = lead or CS.out.vEgo < 12.  # at low speed we always assume the lead is present do ACC can be engaged

            # Lexus IS uses a different cancellation message
            if pcm_cancel_cmd and CS.CP.carFingerprint in [
                    CAR.LEXUS_IS, CAR.LEXUS_ISH, CAR.LEXUS_GSH
            ]:
                can_sends.append(create_acc_cancel_command(self.packer))
            elif CS.CP.openpilotLongitudinalControl:
                can_sends.append(
                    create_accel_command(self.packer, apply_accel,
                                         pcm_cancel_cmd, self.standstill_req,
                                         lead))
            else:
                can_sends.append(
                    create_accel_command(self.packer, 0, pcm_cancel_cmd, False,
                                         lead))

        if (frame % 2 == 0) and (CS.CP.enableGasInterceptor):
            # send exactly zero if apply_gas is zero. Interceptor will send the max between read value and apply_gas.
            # This prevents unexpected pedal range rescaling
            can_sends.append(
                create_gas_command(self.packer, apply_gas, frame // 2))

        # ui mesg is at 100Hz but we send asap if:
        # - there is something to display
        # - there is something to stop displaying
        fcw_alert = hud_alert == VisualAlert.fcw
        steer_alert = hud_alert == VisualAlert.steerRequired

        send_ui = False
        if ((fcw_alert or steer_alert) and not self.alert_active) or \
           (not (fcw_alert or steer_alert) and self.alert_active):
            send_ui = True
            self.alert_active = not self.alert_active
        elif pcm_cancel_cmd:
            # forcing the pcm to disengage causes a bad fault sound so play a good sound instead
            send_ui = True

        # dp
        if self.dragon_lane_departure_warning:
            dragon_left_lane_depart = left_lane_depart
            dragon_right_lane_depart = right_lane_depart
        else:
            dragon_left_lane_depart = False
            dragon_right_lane_depart = False

        if (frame % 100 == 0 or send_ui) and Ecu.fwdCamera in self.fake_ecus:
            can_sends.append(
                create_ui_command(self.packer, steer_alert, pcm_cancel_cmd,
                                  left_line, right_line,
                                  dragon_left_lane_depart,
                                  dragon_right_lane_depart))

        if frame % 100 == 0 and Ecu.dsu in self.fake_ecus:
            can_sends.append(create_fcw_command(self.packer, fcw_alert))

        #*** static msgs ***

        for (addr, ecu, cars, bus, fr_step, vl) in STATIC_MSGS:
            if frame % fr_step == 0 and ecu in self.fake_ecus and CS.CP.carFingerprint in cars:
                can_sends.append(make_can_msg(addr, vl, bus))

        return can_sends