MADS: prerequisite for partial platform support (#938)

* MADS: prerequisite for partial platform support

* ui: support specific button enabled selections for `ButtonParamControlSP`

Replaced setDisabledSelectedButton with setEnableSelectedButtons for improved flexibility. The new implementation allows enabling multiple buttons based on a given list and maintains clarity in handling button states. This enhances functionality and aligns with better code practices.

* don't think we need to

* update
This commit is contained in:
Jason Wen
2025-05-19 14:25:26 -04:00
committed by GitHub
parent a6eba52791
commit ddfb7420ca
6 changed files with 126 additions and 27 deletions
@@ -21,22 +21,11 @@ MadsSettings::MadsSettings(QWidget *parent) : QWidget(parent) {
ListWidget *list = new ListWidget(this, false);
// Main cruise
madsMainCruiseToggle = new ParamControl(
"MadsMainCruiseAllowed",
tr("Toggle with Main Cruise"),
tr("Note: For vehicles without LFA/LKAS button, disabling this will prevent lateral control engagement."),
"");
madsMainCruiseToggle = new ParamControl("MadsMainCruiseAllowed", tr("Toggle with Main Cruise"), "", "");
list->addItem(madsMainCruiseToggle);
// Unified Engagement Mode
madsUnifiedEngagementModeToggle = new ParamControl(
"MadsUnifiedEngagementMode",
tr("Unified Engagement Mode (UEM)"),
QString("%1<br>"
"<h4>%2</h4>")
.arg(tr("Engage lateral and longitudinal control with cruise control engagement."))
.arg(tr("Note: Once lateral control is engaged via UEM, it will remain engaged until it is manually disabled via the MADS button or car shut off.")),
"");
madsUnifiedEngagementModeToggle = new ParamControl("MadsUnifiedEngagementMode", tr("Unified Engagement Mode (UEM)"), "", "");
list->addItem(madsUnifiedEngagementModeToggle);
// Steering Mode On Brake
@@ -62,8 +51,51 @@ void MadsSettings::updateToggles(bool _offroad) {
std::clamp(mads_steering_mode_param, static_cast<int>(MadsSteeringMode::REMAIN_ACTIVE), static_cast<int>(MadsSteeringMode::DISENGAGE))
);
madsSteeringMode->setEnabled(_offroad);
madsSteeringMode->setDescription(madsSteeringModeDescription(steering_mode));
auto cp_bytes = params.get("CarParamsPersistent");
if (!cp_bytes.empty()) {
AlignedBuffer aligned_buf;
capnp::FlatArrayMessageReader cmsg(aligned_buf.align(cp_bytes.data(), cp_bytes.size()));
cereal::CarParams::Reader CP = cmsg.getRoot<cereal::CarParams>();
if (isBrandInList(CP.getBrand(), mads_limited_settings_brands)) {
params.remove("MadsMainCruiseAllowed");
params.putBool("MadsUnifiedEngagementMode", true);
params.put("MadsSteeringMode", std::to_string(static_cast<int>(MadsSteeringMode::DISENGAGE)));
madsMainCruiseToggle->setEnabled(false);
madsMainCruiseToggle->setDescription(madsDescriptionBuilder(DEFAULT_TO_OFF, MADS_MAIN_CRUISE_BASE_DESC));
madsMainCruiseToggle->showDescription();
madsUnifiedEngagementModeToggle->setEnabled(false);
madsUnifiedEngagementModeToggle->setDescription(madsDescriptionBuilder(DEFAULT_TO_ON, MADS_UNIFIED_ENGAGEMENT_MODE_BASE_DESC));
madsUnifiedEngagementModeToggle->showDescription();
madsSteeringModeValues = convertMadsSteeringModeValues({MadsSteeringMode::DISENGAGE});
madsSteeringMode->setDescription(madsDescriptionBuilder(STATUS_DISENGAGE_ONLY, madsSteeringModeDescription(steering_mode)));
} else {
madsMainCruiseToggle->setEnabled(true);
madsMainCruiseToggle->setDescription(MADS_MAIN_CRUISE_BASE_DESC);
madsUnifiedEngagementModeToggle->setEnabled(true);
madsUnifiedEngagementModeToggle->setDescription(MADS_UNIFIED_ENGAGEMENT_MODE_BASE_DESC);
madsSteeringModeValues = convertMadsSteeringModeValues(getMadsSteeringModeValues());
madsSteeringMode->setDescription(madsSteeringModeDescription(steering_mode));
}
} else {
madsMainCruiseToggle->setEnabled(false);
madsMainCruiseToggle->setDescription(madsDescriptionBuilder(STATUS_CHECK_COMPATIBILITY, MADS_MAIN_CRUISE_BASE_DESC));
madsMainCruiseToggle->showDescription();
madsUnifiedEngagementModeToggle->setEnabled(false);
madsUnifiedEngagementModeToggle->setDescription(madsDescriptionBuilder(STATUS_CHECK_COMPATIBILITY, MADS_UNIFIED_ENGAGEMENT_MODE_BASE_DESC));
madsUnifiedEngagementModeToggle->showDescription();
madsSteeringModeValues = {};
madsSteeringMode->setDescription(madsDescriptionBuilder(STATUS_CHECK_COMPATIBILITY, madsSteeringModeDescription(steering_mode)));
}
madsSteeringMode->setEnableSelectedButtons(_offroad, madsSteeringModeValues);
madsSteeringMode->showDescription();
offroad = _offroad;
@@ -12,6 +12,8 @@
#include "selfdrive/ui/sunnypilot/qt/offroad/settings/settings.h"
#include "selfdrive/ui/sunnypilot/qt/widgets/controls.h"
const std::vector<std::string> mads_limited_settings_brands = {"rivian"};
enum class MadsSteeringMode {
REMAIN_ACTIVE = 0,
PAUSE = 1,
@@ -46,15 +48,44 @@ private:
ParamControl *madsUnifiedEngagementModeToggle;
ButtonParamControl *madsSteeringMode;
std::vector<int> madsSteeringModeValues = {};
const QString MADS_MAIN_CRUISE_BASE_DESC = tr("Note: For vehicles without LFA/LKAS button, disabling this will prevent lateral control engagement.");
const QString MADS_UNIFIED_ENGAGEMENT_MODE_BASE_DESC = QString("%1<br>"
"<h4>%2</h4>")
.arg(tr("Engage lateral and longitudinal control with cruise control engagement."))
.arg(tr("Note: Once lateral control is engaged via UEM, it will remain engaged until it is manually disabled via the MADS button or car shut off."));
const QString STATUS_CHECK_COMPATIBILITY = tr("Start the vehicle to check vehicle compatibility.");
const QString DEFAULT_TO_OFF = tr("This feature defaults to OFF, and does not allow selection due to vehicle limitations.");
const QString DEFAULT_TO_ON = tr("This feature defaults to ON, and does not allow selection due to vehicle limitations.");
const QString STATUS_DISENGAGE_ONLY = tr("This platform only supports Disengage mode due to vehicle limitations.");
static const std::vector<MadsSteeringModeOption> &madsSteeringModeOptions() {
static const std::vector<MadsSteeringModeOption> options = {
{MadsSteeringMode::REMAIN_ACTIVE, tr("Remain Active"), tr("Remain Active: ALC will remain active when the brake pedal is pressed.")},
{MadsSteeringMode::PAUSE, tr("Pause"), tr("Pause: ALC will pause when the brake pedal is pressed.")},
{MadsSteeringMode::DISENGAGE, tr("Disengage"), tr("Disengage: ALC will disengage when the brake pedal is pressed.")},
{MadsSteeringMode::REMAIN_ACTIVE, tr("Remain Active"), tr("Remain Active: ALC will remain active when the brake pedal is pressed.")},
{MadsSteeringMode::PAUSE, tr("Pause"), tr("Pause: ALC will pause when the brake pedal is pressed.")},
{MadsSteeringMode::DISENGAGE, tr("Disengage"), tr("Disengage: ALC will disengage when the brake pedal is pressed.")},
};
return options;
}
static std::vector<MadsSteeringMode> getMadsSteeringModeValues() {
std::vector<MadsSteeringMode> values;
for (const auto& option : madsSteeringModeOptions()) {
values.push_back(option.mode);
}
return values;
}
static std::vector<int> convertMadsSteeringModeValues(const std::vector<MadsSteeringMode> &modes) {
std::vector<int> values;
for (const auto& mode : modes) {
values.push_back(static_cast<int>(mode));
}
return values;
}
static std::vector<QString> madsSteeringModeTexts() {
std::vector<QString> texts;
for (const auto& option : madsSteeringModeOptions()) {
@@ -63,7 +94,7 @@ private:
return texts;
}
static QString madsSteeringModeDescription(const MadsSteeringMode mode) {
static QString madsSteeringModeDescription(const MadsSteeringMode mode = MadsSteeringMode::REMAIN_ACTIVE) {
QString base_desc = tr("Choose how Automatic Lane Centering (ALC) behaves after the brake pedal is manually pressed in sunnypilot.");
QString result = base_desc + "<br><br>";
@@ -77,4 +108,8 @@ private:
return result;
}
static QString madsDescriptionBuilder(const QString &custom_description, const QString &base_description) {
return "<font color='white'><b>" + custom_description + "</b></font><br><br>" + base_description;
}
};
@@ -122,6 +122,21 @@ void LateralPanel::updateToggles(bool _offroad) {
toggle->setEnabled(_offroad);
}
auto cp_bytes = params.get("CarParamsPersistent");
if (!cp_bytes.empty()) {
AlignedBuffer aligned_buf;
capnp::FlatArrayMessageReader cmsg(aligned_buf.align(cp_bytes.data(), cp_bytes.size()));
cereal::CarParams::Reader CP = cmsg.getRoot<cereal::CarParams>();
if (isBrandInList(CP.getBrand(), mads_limited_settings_brands)) {
madsToggle->setDescription(descriptionBuilder(STATUS_MADS_SETTINGS_LIMITED_COMPATIBILITY, MADS_BASE_DESC));
} else {
madsToggle->setDescription(descriptionBuilder(STATUS_MADS_SETTINGS_FULL_COMPATIBILITY, MADS_BASE_DESC));
}
} else {
madsToggle->setDescription(descriptionBuilder(STATUS_MADS_CHECK_COMPATIBILITY, MADS_BASE_DESC));
}
madsSettingsButton->setEnabled(madsToggle->isToggled());
offroad = _offroad;
@@ -30,6 +30,7 @@ public slots:
void updateToggles(bool _offroad);
private:
Params params;
QStackedLayout* main_layout = nullptr;
QWidget* sunnypilotScreen = nullptr;
ScrollViewSP *sunnypilotScroller = nullptr;
@@ -42,4 +43,14 @@ private:
PushButtonSP *laneChangeSettingsButton;
LaneChangeSettings *laneChangeWidget = nullptr;
NeuralNetworkLateralControl *nnlcToggle = nullptr;
const QString MADS_BASE_DESC = tr("Enables independent engagements of Automatic Lane Centering (ALC) and Adaptive Cruise Control (ACC).");
const QString STATUS_MADS_CHECK_COMPATIBILITY = tr("Start the vehicle to check vehicle compatibility.");
const QString STATUS_MADS_SETTINGS_FULL_COMPATIBILITY = tr("This platform supports all MADS settings.");
const QString STATUS_MADS_SETTINGS_LIMITED_COMPATIBILITY = tr("This platform supports limited MADS settings.");
static QString descriptionBuilder(const QString &custom_description, const QString &base_description) {
return "<font color='white'><b>" + custom_description + "</b></font><br><br>" + base_description;
}
};
+12 -7
View File
@@ -46,12 +46,17 @@ def set_car_specific_params(CP: structs.CarParams, CP_SP: structs.CarParamsSP, p
CP_SP.flags |= HyundaiFlagsSP.LONGITUDINAL_MAIN_CRUISE_TOGGLEABLE.value
CP_SP.safetyParam |= HyundaiSafetyFlagsSP.LONG_MAIN_CRUISE_TOGGLEABLE
# MADS is currently not supported in Tesla due to lack of consistent states to engage controls
# TODO-SP: To enable MADS for Tesla, identify consistent signals for MADS toggling
if CP.brand == "tesla":
params.remove("Mads")
# MADS Partial Support
# MADS is currently partially supported for these platforms due to lack of consistent states to engage controls
# Only MadsSteeringModeOnBrake.DISENGAGE is supported for these platforms
mads_partial_support = False
if mads_partial_support:
params.put("MadsSteeringMode", "2")
params.put_bool("MadsUnifiedEngagementMode", True)
params.remove("MadsMainCruiseAllowed")
# MADS is currently not supported in Rivian due to lack of consistent states to engage controls
# TODO-SP: To enable MADS for Rivian, identify consistent signals for MADS toggling
if CP.brand == "rivian":
# MADS Disabled - No Support
# MADS is currently not supported for these platforms due to lack of consistent states to engage controls
# TODO-SP: To enable MADS full support for Rivian/Tesla, identify consistent signals for MADS toggling
if CP.brand in ("rivian", "tesla"):
params.remove("Mads")
+2 -1
View File
@@ -33,6 +33,7 @@ class ModularAssistiveDrivingSystem:
self.active = False
self.available = False
self.allow_always = False
self.no_main_cruise = False
self.selfdrive = selfdrive
self.selfdrive.enabled_prev = False
self.state_machine = StateMachine(self)
@@ -159,7 +160,7 @@ class ModularAssistiveDrivingSystem:
else:
self.events_sp.add(EventNameSP.lkasEnable)
if not CS.cruiseState.available:
if not CS.cruiseState.available and not self.no_main_cruise:
self.events.remove(EventName.buttonEnable)
if self.selfdrive.CS_prev.cruiseState.available:
self.events_sp.add(EventNameSP.lkasDisable)