parent
							
								
									05a09435b0
								
							
						
					
					
						commit
						48340cc8cb
					
				
				 24 changed files with 987 additions and 1171 deletions
			
			
		| @ -1 +1 @@ | ||||
| Subproject commit 4f68db8f6aa31e87d968da882460e196c6b101a3 | ||||
| Subproject commit 856c9812d552fe0ac640b75074b080f76c9a3cba | ||||
| @ -1,825 +0,0 @@ | ||||
| from cereal import car, log | ||||
| 
 | ||||
| # Priority | ||||
| class Priority: | ||||
|   LOWEST = 0 | ||||
|   LOWER = 1 | ||||
|   LOW = 2 | ||||
|   MID = 3 | ||||
|   HIGH = 4 | ||||
|   HIGHEST = 5 | ||||
| 
 | ||||
| AlertSize = log.ControlsState.AlertSize | ||||
| AlertStatus = log.ControlsState.AlertStatus | ||||
| AudibleAlert = car.CarControl.HUDControl.AudibleAlert | ||||
| VisualAlert = car.CarControl.HUDControl.VisualAlert | ||||
| 
 | ||||
| class Alert(): | ||||
|   def __init__(self, | ||||
|                alert_type, | ||||
|                alert_text_1, | ||||
|                alert_text_2, | ||||
|                alert_status, | ||||
|                alert_size, | ||||
|                alert_priority, | ||||
|                visual_alert, | ||||
|                audible_alert, | ||||
|                duration_sound, | ||||
|                duration_hud_alert, | ||||
|                duration_text, | ||||
|                alert_rate=0.): | ||||
| 
 | ||||
|     self.alert_type = alert_type | ||||
|     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.alert_priority = alert_priority | ||||
|     self.visual_alert = visual_alert | ||||
|     self.audible_alert = audible_alert | ||||
| 
 | ||||
|     self.duration_sound = duration_sound | ||||
|     self.duration_hud_alert = duration_hud_alert | ||||
|     self.duration_text = duration_text | ||||
| 
 | ||||
|     self.start_time = 0. | ||||
|     self.alert_rate = alert_rate | ||||
| 
 | ||||
|     # typecheck that enums are valid on startup | ||||
|     tst = car.CarControl.new_message() | ||||
|     tst.hudControl.visualAlert = self.visual_alert | ||||
| 
 | ||||
|   def __str__(self): | ||||
|     return self.alert_text_1 + "/" + self.alert_text_2 + " " + str(self.alert_priority) + "  " + str( | ||||
|       self.visual_alert) + " " + str(self.audible_alert) | ||||
| 
 | ||||
|   def __gt__(self, alert2): | ||||
|     return self.alert_priority > alert2.alert_priority | ||||
| 
 | ||||
| 
 | ||||
