diff --git a/selfdrive/selfdrived/events.py b/selfdrive/selfdrived/events.py index c9b28143..f5aa853b 100755 --- a/selfdrive/selfdrived/events.py +++ b/selfdrive/selfdrived/events.py @@ -73,25 +73,25 @@ def startup_master_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.SubM if "REPLAY" in os.environ: branch = "replay" - return StartupAlert("WARNING: This branch is not tested", branch, alert_status=AlertStatus.userPrompt) + 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"Drive above {get_display_speed(CP.minEnableSpeed, metric)} to engage") + 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"Steer Assist Unavailable Below {get_display_speed(CP.minSteerSpeed, metric)}", + f"转向辅助在 {get_display_speed(CP.minSteerSpeed, metric)} 以下不可用", "", AlertStatus.userPrompt, AlertSize.small, Priority.LOW, VisualAlert.none, 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 = 'Recalibrating' if sm['liveCalibration'].calStatus == log.LiveCalibrationData.Status.recalibrating else 'Calibrating' + first_word = '重新标定中' if sm['liveCalibration'].calStatus == log.LiveCalibrationData.Status.recalibrating else '标定中' return Alert( - f"{first_word}: {sm['liveCalibration'].calPerc:.0f}%", - f"Drive Above {get_display_speed(MIN_SPEED_FILTER, metric)}", + 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) @@ -99,8 +99,8 @@ def calibration_incomplete_alert(CP: car.CarParams, CS: car.CarState, sm: messag def audio_feedback_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.SubMaster, metric: bool, soft_disable_time: int, personality) -> Alert: duration = FEEDBACK_MAX_DURATION - ((sm['audioFeedback'].blockNum + 1) * SAMPLE_BUFFER / SAMPLE_RATE) return NormalPermanentAlert( - "Recording Audio Feedback", - f"{round(duration)} second{'s' if round(duration) != 1 else ''} remaining. Press again to save early.", + "正在录制语音反馈", + f"剩余 {round(duration)} 秒,再次按下可提前保存。", priority=Priority.LOW) @@ -108,57 +108,57 @@ def audio_feedback_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.SubM 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("Out of Storage", f"{full_perc}% full") + return NormalPermanentAlert("存储空间不足", f"已用 {full_perc}%") 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 Speed Invalid") + msg = f"速度误差:{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="Process 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="Communication Issue Between Processes") + 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("Camera Malfunction", ', '.join(bad_cams)) + 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"Remount Device (Pitch: {pitch:.1f}°, Yaw: {yaw:.1f}°)" - return NormalPermanentAlert("Calibration Invalid", angles) + angles = f"重新安装设备(俯仰:{pitch:.1f}°,偏航:{yaw:.1f}°)" + return NormalPermanentAlert("标定无效", angles) def paramsd_invalid_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.SubMaster, metric: bool, soft_disable_time: int, personality) -> Alert: if not sm['liveParameters'].angleOffsetValid: angle_offset_deg = sm['liveParameters'].angleOffsetDeg - title = "Steering misalignment detected" - text = f"Angle offset too high (Offset: {angle_offset_deg:.1f}°)" + title = "检测到转向偏移" + text = f"角度偏移过大(偏移:{angle_offset_deg:.1f}°)" elif not sm['liveParameters'].steerRatioValid: steer_ratio = sm['liveParameters'].steerRatio - title = "Steer ratio mismatch" - text = f"Steering rack geometry may be off (Ratio: {steer_ratio:.1f})" + title = "转向比不匹配" + text = f"转向几何可能存在问题(比例:{steer_ratio:.1f})" elif not sm['liveParameters'].stiffnessFactorValid: stiffness_factor = sm['liveParameters'].stiffnessFactor - title = "Abnormal tire stiffness" - text = f"Check tires, pressure, or alignment (Factor: {stiffness_factor:.1f})" + title = "轮胎刚度异常" + text = f"检查轮胎、胎压或定位(系数:{stiffness_factor:.1f})" else: - return NoEntryAlert("paramsd Temporary Error") + return NoEntryAlert("paramsd 临时错误") return NoEntryAlert(alert_text_1=title, alert_text_2=text) @@ -166,27 +166,27 @@ def overheat_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.SubMaster, cpu = max(sm['deviceState'].cpuTempC, default=0.) gpu = max(sm['deviceState'].gpuTempC, default=0.) temp = max((cpu, gpu, sm['deviceState'].memoryTempC)) - return NormalPermanentAlert("System Overheated", f"{temp:.0f} °C") + 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("Low Memory", f"{sm['deviceState'].memoryUsagePercent}% used") + return NormalPermanentAlert("内存不足", f"已用 {sm['deviceState'].memoryUsagePercent}%") 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("High CPU Usage", f"{x}% used") + return NormalPermanentAlert("CPU 负载过高", f"已用 {x}%") def modeld_lagging_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.SubMaster, metric: bool, soft_disable_time: int, personality) -> Alert: - return NormalPermanentAlert("Driving Model Lagging", f"{sm['modelV2'].frameDropPerc:.1f}% frames dropped") + return NormalPermanentAlert("驾驶模型延迟", f"丢帧 {sm['modelV2'].frameDropPerc:.1f}%") 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.torque - vals = f"Gas: {round(gb * 100.)}%, Steer: {round(steer * 100.)}%" - return NormalPermanentAlert("Joystick Mode", vals) + vals = f"油门:{round(gb * 100.)}%,转向:{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: @@ -201,18 +201,18 @@ def longitudinal_maneuver_alert(CP: car.CarParams, CS: car.CarState, sm: messagi 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) + return NormalPermanentAlert(f"驾驶风格:{personality}", duration=1.5) def invalid_lkas_setting_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.SubMaster, metric: bool, soft_disable_time: int, personality) -> Alert: - text = "Toggle stock LKAS on or off to engage" + text = "切换原车 LKAS 开关后即可开启" if CP.brand == "tesla": - text = "Switch to Traffic-Aware Cruise Control to engage" + text = "切换到交通感知巡航控制后即可开启" elif CP.brand == "mazda": - text = "Enable your car's LKAS to engage" + text = "开启车辆原车 LKAS 后即可开启" elif CP.brand == "nissan": - text = "Disable your car's stock LKAS to engage" - return NormalPermanentAlert("Invalid LKAS setting", text) + text = "关闭原车 LKAS 后即可开启" + return NormalPermanentAlert("LKAS 设置无效", text) @@ -226,26 +226,26 @@ EVENTS: dict[int, dict[str, Alert | AlertCallbackType]] = { EventName.joystickDebug: { ET.WARNING: joystick_alert, - ET.PERMANENT: NormalPermanentAlert("Joystick Mode"), + ET.PERMANENT: NormalPermanentAlert("摇杆模式"), }, EventName.longitudinalManeuver: { ET.WARNING: longitudinal_maneuver_alert, - ET.PERMANENT: NormalPermanentAlert("Longitudinal Maneuver Mode", - "Ensure road ahead is clear"), + ET.PERMANENT: NormalPermanentAlert("纵向操纵模式", + "确保前方道路空旷"), }, EventName.lateralManeuver: { ET.WARNING: longitudinal_maneuver_alert, - ET.PERMANENT: NormalPermanentAlert("Lateral Maneuver Mode"), + ET.PERMANENT: NormalPermanentAlert("横向操纵模式"), }, EventName.selfdriveInitializing: { - ET.NO_ENTRY: NoEntryAlert("System Initializing"), + ET.NO_ENTRY: NoEntryAlert("系统初始化中"), }, EventName.startup: { - ET.PERMANENT: StartupAlert("Be ready to take over at any time") + ET.PERMANENT: StartupAlert("随时准备接管") }, EventName.startupMaster: { @@ -253,28 +253,28 @@ EVENTS: dict[int, dict[str, Alert | AlertCallbackType]] = { }, EventName.startupNoControl: { - ET.PERMANENT: StartupAlert("Dashcam mode"), - ET.NO_ENTRY: NoEntryAlert("Dashcam mode"), + ET.PERMANENT: StartupAlert("行车记录仪模式"), + ET.NO_ENTRY: NoEntryAlert("行车记录仪模式"), }, EventName.startupNoCar: { - ET.PERMANENT: StartupAlert("Dashcam mode for unsupported car"), + ET.PERMANENT: StartupAlert("不支持的车型,进入行车记录仪模式"), }, EventName.startupNoSecOcKey: { - ET.PERMANENT: NormalPermanentAlert("Dashcam Mode", - "Security Key Not Available", + ET.PERMANENT: NormalPermanentAlert("行车记录仪模式", + "安全密钥不可用", priority=Priority.HIGH), }, EventName.dashcamMode: { - ET.PERMANENT: NormalPermanentAlert("Dashcam Mode", + ET.PERMANENT: NormalPermanentAlert("行车记录仪模式", priority=Priority.LOWEST), }, EventName.invalidLkasSetting: { ET.PERMANENT: invalid_lkas_setting_alert, - ET.NO_ENTRY: NoEntryAlert("Invalid LKAS setting"), + ET.NO_ENTRY: NoEntryAlert("LKAS 设置无效"), }, EventName.cruiseMismatch: { @@ -285,44 +285,44 @@ EVENTS: dict[int, dict[str, Alert | AlertCallbackType]] = { # 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("Dashcam Mode", - "Car Unrecognized", + ET.PERMANENT: NormalPermanentAlert("行车记录仪模式", + "车型未识别", priority=Priority.LOWEST), }, EventName.aeb: { ET.PERMANENT: Alert( - "BRAKE!", - "Emergency Braking: Risk of Collision", + "刹车!", + "紧急刹车:碰撞风险", AlertStatus.critical, AlertSize.full, Priority.HIGHEST, VisualAlert.fcw, AudibleAlert.none, 2.), - ET.NO_ENTRY: NoEntryAlert("AEB: Risk of Collision"), + ET.NO_ENTRY: NoEntryAlert("AEB:碰撞风险"), }, EventName.stockAeb: { ET.PERMANENT: Alert( - "BRAKE!", - "Stock AEB: Risk of Collision", + "刹车!", + "原车 AEB:碰撞风险", AlertStatus.critical, AlertSize.full, Priority.HIGHEST, VisualAlert.fcw, AudibleAlert.none, 2.), - ET.NO_ENTRY: NoEntryAlert("Stock AEB: Risk of Collision"), + ET.NO_ENTRY: NoEntryAlert("原车 AEB:碰撞风险"), }, EventName.stockLkas: { - ET.NO_ENTRY: NoEntryAlert("Stock LKAS: Lane Departure Detected"), + ET.NO_ENTRY: NoEntryAlert("原车 LKAS:检测到车道偏离"), }, EventName.fcw: { ET.PERMANENT: Alert( - "BRAKE!", - "Risk of Collision", + "刹车!", + "碰撞风险", AlertStatus.critical, AlertSize.full, Priority.HIGHEST, VisualAlert.fcw, AudibleAlert.warningSoft, 2.), }, EventName.ldw: { ET.PERMANENT: Alert( - "Lane Departure Detected", + "检测到车道偏离", "", AlertStatus.userPrompt, AlertSize.small, Priority.LOW, VisualAlert.ldw, AudibleAlert.prompt, 3.), @@ -332,7 +332,7 @@ EVENTS: dict[int, dict[str, Alert | AlertCallbackType]] = { EventName.steerTempUnavailableSilent: { ET.WARNING: Alert( - "Steering Assist Temporarily Unavailable", + "转向辅助暂时不可用", "", AlertStatus.userPrompt, AlertSize.small, Priority.LOW, VisualAlert.steerRequired, AudibleAlert.prompt, 1.8), @@ -340,7 +340,7 @@ EVENTS: dict[int, dict[str, Alert | AlertCallbackType]] = { EventName.driverDistracted1: { ET.PERMANENT: Alert( - "Pay Attention", + "请注意路况", "", AlertStatus.normal, AlertSize.small, Priority.LOW, VisualAlert.none, AudibleAlert.none, .1), @@ -348,23 +348,23 @@ EVENTS: dict[int, dict[str, Alert | AlertCallbackType]] = { EventName.driverDistracted2: { ET.PERMANENT: Alert( - "Pay Attention", - "Driver Distracted", + "请注意路况", + "驾驶分心", AlertStatus.userPrompt, AlertSize.mid, Priority.MID, VisualAlert.steerRequired, AudibleAlert.promptDistracted, .1), }, EventName.driverDistracted3: { ET.PERMANENT: Alert( - "DISENGAGE IMMEDIATELY", - "Driver Distracted", + "立即退出", + "驾驶分心", AlertStatus.critical, AlertSize.full, Priority.HIGH, VisualAlert.steerRequired, AudibleAlert.warningImmediate, .1), }, EventName.driverUnresponsive1: { ET.PERMANENT: Alert( - "Touch Steering Wheel: No Face Detected", + "请握住方向盘:未检测到面部", "", AlertStatus.normal, AlertSize.small, Priority.LOW, VisualAlert.steerRequired, AudibleAlert.none, .1), @@ -372,31 +372,31 @@ EVENTS: dict[int, dict[str, Alert | AlertCallbackType]] = { EventName.driverUnresponsive2: { ET.PERMANENT: Alert( - "Touch Steering Wheel", - "Driver Unresponsive", + "请握住方向盘", + "驾驶员无响应", AlertStatus.userPrompt, AlertSize.mid, Priority.MID, VisualAlert.steerRequired, AudibleAlert.promptDistracted, .1), }, EventName.driverUnresponsive3: { ET.PERMANENT: Alert( - "DISENGAGE IMMEDIATELY", - "Driver Unresponsive", + "立即退出", + "驾驶员无响应", AlertStatus.critical, AlertSize.full, Priority.HIGH, VisualAlert.steerRequired, AudibleAlert.warningImmediate, .1), }, EventName.manualRestart: { ET.WARNING: Alert( - "TAKE CONTROL", - "Resume Driving Manually", + "请接管", + "请手动恢复驾驶", AlertStatus.userPrompt, AlertSize.mid, Priority.LOW, VisualAlert.none, AudibleAlert.none, .2), }, EventName.resumeRequired: { ET.WARNING: Alert( - "Press Resume to Exit Standstill", + "按 Resume 退出静止状态", "", AlertStatus.userPrompt, AlertSize.small, Priority.LOW, VisualAlert.none, AudibleAlert.none, .2), @@ -408,7 +408,7 @@ EVENTS: dict[int, dict[str, Alert | AlertCallbackType]] = { EventName.preLaneChangeLeft: { ET.WARNING: Alert( - "Steer Left to Start Lane Change Once Safe", + "确认安全后左转方向盘开始变道", "", AlertStatus.normal, AlertSize.small, Priority.LOW, VisualAlert.none, AudibleAlert.none, .1), @@ -416,7 +416,7 @@ EVENTS: dict[int, dict[str, Alert | AlertCallbackType]] = { EventName.preLaneChangeRight: { ET.WARNING: Alert( - "Steer Right to Start Lane Change Once Safe", + "确认安全后右转方向盘开始变道", "", AlertStatus.normal, AlertSize.small, Priority.LOW, VisualAlert.none, AudibleAlert.none, .1), @@ -424,7 +424,7 @@ EVENTS: dict[int, dict[str, Alert | AlertCallbackType]] = { EventName.laneChangeBlocked: { ET.WARNING: Alert( - "Car Detected in Blindspot", + "盲区检测到车辆", "", AlertStatus.userPrompt, AlertSize.small, Priority.LOW, VisualAlert.none, AudibleAlert.prompt, .1), @@ -432,7 +432,7 @@ EVENTS: dict[int, dict[str, Alert | AlertCallbackType]] = { EventName.laneChange: { ET.WARNING: Alert( - "Changing Lanes", + "正在变道", "", AlertStatus.normal, AlertSize.small, Priority.LOW, VisualAlert.none, AudibleAlert.none, .1), @@ -440,41 +440,41 @@ EVENTS: dict[int, dict[str, Alert | AlertCallbackType]] = { EventName.steerSaturated: { ET.WARNING: Alert( - "Take Control", - "Turn Exceeds Steering Limit", + "请接管", + "转向达到极限", 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 Malfunction", "Likely Hardware Issue"), + ET.PERMANENT: NormalPermanentAlert("风扇故障", "可能为硬件问题"), }, # Camera is not outputting frames EventName.cameraMalfunction: { ET.PERMANENT: camera_malfunction_alert, - ET.SOFT_DISABLE: soft_disable_alert("Camera Malfunction"), - ET.NO_ENTRY: NoEntryAlert("Camera Malfunction: Reboot Your Device"), + ET.SOFT_DISABLE: soft_disable_alert("摄像头故障"), + ET.NO_ENTRY: NoEntryAlert("摄像头故障:请重启设备"), }, # Camera framerate too low EventName.cameraFrameRate: { - ET.PERMANENT: NormalPermanentAlert("Camera Frame Rate Low", "Reboot your Device"), - ET.SOFT_DISABLE: soft_disable_alert("Camera Frame Rate Low"), - ET.NO_ENTRY: NoEntryAlert("Camera Frame Rate Low: Reboot Your Device"), + ET.PERMANENT: NormalPermanentAlert("摄像头帧率过低", "请重启设备"), + ET.SOFT_DISABLE: soft_disable_alert("摄像头帧率过低"), + ET.NO_ENTRY: NoEntryAlert("摄像头帧率过低:请重启设备"), }, # Unused EventName.locationdTemporaryError: { - ET.NO_ENTRY: NoEntryAlert("locationd Temporary Error"), - ET.SOFT_DISABLE: soft_disable_alert("locationd Temporary Error"), + ET.NO_ENTRY: NoEntryAlert("locationd 临时错误"), + ET.SOFT_DISABLE: soft_disable_alert("locationd 临时错误"), }, EventName.locationdPermanentError: { - ET.NO_ENTRY: NoEntryAlert("locationd Permanent Error"), - ET.IMMEDIATE_DISABLE: ImmediateDisableAlert("locationd Permanent Error"), - ET.PERMANENT: NormalPermanentAlert("locationd Permanent Error"), + 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 @@ -487,13 +487,13 @@ EVENTS: dict[int, dict[str, Alert | AlertCallbackType]] = { # bad alignment or bad sensor data. If this happens consistently consider creating an issue on GitHub EventName.paramsdTemporaryError: { ET.NO_ENTRY: paramsd_invalid_alert, - ET.SOFT_DISABLE: soft_disable_alert("paramsd Temporary Error"), + ET.SOFT_DISABLE: soft_disable_alert("paramsd 临时错误"), }, EventName.paramsdPermanentError: { - ET.NO_ENTRY: NoEntryAlert("paramsd Permanent Error"), - ET.IMMEDIATE_DISABLE: ImmediateDisableAlert("paramsd Permanent Error"), - ET.PERMANENT: NormalPermanentAlert("paramsd Permanent Error"), + ET.NO_ENTRY: NoEntryAlert("paramsd 永久错误"), + ET.IMMEDIATE_DISABLE: ImmediateDisableAlert("paramsd 永久错误"), + ET.PERMANENT: NormalPermanentAlert("paramsd 永久错误"), }, # ********** events that affect controls state transitions ********** @@ -512,12 +512,12 @@ EVENTS: dict[int, dict[str, Alert | AlertCallbackType]] = { EventName.buttonCancel: { ET.USER_DISABLE: EngagementAlert(AudibleAlert.disengage), - ET.NO_ENTRY: NoEntryAlert("Cancel Pressed"), + ET.NO_ENTRY: NoEntryAlert("已按下取消"), }, EventName.brakeHold: { ET.WARNING: Alert( - "Press Resume to Exit Brake Hold", + "按 Resume 退出刹车保持", "", AlertStatus.userPrompt, AlertSize.small, Priority.LOW, VisualAlert.none, AudibleAlert.none, .2), @@ -525,23 +525,23 @@ EVENTS: dict[int, dict[str, Alert | AlertCallbackType]] = { EventName.parkBrake: { ET.USER_DISABLE: EngagementAlert(AudibleAlert.disengage), - ET.NO_ENTRY: NoEntryAlert("Parking Brake Engaged"), + ET.NO_ENTRY: NoEntryAlert("手刹已拉起"), }, EventName.pedalPressed: { ET.USER_DISABLE: EngagementAlert(AudibleAlert.disengage), - ET.NO_ENTRY: NoEntryAlert("Pedal Pressed", + ET.NO_ENTRY: NoEntryAlert("已踩下踏板", visual_alert=VisualAlert.brakePressed), }, EventName.steerDisengage: { ET.USER_DISABLE: EngagementAlert(AudibleAlert.disengage), - ET.NO_ENTRY: NoEntryAlert("Steering Pressed"), + ET.NO_ENTRY: NoEntryAlert("已转动方向盘"), }, EventName.preEnableStandstill: { ET.PRE_ENABLE: Alert( - "Release Brake to Engage", + "松开刹车以开启", "", AlertStatus.normal, AlertSize.small, Priority.LOWEST, VisualAlert.none, AudibleAlert.none, .1, creation_delay=1.), @@ -569,27 +569,27 @@ EVENTS: dict[int, dict[str, Alert | AlertCallbackType]] = { }, EventName.resumeBlocked: { - ET.NO_ENTRY: NoEntryAlert("Press Set to Engage"), + ET.NO_ENTRY: NoEntryAlert("按 Set 以开启"), }, EventName.wrongCruiseMode: { ET.USER_DISABLE: EngagementAlert(AudibleAlert.disengage), - ET.NO_ENTRY: NoEntryAlert("Adaptive Cruise Disabled"), + ET.NO_ENTRY: NoEntryAlert("自适应巡航已禁用"), }, EventName.steerTempUnavailable: { - ET.SOFT_DISABLE: soft_disable_alert("Steering Assist Temporarily Unavailable"), - ET.NO_ENTRY: NoEntryAlert("Steering Temporarily Unavailable"), + ET.SOFT_DISABLE: soft_disable_alert("转向辅助暂时不可用"), + ET.NO_ENTRY: NoEntryAlert("转向暂时不可用"), }, EventName.steerTimeLimit: { - ET.SOFT_DISABLE: soft_disable_alert("Vehicle Steering Time Limit"), - ET.NO_ENTRY: NoEntryAlert("Vehicle Steering Time Limit"), + ET.SOFT_DISABLE: soft_disable_alert("车辆转向时间限制"), + ET.NO_ENTRY: NoEntryAlert("车辆转向时间限制"), }, EventName.outOfSpace: { ET.PERMANENT: out_of_space_alert, - ET.NO_ENTRY: NoEntryAlert("Out of Storage"), + ET.NO_ENTRY: NoEntryAlert("存储空间不足"), }, EventName.belowEngageSpeed: { @@ -598,35 +598,35 @@ EVENTS: dict[int, dict[str, Alert | AlertCallbackType]] = { EventName.sensorDataInvalid: { ET.PERMANENT: Alert( - "Sensor Data Invalid", - "Possible Hardware Issue", + "传感器数据无效", + "可能为硬件问题", AlertStatus.normal, AlertSize.mid, Priority.LOWER, VisualAlert.none, AudibleAlert.none, .2, creation_delay=1.), - ET.NO_ENTRY: NoEntryAlert("Sensor Data Invalid"), - ET.SOFT_DISABLE: soft_disable_alert("Sensor Data Invalid"), + ET.NO_ENTRY: NoEntryAlert("传感器数据无效"), + ET.SOFT_DISABLE: soft_disable_alert("传感器数据无效"), }, EventName.noGps: { }, EventName.tooDistracted: { - ET.NO_ENTRY: NoEntryAlert("Distraction Level Too High"), + ET.NO_ENTRY: NoEntryAlert("分心程度过高"), }, EventName.excessiveActuation: { - ET.SOFT_DISABLE: soft_disable_alert("Excessive Actuation"), - ET.NO_ENTRY: NoEntryAlert("Excessive Actuation"), + ET.SOFT_DISABLE: soft_disable_alert("执行器过度动作"), + ET.NO_ENTRY: NoEntryAlert("执行器过度动作"), }, EventName.overheat: { ET.PERMANENT: overheat_alert, - ET.SOFT_DISABLE: soft_disable_alert("System Overheated"), - ET.NO_ENTRY: NoEntryAlert("System Overheated"), + ET.SOFT_DISABLE: soft_disable_alert("系统过热"), + ET.NO_ENTRY: NoEntryAlert("系统过热"), }, EventName.wrongGear: { - ET.SOFT_DISABLE: user_soft_disable_alert("Gear not D"), - ET.NO_ENTRY: NoEntryAlert("Gear not D"), + ET.SOFT_DISABLE: user_soft_disable_alert("不在 D 档"), + ET.NO_ENTRY: NoEntryAlert("不在 D 档"), }, # This alert is thrown when the calibration angles are outside of the acceptable range. @@ -636,40 +636,40 @@ EVENTS: dict[int, dict[str, Alert | AlertCallbackType]] = { # See https://comma.ai/setup for more information EventName.calibrationInvalid: { ET.PERMANENT: calibration_invalid_alert, - ET.SOFT_DISABLE: soft_disable_alert("Calibration Invalid: Remount Device & Recalibrate"), - ET.NO_ENTRY: NoEntryAlert("Calibration Invalid: Remount Device & Recalibrate"), + ET.SOFT_DISABLE: soft_disable_alert("标定无效:重新安装设备并重新标定"), + ET.NO_ENTRY: NoEntryAlert("标定无效:重新安装设备并重新标定"), }, EventName.calibrationIncomplete: { ET.PERMANENT: calibration_incomplete_alert, - ET.SOFT_DISABLE: soft_disable_alert("Calibration Incomplete"), - ET.NO_ENTRY: NoEntryAlert("Calibration in Progress"), + ET.SOFT_DISABLE: soft_disable_alert("标定未完成"), + ET.NO_ENTRY: NoEntryAlert("标定进行中"), }, EventName.calibrationRecalibrating: { ET.PERMANENT: calibration_incomplete_alert, - ET.SOFT_DISABLE: soft_disable_alert("Device Remount Detected: Recalibrating"), - ET.NO_ENTRY: NoEntryAlert("Remount Detected: Recalibrating"), + ET.SOFT_DISABLE: soft_disable_alert("检测到设备重装:正在重新标定"), + ET.NO_ENTRY: NoEntryAlert("检测到重装:正在重新标定"), }, EventName.doorOpen: { - ET.SOFT_DISABLE: user_soft_disable_alert("Door Open"), - ET.NO_ENTRY: NoEntryAlert("Door Open"), + ET.SOFT_DISABLE: user_soft_disable_alert("车门打开"), + ET.NO_ENTRY: NoEntryAlert("车门打开"), }, EventName.seatbeltNotLatched: { - ET.SOFT_DISABLE: user_soft_disable_alert("Seatbelt Unlatched"), - ET.NO_ENTRY: NoEntryAlert("Seatbelt Unlatched"), + ET.SOFT_DISABLE: user_soft_disable_alert("安全带未系"), + ET.NO_ENTRY: NoEntryAlert("安全带未系"), }, EventName.espDisabled: { - ET.SOFT_DISABLE: soft_disable_alert("Electronic Stability Control Disabled"), - ET.NO_ENTRY: NoEntryAlert("Electronic Stability Control Disabled"), + ET.SOFT_DISABLE: soft_disable_alert("车身稳定系统已关闭"), + ET.NO_ENTRY: NoEntryAlert("车身稳定系统已关闭"), }, EventName.lowBattery: { - ET.SOFT_DISABLE: soft_disable_alert("Low Battery"), - ET.NO_ENTRY: NoEntryAlert("Low Battery"), + ET.SOFT_DISABLE: soft_disable_alert("电池电量低"), + ET.NO_ENTRY: NoEntryAlert("电池电量低"), }, # Different openpilot services communicate between each other at a certain @@ -677,41 +677,41 @@ EVENTS: dict[int, dict[str, Alert | AlertCallbackType]] = { # 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("Communication Issue Between Processes"), + ET.SOFT_DISABLE: soft_disable_alert("进程间通信异常"), ET.NO_ENTRY: comm_issue_alert, }, EventName.commIssueAvgFreq: { - ET.SOFT_DISABLE: soft_disable_alert("Low Communication Rate Between Processes"), - ET.NO_ENTRY: NoEntryAlert("Low Communication Rate Between Processes"), + ET.SOFT_DISABLE: soft_disable_alert("进程间通信频率过低"), + ET.NO_ENTRY: NoEntryAlert("进程间通信频率过低"), }, EventName.selfdrivedLagging: { - ET.SOFT_DISABLE: soft_disable_alert("System Lagging"), - ET.NO_ENTRY: NoEntryAlert("Selfdrive Process Lagging: Reboot Your Device"), + 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("Process Not Running"), + ET.SOFT_DISABLE: soft_disable_alert("进程未运行"), }, EventName.radarFault: { - ET.SOFT_DISABLE: soft_disable_alert("Radar Error: Restart the Car"), - ET.NO_ENTRY: NoEntryAlert("Radar Error: Restart the Car"), + ET.SOFT_DISABLE: soft_disable_alert("雷达错误:请重启车辆"), + ET.NO_ENTRY: NoEntryAlert("雷达错误:请重启车辆"), }, EventName.radarTempUnavailable: { - ET.SOFT_DISABLE: soft_disable_alert("Radar Temporarily Unavailable"), - ET.NO_ENTRY: NoEntryAlert("Radar Temporarily Unavailable"), + 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("Driving Model Lagging"), - ET.NO_ENTRY: NoEntryAlert("Driving Model Lagging"), + ET.SOFT_DISABLE: soft_disable_alert("驾驶模型延迟"), + ET.NO_ENTRY: NoEntryAlert("驾驶模型延迟"), ET.PERMANENT: modeld_lagging_alert, }, @@ -721,45 +721,45 @@ EVENTS: dict[int, dict[str, Alert | AlertCallbackType]] = { # 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 Speed Invalid"), + 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("Device Fell Off Mount"), - ET.NO_ENTRY: NoEntryAlert("Device Fell Off Mount"), + ET.SOFT_DISABLE: soft_disable_alert("设备从支架掉落"), + ET.NO_ENTRY: NoEntryAlert("设备从支架掉落"), }, EventName.lowMemory: { - ET.SOFT_DISABLE: soft_disable_alert("Low Memory: Reboot Your Device"), + ET.SOFT_DISABLE: soft_disable_alert("内存不足:请重启设备"), ET.PERMANENT: low_memory_alert, - ET.NO_ENTRY: NoEntryAlert("Low Memory: Reboot Your Device"), + ET.NO_ENTRY: NoEntryAlert("内存不足:请重启设备"), }, EventName.accFaulted: { - ET.IMMEDIATE_DISABLE: ImmediateDisableAlert("Cruise Fault: Restart the Car"), - ET.PERMANENT: NormalPermanentAlert("Cruise Fault: Restart the car to engage"), - ET.NO_ENTRY: NoEntryAlert("Cruise Fault: Restart the Car"), + ET.IMMEDIATE_DISABLE: ImmediateDisableAlert("巡航故障:请重启车辆"), + ET.PERMANENT: NormalPermanentAlert("巡航故障:重启车辆后可开启"), + ET.NO_ENTRY: NoEntryAlert("巡航故障:请重启车辆"), }, EventName.espActive: { - ET.SOFT_DISABLE: soft_disable_alert("Electronic Stability Control Active"), - ET.NO_ENTRY: NoEntryAlert("Electronic Stability Control Active"), + ET.SOFT_DISABLE: soft_disable_alert("车身稳定系统已激活"), + ET.NO_ENTRY: NoEntryAlert("车身稳定系统已激活"), }, EventName.controlsMismatch: { - ET.IMMEDIATE_DISABLE: ImmediateDisableAlert("Controls Mismatch"), - ET.NO_ENTRY: NoEntryAlert("Controls Mismatch"), + 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 Error: Reboot Your Device"), - ET.PERMANENT: NormalPermanentAlert("USB Error: Reboot Your Device"), - ET.NO_ENTRY: NoEntryAlert("USB Error: Reboot Your Device"), + 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: @@ -767,45 +767,45 @@ EVENTS: dict[int, dict[str, Alert | AlertCallbackType]] = { # - 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.IMMEDIATE_DISABLE: ImmediateDisableAlert("Unknown Vehicle Variant"), + ET.IMMEDIATE_DISABLE: ImmediateDisableAlert("未知车型变体"), ET.PERMANENT: Alert( - "Unknown Vehicle Variant", + "未知车型变体", "", AlertStatus.normal, AlertSize.small, Priority.LOW, VisualAlert.none, AudibleAlert.none, 1., creation_delay=1.), - ET.NO_ENTRY: NoEntryAlert("Unknown Vehicle Variant"), + ET.NO_ENTRY: NoEntryAlert("未知车型变体"), }, EventName.canBusMissing: { - ET.IMMEDIATE_DISABLE: ImmediateDisableAlert("CAN Bus Disconnected"), + ET.IMMEDIATE_DISABLE: ImmediateDisableAlert("CAN 总线断开"), ET.PERMANENT: Alert( - "CAN Bus Disconnected: Likely Faulty Cable", + "CAN 总线断开:可能为线缆故障", "", AlertStatus.normal, AlertSize.small, Priority.LOW, VisualAlert.none, AudibleAlert.none, 1., creation_delay=1.), - ET.NO_ENTRY: NoEntryAlert("CAN Bus Disconnected: Check Connections"), + ET.NO_ENTRY: NoEntryAlert("CAN 总线断开:请检查连接"), }, EventName.steerUnavailable: { - ET.IMMEDIATE_DISABLE: ImmediateDisableAlert("LKAS Fault: Restart the Car"), - ET.PERMANENT: NormalPermanentAlert("LKAS Fault: Restart the car to engage"), - ET.NO_ENTRY: NoEntryAlert("LKAS Fault: Restart the Car"), + ET.IMMEDIATE_DISABLE: ImmediateDisableAlert("LKAS故障:请重启车辆"), + ET.PERMANENT: NormalPermanentAlert("LKAS故障:重启车辆后可开启"), + ET.NO_ENTRY: NoEntryAlert("LKAS故障:请重启车辆"), }, EventName.reverseGear: { ET.PERMANENT: Alert( - "Reverse\nGear", + "倒车\n档位", "", AlertStatus.normal, AlertSize.full, Priority.LOWEST, VisualAlert.none, AudibleAlert.none, .2, creation_delay=0.5), - ET.USER_DISABLE: ImmediateDisableAlert("Reverse Gear"), - ET.NO_ENTRY: NoEntryAlert("Reverse Gear"), + ET.USER_DISABLE: ImmediateDisableAlert("倒车档位"), + ET.NO_ENTRY: NoEntryAlert("倒车档位"), }, # 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("Cruise Is Off"), + ET.IMMEDIATE_DISABLE: ImmediateDisableAlert("巡航已关闭"), }, # When the relay in the harness box opens the CAN bus between the LKAS camera @@ -813,15 +813,15 @@ EVENTS: dict[int, dict[str, Alert | AlertCallbackType]] = { # 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("Harness Relay Malfunction"), - ET.PERMANENT: NormalPermanentAlert("Harness Relay Malfunction", "Check Hardware"), - ET.NO_ENTRY: NoEntryAlert("Harness Relay Malfunction"), + ET.IMMEDIATE_DISABLE: ImmediateDisableAlert("线束继电器故障"), + ET.PERMANENT: NormalPermanentAlert("线束继电器故障", "请检查硬件"), + ET.NO_ENTRY: NoEntryAlert("线束继电器故障"), }, EventName.speedTooLow: { ET.IMMEDIATE_DISABLE: Alert( - "openpilot Canceled", - "Speed too low", + "openpilot 已取消", + "速度过低", AlertStatus.normal, AlertSize.mid, Priority.HIGH, VisualAlert.none, AudibleAlert.disengage, 3.), }, @@ -829,17 +829,17 @@ EVENTS: dict[int, dict[str, Alert | AlertCallbackType]] = { # When the car is driving faster than most cars in the training data, the model outputs can be unpredictable. EventName.speedTooHigh: { ET.WARNING: Alert( - "Speed Too High", - "Model uncertain at this speed", + "速度过高", + "模型在此速度下不确定", AlertStatus.userPrompt, AlertSize.mid, Priority.HIGH, VisualAlert.steerRequired, AudibleAlert.promptRepeat, 4.), - ET.NO_ENTRY: NoEntryAlert("Slow down to engage"), + ET.NO_ENTRY: NoEntryAlert("请减速后开启"), }, EventName.vehicleSensorsInvalid: { - ET.IMMEDIATE_DISABLE: ImmediateDisableAlert("Vehicle Sensors Invalid"), - ET.PERMANENT: NormalPermanentAlert("Vehicle Sensors Calibrating", "Drive to Calibrate"), - ET.NO_ENTRY: NoEntryAlert("Vehicle Sensors Calibrating"), + ET.IMMEDIATE_DISABLE: ImmediateDisableAlert("车辆传感器无效"), + ET.PERMANENT: NormalPermanentAlert("车辆传感器校准中", "行驶即可完成标定"), + ET.NO_ENTRY: NoEntryAlert("车辆传感器校准中"), }, EventName.personalityChanged: { @@ -847,7 +847,7 @@ EVENTS: dict[int, dict[str, Alert | AlertCallbackType]] = { }, EventName.userBookmark: { - ET.PERMANENT: NormalPermanentAlert("Bookmark Saved", duration=1.5), + ET.PERMANENT: NormalPermanentAlert("书签已保存", duration=1.5), }, EventName.audioFeedback: { @@ -860,66 +860,66 @@ if HARDWARE.get_device_type() == 'mici': EVENTS.update({ EventName.driverDistracted1: { ET.PERMANENT: Alert( - "Pay Attention", + "请注意路况", "", AlertStatus.normal, AlertSize.small, Priority.LOW, VisualAlert.none, AudibleAlert.none, 2), }, EventName.driverDistracted2: { ET.PERMANENT: Alert( - "Pay Attention", - "Driver Distracted", + "请注意路况", + "驾驶分心", AlertStatus.userPrompt, AlertSize.mid, Priority.MID, VisualAlert.steerRequired, AudibleAlert.promptDistracted, 1), }, EventName.resumeRequired: { ET.WARNING: Alert( - "Press Resume", + "按 Resume", "", AlertStatus.userPrompt, AlertSize.small, Priority.LOW, VisualAlert.none, AudibleAlert.none, .2), }, EventName.preLaneChangeLeft: { ET.WARNING: Alert( - "Steer Left", - "Confirm Lane Change", + "向左转向", + "确认变道", AlertStatus.normal, AlertSize.mid, Priority.LOW, VisualAlert.none, AudibleAlert.none, .1), }, EventName.preLaneChangeRight: { ET.WARNING: Alert( - "Steer Right", - "Confirm Lane Change", + "向右转向", + "确认变道", AlertStatus.normal, AlertSize.mid, Priority.LOW, VisualAlert.none, AudibleAlert.none, .1), }, EventName.laneChangeBlocked: { ET.WARNING: Alert( - "Car in Blindspot", + "盲区有车辆", "", AlertStatus.userPrompt, AlertSize.small, Priority.LOW, VisualAlert.none, AudibleAlert.prompt, .1), }, EventName.steerSaturated: { ET.WARNING: Alert( - "take control", - "turn exceeds limit", + "请接管", + "转向超过限制", AlertStatus.userPrompt, AlertSize.mid, Priority.LOW, VisualAlert.steerRequired, AudibleAlert.promptRepeat, 2.), }, EventName.calibrationIncomplete: { ET.PERMANENT: calibration_incomplete_alert, - ET.SOFT_DISABLE: soft_disable_alert("Calibration Incomplete"), - ET.NO_ENTRY: NoEntryAlert("Calibrating"), + ET.SOFT_DISABLE: soft_disable_alert("标定未完成"), + ET.NO_ENTRY: NoEntryAlert("标定中"), }, EventName.reverseGear: { ET.PERMANENT: Alert( - "Reverse", + "倒车", "", AlertStatus.normal, AlertSize.full, Priority.LOWEST, VisualAlert.none, AudibleAlert.none, .2, creation_delay=0.5), - ET.USER_DISABLE: ImmediateDisableAlert("Reverse"), - ET.NO_ENTRY: NoEntryAlert("Reverse"), + ET.USER_DISABLE: ImmediateDisableAlert("倒车"), + ET.NO_ENTRY: NoEntryAlert("倒车"), }, }) diff --git a/selfdrive/selfdrived/events.py.bak b/selfdrive/selfdrived/events.py.bak new file mode 100755 index 00000000..c9b28143 --- /dev/null +++ b/selfdrive/selfdrived/events.py.bak @@ -0,0 +1,953 @@ +#!/usr/bin/env python3 +import math +import os + +from cereal import log, car +import cereal.messaging as messaging +from openpilot.common.constants import CV +from openpilot.common.git import get_short_branch +from openpilot.common.realtime import DT_CTRL +from openpilot.selfdrive.locationd.calibrationd import MIN_SPEED_FILTER +from openpilot.system.micd import SAMPLE_RATE, SAMPLE_BUFFER +from openpilot.selfdrive.ui.feedback.feedbackd import FEEDBACK_MAX_DURATION +from openpilot.system.hardware import HARDWARE + +from openpilot.sunnypilot.selfdrive.selfdrived.events_base import EventsBase, Priority, ET, Alert, \ + NoEntryAlert, SoftDisableAlert, UserSoftDisableAlert, ImmediateDisableAlert, EngagementAlert, NormalPermanentAlert, \ + StartupAlert, AlertCallbackType, wrong_car_mode_alert + + +AlertSize = log.SelfdriveState.AlertSize +AlertStatus = log.SelfdriveState.AlertStatus +VisualAlert = car.CarControl.HUDControl.VisualAlert +AudibleAlert = car.CarControl.HUDControl.AudibleAlert +EventName = log.OnroadEvent.EventName + + +# get event name from enum +EVENT_NAME = {v: k for k, v in EventName.schema.enumerants.items()} + + +class Events(EventsBase): + def __init__(self): + super().__init__() + self.event_counters = dict.fromkeys(EVENTS.keys(), 0) + + def get_events_mapping(self) -> dict[int, dict[str, Alert | AlertCallbackType]]: + return EVENTS + + def get_event_name(self, event: int): + return EVENT_NAME[event] + + def get_event_msg_type(self): + return log.OnroadEvent + + + +# ********** 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 ********** + + +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("WARNING: This branch is not tested", 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"Drive above {get_display_speed(CP.minEnableSpeed, metric)} to engage") + + +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"Steer Assist Unavailable Below {get_display_speed(CP.minSteerSpeed, metric)}", + "", + AlertStatus.userPrompt, AlertSize.small, + Priority.LOW, VisualAlert.none, 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 = 'Recalibrating' if sm['liveCalibration'].calStatus == log.LiveCalibrationData.Status.recalibrating else 'Calibrating' + return Alert( + f"{first_word}: {sm['liveCalibration'].calPerc:.0f}%", + f"Drive Above {get_display_speed(MIN_SPEED_FILTER, metric)}", + AlertStatus.normal, AlertSize.mid, + Priority.LOWEST, VisualAlert.none, AudibleAlert.none, .2) + + +def audio_feedback_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.SubMaster, metric: bool, soft_disable_time: int, personality) -> Alert: + duration = FEEDBACK_MAX_DURATION - ((sm['audioFeedback'].blockNum + 1) * SAMPLE_BUFFER / SAMPLE_RATE) + return NormalPermanentAlert( + "Recording Audio Feedback", + f"{round(duration)} second{'s' if round(duration) != 1 else ''} remaining. Press again to save early.", + priority=Priority.LOW) + + +# *** 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("Out of Storage", 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 Speed Invalid") + + +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="Process Not Running") + + +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="Communication Issue Between Processes") + + +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("Camera Malfunction", ', '.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"Remount Device (Pitch: {pitch:.1f}°, Yaw: {yaw:.1f}°)" + return NormalPermanentAlert("Calibration Invalid", angles) + + +def paramsd_invalid_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.SubMaster, metric: bool, soft_disable_time: int, personality) -> Alert: + if not sm['liveParameters'].angleOffsetValid: + angle_offset_deg = sm['liveParameters'].angleOffsetDeg + title = "Steering misalignment detected" + text = f"Angle offset too high (Offset: {angle_offset_deg:.1f}°)" + elif not sm['liveParameters'].steerRatioValid: + steer_ratio = sm['liveParameters'].steerRatio + title = "Steer ratio mismatch" + text = f"Steering rack geometry may be off (Ratio: {steer_ratio:.1f})" + elif not sm['liveParameters'].stiffnessFactorValid: + stiffness_factor = sm['liveParameters'].stiffnessFactor + title = "Abnormal tire stiffness" + text = f"Check tires, pressure, or alignment (Factor: {stiffness_factor:.1f})" + else: + return NoEntryAlert("paramsd Temporary Error") + + return NoEntryAlert(alert_text_1=title, alert_text_2=text) + +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("System Overheated", 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("Low Memory", 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("High CPU Usage", 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("Driving Model Lagging", f"{sm['modelV2'].frameDropPerc:.1f}% frames dropped") + + +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.torque + vals = f"Gas: {round(gb * 100.)}%, Steer: {round(steer * 100.)}%" + return NormalPermanentAlert("Joystick Mode", 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 invalid_lkas_setting_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.SubMaster, metric: bool, soft_disable_time: int, personality) -> Alert: + text = "Toggle stock LKAS on or off to engage" + if CP.brand == "tesla": + text = "Switch to Traffic-Aware Cruise Control to engage" + elif CP.brand == "mazda": + text = "Enable your car's LKAS to engage" + elif CP.brand == "nissan": + text = "Disable your car's stock LKAS to engage" + return NormalPermanentAlert("Invalid LKAS setting", text) + + + +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("Joystick Mode"), + }, + + EventName.longitudinalManeuver: { + ET.WARNING: longitudinal_maneuver_alert, + ET.PERMANENT: NormalPermanentAlert("Longitudinal Maneuver Mode", + "Ensure road ahead is clear"), + }, + + EventName.lateralManeuver: { + ET.WARNING: longitudinal_maneuver_alert, + ET.PERMANENT: NormalPermanentAlert("Lateral Maneuver Mode"), + }, + + EventName.selfdriveInitializing: { + ET.NO_ENTRY: NoEntryAlert("System Initializing"), + }, + + EventName.startup: { + ET.PERMANENT: StartupAlert("Be ready to take over at any time") + }, + + EventName.startupMaster: { + ET.PERMANENT: startup_master_alert, + }, + + EventName.startupNoControl: { + ET.PERMANENT: StartupAlert("Dashcam mode"), + ET.NO_ENTRY: NoEntryAlert("Dashcam mode"), + }, + + EventName.startupNoCar: { + ET.PERMANENT: StartupAlert("Dashcam mode for unsupported car"), + }, + + EventName.startupNoSecOcKey: { + ET.PERMANENT: NormalPermanentAlert("Dashcam Mode", + "Security Key Not Available", + priority=Priority.HIGH), + }, + + EventName.dashcamMode: { + ET.PERMANENT: NormalPermanentAlert("Dashcam Mode", + priority=Priority.LOWEST), + }, + + EventName.invalidLkasSetting: { + ET.PERMANENT: invalid_lkas_setting_alert, + 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("Dashcam Mode", + "Car Unrecognized", + priority=Priority.LOWEST), + }, + + EventName.aeb: { + ET.PERMANENT: Alert( + "BRAKE!", + "Emergency Braking: Risk of Collision", + AlertStatus.critical, AlertSize.full, + Priority.HIGHEST, VisualAlert.fcw, AudibleAlert.none, 2.), + ET.NO_ENTRY: NoEntryAlert("AEB: Risk of Collision"), + }, + + EventName.stockAeb: { + ET.PERMANENT: Alert( + "BRAKE!", + "Stock AEB: Risk of Collision", + AlertStatus.critical, AlertSize.full, + Priority.HIGHEST, VisualAlert.fcw, AudibleAlert.none, 2.), + ET.NO_ENTRY: NoEntryAlert("Stock AEB: Risk of Collision"), + }, + + EventName.stockLkas: { + ET.NO_ENTRY: NoEntryAlert("Stock LKAS: Lane Departure Detected"), + }, + + EventName.fcw: { + ET.PERMANENT: Alert( + "BRAKE!", + "Risk of Collision", + AlertStatus.critical, AlertSize.full, + Priority.HIGHEST, VisualAlert.fcw, AudibleAlert.warningSoft, 2.), + }, + + EventName.ldw: { + ET.PERMANENT: Alert( + "Lane Departure Detected", + "", + AlertStatus.userPrompt, AlertSize.small, + Priority.LOW, VisualAlert.ldw, AudibleAlert.prompt, 3.), + }, + + # ********** events only containing alerts that display while engaged ********** + + EventName.steerTempUnavailableSilent: { + ET.WARNING: Alert( + "Steering Assist Temporarily Unavailable", + "", + AlertStatus.userPrompt, AlertSize.small, + Priority.LOW, VisualAlert.steerRequired, AudibleAlert.prompt, 1.8), + }, + + EventName.driverDistracted1: { + ET.PERMANENT: Alert( + "Pay Attention", + "", + AlertStatus.normal, AlertSize.small, + Priority.LOW, VisualAlert.none, AudibleAlert.none, .1), + }, + + EventName.driverDistracted2: { + ET.PERMANENT: Alert( + "Pay Attention", + "Driver Distracted", + AlertStatus.userPrompt, AlertSize.mid, + Priority.MID, VisualAlert.steerRequired, AudibleAlert.promptDistracted, .1), + }, + + EventName.driverDistracted3: { + ET.PERMANENT: Alert( + "DISENGAGE IMMEDIATELY", + "Driver Distracted", + AlertStatus.critical, AlertSize.full, + Priority.HIGH, VisualAlert.steerRequired, AudibleAlert.warningImmediate, .1), + }, + + EventName.driverUnresponsive1: { + ET.PERMANENT: Alert( + "Touch Steering Wheel: No Face Detected", + "", + AlertStatus.normal, AlertSize.small, + Priority.LOW, VisualAlert.steerRequired, AudibleAlert.none, .1), + }, + + EventName.driverUnresponsive2: { + ET.PERMANENT: Alert( + "Touch Steering Wheel", + "Driver Unresponsive", + AlertStatus.userPrompt, AlertSize.mid, + Priority.MID, VisualAlert.steerRequired, AudibleAlert.promptDistracted, .1), + }, + + EventName.driverUnresponsive3: { + ET.PERMANENT: Alert( + "DISENGAGE IMMEDIATELY", + "Driver Unresponsive", + AlertStatus.critical, AlertSize.full, + Priority.HIGH, VisualAlert.steerRequired, AudibleAlert.warningImmediate, .1), + }, + + EventName.manualRestart: { + ET.WARNING: Alert( + "TAKE CONTROL", + "Resume Driving Manually", + AlertStatus.userPrompt, AlertSize.mid, + Priority.LOW, VisualAlert.none, AudibleAlert.none, .2), + }, + + EventName.resumeRequired: { + ET.WARNING: Alert( + "Press Resume to Exit Standstill", + "", + AlertStatus.userPrompt, AlertSize.small, + Priority.LOW, VisualAlert.none, AudibleAlert.none, .2), + }, + + EventName.belowSteerSpeed: { + ET.WARNING: below_steer_speed_alert, + }, + + EventName.preLaneChangeLeft: { + ET.WARNING: Alert( + "Steer Left to Start Lane Change Once Safe", + "", + AlertStatus.normal, AlertSize.small, + Priority.LOW, VisualAlert.none, AudibleAlert.none, .1), + }, + + EventName.preLaneChangeRight: { + ET.WARNING: Alert( + "Steer Right to Start Lane Change Once Safe", + "", + AlertStatus.normal, AlertSize.small, + Priority.LOW, VisualAlert.none, AudibleAlert.none, .1), + }, + + EventName.laneChangeBlocked: { + ET.WARNING: Alert( + "Car Detected in Blindspot", + "", + AlertStatus.userPrompt, AlertSize.small, + Priority.LOW, VisualAlert.none, AudibleAlert.prompt, .1), + }, + + EventName.laneChange: { + ET.WARNING: Alert( + "Changing Lanes", + "", + AlertStatus.normal, AlertSize.small, + Priority.LOW, VisualAlert.none, AudibleAlert.none, .1), + }, + + EventName.steerSaturated: { + ET.WARNING: Alert( + "Take Control", + "Turn Exceeds Steering Limit", + 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 Malfunction", "Likely Hardware Issue"), + }, + + # Camera is not outputting frames + EventName.cameraMalfunction: { + ET.PERMANENT: camera_malfunction_alert, + ET.SOFT_DISABLE: soft_disable_alert("Camera Malfunction"), + ET.NO_ENTRY: NoEntryAlert("Camera Malfunction: Reboot Your Device"), + }, + # Camera framerate too low + EventName.cameraFrameRate: { + ET.PERMANENT: NormalPermanentAlert("Camera Frame Rate Low", "Reboot your Device"), + ET.SOFT_DISABLE: soft_disable_alert("Camera Frame Rate Low"), + ET.NO_ENTRY: NoEntryAlert("Camera Frame Rate Low: Reboot Your Device"), + }, + + # Unused + + EventName.locationdTemporaryError: { + ET.NO_ENTRY: NoEntryAlert("locationd Temporary Error"), + ET.SOFT_DISABLE: soft_disable_alert("locationd Temporary Error"), + }, + + EventName.locationdPermanentError: { + ET.NO_ENTRY: NoEntryAlert("locationd Permanent Error"), + ET.IMMEDIATE_DISABLE: ImmediateDisableAlert("locationd Permanent Error"), + ET.PERMANENT: NormalPermanentAlert("locationd Permanent Error"), + }, + + # 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: paramsd_invalid_alert, + ET.SOFT_DISABLE: soft_disable_alert("paramsd Temporary Error"), + }, + + EventName.paramsdPermanentError: { + ET.NO_ENTRY: NoEntryAlert("paramsd Permanent Error"), + ET.IMMEDIATE_DISABLE: ImmediateDisableAlert("paramsd Permanent Error"), + ET.PERMANENT: NormalPermanentAlert("paramsd Permanent Error"), + }, + + # ********** 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 Pressed"), + }, + + EventName.brakeHold: { + ET.WARNING: Alert( + "Press Resume to Exit Brake Hold", + "", + AlertStatus.userPrompt, AlertSize.small, + Priority.LOW, VisualAlert.none, AudibleAlert.none, .2), + }, + + EventName.parkBrake: { + ET.USER_DISABLE: EngagementAlert(AudibleAlert.disengage), + ET.NO_ENTRY: NoEntryAlert("Parking Brake Engaged"), + }, + + EventName.pedalPressed: { + ET.USER_DISABLE: EngagementAlert(AudibleAlert.disengage), + ET.NO_ENTRY: NoEntryAlert("Pedal Pressed", + visual_alert=VisualAlert.brakePressed), + }, + + EventName.steerDisengage: { + ET.USER_DISABLE: EngagementAlert(AudibleAlert.disengage), + ET.NO_ENTRY: NoEntryAlert("Steering Pressed"), + }, + + EventName.preEnableStandstill: { + ET.PRE_ENABLE: Alert( + "Release Brake to Engage", + "", + 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("Press Set to Engage"), + }, + + EventName.wrongCruiseMode: { + ET.USER_DISABLE: EngagementAlert(AudibleAlert.disengage), + ET.NO_ENTRY: NoEntryAlert("Adaptive Cruise Disabled"), + }, + + EventName.steerTempUnavailable: { + ET.SOFT_DISABLE: soft_disable_alert("Steering Assist Temporarily Unavailable"), + ET.NO_ENTRY: NoEntryAlert("Steering Temporarily Unavailable"), + }, + + EventName.steerTimeLimit: { + ET.SOFT_DISABLE: soft_disable_alert("Vehicle Steering Time Limit"), + ET.NO_ENTRY: NoEntryAlert("Vehicle Steering Time Limit"), + }, + + EventName.outOfSpace: { + ET.PERMANENT: out_of_space_alert, + ET.NO_ENTRY: NoEntryAlert("Out of Storage"), + }, + + EventName.belowEngageSpeed: { + ET.NO_ENTRY: below_engage_speed_alert, + }, + + EventName.sensorDataInvalid: { + ET.PERMANENT: Alert( + "Sensor Data Invalid", + "Possible Hardware Issue", + AlertStatus.normal, AlertSize.mid, + Priority.LOWER, VisualAlert.none, AudibleAlert.none, .2, creation_delay=1.), + ET.NO_ENTRY: NoEntryAlert("Sensor Data Invalid"), + ET.SOFT_DISABLE: soft_disable_alert("Sensor Data Invalid"), + }, + + EventName.noGps: { + }, + + EventName.tooDistracted: { + ET.NO_ENTRY: NoEntryAlert("Distraction Level Too High"), + }, + + EventName.excessiveActuation: { + ET.SOFT_DISABLE: soft_disable_alert("Excessive Actuation"), + ET.NO_ENTRY: NoEntryAlert("Excessive Actuation"), + }, + + EventName.overheat: { + ET.PERMANENT: overheat_alert, + ET.SOFT_DISABLE: soft_disable_alert("System Overheated"), + ET.NO_ENTRY: NoEntryAlert("System Overheated"), + }, + + EventName.wrongGear: { + ET.SOFT_DISABLE: user_soft_disable_alert("Gear not D"), + ET.NO_ENTRY: NoEntryAlert("Gear not 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("Calibration Invalid: Remount Device & Recalibrate"), + ET.NO_ENTRY: NoEntryAlert("Calibration Invalid: Remount Device & Recalibrate"), + }, + + EventName.calibrationIncomplete: { + ET.PERMANENT: calibration_incomplete_alert, + ET.SOFT_DISABLE: soft_disable_alert("Calibration Incomplete"), + ET.NO_ENTRY: NoEntryAlert("Calibration in Progress"), + }, + + EventName.calibrationRecalibrating: { + ET.PERMANENT: calibration_incomplete_alert, + ET.SOFT_DISABLE: soft_disable_alert("Device Remount Detected: Recalibrating"), + ET.NO_ENTRY: NoEntryAlert("Remount Detected: Recalibrating"), + }, + + EventName.doorOpen: { + ET.SOFT_DISABLE: user_soft_disable_alert("Door Open"), + ET.NO_ENTRY: NoEntryAlert("Door Open"), + }, + + EventName.seatbeltNotLatched: { + ET.SOFT_DISABLE: user_soft_disable_alert("Seatbelt Unlatched"), + ET.NO_ENTRY: NoEntryAlert("Seatbelt Unlatched"), + }, + + EventName.espDisabled: { + ET.SOFT_DISABLE: soft_disable_alert("Electronic Stability Control Disabled"), + ET.NO_ENTRY: NoEntryAlert("Electronic Stability Control Disabled"), + }, + + EventName.lowBattery: { + ET.SOFT_DISABLE: soft_disable_alert("Low Battery"), + ET.NO_ENTRY: NoEntryAlert("Low Battery"), + }, + + # 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("Communication Issue Between Processes"), + ET.NO_ENTRY: comm_issue_alert, + }, + EventName.commIssueAvgFreq: { + ET.SOFT_DISABLE: soft_disable_alert("Low Communication Rate Between Processes"), + ET.NO_ENTRY: NoEntryAlert("Low Communication Rate Between Processes"), + }, + + EventName.selfdrivedLagging: { + ET.SOFT_DISABLE: soft_disable_alert("System Lagging"), + ET.NO_ENTRY: NoEntryAlert("Selfdrive Process Lagging: Reboot Your Device"), + }, + + # 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("Process Not Running"), + }, + + EventName.radarFault: { + ET.SOFT_DISABLE: soft_disable_alert("Radar Error: Restart the Car"), + ET.NO_ENTRY: NoEntryAlert("Radar Error: Restart the Car"), + }, + + EventName.radarTempUnavailable: { + ET.SOFT_DISABLE: soft_disable_alert("Radar Temporarily Unavailable"), + ET.NO_ENTRY: NoEntryAlert("Radar Temporarily Unavailable"), + }, + + # 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("Driving Model Lagging"), + ET.NO_ENTRY: NoEntryAlert("Driving Model Lagging"), + 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 Speed Invalid"), + 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("Device Fell Off Mount"), + ET.NO_ENTRY: NoEntryAlert("Device Fell Off Mount"), + }, + + EventName.lowMemory: { + ET.SOFT_DISABLE: soft_disable_alert("Low Memory: Reboot Your Device"), + ET.PERMANENT: low_memory_alert, + ET.NO_ENTRY: NoEntryAlert("Low Memory: Reboot Your Device"), + }, + + EventName.accFaulted: { + ET.IMMEDIATE_DISABLE: ImmediateDisableAlert("Cruise Fault: Restart the Car"), + ET.PERMANENT: NormalPermanentAlert("Cruise Fault: Restart the car to engage"), + ET.NO_ENTRY: NoEntryAlert("Cruise Fault: Restart the Car"), + }, + + EventName.espActive: { + ET.SOFT_DISABLE: soft_disable_alert("Electronic Stability Control Active"), + ET.NO_ENTRY: NoEntryAlert("Electronic Stability Control Active"), + }, + + EventName.controlsMismatch: { + ET.IMMEDIATE_DISABLE: ImmediateDisableAlert("Controls Mismatch"), + ET.NO_ENTRY: NoEntryAlert("Controls Mismatch"), + }, + + # 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 Error: Reboot Your Device"), + ET.PERMANENT: NormalPermanentAlert("USB Error: Reboot Your Device"), + ET.NO_ENTRY: NoEntryAlert("USB Error: Reboot Your Device"), + }, + + # 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.IMMEDIATE_DISABLE: ImmediateDisableAlert("Unknown Vehicle Variant"), + ET.PERMANENT: Alert( + "Unknown Vehicle Variant", + "", + AlertStatus.normal, AlertSize.small, + Priority.LOW, VisualAlert.none, AudibleAlert.none, 1., creation_delay=1.), + ET.NO_ENTRY: NoEntryAlert("Unknown Vehicle Variant"), + }, + + EventName.canBusMissing: { + ET.IMMEDIATE_DISABLE: ImmediateDisableAlert("CAN Bus Disconnected"), + ET.PERMANENT: Alert( + "CAN Bus Disconnected: Likely Faulty Cable", + "", + AlertStatus.normal, AlertSize.small, + Priority.LOW, VisualAlert.none, AudibleAlert.none, 1., creation_delay=1.), + ET.NO_ENTRY: NoEntryAlert("CAN Bus Disconnected: Check Connections"), + }, + + EventName.steerUnavailable: { + ET.IMMEDIATE_DISABLE: ImmediateDisableAlert("LKAS Fault: Restart the Car"), + ET.PERMANENT: NormalPermanentAlert("LKAS Fault: Restart the car to engage"), + ET.NO_ENTRY: NoEntryAlert("LKAS Fault: Restart the Car"), + }, + + EventName.reverseGear: { + ET.PERMANENT: Alert( + "Reverse\nGear", + "", + AlertStatus.normal, AlertSize.full, + Priority.LOWEST, VisualAlert.none, AudibleAlert.none, .2, creation_delay=0.5), + ET.USER_DISABLE: ImmediateDisableAlert("Reverse Gear"), + ET.NO_ENTRY: NoEntryAlert("Reverse Gear"), + }, + + # 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("Cruise Is Off"), + }, + + # 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("Harness Relay Malfunction"), + ET.PERMANENT: NormalPermanentAlert("Harness Relay Malfunction", "Check Hardware"), + ET.NO_ENTRY: NoEntryAlert("Harness Relay Malfunction"), + }, + + EventName.speedTooLow: { + ET.IMMEDIATE_DISABLE: Alert( + "openpilot Canceled", + "Speed too low", + 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( + "Speed Too High", + "Model uncertain at this speed", + AlertStatus.userPrompt, AlertSize.mid, + Priority.HIGH, VisualAlert.steerRequired, AudibleAlert.promptRepeat, 4.), + ET.NO_ENTRY: NoEntryAlert("Slow down to engage"), + }, + + EventName.vehicleSensorsInvalid: { + ET.IMMEDIATE_DISABLE: ImmediateDisableAlert("Vehicle Sensors Invalid"), + ET.PERMANENT: NormalPermanentAlert("Vehicle Sensors Calibrating", "Drive to Calibrate"), + ET.NO_ENTRY: NoEntryAlert("Vehicle Sensors Calibrating"), + }, + + EventName.personalityChanged: { + ET.WARNING: personality_changed_alert, + }, + + EventName.userBookmark: { + ET.PERMANENT: NormalPermanentAlert("Bookmark Saved", duration=1.5), + }, + + EventName.audioFeedback: { + ET.PERMANENT: audio_feedback_alert, + }, +} + + +if HARDWARE.get_device_type() == 'mici': + EVENTS.update({ + EventName.driverDistracted1: { + ET.PERMANENT: Alert( + "Pay Attention", + "", + AlertStatus.normal, AlertSize.small, + Priority.LOW, VisualAlert.none, AudibleAlert.none, 2), + }, + EventName.driverDistracted2: { + ET.PERMANENT: Alert( + "Pay Attention", + "Driver Distracted", + AlertStatus.userPrompt, AlertSize.mid, + Priority.MID, VisualAlert.steerRequired, AudibleAlert.promptDistracted, 1), + }, + EventName.resumeRequired: { + ET.WARNING: Alert( + "Press Resume", + "", + AlertStatus.userPrompt, AlertSize.small, + Priority.LOW, VisualAlert.none, AudibleAlert.none, .2), + }, + EventName.preLaneChangeLeft: { + ET.WARNING: Alert( + "Steer Left", + "Confirm Lane Change", + AlertStatus.normal, AlertSize.mid, + Priority.LOW, VisualAlert.none, AudibleAlert.none, .1), + }, + EventName.preLaneChangeRight: { + ET.WARNING: Alert( + "Steer Right", + "Confirm Lane Change", + AlertStatus.normal, AlertSize.mid, + Priority.LOW, VisualAlert.none, AudibleAlert.none, .1), + }, + EventName.laneChangeBlocked: { + ET.WARNING: Alert( + "Car in Blindspot", + "", + AlertStatus.userPrompt, AlertSize.small, + Priority.LOW, VisualAlert.none, AudibleAlert.prompt, .1), + }, + EventName.steerSaturated: { + ET.WARNING: Alert( + "take control", + "turn exceeds limit", + AlertStatus.userPrompt, AlertSize.mid, + Priority.LOW, VisualAlert.steerRequired, AudibleAlert.promptRepeat, 2.), + }, + EventName.calibrationIncomplete: { + ET.PERMANENT: calibration_incomplete_alert, + ET.SOFT_DISABLE: soft_disable_alert("Calibration Incomplete"), + ET.NO_ENTRY: NoEntryAlert("Calibrating"), + }, + EventName.reverseGear: { + ET.PERMANENT: Alert( + "Reverse", + "", + AlertStatus.normal, AlertSize.full, + Priority.LOWEST, VisualAlert.none, AudibleAlert.none, .2, creation_delay=0.5), + ET.USER_DISABLE: ImmediateDisableAlert("Reverse"), + ET.NO_ENTRY: NoEntryAlert("Reverse"), + }, + }) + + +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 not isinstance(alert, 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") diff --git a/selfdrive/ui/layouts/settings/settings.py b/selfdrive/ui/layouts/settings/settings.py index 68f45df7..e2a12f5e 100644 --- a/selfdrive/ui/layouts/settings/settings.py +++ b/selfdrive/ui/layouts/settings/settings.py @@ -60,7 +60,7 @@ class SettingsLayout(Widget): PanelType.NETWORK: PanelInfo(tr_noop("Network"), NetworkUI(wifi_manager)), PanelType.TOGGLES: PanelInfo(tr_noop("Toggles"), TogglesLayout()), PanelType.SOFTWARE: PanelInfo(tr_noop("Software"), SoftwareLayout()), - PanelType.FIREHOSE: PanelInfo(tr_noop("Firehose"), FirehoseLayout()), + # PanelType.FIREHOSE: PanelInfo(tr_noop("Firehose"), FirehoseLayout()), PanelType.DEVELOPER: PanelInfo(tr_noop("Developer"), DeveloperLayout()), } diff --git a/sunnypilot/selfdrive/selfdrived/events.py b/sunnypilot/selfdrive/selfdrived/events.py index b1343b2a..44abf41e 100644 --- a/sunnypilot/selfdrive/selfdrived/events.py +++ b/sunnypilot/selfdrive/selfdrived/events.py @@ -55,13 +55,13 @@ def speed_limit_pre_active_alert(CP: car.CarParams, CS: car.CarState, sm: messag pcm_long_required_max_set_speed_conv = round(pcm_long_required_max * speed_conv) speed_unit = "km/h" if metric else "mph" - alert_1_str = f"Speed Limit Assist: set to {pcm_long_required_max_set_speed_conv} {speed_unit} to engage" + alert_1_str = f"限速辅助:设定至 {pcm_long_required_max_set_speed_conv} {speed_unit} 即可开启" else: if IS_MICI: if set_speed_conv < speed_limit_final_last_conv: - alert_1_str = "Press + to confirm speed limit" + alert_1_str = "按 + 确认限速" elif set_speed_conv > speed_limit_final_last_conv: - alert_1_str = "Press - to confirm speed limit" + alert_1_str = "按 - 确认限速" else: alert_size = AlertSize.none @@ -99,16 +99,16 @@ EVENTS_SP: dict[int, dict[str, Alert | AlertCallbackType]] = { EventNameSP.manualSteeringRequired: { ET.USER_DISABLE: Alert( - "Automatic Lane Centering is OFF", - "Manual Steering Required", + "自动车道居中已关闭", + "需要手动转向", AlertStatus.normal, AlertSize.mid, Priority.LOW, VisualAlert.none, AudibleAlert.disengage, 1.), }, EventNameSP.manualLongitudinalRequired: { ET.WARNING: Alert( - "Smart/Adaptive Cruise Control: OFF", - "Manual Speed Control Required", + "智能/自适应巡航已关闭", + "需要手动控制速度", AlertStatus.normal, AlertSize.mid, Priority.LOW, VisualAlert.none, AudibleAlert.none, 1.), }, @@ -123,7 +123,7 @@ EVENTS_SP: dict[int, dict[str, Alert | AlertCallbackType]] = { EventNameSP.silentBrakeHold: { ET.WARNING: EngagementAlert(AudibleAlert.none), - ET.NO_ENTRY: NoEntryAlert("Brake Hold Active"), + ET.NO_ENTRY: NoEntryAlert("刹车保持已激活"), }, EventNameSP.silentWrongGear: { @@ -133,19 +133,19 @@ EVENTS_SP: dict[int, dict[str, Alert | AlertCallbackType]] = { AlertStatus.normal, AlertSize.none, Priority.LOWEST, VisualAlert.none, AudibleAlert.none, 0.), ET.NO_ENTRY: Alert( - "Gear not D", - "openpilot Unavailable", + "档位不在D档", + "openpilot 不可用", AlertStatus.normal, AlertSize.mid, Priority.LOW, VisualAlert.none, AudibleAlert.none, 0.), }, EventNameSP.silentReverseGear: { ET.PERMANENT: Alert( - "Reverse\nGear", + "倒车\n档位", "", AlertStatus.normal, AlertSize.full, Priority.LOWEST, VisualAlert.none, AudibleAlert.none, .2, creation_delay=0.5), - ET.NO_ENTRY: NoEntryAlert("Reverse Gear"), + ET.NO_ENTRY: NoEntryAlert("倒车档位"), }, EventNameSP.silentDoorOpen: { @@ -154,7 +154,7 @@ EVENTS_SP: dict[int, dict[str, Alert | AlertCallbackType]] = { "", AlertStatus.normal, AlertSize.none, Priority.LOWEST, VisualAlert.none, AudibleAlert.none, 0.), - ET.NO_ENTRY: NoEntryAlert("Door Open"), + ET.NO_ENTRY: NoEntryAlert("车门未关"), }, EventNameSP.silentSeatbeltNotLatched: { @@ -163,7 +163,7 @@ EVENTS_SP: dict[int, dict[str, Alert | AlertCallbackType]] = { "", AlertStatus.normal, AlertSize.none, Priority.LOWEST, VisualAlert.none, AudibleAlert.none, 0.), - ET.NO_ENTRY: NoEntryAlert("Seatbelt Unlatched"), + ET.NO_ENTRY: NoEntryAlert("安全带未系"), }, EventNameSP.silentParkBrake: { @@ -172,16 +172,16 @@ EVENTS_SP: dict[int, dict[str, Alert | AlertCallbackType]] = { "", AlertStatus.normal, AlertSize.none, Priority.LOWEST, VisualAlert.none, AudibleAlert.none, 0.), - ET.NO_ENTRY: NoEntryAlert("Parking Brake Engaged"), + ET.NO_ENTRY: NoEntryAlert("手刹已拉起"), }, EventNameSP.controlsMismatchLateral: { - ET.IMMEDIATE_DISABLE: ImmediateDisableAlert("Controls Mismatch: Lateral"), - ET.NO_ENTRY: NoEntryAlert("Controls Mismatch: Lateral"), + ET.IMMEDIATE_DISABLE: ImmediateDisableAlert("控制不匹配:横向"), + ET.NO_ENTRY: NoEntryAlert("控制不匹配:横向"), }, EventNameSP.experimentalModeSwitched: { - ET.WARNING: NormalPermanentAlert("Experimental Mode Switched", duration=1.5) + ET.WARNING: NormalPermanentAlert("实验模式已切换", duration=1.5) }, EventNameSP.wrongCarModeAlertOnly: { @@ -189,12 +189,12 @@ EVENTS_SP: dict[int, dict[str, Alert | AlertCallbackType]] = { }, EventNameSP.pedalPressedAlertOnly: { - ET.WARNING: NoEntryAlert("Pedal Pressed") + ET.WARNING: NoEntryAlert("已踩下踏板") }, EventNameSP.laneTurnLeft: { ET.WARNING: Alert( - "Turning Left", + "正在左转", "", AlertStatus.normal, AlertSize.small, Priority.LOW, VisualAlert.none, AudibleAlert.none, 1.), @@ -202,7 +202,7 @@ EVENTS_SP: dict[int, dict[str, Alert | AlertCallbackType]] = { EventNameSP.laneTurnRight: { ET.WARNING: Alert( - "Turning Right", + "正在右转", "", AlertStatus.normal, AlertSize.small, Priority.LOW, VisualAlert.none, AudibleAlert.none, 1.), @@ -210,7 +210,7 @@ EVENTS_SP: dict[int, dict[str, Alert | AlertCallbackType]] = { EventNameSP.speedLimitActive: { ET.WARNING: Alert( - "Auto adjusting to speed limit", + "自动调整至限速", "", AlertStatus.normal, AlertSize.small, Priority.LOW, VisualAlert.none, AudibleAlertSP.promptSingleHigh, 5.), @@ -218,7 +218,7 @@ EVENTS_SP: dict[int, dict[str, Alert | AlertCallbackType]] = { EventNameSP.speedLimitChanged: { ET.WARNING: Alert( - "Set speed changed", + "设定速度已变更", "", AlertStatus.normal, AlertSize.small, Priority.LOW, VisualAlert.none, AudibleAlertSP.promptSingleHigh, 5.), @@ -230,7 +230,7 @@ EVENTS_SP: dict[int, dict[str, Alert | AlertCallbackType]] = { EventNameSP.speedLimitPending: { ET.WARNING: Alert( - "Auto adjusting to last speed limit", + "自动调整至上一限速", "", AlertStatus.normal, AlertSize.small, Priority.LOW, VisualAlert.none, AudibleAlertSP.promptSingleHigh, 5.),