Deprecate carState.events (#33693)

* add lkas bools

* switch these two over

* bump

* deprecate low speed lockout

* add lowSpeedAlert bool

bump

* GM vehicle speed is now signed!

* reimagine

* rm

* do event

* bump

* STASH

* comment

* bump

* no out!

* format

* move almost everything to selfdrived

* add back CC_prev for cruise initialization

* ok

* errors are passed to radarState as well as freq check

* deprecate!

* use selfdrived for test models events

* we only want noEntry from car events, not system, have to check pedalPressed

* no more events

* regen with buttonEvents set properly

* update refs
pull/33719/head
Shane Smiskol 7 months ago committed by GitHub
parent 3ca158ad3e
commit aed1eaede5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 3
      cereal/car.capnp
  2. 66
      selfdrive/car/car_specific.py
  3. 38
      selfdrive/car/card.py
  4. 15
      selfdrive/car/tests/test_models.py
  5. 25
      selfdrive/selfdrived/selfdrived.py
  6. 2
      selfdrive/test/process_replay/README.md
  7. 2
      selfdrive/test/process_replay/ref_commit
  8. 4
      selfdrive/test/process_replay/test_processes.py

@ -157,8 +157,6 @@ struct OnroadEvent @0x9b1657f34caf3ad3 {
# all speeds in m/s
struct CarState {
events @13 :List(OnroadEvent);
# CAN health
canValid @26 :Bool; # invalid counter/checksums
canTimeout @40 :Bool; # CAN bus dropped out
@ -296,6 +294,7 @@ struct CarState {
steeringRateLimitedDEPRECATED @29 :Bool;
canMonoTimesDEPRECATED @12: List(UInt64);
canRcvTimeoutDEPRECATED @49 :Bool;
eventsDEPRECATED @13 :List(OnroadEvent);
}
# ******* radar state @ 20hz *******

@ -2,7 +2,7 @@ from collections import deque
from cereal import car
import cereal.messaging as messaging
from opendbc.car import DT_CTRL, structs
from opendbc.car.interfaces import MAX_CTRL_SPEED, CarStateBase
from opendbc.car.interfaces import MAX_CTRL_SPEED
from opendbc.car.volkswagen.values import CarControllerParams as VWCarControllerParams
from opendbc.car.hyundai.interface import ENABLE_BUTTONS as HYUNDAI_ENABLE_BUTTONS
from opendbc.car.hyundai.carstate import PREV_BUTTON_SAMPLES as HYUNDAI_PREV_BUTTON_SAMPLES
@ -41,102 +41,102 @@ class CarSpecificEvents:
self.cruise_buttons: deque = deque([], maxlen=HYUNDAI_PREV_BUTTON_SAMPLES)
def update(self, CS: CarStateBase, CS_prev: car.CarState, CC_prev: car.CarControl):
def update(self, CS: car.CarState, CS_prev: car.CarState, CC: car.CarControl):
if self.CP.carName in ('body', 'mock'):
events = Events()
elif self.CP.carName in ('subaru', 'mazda'):
events = self.create_common_events(CS.out, CS_prev)
events = self.create_common_events(CS, CS_prev)
elif self.CP.carName == 'ford':
events = self.create_common_events(CS.out, CS_prev, extra_gears=[GearShifter.manumatic])
events = self.create_common_events(CS, CS_prev, extra_gears=[GearShifter.manumatic])
elif self.CP.carName == 'nissan':
events = self.create_common_events(CS.out, CS_prev, extra_gears=[GearShifter.brake])
events = self.create_common_events(CS, CS_prev, extra_gears=[GearShifter.brake])
elif self.CP.carName == 'chrysler':
events = self.create_common_events(CS.out, CS_prev, extra_gears=[GearShifter.low])
events = self.create_common_events(CS, CS_prev, extra_gears=[GearShifter.low])
# Low speed steer alert hysteresis logic
if self.CP.minSteerSpeed > 0. and CS.out.vEgo < (self.CP.minSteerSpeed + 0.5):
if self.CP.minSteerSpeed > 0. and CS.vEgo < (self.CP.minSteerSpeed + 0.5):
self.low_speed_alert = True
elif CS.out.vEgo > (self.CP.minSteerSpeed + 1.):
elif CS.vEgo > (self.CP.minSteerSpeed + 1.):
self.low_speed_alert = False
if self.low_speed_alert:
events.add(EventName.belowSteerSpeed)
elif self.CP.carName == 'honda':
events = self.create_common_events(CS.out, CS_prev, pcm_enable=False)
events = self.create_common_events(CS, CS_prev, pcm_enable=False)
if self.CP.pcmCruise and CS.out.vEgo < self.CP.minEnableSpeed:
if self.CP.pcmCruise and CS.vEgo < self.CP.minEnableSpeed:
events.add(EventName.belowEngageSpeed)
if self.CP.pcmCruise:
# we engage when pcm is active (rising edge)
if CS.out.cruiseState.enabled and not CS_prev.cruiseState.enabled:
if CS.cruiseState.enabled and not CS_prev.cruiseState.enabled:
events.add(EventName.pcmEnable)
elif not CS.out.cruiseState.enabled and (CC_prev.actuators.accel >= 0. or not self.CP.openpilotLongitudinalControl):
elif not CS.cruiseState.enabled and (CC.actuators.accel >= 0. or not self.CP.openpilotLongitudinalControl):
# it can happen that car cruise disables while comma system is enabled: need to
# keep braking if needed or if the speed is very low
if CS.out.vEgo < self.CP.minEnableSpeed + 2.:
if CS.vEgo < self.CP.minEnableSpeed + 2.:
# non loud alert if cruise disables below 25mph as expected (+ a little margin)
events.add(EventName.speedTooLow)
else:
events.add(EventName.cruiseDisabled)
if self.CP.minEnableSpeed > 0 and CS.out.vEgo < 0.001:
if self.CP.minEnableSpeed > 0 and CS.vEgo < 0.001:
events.add(EventName.manualRestart)
elif self.CP.carName == 'toyota':
events = self.create_common_events(CS.out, CS_prev)
events = self.create_common_events(CS, CS_prev)
if self.CP.openpilotLongitudinalControl:
if CS.out.cruiseState.standstill and not CS.out.brakePressed:
if CS.cruiseState.standstill and not CS.brakePressed:
events.add(EventName.resumeRequired)
if CS.out.vEgo < self.CP.minEnableSpeed:
if CS.vEgo < self.CP.minEnableSpeed:
events.add(EventName.belowEngageSpeed)
if CC_prev.actuators.accel > 0.3:
if CC.actuators.accel > 0.3:
# some margin on the actuator to not false trigger cancellation while stopping
events.add(EventName.speedTooLow)
if CS.out.vEgo < 0.001:
if CS.vEgo < 0.001:
# while in standstill, send a user alert
events.add(EventName.manualRestart)
elif self.CP.carName == 'gm':
# The ECM allows enabling on falling edge of set, but only rising edge of resume
events = self.create_common_events(CS.out, CS_prev, extra_gears=[GearShifter.sport, GearShifter.low,
events = self.create_common_events(CS, CS_prev, extra_gears=[GearShifter.sport, GearShifter.low,
GearShifter.eco, GearShifter.manumatic],
pcm_enable=self.CP.pcmCruise, enable_buttons=(ButtonType.decelCruise,))
if not self.CP.pcmCruise:
if any(b.type == ButtonType.accelCruise and b.pressed for b in CS.out.buttonEvents):
if any(b.type == ButtonType.accelCruise and b.pressed for b in CS.buttonEvents):
events.add(EventName.buttonEnable)
# Enabling at a standstill with brake is allowed
# TODO: verify 17 Volt can enable for the first time at a stop and allow for all GMs
if CS.out.vEgo < self.CP.minEnableSpeed and not (CS.out.standstill and CS.out.brake >= 20 and
if CS.vEgo < self.CP.minEnableSpeed and not (CS.standstill and CS.brake >= 20 and
self.CP.networkLocation == NetworkLocation.fwdCamera):
events.add(EventName.belowEngageSpeed)
if CS.out.cruiseState.standstill:
if CS.cruiseState.standstill:
events.add(EventName.resumeRequired)
if CS.out.vEgo < self.CP.minSteerSpeed:
if CS.vEgo < self.CP.minSteerSpeed:
events.add(EventName.belowSteerSpeed)
elif self.CP.carName == 'volkswagen':
events = self.create_common_events(CS.out, CS_prev, extra_gears=[GearShifter.eco, GearShifter.sport, GearShifter.manumatic],
events = self.create_common_events(CS, CS_prev, extra_gears=[GearShifter.eco, GearShifter.sport, GearShifter.manumatic],
pcm_enable=not self.CP.openpilotLongitudinalControl,
enable_buttons=(ButtonType.setCruise, ButtonType.resumeCruise))
# Low speed steer alert hysteresis logic
if (self.CP.minSteerSpeed - 1e-3) > VWCarControllerParams.DEFAULT_MIN_STEER_SPEED and CS.out.vEgo < (self.CP.minSteerSpeed + 1.):
if (self.CP.minSteerSpeed - 1e-3) > VWCarControllerParams.DEFAULT_MIN_STEER_SPEED and CS.vEgo < (self.CP.minSteerSpeed + 1.):
self.low_speed_alert = True
elif CS.out.vEgo > (self.CP.minSteerSpeed + 2.):
elif CS.vEgo > (self.CP.minSteerSpeed + 2.):
self.low_speed_alert = False
if self.low_speed_alert:
events.add(EventName.belowSteerSpeed)
if self.CP.openpilotLongitudinalControl:
if CS.out.vEgo < self.CP.minEnableSpeed + 0.5:
if CS.vEgo < self.CP.minEnableSpeed + 0.5:
events.add(EventName.belowEngageSpeed)
if CC_prev.enabled and CS.out.vEgo < self.CP.minEnableSpeed:
if CC.enabled and CS.vEgo < self.CP.minEnableSpeed:
events.add(EventName.speedTooLow)
# TODO: this needs to be implemented generically in carState struct
@ -147,13 +147,13 @@ class CarSpecificEvents:
# On some newer model years, the CANCEL button acts as a pause/resume button based on the PCM state
# To avoid re-engaging when openpilot cancels, check user engagement intention via buttons
# Main button also can trigger an engagement on these cars
self.cruise_buttons.append(any(ev.type in HYUNDAI_ENABLE_BUTTONS for ev in CS.out.buttonEvents))
events = self.create_common_events(CS.out, CS_prev, pcm_enable=self.CP.pcmCruise, allow_enable=any(self.cruise_buttons))
self.cruise_buttons.append(any(ev.type in HYUNDAI_ENABLE_BUTTONS for ev in CS.buttonEvents))
events = self.create_common_events(CS, CS_prev, pcm_enable=self.CP.pcmCruise, allow_enable=any(self.cruise_buttons))
# low speed steer alert hysteresis logic (only for cars with steer cut off above 10 m/s)
if CS.out.vEgo < (self.CP.minSteerSpeed + 2.) and self.CP.minSteerSpeed > 10.:
if CS.vEgo < (self.CP.minSteerSpeed + 2.) and self.CP.minSteerSpeed > 10.:
self.low_speed_alert = True
if CS.out.vEgo > (self.CP.minSteerSpeed + 4.):
if CS.vEgo > (self.CP.minSteerSpeed + 4.):
self.low_speed_alert = False
if self.low_speed_alert:
events.add(EventName.belowSteerSpeed)

@ -20,9 +20,8 @@ from opendbc.car.car_helpers import get_car, get_radar_interface
from opendbc.car.interfaces import CarInterfaceBase, RadarInterfaceBase
from openpilot.selfdrive.pandad import can_capnp_to_list, can_list_to_can_capnp
from openpilot.selfdrive.car.cruise import VCruiseHelper
from openpilot.selfdrive.car.car_specific import CarSpecificEvents, MockCarState
from openpilot.selfdrive.car.car_specific import MockCarState
from openpilot.selfdrive.car.helpers import convert_carControl, convert_to_capnp
from openpilot.selfdrive.selfdrived.events import Events, ET
REPLAY = "REPLAY" in os.environ
@ -112,9 +111,9 @@ class Car:
self.RI = RI
# set alternative experiences from parameters
self.disengage_on_accelerator = self.params.get_bool("DisengageOnAccelerator")
disengage_on_accelerator = self.params.get_bool("DisengageOnAccelerator")
self.CP.alternativeExperience = 0
if not self.disengage_on_accelerator:
if not disengage_on_accelerator:
self.CP.alternativeExperience |= ALTERNATIVE_EXPERIENCE.DISABLE_DISENGAGE_ON_GAS
openpilot_enabled_toggle = self.params.get_bool("OpenpilotEnabledToggle")
@ -152,9 +151,6 @@ class Car:
self.params.put_nonblocking("CarParamsCache", cp_bytes)
self.params.put_nonblocking("CarParamsPersistent", cp_bytes)
self.events = Events()
self.car_events = CarSpecificEvents(self.CP)
self.mock_carstate = MockCarState()
self.v_cruise_helper = VCruiseHelper(self.CP)
@ -196,30 +192,6 @@ class Car:
return CS, RD
def update_events(self, CS: car.CarState, RD: structs.RadarData | None):
self.events.clear()
CS.events = self.car_events.update(self.CI.CS, self.CS_prev, self.CC_prev).to_msg()
self.events.add_from_msg(CS.events)
if self.CP.notCar:
# wait for everything to init first
if self.sm.frame > int(5. / DT_CTRL) and self.initialized_prev:
# body always wants to enable
self.events.add(EventName.pcmEnable)
# Disable on rising edge of accelerator or brake. Also disable on brake when speed > 0
if (CS.gasPressed and not self.CS_prev.gasPressed and self.disengage_on_accelerator) or \
(CS.brakePressed and (not self.CS_prev.brakePressed or not CS.standstill)) or \
(CS.regenBraking and (not self.CS_prev.regenBraking or not CS.standstill)):
self.events.add(EventName.pedalPressed)
if RD is not None and len(RD.errors):
self.events.add(EventName.radarFault)
CS.events = self.events.to_msg()
def state_publish(self, CS: car.CarState, RD: structs.RadarData | None):
"""carState and carParams publish loop"""
@ -271,9 +243,7 @@ class Car:
def step(self):
CS, RD = self.state_update()
self.update_events(CS, RD)
if not self.sm['carControl'].enabled and self.events.contains(ET.ENABLE):
if self.sm['carControl'].enabled and not self.CC_prev.enabled:
self.v_cruise_helper.initialize_v_cruise(CS, self.experimental_mode)
self.state_publish(CS, RD)

@ -20,7 +20,9 @@ from opendbc.car.car_helpers import FRAME_FINGERPRINT, interfaces
from opendbc.car.honda.values import CAR as HONDA, HondaFlags
from opendbc.car.values import Platform
from opendbc.car.tests.routes import non_tested_cars, routes, CarTestRoute
from openpilot.selfdrive.car.card import Car, convert_to_capnp
from openpilot.selfdrive.car.card import convert_to_capnp
from openpilot.selfdrive.selfdrived.events import ET
from openpilot.selfdrive.selfdrived.selfdrived import SelfdriveD
from openpilot.selfdrive.pandad import can_capnp_to_list
from openpilot.selfdrive.test.helpers import read_segment_list
from openpilot.system.hardware.hw import DEFAULT_DOWNLOAD_CACHE_ROOT
@ -404,7 +406,8 @@ class TestCarModelBase(unittest.TestCase):
controls_allowed_prev = False
CS_prev = car.CarState.new_message()
checks = defaultdict(int)
card = Car(CI=self.CI)
selfdrived = SelfdriveD(CP=self.CP)
selfdrived.initialized = True
for idx, can in enumerate(self.can_msgs):
CS = convert_to_capnp(self.CI.update(can_capnp_to_list((can.as_builder().to_bytes(), ))))
for msg in filter(lambda m: m.src in range(64), can.can):
@ -449,10 +452,10 @@ class TestCarModelBase(unittest.TestCase):
checks['cruiseState'] += CS.cruiseState.enabled != self.safety.get_cruise_engaged_prev()
else:
# Check for enable events on rising edge of controls allowed
card.update_events(CS, None)
card.CS_prev = CS
button_enable = (any(evt.enable for evt in CS.events) and
not any(evt == EventName.pedalPressed for evt in card.events.names))
selfdrived.update_events(CS)
selfdrived.CS_prev = CS
button_enable = (selfdrived.events.contains(ET.ENABLE) and
EventName.pedalPressed not in selfdrived.events.names)
mismatch = button_enable != (self.safety.get_controls_allowed() and not controls_allowed_prev)
checks['controlsAllowed'] += mismatch
controls_allowed_prev = self.safety.get_controls_allowed()

@ -7,6 +7,7 @@ import cereal.messaging as messaging
from cereal import car, log
from msgq.visionipc import VisionIpcClient, VisionStreamType
from panda import ALTERNATIVE_EXPERIENCE
from openpilot.common.params import Params
@ -14,6 +15,7 @@ from openpilot.common.realtime import config_realtime_process, Priority, Ratekee
from openpilot.common.swaglog import cloudlog
from openpilot.common.gps import get_gps_location_service
from openpilot.selfdrive.car.car_specific import CarSpecificEvents
from openpilot.selfdrive.selfdrived.events import Events, ET
from openpilot.selfdrive.selfdrived.state import StateMachine
from openpilot.selfdrive.selfdrived.alertmanager import AlertManager, set_offroad_alert
@ -41,15 +43,21 @@ IGNORED_SAFETY_MODES = (SafetyModel.silent, SafetyModel.noOutput)
class SelfdriveD:
def __init__(self):
def __init__(self, CP=None):
self.params = Params()
# Ensure the current branch is cached, otherwise the first cycle lags
build_metadata = get_build_metadata()
if CP is None:
cloudlog.info("selfdrived is waiting for CarParams")
self.CP = messaging.log_from_bytes(self.params.get("CarParams", block=True), car.CarParams)
cloudlog.info("selfdrived got CarParams")
else:
self.CP = CP
self.car_events = CarSpecificEvents(self.CP)
self.disengage_on_accelerator = not (self.CP.alternativeExperience & ALTERNATIVE_EXPERIENCE.DISABLE_DISENGAGE_ON_GAS)
# Setup sockets
self.pm = messaging.PubMaster(['selfdriveState', 'onroadEvents'])
@ -166,7 +174,20 @@ class SelfdriveD:
# Add car events, ignore if CAN isn't valid
if CS.canValid:
self.events.add_from_msg(CS.events)
car_events = self.car_events.update(CS, self.CS_prev, self.sm['carControl']).to_msg()
self.events.add_from_msg(car_events)
if self.CP.notCar:
# wait for everything to init first
if self.sm.frame > int(5. / DT_CTRL) and self.initialized:
# body always wants to enable
self.events.add(EventName.pcmEnable)
# Disable on rising edge of accelerator or brake. Also disable on brake when speed > 0
if (CS.gasPressed and not self.CS_prev.gasPressed and self.disengage_on_accelerator) or \
(CS.brakePressed and (not self.CS_prev.brakePressed or not CS.standstill)) or \
(CS.regenBraking and (not self.CS_prev.regenBraking or not CS.standstill)):
self.events.add(EventName.pedalPressed)
# Create events for temperature, disk space, and memory
if self.sm['deviceState'].thermalStatus >= ThermalStatus.red:

@ -30,7 +30,7 @@ optional arguments:
--whitelist-cars WHITELIST_CARS Whitelist given cars from the test (e.g. HONDA)
--blacklist-procs BLACKLIST_PROCS Blacklist given processes from the test (e.g. controlsd)
--blacklist-cars BLACKLIST_CARS Blacklist given cars from the test (e.g. HONDA)
--ignore-fields IGNORE_FIELDS Extra fields or msgs to ignore (e.g. carState.events)
--ignore-fields IGNORE_FIELDS Extra fields or msgs to ignore (e.g. driverMonitoringState.events)
--ignore-msgs IGNORE_MSGS Msgs to ignore (e.g. onroadEvents)
--update-refs Updates reference logs using current commit
--upload-only Skips testing processes and uploads logs from previous test run

@ -1 +1 @@
f9f1fd736c6bbef3aa2d3aea8e4f8e1c892234de
fbf16d1e9b056830a12fcf29a5137e1fc0b01354

@ -42,7 +42,7 @@ source_segments = [
segments = [
("BODY", "regenA67A128BCD8|2024-08-30--02-36-22--0"),
("HYUNDAI", "regen9CBD921E93E|2024-08-30--02-38-51--0"),
("HYUNDAI2", "regen12E0C4EA1A7|2024-08-30--02-42-40--0"),
("HYUNDAI2", "regen306779F6870|2024-10-03--04-03-23--0"),
("TOYOTA", "regen1CA7A48E6F7|2024-08-30--02-45-08--0"),
("TOYOTA2", "regen6E484EDAB96|2024-08-30--02-47-37--0"),
("TOYOTA3", "regen4CE950B0267|2024-08-30--02-51-30--0"),
@ -135,7 +135,7 @@ if __name__ == "__main__":
parser.add_argument("--blacklist-cars", type=str, nargs="*", default=[],
help="Blacklist given cars from the test (e.g. HONDA)")
parser.add_argument("--ignore-fields", type=str, nargs="*", default=[],
help="Extra fields or msgs to ignore (e.g. carState.events)")
help="Extra fields or msgs to ignore (e.g. driverMonitoringState.events)")
parser.add_argument("--ignore-msgs", type=str, nargs="*", default=[],
help="Msgs to ignore (e.g. carEvents)")
parser.add_argument("--update-refs", action="store_true",

Loading…
Cancel
Save