| ALERTS = [ | ||||
|   # Miscellaneous alerts | ||||
|   Alert( | ||||
|       "enable", | ||||
|       "", | ||||
|       "", | ||||
|       AlertStatus.normal, AlertSize.none, | ||||
|       Priority.MID, VisualAlert.none, AudibleAlert.chimeEngage, .2, 0., 0.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "disable", | ||||
|       "", | ||||
|       "", | ||||
|       AlertStatus.normal, AlertSize.none, | ||||
|       Priority.MID, VisualAlert.none, AudibleAlert.chimeDisengage, .2, 0., 0.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "fcw", | ||||
|       "BRAKE!", | ||||
|       "Risk of Collision", | ||||
|       AlertStatus.critical, AlertSize.full, | ||||
|       Priority.HIGHEST, VisualAlert.fcw, AudibleAlert.chimeWarningRepeat, 1., 2., 2.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "fcwStock", | ||||
|       "BRAKE!", | ||||
|       "Risk of Collision", | ||||
|       AlertStatus.critical, AlertSize.full, | ||||
|       Priority.HIGHEST, VisualAlert.fcw, AudibleAlert.none, 1., 2., 2.),  # no EON chime for stock FCW | ||||
| 
 | ||||
|   Alert( | ||||
|       "steerSaturated", | ||||
|       "TAKE CONTROL", | ||||
|       "Turn Exceeds Steering Limit", | ||||
|       AlertStatus.userPrompt, AlertSize.mid, | ||||
|       Priority.LOW, VisualAlert.steerRequired, AudibleAlert.chimePrompt, 1., 2., 3.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "steerTempUnavailable", | ||||
|       "TAKE CONTROL", | ||||
|       "Steering Temporarily Unavailable", | ||||
|       AlertStatus.userPrompt, AlertSize.mid, | ||||
|       Priority.LOW, VisualAlert.steerRequired, AudibleAlert.chimeWarning1, .4, 2., 3.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "steerTempUnavailableMute", | ||||
|       "TAKE CONTROL", | ||||
|       "Steering Temporarily Unavailable", | ||||
|       AlertStatus.userPrompt, AlertSize.mid, | ||||
|       Priority.LOW, VisualAlert.none, AudibleAlert.none, .2, .2, .2), | ||||
| 
 | ||||
|   Alert( | ||||
|       "preDriverDistracted", | ||||
|       "KEEP EYES ON ROAD: Driver Distracted", | ||||
|       "", | ||||
|       AlertStatus.normal, AlertSize.small, | ||||
|       Priority.LOW, VisualAlert.steerRequired, AudibleAlert.none, .0, .1, .1, alert_rate=0.75), | ||||
| 
 | ||||
|   Alert( | ||||
|       "promptDriverDistracted", | ||||
|       "KEEP EYES ON ROAD", | ||||
|       "Driver Appears Distracted", | ||||
|       AlertStatus.userPrompt, AlertSize.mid, | ||||
|       Priority.MID, VisualAlert.steerRequired, AudibleAlert.chimeWarning2Repeat, .1, .1, .1), | ||||
| 
 | ||||
|   Alert( | ||||
|       "driverDistracted", | ||||
|       "DISENGAGE IMMEDIATELY", | ||||
|       "Driver Was Distracted", | ||||
|       AlertStatus.critical, AlertSize.full, | ||||
|       Priority.HIGH, VisualAlert.steerRequired, AudibleAlert.chimeWarningRepeat, .1, .1, .1), | ||||
| 
 | ||||
|   Alert( | ||||
|       "preDriverUnresponsive", | ||||
|       "TOUCH STEERING WHEEL: No Face Detected", | ||||
|       "", | ||||
|       AlertStatus.normal, AlertSize.small, | ||||
|       Priority.LOW, VisualAlert.steerRequired, AudibleAlert.none, .0, .1, .1, alert_rate=0.75), | ||||
| 
 | ||||
|   Alert( | ||||
|       "promptDriverUnresponsive", | ||||
|       "TOUCH STEERING WHEEL", | ||||
|       "Driver Is Unresponsive", | ||||
|       AlertStatus.userPrompt, AlertSize.mid, | ||||
|       Priority.MID, VisualAlert.steerRequired, AudibleAlert.chimeWarning2Repeat, .1, .1, .1), | ||||
| 
 | ||||
|   Alert( | ||||
|       "driverUnresponsive", | ||||
|       "DISENGAGE IMMEDIATELY", | ||||
|       "Driver Was Unresponsive", | ||||
|       AlertStatus.critical, AlertSize.full, | ||||
|       Priority.HIGH, VisualAlert.steerRequired, AudibleAlert.chimeWarningRepeat, .1, .1, .1), | ||||
| 
 | ||||
|   Alert( | ||||
|       "driverMonitorLowAcc", | ||||
|       "CHECK DRIVER FACE VISIBILITY", | ||||
|       "Driver Monitor Model Output Uncertain", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOW, VisualAlert.steerRequired, AudibleAlert.none, .4, 0., 1.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "geofence", | ||||
|       "DISENGAGEMENT REQUIRED", | ||||
|       "Not in Geofenced Area", | ||||
|       AlertStatus.userPrompt, AlertSize.mid, | ||||
|       Priority.HIGH, VisualAlert.steerRequired, AudibleAlert.chimeWarningRepeat, .1, .1, .1), | ||||
| 
 | ||||
|   Alert( | ||||
|       "startup", | ||||
|       "Be ready to take over at any time", | ||||
|       "Always keep hands on wheel and eyes on road", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOWER, VisualAlert.none, AudibleAlert.none, 0., 0., 15.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "startupMaster", | ||||
|       "WARNING: This branch is not tested", | ||||
|       "Always keep hands on wheel and eyes on road", | ||||
|       AlertStatus.userPrompt, AlertSize.mid, | ||||
|       Priority.LOWER, VisualAlert.none, AudibleAlert.none, 0., 0., 15.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "startupNoControl", | ||||
|       "Dashcam mode", | ||||
|       "Always keep hands on wheel and eyes on road", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOWER, VisualAlert.none, AudibleAlert.none, 0., 0., 15.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "startupNoCar", | ||||
|       "Dashcam mode for unsupported car", | ||||
|       "Always keep hands on wheel and eyes on road", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOWER, VisualAlert.none, AudibleAlert.none, 0., 0., 15.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "ethicalDilemma", | ||||
|       "TAKE CONTROL IMMEDIATELY", | ||||
|       "Ethical Dilemma Detected", | ||||
|       AlertStatus.critical, AlertSize.full, | ||||
|       Priority.HIGHEST, VisualAlert.steerRequired, AudibleAlert.chimeWarningRepeat, 1., 3., 3.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "steerTempUnavailableNoEntry", | ||||
|       "openpilot Unavailable", | ||||
|       "Steering Temporarily Unavailable", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOW, VisualAlert.none, AudibleAlert.chimeError, .4, 0., 3.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "manualRestart", | ||||
|       "TAKE CONTROL", | ||||
|       "Resume Driving Manually", | ||||
|       AlertStatus.userPrompt, AlertSize.mid, | ||||
|       Priority.LOW, VisualAlert.none, AudibleAlert.none, 0., 0., .2), | ||||
| 
 | ||||
|   Alert( | ||||
|       "resumeRequired", | ||||
|       "STOPPED", | ||||
|       "Press Resume to Move", | ||||
|       AlertStatus.userPrompt, AlertSize.mid, | ||||
|       Priority.LOW, VisualAlert.none, AudibleAlert.none, 0., 0., .2), | ||||
| 
 | ||||
|   Alert( | ||||
|       "belowSteerSpeed", | ||||
|       "TAKE CONTROL", | ||||
|       "Steer Unavailable Below ", | ||||
|       AlertStatus.userPrompt, AlertSize.mid, | ||||
|       Priority.MID, VisualAlert.steerRequired, AudibleAlert.none, 0., 0.4, .3), | ||||
| 
 | ||||
|   Alert( | ||||
|       "debugAlert", | ||||
|       "DEBUG ALERT", | ||||
|       "", | ||||
|       AlertStatus.userPrompt, AlertSize.mid, | ||||
|       Priority.LOW, VisualAlert.none, AudibleAlert.none, .1, .1, .1), | ||||
|   Alert( | ||||
|       "preLaneChangeLeft", | ||||
|       "Steer Left to Start Lane Change", | ||||
|       "Monitor Other Vehicles", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOW, VisualAlert.steerRequired, AudibleAlert.none, .0, .1, .1, alert_rate=0.75), | ||||
| 
 | ||||
|   Alert( | ||||
|       "preLaneChangeRight", | ||||
|       "Steer Right to Start Lane Change", | ||||
|       "Monitor Other Vehicles", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOW, VisualAlert.steerRequired, AudibleAlert.none, .0, .1, .1, alert_rate=0.75), | ||||
| 
 | ||||
|   Alert( | ||||
|       "laneChange", | ||||
|       "Changing Lane", | ||||
|       "Monitor Other Vehicles", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOW, VisualAlert.steerRequired, AudibleAlert.none, .0, .1, .1), | ||||
| 
 | ||||
|   Alert( | ||||
|       "posenetInvalid", | ||||
|       "TAKE CONTROL", | ||||
|       "Vision Model Output Uncertain", | ||||
|       AlertStatus.userPrompt, AlertSize.mid, | ||||
|       Priority.LOW, VisualAlert.steerRequired, AudibleAlert.chimeWarning1, .4, 2., 3.), | ||||
| 
 | ||||
|   # Non-entry only alerts | ||||
|   Alert( | ||||
|       "wrongCarModeNoEntry", | ||||
|       "openpilot Unavailable", | ||||
|       "Main Switch Off", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOW, VisualAlert.none, AudibleAlert.chimeError, .4, 0., 3.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "dataNeededNoEntry", | ||||
|       "openpilot Unavailable", | ||||
|       "Calibration Needs Data. Upload Drive, Try Again", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOW, VisualAlert.none, AudibleAlert.chimeError, .4, 0., 3.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "outOfSpaceNoEntry", | ||||
|       "openpilot Unavailable", | ||||
|       "Out of Storage Space", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOW, VisualAlert.none, AudibleAlert.chimeError, .4, 0., 3.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "pedalPressedNoEntry", | ||||
|       "openpilot Unavailable", | ||||
|       "Pedal Pressed During Attempt", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOW, "brakePressed", AudibleAlert.chimeError, .4, 2., 3.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "speedTooLowNoEntry", | ||||
|       "openpilot Unavailable", | ||||
|       "Speed Too Low", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOW, VisualAlert.none, AudibleAlert.chimeError, .4, 2., 3.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "brakeHoldNoEntry", | ||||
|       "openpilot Unavailable", | ||||
|       "Brake Hold Active", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOW, VisualAlert.none, AudibleAlert.chimeError, .4, 2., 3.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "parkBrakeNoEntry", | ||||
|       "openpilot Unavailable", | ||||
|       "Park Brake Engaged", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOW, VisualAlert.none, AudibleAlert.chimeError, .4, 2., 3.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "lowSpeedLockoutNoEntry", | ||||
|       "openpilot Unavailable", | ||||
|       "Cruise Fault: Restart the Car", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOW, VisualAlert.none, AudibleAlert.chimeError, .4, 2., 3.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "lowBatteryNoEntry", | ||||
|       "openpilot Unavailable", | ||||
|       "Low Battery", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOW, VisualAlert.none, AudibleAlert.chimeError, .4, 2., 3.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "sensorDataInvalidNoEntry", | ||||
|       "openpilot Unavailable", | ||||
|       "No Data from Device Sensors", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOW, VisualAlert.none, AudibleAlert.chimeError, .4, 2., 3.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "soundsUnavailableNoEntry", | ||||
|       "openpilot Unavailable", | ||||
|       "Speaker not found", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOW, VisualAlert.none, AudibleAlert.chimeError, .4, 2., 3.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "tooDistractedNoEntry", | ||||
|       "openpilot Unavailable", | ||||
|       "Distraction Level Too High", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOW, VisualAlert.none, AudibleAlert.chimeError, .4, 2., 3.), | ||||
| 
 | ||||
|   # Cancellation alerts causing soft disabling | ||||
|   Alert( | ||||
|       "overheat", | ||||
|       "TAKE CONTROL IMMEDIATELY", | ||||
|       "System Overheated", | ||||
|       AlertStatus.critical, AlertSize.full, | ||||
|       Priority.MID, VisualAlert.steerRequired, AudibleAlert.chimeWarningRepeat, .1, 2., 2.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "wrongGear", | ||||
|       "TAKE CONTROL IMMEDIATELY", | ||||
|       "Gear not D", | ||||
|       AlertStatus.critical, AlertSize.full, | ||||
|       Priority.MID, VisualAlert.steerRequired, AudibleAlert.chimeWarningRepeat, .1, 2., 2.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "calibrationInvalid", | ||||
|       "TAKE CONTROL IMMEDIATELY", | ||||
|       "Calibration Invalid: Reposition Device and Recalibrate", | ||||
|       AlertStatus.critical, AlertSize.full, | ||||
|       Priority.MID, VisualAlert.steerRequired, AudibleAlert.chimeWarningRepeat, .1, 2., 2.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "calibrationIncomplete", | ||||
|       "TAKE CONTROL IMMEDIATELY", | ||||
|       "Calibration in Progress", | ||||
|       AlertStatus.critical, AlertSize.full, | ||||
|       Priority.MID, VisualAlert.steerRequired, AudibleAlert.chimeWarningRepeat, .1, 2., 2.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "doorOpen", | ||||
|       "TAKE CONTROL IMMEDIATELY", | ||||
|       "Door Open", | ||||
|       AlertStatus.critical, AlertSize.full, | ||||
|       Priority.MID, VisualAlert.steerRequired, AudibleAlert.chimeWarningRepeat, .1, 2., 2.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "seatbeltNotLatched", | ||||
|       "TAKE CONTROL IMMEDIATELY", | ||||
|       "Seatbelt Unlatched", | ||||
|       AlertStatus.critical, AlertSize.full, | ||||
|       Priority.MID, VisualAlert.steerRequired, AudibleAlert.chimeWarningRepeat, .1, 2., 2.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "espDisabled", | ||||
|       "TAKE CONTROL IMMEDIATELY", | ||||
|       "ESP Off", | ||||
|       AlertStatus.critical, AlertSize.full, | ||||
|       Priority.MID, VisualAlert.steerRequired, AudibleAlert.chimeWarningRepeat, .1, 2., 2.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "lowBattery", | ||||
|       "TAKE CONTROL IMMEDIATELY", | ||||
|       "Low Battery", | ||||
|       AlertStatus.critical, AlertSize.full, | ||||
|       Priority.MID, VisualAlert.steerRequired, AudibleAlert.chimeWarningRepeat, .1, 2., 2.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "commIssue", | ||||
|       "TAKE CONTROL IMMEDIATELY", | ||||
|       "Communication Issue between Processes", | ||||
|       AlertStatus.critical, AlertSize.full, | ||||
|       Priority.MID, VisualAlert.steerRequired, AudibleAlert.chimeWarningRepeat, .1, 2., 2.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "radarCommIssue", | ||||
|       "TAKE CONTROL IMMEDIATELY", | ||||
|       "Radar Communication Issue", | ||||
|       AlertStatus.critical, AlertSize.full, | ||||
|       Priority.MID, VisualAlert.steerRequired, AudibleAlert.chimeWarningRepeat, .1, 2., 2.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "radarCanError", | ||||
|       "TAKE CONTROL IMMEDIATELY", | ||||
|       "Radar Error: Restart the Car", | ||||
|       AlertStatus.critical, AlertSize.full, | ||||
|       Priority.MID, VisualAlert.steerRequired, AudibleAlert.chimeWarningRepeat, .1, 2., 2.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "radarFault", | ||||
|       "TAKE CONTROL IMMEDIATELY", | ||||
|       "Radar Error: Restart the Car", | ||||
|       AlertStatus.critical, AlertSize.full, | ||||
|       Priority.MID, VisualAlert.steerRequired, AudibleAlert.chimeWarningRepeat, .1, 2., 2.), | ||||
| 
 | ||||
| 
 | ||||
|   Alert( | ||||
|       "lowMemory", | ||||
|       "TAKE CONTROL IMMEDIATELY", | ||||
|       "Low Memory: Reboot Your Device", | ||||
|       AlertStatus.critical, AlertSize.full, | ||||
|       Priority.MID, VisualAlert.steerRequired, AudibleAlert.chimeWarningRepeat, .1, 2., 2.), | ||||
| 
 | ||||
|   # Cancellation alerts causing immediate disabling | ||||
|   Alert( | ||||
|       "controlsFailed", | ||||
|       "TAKE CONTROL IMMEDIATELY", | ||||
|       "Controls Failed", | ||||
|       AlertStatus.critical, AlertSize.full, | ||||
|       Priority.HIGHEST, VisualAlert.steerRequired, AudibleAlert.chimeWarningRepeat, 2.2, 3., 4.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "controlsMismatch", | ||||
|       "TAKE CONTROL IMMEDIATELY", | ||||
|       "Controls Mismatch", | ||||
|       AlertStatus.critical, AlertSize.full, | ||||
|       Priority.HIGHEST, VisualAlert.steerRequired, AudibleAlert.chimeWarningRepeat, 2.2, 3., 4.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "canError", | ||||
|       "TAKE CONTROL IMMEDIATELY", | ||||
|       "CAN Error: Check Connections", | ||||
|       AlertStatus.critical, AlertSize.full, | ||||
|       Priority.HIGHEST, VisualAlert.steerRequired, AudibleAlert.chimeWarningRepeat, 2.2, 3., 4.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "steerUnavailable", | ||||
|       "TAKE CONTROL IMMEDIATELY", | ||||
|       "LKAS Fault: Restart the Car", | ||||
|       AlertStatus.critical, AlertSize.full, | ||||
|       Priority.HIGHEST, VisualAlert.steerRequired, AudibleAlert.chimeWarningRepeat, 2.2, 3., 4.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "brakeUnavailable", | ||||
|       "TAKE CONTROL IMMEDIATELY", | ||||
|       "Cruise Fault: Restart the Car", | ||||
|       AlertStatus.critical, AlertSize.full, | ||||
|       Priority.HIGHEST, VisualAlert.steerRequired, AudibleAlert.chimeWarningRepeat, 2.2, 3., 4.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "gasUnavailable", | ||||
|       "TAKE CONTROL IMMEDIATELY", | ||||
|       "Gas Fault: Restart the Car", | ||||
|       AlertStatus.critical, AlertSize.full, | ||||
|       Priority.HIGHEST, VisualAlert.steerRequired, AudibleAlert.chimeWarningRepeat, 2.2, 3., 4.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "reverseGear", | ||||
|       "TAKE CONTROL IMMEDIATELY", | ||||
|       "Reverse Gear", | ||||
|       AlertStatus.critical, AlertSize.full, | ||||
|       Priority.HIGHEST, VisualAlert.steerRequired, AudibleAlert.chimeWarningRepeat, 2.2, 3., 4.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "cruiseDisabled", | ||||
|       "TAKE CONTROL IMMEDIATELY", | ||||
|       "Cruise Is Off", | ||||
|       AlertStatus.critical, AlertSize.full, | ||||
|       Priority.HIGHEST, VisualAlert.steerRequired, AudibleAlert.chimeWarningRepeat, 2.2, 3., 4.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "plannerError", | ||||
|       "TAKE CONTROL IMMEDIATELY", | ||||
|       "Planner Solution Error", | ||||
|       AlertStatus.critical, AlertSize.full, | ||||
|       Priority.HIGHEST, VisualAlert.steerRequired, AudibleAlert.chimeWarningRepeat, 2.2, 3., 4.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "relayMalfunction", | ||||
|       "TAKE CONTROL IMMEDIATELY", | ||||
|       "Harness Malfunction", | ||||
|       AlertStatus.critical, AlertSize.full, | ||||
|       Priority.HIGHEST, VisualAlert.steerRequired, AudibleAlert.chimeWarningRepeat, 2.2, 3., 4.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "speedTooHigh", | ||||
|       "Speed Too High", | ||||
|       "Slow down to resume operation", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.HIGH, VisualAlert.steerRequired, AudibleAlert.chimeWarning2Repeat, 2.2, 3., 4.), | ||||
| 
 | ||||
| 
 | ||||
|   # not loud cancellations (user is in control) | ||||
|   Alert( | ||||
|       "noTarget", | ||||
|       "openpilot Canceled", | ||||
|       "No close lead car", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.HIGH, VisualAlert.none, AudibleAlert.chimeDisengage, .4, 2., 3.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "speedTooLow", | ||||
|       "openpilot Canceled", | ||||
|       "Speed too low", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.HIGH, VisualAlert.none, AudibleAlert.chimeDisengage, .4, 2., 3.), | ||||
| 
 | ||||
| 
 | ||||
|   # Cancellation alerts causing non-entry | ||||
|   Alert( | ||||
|       "overheatNoEntry", | ||||
|       "openpilot Unavailable", | ||||
|       "System overheated", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOW, VisualAlert.none, AudibleAlert.chimeError, .4, 2., 3.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "wrongGearNoEntry", | ||||
|       "openpilot Unavailable", | ||||
|       "Gear not D", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOW, VisualAlert.none, AudibleAlert.chimeError, .4, 2., 3.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "calibrationInvalidNoEntry", | ||||
|       "openpilot Unavailable", | ||||
|       "Calibration Invalid: Reposition Device & Recalibrate", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOW, VisualAlert.none, AudibleAlert.chimeError, .4, 2., 3.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "calibrationIncompleteNoEntry", | ||||
|       "openpilot Unavailable", | ||||
|       "Calibration in Progress", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOW, VisualAlert.none, AudibleAlert.chimeError, .4, 2., 3.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "doorOpenNoEntry", | ||||
|       "openpilot Unavailable", | ||||
|       "Door open", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOW, VisualAlert.none, AudibleAlert.chimeError, .4, 2., 3.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "seatbeltNotLatchedNoEntry", | ||||
|       "openpilot Unavailable", | ||||
|       "Seatbelt unlatched", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOW, VisualAlert.none, AudibleAlert.chimeError, .4, 2., 3.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "espDisabledNoEntry", | ||||
|       "openpilot Unavailable", | ||||
|       "ESP Off", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOW, VisualAlert.none, AudibleAlert.chimeError, .4, 2., 3.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "geofenceNoEntry", | ||||
|       "openpilot Unavailable", | ||||
|       "Not in Geofenced Area", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.MID, VisualAlert.none, AudibleAlert.chimeError, .4, 2., 3.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "radarCanErrorNoEntry", | ||||
|       "openpilot Unavailable", | ||||
|       "Radar Error: Restart the Car", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOW, VisualAlert.none, AudibleAlert.chimeError, .4, 2., 3.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "radarFaultNoEntry", | ||||
|       "openpilot Unavailable", | ||||
|       "Radar Error: Restart the Car", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOW, VisualAlert.none, AudibleAlert.chimeError, .4, 2., 3.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "posenetInvalidNoEntry", | ||||
|       "openpilot Unavailable", | ||||
|       "Vision Model Output Uncertain", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOW, VisualAlert.none, AudibleAlert.chimeError, .4, 2., 3.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "controlsFailedNoEntry", | ||||
|       "openpilot Unavailable", | ||||
|       "Controls Failed", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOW, VisualAlert.none, AudibleAlert.chimeError, .4, 2., 3.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "canErrorNoEntry", | ||||
|       "openpilot Unavailable", | ||||
|       "CAN Error: Check Connections", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOW, VisualAlert.none, AudibleAlert.chimeError, .4, 2., 3.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "steerUnavailableNoEntry", | ||||
|       "openpilot Unavailable", | ||||
|       "LKAS Fault: Restart the Car", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOW, VisualAlert.none, AudibleAlert.chimeError, .4, 2., 3.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "brakeUnavailableNoEntry", | ||||
|       "openpilot Unavailable", | ||||
|       "Cruise Fault: Restart the Car", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOW, VisualAlert.none, AudibleAlert.chimeError, .4, 2., 3.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "gasUnavailableNoEntry", | ||||
|       "openpilot Unavailable", | ||||
|       "Gas Error: Restart the Car", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOW, VisualAlert.none, AudibleAlert.chimeError, .4, 2., 3.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "reverseGearNoEntry", | ||||
|       "openpilot Unavailable", | ||||
|       "Reverse Gear", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOW, VisualAlert.none, AudibleAlert.chimeError, .4, 2., 3.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "cruiseDisabledNoEntry", | ||||
|       "openpilot Unavailable", | ||||
|       "Cruise is Off", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOW, VisualAlert.none, AudibleAlert.chimeError, .4, 2., 3.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "noTargetNoEntry", | ||||
|       "openpilot Unavailable", | ||||
|       "No Close Lead Car", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOW, VisualAlert.none, AudibleAlert.chimeError, .4, 2., 3.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "plannerErrorNoEntry", | ||||
|       "openpilot Unavailable", | ||||
|       "Planner Solution Error", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOW, VisualAlert.none, AudibleAlert.chimeError, .4, 2., 3.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "commIssueNoEntry", | ||||
|       "openpilot Unavailable", | ||||
|       "Communication Issue between Processes", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOW, VisualAlert.none, AudibleAlert.chimeDisengage, .4, 2., 3.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "radarCommIssueNoEntry", | ||||
|       "openpilot Unavailable", | ||||
|       "Radar Communication Issue", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOW, VisualAlert.none, AudibleAlert.chimeDisengage, .4, 2., 3.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "internetConnectivityNeededNoEntry", | ||||
|       "openpilot Unavailable", | ||||
|       "Please Connect to Internet", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOW, VisualAlert.none, AudibleAlert.chimeDisengage, .4, 2., 3.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "lowMemoryNoEntry", | ||||
|       "openpilot Unavailable", | ||||
|       "Low Memory: Reboot Your Device", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOW, VisualAlert.none, AudibleAlert.chimeDisengage, .4, 2., 3.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "speedTooHighNoEntry", | ||||
|       "Speed Too High", | ||||
|       "Slow down to engage", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOW, VisualAlert.none, AudibleAlert.chimeError, .4, 2., 3.), | ||||
| 
 | ||||
|   Alert( | ||||
|       "relayMalfunctionNoEntry", | ||||
|       "openpilot Unavailable", | ||||
|       "Harness Malfunction", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOW, VisualAlert.none, AudibleAlert.chimeError, .4, 2., 3.), | ||||
| 
 | ||||
|   # permanent alerts | ||||
|   Alert( | ||||
|       "steerUnavailablePermanent", | ||||
|       "LKAS Fault: Restart the car to engage", | ||||
|       "", | ||||
|       AlertStatus.normal, AlertSize.small, | ||||
|       Priority.LOWER, VisualAlert.none, AudibleAlert.none, 0., 0., .2), | ||||
| 
 | ||||
|   Alert( | ||||
|       "brakeUnavailablePermanent", | ||||
|       "Cruise Fault: Restart the car to engage", | ||||
|       "", | ||||
|       AlertStatus.normal, AlertSize.small, | ||||
|       Priority.LOWER, VisualAlert.none, AudibleAlert.none, 0., 0., .2), | ||||
| 
 | ||||
|   Alert( | ||||
|       "lowSpeedLockoutPermanent", | ||||
|       "Cruise Fault: Restart the car to engage", | ||||
|       "", | ||||
|       AlertStatus.normal, AlertSize.small, | ||||
|       Priority.LOWER, VisualAlert.none, AudibleAlert.none, 0., 0., .2), | ||||
| 
 | ||||
|   Alert( | ||||
|       "calibrationIncompletePermanent", | ||||
|       "Calibration in Progress: ", | ||||
|       "Drive Above ", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOWEST, VisualAlert.none, AudibleAlert.none, 0., 0., .2), | ||||
| 
 | ||||
|   Alert( | ||||
|       "invalidGiraffeToyotaPermanent", | ||||
|       "Unsupported Giraffe Configuration", | ||||
|       "Visit comma.ai/tg", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOWER, VisualAlert.none, AudibleAlert.none, 0., 0., .2), | ||||
| 
 | ||||
|   Alert( | ||||
|       "invalidLkasSettingPermanent", | ||||
|       "Stock LKAS is turned on", | ||||
|       "Turn off stock LKAS to engage", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOWER, VisualAlert.none, AudibleAlert.none, 0., 0., .2), | ||||
| 
 | ||||
|   Alert( | ||||
|       "internetConnectivityNeededPermanent", | ||||
|       "Please connect to Internet", | ||||
|       "An Update Check Is Required to Engage", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOWER, VisualAlert.none, AudibleAlert.none, 0., 0., .2), | ||||
| 
 | ||||
|   Alert( | ||||
|       "communityFeatureDisallowedPermanent", | ||||
|       "Community Feature Detected", | ||||
|       "Enable Community Features in Developer Settings", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOW, VisualAlert.none, AudibleAlert.none, 0., 0., .2),  # LOW priority to overcome Cruise Error | ||||
| 
 | ||||
|   Alert( | ||||
|       "sensorDataInvalidPermanent", | ||||
|       "No Data from Device Sensors", | ||||
|       "Reboot your Device", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOWER, VisualAlert.none, AudibleAlert.none, 0., 0., .2), | ||||
| 
 | ||||
|   Alert( | ||||
|       "soundsUnavailablePermanent", | ||||
|       "Speaker not found", | ||||
|       "Reboot your Device", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOWER, VisualAlert.none, AudibleAlert.none, 0., 0., .2), | ||||
| 
 | ||||
|   Alert( | ||||
|       "lowMemoryPermanent", | ||||
|       "RAM Critically Low", | ||||
|       "Reboot your Device", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOWER, VisualAlert.none, AudibleAlert.none, 0., 0., .2), | ||||
| 
 | ||||
|   Alert( | ||||
|       "carUnrecognizedPermanent", | ||||
|       "Dashcam Mode", | ||||
|       "Car Unrecognized", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOWER, VisualAlert.none, AudibleAlert.none, 0., 0., .2), | ||||
| 
 | ||||
|   Alert( | ||||
|       "relayMalfunctionPermanent", | ||||
|       "Harness Malfunction", | ||||
|       "Please Check Hardware", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOWER, VisualAlert.none, AudibleAlert.none, 0., 0., .2), | ||||
| 
 | ||||
|   Alert( | ||||
|       "vehicleModelInvalid", | ||||
|       "Vehicle Parameter Identification Failed", | ||||
|       "", | ||||
|       AlertStatus.normal, AlertSize.small, | ||||
|       Priority.LOWEST, VisualAlert.steerRequired, AudibleAlert.none, .0, .0, .1), | ||||
| 
 | ||||
|   Alert( | ||||
|       "ldwPermanent", | ||||
|       "TAKE CONTROL", | ||||
|       "Lane Departure Detected", | ||||
|       AlertStatus.userPrompt, AlertSize.mid, | ||||
|       Priority.LOW, VisualAlert.steerRequired, AudibleAlert.chimePrompt, 1., 2., 3.), | ||||
| ] | ||||
| @ -0,0 +1,694 @@ | ||||
| from cereal import log, car | ||||
| 
 | ||||
