From eed6803ccc55ecbfab4bd52a7ea62c9942243aea Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Wed, 1 Jun 2022 12:03:34 -0700 Subject: [PATCH] Button-enable cars: common functions for button events (#24678) * function for creating button events * fix * one line * alphabetical alphabetical * only needed once * common function for enable events * add to list * extend * fixes * add type hints * flip around --- selfdrive/car/__init__.py | 31 +++++++++++++++++++- selfdrive/car/gm/interface.py | 42 ++++++++------------------ selfdrive/car/honda/interface.py | 47 +++++------------------------- selfdrive/car/hyundai/interface.py | 39 +++++-------------------- 4 files changed, 56 insertions(+), 103 deletions(-) diff --git a/selfdrive/car/__init__.py b/selfdrive/car/__init__.py index 7bb91c40f7..806a060f97 100644 --- a/selfdrive/car/__init__.py +++ b/selfdrive/car/__init__.py @@ -1,11 +1,40 @@ # functions common among cars +import capnp + from cereal import car from common.numpy_fast import clip -from typing import Dict +from typing import Dict, List # kg of standard extra cargo to count for drive, gas, etc... STD_CARGO_KG = 136. +ButtonType = car.CarState.ButtonEvent.Type +EventName = car.CarEvent.EventName + + +def create_button_event(cur_but: int, prev_but: int, buttons_dict: Dict[int, capnp.lib.capnp._EnumModule], + unpressed: int = 0) -> capnp.lib.capnp._DynamicStructBuilder: + if cur_but != unpressed: + be = car.CarState.ButtonEvent(pressed=True) + but = cur_but + else: + be = car.CarState.ButtonEvent(pressed=False) + but = prev_but + be.type = buttons_dict.get(but, ButtonType.unknown) + return be + + +def create_button_enable_events(buttonEvents: capnp.lib.capnp._DynamicListBuilder) -> List[int]: + events = [] + for b in buttonEvents: + # do enable on both accel and decel buttons + if b.type in (ButtonType.accelCruise, ButtonType.decelCruise) and not b.pressed: + events.append(EventName.buttonEnable) + # do disable on button down + if b.type == ButtonType.cancel and b.pressed: + events.append(EventName.buttonCancel) + return events + def gen_empty_fingerprint(): return {i: {} for i in range(0, 4)} diff --git a/selfdrive/car/gm/interface.py b/selfdrive/car/gm/interface.py index d00708c336..b4265fc0bd 100755 --- a/selfdrive/car/gm/interface.py +++ b/selfdrive/car/gm/interface.py @@ -3,12 +3,15 @@ from cereal import car from math import fabs from common.conversions import Conversions as CV -from selfdrive.car import STD_CARGO_KG, scale_rot_inertia, scale_tire_stiffness, gen_empty_fingerprint, get_safety_config +from selfdrive.car import STD_CARGO_KG, create_button_enable_events, create_button_event, scale_rot_inertia, scale_tire_stiffness, gen_empty_fingerprint, get_safety_config from selfdrive.car.gm.values import CAR, CruiseButtons, CarControllerParams from selfdrive.car.interfaces import CarInterfaceBase ButtonType = car.CarState.ButtonEvent.Type EventName = car.CarEvent.EventName +BUTTONS_DICT = {CruiseButtons.RES_ACCEL: ButtonType.accelCruise, CruiseButtons.DECEL_SET: ButtonType.decelCruise, + CruiseButtons.MAIN: ButtonType.altButton3, CruiseButtons.CANCEL: ButtonType.cancel} + class CarInterface(CarInterfaceBase): @staticmethod @@ -159,29 +162,14 @@ class CarInterface(CarInterfaceBase): ret.steeringRateLimited = self.CC.steer_rate_limited if self.CC is not None else False - buttonEvents = [] - if self.CS.cruise_buttons != self.CS.prev_cruise_buttons and self.CS.prev_cruise_buttons != CruiseButtons.INIT: - be = car.CarState.ButtonEvent.new_message() - be.type = ButtonType.unknown - if self.CS.cruise_buttons != CruiseButtons.UNPRESS: - be.pressed = True - but = self.CS.cruise_buttons - else: - be.pressed = False - but = self.CS.prev_cruise_buttons - if but == CruiseButtons.RES_ACCEL: - if not (ret.cruiseState.enabled and ret.standstill): - be.type = ButtonType.accelCruise # Suppress resume button if we're resuming from stop so we don't adjust speed. - elif but == CruiseButtons.DECEL_SET: - be.type = ButtonType.decelCruise - elif but == CruiseButtons.CANCEL: - be.type = ButtonType.cancel - elif but == CruiseButtons.MAIN: - be.type = ButtonType.altButton3 - buttonEvents.append(be) - - ret.buttonEvents = buttonEvents + be = create_button_event(self.CS.cruise_buttons, self.CS.prev_cruise_buttons, BUTTONS_DICT, CruiseButtons.UNPRESS) + + # Suppress resume button if we're resuming from stop so we don't adjust speed. + if be.type == ButtonType.accelCruise and (ret.cruiseState.enabled and ret.standstill): + be.type = ButtonType.unknown + + ret.buttonEvents = [be] events = self.create_common_events(ret, pcm_enable=False) @@ -193,13 +181,7 @@ class CarInterface(CarInterfaceBase): events.add(car.CarEvent.EventName.belowSteerSpeed) # handle button presses - for b in ret.buttonEvents: - # do enable on both accel and decel buttons - if b.type in (ButtonType.accelCruise, ButtonType.decelCruise) and not b.pressed: - events.add(EventName.buttonEnable) - # do disable on button down - if b.type == ButtonType.cancel and b.pressed: - events.add(EventName.buttonCancel) + events.events.extend(create_button_enable_events(ret.buttonEvents)) ret.events = events.to_msg() diff --git a/selfdrive/car/honda/interface.py b/selfdrive/car/honda/interface.py index 265175d940..5b97b3389f 100755 --- a/selfdrive/car/honda/interface.py +++ b/selfdrive/car/honda/interface.py @@ -4,7 +4,7 @@ from panda import Panda from common.conversions import Conversions as CV from common.numpy_fast import interp from selfdrive.car.honda.values import CarControllerParams, CruiseButtons, HondaFlags, CAR, HONDA_BOSCH, HONDA_NIDEC_ALT_SCM_MESSAGES, HONDA_BOSCH_ALT_BRAKE_SIGNAL -from selfdrive.car import STD_CARGO_KG, CivicParams, scale_rot_inertia, scale_tire_stiffness, gen_empty_fingerprint, get_safety_config +from selfdrive.car import STD_CARGO_KG, CivicParams, create_button_enable_events, create_button_event, scale_rot_inertia, scale_tire_stiffness, gen_empty_fingerprint, get_safety_config from selfdrive.car.interfaces import CarInterfaceBase from selfdrive.car.disable_ecu import disable_ecu @@ -12,6 +12,8 @@ from selfdrive.car.disable_ecu import disable_ecu ButtonType = car.CarState.ButtonEvent.Type EventName = car.CarEvent.EventName TransmissionType = car.CarParams.TransmissionType +BUTTONS_DICT = {CruiseButtons.RES_ACCEL: ButtonType.accelCruise, CruiseButtons.DECEL_SET: ButtonType.decelCruise, + CruiseButtons.MAIN: ButtonType.altButton3, CruiseButtons.CANCEL: ButtonType.cancel} class CarInterface(CarInterfaceBase): @@ -334,37 +336,11 @@ class CarInterface(CarInterfaceBase): buttonEvents = [] if self.CS.cruise_buttons != self.CS.prev_cruise_buttons: - be = car.CarState.ButtonEvent.new_message() - be.type = ButtonType.unknown - if self.CS.cruise_buttons != 0: - be.pressed = True - but = self.CS.cruise_buttons - else: - be.pressed = False - but = self.CS.prev_cruise_buttons - if but == CruiseButtons.RES_ACCEL: - be.type = ButtonType.accelCruise - elif but == CruiseButtons.DECEL_SET: - be.type = ButtonType.decelCruise - elif but == CruiseButtons.CANCEL: - be.type = ButtonType.cancel - elif but == CruiseButtons.MAIN: - be.type = ButtonType.altButton3 - buttonEvents.append(be) + buttonEvents.append(create_button_event(self.CS.cruise_buttons, self.CS.prev_cruise_buttons, BUTTONS_DICT)) if self.CS.cruise_setting != self.CS.prev_cruise_setting: - be = car.CarState.ButtonEvent.new_message() - be.type = ButtonType.unknown - if self.CS.cruise_setting != 0: - be.pressed = True - but = self.CS.cruise_setting - else: - be.pressed = False - but = self.CS.prev_cruise_setting - if but == 1: - be.type = ButtonType.altButton1 - # TODO: more buttons? - buttonEvents.append(be) + buttonEvents.append(create_button_event(self.CS.cruise_setting, self.CS.prev_cruise_setting, {1: ButtonType.altButton1})) + ret.buttonEvents = buttonEvents # events @@ -391,16 +367,7 @@ class CarInterface(CarInterfaceBase): events.add(EventName.manualRestart) # handle button presses - for b in ret.buttonEvents: - - # do enable on both accel and decel buttons - if not self.CP.pcmCruise: - if b.type in (ButtonType.accelCruise, ButtonType.decelCruise) and not b.pressed: - events.add(EventName.buttonEnable) - - # do disable on button down - if b.type == ButtonType.cancel and b.pressed: - events.add(EventName.buttonCancel) + events.events.extend(create_button_enable_events(ret.buttonEvents)) ret.events = events.to_msg() diff --git a/selfdrive/car/hyundai/interface.py b/selfdrive/car/hyundai/interface.py index b4dc26c87a..7299e29ba8 100644 --- a/selfdrive/car/hyundai/interface.py +++ b/selfdrive/car/hyundai/interface.py @@ -4,7 +4,7 @@ from panda import Panda from common.conversions import Conversions as CV from selfdrive.car.hyundai.values import CAR, DBC, HDA2_CAR, EV_CAR, HYBRID_CAR, LEGACY_SAFETY_MODE_CAR, Buttons, CarControllerParams from selfdrive.car.hyundai.radar_interface import RADAR_START_ADDR -from selfdrive.car import STD_CARGO_KG, scale_rot_inertia, scale_tire_stiffness, gen_empty_fingerprint, get_safety_config +from selfdrive.car import STD_CARGO_KG, create_button_enable_events, create_button_event, scale_rot_inertia, scale_tire_stiffness, gen_empty_fingerprint, get_safety_config from selfdrive.car.interfaces import CarInterfaceBase from selfdrive.car.disable_ecu import disable_ecu from selfdrive.controls.lib.latcontrol_torque import set_torque_tune @@ -12,6 +12,8 @@ from selfdrive.controls.lib.latcontrol_torque import set_torque_tune ButtonType = car.CarState.ButtonEvent.Type EventName = car.CarEvent.EventName ENABLE_BUTTONS = (Buttons.RES_ACCEL, Buttons.SET_DECEL, Buttons.CANCEL) +BUTTONS_DICT = {Buttons.RES_ACCEL: ButtonType.accelCruise, Buttons.SET_DECEL: ButtonType.decelCruise, + Buttons.GAP_DIST: ButtonType.gapAdjustCruise, Buttons.CANCEL: ButtonType.cancel} class CarInterface(CarInterfaceBase): @@ -338,37 +340,10 @@ class CarInterface(CarInterfaceBase): if self.CS.brake_error: events.add(EventName.brakeUnavailable) - if self.CS.CP.openpilotLongitudinalControl: - buttonEvents = [] - - if self.CS.cruise_buttons[-1] != self.CS.prev_cruise_buttons: - be = car.CarState.ButtonEvent.new_message() - be.type = ButtonType.unknown - if self.CS.cruise_buttons[-1] != 0: - be.pressed = True - but = self.CS.cruise_buttons[-1] - else: - be.pressed = False - but = self.CS.prev_cruise_buttons - if but == Buttons.RES_ACCEL: - be.type = ButtonType.accelCruise - elif but == Buttons.SET_DECEL: - be.type = ButtonType.decelCruise - elif but == Buttons.GAP_DIST: - be.type = ButtonType.gapAdjustCruise - elif but == Buttons.CANCEL: - be.type = ButtonType.cancel - buttonEvents.append(be) - - ret.buttonEvents = buttonEvents - - for b in ret.buttonEvents: - # do enable on both accel and decel buttons - if b.type in (ButtonType.accelCruise, ButtonType.decelCruise) and not b.pressed: - events.add(EventName.buttonEnable) - # do disable on button down - if b.type == ButtonType.cancel and b.pressed: - events.add(EventName.buttonCancel) + if self.CS.CP.openpilotLongitudinalControl and self.CS.cruise_buttons[-1] != self.CS.prev_cruise_buttons: + ret.buttonEvents = [create_button_event(self.CS.cruise_buttons[-1], self.CS.prev_cruise_buttons, BUTTONS_DICT)] + + events.events.extend(create_button_enable_events(ret.buttonEvents)) # low speed steer alert hysteresis logic (only for cars with steer cut off above 10 m/s) if ret.vEgo < (self.CP.minSteerSpeed + 2.) and self.CP.minSteerSpeed > 10.: