mirror of
https://github.com/sunnypilot/sunnypilot.git
synced 2026-06-08 16:04:50 +08:00
Compare commits
9 Commits
test-texts
...
feature/de
| 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, \
|
||||
NoEntryAlert, SoftDisableAlert, UserSoftDisableAlert, ImmediateDisableAlert, EngagementAlert, NormalPermanentAlert, \
|
||||
StartupAlert, AlertCallbackType, wrong_car_mode_alert
|
||||
StartupAlert, AlertCallbackType, AlertCallbackTypeSP, wrong_car_mode_alert
|
||||
|
||||
|
||||
AlertSize = log.SelfdriveState.AlertSize
|
||||
@@ -30,7 +30,7 @@ class Events(EventsBase):
|
||||
super().__init__()
|
||||
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
|
||||
|
||||
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 **********
|
||||
|
||||
EventName.stockFcw: {},
|
||||
@@ -828,7 +828,7 @@ if __name__ == '__main__':
|
||||
for i, alerts in EVENTS.items():
|
||||
for et, alert in alerts.items():
|
||||
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])
|
||||
|
||||
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)
|
||||
|
||||
CruiseHelper.__init__(self, self.CP)
|
||||
CruiseHelper.__init__(self, self.CP, self)
|
||||
|
||||
def update_events(self, CS):
|
||||
"""Compute onroadEvents from carState"""
|
||||
@@ -394,7 +394,7 @@ class SelfdriveD(CruiseHelper):
|
||||
if CS.gearShifter == car.CarState.GearShifter.park and self.mads.enabled:
|
||||
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
|
||||
if self.CP.openpilotLongitudinalControl:
|
||||
@@ -462,9 +462,11 @@ class SelfdriveD(CruiseHelper):
|
||||
pers = LONGITUDINAL_PERSONALITY_MAP[self.personality]
|
||||
callback_args = [self.CP, CS, self.sm, self.is_metric,
|
||||
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_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.process_alerts(self.sm.frame, clear_event_types)
|
||||
@@ -546,6 +548,7 @@ class SelfdriveD(CruiseHelper):
|
||||
|
||||
self.mads.read_params()
|
||||
self.car_events_sp.read_params()
|
||||
CruiseHelper.read_params(self)
|
||||
time.sleep(0.1)
|
||||
|
||||
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});
|
||||
experimental_img = loadPixmap("../assets/img_experimental.svg", {img_size, img_size});
|
||||
#ifndef SUNNYPILOT
|
||||
QObject::connect(this, &QPushButton::clicked, this, &ExperimentalButton::changeMode);
|
||||
#endif
|
||||
}
|
||||
|
||||
void ExperimentalButton::changeMode() {
|
||||
|
||||
@@ -20,13 +20,12 @@ public:
|
||||
|
||||
private:
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
void changeMode();
|
||||
|
||||
Params params;
|
||||
|
||||
protected:
|
||||
virtual void drawButton(QPainter &p);
|
||||
virtual void changeMode();
|
||||
|
||||
Params params;
|
||||
QPixmap engage_img;
|
||||
QPixmap experimental_img;
|
||||
bool experimental_mode;
|
||||
|
||||
@@ -9,9 +9,36 @@
|
||||
|
||||
#include <QPainter>
|
||||
|
||||
#include "selfdrive/ui/qt/util.h"
|
||||
|
||||
ExperimentalButtonSP::ExperimentalButtonSP(QWidget *parent) : ExperimentalButton(parent) {
|
||||
QObject::disconnect(uiState(), &UIState::uiUpdate, this, &ExperimentalButton::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) {
|
||||
|
||||
@@ -18,6 +18,7 @@ public:
|
||||
|
||||
private:
|
||||
void drawButton(QPainter &p) override;
|
||||
void changeMode() override;
|
||||
|
||||
bool dynamic_experimental_control;
|
||||
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 opendbc.car import structs
|
||||
from openpilot.common.params import Params
|
||||
|
||||
ButtonType = car.CarState.ButtonEvent.Type
|
||||
EventNameSP = custom.OnroadEventSP.EventName
|
||||
@@ -16,21 +15,27 @@ DISTANCE_LONG_PRESS = 50
|
||||
|
||||
|
||||
class CruiseHelper:
|
||||
def __init__(self, CP: structs.CarParams):
|
||||
def __init__(self, CP: structs.CarParams, selfdrived):
|
||||
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._experimental_mode = 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 CS.cruiseState.available:
|
||||
self.update_button_frame_counts(CS)
|
||||
|
||||
# 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:
|
||||
for button in self.button_frame_counts:
|
||||
@@ -42,9 +47,23 @@ class CruiseHelper:
|
||||
if button in self.button_frame_counts:
|
||||
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:
|
||||
self._experimental_mode = not experimental_mode
|
||||
self.params.put_bool_nonblocking("ExperimentalMode", self._experimental_mode)
|
||||
events.add(EventNameSP.experimentalModeSwitched)
|
||||
if not self.experimental_mode and not self.dynamic_experimental_control:
|
||||
# State 1 -> 2: Turn on experimental mode only
|
||||
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
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
from cereal import log, car, custom
|
||||
import cereal.messaging as messaging
|
||||
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
|
||||
@@ -19,7 +20,7 @@ class EventsSP(EventsBase):
|
||||
super().__init__()
|
||||
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
|
||||
|
||||
def get_event_name(self, event: int):
|
||||
@@ -29,7 +30,14 @@ class EventsSP(EventsBase):
|
||||
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
|
||||
EventNameSP.lkasEnable: {
|
||||
ET.ENABLE: EngagementAlert(AudibleAlert.engage),
|
||||
@@ -127,7 +135,7 @@ EVENTS_SP: dict[int, dict[str, Alert | AlertCallbackType]] = {
|
||||
},
|
||||
|
||||
EventNameSP.experimentalModeSwitched: {
|
||||
ET.WARNING: NormalPermanentAlert("Experimental Mode Switched", duration=1.5)
|
||||
ET.WARNING: experimental_mode_changed_alert,
|
||||
},
|
||||
|
||||
EventNameSP.wrongCarModeAlertOnly: {
|
||||
|
||||
@@ -81,6 +81,8 @@ class AlertBase(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 **********
|
||||
@@ -166,7 +168,7 @@ class EventsBase:
|
||||
self.events.remove(event_name)
|
||||
|
||||
@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
|
||||
|
||||
@abstractmethod
|
||||
|
||||
Reference in New Issue
Block a user