You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
397 lines
12 KiB
397 lines
12 KiB
from cereal import car
|
|
from selfdrive.swaglog import cloudlog
|
|
import copy
|
|
|
|
|
|
# Priority
|
|
class PT:
|
|
HIGH = 3
|
|
MID = 2
|
|
LOW = 1
|
|
|
|
|
|
class Alert(object):
|
|
def __init__(self,
|
|
alert_text_1,
|
|
alert_text_2,
|
|
alert_priority,
|
|
visual_alert,
|
|
audible_alert,
|
|
duration_sound,
|
|
duration_hud_alert,
|
|
duration_text):
|
|
|
|
self.alert_text_1 = alert_text_1
|
|
self.alert_text_2 = alert_text_2
|
|
self.alert_priority = alert_priority
|
|
self.visual_alert = visual_alert if visual_alert is not None else "none"
|
|
self.audible_alert = audible_alert if audible_alert is not None else "none"
|
|
|
|
self.duration_sound = duration_sound
|
|
self.duration_hud_alert = duration_hud_alert
|
|
self.duration_text = duration_text
|
|
|
|
# typecheck that enums are valid on startup
|
|
tst = car.CarControl.new_message()
|
|
tst.hudControl.visualAlert = self.visual_alert
|
|
tst.hudControl.audibleAlert = self.audible_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 AlertManager(object):
|
|
alerts = {
|
|
|
|
# Miscellaneous alerts
|
|
"enable": Alert(
|
|
"",
|
|
"",
|
|
PT.MID, None, "beepSingle", .2, 0., 0.),
|
|
|
|
"disable": Alert(
|
|
"",
|
|
"",
|
|
PT.MID, None, "beepSingle", .2, 0., 0.),
|
|
|
|
"fcw": Alert(
|
|
"Brake",
|
|
"Risk of Collision",
|
|
PT.HIGH, "fcw", "chimeRepeated", 1., 2., 2.),
|
|
|
|
"steerSaturated": Alert(
|
|
"Take Control",
|
|
"Turn Exceeds Limit",
|
|
PT.LOW, "steerRequired", "chimeSingle", 1., 2., 3.),
|
|
|
|
"steerTempUnavailable": Alert(
|
|
"Take Control",
|
|
"Steer Temporarily Unavailable",
|
|
PT.LOW, "steerRequired", "chimeDouble", .4, 2., 3.),
|
|
|
|
"preDriverDistracted": Alert(
|
|
"Take Control",
|
|
"User Distracted",
|
|
PT.LOW, "steerRequired", "chimeDouble", .4, 2., 3.),
|
|
|
|
"driverDistracted": Alert(
|
|
"Take Control to Regain Speed",
|
|
"User Distracted",
|
|
PT.LOW, "steerRequired", "chimeRepeated", .5, .5, .5),
|
|
|
|
"startup": Alert(
|
|
"Always Keep Hands on Wheel",
|
|
"Be Ready to Take Over Any Time",
|
|
PT.LOW, None, None, 0., 0., 15.),
|
|
|
|
"ethicalDilemma": Alert(
|
|
"Take Control Immediately",
|
|
"Ethical Dilemma Detected",
|
|
PT.HIGH, "steerRequired", "chimeRepeated", 1., 3., 3.),
|
|
|
|
"steerTempUnavailableNoEntry": Alert(
|
|
"Comma Unavailable",
|
|
"Steer Temporary Unavailable",
|
|
PT.LOW, None, "chimeDouble", .4, 0., 3.),
|
|
|
|
"manualRestart": Alert(
|
|
"Take Control",
|
|
"Resume Driving Manually",
|
|
PT.LOW, None, None, .0, 0., 1.),
|
|
|
|
# Non-entry only alerts
|
|
"wrongCarModeNoEntry": Alert(
|
|
"Comma Unavailable",
|
|
"Main Switch Off",
|
|
PT.LOW, None, "chimeDouble", .4, 0., 3.),
|
|
|
|
"dataNeededNoEntry": Alert(
|
|
"Comma Unavailable",
|
|
"Data needed for calibration. Upload drive, try again",
|
|
PT.LOW, None, "chimeDouble", .4, 0., 3.),
|
|
|
|
"outOfSpaceNoEntry": Alert(
|
|
"Comma Unavailable",
|
|
"Out of Space",
|
|
PT.LOW, None, "chimeDouble", .4, 0., 3.),
|
|
|
|
"pedalPressedNoEntry": Alert(
|
|
"Comma Unavailable",
|
|
"Pedal Pressed",
|
|
PT.LOW, "brakePressed", "chimeDouble", .4, 2., 3.),
|
|
|
|
"speedTooLowNoEntry": Alert(
|
|
"Comma Unavailable",
|
|
"Speed Too Low",
|
|
PT.LOW, None, "chimeDouble", .4, 2., 3.),
|
|
|
|
"brakeHoldNoEntry": Alert(
|
|
"Comma Unavailable",
|
|
"Brake Hold Active",
|
|
PT.LOW, None, "chimeDouble", .4, 2., 3.),
|
|
|
|
"parkBrakeNoEntry": Alert(
|
|
"Comma Unavailable",
|
|
"Park Brake Engaged",
|
|
PT.LOW, None, "chimeDouble", .4, 2., 3.),
|
|
|
|
"lowSpeedLockoutNoEntry": Alert(
|
|
"Comma Unavailable",
|
|
"Cruise Fault: Restart the Car",
|
|
PT.LOW, None, "chimeDouble", .4, 2., 3.),
|
|
|
|
# Cancellation alerts causing disabling
|
|
"overheat": Alert(
|
|
"Take Control Immediately",
|
|
"System Overheated",
|
|
PT.MID, "steerRequired", "chimeRepeated", 1., 3., 3.),
|
|
|
|
"wrongGear": Alert(
|
|
"Take Control Immediately",
|
|
"Gear not D",
|
|
PT.MID, "steerRequired", "chimeRepeated", 1., 3., 3.),
|
|
|
|
"calibrationInvalid": Alert(
|
|
"Take Control Immediately",
|
|
"Calibration Invalid: Reposition Neo and Recalibrate",
|
|
PT.MID, "steerRequired", "chimeRepeated", 1., 3., 3.),
|
|
|
|
"calibrationInProgress": Alert(
|
|
"Take Control Immediately",
|
|
"Calibration in Progress",
|
|
PT.MID, "steerRequired", "chimeRepeated", 1., 3., 3.),
|
|
|
|
"doorOpen": Alert(
|
|
"Take Control Immediately",
|
|
"Door Open",
|
|
PT.MID, "steerRequired", "chimeRepeated", 1., 3., 3.),
|
|
|
|
"seatbeltNotLatched": Alert(
|
|
"Take Control Immediately",
|
|
"Seatbelt Unlatched",
|
|
PT.MID, "steerRequired", "chimeRepeated", 1., 3., 3.),
|
|
|
|
"espDisabled": Alert(
|
|
"Take Control Immediately",
|
|
"ESP Off",
|
|
PT.MID, "steerRequired", "chimeRepeated", 1., 3., 3.),
|
|
|
|
"radarCommIssue": Alert(
|
|
"Take Control Immediately",
|
|
"Radar Error: Restart the Car",
|
|
PT.HIGH, "steerRequired", "chimeRepeated", 1., 3., 3.),
|
|
|
|
"radarFault": Alert(
|
|
"Take Control Immediately",
|
|
"Radar Error: Restart the Car",
|
|
PT.HIGH, "steerRequired", "chimeRepeated", 1., 3., 3.),
|
|
|
|
"modelCommIssue": Alert(
|
|
"Take Control Immediately",
|
|
"Model Error: Restart the Car",
|
|
PT.HIGH, "steerRequired", "chimeRepeated", 1., 3., 3.),
|
|
|
|
"controlsFailed": Alert(
|
|
"Take Control Immediately",
|
|
"Controls Failed",
|
|
PT.HIGH, "steerRequired", "chimeRepeated", 1., 3., 3.),
|
|
|
|
"controlsMismatch": Alert(
|
|
"Take Control Immediately",
|
|
"Controls Mismatch",
|
|
PT.HIGH, "steerRequired", "chimeRepeated", 1., 3., 3.),
|
|
|
|
"commIssue": Alert(
|
|
"Take Control Immediately",
|
|
"CAN Error: Restart the Car",
|
|
PT.HIGH, "steerRequired", "chimeRepeated", 1., 3., 3.),
|
|
|
|
"steerUnavailable": Alert(
|
|
"Take Control Immediately",
|
|
"Steer Error: Restart the Car",
|
|
PT.HIGH, "steerRequired", "chimeRepeated", 1., 3., 3.),
|
|
|
|
"brakeUnavailable": Alert(
|
|
"Take Control Immediately",
|
|
"Brake Error: Restart the Car",
|
|
PT.HIGH, "steerRequired", "chimeRepeated", 1., 3., 3.),
|
|
|
|
"gasUnavailable": Alert(
|
|
"Take Control Immediately",
|
|
"Gas Error: Restart the Car",
|
|
PT.HIGH, "steerRequired", "chimeRepeated", 1., 3., 3.),
|
|
|
|
"reverseGear": Alert(
|
|
"Take Control Immediately",
|
|
"Reverse Gear",
|
|
PT.HIGH, "steerRequired", "chimeRepeated", 1., 3., 3.),
|
|
|
|
"cruiseDisabled": Alert(
|
|
"Take Control Immediately",
|
|
"Cruise Is Off",
|
|
PT.HIGH, "steerRequired", "chimeRepeated", 1., 3., 3.),
|
|
|
|
# not loud cancellations (user is in control)
|
|
"noTarget": Alert(
|
|
"Comma Canceled",
|
|
"No Close Lead",
|
|
PT.HIGH, None, "chimeDouble", .4, 2., 3.),
|
|
|
|
"speedTooLow": Alert(
|
|
"Comma Canceled",
|
|
"Speed Too Low",
|
|
PT.HIGH, None, "chimeDouble", .4, 2., 3.),
|
|
|
|
# Cancellation alerts causing non-entry
|
|
"overheatNoEntry": Alert(
|
|
"Comma Unavailable",
|
|
"System Overheated",
|
|
PT.LOW, None, "chimeDouble", .4, 2., 3.),
|
|
|
|
"wrongGearNoEntry": Alert(
|
|
"Comma Unavailable",
|
|
"Gear not D",
|
|
PT.LOW, None, "chimeDouble", .4, 2., 3.),
|
|
|
|
"calibrationInvalidNoEntry": Alert(
|
|
"Comma Unavailable",
|
|
"Calibration Invalid: Reposition Neo and Recalibrate",
|
|
PT.LOW, None, "chimeDouble", .4, 2., 3.),
|
|
|
|
"calibrationInProgressNoEntry": Alert(
|
|
"Comma Unavailable",
|
|
"Calibration in Progress",
|
|
PT.LOW, None, "chimeDouble", .4, 2., 3.),
|
|
|
|
"doorOpenNoEntry": Alert(
|
|
"Comma Unavailable",
|
|
"Door Open",
|
|
PT.LOW, None, "chimeDouble", .4, 2., 3.),
|
|
|
|
"seatbeltNotLatchedNoEntry": Alert(
|
|
"Comma Unavailable",
|
|
"Seatbelt Unlatched",
|
|
PT.LOW, None, "chimeDouble", .4, 2., 3.),
|
|
|
|
"espDisabledNoEntry": Alert(
|
|
"Comma Unavailable",
|
|
"ESP Off",
|
|
PT.LOW, None, "chimeDouble", .4, 2., 3.),
|
|
|
|
"radarCommIssueNoEntry": Alert(
|
|
"Comma Unavailable",
|
|
"Radar Error: Restart the Car",
|
|
PT.LOW, None, "chimeDouble", .4, 2., 3.),
|
|
|
|
"radarFaultNoEntry": Alert(
|
|
"Comma Unavailable",
|
|
"Radar Error: Restart the Car",
|
|
PT.LOW, None, "chimeDouble", .4, 2., 3.),
|
|
|
|
"modelCommIssueNoEntry": Alert(
|
|
"Comma Unavailable",
|
|
"Model Error: Restart the Car",
|
|
PT.LOW, None, "chimeDouble", .4, 2., 3.),
|
|
|
|
"controlsFailedNoEntry": Alert(
|
|
"Comma Unavailable",
|
|
"Controls Failed",
|
|
PT.LOW, None, "chimeDouble", .4, 2., 3.),
|
|
|
|
"controlsMismatchNoEntry": Alert(
|
|
"Comma Unavailable",
|
|
"Controls Mismatch",
|
|
PT.LOW, None, "chimeDouble", .4, 2., 3.),
|
|
|
|
"commIssueNoEntry": Alert(
|
|
"Comma Unavailable",
|
|
"CAN Error: Restart the Car",
|
|
PT.LOW, None, "chimeDouble", .4, 2., 3.),
|
|
|
|
"steerUnavailableNoEntry": Alert(
|
|
"Comma Unavailable",
|
|
"Steer Error: Restart the Car",
|
|
PT.LOW, None, "chimeDouble", .4, 2., 3.),
|
|
|
|
"brakeUnavailableNoEntry": Alert(
|
|
"Comma Unavailable",
|
|
"Brake Error: Restart the Car",
|
|
PT.LOW, None, "chimeDouble", .4, 2., 3.),
|
|
|
|
"gasUnavailableNoEntry": Alert(
|
|
"Comma Unavailable",
|
|
"Gas Error: Restart the Car",
|
|
PT.LOW, None, "chimeDouble", .4, 2., 3.),
|
|
|
|
"reverseGearNoEntry": Alert(
|
|
"Comma Unavailable",
|
|
"Reverse Gear",
|
|
PT.LOW, None, "chimeDouble", .4, 2., 3.),
|
|
|
|
"cruiseDisabledNoEntry": Alert(
|
|
"Comma Unavailable",
|
|
"Cruise is Off",
|
|
PT.LOW, None, "chimeDouble", .4, 2., 3.),
|
|
|
|
"noTargetNoEntry": Alert(
|
|
"Comma Unavailable",
|
|
"No Close Lead",
|
|
PT.LOW, None, "chimeDouble", .4, 2., 3.),
|
|
}
|
|
|
|
def __init__(self):
|
|
self.activealerts = []
|
|
self.current_alert = None
|
|
|
|
def alertPresent(self):
|
|
return len(self.activealerts) > 0
|
|
|
|
def add(self, alert_type, enabled=True, extra_text=''):
|
|
alert_type = str(alert_type)
|
|
this_alert = copy.copy(self.alerts[alert_type])
|
|
this_alert.alert_text_2 += extra_text
|
|
|
|
# if new alert is higher priority, log it
|
|
if self.current_alert is None or this_alert > self.current_alert:
|
|
cloudlog.event('alert_add',
|
|
alert_type=alert_type,
|
|
enabled=enabled)
|
|
|
|
self.activealerts.append(this_alert)
|
|
self.activealerts.sort()
|
|
|
|
def process_alerts(self, cur_time):
|
|
if self.alertPresent():
|
|
self.alert_start_time = cur_time
|
|
self.current_alert = self.activealerts[0]
|
|
print self.current_alert
|
|
|
|
# start with assuming no alerts
|
|
self.alert_text_1 = ""
|
|
self.alert_text_2 = ""
|
|
self.visual_alert = "none"
|
|
self.audible_alert = "none"
|
|
|
|
if self.current_alert is not None:
|
|
# ewwwww
|
|
if self.alert_start_time + self.current_alert.duration_sound > cur_time:
|
|
self.audible_alert = self.current_alert.audible_alert
|
|
|
|
if self.alert_start_time + self.current_alert.duration_hud_alert > cur_time:
|
|
self.visual_alert = self.current_alert.visual_alert
|
|
|
|
if self.alert_start_time + self.current_alert.duration_text > cur_time:
|
|
self.alert_text_1 = self.current_alert.alert_text_1
|
|
self.alert_text_2 = self.current_alert.alert_text_2
|
|
|
|
# disable current alert
|
|
if self.alert_start_time + max(self.current_alert.duration_sound, self.current_alert.duration_hud_alert,
|
|
self.current_alert.duration_text) < cur_time:
|
|
self.current_alert = None
|
|
|
|
# reset
|
|
self.activealerts = []
|
|
|