controlsd: split out state/alerts into selfdriveState (#33421)

* setup selfdriveState

* little more

* update refs

* migration

* all too slow
old-commit-hash: 87051803ab
pull/33433/head
Adeeb Shihadeh 8 months ago committed by GitHub
parent 60549c9557
commit 1b2bc44227
  1. 86
      cereal/log.capnp
  2. 1
      cereal/services.py
  3. 23
      selfdrive/controls/controlsd.py
  4. 8
      selfdrive/controls/lib/events.py
  5. 2
      selfdrive/controls/tests/test_alerts.py
  6. 4
      selfdrive/controls/tests/test_startup.py
  7. 2
      selfdrive/controls/tests/test_state_machine.py
  8. 20
      selfdrive/debug/cycle_alerts.py
  9. 18
      selfdrive/test/process_replay/migration.py
  10. 2
      selfdrive/test/process_replay/process_replay.py
  11. 2
      selfdrive/test/process_replay/ref_commit
  12. 4
      selfdrive/test/test_onroad.py
  13. 4
      selfdrive/ui/qt/offroad/settings.cc
  14. 40
      selfdrive/ui/qt/onroad/alerts.cc
  15. 12
      selfdrive/ui/qt/onroad/alerts.h
  16. 6
      selfdrive/ui/qt/onroad/annotated_camera.cc
  17. 2
      selfdrive/ui/qt/onroad/buttons.cc
  18. 10
      selfdrive/ui/soundd.py
  19. 10
      selfdrive/ui/tests/test_soundd.py
  20. 21
      selfdrive/ui/tests/test_ui/run.py
  21. 12
      selfdrive/ui/ui.cc
  22. 2
      selfdrive/ui/ui.h
  23. 8
      tools/cabana/videowidget.cc
  24. 2
      tools/cabana/videowidget.h
  25. 16
      tools/replay/replay.cc

@ -684,18 +684,53 @@ struct LiveTracks {
oncoming @9 :Bool; oncoming @9 :Bool;
} }
struct SelfdriveState {
# high level system state
state @0 :OpenpilotState;
enabled @1 :Bool;
active @2 :Bool;
engageable @9 :Bool; # can OP be engaged?
# UI alerts
alertText1 @3 :Text;
alertText2 @4 :Text;
alertStatus @5 :AlertStatus;
alertSize @6 :AlertSize;
alertType @7 :Text;
alertSound @8 :Car.CarControl.HUDControl.AudibleAlert;
# configurable driving settings
experimentalMode @10 :Bool;
personality @11 :LongitudinalPersonality;
enum OpenpilotState @0xdbe58b96d2d1ac61 {
disabled @0;
preEnabled @1;
enabled @2;
softDisabling @3;
overriding @4; # superset of overriding with steering or accelerator
}
enum AlertStatus @0xa0d0dcd113193c62 {
normal @0;
userPrompt @1;
critical @2;
}
enum AlertSize @0xe98bb99d6e985f64 {
none @0;
small @1;
mid @2;
full @3;
}
}
struct ControlsState @0x97ff69c53601abf1 { struct ControlsState @0x97ff69c53601abf1 {
cumLagMs @15 :Float32;
startMonoTime @48 :UInt64; startMonoTime @48 :UInt64;
longitudinalPlanMonoTime @28 :UInt64; longitudinalPlanMonoTime @28 :UInt64;
lateralPlanMonoTime @50 :UInt64; lateralPlanMonoTime @50 :UInt64;
state @31 :OpenpilotState;
enabled @19 :Bool;
active @36 :Bool;
experimentalMode @64 :Bool;
personality @66 :LongitudinalPersonality;
longControlState @30 :Car.CarControl.Actuators.LongControlState; longControlState @30 :Car.CarControl.Actuators.LongControlState;
vTargetLead @3 :Float32; vTargetLead @3 :Float32;
vCruise @22 :Float32; # actual set speed vCruise @22 :Float32; # actual set speed
@ -706,18 +741,21 @@ struct ControlsState @0x97ff69c53601abf1 {
aTarget @35 :Float32; aTarget @35 :Float32;
curvature @37 :Float32; # path curvature from vehicle model curvature @37 :Float32; # path curvature from vehicle model
desiredCurvature @61 :Float32; # lag adjusted curvatures used by lateral controllers desiredCurvature @61 :Float32; # lag adjusted curvatures used by lateral controllers
forceDecel @51 :Bool;
# UI alerts # TODO: remove these, they're now in selfdriveState
alertText1 @24 :Text; alertText1 @24 :Text;
alertText2 @25 :Text; alertText2 @25 :Text;
alertStatus @38 :AlertStatus; alertStatus @38 :SelfdriveState.AlertStatus;
alertSize @39 :AlertSize; alertSize @39 :SelfdriveState.AlertSize;
alertType @44 :Text; alertType @44 :Text;
alertSound @56 :Car.CarControl.HUDControl.AudibleAlert; alertSound @56 :Car.CarControl.HUDControl.AudibleAlert;
engageable @41 :Bool; # can OP be engaged? engageable @41 :Bool; # can OP be engaged?
forceDecel @51 :Bool;
cumLagMs @15 :Float32; state @31 :SelfdriveState.OpenpilotState;
enabled @19 :Bool;
active @36 :Bool;
experimentalMode @64 :Bool;
personality @66 :LongitudinalPersonality;
lateralControlState :union { lateralControlState :union {
indiState @52 :LateralINDIState; indiState @52 :LateralINDIState;
@ -730,27 +768,6 @@ struct ControlsState @0x97ff69c53601abf1 {
lqrStateDEPRECATED @55 :LateralLQRState; lqrStateDEPRECATED @55 :LateralLQRState;
} }
enum OpenpilotState @0xdbe58b96d2d1ac61 {
disabled @0;
preEnabled @1;
enabled @2;
softDisabling @3;
overriding @4; # superset of overriding with steering or accelerator
}
enum AlertStatus {
normal @0; # low priority alert for user's convenience
userPrompt @1; # mid priority alert that might require user intervention
critical @2; # high priority alert that needs immediate user intervention
}
enum AlertSize {
none @0; # don't display the alert
small @1; # small box
mid @2; # mid screen
full @3; # full screen
}
struct LateralINDIState { struct LateralINDIState {
active @0 :Bool; active @0 :Bool;
steeringAngleDeg @1 :Float32; steeringAngleDeg @1 :Float32;
@ -2300,6 +2317,7 @@ struct Event {
gpsNMEA @3 :GPSNMEAData; gpsNMEA @3 :GPSNMEAData;
can @5 :List(CanData); can @5 :List(CanData);
controlsState @7 :ControlsState; controlsState @7 :ControlsState;
selfdriveState @130 :SelfdriveState;
gyroscope @99 :SensorEventData; gyroscope @99 :SensorEventData;
gyroscope2 @100 :SensorEventData; gyroscope2 @100 :SensorEventData;
accelerometer @98 :SensorEventData; accelerometer @98 :SensorEventData;

@ -24,6 +24,7 @@ _services: dict[str, tuple] = {
"deviceState": (True, 2., 1), "deviceState": (True, 2., 1),
"can": (True, 100., 2053), # decimation gives ~3 msgs in a full segment "can": (True, 100., 2053), # decimation gives ~3 msgs in a full segment
"controlsState": (True, 100., 10), "controlsState": (True, 100., 10),
"selfdriveState": (True, 100., 10),
"pandaStates": (True, 10., 1), "pandaStates": (True, 10., 1),
"peripheralState": (True, 2., 1), "peripheralState": (True, 2., 1),
"radarState": (True, 20., 5), "radarState": (True, 20., 5),

@ -44,7 +44,7 @@ TESTING_CLOSET = "TESTING_CLOSET" in os.environ
IGNORE_PROCESSES = {"loggerd", "encoderd", "statsd"} IGNORE_PROCESSES = {"loggerd", "encoderd", "statsd"}
ThermalStatus = log.DeviceState.ThermalStatus ThermalStatus = log.DeviceState.ThermalStatus
State = log.ControlsState.OpenpilotState State = log.SelfdriveState.OpenpilotState
PandaType = log.PandaState.PandaType PandaType = log.PandaState.PandaType
Desire = log.Desire Desire = log.Desire
LaneChangeState = log.LaneChangeState LaneChangeState = log.LaneChangeState
@ -78,7 +78,7 @@ class Controls:
self.branch = get_short_branch() self.branch = get_short_branch()
# Setup sockets # Setup sockets
self.pm = messaging.PubMaster(['controlsState', 'carControl', 'onroadEvents']) self.pm = messaging.PubMaster(['selfdriveState', 'controlsState', 'carControl', 'onroadEvents'])
self.gps_location_service = get_gps_location_service(self.params) self.gps_location_service = get_gps_location_service(self.params)
self.gps_packets = [self.gps_location_service] self.gps_packets = [self.gps_location_service]
@ -781,6 +781,25 @@ class Controls:
self.pm.send('controlsState', dat) self.pm.send('controlsState', dat)
# selfdriveState
ss_msg = messaging.new_message('selfdriveState')
ss_msg.valid = CS.canValid
ss = ss_msg.selfdriveState
if current_alert:
ss.alertText1 = current_alert.alert_text_1
ss.alertText2 = current_alert.alert_text_2
ss.alertSize = current_alert.alert_size
ss.alertStatus = current_alert.alert_status
ss.alertType = current_alert.alert_type
ss.alertSound = current_alert.audible_alert
ss.enabled = self.enabled
ss.active = self.active
ss.state = self.state
ss.engageable = not self.events.contains(ET.NO_ENTRY)
ss.experimentalMode = self.experimental_mode
ss.personality = self.personality
self.pm.send('selfdriveState', ss_msg)
# onroadEvents - logged every second or on change # onroadEvents - logged every second or on change
if (self.sm.frame % int(1. / DT_CTRL) == 0) or (self.events.names != self.events_prev): if (self.sm.frame % int(1. / DT_CTRL) == 0) or (self.events.names != self.events_prev):
ce_send = messaging.new_message('onroadEvents', len(self.events)) ce_send = messaging.new_message('onroadEvents', len(self.events))

@ -12,8 +12,8 @@ from openpilot.common.git import get_short_branch
from openpilot.common.realtime import DT_CTRL from openpilot.common.realtime import DT_CTRL
from openpilot.selfdrive.locationd.calibrationd import MIN_SPEED_FILTER from openpilot.selfdrive.locationd.calibrationd import MIN_SPEED_FILTER
AlertSize = log.ControlsState.AlertSize AlertSize = log.SelfdriveState.AlertSize
AlertStatus = log.ControlsState.AlertStatus AlertStatus = log.SelfdriveState.AlertStatus
VisualAlert = car.CarControl.HUDControl.VisualAlert VisualAlert = car.CarControl.HUDControl.VisualAlert
AudibleAlert = car.CarControl.HUDControl.AudibleAlert AudibleAlert = car.CarControl.HUDControl.AudibleAlert
EventName = car.CarEvent.EventName EventName = car.CarEvent.EventName
@ -110,8 +110,8 @@ class Alert:
def __init__(self, def __init__(self,
alert_text_1: str, alert_text_1: str,
alert_text_2: str, alert_text_2: str,
alert_status: log.ControlsState.AlertStatus, alert_status: log.SelfdriveState.AlertStatus,
alert_size: log.ControlsState.AlertSize, alert_size: log.SelfdriveState.AlertSize,
priority: Priority, priority: Priority,
visual_alert: car.CarControl.HUDControl.VisualAlert, visual_alert: car.CarControl.HUDControl.VisualAlert,
audible_alert: car.CarControl.HUDControl.AudibleAlert, audible_alert: car.CarControl.HUDControl.AudibleAlert,

@ -12,7 +12,7 @@ from openpilot.selfdrive.controls.lib.events import Alert, EVENTS, ET
from openpilot.selfdrive.controls.lib.alertmanager import set_offroad_alert from openpilot.selfdrive.controls.lib.alertmanager import set_offroad_alert
from openpilot.selfdrive.test.process_replay.process_replay import CONFIGS from openpilot.selfdrive.test.process_replay.process_replay import CONFIGS
AlertSize = log.ControlsState.AlertSize AlertSize = log.SelfdriveState.AlertSize
OFFROAD_ALERTS_PATH = os.path.join(BASEDIR, "selfdrive/controls/lib/alerts_offroad.json") OFFROAD_ALERTS_PATH = os.path.join(BASEDIR, "selfdrive/controls/lib/alerts_offroad.json")

@ -59,7 +59,7 @@ CX5_FW_VERSIONS = [
(EventName.startupMaster, TOYOTA.TOYOTA_COROLLA, COROLLA_FW_VERSIONS_FUZZY, "toyota"), (EventName.startupMaster, TOYOTA.TOYOTA_COROLLA, COROLLA_FW_VERSIONS_FUZZY, "toyota"),
]) ])
def test_startup_alert(expected_event, car_model, fw_versions, brand): def test_startup_alert(expected_event, car_model, fw_versions, brand):
controls_sock = messaging.sub_sock("controlsState") controls_sock = messaging.sub_sock("selfdriveState")
pm = messaging.PubMaster(['can', 'pandaStates']) pm = messaging.PubMaster(['can', 'pandaStates'])
params = Params() params = Params()
@ -114,7 +114,7 @@ def test_startup_alert(expected_event, car_model, fw_versions, brand):
ctrls = messaging.drain_sock(controls_sock) ctrls = messaging.drain_sock(controls_sock)
if len(ctrls): if len(ctrls):
event_name = ctrls[0].controlsState.alertType.split("/")[0] event_name = ctrls[0].selfdriveState.alertType.split("/")[0]
assert EVENT_NAME[expected_event] == event_name, f"expected {EVENT_NAME[expected_event]} for '{car_model}', got {event_name}" assert EVENT_NAME[expected_event] == event_name, f"expected {EVENT_NAME[expected_event]} for '{car_model}', got {event_name}"
break break
else: else:

@ -6,7 +6,7 @@ from openpilot.selfdrive.controls.controlsd import Controls, SOFT_DISABLE_TIME
from openpilot.selfdrive.controls.lib.events import Events, ET, Alert, Priority, AlertSize, AlertStatus, VisualAlert, \ from openpilot.selfdrive.controls.lib.events import Events, ET, Alert, Priority, AlertSize, AlertStatus, VisualAlert, \
AudibleAlert, EVENTS AudibleAlert, EVENTS
State = log.ControlsState.OpenpilotState State = log.SelfdriveState.OpenpilotState
# The event types that maintain the current state # The event types that maintain the current state
MAINTAIN_STATES = {State.enabled: (None,), State.disabled: (None,), State.softDisabling: (ET.SOFT_DISABLE,), MAINTAIN_STATES = {State.enabled: (None,), State.disabled: (None,), State.softDisabling: (ET.SOFT_DISABLE,),

@ -57,7 +57,7 @@ def cycle_alerts(duration=200, is_metric=False):
'driverMonitoringState', 'longitudinalPlan', 'livePose', 'driverMonitoringState', 'longitudinalPlan', 'livePose',
'managerState'] + cameras) 'managerState'] + cameras)
pm = messaging.PubMaster(['controlsState', 'pandaStates', 'deviceState']) pm = messaging.PubMaster(['selfdriveState', 'pandaStates', 'deviceState'])
events = Events() events = Events()
AM = AlertManager() AM = AlertManager()
@ -100,17 +100,17 @@ def cycle_alerts(duration=200, is_metric=False):
print(alert) print(alert)
for _ in range(duration): for _ in range(duration):
dat = messaging.new_message() dat = messaging.new_message()
dat.init('controlsState') dat.init('selfdriveState')
dat.controlsState.enabled = False dat.selfdriveState.enabled = False
if alert: if alert:
dat.controlsState.alertText1 = alert.alert_text_1 dat.selfdriveState.alertText1 = alert.alert_text_1
dat.controlsState.alertText2 = alert.alert_text_2 dat.selfdriveState.alertText2 = alert.alert_text_2
dat.controlsState.alertSize = alert.alert_size dat.selfdriveState.alertSize = alert.alert_size
dat.controlsState.alertStatus = alert.alert_status dat.selfdriveState.alertStatus = alert.alert_status
dat.controlsState.alertType = alert.alert_type dat.selfdriveState.alertType = alert.alert_type
dat.controlsState.alertSound = alert.audible_alert dat.selfdriveState.alertSound = alert.audible_alert
pm.send('controlsState', dat) pm.send('selfdriveState', dat)
dat = messaging.new_message() dat = messaging.new_message()
dat.init('deviceState') dat.init('deviceState')

@ -15,6 +15,7 @@ def migrate_all(lr, old_logtime=False, manager_states=False, panda_states=False,
msgs = migrate_gpsLocation(msgs) msgs = migrate_gpsLocation(msgs)
msgs = migrate_deviceState(msgs) msgs = migrate_deviceState(msgs)
msgs = migrate_carOutput(msgs) msgs = migrate_carOutput(msgs)
msgs = migrate_selfdriveState(msgs)
if manager_states: if manager_states:
msgs = migrate_managerState(msgs) msgs = migrate_managerState(msgs)
if panda_states: if panda_states:
@ -26,6 +27,23 @@ def migrate_all(lr, old_logtime=False, manager_states=False, panda_states=False,
return msgs return msgs
def migrate_selfdriveState(lr):
ret = []
for msg in lr:
if msg.which() == 'controlsState':
m = messaging.new_message('selfdriveState')
m.valid = msg.valid
m.logMonoTime = msg.logMonoTime
ss = m.selfdriveState
for field in ("enabled", "active", "state", "engageable", "alertText1", "alertText2",
"alertStatus", "alertSize", "alertType", "alertSound", "experimentalMode",
"personality"):
setattr(ss, field, getattr(msg.controlsState, field))
ret.append(m.as_reader())
ret.append(msg)
return ret
def migrate_managerState(lr): def migrate_managerState(lr):
all_msgs = [] all_msgs = []
for msg in lr: for msg in lr:

@ -489,7 +489,7 @@ CONFIGS = [
"testJoystick", "liveTorqueParameters", "accelerometer", "gyroscope", "carOutput", "testJoystick", "liveTorqueParameters", "accelerometer", "gyroscope", "carOutput",
"gpsLocationExternal", "gpsLocation", "gpsLocationExternal", "gpsLocation",
], ],
subs=["controlsState", "carControl", "onroadEvents"], subs=["selfdriveState", "controlsState", "carControl", "onroadEvents"],
ignore=["logMonoTime", "controlsState.startMonoTime", "controlsState.cumLagMs"], ignore=["logMonoTime", "controlsState.startMonoTime", "controlsState.cumLagMs"],
config_callback=controlsd_config_callback, config_callback=controlsd_config_callback,
init_callback=get_car_params_callback, init_callback=get_car_params_callback,

@ -1 +1 @@
a8b4c81ec1df5135ae448c8273ce14c1a98b1bfc ab4983de4477d648e5c36447debfd6735dfc466f

@ -416,8 +416,8 @@ class TestOnroad:
startup_alert = None startup_alert = None
for msg in self.lrs[0]: for msg in self.lrs[0]:
# can't use onroadEvents because the first msg can be dropped while loggerd is starting up # can't use onroadEvents because the first msg can be dropped while loggerd is starting up
if msg.which() == "controlsState": if msg.which() == "selfdriveState":
startup_alert = msg.controlsState.alertText1 startup_alert = msg.selfdriveState.alertText1
break break
expected = EVENTS[car.CarEvent.EventName.startup][ET.PERMANENT].alert_text_1 expected = EVENTS[car.CarEvent.EventName.startup][ET.PERMANENT].alert_text_1
assert startup_alert == expected, "wrong startup alert" assert startup_alert == expected, "wrong startup alert"

@ -111,8 +111,8 @@ TogglesPanel::TogglesPanel(SettingsWindow *parent) : ListWidget(parent) {
void TogglesPanel::updateState(const UIState &s) { void TogglesPanel::updateState(const UIState &s) {
const SubMaster &sm = *(s.sm); const SubMaster &sm = *(s.sm);
if (sm.updated("controlsState")) { if (sm.updated("selfdriveState")) {
auto personality = sm["controlsState"].getControlsState().getPersonality(); auto personality = sm["selfdriveState"].getSelfdriveState().getPersonality();
if (personality != s.scene.personality && s.scene.started && isVisible()) { if (personality != s.scene.personality && s.scene.started && isVisible()) {
long_personality_setting->setCheckedButton(static_cast<int>(personality)); long_personality_setting->setCheckedButton(static_cast<int>(personality));
} }

@ -19,8 +19,8 @@ void OnroadAlerts::clear() {
} }
OnroadAlerts::Alert OnroadAlerts::getAlert(const SubMaster &sm, uint64_t started_frame) { OnroadAlerts::Alert OnroadAlerts::getAlert(const SubMaster &sm, uint64_t started_frame) {
const cereal::ControlsState::Reader &cs = sm["controlsState"].getControlsState(); const cereal::SelfdriveState::Reader &cs = sm["selfdriveState"].getSelfdriveState();
const uint64_t controls_frame = sm.rcv_frame("controlsState"); const uint64_t controls_frame = sm.rcv_frame("selfdriveState");
Alert a = {}; Alert a = {};
if (controls_frame >= started_frame) { // Don't get old alert. if (controls_frame >= started_frame) { // Don't get old alert.
@ -28,26 +28,26 @@ OnroadAlerts::Alert OnroadAlerts::getAlert(const SubMaster &sm, uint64_t started
cs.getAlertType().cStr(), cs.getAlertSize(), cs.getAlertStatus()}; cs.getAlertType().cStr(), cs.getAlertSize(), cs.getAlertStatus()};
} }
if (!sm.updated("controlsState") && (sm.frame - started_frame) > 5 * UI_FREQ) { if (!sm.updated("selfdriveState") && (sm.frame - started_frame) > 5 * UI_FREQ) {
const int CONTROLS_TIMEOUT = 5; const int CONTROLS_TIMEOUT = 5;
const int controls_missing = (nanos_since_boot() - sm.rcv_time("controlsState")) / 1e9; const int controls_missing = (nanos_since_boot() - sm.rcv_time("selfdriveState")) / 1e9;
// Handle controls timeout // Handle controls timeout
if (controls_frame < started_frame) { if (controls_frame < started_frame) {
// car is started, but controlsState hasn't been seen at all // car is started, but selfdriveState hasn't been seen at all
a = {tr("openpilot Unavailable"), tr("Waiting for controls to start"), a = {tr("openpilot Unavailable"), tr("Waiting for controls to start"),
"controlsWaiting", cereal::ControlsState::AlertSize::MID, "controlsWaiting", cereal::SelfdriveState::AlertSize::MID,
cereal::ControlsState::AlertStatus::NORMAL}; cereal::SelfdriveState::AlertStatus::NORMAL};
} else if (controls_missing > CONTROLS_TIMEOUT && !Hardware::PC()) { } else if (controls_missing > CONTROLS_TIMEOUT && !Hardware::PC()) {
// car is started, but controls is lagging or died // car is started, but controls is lagging or died
if (cs.getEnabled() && (controls_missing - CONTROLS_TIMEOUT) < 10) { if (cs.getEnabled() && (controls_missing - CONTROLS_TIMEOUT) < 10) {
a = {tr("TAKE CONTROL IMMEDIATELY"), tr("Controls Unresponsive"), a = {tr("TAKE CONTROL IMMEDIATELY"), tr("Controls Unresponsive"),
"controlsUnresponsive", cereal::ControlsState::AlertSize::FULL, "controlsUnresponsive", cereal::SelfdriveState::AlertSize::FULL,
cereal::ControlsState::AlertStatus::CRITICAL}; cereal::SelfdriveState::AlertStatus::CRITICAL};
} else { } else {
a = {tr("Controls Unresponsive"), tr("Reboot Device"), a = {tr("Controls Unresponsive"), tr("Reboot Device"),
"controlsUnresponsivePermanent", cereal::ControlsState::AlertSize::MID, "controlsUnresponsivePermanent", cereal::SelfdriveState::AlertSize::MID,
cereal::ControlsState::AlertStatus::NORMAL}; cereal::SelfdriveState::AlertStatus::NORMAL};
} }
} }
} }
@ -55,19 +55,19 @@ OnroadAlerts::Alert OnroadAlerts::getAlert(const SubMaster &sm, uint64_t started
} }
void OnroadAlerts::paintEvent(QPaintEvent *event) { void OnroadAlerts::paintEvent(QPaintEvent *event) {
if (alert.size == cereal::ControlsState::AlertSize::NONE) { if (alert.size == cereal::SelfdriveState::AlertSize::NONE) {
return; return;
} }
static std::map<cereal::ControlsState::AlertSize, const int> alert_heights = { static std::map<cereal::SelfdriveState::AlertSize, const int> alert_heights = {
{cereal::ControlsState::AlertSize::SMALL, 271}, {cereal::SelfdriveState::AlertSize::SMALL, 271},
{cereal::ControlsState::AlertSize::MID, 420}, {cereal::SelfdriveState::AlertSize::MID, 420},
{cereal::ControlsState::AlertSize::FULL, height()}, {cereal::SelfdriveState::AlertSize::FULL, height()},
}; };
int h = alert_heights[alert.size]; int h = alert_heights[alert.size];
int margin = 40; int margin = 40;
int radius = 30; int radius = 30;
if (alert.size == cereal::ControlsState::AlertSize::FULL) { if (alert.size == cereal::SelfdriveState::AlertSize::FULL) {
margin = 0; margin = 0;
radius = 0; radius = 0;
} }
@ -94,15 +94,15 @@ void OnroadAlerts::paintEvent(QPaintEvent *event) {
const QPoint c = r.center(); const QPoint c = r.center();
p.setPen(QColor(0xff, 0xff, 0xff)); p.setPen(QColor(0xff, 0xff, 0xff));
p.setRenderHint(QPainter::TextAntialiasing); p.setRenderHint(QPainter::TextAntialiasing);
if (alert.size == cereal::ControlsState::AlertSize::SMALL) { if (alert.size == cereal::SelfdriveState::AlertSize::SMALL) {
p.setFont(InterFont(74, QFont::DemiBold)); p.setFont(InterFont(74, QFont::DemiBold));
p.drawText(r, Qt::AlignCenter, alert.text1); p.drawText(r, Qt::AlignCenter, alert.text1);
} else if (alert.size == cereal::ControlsState::AlertSize::MID) { } else if (alert.size == cereal::SelfdriveState::AlertSize::MID) {
p.setFont(InterFont(88, QFont::Bold)); p.setFont(InterFont(88, QFont::Bold));
p.drawText(QRect(0, c.y() - 125, width(), 150), Qt::AlignHCenter | Qt::AlignTop, alert.text1); p.drawText(QRect(0, c.y() - 125, width(), 150), Qt::AlignHCenter | Qt::AlignTop, alert.text1);
p.setFont(InterFont(66)); p.setFont(InterFont(66));
p.drawText(QRect(0, c.y() + 21, width(), 90), Qt::AlignHCenter, alert.text2); p.drawText(QRect(0, c.y() + 21, width(), 90), Qt::AlignHCenter, alert.text2);
} else if (alert.size == cereal::ControlsState::AlertSize::FULL) { } else if (alert.size == cereal::SelfdriveState::AlertSize::FULL) {
bool l = alert.text1.length() > 15; bool l = alert.text1.length() > 15;
p.setFont(InterFont(l ? 132 : 177, QFont::Bold)); p.setFont(InterFont(l ? 132 : 177, QFont::Bold));
p.drawText(QRect(0, r.y() + (l ? 240 : 270), width(), 600), Qt::AlignHCenter | Qt::TextWordWrap, alert.text1); p.drawText(QRect(0, r.y() + (l ? 240 : 270), width(), 600), Qt::AlignHCenter | Qt::TextWordWrap, alert.text1);

@ -17,18 +17,18 @@ protected:
QString text1; QString text1;
QString text2; QString text2;
QString type; QString type;
cereal::ControlsState::AlertSize size; cereal::SelfdriveState::AlertSize size;
cereal::ControlsState::AlertStatus status; cereal::SelfdriveState::AlertStatus status;
bool equal(const Alert &other) const { bool equal(const Alert &other) const {
return text1 == other.text1 && text2 == other.text2 && type == other.type; return text1 == other.text1 && text2 == other.text2 && type == other.type;
} }
}; };
const QMap<cereal::ControlsState::AlertStatus, QColor> alert_colors = { const QMap<cereal::SelfdriveState::AlertStatus, QColor> alert_colors = {
{cereal::ControlsState::AlertStatus::NORMAL, QColor(0x15, 0x15, 0x15, 0xf1)}, {cereal::SelfdriveState::AlertStatus::NORMAL, QColor(0x15, 0x15, 0x15, 0xf1)},
{cereal::ControlsState::AlertStatus::USER_PROMPT, QColor(0xDA, 0x6F, 0x25, 0xf1)}, {cereal::SelfdriveState::AlertStatus::USER_PROMPT, QColor(0xDA, 0x6F, 0x25, 0xf1)},
{cereal::ControlsState::AlertStatus::CRITICAL, QColor(0xC9, 0x22, 0x31, 0xf1)}, {cereal::SelfdriveState::AlertStatus::CRITICAL, QColor(0xC9, 0x22, 0x31, 0xf1)},
}; };
void paintEvent(QPaintEvent*) override; void paintEvent(QPaintEvent*) override;

@ -48,7 +48,7 @@ void AnnotatedCameraWidget::updateState(const UIState &s) {
speed *= is_metric ? MS_TO_KPH : MS_TO_MPH; speed *= is_metric ? MS_TO_KPH : MS_TO_MPH;
speedUnit = is_metric ? tr("km/h") : tr("mph"); speedUnit = is_metric ? tr("km/h") : tr("mph");
hideBottomIcons = (cs.getAlertSize() != cereal::ControlsState::AlertSize::NONE); hideBottomIcons = (sm["selfdriveState"].getSelfdriveState().getAlertSize() != cereal::SelfdriveState::AlertSize::NONE);
status = s.status; status = s.status;
// update engageability/experimental mode button // update engageability/experimental mode button
@ -170,7 +170,7 @@ void AnnotatedCameraWidget::drawLaneLines(QPainter &painter, const UIState *s) {
// paint path // paint path
QLinearGradient bg(0, height(), 0, 0); QLinearGradient bg(0, height(), 0, 0);
if (sm["controlsState"].getControlsState().getExperimentalMode()) { if (sm["selfdriveState"].getSelfdriveState().getExperimentalMode()) {
// The first half of track_vertices are the points for the right side of the path // The first half of track_vertices are the points for the right side of the path
const auto &acceleration = sm["modelV2"].getModelV2().getAcceleration().getX(); const auto &acceleration = sm["modelV2"].getModelV2().getAcceleration().getX();
const int max_len = std::min<int>(scene.track_vertices.length() / 2, acceleration.size()); const int max_len = std::min<int>(scene.track_vertices.length() / 2, acceleration.size());
@ -318,7 +318,7 @@ void AnnotatedCameraWidget::paintGL() {
} else if (v_ego > 15) { } else if (v_ego > 15) {
wide_cam_requested = false; wide_cam_requested = false;
} }
wide_cam_requested = wide_cam_requested && sm["controlsState"].getControlsState().getExperimentalMode(); wide_cam_requested = wide_cam_requested && sm["selfdriveState"].getSelfdriveState().getExperimentalMode();
// for replay of old routes, never go to widecam // for replay of old routes, never go to widecam
wide_cam_requested = wide_cam_requested && s->scene.calibration_wide_valid; wide_cam_requested = wide_cam_requested && s->scene.calibration_wide_valid;
} }

@ -33,7 +33,7 @@ void ExperimentalButton::changeMode() {
} }
void ExperimentalButton::updateState(const UIState &s) { void ExperimentalButton::updateState(const UIState &s) {
const auto cs = (*s.sm)["controlsState"].getControlsState(); const auto cs = (*s.sm)["selfdriveState"].getSelfdriveState();
bool eng = cs.getEngageable() || cs.getEnabled(); bool eng = cs.getEngageable() || cs.getEnabled();
if ((cs.getExperimentalMode() != experimental_mode) || (eng != engageable)) { if ((cs.getExperimentalMode() != experimental_mode) || (eng != engageable)) {
engageable = eng; engageable = eng;

@ -41,10 +41,10 @@ sound_list: dict[int, tuple[str, int | None, float]] = {
} }
def check_controls_timeout_alert(sm): def check_controls_timeout_alert(sm):
controls_missing = time.monotonic() - sm.recv_time['controlsState'] controls_missing = time.monotonic() - sm.recv_time['selfdriveState']
if controls_missing > CONTROLS_TIMEOUT: if controls_missing > CONTROLS_TIMEOUT:
if sm['controlsState'].enabled and (controls_missing - CONTROLS_TIMEOUT) < 10: if sm['selfdriveState'].enabled and (controls_missing - CONTROLS_TIMEOUT) < 10:
return True return True
return False return False
@ -111,8 +111,8 @@ class Soundd:
self.current_sound_frame = 0 self.current_sound_frame = 0
def get_audible_alert(self, sm): def get_audible_alert(self, sm):
if sm.updated['controlsState']: if sm.updated['selfdriveState']:
new_alert = sm['controlsState'].alertSound.raw new_alert = sm['selfdriveState'].alertSound.raw
self.update_alert(new_alert) self.update_alert(new_alert)
elif check_controls_timeout_alert(sm): elif check_controls_timeout_alert(sm):
self.update_alert(AudibleAlert.warningImmediate) self.update_alert(AudibleAlert.warningImmediate)
@ -136,7 +136,7 @@ class Soundd:
# sounddevice must be imported after forking processes # sounddevice must be imported after forking processes
import sounddevice as sd import sounddevice as sd
sm = messaging.SubMaster(['controlsState', 'microphone']) sm = messaging.SubMaster(['selfdriveState', 'microphone'])
with self.get_stream(sd) as stream: with self.get_stream(sd) as stream:
rk = Ratekeeper(20) rk = Ratekeeper(20)

@ -10,14 +10,14 @@ AudibleAlert = car.CarControl.HUDControl.AudibleAlert
class TestSoundd: class TestSoundd:
def test_check_controls_timeout_alert(self): def test_check_controls_timeout_alert(self):
sm = SubMaster(['controlsState']) sm = SubMaster(['selfdriveState'])
pm = PubMaster(['controlsState']) pm = PubMaster(['selfdriveState'])
for _ in range(100): for _ in range(100):
cs = messaging.new_message('controlsState') cs = messaging.new_message('selfdriveState')
cs.controlsState.enabled = True cs.selfdriveState.enabled = True
pm.send("controlsState", cs) pm.send("selfdriveState", cs)
time.sleep(0.01) time.sleep(0.01)

@ -16,6 +16,7 @@ from cereal.messaging import SubMaster, PubMaster
from openpilot.common.params import Params from openpilot.common.params import Params
from openpilot.common.transformations.camera import CameraConfig, DEVICE_CAMERAS from openpilot.common.transformations.camera import CameraConfig, DEVICE_CAMERAS
from openpilot.selfdrive.test.helpers import with_processes from openpilot.selfdrive.test.helpers import with_processes
from openpilot.selfdrive.test.process_replay.migration import migrate_selfdriveState
from openpilot.tools.lib.logreader import LogReader from openpilot.tools.lib.logreader import LogReader
from openpilot.tools.lib.framereader import FrameReader from openpilot.tools.lib.framereader import FrameReader
from openpilot.tools.lib.route import Route from openpilot.tools.lib.route import Route
@ -25,7 +26,7 @@ TEST_ROUTE = "a2a0ccea32023010|2023-07-27--13-01-19"
STREAMS: list[tuple[VisionStreamType, CameraConfig, bytes]] = [] STREAMS: list[tuple[VisionStreamType, CameraConfig, bytes]] = []
DATA: dict[str, capnp.lib.capnp._DynamicStructBuilder] = dict.fromkeys( DATA: dict[str, capnp.lib.capnp._DynamicStructBuilder] = dict.fromkeys(
["deviceState", "pandaStates", "controlsState", "liveCalibration", ["deviceState", "pandaStates", "selfdriveState", "liveCalibration",
"modelV2", "radarState", "driverMonitoringState", "carState", "modelV2", "radarState", "driverMonitoringState", "carState",
"driverStateV2", "roadCameraState", "wideRoadCameraState", "driverCameraState"], None) "driverStateV2", "roadCameraState", "wideRoadCameraState", "driverCameraState"], None)
@ -67,7 +68,7 @@ def setup_onroad(click, pm: PubMaster):
time.sleep(0.05) time.sleep(0.05)
def setup_onroad_wide(click, pm: PubMaster): def setup_onroad_wide(click, pm: PubMaster):
DATA['controlsState'].controlsState.experimentalMode = True DATA['selfdriveState'].selfdriveState.experimentalMode = True
DATA["carState"].carState.vEgo = 1 DATA["carState"].carState.vEgo = 1
setup_onroad(click, pm) setup_onroad(click, pm)
@ -86,26 +87,26 @@ def setup_driver_camera(click, pm: PubMaster):
setup_onroad(click, pm) setup_onroad(click, pm)
DATA['deviceState'].deviceState.started = True DATA['deviceState'].deviceState.started = True
def setup_onroad_alert(click, pm: PubMaster, text1, text2, size, status=log.ControlsState.AlertStatus.normal): def setup_onroad_alert(click, pm: PubMaster, text1, text2, size, status=log.SelfdriveState.AlertStatus.normal):
print(f'setup onroad alert, size: {size}') print(f'setup onroad alert, size: {size}')
setup_onroad(click, pm) setup_onroad(click, pm)
dat = messaging.new_message('controlsState') dat = messaging.new_message('selfdriveState')
cs = dat.controlsState cs = dat.selfdriveState
cs.alertText1 = text1 cs.alertText1 = text1
cs.alertText2 = text2 cs.alertText2 = text2
cs.alertSize = size cs.alertSize = size
cs.alertStatus = status cs.alertStatus = status
cs.alertType = "test_onroad_alert" cs.alertType = "test_onroad_alert"
pm.send('controlsState', dat) pm.send('selfdriveState', dat)
def setup_onroad_alert_small(click, pm: PubMaster): def setup_onroad_alert_small(click, pm: PubMaster):
setup_onroad_alert(click, pm, 'This is a small alert message', '', log.ControlsState.AlertSize.small) setup_onroad_alert(click, pm, 'This is a small alert message', '', log.SelfdriveState.AlertSize.small)
def setup_onroad_alert_mid(click, pm: PubMaster): def setup_onroad_alert_mid(click, pm: PubMaster):
setup_onroad_alert(click, pm, 'Medium Alert', 'This is a medium alert message', log.ControlsState.AlertSize.mid) setup_onroad_alert(click, pm, 'Medium Alert', 'This is a medium alert message', log.SelfdriveState.AlertSize.mid)
def setup_onroad_alert_full(click, pm: PubMaster): def setup_onroad_alert_full(click, pm: PubMaster):
setup_onroad_alert(click, pm, 'Full Alert', 'This is a full alert message', log.ControlsState.AlertSize.full) setup_onroad_alert(click, pm, 'Full Alert', 'This is a full alert message', log.SelfdriveState.AlertSize.full)
CASES = { CASES = {
"homescreen": setup_homescreen, "homescreen": setup_homescreen,
@ -192,7 +193,7 @@ def create_screenshots():
segnum = 2 segnum = 2
lr = LogReader(route.qlog_paths()[segnum]) lr = LogReader(route.qlog_paths()[segnum])
for event in lr: for event in migrate_selfdriveState(lr):
if event.which() in DATA: if event.which() in DATA:
DATA[event.which()] = event.as_builder() DATA[event.which()] = event.as_builder()

@ -217,13 +217,13 @@ void ui_update_params(UIState *s) {
} }
void UIState::updateStatus() { void UIState::updateStatus() {
if (scene.started && sm->updated("controlsState")) { if (scene.started && sm->updated("selfdriveState")) {
auto controls_state = (*sm)["controlsState"].getControlsState(); auto ss = (*sm)["selfdriveState"].getSelfdriveState();
auto state = controls_state.getState(); auto state = ss .getState();
if (state == cereal::ControlsState::OpenpilotState::PRE_ENABLED || state == cereal::ControlsState::OpenpilotState::OVERRIDING) { if (state == cereal::SelfdriveState::OpenpilotState::PRE_ENABLED || state == cereal::SelfdriveState::OpenpilotState::OVERRIDING) {
status = STATUS_OVERRIDE; status = STATUS_OVERRIDE;
} else { } else {
status = controls_state.getEnabled() ? STATUS_ENGAGED : STATUS_DISENGAGED; status = ss.getEnabled() ? STATUS_ENGAGED : STATUS_DISENGAGED;
} }
} }
@ -243,7 +243,7 @@ UIState::UIState(QObject *parent) : QObject(parent) {
sm = std::make_unique<SubMaster>(std::vector<const char*>{ sm = std::make_unique<SubMaster>(std::vector<const char*>{
"modelV2", "controlsState", "liveCalibration", "radarState", "deviceState", "modelV2", "controlsState", "liveCalibration", "radarState", "deviceState",
"pandaStates", "carParams", "driverMonitoringState", "carState", "driverStateV2", "pandaStates", "carParams", "driverMonitoringState", "carState", "driverStateV2",
"wideRoadCameraState", "managerState", "clocks", "wideRoadCameraState", "managerState", "selfdriveState",
}); });
Params params; Params params;

@ -110,7 +110,7 @@ public:
UIState(QObject* parent = 0); UIState(QObject* parent = 0);
void updateStatus(); void updateStatus();
inline bool engaged() const { inline bool engaged() const {
return scene.started && (*sm)["controlsState"].getControlsState().getEnabled(); return scene.started && (*sm)["selfdriveState"].getSelfdriveState().getEnabled();
} }
void setPrimeType(PrimeType type); void setPrimeType(PrimeType type);

@ -279,9 +279,9 @@ void Slider::parseQLog(std::shared_ptr<LogReader> qlog) {
} }
} else if (e.which == cereal::Event::Which::CONTROLS_STATE) { } else if (e.which == cereal::Event::Which::CONTROLS_STATE) {
capnp::FlatArrayMessageReader reader(e.data); capnp::FlatArrayMessageReader reader(e.data);
auto cs = reader.getRoot<cereal::Event>().getControlsState(); auto cs = reader.getRoot<cereal::Event>().getSelfdriveState();
if (cs.getAlertType().size() > 0 && cs.getAlertText1().size() > 0 && if (cs.getAlertType().size() > 0 && cs.getAlertText1().size() > 0 &&
cs.getAlertSize() != cereal::ControlsState::AlertSize::NONE) { cs.getAlertSize() != cereal::SelfdriveState::AlertSize::NONE) {
std::lock_guard lk(mutex); std::lock_guard lk(mutex);
alerts.emplace(e.mono_time, AlertInfo{cs.getAlertStatus(), cs.getAlertText1().cStr(), cs.getAlertText2().cStr()}); alerts.emplace(e.mono_time, AlertInfo{cs.getAlertStatus(), cs.getAlertText1().cStr(), cs.getAlertText2().cStr()});
} }
@ -397,9 +397,9 @@ void InfoLabel::paintEvent(QPaintEvent *event) {
} }
if (alert_info.text1.size() > 0) { if (alert_info.text1.size() > 0) {
QColor color = timeline_colors[(int)TimelineType::AlertInfo]; QColor color = timeline_colors[(int)TimelineType::AlertInfo];
if (alert_info.status == cereal::ControlsState::AlertStatus::USER_PROMPT) { if (alert_info.status == cereal::SelfdriveState::AlertStatus::USER_PROMPT) {
color = timeline_colors[(int)TimelineType::AlertWarning]; color = timeline_colors[(int)TimelineType::AlertWarning];
} else if (alert_info.status == cereal::ControlsState::AlertStatus::CRITICAL) { } else if (alert_info.status == cereal::SelfdriveState::AlertStatus::CRITICAL) {
color = timeline_colors[(int)TimelineType::AlertCritical]; color = timeline_colors[(int)TimelineType::AlertCritical];
} }
color.setAlphaF(0.5); color.setAlphaF(0.5);

@ -18,7 +18,7 @@
#include "tools/replay/logreader.h" #include "tools/replay/logreader.h"
struct AlertInfo { struct AlertInfo {
cereal::ControlsState::AlertStatus status; cereal::SelfdriveState::AlertStatus status;
QString text1; QString text1;
QString text2; QString text2;
}; };

@ -153,15 +153,15 @@ void Replay::buildTimeline() {
uint64_t engaged_begin = 0; uint64_t engaged_begin = 0;
bool engaged = false; bool engaged = false;
auto alert_status = cereal::ControlsState::AlertStatus::NORMAL; auto alert_status = cereal::SelfdriveState::AlertStatus::NORMAL;
auto alert_size = cereal::ControlsState::AlertSize::NONE; auto alert_size = cereal::SelfdriveState::AlertSize::NONE;
uint64_t alert_begin = 0; uint64_t alert_begin = 0;
std::string alert_type; std::string alert_type;
const TimelineType timeline_types[] = { const TimelineType timeline_types[] = {
[(int)cereal::ControlsState::AlertStatus::NORMAL] = TimelineType::AlertInfo, [(int)cereal::SelfdriveState::AlertStatus::NORMAL] = TimelineType::AlertInfo,
[(int)cereal::ControlsState::AlertStatus::USER_PROMPT] = TimelineType::AlertWarning, [(int)cereal::SelfdriveState::AlertStatus::USER_PROMPT] = TimelineType::AlertWarning,
[(int)cereal::ControlsState::AlertStatus::CRITICAL] = TimelineType::AlertCritical, [(int)cereal::SelfdriveState::AlertStatus::CRITICAL] = TimelineType::AlertCritical,
}; };
const auto &route_segments = route_->segments(); const auto &route_segments = route_->segments();
@ -174,7 +174,7 @@ void Replay::buildTimeline() {
if (e.which == cereal::Event::Which::CONTROLS_STATE) { if (e.which == cereal::Event::Which::CONTROLS_STATE) {
capnp::FlatArrayMessageReader reader(e.data); capnp::FlatArrayMessageReader reader(e.data);
auto event = reader.getRoot<cereal::Event>(); auto event = reader.getRoot<cereal::Event>();
auto cs = event.getControlsState(); auto cs = event.getSelfdriveState();
if (engaged != cs.getEnabled()) { if (engaged != cs.getEnabled()) {
if (engaged) { if (engaged) {
@ -185,7 +185,7 @@ void Replay::buildTimeline() {
} }
if (alert_type != cs.getAlertType().cStr() || alert_status != cs.getAlertStatus()) { if (alert_type != cs.getAlertType().cStr() || alert_status != cs.getAlertStatus()) {
if (!alert_type.empty() && alert_size != cereal::ControlsState::AlertSize::NONE) { if (!alert_type.empty() && alert_size != cereal::SelfdriveState::AlertSize::NONE) {
timeline.push_back({toSeconds(alert_begin), toSeconds(e.mono_time), timeline_types[(int)alert_status]}); timeline.push_back({toSeconds(alert_begin), toSeconds(e.mono_time), timeline_types[(int)alert_status]});
} }
alert_begin = e.mono_time; alert_begin = e.mono_time;
@ -202,7 +202,7 @@ void Replay::buildTimeline() {
if (engaged) { if (engaged) {
timeline.push_back({toSeconds(engaged_begin), toSeconds(log->events.back().mono_time), TimelineType::Engaged}); timeline.push_back({toSeconds(engaged_begin), toSeconds(log->events.back().mono_time), TimelineType::Engaged});
} }
if (!alert_type.empty() && alert_size != cereal::ControlsState::AlertSize::NONE) { if (!alert_type.empty() && alert_size != cereal::SelfdriveState::AlertSize::NONE) {
timeline.push_back({toSeconds(alert_begin), toSeconds(log->events.back().mono_time), timeline_types[(int)alert_status]}); timeline.push_back({toSeconds(alert_begin), toSeconds(log->events.back().mono_time), timeline_types[(int)alert_status]});
} }

Loading…
Cancel
Save