mirror of
https://github.com/sunnypilot/sunnypilot.git
synced 2026-06-20 01:02:07 +08:00
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e78b361444 | |||
| 74540873bf | |||
| f3ef8ff6ec | |||
| 79a4f25f77 | |||
| efef671a3f | |||
| ded6049301 | |||
| 51f5193ec5 | |||
| 5db7dbee6b | |||
| aab08b8527 |
@@ -11,7 +11,7 @@ from openpilot.selfdrive.locationd.calibrationd import MIN_SPEED_FILTER
|
|||||||
|
|
||||||
from openpilot.sunnypilot.selfdrive.selfdrived.events_base import EventsBase, Priority, ET, Alert, \
|
from openpilot.sunnypilot.selfdrive.selfdrived.events_base import EventsBase, Priority, ET, Alert, \
|
||||||
NoEntryAlert, SoftDisableAlert, UserSoftDisableAlert, ImmediateDisableAlert, EngagementAlert, NormalPermanentAlert, \
|
NoEntryAlert, SoftDisableAlert, UserSoftDisableAlert, ImmediateDisableAlert, EngagementAlert, NormalPermanentAlert, \
|
||||||
StartupAlert, AlertCallbackType, wrong_car_mode_alert
|
StartupAlert, AlertCallbackType, AlertCallbackTypeSP, wrong_car_mode_alert
|
||||||
|
|
||||||
|
|
||||||
AlertSize = log.SelfdriveState.AlertSize
|
AlertSize = log.SelfdriveState.AlertSize
|
||||||
@@ -30,7 +30,7 @@ class Events(EventsBase):
|
|||||||
super().__init__()
|
super().__init__()
|
||||||
self.event_counters = dict.fromkeys(EVENTS.keys(), 0)
|
self.event_counters = dict.fromkeys(EVENTS.keys(), 0)
|
||||||
|
|
||||||
def get_events_mapping(self) -> dict[int, dict[str, Alert | AlertCallbackType]]:
|
def get_events_mapping(self) -> dict[int, dict[str, Alert | AlertCallbackType | AlertCallbackTypeSP]]:
|
||||||
return EVENTS
|
return EVENTS
|
||||||
|
|
||||||
def get_event_name(self, event: int):
|
def get_event_name(self, event: int):
|
||||||
@@ -193,7 +193,7 @@ def personality_changed_alert(CP: car.CarParams, CS: car.CarState, sm: messaging
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
EVENTS: dict[int, dict[str, Alert | AlertCallbackType]] = {
|
EVENTS: dict[int, dict[str, Alert | AlertCallbackType | AlertCallbackTypeSP]] = {
|
||||||
# ********** events with no alerts **********
|
# ********** events with no alerts **********
|
||||||
|
|
||||||
EventName.stockFcw: {},
|
EventName.stockFcw: {},
|
||||||
@@ -828,7 +828,7 @@ if __name__ == '__main__':
|
|||||||
for i, alerts in EVENTS.items():
|
for i, alerts in EVENTS.items():
|
||||||
for et, alert in alerts.items():
|
for et, alert in alerts.items():
|
||||||
if callable(alert):
|
if callable(alert):
|
||||||
alert = alert(CP, CS, sm, False, 1, log.LongitudinalPersonality.standard)
|
alert = alert(CP, CS, sm, False, 1, log.LongitudinalPersonality.standard) # type: ignore[call-arg]
|
||||||
alerts_by_type[et][alert.priority].append(event_names[i])
|
alerts_by_type[et][alert.priority].append(event_names[i])
|
||||||
|
|
||||||
all_alerts: dict[str, list[tuple[Priority, list[str]]]] = {}
|
all_alerts: dict[str, list[tuple[Priority, list[str]]]] = {}
|
||||||
|
|||||||
@@ -155,7 +155,7 @@ class SelfdriveD(CruiseHelper):
|
|||||||
|
|
||||||
self.car_events_sp = CarSpecificEventsSP(self.CP, self.params)
|
self.car_events_sp = CarSpecificEventsSP(self.CP, self.params)
|
||||||
|
|
||||||
CruiseHelper.__init__(self, self.CP)
|
CruiseHelper.__init__(self, self.CP, self)
|
||||||
|
|
||||||
def update_events(self, CS):
|
def update_events(self, CS):
|
||||||
"""Compute onroadEvents from carState"""
|
"""Compute onroadEvents from carState"""
|
||||||
@@ -394,7 +394,7 @@ class SelfdriveD(CruiseHelper):
|
|||||||
if CS.gearShifter == car.CarState.GearShifter.park and self.mads.enabled:
|
if CS.gearShifter == car.CarState.GearShifter.park and self.mads.enabled:
|
||||||
self.events.remove(EventName.canBusMissing)
|
self.events.remove(EventName.canBusMissing)
|
||||||
|
|
||||||
CruiseHelper.update(self, CS, self.events_sp, self.experimental_mode)
|
CruiseHelper.update(self, CS)
|
||||||
|
|
||||||
# decrement personality on distance button press
|
# decrement personality on distance button press
|
||||||
if self.CP.openpilotLongitudinalControl:
|
if self.CP.openpilotLongitudinalControl:
|
||||||
@@ -462,9 +462,11 @@ class SelfdriveD(CruiseHelper):
|
|||||||
pers = LONGITUDINAL_PERSONALITY_MAP[self.personality]
|
pers = LONGITUDINAL_PERSONALITY_MAP[self.personality]
|
||||||
callback_args = [self.CP, CS, self.sm, self.is_metric,
|
callback_args = [self.CP, CS, self.sm, self.is_metric,
|
||||||
self.state_machine.soft_disable_timer, pers]
|
self.state_machine.soft_disable_timer, pers]
|
||||||
|
callback_args_sp = [self.CP, CS, self.sm, self.is_metric,
|
||||||
|
self.state_machine.soft_disable_timer, pers, self.experimental_mode, self.dynamic_experimental_control]
|
||||||
|
|
||||||
alerts = self.events.create_alerts(self.state_machine.current_alert_types, callback_args)
|
alerts = self.events.create_alerts(self.state_machine.current_alert_types, callback_args)
|
||||||
alerts_sp = self.events_sp.create_alerts(self.state_machine.current_alert_types, callback_args)
|
alerts_sp = self.events_sp.create_alerts(self.state_machine.current_alert_types, callback_args_sp)
|
||||||
|
|
||||||
self.AM.add_many(self.sm.frame, alerts + alerts_sp)
|
self.AM.add_many(self.sm.frame, alerts + alerts_sp)
|
||||||
self.AM.process_alerts(self.sm.frame, clear_event_types)
|
self.AM.process_alerts(self.sm.frame, clear_event_types)
|
||||||
@@ -546,6 +548,7 @@ class SelfdriveD(CruiseHelper):
|
|||||||
|
|
||||||
self.mads.read_params()
|
self.mads.read_params()
|
||||||
self.car_events_sp.read_params()
|
self.car_events_sp.read_params()
|
||||||
|
CruiseHelper.read_params(self)
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
|||||||
@@ -21,7 +21,9 @@ ExperimentalButton::ExperimentalButton(QWidget *parent) : experimental_mode(fals
|
|||||||
|
|
||||||
engage_img = loadPixmap("../assets/img_chffr_wheel.png", {img_size, img_size});
|
engage_img = loadPixmap("../assets/img_chffr_wheel.png", {img_size, img_size});
|
||||||
experimental_img = loadPixmap("../assets/img_experimental.svg", {img_size, img_size});
|
experimental_img = loadPixmap("../assets/img_experimental.svg", {img_size, img_size});
|
||||||
|
#ifndef SUNNYPILOT
|
||||||
QObject::connect(this, &QPushButton::clicked, this, &ExperimentalButton::changeMode);
|
QObject::connect(this, &QPushButton::clicked, this, &ExperimentalButton::changeMode);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExperimentalButton::changeMode() {
|
void ExperimentalButton::changeMode() {
|
||||||
|
|||||||
@@ -20,13 +20,12 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void paintEvent(QPaintEvent *event) override;
|
void paintEvent(QPaintEvent *event) override;
|
||||||
void changeMode();
|
|
||||||
|
|
||||||
Params params;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void drawButton(QPainter &p);
|
virtual void drawButton(QPainter &p);
|
||||||
|
virtual void changeMode();
|
||||||
|
|
||||||
|
Params params;
|
||||||
QPixmap engage_img;
|
QPixmap engage_img;
|
||||||
QPixmap experimental_img;
|
QPixmap experimental_img;
|
||||||
bool experimental_mode;
|
bool experimental_mode;
|
||||||
|
|||||||
@@ -9,9 +9,36 @@
|
|||||||
|
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
|
|
||||||
|
#include "selfdrive/ui/qt/util.h"
|
||||||
|
|
||||||
ExperimentalButtonSP::ExperimentalButtonSP(QWidget *parent) : ExperimentalButton(parent) {
|
ExperimentalButtonSP::ExperimentalButtonSP(QWidget *parent) : ExperimentalButton(parent) {
|
||||||
QObject::disconnect(uiState(), &UIState::uiUpdate, this, &ExperimentalButton::updateState);
|
QObject::disconnect(uiState(), &UIState::uiUpdate, this, &ExperimentalButton::updateState);
|
||||||
QObject::connect(uiState(), &UIState::uiUpdate, this, &ExperimentalButtonSP::updateState);
|
QObject::connect(uiState(), &UIState::uiUpdate, this, &ExperimentalButtonSP::updateState);
|
||||||
|
|
||||||
|
QObject::connect(this, &QPushButton::clicked, this, &ExperimentalButtonSP::changeMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExperimentalButtonSP::changeMode() {
|
||||||
|
const auto cp = (*uiState()->sm)["carParams"].getCarParams();
|
||||||
|
bool can_change = hasLongitudinalControl(cp) && params.getBool("ExperimentalModeConfirmed");
|
||||||
|
if (can_change) {
|
||||||
|
bool experimental_mode_new;
|
||||||
|
bool dynamic_experimental_control_new;
|
||||||
|
|
||||||
|
if (!experimental_mode && !dynamic_experimental_control) {
|
||||||
|
experimental_mode_new = true;
|
||||||
|
dynamic_experimental_control_new = false;
|
||||||
|
} else if (experimental_mode && !dynamic_experimental_control) {
|
||||||
|
experimental_mode_new = true;
|
||||||
|
dynamic_experimental_control_new = true;
|
||||||
|
} else {
|
||||||
|
experimental_mode_new = false;
|
||||||
|
dynamic_experimental_control_new = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
params.putBool("ExperimentalMode", experimental_mode_new);
|
||||||
|
params.putBool("DynamicExperimentalControl", dynamic_experimental_control_new);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExperimentalButtonSP::updateState(const UIState &s) {
|
void ExperimentalButtonSP::updateState(const UIState &s) {
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void drawButton(QPainter &p) override;
|
void drawButton(QPainter &p) override;
|
||||||
|
void changeMode() override;
|
||||||
|
|
||||||
bool dynamic_experimental_control;
|
bool dynamic_experimental_control;
|
||||||
int dec_mpc_mode;
|
int dec_mpc_mode;
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ See the LICENSE.md file in the root directory for more details.
|
|||||||
|
|
||||||
from cereal import car, custom
|
from cereal import car, custom
|
||||||
from opendbc.car import structs
|
from opendbc.car import structs
|
||||||
from openpilot.common.params import Params
|
|
||||||
|
|
||||||
ButtonType = car.CarState.ButtonEvent.Type
|
ButtonType = car.CarState.ButtonEvent.Type
|
||||||
EventNameSP = custom.OnroadEventSP.EventName
|
EventNameSP = custom.OnroadEventSP.EventName
|
||||||
@@ -16,21 +15,27 @@ DISTANCE_LONG_PRESS = 50
|
|||||||
|
|
||||||
|
|
||||||
class CruiseHelper:
|
class CruiseHelper:
|
||||||
def __init__(self, CP: structs.CarParams):
|
def __init__(self, CP: structs.CarParams, selfdrived):
|
||||||
self.CP = CP
|
self.CP = CP
|
||||||
self.params = Params()
|
self.selfdrived = selfdrived
|
||||||
|
self.params = self.selfdrived.params
|
||||||
|
self.events_sp = self.selfdrived.events_sp
|
||||||
|
|
||||||
self.button_frame_counts = {ButtonType.gapAdjustCruise: 0}
|
self.button_frame_counts = {ButtonType.gapAdjustCruise: 0}
|
||||||
self._experimental_mode = False
|
|
||||||
self.experimental_mode_switched = False
|
self.experimental_mode_switched = False
|
||||||
|
self.experimental_mode = self.selfdrived.experimental_mode
|
||||||
|
self.dynamic_experimental_control = False
|
||||||
|
|
||||||
def update(self, CS, events, experimental_mode) -> None:
|
def read_params(self):
|
||||||
|
self.dynamic_experimental_control = self.params.get_bool("DynamicExperimentalControl")
|
||||||
|
|
||||||
|
def update(self, CS) -> None:
|
||||||
if self.CP.openpilotLongitudinalControl:
|
if self.CP.openpilotLongitudinalControl:
|
||||||
if CS.cruiseState.available:
|
if CS.cruiseState.available:
|
||||||
self.update_button_frame_counts(CS)
|
self.update_button_frame_counts(CS)
|
||||||
|
|
||||||
# toggle experimental mode once on distance button hold
|
# toggle experimental mode once on distance button hold
|
||||||
self.update_experimental_mode(events, experimental_mode)
|
self.update_experimental_mode()
|
||||||
|
|
||||||
def update_button_frame_counts(self, CS) -> None:
|
def update_button_frame_counts(self, CS) -> None:
|
||||||
for button in self.button_frame_counts:
|
for button in self.button_frame_counts:
|
||||||
@@ -42,9 +47,23 @@ class CruiseHelper:
|
|||||||
if button in self.button_frame_counts:
|
if button in self.button_frame_counts:
|
||||||
self.button_frame_counts[button] = int(button_event.pressed)
|
self.button_frame_counts[button] = int(button_event.pressed)
|
||||||
|
|
||||||
def update_experimental_mode(self, events, experimental_mode) -> None:
|
def update_experimental_mode(self) -> None:
|
||||||
if self.button_frame_counts[ButtonType.gapAdjustCruise] >= DISTANCE_LONG_PRESS and not self.experimental_mode_switched:
|
if self.button_frame_counts[ButtonType.gapAdjustCruise] >= DISTANCE_LONG_PRESS and not self.experimental_mode_switched:
|
||||||
self._experimental_mode = not experimental_mode
|
if not self.experimental_mode and not self.dynamic_experimental_control:
|
||||||
self.params.put_bool_nonblocking("ExperimentalMode", self._experimental_mode)
|
# State 1 -> 2: Turn on experimental mode only
|
||||||
events.add(EventNameSP.experimentalModeSwitched)
|
experimental_mode = True
|
||||||
|
dynamic_experimental_control = False
|
||||||
|
elif self.experimental_mode and not self.dynamic_experimental_control:
|
||||||
|
# State 2 -> 3: Keep experimental mode on, turn on DEC
|
||||||
|
experimental_mode = True
|
||||||
|
dynamic_experimental_control = True
|
||||||
|
else:
|
||||||
|
# State 3 -> 1: Turn everything off, so back to chill mode
|
||||||
|
experimental_mode = False
|
||||||
|
dynamic_experimental_control = False
|
||||||
|
|
||||||
|
self.params.put_bool_nonblocking("ExperimentalMode", experimental_mode)
|
||||||
|
self.params.put_bool_nonblocking("DynamicExperimentalControl", dynamic_experimental_control)
|
||||||
|
|
||||||
|
self.events_sp.add(EventNameSP.experimentalModeSwitched)
|
||||||
self.experimental_mode_switched = True
|
self.experimental_mode_switched = True
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
from cereal import log, car, custom
|
from cereal import log, car, custom
|
||||||
|
import cereal.messaging as messaging
|
||||||
from openpilot.sunnypilot.selfdrive.selfdrived.events_base import EventsBase, Priority, ET, Alert, \
|
from openpilot.sunnypilot.selfdrive.selfdrived.events_base import EventsBase, Priority, ET, Alert, \
|
||||||
NoEntryAlert, ImmediateDisableAlert, EngagementAlert, NormalPermanentAlert, AlertCallbackType, wrong_car_mode_alert
|
NoEntryAlert, ImmediateDisableAlert, EngagementAlert, NormalPermanentAlert, AlertCallbackType, AlertCallbackTypeSP, wrong_car_mode_alert
|
||||||
|
|
||||||
|
|
||||||
AlertSize = log.SelfdriveState.AlertSize
|
AlertSize = log.SelfdriveState.AlertSize
|
||||||
@@ -19,7 +20,7 @@ class EventsSP(EventsBase):
|
|||||||
super().__init__()
|
super().__init__()
|
||||||
self.event_counters = dict.fromkeys(EVENTS_SP.keys(), 0)
|
self.event_counters = dict.fromkeys(EVENTS_SP.keys(), 0)
|
||||||
|
|
||||||
def get_events_mapping(self) -> dict[int, dict[str, Alert | AlertCallbackType]]:
|
def get_events_mapping(self) -> dict[int, dict[str, Alert | AlertCallbackType | AlertCallbackTypeSP]]:
|
||||||
return EVENTS_SP
|
return EVENTS_SP
|
||||||
|
|
||||||
def get_event_name(self, event: int):
|
def get_event_name(self, event: int):
|
||||||
@@ -29,7 +30,14 @@ class EventsSP(EventsBase):
|
|||||||
return custom.OnroadEventSP.Event
|
return custom.OnroadEventSP.Event
|
||||||
|
|
||||||
|
|
||||||
EVENTS_SP: dict[int, dict[str, Alert | AlertCallbackType]] = {
|
def experimental_mode_changed_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.SubMaster, metric: bool,
|
||||||
|
soft_disable_time: int, personality, experimental_mode, dynamic_experimental_control) -> Alert:
|
||||||
|
exp_mode_str = "ON" if experimental_mode else "OFF"
|
||||||
|
dec_str = "ON" if dynamic_experimental_control else "OFF"
|
||||||
|
return NormalPermanentAlert(f"Experimental Mode: {exp_mode_str}\nDynamic Experimental Control: {dec_str}", duration=1.5)
|
||||||
|
|
||||||
|
|
||||||
|
EVENTS_SP: dict[int, dict[str, Alert | AlertCallbackType | AlertCallbackTypeSP]] = {
|
||||||
# sunnypilot
|
# sunnypilot
|
||||||
EventNameSP.lkasEnable: {
|
EventNameSP.lkasEnable: {
|
||||||
ET.ENABLE: EngagementAlert(AudibleAlert.engage),
|
ET.ENABLE: EngagementAlert(AudibleAlert.engage),
|
||||||
@@ -127,7 +135,7 @@ EVENTS_SP: dict[int, dict[str, Alert | AlertCallbackType]] = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
EventNameSP.experimentalModeSwitched: {
|
EventNameSP.experimentalModeSwitched: {
|
||||||
ET.WARNING: NormalPermanentAlert("Experimental Mode Switched", duration=1.5)
|
ET.WARNING: experimental_mode_changed_alert,
|
||||||
},
|
},
|
||||||
|
|
||||||
EventNameSP.wrongCarModeAlertOnly: {
|
EventNameSP.wrongCarModeAlertOnly: {
|
||||||
|
|||||||
@@ -81,6 +81,8 @@ class AlertBase(Alert):
|
|||||||
|
|
||||||
|
|
||||||
AlertCallbackType = Callable[[car.CarParams, car.CarState, messaging.SubMaster, bool, int, log.ControlsState], Alert]
|
AlertCallbackType = Callable[[car.CarParams, car.CarState, messaging.SubMaster, bool, int, log.ControlsState], Alert]
|
||||||
|
AlertCallbackTypeSP = Callable[[car.CarParams, car.CarState, messaging.SubMaster, bool, int, log.ControlsState,
|
||||||
|
bool, bool], Alert]
|
||||||
|
|
||||||
|
|
||||||
# ********** alert callback functions **********
|
# ********** alert callback functions **********
|
||||||
@@ -166,7 +168,7 @@ class EventsBase:
|
|||||||
self.events.remove(event_name)
|
self.events.remove(event_name)
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def get_events_mapping(self) -> dict[int, dict[str, Alert | AlertCallbackType]]:
|
def get_events_mapping(self) -> dict[int, dict[str, Alert | AlertCallbackType | AlertCallbackTypeSP]]:
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
|
|||||||
Reference in New Issue
Block a user