mirror of
https://github.com/sunnypilot/sunnypilot.git
synced 2026-02-18 22:23:56 +08:00
controlsd: split out state/alerts into selfdriveState (#33421)
* setup selfdriveState * little more * update refs * migration * all too slow
This commit is contained in:
@@ -684,18 +684,53 @@ struct LiveTracks {
|
||||
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 {
|
||||
cumLagMs @15 :Float32;
|
||||
startMonoTime @48 :UInt64;
|
||||
longitudinalPlanMonoTime @28 :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;
|
||||
vTargetLead @3 :Float32;
|
||||
vCruise @22 :Float32; # actual set speed
|
||||
@@ -706,18 +741,21 @@ struct ControlsState @0x97ff69c53601abf1 {
|
||||
aTarget @35 :Float32;
|
||||
curvature @37 :Float32; # path curvature from vehicle model
|
||||
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;
|
||||
alertText2 @25 :Text;
|
||||
alertStatus @38 :AlertStatus;
|
||||
alertSize @39 :AlertSize;
|
||||
alertStatus @38 :SelfdriveState.AlertStatus;
|
||||
alertSize @39 :SelfdriveState.AlertSize;
|
||||
alertType @44 :Text;
|
||||
alertSound @56 :Car.CarControl.HUDControl.AudibleAlert;
|
||||
engageable @41 :Bool; # can OP be engaged?
|
||||
|
||||
cumLagMs @15 :Float32;
|
||||
forceDecel @51 :Bool;
|
||||
state @31 :SelfdriveState.OpenpilotState;
|
||||
enabled @19 :Bool;
|
||||
active @36 :Bool;
|
||||
experimentalMode @64 :Bool;
|
||||
personality @66 :LongitudinalPersonality;
|
||||
|
||||
lateralControlState :union {
|
||||
indiState @52 :LateralINDIState;
|
||||
@@ -730,27 +768,6 @@ struct ControlsState @0x97ff69c53601abf1 {
|
||||
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 {
|
||||
active @0 :Bool;
|
||||
steeringAngleDeg @1 :Float32;
|
||||
@@ -2300,6 +2317,7 @@ struct Event {
|
||||
gpsNMEA @3 :GPSNMEAData;
|
||||
can @5 :List(CanData);
|
||||
controlsState @7 :ControlsState;
|
||||
selfdriveState @130 :SelfdriveState;
|
||||
gyroscope @99 :SensorEventData;
|
||||
gyroscope2 @100 :SensorEventData;
|
||||
accelerometer @98 :SensorEventData;
|
||||
|
||||
@@ -24,6 +24,7 @@ _services: dict[str, tuple] = {
|
||||
"deviceState": (True, 2., 1),
|
||||
"can": (True, 100., 2053), # decimation gives ~3 msgs in a full segment
|
||||
"controlsState": (True, 100., 10),
|
||||
"selfdriveState": (True, 100., 10),
|
||||
"pandaStates": (True, 10., 1),
|
||||
"peripheralState": (True, 2., 1),
|
||||
"radarState": (True, 20., 5),
|
||||
|
||||
@@ -44,7 +44,7 @@ TESTING_CLOSET = "TESTING_CLOSET" in os.environ
|
||||
IGNORE_PROCESSES = {"loggerd", "encoderd", "statsd"}
|
||||
|
||||
ThermalStatus = log.DeviceState.ThermalStatus
|
||||
State = log.ControlsState.OpenpilotState
|
||||
State = log.SelfdriveState.OpenpilotState
|
||||
PandaType = log.PandaState.PandaType
|
||||
Desire = log.Desire
|
||||
LaneChangeState = log.LaneChangeState
|
||||
@@ -78,7 +78,7 @@ class Controls:
|
||||
self.branch = get_short_branch()
|
||||
|
||||
# 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_packets = [self.gps_location_service]
|
||||
@@ -781,6 +781,25 @@ class Controls:
|
||||
|
||||
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
|
||||
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))
|
||||
|
||||
@@ -12,8 +12,8 @@ from openpilot.common.git import get_short_branch
|
||||
from openpilot.common.realtime import DT_CTRL
|
||||
from openpilot.selfdrive.locationd.calibrationd import MIN_SPEED_FILTER
|
||||
|
||||
AlertSize = log.ControlsState.AlertSize
|
||||
AlertStatus = log.ControlsState.AlertStatus
|
||||
AlertSize = log.SelfdriveState.AlertSize
|
||||
AlertStatus = log.SelfdriveState.AlertStatus
|
||||
VisualAlert = car.CarControl.HUDControl.VisualAlert
|
||||
AudibleAlert = car.CarControl.HUDControl.AudibleAlert
|
||||
EventName = car.CarEvent.EventName
|
||||
@@ -110,8 +110,8 @@ class Alert:
|
||||
def __init__(self,
|
||||
alert_text_1: str,
|
||||
alert_text_2: str,
|
||||
alert_status: log.ControlsState.AlertStatus,
|
||||
alert_size: log.ControlsState.AlertSize,
|
||||
alert_status: log.SelfdriveState.AlertStatus,
|
||||
alert_size: log.SelfdriveState.AlertSize,
|
||||
priority: Priority,
|
||||
visual_alert: car.CarControl.HUDControl.VisualAlert,
|
||||
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.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")
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ CX5_FW_VERSIONS = [
|
||||
(EventName.startupMaster, TOYOTA.TOYOTA_COROLLA, COROLLA_FW_VERSIONS_FUZZY, "toyota"),
|
||||
])
|
||||
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'])
|
||||
|
||||
params = Params()
|
||||
@@ -114,7 +114,7 @@ def test_startup_alert(expected_event, car_model, fw_versions, brand):
|
||||
|
||||
ctrls = messaging.drain_sock(controls_sock)
|
||||
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}"
|
||||
break
|
||||
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, \
|
||||
AudibleAlert, EVENTS
|
||||
|
||||
State = log.ControlsState.OpenpilotState
|
||||
State = log.SelfdriveState.OpenpilotState
|
||||
|
||||
# The event types that maintain the current state
|
||||
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',
|
||||
'managerState'] + cameras)
|
||||
|
||||
pm = messaging.PubMaster(['controlsState', 'pandaStates', 'deviceState'])
|
||||
pm = messaging.PubMaster(['selfdriveState', 'pandaStates', 'deviceState'])
|
||||
|
||||
events = Events()
|
||||
AM = AlertManager()
|
||||
@@ -100,17 +100,17 @@ def cycle_alerts(duration=200, is_metric=False):
|
||||
print(alert)
|
||||
for _ in range(duration):
|
||||
dat = messaging.new_message()
|
||||
dat.init('controlsState')
|
||||
dat.controlsState.enabled = False
|
||||
dat.init('selfdriveState')
|
||||
dat.selfdriveState.enabled = False
|
||||
|
||||
if alert:
|
||||
dat.controlsState.alertText1 = alert.alert_text_1
|
||||
dat.controlsState.alertText2 = alert.alert_text_2
|
||||
dat.controlsState.alertSize = alert.alert_size
|
||||
dat.controlsState.alertStatus = alert.alert_status
|
||||
dat.controlsState.alertType = alert.alert_type
|
||||
dat.controlsState.alertSound = alert.audible_alert
|
||||
pm.send('controlsState', dat)
|
||||
dat.selfdriveState.alertText1 = alert.alert_text_1
|
||||
dat.selfdriveState.alertText2 = alert.alert_text_2
|
||||
dat.selfdriveState.alertSize = alert.alert_size
|
||||
dat.selfdriveState.alertStatus = alert.alert_status
|
||||
dat.selfdriveState.alertType = alert.alert_type
|
||||
dat.selfdriveState.alertSound = alert.audible_alert
|
||||
pm.send('selfdriveState', dat)
|
||||
|
||||
dat = messaging.new_message()
|
||||
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_deviceState(msgs)
|
||||
msgs = migrate_carOutput(msgs)
|
||||
msgs = migrate_selfdriveState(msgs)
|
||||
if manager_states:
|
||||
msgs = migrate_managerState(msgs)
|
||||
if panda_states:
|
||||
@@ -26,6 +27,23 @@ def migrate_all(lr, old_logtime=False, manager_states=False, panda_states=False,
|
||||
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):
|
||||
all_msgs = []
|
||||
for msg in lr:
|
||||
|
||||
@@ -489,7 +489,7 @@ CONFIGS = [
|
||||
"testJoystick", "liveTorqueParameters", "accelerometer", "gyroscope", "carOutput",
|
||||
"gpsLocationExternal", "gpsLocation",
|
||||
],
|
||||
subs=["controlsState", "carControl", "onroadEvents"],
|
||||
subs=["selfdriveState", "controlsState", "carControl", "onroadEvents"],
|
||||
ignore=["logMonoTime", "controlsState.startMonoTime", "controlsState.cumLagMs"],
|
||||
config_callback=controlsd_config_callback,
|
||||
init_callback=get_car_params_callback,
|
||||
|
||||
@@ -1 +1 @@
|
||||
a8b4c81ec1df5135ae448c8273ce14c1a98b1bfc
|
||||
ab4983de4477d648e5c36447debfd6735dfc466f
|
||||
@@ -416,8 +416,8 @@ class TestOnroad:
|
||||
startup_alert = None
|
||||
for msg in self.lrs[0]:
|
||||
# can't use onroadEvents because the first msg can be dropped while loggerd is starting up
|
||||
if msg.which() == "controlsState":
|
||||
startup_alert = msg.controlsState.alertText1
|
||||
if msg.which() == "selfdriveState":
|
||||
startup_alert = msg.selfdriveState.alertText1
|
||||
break
|
||||
expected = EVENTS[car.CarEvent.EventName.startup][ET.PERMANENT].alert_text_1
|
||||
assert startup_alert == expected, "wrong startup alert"
|
||||
|
||||
@@ -111,8 +111,8 @@ TogglesPanel::TogglesPanel(SettingsWindow *parent) : ListWidget(parent) {
|
||||
void TogglesPanel::updateState(const UIState &s) {
|
||||
const SubMaster &sm = *(s.sm);
|
||||
|
||||
if (sm.updated("controlsState")) {
|
||||
auto personality = sm["controlsState"].getControlsState().getPersonality();
|
||||
if (sm.updated("selfdriveState")) {
|
||||
auto personality = sm["selfdriveState"].getSelfdriveState().getPersonality();
|
||||
if (personality != s.scene.personality && s.scene.started && isVisible()) {
|
||||
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) {
|
||||
const cereal::ControlsState::Reader &cs = sm["controlsState"].getControlsState();
|
||||
const uint64_t controls_frame = sm.rcv_frame("controlsState");
|
||||
const cereal::SelfdriveState::Reader &cs = sm["selfdriveState"].getSelfdriveState();
|
||||
const uint64_t controls_frame = sm.rcv_frame("selfdriveState");
|
||||
|
||||
Alert a = {};
|
||||
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()};
|
||||
}
|
||||
|
||||
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_missing = (nanos_since_boot() - sm.rcv_time("controlsState")) / 1e9;
|
||||
const int controls_missing = (nanos_since_boot() - sm.rcv_time("selfdriveState")) / 1e9;
|
||||
|
||||
// Handle controls timeout
|
||||
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"),
|
||||
"controlsWaiting", cereal::ControlsState::AlertSize::MID,
|
||||
cereal::ControlsState::AlertStatus::NORMAL};
|
||||
"controlsWaiting", cereal::SelfdriveState::AlertSize::MID,
|
||||
cereal::SelfdriveState::AlertStatus::NORMAL};
|
||||
} else if (controls_missing > CONTROLS_TIMEOUT && !Hardware::PC()) {
|
||||
// car is started, but controls is lagging or died
|
||||
if (cs.getEnabled() && (controls_missing - CONTROLS_TIMEOUT) < 10) {
|
||||
a = {tr("TAKE CONTROL IMMEDIATELY"), tr("Controls Unresponsive"),
|
||||
"controlsUnresponsive", cereal::ControlsState::AlertSize::FULL,
|
||||
cereal::ControlsState::AlertStatus::CRITICAL};
|
||||
"controlsUnresponsive", cereal::SelfdriveState::AlertSize::FULL,
|
||||
cereal::SelfdriveState::AlertStatus::CRITICAL};
|
||||
} else {
|
||||
a = {tr("Controls Unresponsive"), tr("Reboot Device"),
|
||||
"controlsUnresponsivePermanent", cereal::ControlsState::AlertSize::MID,
|
||||
cereal::ControlsState::AlertStatus::NORMAL};
|
||||
"controlsUnresponsivePermanent", cereal::SelfdriveState::AlertSize::MID,
|
||||
cereal::SelfdriveState::AlertStatus::NORMAL};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -55,19 +55,19 @@ OnroadAlerts::Alert OnroadAlerts::getAlert(const SubMaster &sm, uint64_t started
|
||||
}
|
||||
|
||||
void OnroadAlerts::paintEvent(QPaintEvent *event) {
|
||||
if (alert.size == cereal::ControlsState::AlertSize::NONE) {
|
||||
if (alert.size == cereal::SelfdriveState::AlertSize::NONE) {
|
||||
return;
|
||||
}
|
||||
static std::map<cereal::ControlsState::AlertSize, const int> alert_heights = {
|
||||
{cereal::ControlsState::AlertSize::SMALL, 271},
|
||||
{cereal::ControlsState::AlertSize::MID, 420},
|
||||
{cereal::ControlsState::AlertSize::FULL, height()},
|
||||
static std::map<cereal::SelfdriveState::AlertSize, const int> alert_heights = {
|
||||
{cereal::SelfdriveState::AlertSize::SMALL, 271},
|
||||
{cereal::SelfdriveState::AlertSize::MID, 420},
|
||||
{cereal::SelfdriveState::AlertSize::FULL, height()},
|
||||
};
|
||||
int h = alert_heights[alert.size];
|
||||
|
||||
int margin = 40;
|
||||
int radius = 30;
|
||||
if (alert.size == cereal::ControlsState::AlertSize::FULL) {
|
||||
if (alert.size == cereal::SelfdriveState::AlertSize::FULL) {
|
||||
margin = 0;
|
||||
radius = 0;
|
||||
}
|
||||
@@ -94,15 +94,15 @@ void OnroadAlerts::paintEvent(QPaintEvent *event) {
|
||||
const QPoint c = r.center();
|
||||
p.setPen(QColor(0xff, 0xff, 0xff));
|
||||
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.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.drawText(QRect(0, c.y() - 125, width(), 150), Qt::AlignHCenter | Qt::AlignTop, alert.text1);
|
||||
p.setFont(InterFont(66));
|
||||
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;
|
||||
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);
|
||||
|
||||
@@ -17,18 +17,18 @@ protected:
|
||||
QString text1;
|
||||
QString text2;
|
||||
QString type;
|
||||
cereal::ControlsState::AlertSize size;
|
||||
cereal::ControlsState::AlertStatus status;
|
||||
cereal::SelfdriveState::AlertSize size;
|
||||
cereal::SelfdriveState::AlertStatus status;
|
||||
|
||||
bool equal(const Alert &other) const {
|
||||
return text1 == other.text1 && text2 == other.text2 && type == other.type;
|
||||
}
|
||||
};
|
||||
|
||||
const QMap<cereal::ControlsState::AlertStatus, QColor> alert_colors = {
|
||||
{cereal::ControlsState::AlertStatus::NORMAL, QColor(0x15, 0x15, 0x15, 0xf1)},
|
||||
{cereal::ControlsState::AlertStatus::USER_PROMPT, QColor(0xDA, 0x6F, 0x25, 0xf1)},
|
||||
{cereal::ControlsState::AlertStatus::CRITICAL, QColor(0xC9, 0x22, 0x31, 0xf1)},
|
||||
const QMap<cereal::SelfdriveState::AlertStatus, QColor> alert_colors = {
|
||||
{cereal::SelfdriveState::AlertStatus::NORMAL, QColor(0x15, 0x15, 0x15, 0xf1)},
|
||||
{cereal::SelfdriveState::AlertStatus::USER_PROMPT, QColor(0xDA, 0x6F, 0x25, 0xf1)},
|
||||
{cereal::SelfdriveState::AlertStatus::CRITICAL, QColor(0xC9, 0x22, 0x31, 0xf1)},
|
||||
};
|
||||
|
||||
void paintEvent(QPaintEvent*) override;
|
||||
|
||||
@@ -48,7 +48,7 @@ void AnnotatedCameraWidget::updateState(const UIState &s) {
|
||||
speed *= is_metric ? MS_TO_KPH : MS_TO_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;
|
||||
|
||||
// update engageability/experimental mode button
|
||||
@@ -170,7 +170,7 @@ void AnnotatedCameraWidget::drawLaneLines(QPainter &painter, const UIState *s) {
|
||||
|
||||
// paint path
|
||||
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
|
||||
const auto &acceleration = sm["modelV2"].getModelV2().getAcceleration().getX();
|
||||
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) {
|
||||
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
|
||||
wide_cam_requested = wide_cam_requested && s->scene.calibration_wide_valid;
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ void ExperimentalButton::changeMode() {
|
||||
}
|
||||
|
||||
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();
|
||||
if ((cs.getExperimentalMode() != experimental_mode) || (eng != engageable)) {
|
||||
engageable = eng;
|
||||
|
||||
@@ -41,10 +41,10 @@ sound_list: dict[int, tuple[str, int | None, float]] = {
|
||||
}
|
||||
|
||||
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 sm['controlsState'].enabled and (controls_missing - CONTROLS_TIMEOUT) < 10:
|
||||
if sm['selfdriveState'].enabled and (controls_missing - CONTROLS_TIMEOUT) < 10:
|
||||
return True
|
||||
|
||||
return False
|
||||
@@ -111,8 +111,8 @@ class Soundd:
|
||||
self.current_sound_frame = 0
|
||||
|
||||
def get_audible_alert(self, sm):
|
||||
if sm.updated['controlsState']:
|
||||
new_alert = sm['controlsState'].alertSound.raw
|
||||
if sm.updated['selfdriveState']:
|
||||
new_alert = sm['selfdriveState'].alertSound.raw
|
||||
self.update_alert(new_alert)
|
||||
elif check_controls_timeout_alert(sm):
|
||||
self.update_alert(AudibleAlert.warningImmediate)
|
||||
@@ -136,7 +136,7 @@ class Soundd:
|
||||
# sounddevice must be imported after forking processes
|
||||
import sounddevice as sd
|
||||
|
||||
sm = messaging.SubMaster(['controlsState', 'microphone'])
|
||||
sm = messaging.SubMaster(['selfdriveState', 'microphone'])
|
||||
|
||||
with self.get_stream(sd) as stream:
|
||||
rk = Ratekeeper(20)
|
||||
|
||||
@@ -10,14 +10,14 @@ AudibleAlert = car.CarControl.HUDControl.AudibleAlert
|
||||
|
||||
class TestSoundd:
|
||||
def test_check_controls_timeout_alert(self):
|
||||
sm = SubMaster(['controlsState'])
|
||||
pm = PubMaster(['controlsState'])
|
||||
sm = SubMaster(['selfdriveState'])
|
||||
pm = PubMaster(['selfdriveState'])
|
||||
|
||||
for _ in range(100):
|
||||
cs = messaging.new_message('controlsState')
|
||||
cs.controlsState.enabled = True
|
||||
cs = messaging.new_message('selfdriveState')
|
||||
cs.selfdriveState.enabled = True
|
||||
|
||||
pm.send("controlsState", cs)
|
||||
pm.send("selfdriveState", cs)
|
||||
|
||||
time.sleep(0.01)
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ from cereal.messaging import SubMaster, PubMaster
|
||||
from openpilot.common.params import Params
|
||||
from openpilot.common.transformations.camera import CameraConfig, DEVICE_CAMERAS
|
||||
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.framereader import FrameReader
|
||||
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]] = []
|
||||
DATA: dict[str, capnp.lib.capnp._DynamicStructBuilder] = dict.fromkeys(
|
||||
["deviceState", "pandaStates", "controlsState", "liveCalibration",
|
||||
["deviceState", "pandaStates", "selfdriveState", "liveCalibration",
|
||||
"modelV2", "radarState", "driverMonitoringState", "carState",
|
||||
"driverStateV2", "roadCameraState", "wideRoadCameraState", "driverCameraState"], None)
|
||||
|
||||
@@ -67,7 +68,7 @@ def setup_onroad(click, pm: PubMaster):
|
||||
time.sleep(0.05)
|
||||
|
||||
def setup_onroad_wide(click, pm: PubMaster):
|
||||
DATA['controlsState'].controlsState.experimentalMode = True
|
||||
DATA['selfdriveState'].selfdriveState.experimentalMode = True
|
||||
DATA["carState"].carState.vEgo = 1
|
||||
setup_onroad(click, pm)
|
||||
|
||||
@@ -86,26 +87,26 @@ def setup_driver_camera(click, pm: PubMaster):
|
||||
setup_onroad(click, pm)
|
||||
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}')
|
||||
setup_onroad(click, pm)
|
||||
dat = messaging.new_message('controlsState')
|
||||
cs = dat.controlsState
|
||||
dat = messaging.new_message('selfdriveState')
|
||||
cs = dat.selfdriveState
|
||||
cs.alertText1 = text1
|
||||
cs.alertText2 = text2
|
||||
cs.alertSize = size
|
||||
cs.alertStatus = status
|
||||
cs.alertType = "test_onroad_alert"
|
||||
pm.send('controlsState', dat)
|
||||
pm.send('selfdriveState', dat)
|
||||
|
||||
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):
|
||||
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):
|
||||
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 = {
|
||||
"homescreen": setup_homescreen,
|
||||
@@ -192,7 +193,7 @@ def create_screenshots():
|
||||
|
||||
segnum = 2
|
||||
lr = LogReader(route.qlog_paths()[segnum])
|
||||
for event in lr:
|
||||
for event in migrate_selfdriveState(lr):
|
||||
if event.which() in DATA:
|
||||
DATA[event.which()] = event.as_builder()
|
||||
|
||||
|
||||
@@ -217,13 +217,13 @@ void ui_update_params(UIState *s) {
|
||||
}
|
||||
|
||||
void UIState::updateStatus() {
|
||||
if (scene.started && sm->updated("controlsState")) {
|
||||
auto controls_state = (*sm)["controlsState"].getControlsState();
|
||||
auto state = controls_state.getState();
|
||||
if (state == cereal::ControlsState::OpenpilotState::PRE_ENABLED || state == cereal::ControlsState::OpenpilotState::OVERRIDING) {
|
||||
if (scene.started && sm->updated("selfdriveState")) {
|
||||
auto ss = (*sm)["selfdriveState"].getSelfdriveState();
|
||||
auto state = ss .getState();
|
||||
if (state == cereal::SelfdriveState::OpenpilotState::PRE_ENABLED || state == cereal::SelfdriveState::OpenpilotState::OVERRIDING) {
|
||||
status = STATUS_OVERRIDE;
|
||||
} 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*>{
|
||||
"modelV2", "controlsState", "liveCalibration", "radarState", "deviceState",
|
||||
"pandaStates", "carParams", "driverMonitoringState", "carState", "driverStateV2",
|
||||
"wideRoadCameraState", "managerState", "clocks",
|
||||
"wideRoadCameraState", "managerState", "selfdriveState",
|
||||
});
|
||||
|
||||
Params params;
|
||||
|
||||
@@ -110,7 +110,7 @@ public:
|
||||
UIState(QObject* parent = 0);
|
||||
void updateStatus();
|
||||
inline bool engaged() const {
|
||||
return scene.started && (*sm)["controlsState"].getControlsState().getEnabled();
|
||||
return scene.started && (*sm)["selfdriveState"].getSelfdriveState().getEnabled();
|
||||
}
|
||||
|
||||
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) {
|
||||
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 &&
|
||||
cs.getAlertSize() != cereal::ControlsState::AlertSize::NONE) {
|
||||
cs.getAlertSize() != cereal::SelfdriveState::AlertSize::NONE) {
|
||||
std::lock_guard lk(mutex);
|
||||
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) {
|
||||
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];
|
||||
} 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.setAlphaF(0.5);
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#include "tools/replay/logreader.h"
|
||||
|
||||
struct AlertInfo {
|
||||
cereal::ControlsState::AlertStatus status;
|
||||
cereal::SelfdriveState::AlertStatus status;
|
||||
QString text1;
|
||||
QString text2;
|
||||
};
|
||||
|
||||
@@ -153,15 +153,15 @@ void Replay::buildTimeline() {
|
||||
uint64_t engaged_begin = 0;
|
||||
bool engaged = false;
|
||||
|
||||
auto alert_status = cereal::ControlsState::AlertStatus::NORMAL;
|
||||
auto alert_size = cereal::ControlsState::AlertSize::NONE;
|
||||
auto alert_status = cereal::SelfdriveState::AlertStatus::NORMAL;
|
||||
auto alert_size = cereal::SelfdriveState::AlertSize::NONE;
|
||||
uint64_t alert_begin = 0;
|
||||
std::string alert_type;
|
||||
|
||||
const TimelineType timeline_types[] = {
|
||||
[(int)cereal::ControlsState::AlertStatus::NORMAL] = TimelineType::AlertInfo,
|
||||
[(int)cereal::ControlsState::AlertStatus::USER_PROMPT] = TimelineType::AlertWarning,
|
||||
[(int)cereal::ControlsState::AlertStatus::CRITICAL] = TimelineType::AlertCritical,
|
||||
[(int)cereal::SelfdriveState::AlertStatus::NORMAL] = TimelineType::AlertInfo,
|
||||
[(int)cereal::SelfdriveState::AlertStatus::USER_PROMPT] = TimelineType::AlertWarning,
|
||||
[(int)cereal::SelfdriveState::AlertStatus::CRITICAL] = TimelineType::AlertCritical,
|
||||
};
|
||||
|
||||
const auto &route_segments = route_->segments();
|
||||
@@ -174,7 +174,7 @@ void Replay::buildTimeline() {
|
||||
if (e.which == cereal::Event::Which::CONTROLS_STATE) {
|
||||
capnp::FlatArrayMessageReader reader(e.data);
|
||||
auto event = reader.getRoot<cereal::Event>();
|
||||
auto cs = event.getControlsState();
|
||||
auto cs = event.getSelfdriveState();
|
||||
|
||||
if (engaged != cs.getEnabled()) {
|
||||
if (engaged) {
|
||||
@@ -185,7 +185,7 @@ void Replay::buildTimeline() {
|
||||
}
|
||||
|
||||
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]});
|
||||
}
|
||||
alert_begin = e.mono_time;
|
||||
@@ -202,7 +202,7 @@ void Replay::buildTimeline() {
|
||||
if (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]});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user