| from selfdrive.config import Conversions as CV | ||||
| 
 | ||||
| from selfdrive.locationd.calibration_helpers import Filter | ||||
| 
 | ||||
| AlertSize = log.ControlsState.AlertSize | ||||
| AlertStatus = log.ControlsState.AlertStatus | ||||
| VisualAlert = car.CarControl.HUDControl.VisualAlert | ||||
| AudibleAlert = car.CarControl.HUDControl.AudibleAlert | ||||
| EventName = car.CarEvent.EventName | ||||
| 
 | ||||
| # Alert priorities | ||||
| class Priority: | ||||
|   LOWEST = 0 | ||||
|   LOWER = 1 | ||||
|   LOW = 2 | ||||
|   MID = 3 | ||||
|   HIGH = 4 | ||||
|   HIGHEST = 5 | ||||
| 
 | ||||
| # Event types | ||||
| class ET: | ||||
|   ENABLE = 'enable' | ||||
|   PRE_ENABLE = 'preEnable' | ||||
|   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 = [] | ||||
|     self.static_events = [] | ||||
| 
 | ||||
|   @property | ||||
|   def names(self): | ||||
|     return self.events | ||||
| 
 | ||||
|   def __len__(self): | ||||
|     return len(self.events) | ||||
| 
 | ||||
