diff --git a/cereal/car.capnp b/cereal/car.capnp index d0edfc3..366b796 100644 --- a/cereal/car.capnp +++ b/cereal/car.capnp @@ -124,6 +124,7 @@ struct CarEvent @0x9b1657f34caf3ad3 { laneChangeBlockedLoud @125; leadDeparting @126; noLaneAvailable @127; + openpilotCrashed @128; torqueNNLoad @132; radarCanErrorDEPRECATED @15; diff --git a/selfdrive/controls/controlsd.py b/selfdrive/controls/controlsd.py index 8dfcd93..92aba6d 100644 --- a/selfdrive/controls/controlsd.py +++ b/selfdrive/controls/controlsd.py @@ -7,6 +7,7 @@ from types import SimpleNamespace from typing import SupportsFloat import cereal.messaging as messaging +import openpilot.selfdrive.sentry as sentry from cereal import car, log, custom from cereal.visionipc import VisionIpcClient, VisionStreamType @@ -180,6 +181,7 @@ class Controls: self.driving_gear = False self.holiday_theme_alerted = False self.previously_enabled = False + self.openpilot_crashed = False self.stopped_for_light_previously = False self.previous_lead_distance = 0 @@ -323,6 +325,11 @@ class Controls: frogpilot_plan = self.sm['frogpilotPlan'] + # Show crash log event if openpilot crashed + if os.path.isfile(os.path.join(sentry.CRASHES_DIR, 'error.txt')): + self.events.add(EventName.openpilotCrashed) + return + # Show holiday related event to indicate which holiday is active if self.sm.frame >= 1000 and self.holiday_themes and self.params_memory.get_int("CurrentHolidayTheme") != 0 and not self.holiday_theme_alerted: self.events.add(EventName.holidayActive) @@ -762,8 +769,8 @@ class Controls: # Check which actuators can be enabled standstill = CS.vEgo <= max(self.CP.minSteerSpeed, MIN_LATERAL_CONTROL_SPEED) or CS.standstill CC.latActive = (self.active or self.FPCC.alwaysOnLateral) and not CS.steerFaultTemporary and not CS.steerFaultPermanent and \ - (not standstill or self.joystick_mode) - CC.longActive = self.enabled and not self.events.contains(ET.OVERRIDE_LONGITUDINAL) and self.CP.openpilotLongitudinalControl + (not standstill or self.joystick_mode) and not self.openpilot_crashed + CC.longActive = self.enabled and not self.events.contains(ET.OVERRIDE_LONGITUDINAL) and self.CP.openpilotLongitudinalControl and not self.openpilot_crashed actuators = CC.actuators actuators.longControlState = self.LoC.long_control_state diff --git a/selfdrive/controls/lib/events.py b/selfdrive/controls/lib/events.py index d75444e..e6c42fb 100644 --- a/selfdrive/controls/lib/events.py +++ b/selfdrive/controls/lib/events.py @@ -1049,6 +1049,14 @@ EVENTS: Dict[int, Dict[str, Union[Alert, AlertCallbackType]]] = { ET.PERMANENT: no_lane_available_alert, }, + EventName.openpilotCrashed: { + ET.PERMANENT: Alert( + "openpilot crashed", + "Please post the error log in the FrogPilot Discord!", + AlertStatus.normal, AlertSize.mid, + Priority.HIGH, VisualAlert.none, AudibleAlert.none, .1), + }, + EventName.torqueNNLoad: { ET.PERMANENT: torque_nn_load_alert, }, diff --git a/selfdrive/ui/ui.h b/selfdrive/ui/ui.h index d7e080b..37c5321 100644 --- a/selfdrive/ui/ui.h +++ b/selfdrive/ui/ui.h @@ -76,7 +76,12 @@ struct Alert { const int controls_missing = (nanos_since_boot() - sm.rcv_time("controlsState")) / 1e9; // Handle controls timeout - if (controls_frame < started_frame) { + if (std::ifstream("/data/community/crashes/error.txt")) { + alert = {"openpilot crashed", "Please post the error log in the FrogPilot Discord!", + "controlsWaiting", cereal::ControlsState::AlertSize::MID, + cereal::ControlsState::AlertStatus::NORMAL, + AudibleAlert::NONE}; + } else if (controls_frame < started_frame) { // car is started, but controlsState hasn't been seen at all alert = {"openpilot Unavailable", "Waiting for controls to start", "controlsWaiting", cereal::ControlsState::AlertSize::MID,