mirror of
https://github.com/infiniteCable2/openpilot.git
synced 2026-09-08 09:13:42 +08:00
Merge branch 'master-new' of https://github.com/sunnypilot/sunnypilot into master-new
This commit is contained in:
@@ -170,7 +170,6 @@ inline static std::unordered_map<std::string, uint32_t> keys = {
|
||||
{"BackupManager_RestoreVersion", PERSISTENT},
|
||||
|
||||
// sunnypilot car specific params
|
||||
{"HyundaiLongitudinalTuning", PERSISTENT},
|
||||
{"HyundaiRadarTracks", PERSISTENT},
|
||||
{"HyundaiRadarTracksConfirmed", PERSISTENT},
|
||||
{"HyundaiRadarTracksPersistent", PERSISTENT},
|
||||
|
||||
@@ -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])
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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<PushButtonSP*>()) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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();
|
||||
};
|
||||
@@ -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"
|
||||
@@ -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 <QWidget>
|
||||
|
||||
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;
|
||||
};
|
||||
@@ -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"
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
@@ -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<QString> 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<cereal::CarParams>();
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
@@ -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<cereal::CarParams>();
|
||||
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("<b>%1</b><br><br>%2")
|
||||
.arg(platform, offroad_msg);
|
||||
.arg(_platform, offroad_msg);
|
||||
|
||||
QString content("<body><h2 style=\"text-align: center;\">" + tr("Vehicle Selector") + "</h2><br>"
|
||||
"<p style=\"text-align: center; margin: 0 128px; font-size: 50px;\">" + msg + "</p></body>");
|
||||
@@ -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();
|
||||
|
||||
@@ -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 = "<font color='white'><b>" + auto_str + "</b></font>";
|
||||
} else if (status == FingerprintStatus::MANUAL_FINGERPRINT) {
|
||||
manual_str = "<font color='white'><b>" + manual_str + "</b></font>";
|
||||
} else {
|
||||
unrecognized_str = "<font color='white'><b>" + unrecognized_str + "</b></font>";
|
||||
}
|
||||
|
||||
return QString("%1<br>%2<br><br>%3<br>%4<br>%5")
|
||||
.arg(tr("Select vehicle to force fingerprint manually."))
|
||||
.arg(tr("Colors represent fingerprint status:"))
|
||||
.arg(auto_str)
|
||||
.arg(manual_str)
|
||||
.arg(unrecognized_str);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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<QString> &button_texts, const int minimum_button_width = 300) : AbstractControlSP_SELECTOR(title, desc, icon), button_texts(button_texts) {
|
||||
const std::vector<QString> &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<int>::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<QString> 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<QString, QString> *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<QString, QString> *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);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:]
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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():
|
||||
|
||||
@@ -45,7 +45,6 @@ def manager_init() -> None:
|
||||
("AutoLaneChangeTimer", "0"),
|
||||
("AutoLaneChangeBsmDelay", "0"),
|
||||
("DynamicExperimentalControl", "0"),
|
||||
("HyundaiLongitudinalTuning", "0"),
|
||||
("Mads", "1"),
|
||||
("MadsMainCruiseAllowed", "1"),
|
||||
("MadsPauseLateralOnBrake", "0"),
|
||||
|
||||
Reference in New Issue
Block a user