|   def add(self, event_name, static=False): | ||||
|     if static: | ||||
|       self.static_events.append(event_name) | ||||
|     self.events.append(event_name) | ||||
| 
 | ||||
|   def clear(self): | ||||
|     self.events = self.static_events.copy() | ||||
| 
 | ||||
|   def any(self, event_type): | ||||
|     for e in self.events: | ||||
|       if event_type in EVENTS.get(e, {}).keys(): | ||||
|         return True | ||||
|     return False | ||||
| 
 | ||||
|   def create_alerts(self, event_types, 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) | ||||
|           alert.alert_type = EVENT_NAME[e] | ||||
|           ret.append(alert) | ||||
|     return ret | ||||
| 
 | ||||
|   def add_from_msg(self, events): | ||||
|     for e in events: | ||||
|       self.events.append(e.name.raw) | ||||
| 
 | ||||
|   def to_msg(self): | ||||
|     ret = [] | ||||
|     for event_name in self.events: | ||||
|       event = car.CarEvent.new_message() | ||||
|       event.name = event_name | ||||
|       for event_type in EVENTS.get(event_name, {}).keys(): | ||||
|         setattr(event, event_type , True) | ||||
|       ret.append(event) | ||||
|     return ret | ||||
| 
 | ||||
| class Alert: | ||||
|   def __init__(self, | ||||
|                alert_text_1, | ||||
|                alert_text_2, | ||||
|                alert_status, | ||||
|                alert_size, | ||||
|                alert_priority, | ||||
|                visual_alert, | ||||
|                audible_alert, | ||||
|                duration_sound, | ||||
|                duration_hud_alert, | ||||
|                duration_text, | ||||
|                alert_rate=0.): | ||||
| 
 | ||||
