diff --git a/common/params_keys.h b/common/params_keys.h index 84ad61981..e6de3d8fd 100644 --- a/common/params_keys.h +++ b/common/params_keys.h @@ -170,7 +170,6 @@ inline static std::unordered_map keys = { {"BackupManager_RestoreVersion", PERSISTENT}, // sunnypilot car specific params - {"HyundaiLongitudinalTuning", PERSISTENT}, {"HyundaiRadarTracks", PERSISTENT}, {"HyundaiRadarTracksConfirmed", PERSISTENT}, {"HyundaiRadarTracksPersistent", PERSISTENT}, diff --git a/selfdrive/controls/lib/longitudinal_planner.py b/selfdrive/controls/lib/longitudinal_planner.py index 1b734a0c7..6ab8c6d42 100644 --- a/selfdrive/controls/lib/longitudinal_planner.py +++ b/selfdrive/controls/lib/longitudinal_planner.py @@ -187,6 +187,10 @@ class LongitudinalPlanner(LongitudinalPlannerSP): output_a_target = min(output_a_target_mpc, output_a_target_e2e) self.output_should_stop = output_should_stop_e2e or output_should_stop_mpc + if not self.is_stock: + # To support non Tomb Raider models + output_a_target, self.output_should_stop = output_a_target_mpc, output_should_stop_mpc + for idx in range(2): accel_clip[idx] = np.clip(accel_clip[idx], self.prev_accel_clip[idx] - 0.05, self.prev_accel_clip[idx] + 0.05) self.output_a_target = np.clip(output_a_target, accel_clip[0], accel_clip[1]) diff --git a/selfdrive/ui/sunnypilot/SConscript b/selfdrive/ui/sunnypilot/SConscript index 82a257523..379adfced 100644 --- a/selfdrive/ui/sunnypilot/SConscript +++ b/selfdrive/ui/sunnypilot/SConscript @@ -50,12 +50,28 @@ network_src = [ ] vehicle_panel_qt_src = [ - "sunnypilot/qt/offroad/settings/vehicle/hyundai_settings.cc", + "sunnypilot/qt/offroad/settings/vehicle/brand_settings_factory.cc", + "sunnypilot/qt/offroad/settings/vehicle/brand_settings_interface.cc", "sunnypilot/qt/offroad/settings/vehicle/platform_selector.cc", ] +brand_settings_qt_src = [ + "sunnypilot/qt/offroad/settings/vehicle/chrysler_settings.cc", + "sunnypilot/qt/offroad/settings/vehicle/ford_settings.cc", + "sunnypilot/qt/offroad/settings/vehicle/gm_settings.cc", + "sunnypilot/qt/offroad/settings/vehicle/honda_settings.cc", + "sunnypilot/qt/offroad/settings/vehicle/hyundai_settings.cc", + "sunnypilot/qt/offroad/settings/vehicle/mazda_settings.cc", + "sunnypilot/qt/offroad/settings/vehicle/nissan_settings.cc", + "sunnypilot/qt/offroad/settings/vehicle/rivian_settings.cc", + "sunnypilot/qt/offroad/settings/vehicle/subaru_settings.cc", + "sunnypilot/qt/offroad/settings/vehicle/tesla_settings.cc", + "sunnypilot/qt/offroad/settings/vehicle/toyota_settings.cc", + "sunnypilot/qt/offroad/settings/vehicle/volkswagen_settings.cc", +] + sp_widgets_src = widgets_src + network_src -sp_qt_src = qt_src + lateral_panel_qt_src + vehicle_panel_qt_src +sp_qt_src = qt_src + lateral_panel_qt_src + vehicle_panel_qt_src + brand_settings_qt_src sp_qt_util = qt_util Export('sp_widgets_src', 'sp_qt_src', "sp_qt_util") diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/device_panel.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/device_panel.cc index 3e613e102..e6855c4b4 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/device_panel.cc +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/device_panel.cc @@ -112,9 +112,18 @@ DevicePanelSP::DevicePanelSP(SettingsWindowSP *parent) : DevicePanel(parent) { addItem(power_group_layout); + std::vector always_enabled_btns = { + rebootBtn, + poweroffBtn, + offroadBtn, + buttons["quietModeBtn"], + }; + QObject::connect(uiState(), &UIState::offroadTransition, [=](bool offroad) { for (auto btn : findChildren()) { - if (btn != rebootBtn && btn != poweroffBtn && btn != offroadBtn) { + bool always_enabled = std::find(always_enabled_btns.begin(), always_enabled_btns.end(), btn) != always_enabled_btns.end(); + + if (!always_enabled) { btn->setEnabled(offroad); } } diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/brand_settings_factory.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/brand_settings_factory.cc new file mode 100644 index 000000000..08b137d27 --- /dev/null +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/brand_settings_factory.cc @@ -0,0 +1,62 @@ +/** + * Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + * + * This file is part of sunnypilot and is licensed under the MIT License. + * See the LICENSE.md file in the root directory for more details. + */ + +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/brand_settings_factory.h" +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/brands.h" + +static const QStringList supportedBrands = { + "chrysler", + "ford", + "gm", + "honda", + "hyundai", + "mazda", + "nissan", + "rivian", + "subaru" + "tesla", + "toyota", + "volkswagen", +}; + +BrandSettingsInterface* BrandSettingsFactory::createBrandSettings(const QString& brand, QWidget* parent) { + if (brand == "chrysler") + return new ChryslerSettings(parent); + if (brand == "ford") + return new FordSettings(parent); + if (brand == "gm") + return new GMSettings(parent); + if (brand == "honda") + return new HondaSettings(parent); + if (brand == "hyundai") + return new HyundaiSettings(parent); + if (brand == "mazda") + return new MazdaSettings(parent); + if (brand == "nissan") + return new NissanSettings(parent); + if (brand == "rivian") + return new RivianSettings(parent); + if (brand == "subaru") + return new SubaruSettings(parent); + if (brand == "tesla") + return new TeslaSettings(parent); + if (brand == "toyota") + return new ToyotaSettings(parent); + if (brand == "volkswagen") + return new VolkswagenSettings(parent); + + // Default empty settings if brand not supported + return nullptr; +} + +bool BrandSettingsFactory::isBrandSupported(const QString& brand) { + return supportedBrands.contains(brand); +} + +QStringList BrandSettingsFactory::getSupportedBrands() { + return supportedBrands; +} diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/brand_settings_factory.h b/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/brand_settings_factory.h new file mode 100644 index 000000000..b4dc9fc81 --- /dev/null +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/brand_settings_factory.h @@ -0,0 +1,18 @@ +/** + * Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + * + * This file is part of sunnypilot and is licensed under the MIT License. + * See the LICENSE.md file in the root directory for more details. + */ + +#pragma once + +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/brand_settings_interface.h" + +class BrandSettingsFactory { + +public: + static BrandSettingsInterface* createBrandSettings(const QString &brand, QWidget *parent = nullptr); + static bool isBrandSupported(const QString& brand); + static QStringList getSupportedBrands(); +}; diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/brand_settings_interface.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/brand_settings_interface.cc new file mode 100644 index 000000000..4c4920727 --- /dev/null +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/brand_settings_interface.cc @@ -0,0 +1,8 @@ +/** + * Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + * + * This file is part of sunnypilot and is licensed under the MIT License. + * See the LICENSE.md file in the root directory for more details. + */ + +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/brand_settings_interface.h" diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/brand_settings_interface.h b/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/brand_settings_interface.h new file mode 100644 index 000000000..2b6c57ae9 --- /dev/null +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/brand_settings_interface.h @@ -0,0 +1,21 @@ +/** + * Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + * + * This file is part of sunnypilot and is licensed under the MIT License. + * See the LICENSE.md file in the root directory for more details. + */ + +#pragma once + +#include + +class BrandSettingsInterface : public QWidget { + Q_OBJECT + +public: + explicit BrandSettingsInterface(QWidget *parent = nullptr) : QWidget(parent) {} + virtual ~BrandSettingsInterface() = default; + + virtual void updatePanel(bool offroad) = 0; + virtual void updateSettings() = 0; +}; diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/brands.h b/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/brands.h new file mode 100644 index 000000000..795dba573 --- /dev/null +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/brands.h @@ -0,0 +1,21 @@ +/** + * Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + * + * This file is part of sunnypilot and is licensed under the MIT License. + * See the LICENSE.md file in the root directory for more details. + */ + +#pragma once + +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/chrysler_settings.h" +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/ford_settings.h" +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/gm_settings.h" +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/honda_settings.h" +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/hyundai_settings.h" +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/mazda_settings.h" +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/nissan_settings.h" +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/rivian_settings.h" +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/subaru_settings.h" +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/tesla_settings.h" +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/toyota_settings.h" +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/volkswagen_settings.h" diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/chrysler_settings.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/chrysler_settings.cc new file mode 100644 index 000000000..0912a7afd --- /dev/null +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/chrysler_settings.cc @@ -0,0 +1,31 @@ +/** + * Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + * + * This file is part of sunnypilot and is licensed under the MIT License. + * See the LICENSE.md file in the root directory for more details. + */ + +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/chrysler_settings.h" + +#include "selfdrive/ui/sunnypilot/qt/widgets/scrollview.h" + +ChryslerSettings::ChryslerSettings(QWidget *parent) : BrandSettingsInterface(parent) { + QVBoxLayout *main_layout = new QVBoxLayout(this); + main_layout->setContentsMargins(0, 0, 0, 0); + + ListWidget *list = new ListWidget(this, false); + + main_layout->addWidget(new ScrollViewSP(list, this)); +} + +void ChryslerSettings::updatePanel(bool _offroad) { + updateSettings(); + + offroad = _offroad; +} + +void ChryslerSettings::updateSettings() { + if (!isVisible()) { + return; + } +} diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/chrysler_settings.h b/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/chrysler_settings.h new file mode 100644 index 000000000..20a623554 --- /dev/null +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/chrysler_settings.h @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + * + * This file is part of sunnypilot and is licensed under the MIT License. + * See the LICENSE.md file in the root directory for more details. + */ + +#pragma once + +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/brand_settings_interface.h" + +#include "selfdrive/ui/qt/util.h" +#include "selfdrive/ui/sunnypilot/ui.h" +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/settings.h" +#include "selfdrive/ui/sunnypilot/qt/widgets/controls.h" + +class ChryslerSettings : public BrandSettingsInterface { + Q_OBJECT + +public: + explicit ChryslerSettings(QWidget *parent = nullptr); + void updatePanel(bool _offroad); + void updateSettings(); + +private: + bool offroad = false; +}; diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/ford_settings.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/ford_settings.cc new file mode 100644 index 000000000..eaae5a621 --- /dev/null +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/ford_settings.cc @@ -0,0 +1,31 @@ +/** + * Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + * + * This file is part of sunnypilot and is licensed under the MIT License. + * See the LICENSE.md file in the root directory for more details. + */ + +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/ford_settings.h" + +#include "selfdrive/ui/sunnypilot/qt/widgets/scrollview.h" + +FordSettings::FordSettings(QWidget *parent) : BrandSettingsInterface(parent) { + QVBoxLayout *main_layout = new QVBoxLayout(this); + main_layout->setContentsMargins(0, 0, 0, 0); + + ListWidget *list = new ListWidget(this, false); + + main_layout->addWidget(new ScrollViewSP(list, this)); +} + +void FordSettings::updatePanel(bool _offroad) { + updateSettings(); + + offroad = _offroad; +} + +void FordSettings::updateSettings() { + if (!isVisible()) { + return; + } +} diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/ford_settings.h b/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/ford_settings.h new file mode 100644 index 000000000..1d97651ba --- /dev/null +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/ford_settings.h @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + * + * This file is part of sunnypilot and is licensed under the MIT License. + * See the LICENSE.md file in the root directory for more details. + */ + +#pragma once + +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/brand_settings_interface.h" + +#include "selfdrive/ui/qt/util.h" +#include "selfdrive/ui/sunnypilot/ui.h" +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/settings.h" +#include "selfdrive/ui/sunnypilot/qt/widgets/controls.h" + +class FordSettings : public BrandSettingsInterface { + Q_OBJECT + +public: + explicit FordSettings(QWidget *parent = nullptr); + void updatePanel(bool _offroad); + void updateSettings(); + +private: + bool offroad = false; +}; diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/gm_settings.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/gm_settings.cc new file mode 100644 index 000000000..1aa4ccf93 --- /dev/null +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/gm_settings.cc @@ -0,0 +1,31 @@ +/** + * Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + * + * This file is part of sunnypilot and is licensed under the MIT License. + * See the LICENSE.md file in the root directory for more details. + */ + +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/gm_settings.h" + +#include "selfdrive/ui/sunnypilot/qt/widgets/scrollview.h" + +GMSettings::GMSettings(QWidget *parent) : BrandSettingsInterface(parent) { + QVBoxLayout *main_layout = new QVBoxLayout(this); + main_layout->setContentsMargins(0, 0, 0, 0); + + ListWidget *list = new ListWidget(this, false); + + main_layout->addWidget(new ScrollViewSP(list, this)); +} + +void GMSettings::updatePanel(bool _offroad) { + updateSettings(); + + offroad = _offroad; +} + +void GMSettings::updateSettings() { + if (!isVisible()) { + return; + } +} diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/gm_settings.h b/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/gm_settings.h new file mode 100644 index 000000000..35988d95e --- /dev/null +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/gm_settings.h @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + * + * This file is part of sunnypilot and is licensed under the MIT License. + * See the LICENSE.md file in the root directory for more details. + */ + +#pragma once + +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/brand_settings_interface.h" + +#include "selfdrive/ui/qt/util.h" +#include "selfdrive/ui/sunnypilot/ui.h" +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/settings.h" +#include "selfdrive/ui/sunnypilot/qt/widgets/controls.h" + +class GMSettings : public BrandSettingsInterface { + Q_OBJECT + +public: + explicit GMSettings(QWidget *parent = nullptr); + void updatePanel(bool _offroad); + void updateSettings(); + +private: + bool offroad = false; +}; diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/honda_settings.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/honda_settings.cc new file mode 100644 index 000000000..1efdb747f --- /dev/null +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/honda_settings.cc @@ -0,0 +1,31 @@ +/** + * Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + * + * This file is part of sunnypilot and is licensed under the MIT License. + * See the LICENSE.md file in the root directory for more details. + */ + +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/honda_settings.h" + +#include "selfdrive/ui/sunnypilot/qt/widgets/scrollview.h" + +HondaSettings::HondaSettings(QWidget *parent) : BrandSettingsInterface(parent) { + QVBoxLayout *main_layout = new QVBoxLayout(this); + main_layout->setContentsMargins(0, 0, 0, 0); + + ListWidget *list = new ListWidget(this, false); + + main_layout->addWidget(new ScrollViewSP(list, this)); +} + +void HondaSettings::updatePanel(bool _offroad) { + updateSettings(); + + offroad = _offroad; +} + +void HondaSettings::updateSettings() { + if (!isVisible()) { + return; + } +} diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/honda_settings.h b/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/honda_settings.h new file mode 100644 index 000000000..e494e8001 --- /dev/null +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/honda_settings.h @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + * + * This file is part of sunnypilot and is licensed under the MIT License. + * See the LICENSE.md file in the root directory for more details. + */ + +#pragma once + +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/brand_settings_interface.h" + +#include "selfdrive/ui/qt/util.h" +#include "selfdrive/ui/sunnypilot/ui.h" +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/settings.h" +#include "selfdrive/ui/sunnypilot/qt/widgets/controls.h" + +class HondaSettings : public BrandSettingsInterface { + Q_OBJECT + +public: + explicit HondaSettings(QWidget *parent = nullptr); + void updatePanel(bool _offroad); + void updateSettings(); + +private: + bool offroad = false; +}; diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/hyundai_settings.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/hyundai_settings.cc index 08d76f592..7e4ea4326 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/hyundai_settings.cc +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/hyundai_settings.cc @@ -9,76 +9,23 @@ #include "selfdrive/ui/sunnypilot/qt/widgets/scrollview.h" -HyundaiSettings::HyundaiSettings(QWidget *parent) : QWidget(parent) { +HyundaiSettings::HyundaiSettings(QWidget *parent) : BrandSettingsInterface(parent) { QVBoxLayout *main_layout = new QVBoxLayout(this); main_layout->setContentsMargins(0, 0, 0, 0); ListWidget *list = new ListWidget(this, false); - std::vector tuning_texts{ tr("Off"), tr("Dynamic"), tr("Predictive") }; - longitudinalTuningToggle = new ButtonParamControlSP( - "HyundaiLongitudinalTuning", - tr("Custom Longitudinal Tuning"), - tr("Select a tuning mode.\n" - "Off: no custom tuning applied.\n" - "Dynamic: on-the-spot adjustments using dynamic calculations.\n" - "Predictive: adjusts based on anticipated ACC variation."), - "", - tuning_texts, - 500 - ); - longitudinalTuningToggle->showDescription(); - longitudinalTuningToggle->setProperty("originalDesc", longitudinalTuningToggle->getDescription()); - list->addItem(longitudinalTuningToggle); - - QObject::connect(uiState(), &UIState::offroadTransition, this, &HyundaiSettings::updateSettings); - main_layout->addWidget(new ScrollViewSP(list, this)); } -QString HyundaiSettings::toggleDisableMsg() const { - if (!has_longitudinal_control) { - return tr("This feature can only be used with openpilot longitudinal control enabled."); - } - - if (!offroad) { - return tr("Enable \"Always Offroad\" in Device panel, or turn vehicle off to select an option."); - } - - return QString(); -} - -void HyundaiSettings::showEvent(QShowEvent *event) { - updateSettings(offroad); -} - -void HyundaiSettings::updateSettings(bool _offroad) { - if (!isVisible()) { - return; - } - - 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(); - - has_longitudinal_control = hasLongitudinalControl(CP); - - QString longitudinal_tuning_disabled_msg = toggleDisableMsg(); - if (!longitudinal_tuning_disabled_msg.isEmpty()) { - longitudinalTuningToggle->setEnabled(false); - longitudinalTuningToggle->setDescription(longitudinal_tuning_disabled_msg); - } else { - longitudinalTuningToggle->setEnabled(true); - longitudinalTuningToggle->setDescription(longitudinalTuningToggle->property("originalDesc").toString()); - } - - longitudinalTuningToggle->showDescription(); - } else { - has_longitudinal_control = false; - longitudinalTuningToggle->setEnabled(false); - } +void HyundaiSettings::updatePanel(bool _offroad) { + updateSettings(); offroad = _offroad; } + +void HyundaiSettings::updateSettings() { + if (!isVisible()) { + return; + } +} diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/hyundai_settings.h b/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/hyundai_settings.h index 3137a0d1b..0f065124f 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/hyundai_settings.h +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/hyundai_settings.h @@ -7,26 +7,21 @@ #pragma once +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/brand_settings_interface.h" + #include "selfdrive/ui/qt/util.h" #include "selfdrive/ui/sunnypilot/ui.h" #include "selfdrive/ui/sunnypilot/qt/offroad/settings/settings.h" #include "selfdrive/ui/sunnypilot/qt/widgets/controls.h" -class HyundaiSettings : public QWidget { +class HyundaiSettings : public BrandSettingsInterface { Q_OBJECT public: explicit HyundaiSettings(QWidget *parent = nullptr); - void showEvent(QShowEvent *event) override; - -public slots: - void updateSettings(bool _offroad); + void updatePanel(bool _offroad); + void updateSettings(); private: - Params params; bool offroad = false; - bool has_longitudinal_control = false; - - ButtonParamControlSP *longitudinalTuningToggle = nullptr; - QString toggleDisableMsg() const; }; diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/mazda_settings.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/mazda_settings.cc new file mode 100644 index 000000000..330afdc48 --- /dev/null +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/mazda_settings.cc @@ -0,0 +1,31 @@ +/** + * Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + * + * This file is part of sunnypilot and is licensed under the MIT License. + * See the LICENSE.md file in the root directory for more details. + */ + +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/mazda_settings.h" + +#include "selfdrive/ui/sunnypilot/qt/widgets/scrollview.h" + +MazdaSettings::MazdaSettings(QWidget *parent) : BrandSettingsInterface(parent) { + QVBoxLayout *main_layout = new QVBoxLayout(this); + main_layout->setContentsMargins(0, 0, 0, 0); + + ListWidget *list = new ListWidget(this, false); + + main_layout->addWidget(new ScrollViewSP(list, this)); +} + +void MazdaSettings::updatePanel(bool _offroad) { + updateSettings(); + + offroad = _offroad; +} + +void MazdaSettings::updateSettings() { + if (!isVisible()) { + return; + } +} diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/mazda_settings.h b/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/mazda_settings.h new file mode 100644 index 000000000..3d109fbe9 --- /dev/null +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/mazda_settings.h @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + * + * This file is part of sunnypilot and is licensed under the MIT License. + * See the LICENSE.md file in the root directory for more details. + */ + +#pragma once + +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/brand_settings_interface.h" + +#include "selfdrive/ui/qt/util.h" +#include "selfdrive/ui/sunnypilot/ui.h" +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/settings.h" +#include "selfdrive/ui/sunnypilot/qt/widgets/controls.h" + +class MazdaSettings : public BrandSettingsInterface { + Q_OBJECT + +public: + explicit MazdaSettings(QWidget *parent = nullptr); + void updatePanel(bool _offroad); + void updateSettings(); + +private: + bool offroad = false; +}; diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/nissan_settings.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/nissan_settings.cc new file mode 100644 index 000000000..0faa6836f --- /dev/null +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/nissan_settings.cc @@ -0,0 +1,31 @@ +/** + * Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + * + * This file is part of sunnypilot and is licensed under the MIT License. + * See the LICENSE.md file in the root directory for more details. + */ + +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/nissan_settings.h" + +#include "selfdrive/ui/sunnypilot/qt/widgets/scrollview.h" + +NissanSettings::NissanSettings(QWidget *parent) : BrandSettingsInterface(parent) { + QVBoxLayout *main_layout = new QVBoxLayout(this); + main_layout->setContentsMargins(0, 0, 0, 0); + + ListWidget *list = new ListWidget(this, false); + + main_layout->addWidget(new ScrollViewSP(list, this)); +} + +void NissanSettings::updatePanel(bool _offroad) { + updateSettings(); + + offroad = _offroad; +} + +void NissanSettings::updateSettings() { + if (!isVisible()) { + return; + } +} diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/nissan_settings.h b/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/nissan_settings.h new file mode 100644 index 000000000..397a17e97 --- /dev/null +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/nissan_settings.h @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + * + * This file is part of sunnypilot and is licensed under the MIT License. + * See the LICENSE.md file in the root directory for more details. + */ + +#pragma once + +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/brand_settings_interface.h" + +#include "selfdrive/ui/qt/util.h" +#include "selfdrive/ui/sunnypilot/ui.h" +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/settings.h" +#include "selfdrive/ui/sunnypilot/qt/widgets/controls.h" + +class NissanSettings : public BrandSettingsInterface { + Q_OBJECT + +public: + explicit NissanSettings(QWidget *parent = nullptr); + void updatePanel(bool _offroad); + void updateSettings(); + +private: + bool offroad = false; +}; diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/platform_selector.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/platform_selector.cc index 83fa0b169..21c9a44cb 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/platform_selector.cc +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/platform_selector.cc @@ -43,37 +43,74 @@ PlatformSelector::PlatformSelector() : ButtonControl(tr("Vehicle"), "", "") { } }); + main_layout->addStretch(0); refresh(offroad); } void PlatformSelector::refresh(bool _offroad) { QString name = getPlatformBundle("name").toString(); + platform = unrecognized_str; + QString platform_color = YELLOW_PLATFORM; + if (!name.isEmpty()) { - setValue(name); + platform = name; + platform_color = BLUE_PLATFORM; + brand = getPlatformBundle("brand").toString(); setText(tr("REMOVE")); } else { setText(tr("SEARCH")); + + platform = unrecognized_str; + brand = ""; 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(); - setValue(QString::fromStdString(CP.getCarFingerprint().cStr())); + + platform = QString::fromStdString(CP.getCarFingerprint().cStr()); + + for (auto it = platforms.constBegin(); it != platforms.constEnd(); ++it) { + if (it.value()["platform"].toString() == platform) { + platform = it.key(); + brand = it.value()["brand"].toString(); + break; + } + } + + if (platform == "MOCK") { + platform = unrecognized_str; + } else { + platform_color = GREEN_PLATFORM; + } } } + setValue(platform, platform_color); setEnabled(true); emit refreshPanel(); offroad = _offroad; + + FingerprintStatus cur_status; + if (platform_color == GREEN_PLATFORM) { + cur_status = FingerprintStatus::AUTO_FINGERPRINT; + } else if (platform_color == BLUE_PLATFORM) { + cur_status = FingerprintStatus::MANUAL_FINGERPRINT; + } else { + cur_status = FingerprintStatus::UNRECOGNIZED; + } + + setDescription(platformDescription(cur_status)); + showDescription(); } -void PlatformSelector::setPlatform(const QString &platform) { - QVariantMap platform_data = platforms[platform]; +void PlatformSelector::setPlatform(const QString &_platform) { + QVariantMap platform_data = platforms[_platform]; const QString offroad_msg = offroad ? tr("This setting will take effect immediately.") : tr("This setting will take effect once the device enters offroad state."); const QString msg = QString("%1

%2") - .arg(platform, offroad_msg); + .arg(_platform, offroad_msg); QString content("

" + tr("Vehicle Selector") + "


" "

" + msg + "

"); @@ -81,7 +118,7 @@ void PlatformSelector::setPlatform(const QString &platform) { if (ConfirmationDialog(content, tr("Confirm"), tr("Cancel"), true, this).exec()) { QJsonObject json_bundle; json_bundle["platform"] = platform_data["platform"].toString(); - json_bundle["name"] = platform; + json_bundle["name"] = _platform; json_bundle["make"] = platform_data["make"].toString(); json_bundle["brand"] = platform_data["brand"].toString(); json_bundle["model"] = platform_data["model"].toString(); diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/platform_selector.h b/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/platform_selector.h index 3d912f822..9867371ef 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/platform_selector.h +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/platform_selector.h @@ -9,6 +9,16 @@ #include "selfdrive/ui/sunnypilot/qt/offroad/settings/settings.h" +static const QString GREEN_PLATFORM = "#00F100"; +static const QString BLUE_PLATFORM = "#0086E9"; +static const QString YELLOW_PLATFORM = "#FFD500"; + +enum class FingerprintStatus { + AUTO_FINGERPRINT, + MANUAL_FINGERPRINT, + UNRECOGNIZED, +}; + class PlatformSelector : public ButtonControl { Q_OBJECT @@ -16,6 +26,9 @@ public: PlatformSelector(); QVariant getPlatformBundle(const QString &key); + QString platform; + QString brand; + public slots: void refresh(bool _offroad); @@ -29,4 +42,27 @@ private: Params params; bool offroad; + + QString unrecognized_str = tr("Unrecognized Vehicle"); + + static QString platformDescription(FingerprintStatus status = FingerprintStatus::UNRECOGNIZED) { + QString auto_str = "🟢 - " + tr("Fingerprinted automatically"); + QString manual_str = "🔵 - " + tr("Manually selected"); + QString unrecognized_str = "🟡 - " + tr("Not fingerprinted or manually selected"); + + if (status == FingerprintStatus::AUTO_FINGERPRINT) { + auto_str = "" + auto_str + ""; + } else if (status == FingerprintStatus::MANUAL_FINGERPRINT) { + manual_str = "" + manual_str + ""; + } else { + unrecognized_str = "" + unrecognized_str + ""; + } + + return QString("%1
%2

%3
%4
%5") + .arg(tr("Select vehicle to force fingerprint manually.")) + .arg(tr("Colors represent fingerprint status:")) + .arg(auto_str) + .arg(manual_str) + .arg(unrecognized_str); + } }; diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/rivian_settings.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/rivian_settings.cc new file mode 100644 index 000000000..401048ee5 --- /dev/null +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/rivian_settings.cc @@ -0,0 +1,31 @@ +/** + * Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + * + * This file is part of sunnypilot and is licensed under the MIT License. + * See the LICENSE.md file in the root directory for more details. + */ + +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/rivian_settings.h" + +#include "selfdrive/ui/sunnypilot/qt/widgets/scrollview.h" + +RivianSettings::RivianSettings(QWidget *parent) : BrandSettingsInterface(parent) { + QVBoxLayout *main_layout = new QVBoxLayout(this); + main_layout->setContentsMargins(0, 0, 0, 0); + + ListWidget *list = new ListWidget(this, false); + + main_layout->addWidget(new ScrollViewSP(list, this)); +} + +void RivianSettings::updatePanel(bool _offroad) { + updateSettings(); + + offroad = _offroad; +} + +void RivianSettings::updateSettings() { + if (!isVisible()) { + return; + } +} diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/rivian_settings.h b/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/rivian_settings.h new file mode 100644 index 000000000..bf83f5966 --- /dev/null +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/rivian_settings.h @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + * + * This file is part of sunnypilot and is licensed under the MIT License. + * See the LICENSE.md file in the root directory for more details. + */ + +#pragma once + +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/brand_settings_interface.h" + +#include "selfdrive/ui/qt/util.h" +#include "selfdrive/ui/sunnypilot/ui.h" +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/settings.h" +#include "selfdrive/ui/sunnypilot/qt/widgets/controls.h" + +class RivianSettings : public BrandSettingsInterface { + Q_OBJECT + +public: + explicit RivianSettings(QWidget *parent = nullptr); + void updatePanel(bool _offroad); + void updateSettings(); + +private: + bool offroad = false; +}; diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/subaru_settings.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/subaru_settings.cc new file mode 100644 index 000000000..7a021ef4c --- /dev/null +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/subaru_settings.cc @@ -0,0 +1,31 @@ +/** + * Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + * + * This file is part of sunnypilot and is licensed under the MIT License. + * See the LICENSE.md file in the root directory for more details. + */ + +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/subaru_settings.h" + +#include "selfdrive/ui/sunnypilot/qt/widgets/scrollview.h" + +SubaruSettings::SubaruSettings(QWidget *parent) : BrandSettingsInterface(parent) { + QVBoxLayout *main_layout = new QVBoxLayout(this); + main_layout->setContentsMargins(0, 0, 0, 0); + + ListWidget *list = new ListWidget(this, false); + + main_layout->addWidget(new ScrollViewSP(list, this)); +} + +void SubaruSettings::updatePanel(bool _offroad) { + updateSettings(); + + offroad = _offroad; +} + +void SubaruSettings::updateSettings() { + if (!isVisible()) { + return; + } +} diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/subaru_settings.h b/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/subaru_settings.h new file mode 100644 index 000000000..bdf783559 --- /dev/null +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/subaru_settings.h @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + * + * This file is part of sunnypilot and is licensed under the MIT License. + * See the LICENSE.md file in the root directory for more details. + */ + +#pragma once + +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/brand_settings_interface.h" + +#include "selfdrive/ui/qt/util.h" +#include "selfdrive/ui/sunnypilot/ui.h" +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/settings.h" +#include "selfdrive/ui/sunnypilot/qt/widgets/controls.h" + +class SubaruSettings : public BrandSettingsInterface { + Q_OBJECT + +public: + explicit SubaruSettings(QWidget *parent = nullptr); + void updatePanel(bool _offroad); + void updateSettings(); + +private: + bool offroad = false; +}; diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/tesla_settings.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/tesla_settings.cc new file mode 100644 index 000000000..d811f1991 --- /dev/null +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/tesla_settings.cc @@ -0,0 +1,31 @@ +/** + * Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + * + * This file is part of sunnypilot and is licensed under the MIT License. + * See the LICENSE.md file in the root directory for more details. + */ + +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/tesla_settings.h" + +#include "selfdrive/ui/sunnypilot/qt/widgets/scrollview.h" + +TeslaSettings::TeslaSettings(QWidget *parent) : BrandSettingsInterface(parent) { + QVBoxLayout *main_layout = new QVBoxLayout(this); + main_layout->setContentsMargins(0, 0, 0, 0); + + ListWidget *list = new ListWidget(this, false); + + main_layout->addWidget(new ScrollViewSP(list, this)); +} + +void TeslaSettings::updatePanel(bool _offroad) { + updateSettings(); + + offroad = _offroad; +} + +void TeslaSettings::updateSettings() { + if (!isVisible()) { + return; + } +} diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/tesla_settings.h b/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/tesla_settings.h new file mode 100644 index 000000000..5c40324dc --- /dev/null +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/tesla_settings.h @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + * + * This file is part of sunnypilot and is licensed under the MIT License. + * See the LICENSE.md file in the root directory for more details. + */ + +#pragma once + +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/brand_settings_interface.h" + +#include "selfdrive/ui/qt/util.h" +#include "selfdrive/ui/sunnypilot/ui.h" +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/settings.h" +#include "selfdrive/ui/sunnypilot/qt/widgets/controls.h" + +class TeslaSettings : public BrandSettingsInterface { + Q_OBJECT + +public: + explicit TeslaSettings(QWidget *parent = nullptr); + void updatePanel(bool _offroad); + void updateSettings(); + +private: + bool offroad = false; +}; diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/toyota_settings.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/toyota_settings.cc new file mode 100644 index 000000000..13b4435d1 --- /dev/null +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/toyota_settings.cc @@ -0,0 +1,31 @@ +/** + * Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + * + * This file is part of sunnypilot and is licensed under the MIT License. + * See the LICENSE.md file in the root directory for more details. + */ + +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/toyota_settings.h" + +#include "selfdrive/ui/sunnypilot/qt/widgets/scrollview.h" + +ToyotaSettings::ToyotaSettings(QWidget *parent) : BrandSettingsInterface(parent) { + QVBoxLayout *main_layout = new QVBoxLayout(this); + main_layout->setContentsMargins(0, 0, 0, 0); + + ListWidget *list = new ListWidget(this, false); + + main_layout->addWidget(new ScrollViewSP(list, this)); +} + +void ToyotaSettings::updatePanel(bool _offroad) { + updateSettings(); + + offroad = _offroad; +} + +void ToyotaSettings::updateSettings() { + if (!isVisible()) { + return; + } +} diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/toyota_settings.h b/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/toyota_settings.h new file mode 100644 index 000000000..46c8ef982 --- /dev/null +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/toyota_settings.h @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + * + * This file is part of sunnypilot and is licensed under the MIT License. + * See the LICENSE.md file in the root directory for more details. + */ + +#pragma once + +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/brand_settings_interface.h" + +#include "selfdrive/ui/qt/util.h" +#include "selfdrive/ui/sunnypilot/ui.h" +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/settings.h" +#include "selfdrive/ui/sunnypilot/qt/widgets/controls.h" + +class ToyotaSettings : public BrandSettingsInterface { + Q_OBJECT + +public: + explicit ToyotaSettings(QWidget *parent = nullptr); + void updatePanel(bool _offroad); + void updateSettings(); + +private: + bool offroad = false; +}; diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/volkswagen_settings.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/volkswagen_settings.cc new file mode 100644 index 000000000..457776f50 --- /dev/null +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/volkswagen_settings.cc @@ -0,0 +1,31 @@ +/** + * Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + * + * This file is part of sunnypilot and is licensed under the MIT License. + * See the LICENSE.md file in the root directory for more details. + */ + +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/volkswagen_settings.h" + +#include "selfdrive/ui/sunnypilot/qt/widgets/scrollview.h" + +VolkswagenSettings::VolkswagenSettings(QWidget *parent) : BrandSettingsInterface(parent) { + QVBoxLayout *main_layout = new QVBoxLayout(this); + main_layout->setContentsMargins(0, 0, 0, 0); + + ListWidget *list = new ListWidget(this, false); + + main_layout->addWidget(new ScrollViewSP(list, this)); +} + +void VolkswagenSettings::updatePanel(bool _offroad) { + updateSettings(); + + offroad = _offroad; +} + +void VolkswagenSettings::updateSettings() { + if (!isVisible()) { + return; + } +} diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/volkswagen_settings.h b/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/volkswagen_settings.h new file mode 100644 index 000000000..c74123e7b --- /dev/null +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/volkswagen_settings.h @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors. + * + * This file is part of sunnypilot and is licensed under the MIT License. + * See the LICENSE.md file in the root directory for more details. + */ + +#pragma once + +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/brand_settings_interface.h" + +#include "selfdrive/ui/qt/util.h" +#include "selfdrive/ui/sunnypilot/ui.h" +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/settings.h" +#include "selfdrive/ui/sunnypilot/qt/widgets/controls.h" + +class VolkswagenSettings : public BrandSettingsInterface { + Q_OBJECT + +public: + explicit VolkswagenSettings(QWidget *parent = nullptr); + void updatePanel(bool _offroad); + void updateSettings(); + +private: + bool offroad = false; +}; diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle_panel.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle_panel.cc index bc9f645f3..7ba5790ac 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle_panel.cc +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle_panel.cc @@ -7,7 +7,8 @@ #include "selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle_panel.h" -#include "selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/hyundai_settings.h" +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/brand_settings_factory.h" +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/brands.h" #include "selfdrive/ui/sunnypilot/qt/widgets/scrollview.h" VehiclePanel::VehiclePanel(QWidget *parent) : QFrame(parent) { @@ -25,9 +26,7 @@ VehiclePanel::VehiclePanel(QWidget *parent) : QFrame(parent) { ScrollViewSP *scroller = new ScrollViewSP(list, this); vlayout->addWidget(scroller); - hyundaiSettings = new HyundaiSettings(this); - vlayout->addWidget(hyundaiSettings); - hyundaiSettings->setVisible(false); + currentBrandSettings = nullptr; QObject::connect(uiState(), &UIState::offroadTransition, this, &VehiclePanel::updatePanel); @@ -41,9 +40,7 @@ void VehiclePanel::showEvent(QShowEvent *event) { void VehiclePanel::updatePanel(bool _offroad) { platformSelector->refresh(_offroad); - updateBrandSettings(); - offroad = _offroad; } @@ -52,14 +49,17 @@ void VehiclePanel::updateBrandSettings() { return; } - resetBrandSettings(); + if (currentBrandSettings) { + vehicleScreen->layout()->removeWidget(currentBrandSettings); + delete currentBrandSettings; + currentBrandSettings = nullptr; + } - QString brand = platformSelector->getPlatformBundle("brand").toString(); - if (brand == "hyundai") { - hyundaiSettings->setVisible(true); + if (BrandSettingsFactory::isBrandSupported(platformSelector->brand)) { + currentBrandSettings = BrandSettingsFactory::createBrandSettings(platformSelector->brand, this); + if (currentBrandSettings) { + vehicleScreen->layout()->addWidget(currentBrandSettings); + currentBrandSettings->updatePanel(offroad); + } } } - -void VehiclePanel::resetBrandSettings() { - hyundaiSettings->setVisible(false); -} diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle_panel.h b/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle_panel.h index 5548ff718..5fc03d3d6 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle_panel.h +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle_panel.h @@ -9,7 +9,7 @@ #include "selfdrive/ui/sunnypilot/qt/offroad/settings/settings.h" -#include "selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/hyundai_settings.h" +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/brand_settings_interface.h" #include "selfdrive/ui/sunnypilot/qt/offroad/settings/vehicle/platform_selector.h" class VehiclePanel : public QFrame { @@ -23,15 +23,10 @@ public slots: void updatePanel(bool _offroad); private: - void resetBrandSettings(); - QStackedLayout* main_layout = nullptr; QWidget* vehicleScreen = nullptr; PlatformSelector* platformSelector = nullptr; - - // brand panels - HyundaiSettings* hyundaiSettings = nullptr; - + BrandSettingsInterface* currentBrandSettings = nullptr; bool offroad = false; private slots: diff --git a/selfdrive/ui/sunnypilot/qt/widgets/controls.h b/selfdrive/ui/sunnypilot/qt/widgets/controls.h index d1edaf862..2a1bc20ac 100644 --- a/selfdrive/ui/sunnypilot/qt/widgets/controls.h +++ b/selfdrive/ui/sunnypilot/qt/widgets/controls.h @@ -219,7 +219,7 @@ class ButtonParamControlSP : public AbstractControlSP_SELECTOR { public: ButtonParamControlSP(const QString ¶m, const QString &title, const QString &desc, const QString &icon, - const std::vector &button_texts, const int minimum_button_width = 300) : AbstractControlSP_SELECTOR(title, desc, icon), button_texts(button_texts) { + const std::vector &button_texts, const int minimum_button_width = 300, const bool inline_layout = false) : AbstractControlSP_SELECTOR(title, desc, icon), button_texts(button_texts), is_inline_layout(inline_layout) { const QString style = R"( QPushButton { border-radius: 20px; @@ -246,6 +246,19 @@ public: key = param.toStdString(); int value = atoi(params.get(key).c_str()); + if (inline_layout) { + button_param_layout->setMargin(0); + button_param_layout->setSpacing(0); + if (!title.isEmpty()) { + main_layout->removeWidget(title_label); + hlayout->addWidget(title_label, 1); + } + if (spacingItem != nullptr && main_layout->indexOf(spacingItem) != -1) { + main_layout->removeItem(spacingItem); + spacingItem = nullptr; + } + } + button_group = new QButtonGroup(this); button_group->setExclusive(true); for (int i = 0; i < button_texts.size(); i++) { @@ -254,12 +267,18 @@ public: button->setChecked(i == value); button->setStyleSheet(style); button->setMinimumWidth(minimum_button_width); - if (i == 0) hlayout->addSpacing(2); - hlayout->addWidget(button); + if (i == 0) button_param_layout->addSpacing(2); + button_param_layout->addWidget(button); button_group->addButton(button, i); } - hlayout->setAlignment(Qt::AlignLeft); + button_param_layout->setAlignment(Qt::AlignLeft); + if (is_inline_layout) { + QFrame *container = new QFrame; + container->setLayout(button_param_layout); + container->setStyleSheet("background-color: #393939; border-radius: 20px;"); + hlayout->addWidget(container); + } QObject::connect(button_group, QOverload::of(&QButtonGroup::buttonClicked), [=](int id) { params.put(key, std::to_string(id)); @@ -314,6 +333,10 @@ public: protected: void paintEvent(QPaintEvent *event) override { + if (is_inline_layout) { + return; + } + QPainter p(this); p.setRenderHint(QPainter::Antialiasing); @@ -348,6 +371,8 @@ private: std::vector button_texts; bool button_group_enabled = true; + bool is_inline_layout; + QHBoxLayout *button_param_layout = is_inline_layout ? new QHBoxLayout() : hlayout; }; class ListWidgetSP : public QWidget { @@ -360,7 +385,7 @@ public: outer_layout.addLayout(&inner_layout); inner_layout.setMargin(0); inner_layout.setSpacing(25); // default spacing is 25 - outer_layout.addStretch(); + outer_layout.addStretch(1); } inline void addItem(QWidget *w) { inner_layout.addWidget(w); } inline void addItem(QLayout *layout) { inner_layout.addLayout(layout); } @@ -416,8 +441,8 @@ class OptionControlSP : public AbstractControlSP_SELECTOR { Q_OBJECT private: - bool isInlineLayout; - QHBoxLayout *optionSelectorLayout = isInlineLayout ? new QHBoxLayout() : hlayout; + bool is_inline_layout; + QHBoxLayout *optionSelectorLayout = is_inline_layout ? new QHBoxLayout() : hlayout; struct MinMaxValue { int min_value; @@ -438,7 +463,7 @@ private: public: OptionControlSP(const QString ¶m, const QString &title, const QString &desc, const QString &icon, - const MinMaxValue &range, const int per_value_change = 1, const bool inline_layout = false, const QMap *valMap = nullptr) : AbstractControlSP_SELECTOR(title, desc, icon, nullptr), _title(title), valueMap(valMap), isInlineLayout(inline_layout) { + const MinMaxValue &range, const int per_value_change = 1, const bool inline_layout = false, const QMap *valMap = nullptr) : AbstractControlSP_SELECTOR(title, desc, icon, nullptr), _title(title), valueMap(valMap), is_inline_layout(inline_layout) { const QString style = R"( QPushButton { border-radius: 20px; @@ -513,7 +538,7 @@ public: } optionSelectorLayout->setAlignment(Qt::AlignLeft); - if (isInlineLayout) { + if (is_inline_layout) { QFrame *container = new QFrame; container->setLayout(optionSelectorLayout); container->setStyleSheet("background-color: #393939; border-radius: 20px;"); @@ -540,7 +565,7 @@ public: protected: void paintEvent(QPaintEvent *event) override { - if (isInlineLayout) { + if (is_inline_layout) { return; } @@ -633,16 +658,6 @@ public: } } -protected: - // Override mouse release event to handle style updates smoothly - void mouseReleaseEvent(QMouseEvent *event) override { - if (!key.empty()) { - bool next_state = !params.getBool(key); - updateStyle(next_state); - } - QPushButton::mouseReleaseEvent(event); - } - private: std::string key = ""; Params params; @@ -651,13 +666,14 @@ private: QString btn_enabled_off_style = "QPushButton:enabled { background-color: #393939; }"; QString btn_enabled_on_style = "QPushButton:enabled { background-color: #1e79e8; }"; - QString btn_pressed_style = "QPushButton:pressed { background-color: #4A4A4A; }"; - QString btn_disabled_stype = "QPushButton:disabled { background-color: #121212; color: #5C5C5C; }"; + QString btn_off_pressed_style = "QPushButton:pressed { background-color: #4A4A4A; }"; + QString btn_on_pressed_style = "QPushButton:pressed { background-color: #1E8FFF; }"; + QString btn_disabled_style = "QPushButton:disabled { background-color: #121212; color: #5C5C5C; }"; void updateStyle(bool enabled) { QString enabled_style = enabled ? btn_enabled_on_style : btn_enabled_off_style; - - setStyleSheet(buttonStyle + enabled_style + btn_pressed_style + btn_disabled_stype); + QString pressed_style = enabled ? btn_on_pressed_style : btn_off_pressed_style; + setStyleSheet(buttonStyle + enabled_style + pressed_style + btn_disabled_style); } }; diff --git a/selfdrive/ui/tests/test_ui/run.py b/selfdrive/ui/tests/test_ui/run.py index 064ef14a7..9d078fdd9 100755 --- a/selfdrive/ui/tests/test_ui/run.py +++ b/selfdrive/ui/tests/test_ui/run.py @@ -37,7 +37,7 @@ DATA: dict[str, capnp.lib.capnp._DynamicStructBuilder] = dict.fromkeys( "driverStateV2", "roadCameraState", "wideRoadCameraState", "driverCameraState"], None) def setup_homescreen(click, pm: PubMaster, scroll=None): - pass + time.sleep(UI_DELAY) def setup_settings_device(click, pm: PubMaster, scroll=None): click(100, 100) @@ -61,6 +61,7 @@ def setup_settings_software(click, pm: PubMaster, scroll=None): time.sleep(UI_DELAY) def setup_settings_firehose(click, pm: PubMaster, scroll=None): + setup_settings_device(click, pm) scroll(-400, 278, 962) click(278, 862) @@ -151,7 +152,7 @@ def setup_keyboard_uppercase(click, pm: PubMaster, scroll=None): def setup_driver_camera(click, pm: PubMaster, scroll=None): setup_settings_device(click, pm) - click(1720, 620) + click(1720, 825) DATA['deviceState'].deviceState.started = False setup_onroad(click, pm) DATA['deviceState'].deviceState.started = True diff --git a/sunnypilot/modeld_v2/modeld.py b/sunnypilot/modeld_v2/modeld.py index e0f38c59a..a52d844ae 100755 --- a/sunnypilot/modeld_v2/modeld.py +++ b/sunnypilot/modeld_v2/modeld.py @@ -53,8 +53,8 @@ class ModelState: self.frames = {'input_imgs': DrivingModelFrame(context, buffer_length), 'big_input_imgs': DrivingModelFrame(context, buffer_length)} self.prev_desire = np.zeros(ModelConstants.DESIRE_LEN, dtype=np.float32) if self.model_runner.is_20hz: - self.full_features_20Hz = np.zeros((ModelConstants.FULL_HISTORY_BUFFER_LEN, ModelConstants.FEATURE_LEN), dtype=np.float32) - self.desire_20Hz = np.zeros((ModelConstants.FULL_HISTORY_BUFFER_LEN + 1, ModelConstants.DESIRE_LEN), dtype=np.float32) + self.full_features_buffer = np.zeros((ModelConstants.FULL_HISTORY_BUFFER_LEN, ModelConstants.FEATURE_LEN), dtype=np.float32) + self.full_desire = np.zeros((ModelConstants.FULL_HISTORY_BUFFER_LEN + 1, ModelConstants.DESIRE_LEN), dtype=np.float32) # img buffers are managed in openCL transform code self.numpy_inputs = {} @@ -66,7 +66,7 @@ class ModelState: if self.model_runner.is_20hz: num_elements = self.numpy_inputs['features_buffer'].shape[1] step_size = int(-100 / num_elements) - self.full_features_20Hz_idxs = np.arange(step_size, step_size * (num_elements + 1), step_size)[::-1] + self.full_features_buffer_idxs = np.arange(step_size, step_size * (num_elements + 1), step_size)[::-1] self.desire_reshape_dims = (self.numpy_inputs['desire'].shape[0], self.numpy_inputs['desire'].shape[1], -1, self.numpy_inputs['desire'].shape[2]) def run(self, buf: VisionBuf, wbuf: VisionBuf, transform: np.ndarray, transform_wide: np.ndarray, @@ -77,9 +77,9 @@ class ModelState: self.prev_desire[:] = inputs['desire'] if self.model_runner.is_20hz: - self.desire_20Hz[:-1] = self.desire_20Hz[1:] - self.desire_20Hz[-1] = new_desire - self.numpy_inputs['desire'][:] = self.desire_20Hz.reshape(self.desire_reshape_dims).max(axis=2) + self.full_desire[:-1] = self.full_desire[1:] + self.full_desire[-1] = new_desire + self.numpy_inputs['desire'][:] = self.full_desire.reshape(self.desire_reshape_dims).max(axis=2) else: length = inputs['desire'].shape[0] self.numpy_inputs['desire'][0, :-1] = self.numpy_inputs['desire'][0, 1:] @@ -102,9 +102,9 @@ class ModelState: outputs = self.model_runner.run_model() if self.model_runner.is_20hz: - self.full_features_20Hz[:-1] = self.full_features_20Hz[1:] - self.full_features_20Hz[-1] = outputs['hidden_state'][0, :] - self.numpy_inputs['features_buffer'][:] = self.full_features_20Hz[self.full_features_20Hz_idxs] + self.full_features_buffer[:-1] = self.full_features_buffer[1:] + self.full_features_buffer[-1] = outputs['hidden_state'][0, :] + self.numpy_inputs['features_buffer'][:] = self.full_features_buffer[self.full_features_buffer_idxs] else: feature_len = outputs['hidden_state'].shape[1] self.numpy_inputs['features_buffer'][0, :-1] = self.numpy_inputs['features_buffer'][0, 1:] diff --git a/sunnypilot/models/helpers.py b/sunnypilot/models/helpers.py index 7bcf1a148..e6001f264 100644 --- a/sunnypilot/models/helpers.py +++ b/sunnypilot/models/helpers.py @@ -19,7 +19,7 @@ from openpilot.system.hardware import PC from openpilot.system.hardware.hw import Paths from pathlib import Path -CURRENT_SELECTOR_VERSION = 2 +CURRENT_SELECTOR_VERSION = 3 REQUIRED_MIN_SELECTOR_VERSION = 2 USE_ONNX = os.getenv('USE_ONNX', PC) diff --git a/sunnypilot/selfdrive/car/interfaces.py b/sunnypilot/selfdrive/car/interfaces.py index f2019f5ed..2c27e960e 100644 --- a/sunnypilot/selfdrive/car/interfaces.py +++ b/sunnypilot/selfdrive/car/interfaces.py @@ -11,7 +11,6 @@ from opendbc.car.car_helpers import can_fingerprint from opendbc.car.interfaces import CarInterfaceBase from opendbc.car.hyundai.radar_interface import RADAR_START_ADDR from opendbc.car.hyundai.values import HyundaiFlags, DBC as HYUNDAI_DBC -from opendbc.sunnypilot.car.hyundai.longitudinal.helpers import LongitudinalTuningType from opendbc.sunnypilot.car.hyundai.values import HyundaiFlagsSP from openpilot.common.params import Params from openpilot.common.swaglog import cloudlog @@ -26,21 +25,6 @@ def log_fingerprint(CP: structs.CarParams) -> None: else: sentry.capture_fingerprint(CP.carFingerprint, CP.brand) -def _initialize_custom_longitudinal_tuning(CI: CarInterfaceBase, CP: structs.CarParams, CP_SP: structs.CarParamsSP, - params: Params = None) -> None: - if params is None: - params = Params() - - # Hyundai Custom Longitudinal Tuning - if CP.brand == 'hyundai': - hyundai_longitudinal_tuning = int(params.get("HyundaiLongitudinalTuning", encoding="utf8") or 0) - if hyundai_longitudinal_tuning == LongitudinalTuningType.DYNAMIC: - CP_SP.flags |= HyundaiFlagsSP.LONG_TUNING_DYNAMIC.value - if hyundai_longitudinal_tuning == LongitudinalTuningType.PREDICTIVE: - CP_SP.flags |= HyundaiFlagsSP.LONG_TUNING_PREDICTIVE.value - - CP_SP = CI.get_longitudinal_tuning_sp(CP, CP_SP) - def _initialize_neural_network_lateral_control(CI: CarInterfaceBase, CP: structs.CarParams, CP_SP: structs.CarParamsSP, params: Params = None, enabled: bool = False) -> None: @@ -77,11 +61,10 @@ def _initialize_radar_tracks(CP: structs.CarParams, CP_SP: structs.CarParamsSP, CP.radarUnavailable = False -def setup_interfaces(CI: CarInterfaceBase, params: Params = None) -> None: +def setup_interfaces(CI: CarInterfaceBase, params: Params = None): CP = CI.CP CP_SP = CI.CP_SP - _initialize_custom_longitudinal_tuning(CI, CP, CP_SP, params) _initialize_neural_network_lateral_control(CI, CP, CP_SP, params) _initialize_radar_tracks(CP, CP_SP, params) diff --git a/sunnypilot/selfdrive/controls/lib/longitudinal_planner.py b/sunnypilot/selfdrive/controls/lib/longitudinal_planner.py index 56f32373d..9f0c503fb 100644 --- a/sunnypilot/selfdrive/controls/lib/longitudinal_planner.py +++ b/sunnypilot/selfdrive/controls/lib/longitudinal_planner.py @@ -7,6 +7,7 @@ See the LICENSE.md file in the root directory for more details. from cereal import messaging, custom from opendbc.car import structs +from openpilot.sunnypilot.models.helpers import get_active_model_runner from openpilot.sunnypilot.selfdrive.controls.lib.dec.dec import DynamicExperimentalController DecState = custom.LongitudinalPlanSP.DynamicExperimentalControl.DynamicExperimentalControlState @@ -15,6 +16,7 @@ DecState = custom.LongitudinalPlanSP.DynamicExperimentalControl.DynamicExperimen class LongitudinalPlannerSP: def __init__(self, CP: structs.CarParams, mpc): self.dec = DynamicExperimentalController(CP, mpc) + self.is_stock = get_active_model_runner() == custom.ModelManagerSP.Runner.stock def get_mpc_mode(self) -> str | None: if not self.dec.active(): diff --git a/system/manager/manager.py b/system/manager/manager.py index 90df415a8..fde85f0f7 100755 --- a/system/manager/manager.py +++ b/system/manager/manager.py @@ -45,7 +45,6 @@ def manager_init() -> None: ("AutoLaneChangeTimer", "0"), ("AutoLaneChangeBsmDelay", "0"), ("DynamicExperimentalControl", "0"), - ("HyundaiLongitudinalTuning", "0"), ("Mads", "1"), ("MadsMainCruiseAllowed", "1"), ("MadsPauseLateralOnBrake", "0"),