carrot/scripts/add/events_ko.py

1116 lines
41 KiB
Python
Raw Normal View History

2025-02-12 09:12:43 +09:00
#!/usr/bin/env python3
2024-09-03 16:09:00 +09:00
import bisect
import math
import os
from enum import IntEnum
from collections.abc import Callable
from cereal import log, car
import cereal.messaging as messaging
from openpilot.common.conversions import Conversions as CV
2025-02-12 09:12:43 +09:00
from openpilot.common.params import Params
2024-09-03 16:09:00 +09:00
from openpilot.common.git import get_short_branch
from openpilot.common.realtime import DT_CTRL
from openpilot.selfdrive.locationd.calibrationd import MIN_SPEED_FILTER
AlertSize = log.SelfdriveState.AlertSize
AlertStatus = log.SelfdriveState.AlertStatus
VisualAlert = car.CarControl.HUDControl.VisualAlert
AudibleAlert = car.CarControl.HUDControl.AudibleAlert
EventName = log.OnroadEvent.EventName
# Alert priorities
class Priority(IntEnum):
LOWEST = 0
LOWER = 1
LOW = 2
MID = 3
HIGH = 4
HIGHEST = 5
# Event types
class ET:
ENABLE = 'enable'
PRE_ENABLE = 'preEnable'
OVERRIDE_LATERAL = 'overrideLateral'
OVERRIDE_LONGITUDINAL = 'overrideLongitudinal'
NO_ENTRY = 'noEntry'
WARNING = 'warning'
USER_DISABLE = 'userDisable'
SOFT_DISABLE = 'softDisable'
IMMEDIATE_DISABLE = 'immediateDisable'
PERMANENT = 'permanent'
# get event name from enum
EVENT_NAME = {v: k for k, v in EventName.schema.enumerants.items()}
class Events:
def __init__(self):
self.events: list[int] = []
self.static_events: list[int] = []
self.event_counters = dict.fromkeys(EVENTS.keys(), 0)
@property
def names(self) -> list[int]:
return self.events
def __len__(self) -> int:
return len(self.events)
def add(self, event_name: int, static: bool=False) -> None:
if static:
bisect.insort(self.static_events, event_name)
bisect.insort(self.events, event_name)
def clear(self) -> None:
self.event_counters = {k: (v + 1 if k in self.events else 0) for k, v in self.event_counters.items()}
self.events = self.static_events.copy()
def contains(self, event_type: str) -> bool:
return any(event_type in EVENTS.get(e, {}) for e in self.events)
def create_alerts(self, event_types: list[str], callback_args=None):
if callback_args is None:
callback_args = []
ret = []
for e in self.events:
types = EVENTS[e].keys()
for et in event_types:
if et in types:
alert = EVENTS[e][et]
if not isinstance(alert, Alert):
alert = alert(*callback_args)
if DT_CTRL * (self.event_counters[e] + 1) >= alert.creation_delay:
alert.alert_type = f"{EVENT_NAME[e]}/{et}"
alert.event_type = et
ret.append(alert)
return ret
def add_from_msg(self, events):
for e in events:
bisect.insort(self.events, e.name.raw)
def to_msg(self):
ret = []
for event_name in self.events:
event = log.OnroadEvent.new_message()
event.name = event_name
for event_type in EVENTS.get(event_name, {}):
setattr(event, event_type, True)
ret.append(event)
return ret
# 메세지 한글화 : 로웰 ( https://github.com/crwusiz/openpilot )
class Alert:
def __init__(self,
alert_text_1: str,
alert_text_2: str,
alert_status: log.SelfdriveState.AlertStatus,
alert_size: log.SelfdriveState.AlertSize,
priority: Priority,
visual_alert: car.CarControl.HUDControl.VisualAlert,
audible_alert: car.CarControl.HUDControl.AudibleAlert,
duration: float,
creation_delay: float = 0.):
self.alert_text_1 = alert_text_1
self.alert_text_2 = alert_text_2
self.alert_status = alert_status
self.alert_size = alert_size
self.priority = priority
self.visual_alert = visual_alert
self.audible_alert = audible_alert
self.duration = int(duration / DT_CTRL)
self.creation_delay = creation_delay
self.alert_type = ""
self.event_type: str | None = None
def __str__(self) -> str:
return f"{self.alert_text_1}/{self.alert_text_2} {self.priority} {self.visual_alert} {self.audible_alert}"
def __gt__(self, alert2) -> bool:
if not isinstance(alert2, Alert):
return False
return self.priority > alert2.priority
EmptyAlert = Alert("" , "", AlertStatus.normal, AlertSize.none, Priority.LOWEST,
VisualAlert.none, AudibleAlert.none, 0)
class NoEntryAlert(Alert):
def __init__(self, alert_text_2: str,
alert_text_1: str = "오픈파일럿 사용불가",
visual_alert: car.CarControl.HUDControl.VisualAlert=VisualAlert.none):
super().__init__(alert_text_1, alert_text_2, AlertStatus.normal,
AlertSize.mid, Priority.LOW, visual_alert,
AudibleAlert.refuse, 3.)
class SoftDisableAlert(Alert):
def __init__(self, alert_text_2: str):
super().__init__("핸들을 즉시 잡아주세요", alert_text_2,
AlertStatus.userPrompt, AlertSize.full,
Priority.MID, VisualAlert.steerRequired,
AudibleAlert.warningSoft, 2.),
# less harsh version of SoftDisable, where the condition is user-triggered
class UserSoftDisableAlert(SoftDisableAlert):
def __init__(self, alert_text_2: str):
super().__init__(alert_text_2),
self.alert_text_1 = "오픈파일럿이 해제됩니다"
class ImmediateDisableAlert(Alert):
def __init__(self, alert_text_2: str):
super().__init__("핸들을 즉시 잡아주세요", alert_text_2,
AlertStatus.critical, AlertSize.full,
Priority.HIGHEST, VisualAlert.steerRequired,
AudibleAlert.warningImmediate, 4.),
class EngagementAlert(Alert):
def __init__(self, audible_alert: car.CarControl.HUDControl.AudibleAlert):
super().__init__("", "",
AlertStatus.normal, AlertSize.none,
Priority.MID, VisualAlert.none,
audible_alert, .2),
class NormalPermanentAlert(Alert):
def __init__(self, alert_text_1: str, alert_text_2: str = "", duration: float = 0.2, priority: Priority = Priority.LOWER, creation_delay: float = 0.):
super().__init__(alert_text_1, alert_text_2,
AlertStatus.normal, AlertSize.mid if len(alert_text_2) else AlertSize.small,
priority, VisualAlert.none, AudibleAlert.none, duration, creation_delay=creation_delay),
class StartupAlert(Alert):
def __init__(self, alert_text_1: str, alert_text_2: str = "항상 핸들을 잡고 도로를 주시하세요", alert_status=AlertStatus.normal):
super().__init__(alert_text_1, alert_text_2,
alert_status, AlertSize.mid,
Priority.LOWER, VisualAlert.none, AudibleAlert.none, 5.),
# ********** helper functions **********
def get_display_speed(speed_ms: float, metric: bool) -> str:
speed = int(round(speed_ms * (CV.MS_TO_KPH if metric else CV.MS_TO_MPH)))
unit = 'km/h' if metric else 'mph'
return f"{speed} {unit}"
# ********** alert callback functions **********
AlertCallbackType = Callable[[car.CarParams, car.CarState, messaging.SubMaster, bool, int, log.ControlsState], Alert]
def soft_disable_alert(alert_text_2: str) -> AlertCallbackType:
def func(CP: car.CarParams, CS: car.CarState, sm: messaging.SubMaster, metric: bool, soft_disable_time: int, personality) -> Alert:
if soft_disable_time < int(0.5 / DT_CTRL):
return ImmediateDisableAlert(alert_text_2)
return SoftDisableAlert(alert_text_2)
return func
def user_soft_disable_alert(alert_text_2: str) -> AlertCallbackType:
def func(CP: car.CarParams, CS: car.CarState, sm: messaging.SubMaster, metric: bool, soft_disable_time: int, personality) -> Alert:
if soft_disable_time < int(0.5 / DT_CTRL):
return ImmediateDisableAlert(alert_text_2)
return UserSoftDisableAlert(alert_text_2)
return func
def startup_master_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.SubMaster, metric: bool, soft_disable_time: int, personality) -> Alert:
branch = get_short_branch() # Ensure get_short_branch is cached to avoid lags on startup
if "REPLAY" in os.environ:
branch = "replay"
return StartupAlert("경고: 이 브랜치는 테스트되지 않았습니다", branch, alert_status=AlertStatus.userPrompt)
def below_engage_speed_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.SubMaster, metric: bool, soft_disable_time: int, personality) -> Alert:
return NoEntryAlert(f"{get_display_speed(CP.minEnableSpeed, metric)} 이상의 속도에서 활성됩니다")
def below_steer_speed_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.SubMaster, metric: bool, soft_disable_time: int, personality) -> Alert:
return Alert(
f"{get_display_speed(CP.minSteerSpeed, metric)} 이상의 속도에서 조향 됩니다",
"",
AlertStatus.userPrompt, AlertSize.small,
Priority.LOW, VisualAlert.steerRequired, AudibleAlert.prompt, 0.4)
def calibration_incomplete_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.SubMaster, metric: bool, soft_disable_time: int, personality) -> Alert:
first_word = '캘리브레이션을 다시' if sm['liveCalibration'].calStatus == log.LiveCalibrationData.Status.recalibrating else '캘리브레이션'
return Alert(
f"{first_word} 진행중 : {sm['liveCalibration'].calPerc:.0f}%",
f"{get_display_speed(MIN_SPEED_FILTER, metric)} 이상의 속도로 주행하세요",
AlertStatus.normal, AlertSize.mid,
Priority.LOWEST, VisualAlert.none, AudibleAlert.none, .2)
2025-02-12 09:12:43 +09:00
def torque_nn_load_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.SubMaster, metric: bool, soft_disable_time: int, personality) -> Alert:
model_name = Params().get("NNFFModelName", encoding='utf-8')
if model_name == "":
return Alert(
"NNFF Torque Controller not available",
"Donate logs to Twilsonco to get it added!",
AlertStatus.userPrompt, AlertSize.mid,
Priority.LOW, VisualAlert.none, AudibleAlert.prompt, 6.0)
else:
return Alert(
"NNFF Torque Controller loaded",
model_name,
AlertStatus.userPrompt, AlertSize.mid,
Priority.LOW, VisualAlert.none, AudibleAlert.nnff, 5.0)
2024-09-03 16:09:00 +09:00
# *** debug alerts ***
def out_of_space_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.SubMaster, metric: bool, soft_disable_time: int, personality) -> Alert:
full_perc = round(100. - sm['deviceState'].freeSpacePercent)
return NormalPermanentAlert("저장공간이 부족합니다", f"{full_perc}% full")
def posenet_invalid_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.SubMaster, metric: bool, soft_disable_time: int, personality) -> Alert:
mdl = sm['modelV2'].velocity.x[0] if len(sm['modelV2'].velocity.x) else math.nan
err = CS.vEgo - mdl
msg = f"Speed Error: {err:.1f} m/s"
return NoEntryAlert(msg, alert_text_1="잘못된 Posenet 속도")
def process_not_running_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.SubMaster, metric: bool, soft_disable_time: int, personality) -> Alert:
not_running = [p.name for p in sm['managerState'].processes if not p.running and p.shouldBeRunning]
msg = ', '.join(not_running)
return NoEntryAlert(msg, alert_text_1="프로세스가 실행되지 않았습니다")
def comm_issue_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.SubMaster, metric: bool, soft_disable_time: int, personality) -> Alert:
bs = [s for s in sm.data.keys() if not sm.all_checks([s, ])]
msg = ', '.join(bs[:4]) # can't fit too many on one line
return NoEntryAlert(msg, alert_text_1="프로세스 동작오류")
def camera_malfunction_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.SubMaster, metric: bool, soft_disable_time: int, personality) -> Alert:
all_cams = ('roadCameraState', 'driverCameraState', 'wideRoadCameraState')
bad_cams = [s.replace('State', '') for s in all_cams if s in sm.data.keys() and not sm.all_checks([s, ])]
return NormalPermanentAlert("카메라를 점검하세요", ', '.join(bad_cams))
def calibration_invalid_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.SubMaster, metric: bool, soft_disable_time: int, personality) -> Alert:
rpy = sm['liveCalibration'].rpyCalib
yaw = math.degrees(rpy[2] if len(rpy) == 3 else math.nan)
pitch = math.degrees(rpy[1] if len(rpy) == 3 else math.nan)
angles = f"장치 재장착 (Pitch: {pitch:.1f}°, Yaw: {yaw:.1f}°)"
return NormalPermanentAlert("캘리브레이션 오류", angles)
def overheat_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.SubMaster, metric: bool, soft_disable_time: int, personality) -> Alert:
cpu = max(sm['deviceState'].cpuTempC, default=0.)
gpu = max(sm['deviceState'].gpuTempC, default=0.)
temp = max((cpu, gpu, sm['deviceState'].memoryTempC))
return NormalPermanentAlert("시스템 과열", f"{temp:.0f} °C")
def low_memory_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.SubMaster, metric: bool, soft_disable_time: int, personality) -> Alert:
return NormalPermanentAlert("메모리 부족", f"{sm['deviceState'].memoryUsagePercent}% used")
def high_cpu_usage_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.SubMaster, metric: bool, soft_disable_time: int, personality) -> Alert:
x = max(sm['deviceState'].cpuUsagePercent, default=0.)
return NormalPermanentAlert("CPU 사용량이 높습니다", f"{x}% used")
def modeld_lagging_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.SubMaster, metric: bool, soft_disable_time: int, personality) -> Alert:
return NormalPermanentAlert("주행모델 지연됨", f"{sm['modelV2'].frameDropPerc:.1f}% frames dropped")
def wrong_car_mode_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.SubMaster, metric: bool, soft_disable_time: int, personality) -> Alert:
text = "크루즈 버튼으로 활성화됩니다"
if CP.carName == "honda":
text = "메인 스위치로 활성화됩니다"
return NoEntryAlert(text)
def joystick_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.SubMaster, metric: bool, soft_disable_time: int, personality) -> Alert:
gb = sm['carControl'].actuators.accel / 4.
steer = sm['carControl'].actuators.steer
vals = f"Gas: {round(gb * 100.)}%, Steer: {round(steer * 100.)}%"
return NormalPermanentAlert("조이스틱 모드", vals)
def longitudinal_maneuver_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.SubMaster, metric: bool, soft_disable_time: int, personality) -> Alert:
ad = sm['alertDebug']
audible_alert = AudibleAlert.prompt if 'Active' in ad.alertText1 else AudibleAlert.none
alert_status = AlertStatus.userPrompt if 'Active' in ad.alertText1 else AlertStatus.normal
alert_size = AlertSize.mid if ad.alertText2 else AlertSize.small
return Alert(ad.alertText1, ad.alertText2,
alert_status, alert_size,
Priority.LOW, VisualAlert.none, audible_alert, 0.2)
def personality_changed_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.SubMaster, metric: bool, soft_disable_time: int, personality) -> Alert:
personality = str(personality).title()
return NormalPermanentAlert(f"Driving Personality: {personality}", duration=1.5)
def car_parser_result(CP: car.CarParams, CS: car.CarState, sm: messaging.SubMaster, metric: bool, soft_disable_time: int, personality) -> Alert:
results = Params().get("CanParserResult")
if results is None:
results = ""
return Alert(
"CAN 오류: Check Connections",
results,
AlertStatus.normal, AlertSize.small,
Priority.LOW, VisualAlert.none, AudibleAlert.none, 1., creation_delay=1.)
2024-09-03 16:09:00 +09:00
EVENTS: dict[int, dict[str, Alert | AlertCallbackType]] = {
# ********** events with no alerts **********
EventName.stockFcw: {},
EventName.actuatorsApiUnavailable: {},
# ********** events only containing alerts displayed in all states **********
EventName.joystickDebug: {
ET.WARNING: joystick_alert,
ET.PERMANENT: NormalPermanentAlert("조이스틱 모드"),
},
EventName.longitudinalManeuver: {
ET.WARNING: longitudinal_maneuver_alert,
ET.PERMANENT: NormalPermanentAlert("롱컨 가동 모드",
"전방 도로에 장애물이 없는지 확인하세요"),
},
EventName.selfdriveInitializing: {
ET.NO_ENTRY: NoEntryAlert("시스템이 준비중입니다"),
},
EventName.startup: {
ET.PERMANENT: StartupAlert("오픈파일럿 사용준비 완료")
},
EventName.startupMaster: {
ET.PERMANENT: startup_master_alert,
},
EventName.startupNoControl: {
ET.PERMANENT: StartupAlert("대시캠 모드"),
ET.NO_ENTRY: NoEntryAlert("대시캠 모드"),
},
EventName.startupNoCar: {
ET.PERMANENT: StartupAlert("대시캠 모드 : 호환되지않는 차량"),
},
EventName.startupNoSecOcKey: {
ET.PERMANENT: NormalPermanentAlert("대시캠 모드",
"보안키 사용불가",
priority=Priority.HIGH),
},
EventName.dashcamMode: {
ET.PERMANENT: NormalPermanentAlert("대시캠 모드",
priority=Priority.LOWEST),
},
EventName.invalidLkasSetting: {
ET.PERMANENT: NormalPermanentAlert("잘못된 LKAS 설정",
"활성화 하려면 차량의 LKAS를 켜거나 끄세요."),
ET.NO_ENTRY: NoEntryAlert("Invalid LKAS setting"),
},
EventName.cruiseMismatch: {
#ET.PERMANENT: ImmediateDisableAlert("openpilot failed to cancel cruise"),
},
# openpilot doesn't recognize the car. This switches openpilot into a
# read-only mode. This can be solved by adding your fingerprint.
# See https://github.com/commaai/openpilot/wiki/Fingerprinting for more information
EventName.carUnrecognized: {
ET.PERMANENT: NormalPermanentAlert("대시캠 모드",
"배선연결상태를 확인하세요",
priority=Priority.LOWEST),
},
EventName.aeb: {
ET.PERMANENT: Alert(
"브레이크!",
"추돌 위험: 긴급제동 작동",
AlertStatus.critical, AlertSize.full,
Priority.HIGHEST, VisualAlert.fcw, AudibleAlert.none, 2.),
ET.NO_ENTRY: NoEntryAlert("추돌 위험: 긴급제동 작동"),
},
EventName.stockAeb: {
ET.PERMANENT: Alert(
"브레이크!",
"추돌 위험: 차량 AEB 작동",
AlertStatus.critical, AlertSize.full,
Priority.HIGHEST, VisualAlert.fcw, AudibleAlert.warningSoft, 2.),
ET.NO_ENTRY: NoEntryAlert("추돌 위험: 차량 AEB 작동"),
},
EventName.fcw: {
ET.PERMANENT: Alert(
"브레이크!",
"추돌 위험",
AlertStatus.critical, AlertSize.full,
Priority.HIGHEST, VisualAlert.fcw, AudibleAlert.warningSoft, 2.),
},
EventName.ldw: {
ET.PERMANENT: Alert(
"차선이탈",
"",
AlertStatus.userPrompt, AlertSize.small,
Priority.LOW, VisualAlert.ldw, AudibleAlert.prompt, 3.),
},
# ********** events only containing alerts that display while engaged **********
EventName.steerTempUnavailableSilent: {
ET.WARNING: Alert(
"조향제어 일시적 불가능",
"",
AlertStatus.userPrompt, AlertSize.small,
Priority.LOW, VisualAlert.steerRequired, AudibleAlert.prompt, 1.8),
},
EventName.preDriverDistracted: {
ET.WARNING: Alert(
"도로를 주시하세요",
"",
AlertStatus.normal, AlertSize.small,
Priority.LOW, VisualAlert.none, AudibleAlert.prompt, 1.),
},
EventName.promptDriverDistracted: {
ET.WARNING: Alert(
"도로를 주시하세요",
"운전자 도로주시 불안",
AlertStatus.userPrompt, AlertSize.mid,
Priority.MID, VisualAlert.steerRequired, AudibleAlert.promptDistracted, .1),
},
EventName.driverDistracted: {
ET.WARNING: Alert(
"조향제어가 해제됩니다",
"운전자 도로주시 불안",
AlertStatus.critical, AlertSize.full,
Priority.HIGH, VisualAlert.steerRequired, AudibleAlert.warningImmediate, .1),
},
EventName.preDriverUnresponsive: {
ET.WARNING: Alert(
"핸들을 잡아주세요 : 운전자 인식 불가",
"",
AlertStatus.normal, AlertSize.small,
Priority.LOW, VisualAlert.steerRequired, AudibleAlert.prompt, .1),
},
EventName.promptDriverUnresponsive: {
ET.WARNING: Alert(
"핸들을 잡아주세요",
"운전자 응답없음",
AlertStatus.userPrompt, AlertSize.mid,
Priority.MID, VisualAlert.steerRequired, AudibleAlert.promptDistracted, .1),
},
EventName.driverUnresponsive: {
ET.WARNING: Alert(
"조향제어가 해제됩니다",
"운전자 응답없음",
AlertStatus.critical, AlertSize.full,
Priority.HIGH, VisualAlert.steerRequired, AudibleAlert.warningImmediate, .1),
},
EventName.manualRestart: {
ET.WARNING: Alert(
"핸들을 잡아주세요",
"장치를 재부팅 하세요",
AlertStatus.userPrompt, AlertSize.mid,
Priority.LOW, VisualAlert.none, AudibleAlert.none, .2),
},
EventName.resumeRequired: {
ET.WARNING: Alert(
"정지 상태를 종료하려면 RES버튼을 누르세요",
"",
AlertStatus.userPrompt, AlertSize.small,
Priority.MID, VisualAlert.none, AudibleAlert.none, .2),
},
EventName.belowSteerSpeed: {
ET.WARNING: below_steer_speed_alert,
},
EventName.preLaneChangeLeft: {
ET.WARNING: Alert(
"좌측 차선이 안전한지 확인하세요",
"",
AlertStatus.normal, AlertSize.small,
Priority.LOW, VisualAlert.none, AudibleAlert.none, .1),
},
EventName.preLaneChangeRight: {
ET.WARNING: Alert(
"우측 차선이 안전한지 확인하세요",
"",
AlertStatus.normal, AlertSize.small,
Priority.LOW, VisualAlert.none, AudibleAlert.none, .1),
},
EventName.laneChangeBlocked: {
ET.WARNING: Alert(
"사각지대에 차량이 감지되니 대기하세요",
"",
AlertStatus.userPrompt, AlertSize.small,
Priority.LOW, VisualAlert.none, AudibleAlert.prompt, .1),
},
EventName.laneChange: {
ET.WARNING: Alert(
"차선을 변경합니다",
"",
AlertStatus.normal, AlertSize.small,
Priority.LOW, VisualAlert.none, AudibleAlert.none, .1),
},
EventName.steerSaturated: {
ET.WARNING: Alert(
"핸들을 잡아주세요",
"회전이 조향 한도를 초과함",
AlertStatus.userPrompt, AlertSize.mid,
Priority.LOW, VisualAlert.steerRequired, AudibleAlert.promptRepeat, 2.),
},
# Thrown when the fan is driven at >50% but is not rotating
EventName.fanMalfunction: {
ET.PERMANENT: NormalPermanentAlert("FAN 오작동", "장치를 점검하세요"),
},
# Camera is not outputting frames
EventName.cameraMalfunction: {
ET.PERMANENT: camera_malfunction_alert,
ET.SOFT_DISABLE: soft_disable_alert("카메라 오작동"),
ET.NO_ENTRY: NoEntryAlert("카메라 오작동: 장치를 재부팅 하세요"),
},
# Camera framerate too low
EventName.cameraFrameRate: {
ET.PERMANENT: NormalPermanentAlert("카메라 프레임 낮음", "장치를 재부팅 하세요"),
ET.SOFT_DISABLE: soft_disable_alert("카메라 프레임 낮음"),
ET.NO_ENTRY: NoEntryAlert("카메라 프레임 낮음", "장치를 재부팅 하세요"),
},
# Unused
EventName.locationdTemporaryError: {
ET.NO_ENTRY: NoEntryAlert("locationd 일시적 오류"),
ET.SOFT_DISABLE: soft_disable_alert("locationd 일시적 오류"),
},
EventName.locationdPermanentError: {
ET.NO_ENTRY: NoEntryAlert("locationd 오류"),
ET.IMMEDIATE_DISABLE: ImmediateDisableAlert("locationd 오류"),
ET.PERMANENT: NormalPermanentAlert("locationd 오류"),
},
# openpilot tries to learn certain parameters about your car by observing
# how the car behaves to steering inputs from both human and openpilot driving.
# This includes:
# - steer ratio: gear ratio of the steering rack. Steering angle divided by tire angle
# - tire stiffness: how much grip your tires have
# - angle offset: most steering angle sensors are offset and measure a non zero angle when driving straight
# This alert is thrown when any of these values exceed a sanity check. This can be caused by
# bad alignment or bad sensor data. If this happens consistently consider creating an issue on GitHub
EventName.paramsdTemporaryError: {
ET.NO_ENTRY: NoEntryAlert("paramsd 일시적 오류"),
ET.SOFT_DISABLE: soft_disable_alert("paramsd 일시적 오류"),
},
EventName.paramsdPermanentError: {
ET.NO_ENTRY: NoEntryAlert("paramsd 오류"),
ET.IMMEDIATE_DISABLE: ImmediateDisableAlert("paramsd 오류"),
ET.PERMANENT: NormalPermanentAlert("paramsd 오류"),
},
# ********** events that affect controls state transitions **********
EventName.pcmEnable: {
ET.ENABLE: EngagementAlert(AudibleAlert.engage),
},
EventName.buttonEnable: {
ET.ENABLE: EngagementAlert(AudibleAlert.engage),
},
EventName.pcmDisable: {
ET.USER_DISABLE: EngagementAlert(AudibleAlert.disengage),
},
EventName.buttonCancel: {
ET.USER_DISABLE: EngagementAlert(AudibleAlert.disengage),
ET.NO_ENTRY: NoEntryAlert("Cancel 버튼을 눌렀습니다"),
},
EventName.brakeHold: {
ET.USER_DISABLE: EngagementAlert(AudibleAlert.disengage),
ET.NO_ENTRY: NoEntryAlert("브레이크 감지됨"),
},
EventName.parkBrake: {
ET.USER_DISABLE: EngagementAlert(AudibleAlert.disengage),
ET.NO_ENTRY: NoEntryAlert("주차 브레이크를 해제하세요"),
},
EventName.pedalPressed: {
ET.USER_DISABLE: EngagementAlert(AudibleAlert.disengage),
ET.NO_ENTRY: NoEntryAlert("브레이크 감지됨",
visual_alert=VisualAlert.brakePressed),
},
EventName.preEnableStandstill: {
ET.PRE_ENABLE: Alert(
"브레이크 해제 후 활성화하세요",
"",
AlertStatus.normal, AlertSize.small,
Priority.LOWEST, VisualAlert.none, AudibleAlert.none, .1, creation_delay=1.),
},
EventName.gasPressedOverride: {
ET.OVERRIDE_LONGITUDINAL: Alert(
"",
"",
AlertStatus.normal, AlertSize.none,
Priority.LOWEST, VisualAlert.none, AudibleAlert.none, .1),
},
EventName.steerOverride: {
ET.OVERRIDE_LATERAL: Alert(
"",
"",
AlertStatus.normal, AlertSize.none,
Priority.LOWEST, VisualAlert.none, AudibleAlert.none, .1),
},
EventName.wrongCarMode: {
ET.USER_DISABLE: EngagementAlert(AudibleAlert.disengage),
ET.NO_ENTRY: wrong_car_mode_alert,
},
EventName.resumeBlocked: {
ET.NO_ENTRY: NoEntryAlert("SET 버튼으로 활성화됩니다"),
},
EventName.wrongCruiseMode: {
ET.USER_DISABLE: EngagementAlert(AudibleAlert.disengage),
ET.NO_ENTRY: NoEntryAlert("어뎁티브크루즈를 활성화하세요"),
},
EventName.steerTempUnavailable: {
ET.SOFT_DISABLE: soft_disable_alert("조향제어 일시적 불가능"),
ET.NO_ENTRY: NoEntryAlert("조향제어 일시적 불가능"),
},
EventName.steerTimeLimit: {
ET.SOFT_DISABLE: soft_disable_alert("차량 조향제어 시간 제한"),
ET.NO_ENTRY: NoEntryAlert("차량 조향제어 시간 제한"),
},
EventName.outOfSpace: {
ET.PERMANENT: out_of_space_alert,
ET.NO_ENTRY: NoEntryAlert("저장공간 부족"),
},
EventName.belowEngageSpeed: {
ET.NO_ENTRY: below_engage_speed_alert,
},
EventName.sensorDataInvalid: {
ET.PERMANENT: Alert(
"센서 데이터 오류",
"장치를 점검하세요",
AlertStatus.normal, AlertSize.mid,
Priority.LOWER, VisualAlert.none, AudibleAlert.none, .2, creation_delay=1.),
ET.NO_ENTRY: NoEntryAlert("센서 데이터 오류"),
ET.SOFT_DISABLE: soft_disable_alert("센서 데이터 오류"),
},
EventName.noGps: {
ET.PERMANENT: Alert(
"GPS 수신 불량",
"기기에서 하늘이 잘 보이는지 확인하세요",
AlertStatus.normal, AlertSize.mid,
Priority.LOWER, VisualAlert.none, AudibleAlert.none, .2, creation_delay=600.)
},
EventName.tooDistracted: {
ET.NO_ENTRY: NoEntryAlert("방해 수준이 너무높습니다"),
},
EventName.overheat: {
ET.PERMANENT: overheat_alert,
ET.SOFT_DISABLE: soft_disable_alert("장치 과열됨"),
ET.NO_ENTRY: NoEntryAlert("장치 과열됨"),
},
EventName.wrongGear: {
ET.USER_DISABLE: EngagementAlert(AudibleAlert.disengage),
ET.NO_ENTRY: NoEntryAlert("기어를 [D]로 변경하세요"),
},
# This alert is thrown when the calibration angles are outside of the acceptable range.
# For example if the device is pointed too much to the left or the right.
# Usually this can only be solved by removing the mount from the windshield completely,
# and attaching while making sure the device is pointed straight forward and is level.
# See https://comma.ai/setup for more information
EventName.calibrationInvalid: {
ET.PERMANENT: calibration_invalid_alert,
ET.SOFT_DISABLE: soft_disable_alert("캘리브레이션 오류 : 장치 위치 변경 후 캘리브레이션을 다시 하세요"),
ET.NO_ENTRY: NoEntryAlert("캘리브레이션 오류 : 장치 위치 변경 후 캘리브레이션을 다시 하세요"),
},
EventName.calibrationIncomplete: {
ET.PERMANENT: calibration_incomplete_alert,
ET.SOFT_DISABLE: soft_disable_alert("캘리브레이션이 완료되지않았습니다"),
ET.NO_ENTRY: NoEntryAlert("캘리브레이션이 진행중입니다"),
},
EventName.calibrationRecalibrating: {
ET.PERMANENT: calibration_incomplete_alert,
ET.SOFT_DISABLE: soft_disable_alert("장치 위치변경이 감지되어 캘리브레이션이 다시 진행중입니다"),
ET.NO_ENTRY: NoEntryAlert("장치 위치변경 감지되어 캘리브레이션이 다시 진행중입니다"),
},
EventName.doorOpen: {
#ET.SOFT_DISABLE: user_soft_disable_alert("Door Open"),
ET.USER_DISABLE: EngagementAlert(AudibleAlert.disengage),
ET.NO_ENTRY: NoEntryAlert("도어 열림"),
ET.PERMANENT: Alert(
"도어 열림",
"",
AlertStatus.normal, AlertSize.full,
Priority.LOWEST, VisualAlert.none, AudibleAlert.none, .2, creation_delay=0.5),
},
EventName.seatbeltNotLatched: {
ET.SOFT_DISABLE: user_soft_disable_alert("안전벨트를 착용해주세요"),
ET.NO_ENTRY: NoEntryAlert("안전벨트를 착용해주세요"),
ET.PERMANENT: Alert(
"안전벨트 미착용",
"",
AlertStatus.normal, AlertSize.full,
Priority.LOWEST, VisualAlert.none, AudibleAlert.none, .2, creation_delay=0.5),
},
EventName.espDisabled: {
ET.SOFT_DISABLE: soft_disable_alert("ESC 해제됨"),
ET.NO_ENTRY: NoEntryAlert("ESC 해제됨"),
},
EventName.lowBattery: {
ET.SOFT_DISABLE: soft_disable_alert("배터리 부족"),
ET.NO_ENTRY: NoEntryAlert("배터리 부족"),
},
# Different openpilot services communicate between each other at a certain
# interval. If communication does not follow the regular schedule this alert
# is thrown. This can mean a service crashed, did not broadcast a message for
# ten times the regular interval, or the average interval is more than 10% too high.
EventName.commIssue: {
ET.SOFT_DISABLE: soft_disable_alert("장치 프로세스 동작오류"),
ET.NO_ENTRY: comm_issue_alert,
},
EventName.commIssueAvgFreq: {
ET.SOFT_DISABLE: soft_disable_alert("장치 프로세스 통신속도 오류"),
ET.NO_ENTRY: NoEntryAlert("장치 프로세스 통신속도 오류"),
},
EventName.selfdrivedLagging: {
ET.SOFT_DISABLE: soft_disable_alert("시스템 지연됨"),
ET.NO_ENTRY: NoEntryAlert("Selfdrive 프로세스 지연됨: 장치를 재부팅 하세요"),
},
# Thrown when manager detects a service exited unexpectedly while driving
EventName.processNotRunning: {
ET.NO_ENTRY: process_not_running_alert,
ET.SOFT_DISABLE: soft_disable_alert("프로세스가 실행되지 않았습니다"),
},
EventName.radarFault: {
ET.SOFT_DISABLE: soft_disable_alert("레이더 오류 : 차량을 재가동 하세요"),
ET.NO_ENTRY: NoEntryAlert("레이더 오류 : 차량을 재가동 하세요"),
},
# Every frame from the camera should be processed by the model. If modeld
# is not processing frames fast enough they have to be dropped. This alert is
# thrown when over 20% of frames are dropped.
EventName.modeldLagging: {
ET.SOFT_DISABLE: soft_disable_alert("주행모델 지연됨"),
ET.NO_ENTRY: NoEntryAlert("주행모델 지연됨"),
ET.PERMANENT: modeld_lagging_alert,
},
# Besides predicting the path, lane lines and lead car data the model also
# predicts the current velocity and rotation speed of the car. If the model is
# very uncertain about the current velocity while the car is moving, this
# usually means the model has trouble understanding the scene. This is used
# as a heuristic to warn the driver.
EventName.posenetInvalid: {
ET.SOFT_DISABLE: soft_disable_alert("Posenet 속도 잘못됨"),
ET.NO_ENTRY: posenet_invalid_alert,
},
# When the localizer detects an acceleration of more than 40 m/s^2 (~4G) we
# alert the driver the device might have fallen from the windshield.
EventName.deviceFalling: {
ET.SOFT_DISABLE: soft_disable_alert("장치가 마운트에서 떨어짐"),
ET.NO_ENTRY: NoEntryAlert("장치가 마운트에서 떨어짐"),
},
EventName.lowMemory: {
ET.SOFT_DISABLE: soft_disable_alert("메모리 부족 : 장치를 재부팅 하세요"),
ET.PERMANENT: low_memory_alert,
ET.NO_ENTRY: NoEntryAlert("메모리 부족 : 장치를 재부팅 하세요"),
},
EventName.accFaulted: {
ET.IMMEDIATE_DISABLE: ImmediateDisableAlert("크루즈 오류 : 차량을 재가동 하세요"),
ET.PERMANENT: NormalPermanentAlert("크루즈 오류 : 차량을 재가동 하세요"),
ET.NO_ENTRY: NoEntryAlert("크루즈 오류 : 차량을 재가동 하세요"),
},
EventName.espActive: {
ET.SOFT_DISABLE: ImmediateDisableAlert("ESC 동작됨"),
ET.NO_ENTRY: NoEntryAlert("ESC 동작됨"),
},
EventName.controlsMismatch: {
ET.IMMEDIATE_DISABLE: ImmediateDisableAlert("컨트롤 불일치"),
ET.NO_ENTRY: NoEntryAlert("컨트롤 불일치"),
},
# Sometimes the USB stack on the device can get into a bad state
# causing the connection to the panda to be lost
EventName.usbError: {
ET.SOFT_DISABLE: soft_disable_alert("USB 오류 : 장치를 재부팅 하세요"),
ET.PERMANENT: NormalPermanentAlert("USB 오류 : 장치를 재부팅 하세요", ""),
ET.NO_ENTRY: NoEntryAlert("USB 오류 : 장치를 재부팅 하세요"),
},
# This alert can be thrown for the following reasons:
# - No CAN data received at all
# - CAN data is received, but some message are not received at the right frequency
# If you're not writing a new car port, this is usually cause by faulty wiring
EventName.canError: {
ET.PERMANENT: car_parser_result,
2024-09-03 16:09:00 +09:00
ET.IMMEDIATE_DISABLE: ImmediateDisableAlert("CAN 오류 : 장치를 점검하세요"),
#ET.PERMANENT: Alert(
# "CAN 오류 : 장치를 점검하세요",
# "",
# AlertStatus.normal, AlertSize.small,
# Priority.LOW, VisualAlert.none, AudibleAlert.none, 1., creation_delay=1.),
2024-09-03 16:09:00 +09:00
ET.NO_ENTRY: NoEntryAlert("CAN 오류 : 장치를 점검하세요"),
},
EventName.canBusMissing: {
ET.PERMANENT: car_parser_result,
2024-09-03 16:09:00 +09:00
ET.IMMEDIATE_DISABLE: ImmediateDisableAlert("CAN Bus 연결 끈김"),
#ET.PERMANENT: Alert(
# "CAN Bus 오류 : 케이블을 점검하세요",
# "",
# AlertStatus.normal, AlertSize.small,
# Priority.LOW, VisualAlert.none, AudibleAlert.none, 1., creation_delay=1.),
2024-09-03 16:09:00 +09:00
ET.NO_ENTRY: NoEntryAlert("CAN Bus 오류 : 장치를 점검하세요"),
},
EventName.steerUnavailable: {
ET.IMMEDIATE_DISABLE: ImmediateDisableAlert("LKAS 오류 : 차량을 재가동 하세요"),
ET.PERMANENT: NormalPermanentAlert("LKAS 오류 : 차량을 재가동 하세요"),
ET.NO_ENTRY: NoEntryAlert("LKAS 오류 : 차량을 재가동 하세요"),
},
EventName.reverseGear: {
ET.PERMANENT: Alert(
"기어 [R] 상태",
"",
AlertStatus.normal, AlertSize.full,
Priority.LOWEST, VisualAlert.none, AudibleAlert.none, .2, creation_delay=0.5),
ET.USER_DISABLE: SoftDisableAlert("기어 [R] 상태"),
ET.NO_ENTRY: NoEntryAlert("기어 [R] 상태"),
},
# On cars that use stock ACC the car can decide to cancel ACC for various reasons.
# When this happens we can no long control the car so the user needs to be warned immediately.
EventName.cruiseDisabled: {
ET.IMMEDIATE_DISABLE: ImmediateDisableAlert("크루즈 해제됨"),
},
# When the relay in the harness box opens the CAN bus between the LKAS camera
# and the rest of the car is separated. When messages from the LKAS camera
# are received on the car side this usually means the relay hasn't opened correctly
# and this alert is thrown.
EventName.relayMalfunction: {
ET.IMMEDIATE_DISABLE: ImmediateDisableAlert("하네스 릴레이 오작동"),
ET.PERMANENT: NormalPermanentAlert("하네스 릴레이 오작동", "장치를 점검하세요"),
ET.NO_ENTRY: NoEntryAlert("하네스 릴레이 오작동"),
},
EventName.speedTooLow: {
ET.IMMEDIATE_DISABLE: Alert(
"오픈파일럿 사용불가",
"속도를 높이고 활성화하세요",
AlertStatus.normal, AlertSize.mid,
Priority.HIGH, VisualAlert.none, AudibleAlert.disengage, 3.),
},
# When the car is driving faster than most cars in the training data, the model outputs can be unpredictable.
EventName.speedTooHigh: {
ET.WARNING: Alert(
"속도가 너무 높습니다",
"속도를 줄여주세요",
AlertStatus.userPrompt, AlertSize.mid,
Priority.HIGH, VisualAlert.steerRequired, AudibleAlert.promptRepeat, 4.),
ET.NO_ENTRY: NoEntryAlert("속도를 줄인 후 활성화하세요"),
},
EventName.vehicleSensorsInvalid: {
ET.IMMEDIATE_DISABLE: ImmediateDisableAlert("차량 센서 정보가 유효하지 않습니다"),
ET.PERMANENT: NormalPermanentAlert("차량 센서 보정", "주행 하여 보정하세요"),
ET.NO_ENTRY: NoEntryAlert("차량 센서 보정"),
},
EventName.personalityChanged: {
ET.WARNING: personality_changed_alert,
},
EventName.softHold: {
ET.WARNING: Alert(
"SoftHold 동작",
"",
AlertStatus.normal, AlertSize.small,
Priority.LOW, VisualAlert.none, AudibleAlert.none, .1),
},
EventName.trafficStopping: {
ET.WARNING: EngagementAlert(AudibleAlert.stopping),
#ET.WARNING: Alert(
# "신호 감속정지중입니다.",
# "",
# AlertStatus.normal, AlertSize.small,
# Priority.LOW, VisualAlert.none, AudibleAlert.stopping, 3.),
},
EventName.audioPrompt: {
ET.WARNING: EngagementAlert(AudibleAlert.prompt),
},
EventName.audioRefuse: {
ET.WARNING: EngagementAlert(AudibleAlert.refuse),
},
EventName.stopStop: {
ET.WARNING: EngagementAlert(AudibleAlert.stopStop),
},
EventName.audioLaneChange: {
ET.WARNING: EngagementAlert(AudibleAlert.laneChange),
},
EventName.audioTurn: {
ET.WARNING: EngagementAlert(AudibleAlert.audioTurn),
},
EventName.trafficSignGreen: {
ET.WARNING: EngagementAlert(AudibleAlert.trafficSignGreen),
#ET.WARNING: Alert(
# "출발합니다.",
# "",
# AlertStatus.normal, AlertSize.small,
# Priority.LOW, VisualAlert.none, AudibleAlert.trafficSignGreen, 3.),
},
EventName.trafficSignChanged: {
ET.WARNING: Alert(
"신호가바뀌었어요.",
"",
AlertStatus.normal, AlertSize.small,
Priority.LOW, VisualAlert.none, AudibleAlert.trafficSignChanged, 1.),
},
EventName.turningLeft: {
ET.WARNING: Alert(
"좌회전 합니다",
"",
AlertStatus.normal, AlertSize.small,
Priority.LOW, VisualAlert.none, AudibleAlert.none, .1),
},
EventName.turningRight: {
ET.WARNING: Alert(
"우회전 합니다",
"",
AlertStatus.normal, AlertSize.small,
Priority.LOW, VisualAlert.none, AudibleAlert.none, .1),
},
EventName.audio1: {
ET.WARNING: EngagementAlert(AudibleAlert.audio1),
},
EventName.audio2: {
ET.WARNING: EngagementAlert(AudibleAlert.audio2),
},
EventName.audio3: {
ET.WARNING: EngagementAlert(AudibleAlert.audio3),
},
EventName.audio4: {
ET.WARNING: EngagementAlert(AudibleAlert.audio4),
},
EventName.audio5: {
ET.WARNING: EngagementAlert(AudibleAlert.audio5),
},
EventName.audio6: {
ET.WARNING: EngagementAlert(AudibleAlert.audio6),
},
EventName.audio7: {
ET.WARNING: EngagementAlert(AudibleAlert.audio7),
},
EventName.audio8: {
ET.WARNING: EngagementAlert(AudibleAlert.audio8),
},
EventName.audio9: {
ET.WARNING: EngagementAlert(AudibleAlert.audio9),
},
EventName.audio10: {
ET.WARNING: EngagementAlert(AudibleAlert.audio10),
},
EventName.audio0: {
ET.WARNING: EngagementAlert(AudibleAlert.longDisengaged),
},
}
if __name__ == '__main__':
# print all alerts by type and priority
from cereal.services import SERVICE_LIST
from collections import defaultdict
event_names = {v: k for k, v in EventName.schema.enumerants.items()}
alerts_by_type: dict[str, dict[Priority, list[str]]] = defaultdict(lambda: defaultdict(list))
CP = car.CarParams.new_message()
CS = car.CarState.new_message()
sm = messaging.SubMaster(list(SERVICE_LIST.keys()))
for i, alerts in EVENTS.items():
for et, alert in alerts.items():
if callable(alert):
alert = alert(CP, CS, sm, False, 1, log.LongitudinalPersonality.standard)
alerts_by_type[et][alert.priority].append(event_names[i])
all_alerts: dict[str, list[tuple[Priority, list[str]]]] = {}
for et, priority_alerts in alerts_by_type.items():
all_alerts[et] = sorted(priority_alerts.items(), key=lambda x: x[0], reverse=True)
for status, evs in sorted(all_alerts.items(), key=lambda x: x[0]):
print(f"**** {status} ****")
for p, alert_list in evs:
print(f" {repr(p)}:")
print(" ", ', '.join(alert_list), "\n")