|     self.alert_type = "" | ||||
|     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.alert_priority = alert_priority | ||||
|     self.visual_alert = visual_alert | ||||
|     self.audible_alert = audible_alert | ||||
| 
 | ||||
|     self.duration_sound = duration_sound | ||||
|     self.duration_hud_alert = duration_hud_alert | ||||
|     self.duration_text = duration_text | ||||
| 
 | ||||
|     self.start_time = 0. | ||||
|     self.alert_rate = alert_rate | ||||
| 
 | ||||
|     # typecheck that enums are valid on startup | ||||
|     tst = car.CarControl.new_message() | ||||
|     tst.hudControl.visualAlert = self.visual_alert | ||||
| 
 | ||||
|   def __str__(self): | ||||
|     return self.alert_text_1 + "/" + self.alert_text_2 + " " + str(self.alert_priority) + "  " + str( | ||||
|       self.visual_alert) + " " + str(self.audible_alert) | ||||
| 
 | ||||
|   def __gt__(self, alert2): | ||||
|     return self.alert_priority > alert2.alert_priority | ||||
| 
 | ||||
| class NoEntryAlert(Alert): | ||||
|   def __init__(self, alert_text_2, audible_alert=AudibleAlert.chimeError, | ||||
|                visual_alert=VisualAlert.none, duration_hud_alert=2.): | ||||
|     super().__init__("openpilot Unavailable", alert_text_2, AlertStatus.normal, | ||||
|                      AlertSize.mid, Priority.LOW, visual_alert, | ||||
|                      audible_alert, .4, duration_hud_alert, 3.) | ||||
| 
 | ||||
| 
 | ||||
| class SoftDisableAlert(Alert): | ||||
|   def __init__(self, alert_text_2): | ||||
|     super().__init__("TAKE CONTROL IMMEDIATELY", alert_text_2, | ||||
|                      AlertStatus.critical, AlertSize.full, | ||||
|                      Priority.MID, VisualAlert.steerRequired, | ||||
|                      AudibleAlert.chimeWarningRepeat, .1, 2., 2.), | ||||
| 
 | ||||
| 
 | ||||
| class ImmediateDisableAlert(Alert): | ||||
|   def __init__(self, alert_text_2, alert_text_1="TAKE CONTROL IMMEDIATELY"): | ||||
|     super().__init__(alert_text_1, alert_text_2, | ||||
|                      AlertStatus.critical, AlertSize.full, | ||||
|                      Priority.HIGHEST, VisualAlert.steerRequired, | ||||
|                      AudibleAlert.chimeWarningRepeat, 2.2, 3., 4.), | ||||
| 
 | ||||
| class EngagementAlert(Alert): | ||||
|   def __init__(self, audible_alert=True): | ||||
|     super().__init__("", "", | ||||
|                      AlertStatus.normal, AlertSize.none, | ||||
|                      Priority.MID, VisualAlert.none, | ||||
|                      audible_alert, .2, 0., 0.), | ||||
| 
 | ||||
| def below_steer_speed_alert(CP, sm, metric): | ||||
|   speed = CP.minSteerSpeed * (CV.MS_TO_KPH if metric else CV.MS_TO_MPH) | ||||
|   unit = "kph" if metric else "mph" | ||||
|   return Alert( | ||||
|     "TAKE CONTROL", | ||||
|     "Steer Unavailable Below %d %s" % (speed, unit), | ||||
|     AlertStatus.userPrompt, AlertSize.mid, | ||||
|     Priority.MID, VisualAlert.steerRequired, AudibleAlert.none, 0., 0.4, .3), | ||||
| 
 | ||||
| def calibration_incomplete_alert(CP, sm, metric): | ||||
|   speed = int(Filter.MIN_SPEED * (CV.MS_TO_KPH if metric else CV.MS_TO_MPH)) | ||||
|   unit = "kph" if metric else "mph" | ||||
|   return Alert( | ||||
|     "Calibration in Progress: %d" % sm['liveCalibration'].calPerc, | ||||
|     "Drive Above %d %s" % (speed, unit), | ||||
|     AlertStatus.normal, AlertSize.mid, | ||||
|     Priority.LOWEST, VisualAlert.none, AudibleAlert.none, 0., 0., .2), | ||||
| 
 | ||||
| EVENTS = { | ||||
|   # ********** events with no alerts ********** | ||||
| 
 | ||||
|   EventName.gasPressed: {ET.PRE_ENABLE: None}, | ||||
| 
 | ||||
|   # ********** events only containing alerts displayed in all states ********** | ||||
| 
 | ||||
|   EventName.debugAlert: { | ||||
|     ET.PERMANENT: Alert( | ||||
|       "DEBUG ALERT", | ||||
|       "", | ||||
|       AlertStatus.userPrompt, AlertSize.mid, | ||||
|       Priority.LOW, VisualAlert.none, AudibleAlert.none, .1, .1, .1), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.startup: { | ||||
|     ET.PERMANENT: Alert( | ||||
|       "Be ready to take over at any time", | ||||
|       "Always keep hands on wheel and eyes on road", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOWER, VisualAlert.none, AudibleAlert.none, 0., 0., 15.), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.startupMaster: { | ||||
|     ET.PERMANENT: Alert( | ||||
|       "WARNING: This branch is not tested", | ||||
|       "Always keep hands on wheel and eyes on road", | ||||
|       AlertStatus.userPrompt, AlertSize.mid, | ||||
|       Priority.LOWER, VisualAlert.none, AudibleAlert.none, 0., 0., 15.), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.startupNoControl: { | ||||
|     ET.PERMANENT: Alert( | ||||
|       "Dashcam mode", | ||||
|       "Always keep hands on wheel and eyes on road", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOWER, VisualAlert.none, AudibleAlert.none, 0., 0., 15.), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.startupNoCar: { | ||||
|     ET.PERMANENT: Alert( | ||||
|       "Dashcam mode for unsupported car", | ||||
|       "Always keep hands on wheel and eyes on road", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOWER, VisualAlert.none, AudibleAlert.none, 0., 0., 15.), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.invalidGiraffeToyota: { | ||||
|     ET.PERMANENT: Alert( | ||||
|       "Unsupported Giraffe Configuration", | ||||
|       "Visit comma.ai/tg", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOWER, VisualAlert.none, AudibleAlert.none, 0., 0., .2), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.invalidLkasSetting: { | ||||
|     ET.PERMANENT: Alert( | ||||
|       "Stock LKAS is turned on", | ||||
|       "Turn off stock LKAS to engage", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOWER, VisualAlert.none, AudibleAlert.none, 0., 0., .2), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.communityFeatureDisallowed: { | ||||
|     # LOW priority to overcome Cruise Error | ||||
|     ET.PERMANENT: Alert( | ||||
|       "", | ||||
|       "Community Feature Detected", | ||||
|       "Enable Community Features in Developer Settings", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOW, VisualAlert.none, AudibleAlert.none, 0., 0., .2), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.carUnrecognized: { | ||||
|     ET.PERMANENT: Alert( | ||||
|       "Dashcam Mode", | ||||
|       "Car Unrecognized", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOWER, VisualAlert.none, AudibleAlert.none, 0., 0., .2), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.stockAeb: { | ||||
|     ET.PERMANENT: Alert( | ||||
|       "BRAKE!", | ||||
|       "Stock AEB: Risk of Collision", | ||||
|       AlertStatus.critical, AlertSize.full, | ||||
|       Priority.HIGHEST, VisualAlert.fcw, AudibleAlert.none, 1., 2., 2.), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.stockFcw: { | ||||
|     ET.PERMANENT: Alert( | ||||
|       "BRAKE!", | ||||
|       "Stock FCW: Risk of Collision", | ||||
|       AlertStatus.critical, AlertSize.full, | ||||
|       Priority.HIGHEST, VisualAlert.fcw, AudibleAlert.none, 1., 2., 2.), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.fcw: { | ||||
|     ET.PERMANENT: Alert( | ||||
|       "BRAKE!", | ||||
|       "Risk of Collision", | ||||
|       AlertStatus.critical, AlertSize.full, | ||||
|       Priority.HIGHEST, VisualAlert.fcw, AudibleAlert.chimeWarningRepeat, 1., 2., 2.), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.ldw: { | ||||
|     ET.PERMANENT: Alert( | ||||
|       "TAKE CONTROL", | ||||
|       "Lane Departure Detected", | ||||
|       AlertStatus.userPrompt, AlertSize.mid, | ||||
|       Priority.LOW, VisualAlert.steerRequired, AudibleAlert.chimePrompt, 1., 2., 3.), | ||||
|   }, | ||||
| 
 | ||||
|   # ********** events only containing alerts that display while engaged ********** | ||||
| 
 | ||||
|   EventName.vehicleModelInvalid: { | ||||
|     ET.WARNING: Alert( | ||||
|       "Vehicle Parameter Identification Failed", | ||||
|       "", | ||||
|       AlertStatus.normal, AlertSize.small, | ||||
|       Priority.LOWEST, VisualAlert.steerRequired, AudibleAlert.none, .0, .0, .1), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.steerTempUnavailableMute: { | ||||
|     ET.WARNING: Alert( | ||||
|       "TAKE CONTROL", | ||||
|       "Steering Temporarily Unavailable", | ||||
|       AlertStatus.userPrompt, AlertSize.mid, | ||||
|       Priority.LOW, VisualAlert.none, AudibleAlert.none, .2, .2, .2), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.preDriverDistracted: { | ||||
|     ET.WARNING: Alert( | ||||
|       "KEEP EYES ON ROAD: Driver Distracted", | ||||
|       "", | ||||
|       AlertStatus.normal, AlertSize.small, | ||||
|       Priority.LOW, VisualAlert.steerRequired, AudibleAlert.none, .0, .1, .1, alert_rate=0.75), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.promptDriverDistracted: { | ||||
|     ET.WARNING: Alert( | ||||
|       "KEEP EYES ON ROAD", | ||||
|       "Driver Appears Distracted", | ||||
|       AlertStatus.userPrompt, AlertSize.mid, | ||||
|       Priority.MID, VisualAlert.steerRequired, AudibleAlert.chimeWarning2Repeat, .1, .1, .1), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.driverDistracted: { | ||||
|     ET.WARNING: Alert( | ||||
|       "DISEventName.AGE IMMEDIATELY", | ||||
|       "Driver Was Distracted", | ||||
|       AlertStatus.critical, AlertSize.full, | ||||
|       Priority.HIGH, VisualAlert.steerRequired, AudibleAlert.chimeWarningRepeat, .1, .1, .1), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.preDriverUnresponsive: { | ||||
|     ET.WARNING: Alert( | ||||
|       "TOUCH STEERING WHEEL: No Face Detected", | ||||
|       "", | ||||
|       AlertStatus.normal, AlertSize.small, | ||||
|       Priority.LOW, VisualAlert.steerRequired, AudibleAlert.none, .0, .1, .1, alert_rate=0.75), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.promptDriverUnresponsive: { | ||||
|     ET.WARNING: Alert( | ||||
|       "TOUCH STEERING WHEEL", | ||||
|       "Driver Is Unresponsive", | ||||
|       AlertStatus.userPrompt, AlertSize.mid, | ||||
|       Priority.MID, VisualAlert.steerRequired, AudibleAlert.chimeWarning2Repeat, .1, .1, .1), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.driverUnresponsive: { | ||||
|     ET.WARNING: Alert( | ||||
|       "DISEventName.AGE IMMEDIATELY", | ||||
|       "Driver Was Unresponsive", | ||||
|       AlertStatus.critical, AlertSize.full, | ||||
|       Priority.HIGH, VisualAlert.steerRequired, AudibleAlert.chimeWarningRepeat, .1, .1, .1), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.driverMonitorLowAcc: { | ||||
|     ET.WARNING: Alert( | ||||
|       "CHECK DRIVER FACE VISIBILITY", | ||||
|       "Driver Monitor Model Output Uncertain", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOW, VisualAlert.steerRequired, AudibleAlert.none, .4, 0., 1.), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.manualRestart: { | ||||
|     ET.WARNING: Alert( | ||||
|       "TAKE CONTROL", | ||||
|       "Resume Driving Manually", | ||||
|       AlertStatus.userPrompt, AlertSize.mid, | ||||
|       Priority.LOW, VisualAlert.none, AudibleAlert.none, 0., 0., .2), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.resumeRequired: { | ||||
|     ET.WARNING: Alert( | ||||
|       "STOPPED", | ||||
|       "Press Resume to Move", | ||||
|       AlertStatus.userPrompt, AlertSize.mid, | ||||
|       Priority.LOW, VisualAlert.none, AudibleAlert.none, 0., 0., .2), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.belowSteerSpeed: { | ||||
|     ET.WARNING: Alert( | ||||
|       "TAKE CONTROL", | ||||
|       "Steer Unavailable Below ", | ||||
|       AlertStatus.userPrompt, AlertSize.mid, | ||||
|       Priority.MID, VisualAlert.steerRequired, AudibleAlert.none, 0., 0.4, .3), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.preLaneChangeLeft: { | ||||
|     ET.WARNING: Alert( | ||||
|       "Steer Left to Start Lane Change", | ||||
|       "Monitor Other Vehicles", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOW, VisualAlert.steerRequired, AudibleAlert.none, .0, .1, .1, alert_rate=0.75), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.preLaneChangeRight: { | ||||
|     ET.WARNING: Alert( | ||||
|       "Steer Right to Start Lane Change", | ||||
|       "Monitor Other Vehicles", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOW, VisualAlert.steerRequired, AudibleAlert.none, .0, .1, .1, alert_rate=0.75), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.laneChange: { | ||||
|     ET.WARNING: Alert( | ||||
|       "Changing Lane", | ||||
|       "Monitor Other Vehicles", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOW, VisualAlert.steerRequired, AudibleAlert.none, .0, .1, .1), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.steerSaturated: { | ||||
|     ET.WARNING: Alert( | ||||
|       "TAKE CONTROL", | ||||
|       "Turn Exceeds Steering Limit", | ||||
|       AlertStatus.userPrompt, AlertSize.mid, | ||||
|       Priority.LOW, VisualAlert.steerRequired, AudibleAlert.chimePrompt, 1., 2., 3.), | ||||
|   }, | ||||
| 
 | ||||
|   # ********** events that affect controls state transitions ********** | ||||
| 
 | ||||
|   EventName.pcmEnable: { | ||||
|     ET.ENABLE: EngagementAlert(AudibleAlert.chimeEngage), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.buttonEnable: { | ||||
|     ET.ENABLE: EngagementAlert(AudibleAlert.chimeEngage), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.pcmDisable: { | ||||
|     ET.USER_DISABLE: EngagementAlert(AudibleAlert.chimeDisengage), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.buttonCancel: { | ||||
|     ET.USER_DISABLE: EngagementAlert(AudibleAlert.chimeDisengage), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.brakeHold: { | ||||
|     ET.USER_DISABLE: EngagementAlert(AudibleAlert.chimeDisengage), | ||||
|     ET.NO_ENTRY: NoEntryAlert("Brake Hold Active"), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.parkBrake: { | ||||
|     ET.USER_DISABLE: EngagementAlert(AudibleAlert.chimeDisengage), | ||||
|     ET.NO_ENTRY: NoEntryAlert("Park Brake Engaged"), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.pedalPressed: { | ||||
|     ET.USER_DISABLE: EngagementAlert(AudibleAlert.chimeDisengage), | ||||
|     ET.NO_ENTRY: NoEntryAlert("Pedal Pressed During Attempt", | ||||
|                               visual_alert=VisualAlert.brakePressed), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.wrongCarMode: { | ||||
|     ET.USER_DISABLE: EngagementAlert(AudibleAlert.chimeDisengage), | ||||
|     ET.NO_ENTRY: NoEntryAlert("Main Switch Off", | ||||
|                               duration_hud_alert=0.), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.steerTempUnavailable: { | ||||
|     ET.WARNING: Alert( | ||||
|       "TAKE CONTROL", | ||||
|       "Steering Temporarily Unavailable", | ||||
|       AlertStatus.userPrompt, AlertSize.mid, | ||||
|       Priority.LOW, VisualAlert.steerRequired, AudibleAlert.chimeWarning1, .4, 2., 3.), | ||||
|     ET.NO_ENTRY: NoEntryAlert("Steering Temporarily Unavailable", | ||||
|                               duration_hud_alert=0.), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.posenetInvalid: { | ||||
|     ET.WARNING: Alert( | ||||
|       "TAKE CONTROL", | ||||
|       "Vision Model Output Uncertain", | ||||
|       AlertStatus.userPrompt, AlertSize.mid, | ||||
|       Priority.LOW, VisualAlert.steerRequired, AudibleAlert.chimeWarning1, .4, 2., 3.), | ||||
|     ET.NO_ENTRY: NoEntryAlert("Vision Model Output Uncertain"), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.outOfSpace: { | ||||
|     ET.NO_ENTRY: NoEntryAlert("Out of Storage Space", | ||||
|                               duration_hud_alert=0.), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.sensorDataInvalid: { | ||||
|     ET.PERMANENT: Alert( | ||||
|       "No Data from Device Sensors", | ||||
|       "Reboot your Device", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOWER, VisualAlert.none, AudibleAlert.none, 0., 0., .2), | ||||
|     ET.NO_ENTRY: NoEntryAlert("No Data from Device Sensors"), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.soundsUnavailable: { | ||||
|     ET.PERMANENT: Alert( | ||||
|       "Speaker not found", | ||||
|       "Reboot your Device", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOWER, VisualAlert.none, AudibleAlert.none, 0., 0., .2), | ||||
|     ET.NO_ENTRY: NoEntryAlert("Speaker not found"), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.tooDistracted: { | ||||
|     ET.NO_ENTRY: NoEntryAlert("Distraction Level Too High"), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.overheat: { | ||||
|     ET.SOFT_DISABLE: SoftDisableAlert("System Overheated"), | ||||
|     ET.NO_ENTRY: NoEntryAlert("System overheated"), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.wrongGear: { | ||||
|     ET.SOFT_DISABLE: SoftDisableAlert("Gear not D"), | ||||
|     ET.NO_ENTRY: NoEntryAlert("Gear not D"), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.calibrationInvalid: { | ||||
|     ET.SOFT_DISABLE: SoftDisableAlert("Calibration Invalid: Reposition Device and Recalibrate"), | ||||
|     ET.NO_ENTRY: NoEntryAlert("Calibration Invalid: Reposition Device & Recalibrate"), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.calibrationIncomplete: { | ||||
|     ET.SOFT_DISABLE: SoftDisableAlert("Calibration in Progress"), | ||||
|     ET.PERMANENT: calibration_incomplete_alert, | ||||
|     ET.NO_ENTRY: NoEntryAlert("Calibration in Progress"), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.doorOpen: { | ||||
|     ET.SOFT_DISABLE: SoftDisableAlert("Door Open"), | ||||
|     ET.NO_ENTRY: NoEntryAlert("Door open"), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.seatbeltNotLatched: { | ||||
|     ET.SOFT_DISABLE: SoftDisableAlert("Seatbelt Unlatched"), | ||||
|     ET.NO_ENTRY: NoEntryAlert("Seatbelt unlatched"), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.espDisabled: { | ||||
|     ET.SOFT_DISABLE: SoftDisableAlert("ESP Off"), | ||||
|     ET.NO_ENTRY: NoEntryAlert("ESP Off"), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.lowBattery: { | ||||
|     ET.SOFT_DISABLE: SoftDisableAlert("Low Battery"), | ||||
|     ET.NO_ENTRY: NoEntryAlert("Low Battery"), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.commIssue: { | ||||
|     ET.SOFT_DISABLE: SoftDisableAlert("Communication Issue between Processes"), | ||||
|     ET.NO_ENTRY: NoEntryAlert("Communication Issue between Processes", | ||||
|                               audible_alert=AudibleAlert.chimeDisengage), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.radarCommIssue: { | ||||
|     ET.SOFT_DISABLE: SoftDisableAlert("Radar Communication Issue"), | ||||
|     ET.NO_ENTRY: NoEntryAlert("Radar Communication Issue", | ||||
|                               audible_alert=AudibleAlert.chimeDisengage), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.radarCanError: { | ||||
|     ET.SOFT_DISABLE: SoftDisableAlert("Radar Error: Restart the Car"), | ||||
|     ET.NO_ENTRY: NoEntryAlert("Radar Error: Restart the Car"), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.radarFault: { | ||||
|     ET.SOFT_DISABLE: SoftDisableAlert("Radar Error: Restart the Car"), | ||||
|     ET.NO_ENTRY : NoEntryAlert("Radar Error: Restart the Car"), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.lowMemory: { | ||||
|     ET.SOFT_DISABLE: SoftDisableAlert("Low Memory: Reboot Your Device"), | ||||
|     ET.PERMANENT: Alert( | ||||
|       "RAM Critically Low", | ||||
|       "Reboot your Device", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOWER, VisualAlert.none, AudibleAlert.none, 0., 0., .2), | ||||
|     ET.NO_ENTRY : NoEntryAlert("Low Memory: Reboot Your Device", | ||||
|                                audible_alert=AudibleAlert.chimeDisengage), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.controlsFailed: { | ||||
|     ET.IMMEDIATE_DISABLE: ImmediateDisableAlert("Controls Failed"), | ||||
|     ET.NO_ENTRY: NoEntryAlert("Controls Failed"), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.controlsMismatch: { | ||||
|     ET.IMMEDIATE_DISABLE: ImmediateDisableAlert("Controls Mismatch"), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.canError: { | ||||
|     ET.IMMEDIATE_DISABLE: ImmediateDisableAlert("CAN Error: Check Connections"), | ||||
|     ET.NO_ENTRY: NoEntryAlert("CAN Error: Check Connections"), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.steerUnavailable: { | ||||
|     ET.IMMEDIATE_DISABLE: ImmediateDisableAlert("LKAS Fault: Restart the Car"), | ||||
|     ET.PERMANENT: Alert( | ||||
|       "LKAS Fault: Restart the car to engage", | ||||
|       "", | ||||
|       AlertStatus.normal, AlertSize.small, | ||||
|       Priority.LOWER, VisualAlert.none, AudibleAlert.none, 0., 0., .2), | ||||
|     ET.NO_ENTRY: NoEntryAlert("LKAS Fault: Restart the Car"), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.brakeUnavailable: { | ||||
|     ET.IMMEDIATE_DISABLE: ImmediateDisableAlert("Cruise Fault: Restart the Car"), | ||||
|     ET.PERMANENT: Alert( | ||||
|       "Cruise Fault: Restart the car to engage", | ||||
|       "", | ||||
|       AlertStatus.normal, AlertSize.small, | ||||
|       Priority.LOWER, VisualAlert.none, AudibleAlert.none, 0., 0., .2), | ||||
|     ET.NO_ENTRY: NoEntryAlert("Cruise Fault: Restart the Car"), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.gasUnavailable: { | ||||
|     ET.IMMEDIATE_DISABLE: ImmediateDisableAlert("Gas Fault: Restart the Car"), | ||||
|     ET.NO_ENTRY: NoEntryAlert("Gas Error: Restart the Car"), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.reverseGear: { | ||||
|     ET.IMMEDIATE_DISABLE: ImmediateDisableAlert("Reverse Gear"), | ||||
|     ET.NO_ENTRY: NoEntryAlert("Reverse Gear"), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.cruiseDisabled: { | ||||
|     ET.IMMEDIATE_DISABLE: ImmediateDisableAlert("Cruise Is Off"), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.plannerError: { | ||||
|     ET.IMMEDIATE_DISABLE: ImmediateDisableAlert("Planner Solution Error"), | ||||
|     ET.NO_ENTRY: NoEntryAlert("Planner Solution Error"), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.relayMalfunction: { | ||||
|     ET.IMMEDIATE_DISABLE: ImmediateDisableAlert("Harness Malfunction"), | ||||
|     ET.PERMANENT: Alert( | ||||
|       "Harness Malfunction", | ||||
|       "Please Check Hardware", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOWER, VisualAlert.none, AudibleAlert.none, 0., 0., .2), | ||||
|     ET.NO_ENTRY: NoEntryAlert("Harness Malfunction"), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.noTarget: { | ||||
|     ET.IMMEDIATE_DISABLE: Alert( | ||||
|       "openpilot Canceled", | ||||
|       "No close lead car", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.HIGH, VisualAlert.none, AudibleAlert.chimeDisengage, .4, 2., 3.), | ||||
|     ET.NO_ENTRY : NoEntryAlert("No Close Lead Car"), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.speedTooLow: { | ||||
|     ET.IMMEDIATE_DISABLE: Alert( | ||||
|       "openpilot Canceled", | ||||
|       "Speed too low", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.HIGH, VisualAlert.none, AudibleAlert.chimeDisengage, .4, 2., 3.), | ||||
|     ET.NO_ENTRY: NoEntryAlert("Speed Too Low"), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.speedTooHigh: { | ||||
|     ET.IMMEDIATE_DISABLE: Alert( | ||||
|       "Speed Too High", | ||||
|       "Slow down to resume operation", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.HIGH, VisualAlert.steerRequired, AudibleAlert.chimeWarning2Repeat, 2.2, 3., 4.), | ||||
|     ET.NO_ENTRY: Alert( | ||||
|       "Speed Too High", | ||||
|       "Slow down to engage", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOW, VisualAlert.none, AudibleAlert.chimeError, .4, 2., 3.), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.internetConnectivityNeeded: { | ||||
|     ET.PERMANENT: Alert( | ||||
|       "Please connect to Internet", | ||||
|       "An Update Check Is Required to Engage", | ||||
|       AlertStatus.normal, AlertSize.mid, | ||||
|       Priority.LOWER, VisualAlert.none, AudibleAlert.none, 0., 0., .2), | ||||
|     ET.NO_ENTRY: NoEntryAlert("Please Connect to Internet", | ||||
|                               audible_alert=AudibleAlert.chimeDisengage), | ||||
|   }, | ||||
| 
 | ||||
|   EventName.lowSpeedLockout: { | ||||
|     ET.PERMANENT: Alert( | ||||
|       "Cruise Fault: Restart the car to engage", | ||||
|       "", | ||||
|       AlertStatus.normal, AlertSize.small, | ||||
|       Priority.LOWER, VisualAlert.none, AudibleAlert.none, 0., 0., .2), | ||||
|     ET.NO_ENTRY: NoEntryAlert("Cruise Fault: Restart the Car"), | ||||
|   }, | ||||
| 
 | ||||
| } | ||||
| @ -1,48 +0,0 @@ | ||||
| #!/usr/bin/env python3 | ||||
| import os | ||||
| import unittest | ||||
| from PIL import Image, ImageDraw, ImageFont | ||||
| 
 | ||||
| from cereal import log | ||||
| from common.basedir import BASEDIR | ||||
| from selfdrive.controls.lib.alerts import ALERTS | ||||
| 
 | ||||
| AlertSize = log.ControlsState.AlertSize | ||||
| 
 | ||||
| FONT_PATH = os.path.join(BASEDIR, "selfdrive/assets/fonts") | ||||
| REGULAR_FONT_PATH = os.path.join(FONT_PATH, "opensans_semibold.ttf") | ||||
| BOLD_FONT_PATH = os.path.join(FONT_PATH, "opensans_semibold.ttf") | ||||
| SEMIBOLD_FONT_PATH = os.path.join(FONT_PATH, "opensans_semibold.ttf") | ||||
| 
 | ||||
| MAX_TEXT_WIDTH = 1920 - 300 # full screen width is useable, minus sidebar | ||||
| # TODO: get exact scale factor. found this empirically, works well enough | ||||
| FONT_SIZE_SCALE = 1.85 # factor to scale from nanovg units to PIL | ||||
| 
 | ||||
| class TestAlerts(unittest.TestCase): | ||||
| 
 | ||||
|   # ensure alert text doesn't exceed allowed width | ||||
|   def test_alert_text_length(self): | ||||
|     draw = ImageDraw.Draw(Image.new('RGB', (0, 0))) | ||||
| 
 | ||||
|     fonts = { | ||||
|             AlertSize.small: [ImageFont.truetype(SEMIBOLD_FONT_PATH, int(40*FONT_SIZE_SCALE))], | ||||
|             AlertSize.mid: [ImageFont.truetype(BOLD_FONT_PATH, int(48*FONT_SIZE_SCALE)), | ||||
|                               ImageFont.truetype(REGULAR_FONT_PATH, int(36*FONT_SIZE_SCALE))], | ||||
|             } | ||||
| 
 | ||||
|     for alert in ALERTS: | ||||
|       # for full size alerts, both text fields wrap the text, | ||||
|       # so it's unlikely that they  would go past the max width | ||||
|       if alert.alert_size in [AlertSize.none, AlertSize.full]: | ||||
|         continue | ||||
| 
 | ||||
|       for i, txt in enumerate([alert.alert_text_1, alert.alert_text_2]): | ||||
|         if i >= len(fonts[alert.alert_size]): break | ||||
| 
 | ||||
|         font = fonts[alert.alert_size][i] | ||||
|         w, h = draw.textsize(txt, font) | ||||
|         msg = "type: %s msg: %s" % (alert.alert_type, txt) | ||||
|         self.assertLessEqual(w, MAX_TEXT_WIDTH, msg=msg) | ||||
| 
 | ||||
| if __name__ == "__main__": | ||||
|   unittest.main() | ||||
| @ -0,0 +1,63 @@ | ||||
| #!/usr/bin/env python3 | ||||
| import os | ||||
| import unittest | ||||
| from PIL import Image, ImageDraw, ImageFont | ||||
| 
 | ||||
| from cereal import log, car | ||||
| from common.basedir import BASEDIR | ||||
| from selfdrive.controls.lib.events import Alert, EVENTS | ||||
| 
 | ||||
| AlertSize = log.ControlsState.AlertSize | ||||
| 
 | ||||
| class TestAlerts(unittest.TestCase): | ||||
| 
 | ||||
|   def test_events_defined(self): | ||||
|     # Ensure all events in capnp schema are defined in events.py | ||||
|     events = car.CarEvent.EventName.schema.enumerants | ||||
| 
 | ||||
|     for name, e in events.items(): | ||||
|       if not name.endswith("DEPRECATED"): | ||||
|         fail_msg = "%s @%d not in EVENTS" % (name, e) | ||||
|         self.assertTrue(e in EVENTS.keys(), msg=fail_msg) | ||||
| 
 | ||||
|   # ensure alert text doesn't exceed allowed width | ||||
|   def test_alert_text_length(self): | ||||
|     font_path = os.path.join(BASEDIR, "selfdrive/assets/fonts") | ||||
|     regular_font_path = os.path.join(font_path, "opensans_semibold.ttf") | ||||
|     bold_font_path = os.path.join(font_path, "opensans_semibold.ttf") | ||||
|     semibold_font_path = os.path.join(font_path, "opensans_semibold.ttf") | ||||
| 
 | ||||
|     max_text_width = 1920 - 300 # full screen width is useable, minus sidebar | ||||
|     # TODO: get exact scale factor. found this empirically, works well enough | ||||
|     font_scale_factor = 1.85 # factor to scale from nanovg units to PIL | ||||
| 
 | ||||
|     draw = ImageDraw.Draw(Image.new('RGB', (0, 0))) | ||||
| 
 | ||||
|     fonts = { | ||||
|       AlertSize.small: [ImageFont.truetype(semibold_font_path, int(40*font_scale_factor))], | ||||
|       AlertSize.mid: [ImageFont.truetype(bold_font_path, int(48*font_scale_factor)), | ||||
|                       ImageFont.truetype(regular_font_path, int(36*font_scale_factor))], | ||||
|     } | ||||
| 
 | ||||
|     alerts = [] | ||||
|     for event_types in EVENTS.values(): | ||||
|       for alert in event_types.values(): | ||||
|         if isinstance(alert, Alert): | ||||
|           alerts.append(alert) | ||||
| 
 | ||||
|     for alert in alerts: | ||||
|       # for full size alerts, both text fields wrap the text, | ||||
|       # so it's unlikely that they  would go past the max width | ||||
|       if alert.alert_size in [AlertSize.none, AlertSize.full]: | ||||
|         continue | ||||
| 
 | ||||
|       for i, txt in enumerate([alert.alert_text_1, alert.alert_text_2]): | ||||
|         if i >= len(fonts[alert.alert_size]): break | ||||
| 
 | ||||
|         font = fonts[alert.alert_size][i] | ||||
|         w, h = draw.textsize(txt, font) | ||||
|         msg = "type: %s msg: %s" % (alert.alert_type, txt) | ||||
|         self.assertLessEqual(w, max_text_width, msg=msg) | ||||
| 
 | ||||
| if __name__ == "__main__": | ||||
|   unittest.main() | ||||
| @ -1 +1 @@ | ||||
| 1050a84363baf1e7910d3f8f9a01e201e6041e70 | ||||
| 76e577b86d113139167275b4a7379f3591abfa02 | ||||
					Loading…
					
					
				
		Reference in new issue