From 2fa7a4cf7f534287e36c796c274d0c5cbf86774c Mon Sep 17 00:00:00 2001 From: Jason Wen <47793918+sunnyhaibin@users.noreply.github.com> Date: Mon, 6 Feb 2023 18:11:22 -0500 Subject: [PATCH] UI: initialize settings (#20) * sunnypilot ui init * ui controls init * comment out for now * use ListWidget instead moving forward * wrap for translation * quick test * need this * good to go, no need for now * start with some * some html * that didn't work * fill up General first * add mads options * add mads options 2 * add mads options 3 * add mads options 4 * add mads options 5 * add mads options 6 * add mads options 7 * add mads options 8 * add mads options 9 * add mads options 10 * add mads options 11 * add mads options 12 * add mads options 13 * add mads options 14 * add mads options 15 * add mads options 16 * add mads options 17 * add mads options 18 * add mads options 19 * add mads options 20 * add mads options 21 * add mads options 22 * add mads options 22 * add dlp * add dlp * add dlp * finish up controls panel * QWidget has no refresh() * fix this tr() later * flipped and redundant deleted * missing icons * Bolding * Revert "Revert "Don't delete params"" This reverts commit 7adfc172d599da0e450669a203f5cdb17a32a9d6. * Revert "Revert "Revert "Don't delete params""" This reverts commit 33f28677f1a69fb18c7d1a08c5f02a497005dfbe. * Revert "Revert "don't forget this"" This reverts commit f4485920ed5318e4662e4955a699febb9ba27159. * Revert "Revert "fill up sp - vehicles"" This reverts commit dfab593833ca5a9cb26fb89f36bf7ac19f7432bf. * Revert "Revert "missed this"" This reverts commit bf4ac0289b164ca59cb49c355fa8a5303c66b016. * Revert "Revert "missed that"" This reverts commit da81b7f9eb4e7bbafced4a7a31cb4b7a078d2277. * Revert "Revert "missed these"" This reverts commit 742908dcf5220a93da57a54836b2b890bbbd519a. * Revert "Revert "nicer info?"" This reverts commit e0d6c1c05da394774ad0a7ee0b5c5e5c7f55c08a. * Revert "Revert "fill up sp visuals"" This reverts commit 35759838e0ba4a36f36a12ff1001846b32ddd0c7. * Revert "Revert "don't miss these"" This reverts commit 7f093380b470a7c195d1f6795b76393b72d4e2f7. * Revert "Revert "Revert "ui controls init""" This reverts commit 67c531487e9501ca5658297a20061b88f91c10cc. * Revert "Revert "move stuff around"" This reverts commit 03b72af6d01772b18c506f590e92b6dbc95c2bfc. * change to sunnypilot * update texts * fix * does this work? * Revert "does this work?" This reverts commit 7b3caf3677593550065efe553334d0797dc5ea00. * try this out * add some back * arrange around * maybe less I/O * missing a space * Translate these too * unfinished translations * try this out * easier translation * refresh unfinished translations * update menu texts with Chinese S and T! * missed this translation * more unfinished translations --- selfdrive/assets/offroad/icon_acc_change.png | Bin 0 -> 12267 bytes selfdrive/assets/offroad/icon_blank.png | Bin 0 -> 15538 bytes selfdrive/assets/offroad/icon_dynamic_gac.png | Bin 0 -> 27685 bytes selfdrive/ui/SConscript | 3 +- selfdrive/ui/qt/offroad/settings.cc | 22 +- .../ui/qt/offroad/sunnypilot_settings.cc | 1670 +++++++++++++++++ selfdrive/ui/qt/offroad/sunnypilot_settings.h | 316 ++++ selfdrive/ui/qt/util.cc | 15 +- selfdrive/ui/qt/util.h | 1 + selfdrive/ui/translations/main_de.ts | 660 ++++++- selfdrive/ui/translations/main_ja.ts | 660 ++++++- selfdrive/ui/translations/main_ko.ts | 660 ++++++- selfdrive/ui/translations/main_pt-BR.ts | 660 ++++++- selfdrive/ui/translations/main_zh-CHS.ts | 660 ++++++- selfdrive/ui/translations/main_zh-CHT.ts | 660 ++++++- 15 files changed, 5833 insertions(+), 154 deletions(-) create mode 100644 selfdrive/assets/offroad/icon_acc_change.png create mode 100644 selfdrive/assets/offroad/icon_blank.png create mode 100644 selfdrive/assets/offroad/icon_dynamic_gac.png create mode 100644 selfdrive/ui/qt/offroad/sunnypilot_settings.cc create mode 100644 selfdrive/ui/qt/offroad/sunnypilot_settings.h diff --git a/selfdrive/assets/offroad/icon_acc_change.png b/selfdrive/assets/offroad/icon_acc_change.png new file mode 100644 index 0000000000000000000000000000000000000000..e1e80cd17219707a784cce913921599ded38665d GIT binary patch literal 12267 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 literal 0 HcmV?d00001 diff --git a/selfdrive/assets/offroad/icon_dynamic_gac.png b/selfdrive/assets/offroad/icon_dynamic_gac.png new file mode 100644 index 0000000000000000000000000000000000000000..973715dad12b88f03c71b913fe398265e1f75639 GIT binary patch literal 27685 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 P?e#)NLQ%Xz%rM}8iGQe{ literal 0 HcmV?d00001 diff --git a/selfdrive/ui/SConscript b/selfdrive/ui/SConscript index 0f28f5ccc3..5fd0936a44 100644 --- a/selfdrive/ui/SConscript +++ b/selfdrive/ui/SConscript @@ -24,7 +24,8 @@ widgets_src = ["ui.cc", "qt/widgets/input.cc", "qt/widgets/drive_stats.cc", "qt/widgets/ssh_keys.cc", "qt/widgets/toggle.cc", "qt/widgets/controls.cc", "qt/widgets/offroad_alerts.cc", "qt/widgets/prime.cc", "qt/widgets/keyboard.cc", "qt/widgets/scrollview.cc", "qt/widgets/cameraview.cc", "#third_party/qrcode/QrCode.cc", - "qt/request_repeater.cc", "qt/qt_window.cc", "qt/offroad/networking.cc", "qt/offroad/wifiManager.cc"] + "qt/request_repeater.cc", "qt/qt_window.cc", "qt/offroad/networking.cc", "qt/offroad/wifiManager.cc", + "qt/offroad/sunnypilot_settings.cc"] qt_env['CPPDEFINES'] = [] if maps: diff --git a/selfdrive/ui/qt/offroad/settings.cc b/selfdrive/ui/qt/offroad/settings.cc index 63b87149d4..a6d11b0267 100644 --- a/selfdrive/ui/qt/offroad/settings.cc +++ b/selfdrive/ui/qt/offroad/settings.cc @@ -16,6 +16,7 @@ #include "common/watchdog.h" #include "common/util.h" #include "system/hardware/hw.h" +#include "selfdrive/ui/qt/offroad/sunnypilot_settings.h" #include "selfdrive/ui/qt/widgets/controls.h" #include "selfdrive/ui/qt/widgets/input.h" #include "selfdrive/ui/qt/widgets/scrollview.h" @@ -31,8 +32,8 @@ TogglesPanel::TogglesPanel(SettingsWindow *parent) : ListWidget(parent) { std::vector> toggle_defs{ { "OpenpilotEnabledToggle", - tr("Enable openpilot"), - tr("Use the openpilot system for adaptive cruise control and lane keep driver assistance. Your attention is required at all times to use this feature. Changing this setting takes effect when the car is powered off."), + tr("Enable sunnypilot"), + tr("Use the sunnypilot system for adaptive cruise control and lane keep driver assistance. Your attention is required at all times to use this feature. Changing this setting takes effect when the car is powered off."), "../assets/offroad/icon_openpilot.png", }, { @@ -70,7 +71,7 @@ TogglesPanel::TogglesPanel(SettingsWindow *parent) : ListWidget(parent) { { "DisengageOnAccelerator", tr("Disengage on Accelerator Pedal"), - tr("When enabled, pressing the accelerator pedal will disengage openpilot."), + tr("When enabled, pressing the accelerator pedal will disengage sunnypilot."), "../assets/offroad/icon_disengage_on_accelerator.svg", }, #ifdef ENABLE_MAPS @@ -198,7 +199,7 @@ DevicePanel::DevicePanel(SettingsWindow *parent) : ListWidget(parent) { addItem(resetCalibBtn); if (!params.getBool("Passive")) { - auto retrainingBtn = new ButtonControl(tr("Review Training Guide"), tr("REVIEW"), tr("Review the rules, features, and limitations of openpilot")); + auto retrainingBtn = new ButtonControl(tr("Review Training Guide"), tr("REVIEW"), tr("Review the rules, features, and limitations of sunnypilot")); connect(retrainingBtn, &ButtonControl::clicked, [=]() { if (ConfirmationDialog::confirm(tr("Are you sure you want to review the training guide?"), tr("Review"), this)) { emit reviewTrainingGuide(); @@ -264,8 +265,8 @@ DevicePanel::DevicePanel(SettingsWindow *parent) : ListWidget(parent) { void DevicePanel::updateCalibDescription() { QString desc = - tr("openpilot requires the device to be mounted within 4° left or right and " - "within 5° up or 8° down. openpilot is continuously calibrating, resetting is rarely required."); + tr("sunnypilot requires the device to be mounted within 4° left or right and " + "within 5° up or 8° down. sunnypilot is continuously calibrating, resetting is rarely required."); std::string calib_bytes = Params().get("CalibrationParams"); if (!calib_bytes.empty()) { try { @@ -378,7 +379,12 @@ SettingsWindow::SettingsWindow(QWidget *parent) : QFrame(parent) { QObject::connect(map_panel, &MapPanel::closeSettings, this, &SettingsWindow::closeSettings); #endif - const int padding = panels.size() > 3 ? 25 : 35; + panels.push_back({tr("SP - General"), new SPGeneralPanel(this)}); + panels.push_back({tr("SP - Controls"), new SPControlsPanel(this)}); + panels.push_back({tr("SP - Vehicles"), new SPVehiclesPanel(this)}); + panels.push_back({tr("SP - Visuals"), new SPVisualsPanel(this)}); + + const int padding = panels.size() > 3 ? 5 : 35; nav_btns = new QButtonGroup(this); for (auto &[name, panel] : panels) { @@ -390,7 +396,7 @@ SettingsWindow::SettingsWindow(QWidget *parent) : QFrame(parent) { color: grey; border: none; background: none; - font-size: 65px; + font-size: 50px; font-weight: 500; padding-top: %1px; padding-bottom: %1px; diff --git a/selfdrive/ui/qt/offroad/sunnypilot_settings.cc b/selfdrive/ui/qt/offroad/sunnypilot_settings.cc new file mode 100644 index 0000000000..19cc3f0793 --- /dev/null +++ b/selfdrive/ui/qt/offroad/sunnypilot_settings.cc @@ -0,0 +1,1670 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "common/watchdog.h" +#include "selfdrive/ui/qt/api.h" +#include "selfdrive/ui/qt/offroad/sunnypilot_settings.h" +#include "selfdrive/ui/qt/widgets/input.h" +#include "selfdrive/ui/qt/widgets/scrollview.h" +#include "selfdrive/ui/qt/util.h" + +#include "selfdrive/ui/ui.h" + +SPGeneralPanel::SPGeneralPanel(QWidget *parent) : QWidget(parent) { + main_layout = new QVBoxLayout(this); + + // General: Quiet Drive + main_layout->addWidget(new ParamControl( + "QuietDrive", + tr("Quiet Drive 🤫"), + tr("sunnypilot will display alerts but only play the most important warning sounds. This feature can be toggled while the car is on."), + "../assets/offroad/icon_mute.png" + )); + + // General: Green Traffic Light Chime + endToEndLongAlert = new ParamControl( + "EndToEndLongAlert", + tr("Green Traffic Light Chime (Beta)"), + QString("%1
" + "

%2


") + .arg(tr("A chime will play when the traffic light you are waiting for turns green and you have no vehicle in front of you. If you are waiting behind another vehicle, the chime will play once the vehicle advances unless ACC is engaged.")) + .arg(tr("Note: This chime is only designed as a notification. It is the driver's responsibility to observe their environment and make decisions accordingly.")), + "../assets/offroad/icon_road.png" + ); + endToEndLongAlert->setConfirmation(true, false); + main_layout->addWidget(horizontal_line()); + main_layout->addWidget(endToEndLongAlert); + + // General: Custom Boot Screen + main_layout->addWidget(horizontal_line()); + main_layout->addWidget(new ParamControl( + "CustomBootScreen", + tr("Custom Boot Screen"), + tr("Display sunnypilot welcome screen while booting the device."), + "../assets/offroad/icon_shell.png" + )); + + // General: Max Time Offroad (Shutdown timer) + main_layout->addWidget(horizontal_line()); + main_layout->addWidget(new MaxTimeOffroad()); + + // General: Onroad Screen Off (Auto Onroad Screen Timer) + main_layout->addWidget(horizontal_line()); + main_layout->addWidget(new OnroadScreenOff()); + + // General: Onroad Screen Off Brightness + main_layout->addWidget(horizontal_line()); + main_layout->addWidget(new OnroadScreenOffBrightness()); + + // General: Brightness Control (Global) + main_layout->addWidget(horizontal_line()); + main_layout->addWidget(new BrightnessControl()); + + // General: Disable Onroad Uploads + main_layout->addWidget(horizontal_line()); + main_layout->addWidget(new ParamControl( + "DisableOnroadUploads", + tr("Disable Onroad Uploads"), + tr("Disable uploads completely when onroad. Necessary to avoid high data usage when connected to Wi-Fi hotspot. Turn on this feature if you are looking to utilize map-based features, such as Speed Limit Control (SLC) and Map-based Turn Speed Control (MTSC)."), + "../assets/offroad/icon_network.png" + )); + + // General: Error Troubleshoot + auto errorBtn = new ButtonControl( + tr("Error Troubleshoot"), + tr("VIEW"), + tr("Display error from the tmux session when an error has occurred from a system process.") + ); + QFileInfo file("/data/community/crashes/error.txt"); + QDateTime modifiedTime = file.lastModified(); + QString modified_time = modifiedTime.toString("yyyy-MM-dd hh:mm:ss "); + connect(errorBtn, &ButtonControl::clicked, [=]() { + const std::string txt = util::read_file("/data/community/crashes/error.txt"); + ConfirmationDialog::rich(modified_time + QString::fromStdString(txt), this); + }); + main_layout->addWidget(horizontal_line()); + main_layout->addWidget(errorBtn); + + // General: Debug snapshot on screen center tap + main_layout->addWidget(horizontal_line()); + main_layout->addWidget(new ParamControl( + "EnableDebugSnapshot", + tr("Debug snapshot on screen center tap"), + tr("Stores snapshot file with current state of some modules."), + "../assets/offroad/icon_calibration.png" + )); +} + +SPControlsPanel::SPControlsPanel(QWidget *parent) : QWidget(parent) { + main_layout = new QVBoxLayout(this); + + // M.A.D.S. + madsMainControl = new QWidget(); + madsSubControl = new QVBoxLayout(madsMainControl); + // Controls: Enable M.A.D.S. + madsControl = new ParamControl( + "EnableMads", + tr("Enable M.A.D.S."), + tr("Enable the beloved M.A.D.S. feature. Disable toggle to revert back to stock openpilot engagement/disengagement."), + "../assets/offroad/icon_openpilot.png" + ); + madsControl->setConfirmation(true, false); + connect(uiState(), &UIState::offroadTransition, [=](bool offroad) { + madsControl->setEnabled(offroad); + }); + madsSubControl->setContentsMargins(QMargins()); + madsSubControl->addWidget(horizontal_line()); + + // Controls: Disengage ALC On Brake Pedal + disengageLateralOnBrake = new ParamControl( + "DisengageLateralOnBrake", + tr("Disengage ALC On Brake Pedal ℹ"), + QString("%1
" + "

%2


" + "

%3


") + .arg(tr("Define brake pedal interactions with sunnypilot when M.A.D.S. is enabled.")) + .arg(tr("Enabled: Pressing the brake pedal will disengage Automatic Lane Centering (ALC) on sunnypilot.")) + .arg(tr("Disabled: Pressing the brake pedal will NOT disengage Automatic Lane Centering (ALC) on sunnypilot.")), + "../assets/offroad/icon_openpilot.png" + ); + disengageLateralOnBrake->setConfirmation(true, false); + connect(uiState(), &UIState::offroadTransition, [=](bool offroad) { + disengageLateralOnBrake->setEnabled(offroad); + }); + madsSubControl->addWidget(disengageLateralOnBrake); + madsSubControl->addWidget(horizontal_line()); + + // Controls: Enable ACC+MADS with RES+/SET- + accMadsCombo = new ParamControl( + "AccMadsCombo", + tr("Enable ACC+MADS with RES+/SET-"), + QString("%1
" + "

%2


") + .arg(tr("Engage both M.A.D.S. and ACC with a single press of RES+ or SET- button.")) + .arg(tr("Note: Once M.A.D.S. is engaged via this mode, it will remain engaged until it is manually disabled via the M.A.D.S. button or car shut off.")), + "../assets/offroad/icon_openpilot.png" + ); + connect(uiState(), &UIState::offroadTransition, [=](bool offroad) { + accMadsCombo->setEnabled(offroad); + }); + madsSubControl->addWidget(accMadsCombo); + connect(madsControl, &ToggleControl::toggleFlipped, [=](bool state) { + updateToggles(); + }); + main_layout->addWidget(madsControl); + main_layout->addWidget(madsMainControl); + + + // Controls: Pause Lateral Below Speed w/ Blinker + belowSpeed = new ParamControl( + "BelowSpeedPause", + tr("Pause Lateral Below Speed w/ Blinker"), + tr("Enable this toggle to pause lateral actuation with blinker when traveling below 30 MPH or 50 KM/H."), + "../assets/offroad/icon_openpilot.png" + ); + connect(uiState(), &UIState::offroadTransition, [=](bool offroad) { + belowSpeed->setEnabled(offroad); + }); + main_layout->addWidget(horizontal_line()); + main_layout->addWidget(belowSpeed); + + // D.L.P. + dlpMain = new QWidget(); + dlpSub = new QVBoxLayout(dlpMain); + // Controls: Enable Dynamic Lane Profile + dlpControl = new ParamControl( + "DynamicLaneProfileToggle", + tr("Enable Dynamic Lane Profile"), + tr("Enable toggle to use Dynamic Lane Profile. Disable toggle to use Laneless only."), + "../assets/offroad/icon_road.png" + ); + + // Controls: Laneless for Curves in Auto lane + dlpCurve = new ParamControl( + "VisionCurveLaneless", + tr("Laneless for Curves in \"Auto lane\""), + tr("While in Auto Lane, switch to Laneless for current/future curves."), + "../assets/offroad/icon_blank.png" + ); + dlpSub->addWidget(horizontal_line()); + dlpSub->addWidget(dlpCurve); + connect(dlpControl, &ToggleControl::toggleFlipped, [=](bool state) { + updateToggles(); + }); + main_layout->addWidget(horizontal_line()); + main_layout->addWidget(dlpControl); + main_layout->addWidget(dlpMain); + + + // Custom Offsets + customOffsetsMain = new QWidget(); + customOffsetsSub = new QVBoxLayout(customOffsetsMain); + // Controls: Custom Offsets + customOffsets = new ParamControl( + "CustomOffsets", + tr("Custom Offsets"), + tr("Add custom offsets to Camera and Path in sunnypilot."), + "../assets/offroad/icon_metric.png" + ); + customOffsetsSub->setContentsMargins(QMargins()); + + // Controls: Camera Offset (cm) + customOffsetsSub->addWidget(horizontal_line()); + customOffsetsSub->addWidget(new CameraOffset()); + + // Controls: Path Offset (cm) + customOffsetsSub->addWidget(horizontal_line()); + customOffsetsSub->addWidget(new PathOffset()); + connect(customOffsets, &ToggleControl::toggleFlipped, [=](bool state) { + updateToggles(); + }); + main_layout->addWidget(horizontal_line()); + main_layout->addWidget(customOffsets); + main_layout->addWidget(customOffsetsMain); + + // Controls: Auto Lane Change Timer + main_layout->addWidget(horizontal_line()); + main_layout->addWidget(new AutoLaneChangeTimer()); + + // G.A.C. + gacMain = new QWidget(); + gacSub = new QVBoxLayout(gacMain); + // Controls: Enable Gap Adjust Cruise + gapAdjustCruise = new ParamControl( + "GapAdjustCruise", + tr("Enable Gap Adjust Cruise ℹ"), + QString("%1
" + "

%2

") + .arg(tr("Enable the Interval button on the steering wheel to adjust the cruise gap.")) + .arg(tr("Only available to cars with openpilot Longitudinal Control")), + "../assets/offroad/icon_dynamic_gac.png" + ); + gapAdjustCruise->setConfirmation(true, false); + gacSub->setContentsMargins(QMargins()); + + // Controls: Mode + gacSub->addWidget(horizontal_line()); + gacSub->addWidget(new GapAdjustCruiseMode()); + connect(gapAdjustCruise, &ToggleControl::toggleFlipped, [=](bool state) { + updateToggles(); + }); + main_layout->addWidget(horizontal_line()); + main_layout->addWidget(gapAdjustCruise); + main_layout->addWidget(gacMain); + + // Torque Lateral Control + torqueMain = new QWidget(); + torqueSub = new QVBoxLayout(torqueMain); + customTorqueMain = new QWidget(); + customTorqueSub = new QVBoxLayout(customTorqueMain); + // Controls: Enforce Torque Lateral Control + torqueLateral = new ParamControl( + "EnforceTorqueLateral", + tr("Enforce Torque Lateral Control"), + tr("Enable this to enforce sunnypilot to steer with Torque lateral control."), + "../assets/offroad/icon_calibration.png" + ); + connect(uiState(), &UIState::offroadTransition, [=](bool offroad) { + torqueLateral->setEnabled(offroad); + }); + // Torque Lateral Control Live Tune + customTorqueLateral = new ParamControl( + "CustomTorqueLateral", + tr("Torque Lateral Control Live Tune"), + tr("Enables live tune for Torque lateral control."), + "../assets/offroad/icon_calibration.png" + ); + connect(uiState(), &UIState::offroadTransition, [=](bool offroad) { + customTorqueLateral->setEnabled(offroad); + }); + customTorqueSub->setContentsMargins(QMargins()); + // Control: FRICTION + customTorqueSub->addWidget(horizontal_line()); + customTorqueSub->addWidget(new TorqueFriction()); + // Controls: LAT_ACCEL_FACTOR + customTorqueSub->addWidget(horizontal_line()); + customTorqueSub->addWidget(new TorqueMaxLatAccel()); + connect(customTorqueLateral, &ToggleControl::toggleFlipped, [=](bool state) { + updateToggles(); + ConfirmationDialog::alert(tr("\"Torque Lateral Control Live Tune\"
You must restart your car or your device to apply these changes."), this); + }); + torqueSub->addWidget(horizontal_line()); + torqueSub->addWidget(customTorqueLateral); + torqueSub->addWidget(customTorqueMain); + // Controls: Torque Lateral Controller Self-Tune + liveTorque = new ParamControl( + "LiveTorque", + tr("Torque Lateral Controller Self-Tune"), + tr("Enables self-tune for Torque lateral control."), + "../assets/offroad/icon_calibration.png" + ); + connect(uiState(), &UIState::offroadTransition, [=](bool offroad) { + liveTorque->setEnabled(offroad); + }); + connect(liveTorque, &ToggleControl::toggleFlipped, [=]() { + updateToggles(); + ConfirmationDialog::alert(tr("\"Torque Lateral Controller Self-Tune\"
You must restart your car or your device to apply these changes."), this); + }); + torqueSub->addWidget(horizontal_line()); + torqueSub->addWidget(liveTorque); + connect(torqueLateral, &ToggleControl::toggleFlipped, [=](bool state) { + updateToggles(); + }); + main_layout->addWidget(horizontal_line()); + main_layout->addWidget(torqueLateral); + main_layout->addWidget(torqueMain); + + + // Controls: Enable Hands on Wheel Monitoring + main_layout->addWidget(horizontal_line()); + main_layout->addWidget(new ParamControl( + "HandsOnWheelMonitoring", + tr("Enable Hands on Wheel Monitoring"), + tr("Monitor and alert when driver is not keeping the hands on the steering wheel."), + "../assets/offroad/icon_openpilot.png" + )); + + // Controls: Enable Vision Based Turn Speed Control (V-TSC) + main_layout->addWidget(horizontal_line()); + main_layout->addWidget(new ParamControl( + "TurnVisionControl", + tr("Enable Vision Based Turn Speed Control (V-TSC)"), + tr("Use vision path predictions to estimate the appropriate speed to drive through turns ahead."), + "../assets/offroad/icon_road.png")); + + // S.L.C. + speedLimitMain = new QWidget(); + speedLimitSub = new QVBoxLayout(speedLimitMain); + speedOffsetMain = new QWidget(); + speedOffsetSub = new QVBoxLayout(speedOffsetMain); + // Controls: Enable Speed Limit Control (SLC) + main_layout->addWidget(horizontal_line()); + speedLimitControl = new ParamControl( + "SpeedLimitControl", + tr("Enable Speed Limit Control (SLC)"), + tr("Use speed limit signs information from map data and car interface (if applicable) to automatically adapt cruise speed to road limits."), + "../assets/offroad/icon_speed_limit.png" + ); + speedLimitSub->setContentsMargins(QMargins()); + + // Controls: MUTCD: US/Canada\nVienna: Europe/Asia/etc. + speedLimitSub->addWidget(horizontal_line()); + speedLimitSub->addWidget(new SpeedLimitStyle()); + + // Controls: Enable Speed Limit % Offset + speedLimitSub->addWidget(horizontal_line()); + speedPercControl = new ParamControl( + "SpeedLimitPercOffset", + tr("Enable Speed Limit % Offset"), + tr("Set speed limit slightly higher than actual speed limit for a more natural drive."), + "../assets/offroad/icon_speed_limit.png" + ); + speedOffsetSub->setContentsMargins(QMargins()); + + // Controls: Speed Limit Offset (MPH / KM/H) + speedOffsetSub->addWidget(horizontal_line()); + speedOffsetSub->addWidget(new SpeedLimitValueOffset()); + connect(speedPercControl, &ToggleControl::toggleFlipped, [=](bool state) { + updateToggles(); + }); + + speedLimitSub->addWidget(speedPercControl); + speedLimitSub->addWidget(speedOffsetMain); + + connect(speedLimitControl, &ToggleControl::toggleFlipped, [=](bool state) { + updateToggles(); + }); + + main_layout->addWidget(speedLimitControl); + main_layout->addWidget(speedLimitMain); + + + // Controls: Enable Map Data Turn Speed Control (M-TSC) + main_layout->addWidget(horizontal_line()); + main_layout->addWidget(new ParamControl( + "TurnSpeedControl", + tr("Enable Map Data Turn Speed Control (M-TSC)"), + tr("Use curvature information from map data to define speed limits to take turns ahead."), + "../assets/offroad/icon_openpilot.png" + )); + + // Controls: ACC +/-: Long Press Reverse + main_layout->addWidget(horizontal_line()); + main_layout->addWidget(new ParamControl( + "ReverseAccChange", + tr("ACC +/-: Long Press Reverse"), + QString("%1
" + "

%2


" + "

%3


") + .arg(tr("Change the ACC +/- buttons behavior with cruise speed change in sunnypilot.")) + .arg(tr("Disabled (Stock): Short=1, Long = 5 (imperial) / 10 (metric)")) + .arg(tr("Enabled: Short = 5 (imperial) / 10 (metric), Long=1")), + "../assets/offroad/icon_acc_change.png" + )); + + // Controls: OSM: Use Offline Database + osmLocalDb = new ParamControl( + "OsmLocalDb", + tr("OSM: Use Offline Database"), + "", + "../assets/img_map.png" + ); + connect(osmLocalDb, &ToggleControl::toggleFlipped, [=](bool state) { + if (!state) params.remove("OsmLocalDb"); + }); + main_layout->addWidget(horizontal_line()); + main_layout->addWidget(osmLocalDb); +} + +void SPControlsPanel::showEvent(QShowEvent *event) { + updateToggles(); +} + +void SPControlsPanel::updateToggles() { + madsMainControl->setVisible(params.getBool("EnableMads")); + madsMainControl->update(); + + dlpMain->setVisible(params.getBool("DynamicLaneProfileToggle")); + dlpMain->update(); + + customOffsetsMain->setVisible(params.getBool("CustomOffsets")); + customOffsetsMain->update(); + + gacMain->setVisible(params.getBool("GapAdjustCruise")); + gacMain->update(); + + customTorqueMain->setVisible(params.getBool("CustomTorqueLateral")); + customTorqueMain->update(); + torqueMain->setVisible(params.getBool("EnforceTorqueLateral")); + torqueMain->update(); + if (params.getBool("EnforceTorqueLateral")) { + if (params.getBool("CustomTorqueLateral")) { + liveTorque->setEnabled(false); + params.putBool("LiveTorque", false); + } else { + liveTorque->setEnabled(true); + } + + if (params.getBool("LiveTorque")) { + customTorqueLateral->setEnabled(false); + params.putBool("CustomTorqueLateral", false); + customTorqueMain->setVisible(false); + } else { + customTorqueLateral->setEnabled(true); + } + + liveTorque->refresh(); + customTorqueLateral->refresh(); + } else { + params.putBool("LiveTorque", false); + params.putBool("CustomTorqueLateral", false); + customTorqueMain->setVisible(false); + } + + speedOffsetMain->setVisible(!params.getBool("SpeedLimitPercOffset")); + speedOffsetMain->update(); + speedLimitMain->setVisible(params.getBool("SpeedLimitControl")); + speedLimitMain->update(); +} + +SPVehiclesPanel::SPVehiclesPanel(QWidget *parent) : QWidget(parent) { + main_layout = new QStackedLayout(this); + home = new QWidget(this); + QVBoxLayout* fcr_layout = new QVBoxLayout(home); + fcr_layout->setContentsMargins(0, 20, 0, 20); + + QString set = QString::fromStdString(params.get("CarModelText")); + QPushButton* setCarBtn = new QPushButton(((set == "=== Not Selected ===") || (set.length() == 0)) ? "Select your car" : set); + setCarBtn->setObjectName("setCarBtn"); + setCarBtn->setStyleSheet("margin-right: 30px;"); + connect(setCarBtn, &QPushButton::clicked, [=]() { + QMap cars = getCarNames(); + QString currentCar = QString::fromStdString(params.get("CarModel")); + QString selection = MultiOptionDialog::getSelection("Select your car", cars.keys(), cars.key(currentCar), this); + if (!selection.isEmpty()) { + params.put("CarModel", cars[selection].toStdString()); + params.put("CarModelText", selection.toStdString()); + qApp->exit(18); + watchdog_kick(0); + } + }); + fcr_layout->addSpacing(10); + fcr_layout->addWidget(setCarBtn, 0, Qt::AlignRight); + fcr_layout->addSpacing(10); + + home_widget = new QWidget(this); + QVBoxLayout* toggle_layout = new QVBoxLayout(home_widget); + home_widget->setObjectName("homeWidget"); + + ScrollView *scroller = new ScrollView(home_widget, this); + scroller->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); + fcr_layout->addWidget(scroller, 1); + + main_layout->addWidget(home); + + setStyleSheet(R"( + #setCarBtn { + font-size: 50px; + margin: 0px; + padding: 20px; + border-width: 0; + border-radius: 30px; + color: #dddddd; + background-color: #444444; + } + )"); + + toggle_layout->addWidget(new LabelControl(tr("Hyundai/Kia/Genesis (HKG)"))); + eScc = new ParamControl( + "EnhancedScc", + tr("Enhanced SCC Radar Interceptor ℹ"), + QString("%1
" + "%2
" + "%3") + .arg(tr("sunnypilot will take over control of gas and brakes and will NOT disable the car's radar. This preserves AEB.")) + .arg(tr("Note: Only enable this feature if you have the Enhanced SCC Radar Interceptor hardware installed.")) + .arg(tr("Want to get one for your car? Reach out to sunnyhaibin#0865 on Discord for more information.")), + "../assets/offroad/icon_blank.png" + ); + eScc->setConfirmation(true, false); + toggle_layout->addWidget(horizontal_line()); + toggle_layout->addWidget(eScc); + toggle_layout->addWidget(horizontal_line()); + toggle_layout->addWidget(new LabelControl(tr("Toyota/Lexus"))); + stockLongToyota = new ParamControl( + "StockLongToyota", + "Enable Stock Toyota Longitudinal Control", + "sunnypilot will not take over control of gas and brakes. Stock Toyota longitudinal control will be used.", + "../assets/offroad/icon_blank.png" + ); + stockLongToyota->setConfirmation(true, false); + toggle_layout->addWidget(horizontal_line()); + toggle_layout->addWidget(stockLongToyota); + toggle_layout->addWidget(horizontal_line()); + toggle_layout->addWidget(new LabelControl(tr("Volkswagen MQB/PQ"))); + toggle_layout->addWidget(horizontal_line()); + toggle_layout->addWidget(new VwAccType()); +} + +SPVisualsPanel::SPVisualsPanel(QWidget *parent) : QWidget(parent) { + QVBoxLayout* main_layout = new QVBoxLayout(this); + + // Visuals: Display Braking Status + main_layout->addWidget(new ParamControl( + "BrakeLights", + tr("Display Braking Status"), + tr("Enable this will turn the current speed value to red while the brake is used."), + "../assets/offroad/icon_road.png" + )); + + // Visuals: Display Stand Still Timer + main_layout->addWidget(horizontal_line()); + main_layout->addWidget(new ParamControl( + "StandStillTimer", + tr("Display Stand Still Timer"), + tr("Enable this will display time spent at a stop (i.e., at a stop lights, stop signs, traffic congestions)."), + "../assets/offroad/icon_road.png" + )); + + // Dev U.I. + devUiMain = new QWidget(); + devUiSub = new QVBoxLayout(devUiMain); + // Visuals: Show Developer UI + devUi = new ParamControl( + "DevUI", + tr("Show Developer UI"), + tr("Show developer UI (Dev UI) for real-time parameters from various sources."), + "../assets/offroad/icon_calibration.png" + ); + devUiSub->setContentsMargins(QMargins()); + devUiSub->addWidget(horizontal_line()); + devUiSub->addWidget(new DevUiRow()); + connect(devUi, &ToggleControl::toggleFlipped, [=](bool state) { + updateToggles(); + }); + main_layout->addWidget(horizontal_line()); + main_layout->addWidget(devUi); + main_layout->addWidget(devUiMain); + + + // Visuals: OSM: Show debug UI elements + main_layout->addWidget(horizontal_line()); + main_layout->addWidget(new ParamControl( + "ShowDebugUI", + tr("OSM: Show debug UI elements"), + tr("OSM: Show UI elements that aid debugging."), + "../assets/offroad/icon_calibration.png" + )); + + // Mapbox + mapboxMain = new QWidget(); + mapboxSub = new QVBoxLayout(mapboxMain); + // Visuals: Enable Mapbox Navigation + customMapbox = new ParamControl( + "CustomMapbox", + tr("Enable Mapbox Navigation*"), + QString("%1
" + "%2
" + "%3
" + "

%4

") + .arg(tr("Enable built-in navigation on sunnypilot, powered by Mapbox.")) + .arg(tr("Access via the web interface: \"http://:8082\"")) + .arg(tr("If you do not have comma Prime, you will need to provide your own Mapbox token at https://mapbox.com/. Reach out to sunnyhaibin#0865 on Discord for more information.")) + .arg(tr("Huge thanks to the dragonpilot team for making this possible!")), + "../assets/img_map.png" + ); + connect(uiState(), &UIState::offroadTransition, [=](bool offroad) { + customMapbox->setEnabled(offroad); + }); + connect(customMapbox, &ToggleControl::toggleFlipped, [=](bool state) { + if (ConfirmationDialog::confirm(tr("\"Enable Mapbox Navigation\"\nYou must restart your car or your device to apply these changes.\nReboot now?"), "Reboot", parent)) { + Hardware::reboot(); + } + }); + mapboxFullScreen = new ParamControl( + "MapboxFullScreen", + "Display Navigation Full Screen", + "Enable this will display the built-in navigation in full screen.\nTo switch back to driving view, tap on the border edge.", + "../assets/offroad/icon_blank.png" + ); + connect(mapboxFullScreen, &ToggleControl::toggleFlipped, [=](bool state) { + ConfirmationDialog::alert("\"Enable Mapbox Navigation\"\nEnable this will display the built-in navigation in full screen.\nTo switch back to driving view, tap on the border edge.", this); + }); + mapboxSub->setContentsMargins(QMargins()); + mapboxSub->addWidget(horizontal_line()); + mapboxSub->addWidget(mapboxFullScreen); + QObject::connect(customMapbox, &ToggleControl::toggleFlipped, [=](bool state) { + updateToggles(); + }); + main_layout->addWidget(horizontal_line()); + main_layout->addWidget(customMapbox); + main_layout->addWidget(mapboxMain); +} + +void SPVisualsPanel::showEvent(QShowEvent *event) { + updateToggles(); +} + +void SPVisualsPanel::updateToggles() { + devUiMain->setVisible(params.getBool("DevUI")); + devUiMain->update(); + + mapboxMain->setVisible(params.getBool("CustomMapbox")); + mapboxMain->update(); +} + +// Max Time Offroad (Shutdown timer) +MaxTimeOffroad::MaxTimeOffroad() : AbstractControl( + tr("Max Time Offroad"), + tr("Device is automatically turned off after a set time when the engine is turned off (off-road) after driving (on-road)."), + "../assets/offroad/icon_metric.png") + +{ + label.setAlignment(Qt::AlignVCenter|Qt::AlignRight); + label.setStyleSheet("color: #e0e879"); + hlayout->addWidget(&label); + + btnminus.setStyleSheet(R"( + padding: 0; + border-radius: 50px; + font-size: 35px; + font-weight: 500; + color: #E4E4E4; + background-color: #393939; + )"); + btnplus.setStyleSheet(R"( + padding: 0; + border-radius: 50px; + font-size: 35px; + font-weight: 500; + color: #E4E4E4; + background-color: #393939; + )"); + btnminus.setFixedSize(150, 100); + btnplus.setFixedSize(150, 100); + hlayout->addWidget(&btnminus); + hlayout->addWidget(&btnplus); + + QObject::connect(&btnminus, &QPushButton::clicked, [=]() { + auto str = QString::fromStdString(params.get("MaxTimeOffroad")); + int value = str.toInt(); + value = value - 1; + if (value <= 0 ) { + value = 0; + } + QString values = QString::number(value); + params.put("MaxTimeOffroad", values.toStdString()); + refresh(); + }); + + QObject::connect(&btnplus, &QPushButton::clicked, [=]() { + auto str = QString::fromStdString(params.get("MaxTimeOffroad")); + int value = str.toInt(); + value = value + 1; + if (value >= 12 ) { + value = 12; + } + QString values = QString::number(value); + params.put("MaxTimeOffroad", values.toStdString()); + refresh(); + }); + refresh(); +} + +void MaxTimeOffroad::refresh() { + QString option = QString::fromStdString(params.get("MaxTimeOffroad")); + QString second = tr("s"); + QString minute = tr("m"); + QString hour = tr("h"); + if (option == "0") { + label.setText(tr("Always On")); + } else if (option == "1") { + label.setText(tr("Immediate")); + } else if (option == "2") { + label.setText("30" + second); + } else if (option == "3") { + label.setText("1" + minute); + } else if (option == "4") { + label.setText("3" + minute); + } else if (option == "5") { + label.setText("5" + minute); + } else if (option == "6") { + label.setText("10" + minute); + } else if (option == "7") { + label.setText("30" + minute); + } else if (option == "8") { + label.setText("1" + hour); + } else if (option == "9") { + label.setText("3" + hour); + } else if (option == "10") { + label.setText("5" + hour); + } else if (option == "11") { + label.setText("10" + hour); + } else if (option == "12") { + label.setText("30" + hour); + } + btnminus.setText("-"); + btnplus.setText("+"); +} + +// Onroad Screen Off (Auto Onroad Screen Timer) +OnroadScreenOff::OnroadScreenOff() : AbstractControl( + tr("Driving Screen Off Timer"), + tr("Turn off the device screen or reduce brightness to protect the screen after driving starts. It automatically brightens or turns on when a touch or event occurs."), + "../assets/offroad/icon_metric.png") + +{ + label.setAlignment(Qt::AlignVCenter|Qt::AlignRight); + label.setStyleSheet("color: #e0e879"); + hlayout->addWidget(&label); + + btnminus.setStyleSheet(R"( + padding: 0; + border-radius: 50px; + font-size: 35px; + font-weight: 500; + color: #E4E4E4; + background-color: #393939; + )"); + btnplus.setStyleSheet(R"( + padding: 0; + border-radius: 50px; + font-size: 35px; + font-weight: 500; + color: #E4E4E4; + background-color: #393939; + )"); + btnminus.setFixedSize(150, 100); + btnplus.setFixedSize(150, 100); + hlayout->addWidget(&btnminus); + hlayout->addWidget(&btnplus); + + QObject::connect(&btnminus, &QPushButton::clicked, [=]() { + auto str = QString::fromStdString(params.get("OnroadScreenOff")); + int value = str.toInt(); + value = value - 1; + if (value <= -2 ) { + value = -2; + } + uiState()->scene.onroadScreenOff = value; + QString values = QString::number(value); + params.put("OnroadScreenOff", values.toStdString()); + refresh(); + }); + + QObject::connect(&btnplus, &QPushButton::clicked, [=]() { + auto str = QString::fromStdString(params.get("OnroadScreenOff")); + int value = str.toInt(); + value = value + 1; + if (value >= 10 ) { + value = 10; + } + uiState()->scene.onroadScreenOff = value; + QString values = QString::number(value); + params.put("OnroadScreenOff", values.toStdString()); + refresh(); + }); + refresh(); +} + +void OnroadScreenOff::refresh() +{ + QString option = QString::fromStdString(params.get("OnroadScreenOff")); + QString second = tr("s"); + if (option == "-2") { + label.setText(tr("Always On")); + } else if (option == "-1") { + label.setText("15" + second); + } else if (option == "0") { + label.setText("30" + second); + } else { + label.setText(QString::fromStdString(params.get("OnroadScreenOff")) + "min(s)"); + } + btnminus.setText("-"); + btnplus.setText("+"); +} + +// Onroad Screen Off Brightness +OnroadScreenOffBrightness::OnroadScreenOffBrightness() : AbstractControl( + tr("Driving Screen Off Brightness (%)"), + tr("When using the Driving Screen Off feature, the brightness is reduced according to the automatic brightness ratio."), + "../assets/offroad/icon_metric.png") + +{ + label.setAlignment(Qt::AlignVCenter|Qt::AlignRight); + label.setStyleSheet("color: #e0e879"); + hlayout->addWidget(&label); + + btnminus.setStyleSheet(R"( + padding: 0; + border-radius: 50px; + font-size: 35px; + font-weight: 500; + color: #E4E4E4; + background-color: #393939; + )"); + btnplus.setStyleSheet(R"( + padding: 0; + border-radius: 50px; + font-size: 35px; + font-weight: 500; + color: #E4E4E4; + background-color: #393939; + )"); + btnminus.setFixedSize(150, 100); + btnplus.setFixedSize(150, 100); + hlayout->addWidget(&btnminus); + hlayout->addWidget(&btnplus); + + QObject::connect(&btnminus, &QPushButton::clicked, [=]() { + auto str = QString::fromStdString(params.get("OnroadScreenOffBrightness")); + int value = str.toInt(); + value = value - 10; + if (value <= 0 ) { + value = 0; + } + uiState()->scene.onroadScreenOffBrightness = value; + QString values = QString::number(value); + params.put("OnroadScreenOffBrightness", values.toStdString()); + refresh(); + }); + + QObject::connect(&btnplus, &QPushButton::clicked, [=]() { + auto str = QString::fromStdString(params.get("OnroadScreenOffBrightness")); + int value = str.toInt(); + value = value + 10; + if (value >= 100 ) { + value = 100; + } + uiState()->scene.onroadScreenOffBrightness = value; + QString values = QString::number(value); + params.put("OnroadScreenOffBrightness", values.toStdString()); + refresh(); + }); + refresh(); +} + +void OnroadScreenOffBrightness::refresh() { + QString option = QString::fromStdString(params.get("OnroadScreenOffBrightness")); + if (option == "0") { + label.setText(tr("Dark")); + } else { + label.setText(QString::fromStdString(params.get("OnroadScreenOffBrightness"))); + } + btnminus.setText("-"); + btnplus.setText("+"); +} + +// Brightness Control (Global) +BrightnessControl::BrightnessControl() : AbstractControl( + tr("Brightness Control (Global, %)"), + tr("Manually adjusts the global brightness of the screen."), + "../assets/offroad/icon_metric.png") + +{ + label.setAlignment(Qt::AlignVCenter|Qt::AlignRight); + label.setStyleSheet("color: #e0e879"); + hlayout->addWidget(&label); + + btnminus.setStyleSheet(R"( + padding: 0; + border-radius: 50px; + font-size: 35px; + font-weight: 500; + color: #E4E4E4; + background-color: #393939; + )"); + btnplus.setStyleSheet(R"( + padding: 0; + border-radius: 50px; + font-size: 35px; + font-weight: 500; + color: #E4E4E4; + background-color: #393939; + )"); + btnminus.setFixedSize(150, 100); + btnplus.setFixedSize(150, 100); + hlayout->addWidget(&btnminus); + hlayout->addWidget(&btnplus); + + QObject::connect(&btnminus, &QPushButton::clicked, [=]() { + auto str = QString::fromStdString(params.get("BrightnessControl")); + int value = str.toInt(); + value = value - 5; + if (value <= 0 ) { + value = 0; + } + uiState()->scene.brightness = value; + QString values = QString::number(value); + params.put("BrightnessControl", values.toStdString()); + refresh(); + }); + + QObject::connect(&btnplus, &QPushButton::clicked, [=]() { + auto str = QString::fromStdString(params.get("BrightnessControl")); + int value = str.toInt(); + value = value + 5; + if (value >= 100 ) { + value = 100; + } + uiState()->scene.brightness = value; + QString values = QString::number(value); + params.put("BrightnessControl", values.toStdString()); + refresh(); + }); + refresh(); +} + +void BrightnessControl::refresh() { + QString option = QString::fromStdString(params.get("BrightnessControl")); + if (option == "0") { + label.setText(tr("Auto")); + } else { + label.setText(QString::fromStdString(params.get("BrightnessControl"))); + } + btnminus.setText("-"); + btnplus.setText("+"); +} + +// Camera Offset Value +CameraOffset::CameraOffset() : AbstractControl( + tr("Camera Offset (cm)"), + tr("Hack to trick vehicle to be left or right biased in its lane. Decreasing the value will make the car keep more left, increasing will make it keep more right. Changes take effect immediately."), + "../assets/offroad/icon_blank.png") + +{ + label.setAlignment(Qt::AlignVCenter|Qt::AlignRight); + label.setStyleSheet("color: #e0e879"); + hlayout->addWidget(&label); + + btnminus.setStyleSheet(R"( + padding: 0; + border-radius: 50px; + font-size: 50px; + font-weight: 500; + color: #E4E4E4; + background-color: #393939; + )"); + btnplus.setStyleSheet(R"( + padding: 0; + border-radius: 50px; + font-size: 50px; + font-weight: 500; + color: #E4E4E4; + background-color: #393939; + )"); + btnminus.setFixedSize(150, 100); + btnplus.setFixedSize(150, 100); + hlayout->addWidget(&btnminus); + hlayout->addWidget(&btnplus); + +QObject::connect(&btnminus, &QPushButton::clicked, [=]() { + auto str = QString::fromStdString(params.get("CameraOffset")); + int value = str.toInt(); + value = value - 1; + if (value <= -10 ) { + value = -10; + } + + QString values = QString::number(value); + params.put("CameraOffset", values.toStdString()); + refresh(); + }); + + QObject::connect(&btnplus, &QPushButton::clicked, [=]() { + auto str = QString::fromStdString(params.get("CameraOffset")); + int value = str.toInt(); + value = value + 1; + if (value >= 10 ) { + value = 10; + } + + QString values = QString::number(value); + params.put("CameraOffset", values.toStdString()); + refresh(); + }); + refresh(); +} + +void CameraOffset::refresh() { + QString option = QString::fromStdString(params.get("CameraOffset")); + label.setText(QString::fromStdString(params.get("CameraOffset"))); + btnminus.setText("-"); + btnplus.setText("+"); +} + +// Path Offset Value +PathOffset::PathOffset() : AbstractControl( + tr("Path Offset (cm)"), + tr("Hack to trick the model path to be left or right biased of the lane. Decreasing the value will shift the model more left, increasing will shift the model more right. Changes take effect immediately."), + "../assets/offroad/icon_blank.png") + +{ + label.setAlignment(Qt::AlignVCenter|Qt::AlignRight); + label.setStyleSheet("color: #e0e879"); + hlayout->addWidget(&label); + + btnminus.setStyleSheet(R"( + padding: 0; + border-radius: 50px; + font-size: 50px; + font-weight: 500; + color: #E4E4E4; + background-color: #393939; + )"); + btnplus.setStyleSheet(R"( + padding: 0; + border-radius: 50px; + font-size: 50px; + font-weight: 500; + color: #E4E4E4; + background-color: #393939; + )"); + btnminus.setFixedSize(150, 100); + btnplus.setFixedSize(150, 100); + hlayout->addWidget(&btnminus); + hlayout->addWidget(&btnplus); + +QObject::connect(&btnminus, &QPushButton::clicked, [=]() { + auto str = QString::fromStdString(params.get("PathOffset")); + int value = str.toInt(); + value = value - 1; + if (value <= -10 ) { + value = -10; + } + + QString values = QString::number(value); + params.put("PathOffset", values.toStdString()); + refresh(); + }); + + QObject::connect(&btnplus, &QPushButton::clicked, [=]() { + auto str = QString::fromStdString(params.get("PathOffset")); + int value = str.toInt(); + value = value + 1; + if (value >= 10 ) { + value = 10; + } + + QString values = QString::number(value); + params.put("PathOffset", values.toStdString()); + refresh(); + }); + refresh(); +} + +void PathOffset::refresh() { + QString option = QString::fromStdString(params.get("PathOffset")); + label.setText(QString::fromStdString(params.get("PathOffset"))); + btnminus.setText("-"); + btnplus.setText("+"); +} + +// Auto Lane Change Timer (ALCT) +AutoLaneChangeTimer::AutoLaneChangeTimer() : AbstractControl( + tr("Auto Lane Change Timer"), + tr("Set a timer to delay the auto lane change operation when the blinker is used. No nudge on the steering wheel is required to auto lane change if a timer is set.\nPlease use caution when using this feature. Only use the blinker when traffic and road conditions permit."), + "../assets/offroad/icon_road.png") + +{ + label.setAlignment(Qt::AlignVCenter|Qt::AlignRight); + label.setStyleSheet("color: #e0e879"); + hlayout->addWidget(&label); + + btnminus.setStyleSheet(R"( + padding: 0; + border-radius: 50px; + font-size: 50px; + font-weight: 500; + color: #E4E4E4; + background-color: #393939; + )"); + btnplus.setStyleSheet(R"( + padding: 0; + border-radius: 50px; + font-size: 50px; + font-weight: 500; + color: #E4E4E4; + background-color: #393939; + )"); + btnminus.setFixedSize(150, 100); + btnplus.setFixedSize(150, 100); + hlayout->addWidget(&btnminus); + hlayout->addWidget(&btnplus); + + QObject::connect(&btnminus, &QPushButton::clicked, [=]() { + auto str = QString::fromStdString(params.get("AutoLaneChangeTimer")); + int value = str.toInt(); + value = value - 1; + if (value <= 0 ) { + value = 0; + } + QString values = QString::number(value); + params.put("AutoLaneChangeTimer", values.toStdString()); + refresh(); + }); + + QObject::connect(&btnplus, &QPushButton::clicked, [=]() { + auto str = QString::fromStdString(params.get("AutoLaneChangeTimer")); + int value = str.toInt(); + value = value + 1; + if (value >= 5 ) { + value = 5; + } + QString values = QString::number(value); + params.put("AutoLaneChangeTimer", values.toStdString()); + refresh(); + }); + refresh(); +} + +void AutoLaneChangeTimer::refresh() { + QString option = QString::fromStdString(params.get("AutoLaneChangeTimer")); + QString second = tr("s"); + if (option == "0") { + label.setText(tr("Nudge")); + } else if (option == "1") { + label.setText(tr("Nudgeless")); + } else if (option == "2") { + label.setText("0.5" + second); + } else if (option == "3") { + label.setText("1" + second); + } else if (option == "4") { + label.setText("1.5" + second); + } else { + label.setText("2" + second); + } + btnminus.setText("-"); + btnplus.setText("+"); +} + +// G.A.C. Mode +GapAdjustCruiseMode::GapAdjustCruiseMode() : AbstractControl( + tr("Mode"), + QString("%1
" + "%2
" + "%3") + .arg(tr("SW: Steering Wheel Button only")) + .arg(tr("UI: User Interface Button on screen only")) + .arg(tr("SW + UI: Steering Wheel Button + User Interface Button on screen")), + "../assets/offroad/icon_blank.png") + +{ + label.setAlignment(Qt::AlignVCenter|Qt::AlignRight); + label.setStyleSheet("color: #e0e879"); + hlayout->addWidget(&label); + + btnminus.setStyleSheet(R"( + padding: 0; + border-radius: 50px; + font-size: 50px; + font-weight: 500; + color: #E4E4E4; + background-color: #393939; + )"); + btnplus.setStyleSheet(R"( + padding: 0; + border-radius: 50px; + font-size: 50px; + font-weight: 500; + color: #E4E4E4; + background-color: #393939; + )"); + btnminus.setFixedSize(150, 100); + btnplus.setFixedSize(150, 100); + hlayout->addWidget(&btnminus); + hlayout->addWidget(&btnplus); + + QObject::connect(&btnminus, &QPushButton::clicked, [=]() { + auto str = QString::fromStdString(params.get("GapAdjustCruiseMode")); + int value = str.toInt(); + value = value - 1; + if (value <= 0 ) { + value = 0; + } + QString values = QString::number(value); + params.put("GapAdjustCruiseMode", values.toStdString()); + refresh(); + }); + + QObject::connect(&btnplus, &QPushButton::clicked, [=]() { + auto str = QString::fromStdString(params.get("GapAdjustCruiseMode")); + int value = str.toInt(); + value = value + 1; + if (value >= 2 ) { + value = 2; + } + QString values = QString::number(value); + params.put("GapAdjustCruiseMode", values.toStdString()); + refresh(); + }); + refresh(); +} + +void GapAdjustCruiseMode::refresh() { + QString option = QString::fromStdString(params.get("GapAdjustCruiseMode")); + if (option == "0") { + label.setText(tr("S.W.")); + } else if (option == "1") { + label.setText(tr("UI")); + } else if (option == "2") { + label.setText(tr("S.W. + UI")); + } + btnminus.setText("-"); + btnplus.setText("+"); +} + +TorqueFriction::TorqueFriction() : AbstractControl( + tr("FRICTION"), + tr("Adjust Friction for the Torque Lateral Controller"), + "../assets/offroad/icon_blank.png") + +{ + label.setAlignment(Qt::AlignVCenter|Qt::AlignRight); + label.setStyleSheet("color: #e0e879"); + hlayout->addWidget(&label); + + btnminus.setStyleSheet(R"( + padding: 0; + border-radius: 50px; + font-size: 35px; + font-weight: 500; + color: #E4E4E4; + background-color: #393939; + )"); + btnplus.setStyleSheet(R"( + padding: 0; + border-radius: 50px; + font-size: 35px; + font-weight: 500; + color: #E4E4E4; + background-color: #393939; + )"); + btnminus.setFixedSize(150, 100); + btnplus.setFixedSize(150, 100); + hlayout->addWidget(&btnminus); + hlayout->addWidget(&btnplus); + + QObject::connect(&btnminus, &QPushButton::clicked, [=]() { + auto str = QString::fromStdString(params.get("TorqueFriction")); + int value = str.toInt(); + value = value - 1; + if (value <= 0 ) { + value = 0; + } + QString values = QString::number(value); + params.put("TorqueFriction", values.toStdString()); + refresh(); + }); + + QObject::connect(&btnplus, &QPushButton::clicked, [=]() { + auto str = QString::fromStdString(params.get("TorqueFriction")); + int value = str.toInt(); + value = value + 1; + if (value >= 50 ) { + value = 50; + } + QString values = QString::number(value); + params.put("TorqueFriction", values.toStdString()); + refresh(); + }); + refresh(); +} + +void TorqueFriction::refresh() { + auto strs = QString::fromStdString(params.get("TorqueFriction")); + int valuei = strs.toInt(); + float valuef = valuei * 0.01; + QString valuefs = QString::number(valuef); + label.setText(QString::fromStdString(valuefs.toStdString())); + btnminus.setText("-"); + btnplus.setText("+"); +} + +TorqueMaxLatAccel::TorqueMaxLatAccel() : AbstractControl( + tr("LAT_ACCEL_FACTOR"), + tr("Adjust Max Lateral Acceleration for the Torque Lateral Controller"), + "../assets/offroad/icon_blank.png") + +{ + label.setAlignment(Qt::AlignVCenter|Qt::AlignRight); + label.setStyleSheet("color: #e0e879"); + hlayout->addWidget(&label); + + btnminus.setStyleSheet(R"( + padding: 0; + border-radius: 50px; + font-size: 35px; + font-weight: 500; + color: #E4E4E4; + background-color: #393939; + )"); + btnplus.setStyleSheet(R"( + padding: 0; + border-radius: 50px; + font-size: 35px; + font-weight: 500; + color: #E4E4E4; + background-color: #393939; + )"); + btnminus.setFixedSize(150, 100); + btnplus.setFixedSize(150, 100); + hlayout->addWidget(&btnminus); + hlayout->addWidget(&btnplus); + + QObject::connect(&btnminus, &QPushButton::clicked, [=]() { + auto str = QString::fromStdString(params.get("TorqueMaxLatAccel")); + int value = str.toInt(); + value = value - 1; + if (value <= 1 ) { + value = 1; + } + QString values = QString::number(value); + params.put("TorqueMaxLatAccel", values.toStdString()); + refresh(); + }); + + QObject::connect(&btnplus, &QPushButton::clicked, [=]() { + auto str = QString::fromStdString(params.get("TorqueMaxLatAccel")); + int value = str.toInt(); + value = value + 1; + if (value >= 500 ) { + value = 500; + } + QString values = QString::number(value); + params.put("TorqueMaxLatAccel", values.toStdString()); + refresh(); + }); + refresh(); +} + +void TorqueMaxLatAccel::refresh() { + auto strs = QString::fromStdString(params.get("TorqueMaxLatAccel")); + int valuei = strs.toInt(); + float valuef = valuei * 0.01; + QString valuefs = QString::number(valuef); + label.setText(QString::fromStdString(valuefs.toStdString())); + btnminus.setText("-"); + btnplus.setText("+"); +} + +SpeedLimitStyle::SpeedLimitStyle() : AbstractControl( + tr("Speed Limit Style"), + QString("%1
" + "%2") + .arg(tr("MUTCD: US/Canada")) + .arg(tr("Vienna: Europe/Asia/etc.")), + "../assets/offroad/icon_blank.png") + +{ + label.setAlignment(Qt::AlignVCenter|Qt::AlignRight); + label.setStyleSheet("color: #e0e879"); + hlayout->addWidget(&label); + + btnminus.setStyleSheet(R"( + padding: 0; + border-radius: 50px; + font-size: 50px; + font-weight: 500; + color: #E4E4E4; + background-color: #393939; + )"); + btnplus.setStyleSheet(R"( + padding: 0; + border-radius: 50px; + font-size: 50px; + font-weight: 500; + color: #E4E4E4; + background-color: #393939; + )"); + btnminus.setFixedSize(150, 100); + btnplus.setFixedSize(150, 100); + hlayout->addWidget(&btnminus); + hlayout->addWidget(&btnplus); + + QObject::connect(&btnminus, &QPushButton::clicked, [=]() { + auto str = QString::fromStdString(params.get("SpeedLimitStyle")); + int value = str.toInt(); + value = value - 1; + if (value <= 0 ) { + value = 0; + } + QString values = QString::number(value); + params.put("SpeedLimitStyle", values.toStdString()); + refresh(); + }); + + QObject::connect(&btnplus, &QPushButton::clicked, [=]() { + auto str = QString::fromStdString(params.get("SpeedLimitStyle")); + int value = str.toInt(); + value = value + 1; + if (value >= 1 ) { + value = 1; + } + QString values = QString::number(value); + params.put("SpeedLimitStyle", values.toStdString()); + refresh(); + }); + refresh(); +} + +void SpeedLimitStyle::refresh() { + QString option = QString::fromStdString(params.get("SpeedLimitStyle")); + if (option == "0") { + label.setText(tr("MUTCD")); + } else { + label.setText(tr("Vienna")); + } + btnminus.setText("-"); + btnplus.setText("+"); +} + +// Speed Limit Control Custom Offset +SpeedLimitValueOffset::SpeedLimitValueOffset() : AbstractControl( + tr("Speed Limit Offset (MPH / KM/H) ℹ"), + QString("%1
" + "%2") + .arg(tr("Set speed limit higher or lower than actual speed limit for a more personalized drive.")) + .arg(tr("To use this feature, turn off \"Enable Speed Limit % Offset\".")), + "../assets/offroad/icon_speed_limit.png") + +{ + label.setAlignment(Qt::AlignVCenter|Qt::AlignRight); + label.setStyleSheet("color: #e0e879"); + hlayout->addWidget(&label); + + btnminus.setStyleSheet(R"( + padding: 0; + border-radius: 50px; + font-size: 35px; + font-weight: 500; + color: #E4E4E4; + background-color: #393939; + )"); + btnplus.setStyleSheet(R"( + padding: 0; + border-radius: 50px; + font-size: 35px; + font-weight: 500; + color: #E4E4E4; + background-color: #393939; + )"); + btnminus.setFixedSize(150, 100); + btnplus.setFixedSize(150, 100); + hlayout->addWidget(&btnminus); + hlayout->addWidget(&btnplus); + + QObject::connect(&btnminus, &QPushButton::clicked, [=]() { + auto str = QString::fromStdString(params.get("SpeedLimitValueOffset")); + int value = str.toInt(); + value = value - 1; + if (value <= -30 ) { + value = -30; + } + QString values = QString::number(value); + params.put("SpeedLimitValueOffset", values.toStdString()); + refresh(); + }); + + QObject::connect(&btnplus, &QPushButton::clicked, [=]() { + auto str = QString::fromStdString(params.get("SpeedLimitValueOffset")); + int value = str.toInt(); + value = value + 1; + if (value >= 30 ) { + value = 30; + } + QString values = QString::number(value); + params.put("SpeedLimitValueOffset", values.toStdString()); + refresh(); + }); + refresh(); +} + +void SpeedLimitValueOffset::refresh() { + label.setText(QString::fromStdString(params.get("SpeedLimitValueOffset"))); + btnminus.setText("-"); + btnplus.setText("+"); +} + +// Volkswagen - MQB ACC Type +VwAccType::VwAccType() : AbstractControl( + tr("Short Press +1/-1 Type"), + tr("Define the type of ACC control your car has with short press to +1 or -1."), + "../assets/offroad/icon_blank.png") + +{ + label.setAlignment(Qt::AlignVCenter|Qt::AlignRight); + label.setStyleSheet("color: #e0e879"); + hlayout->addWidget(&label); + + btnminus.setStyleSheet(R"( + padding: 0; + border-radius: 50px; + font-size: 35px; + font-weight: 500; + color: #E4E4E4; + background-color: #393939; + )"); + btnplus.setStyleSheet(R"( + padding: 0; + border-radius: 50px; + font-size: 35px; + font-weight: 500; + color: #E4E4E4; + background-color: #393939; + )"); + btnminus.setFixedSize(150, 100); + btnplus.setFixedSize(150, 100); + hlayout->addWidget(&btnminus); + hlayout->addWidget(&btnplus); + + QObject::connect(&btnminus, &QPushButton::clicked, [=]() { + auto str = QString::fromStdString(params.get("VwAccType")); + int value = str.toInt(); + value = value - 1; + if (value <= 0 ) { + value = 0; + } + QString values = QString::number(value); + params.put("VwAccType", values.toStdString()); + refresh(); + }); + + QObject::connect(&btnplus, &QPushButton::clicked, [=]() { + auto str = QString::fromStdString(params.get("VwAccType")); + int value = str.toInt(); + value = value + 1; + if (value >= 1 ) { + value = 1; + } + QString values = QString::number(value); + params.put("VwAccType", values.toStdString()); + refresh(); + }); + refresh(); +} + +void VwAccType::refresh() { + QString option = QString::fromStdString(params.get("VwAccType")); + if (option == "0") { + label.setText(tr("+/-")); + } else if (option == "1") { + label.setText(tr("RES/SET")); + } + btnminus.setText("-"); + btnplus.setText("+"); +} + +// Developer UI Rows (Dev UI) +DevUiRow::DevUiRow() : AbstractControl( + tr("Developer UI List"), + tr("Select the number of lists of real-time parameters you would like to display on the sunnypilot screen while driving."), + "../assets/offroad/icon_blank.png") + +{ + label.setAlignment(Qt::AlignVCenter|Qt::AlignRight); + label.setStyleSheet("color: #e0e879"); + hlayout->addWidget(&label); + + btnminus.setStyleSheet(R"( + padding: 0; + border-radius: 50px; + font-size: 50px; + font-weight: 500; + color: #E4E4E4; + background-color: #393939; + )"); + btnplus.setStyleSheet(R"( + padding: 0; + border-radius: 50px; + font-size: 50px; + font-weight: 500; + color: #E4E4E4; + background-color: #393939; + )"); + btnminus.setFixedSize(150, 100); + btnplus.setFixedSize(150, 100); + hlayout->addWidget(&btnminus); + hlayout->addWidget(&btnplus); + + QObject::connect(&btnminus, &QPushButton::clicked, [=]() { + auto str = QString::fromStdString(params.get("DevUIRow")); + int value = str.toInt(); + value = value - 1; + if (value <= 0 ) { + value = 0; + } + QString values = QString::number(value); + params.put("DevUIRow", values.toStdString()); + refresh(); + }); + + QObject::connect(&btnplus, &QPushButton::clicked, [=]() { + auto str = QString::fromStdString(params.get("DevUIRow")); + int value = str.toInt(); + value = value + 1; + if (value >= 1 ) { + value = 1; + } + QString values = QString::number(value); + params.put("DevUIRow", values.toStdString()); + refresh(); + }); + refresh(); +} + +void DevUiRow::refresh() { + QString option = QString::fromStdString(params.get("DevUIRow")); + if (option == "0") { + label.setText(tr("1-Row")); + } else { + label.setText(tr("2-Row")); + } + btnminus.setText("-"); + btnplus.setText("+"); +} diff --git a/selfdrive/ui/qt/offroad/sunnypilot_settings.h b/selfdrive/ui/qt/offroad/sunnypilot_settings.h new file mode 100644 index 0000000000..5bb9afed3a --- /dev/null +++ b/selfdrive/ui/qt/offroad/sunnypilot_settings.h @@ -0,0 +1,316 @@ +#pragma once + +#include +#include +#include +#include +#include + +#include "selfdrive/ui/qt/widgets/controls.h" + +class SPGeneralPanel : public QWidget { + Q_OBJECT + +public: + explicit SPGeneralPanel(QWidget *parent = nullptr); + +private: + QVBoxLayout *main_layout; + ParamControl *endToEndLongAlert; +}; + +class SPControlsPanel : public QWidget { + Q_OBJECT + +public: + explicit SPControlsPanel(QWidget *parent = nullptr); + void showEvent(QShowEvent *event) override; + +private: + Params params; + + QVBoxLayout *main_layout; + QWidget *madsMainControl; + QVBoxLayout *madsSubControl; + QWidget *dlpMain; + QVBoxLayout *dlpSub; + QWidget *customOffsetsMain; + QVBoxLayout *customOffsetsSub; + QWidget *gacMain; + QVBoxLayout *gacSub; + QWidget *torqueMain; + QVBoxLayout *torqueSub; + QWidget *customTorqueMain; + QVBoxLayout *customTorqueSub; + QWidget *speedLimitMain; + QVBoxLayout *speedLimitSub; + QWidget *speedOffsetMain; + QVBoxLayout *speedOffsetSub; + + ParamControl *madsControl; + ParamControl *disengageLateralOnBrake; + ParamControl *accMadsCombo; + ParamControl *belowSpeed; + ParamControl *dlpControl; + ParamControl *dlpCurve; + ParamControl *customOffsets; + ParamControl *gapAdjustCruise; + ParamControl *torqueLateral; + ParamControl *customTorqueLateral; + ParamControl *liveTorque; + ParamControl *speedLimitControl; + ParamControl *speedPercControl; + ParamControl *osmLocalDb; + + void updateToggles(); +}; + +class SPVehiclesPanel : public QWidget { + Q_OBJECT + +public: + explicit SPVehiclesPanel(QWidget *parent = nullptr); + +private: + Params params; + + QStackedLayout* main_layout = nullptr; + QWidget* home = nullptr; + + QWidget* home_widget; + + ParamControl *eScc; + ParamControl *stockLongToyota; +}; + +class SPVisualsPanel : public QWidget { + Q_OBJECT + +public: + explicit SPVisualsPanel(QWidget *parent = nullptr); + void showEvent(QShowEvent *event) override; + +private: + Params params; + + QWidget *devUiMain; + QVBoxLayout *devUiSub; + QWidget *mapboxMain; + QVBoxLayout *mapboxSub; + + ParamControl *devUi; + ParamControl *customMapbox; + ParamControl *mapboxFullScreen; + + void updateToggles(); +}; + +class MaxTimeOffroad : public AbstractControl { + Q_OBJECT + +public: + MaxTimeOffroad(); + +private: + QPushButton btnplus; + QPushButton btnminus; + QLabel label; + Params params; + + void refresh(); +}; + +class OnroadScreenOff : public AbstractControl { + Q_OBJECT + +public: + OnroadScreenOff(); + +private: + QPushButton btnplus; + QPushButton btnminus; + QLabel label; + Params params; + + void refresh(); +}; + +class OnroadScreenOffBrightness : public AbstractControl { + Q_OBJECT + +public: + OnroadScreenOffBrightness(); + +private: + QPushButton btnplus; + QPushButton btnminus; + QLabel label; + Params params; + + void refresh(); +}; + +class BrightnessControl : public AbstractControl { + Q_OBJECT + +public: + BrightnessControl(); + +private: + QPushButton btnplus; + QPushButton btnminus; + QLabel label; + Params params; + + void refresh(); +}; + +class CameraOffset : public AbstractControl { + Q_OBJECT + +public: + CameraOffset(); + +private: + QPushButton btnplus; + QPushButton btnminus; + QLabel label; + Params params; + + void refresh(); +}; + +class PathOffset : public AbstractControl { + Q_OBJECT + +public: + PathOffset(); + +private: + QPushButton btnplus; + QPushButton btnminus; + QLabel label; + Params params; + + void refresh(); +}; + +class AutoLaneChangeTimer : public AbstractControl { + Q_OBJECT + +public: + AutoLaneChangeTimer(); + +private: + QPushButton btnplus; + QPushButton btnminus; + QLabel label; + Params params; + + void refresh(); +}; + +class GapAdjustCruiseMode : public AbstractControl { + Q_OBJECT + +public: + GapAdjustCruiseMode(); + +private: + QPushButton btnplus; + QPushButton btnminus; + QLabel label; + Params params; + + void refresh(); +}; + +class TorqueFriction : public AbstractControl { + Q_OBJECT + +public: + TorqueFriction(); + +private: + QPushButton btnplus; + QPushButton btnminus; + QLabel label; + Params params; + + void refresh(); +}; + +class TorqueMaxLatAccel : public AbstractControl { + Q_OBJECT + +public: + TorqueMaxLatAccel(); + +private: + QPushButton btnplus; + QPushButton btnminus; + QLabel label; + Params params; + + void refresh(); +}; + +class SpeedLimitStyle : public AbstractControl { + Q_OBJECT + +public: + SpeedLimitStyle(); + +private: + QPushButton btnplus; + QPushButton btnminus; + QLabel label; + Params params; + + void refresh(); +}; + +class SpeedLimitValueOffset : public AbstractControl { + Q_OBJECT + +public: + SpeedLimitValueOffset(); + +private: + QPushButton btnplus; + QPushButton btnminus; + QLabel label; + Params params; + + void refresh(); +}; + +class VwAccType : public AbstractControl { + Q_OBJECT + +public: + VwAccType(); + +private: + QPushButton btnplus; + QPushButton btnminus; + QLabel label; + Params params; + + void refresh(); +}; + +class DevUiRow : public AbstractControl { + Q_OBJECT + +public: + DevUiRow(); + +private: + QPushButton btnplus; + QPushButton btnminus; + QLabel label; + Params params; + + void refresh(); +}; diff --git a/selfdrive/ui/qt/util.cc b/selfdrive/ui/qt/util.cc index 4f52310649..9f3444db49 100644 --- a/selfdrive/ui/qt/util.cc +++ b/selfdrive/ui/qt/util.cc @@ -21,7 +21,7 @@ QString getVersion() { } QString getBrand() { - return Params().getBool("Passive") ? QObject::tr("dashcam") : QObject::tr("openpilot"); + return Params().getBool("Passive") ? QObject::tr("dashcam") : QObject::tr("sunnypilot"); } QString getUserAgent() { @@ -51,6 +51,19 @@ QMap getSupportedLanguages() { return map; } +QMap getCarNames() { + QFile f("/data/openpilot/selfdrive/car/sunnypilot_carname.json"); + f.open(QIODevice::ReadOnly | QIODevice::Text); + QString val = f.readAll(); + + QJsonObject obj = QJsonDocument::fromJson(val.toUtf8()).object(); + QMap map; + for (auto key : obj.keys()) { + map[key] = obj[key].toString(); + } + return map; +} + void configFont(QPainter &p, const QString &family, int size, const QString &style) { QFont f(family); f.setPixelSize(size); diff --git a/selfdrive/ui/qt/util.h b/selfdrive/ui/qt/util.h index 3188f3f9b9..a47896a8e7 100644 --- a/selfdrive/ui/qt/util.h +++ b/selfdrive/ui/qt/util.h @@ -14,6 +14,7 @@ QString getBrand(); QString getUserAgent(); std::optional getDongleId(); QMap getSupportedLanguages(); +QMap getCarNames(); void configFont(QPainter &p, const QString &family, int size, const QString &style); void clearLayout(QLayout* layout); void setQtSurfaceFormat(); diff --git a/selfdrive/ui/translations/main_de.ts b/selfdrive/ui/translations/main_de.ts index 2606df5efe..d863432580 100644 --- a/selfdrive/ui/translations/main_de.ts +++ b/selfdrive/ui/translations/main_de.ts @@ -89,6 +89,71 @@ LIMIT LIMIT + + Lane +only + + + + Lane +less + + + + Auto +Lane + + + + + AutoLaneChangeTimer + + Auto Lane Change Timer + + + + Set a timer to delay the auto lane change operation when the blinker is used. No nudge on the steering wheel is required to auto lane change if a timer is set. +Please use caution when using this feature. Only use the blinker when traffic and road conditions permit. + + + + Nudge + + + + Nudgeless + + + + s + + + + + BrightnessControl + + Brightness Control (Global, %) + + + + Manually adjusts the global brightness of the screen. + + + + Auto + + + + + CameraOffset + + Camera Offset (cm) + + + + Hack to trick vehicle to be left or right biased in its lane. Decreasing the value will make the car keep more left, increasing will make it keep more right. Changes take effect immediately. + + ConfirmationDialog @@ -116,6 +181,25 @@ Ablehnen, deinstallieren %1 + + DevUiRow + + Developer UI List + + + + Select the number of lists of real-time parameters you would like to display on the sunnypilot screen while driving. + + + + 1-Row + + + + 2-Row + + + DevicePanel @@ -162,10 +246,6 @@ REVIEW TRAINING - - Review the rules, features, and limitations of openpilot - Wiederhole die Regeln, Fähigkeiten und Limitierungen von Openpilot - Are you sure you want to review the training guide? Bist du sicher, dass du die Trainingsanleitung wiederholen möchtest? @@ -198,10 +278,6 @@ Power Off Ausschalten - - openpilot requires the device to be mounted within 4° left or right and within 5° up or 8° down. openpilot is continuously calibrating, resetting is rarely required. - Damit Openpilot funktioniert, darf die Installationsposition nicht mehr als 4° nach rechts/links, 5° nach oben und 8° nach unten abweichen. Openpilot kalibriert sich durchgehend, ein Zurücksetzen ist selten notwendig. - Your device is pointed %1° %2 and %3° %4. Deine Geräteausrichtung ist %1° %2 und %3° %4. @@ -246,6 +322,14 @@ Review Überprüfen + + Review the rules, features, and limitations of sunnypilot + + + + sunnypilot requires the device to be mounted within 4° left or right and within 5° up or 8° down. sunnypilot is continuously calibrating, resetting is rarely required. + + DriveStats @@ -292,6 +376,37 @@ ENTSPANNTER MODUS AN + + GapAdjustCruiseMode + + Mode + + + + SW: Steering Wheel Button only + + + + UI: User Interface Button on screen only + + + + SW + UI: Steering Wheel Button + User Interface Button on screen + + + + S.W. + + + + UI + + + + S.W. + UI + + + InputDialog @@ -417,6 +532,37 @@ location set Warten auf GPS + + MaxTimeOffroad + + Max Time Offroad + + + + Device is automatically turned off after a set time when the engine is turned off (off-road) after driving (on-road). + + + + Always On + + + + Immediate + + + + s + + + + m + + + + h + + + MultiOptionDialog @@ -462,6 +608,40 @@ location set HINWEIS + + OnroadScreenOff + + Driving Screen Off Timer + + + + Turn off the device screen or reduce brightness to protect the screen after driving starts. It automatically brightens or turns on when a touch or event occurs. + + + + Always On + + + + s + + + + + OnroadScreenOffBrightness + + Driving Screen Off Brightness (%) + + + + When using the Driving Screen Off feature, the brightness is reduced according to the automatic brightness ratio. + + + + Dark + + + PairingPopup @@ -492,6 +672,17 @@ location set Aktivieren + + PathOffset + + Path Offset (cm) + + + + Hack to trick the model path to be left or right biased of the lane. Decreasing the value will shift the model more left, increasing will shift the model more right. Changes take effect immediately. + + + PrimeAdWidget @@ -552,10 +743,6 @@ location set dashcam dashcam - - openpilot - openpilot - %n minute(s) ago @@ -577,6 +764,10 @@ location set vor %n Tagen + + sunnypilot + + Reset @@ -617,6 +808,332 @@ location set Datenpartition kann nicht geöffnet werden. Drücke Annehmen, um dein Gerät auf Werkseinstellungen zurückzusetzen. + + SPControlsPanel + + Enable M.A.D.S. + + + + Enable the beloved M.A.D.S. feature. Disable toggle to revert back to stock openpilot engagement/disengagement. + + + + Disengage ALC On Brake Pedal ℹ + + + + Define brake pedal interactions with sunnypilot when M.A.D.S. is enabled. + + + + Enabled: Pressing the brake pedal will disengage Automatic Lane Centering (ALC) on sunnypilot. + + + + Disabled: Pressing the brake pedal will <b>NOT</b> disengage Automatic Lane Centering (ALC) on sunnypilot. + + + + Enable ACC+MADS with RES+/SET- + + + + Engage both M.A.D.S. and ACC with a single press of RES+ or SET- button. + + + + Note: Once M.A.D.S. is engaged via this mode, it will remain engaged until it is manually disabled via the M.A.D.S. button or car shut off. + + + + Pause Lateral Below Speed w/ Blinker + + + + Enable this toggle to pause lateral actuation with blinker when traveling below 30 MPH or 50 KM/H. + + + + Enable Dynamic Lane Profile + + + + Enable toggle to use Dynamic Lane Profile. Disable toggle to use Laneless only. + + + + Laneless for Curves in "Auto lane" + + + + While in Auto Lane, switch to Laneless for current/future curves. + + + + Custom Offsets + + + + Add custom offsets to Camera and Path in sunnypilot. + + + + Enable Gap Adjust Cruise ℹ + + + + Enable the Interval button on the steering wheel to adjust the cruise gap. + + + + Only available to cars with openpilot Longitudinal Control + + + + Enforce Torque Lateral Control + + + + Enable this to enforce sunnypilot to steer with Torque lateral control. + + + + Torque Lateral Control Live Tune + + + + Enables live tune for Torque lateral control. + + + + "Torque Lateral Control Live Tune"<br>You must restart your car or your device to apply these changes. + + + + Torque Lateral Controller Self-Tune + + + + Enables self-tune for Torque lateral control. + + + + "Torque Lateral Controller Self-Tune"<br>You must restart your car or your device to apply these changes. + + + + Enable Hands on Wheel Monitoring + + + + Monitor and alert when driver is not keeping the hands on the steering wheel. + + + + Enable Vision Based Turn Speed Control (V-TSC) + + + + Use vision path predictions to estimate the appropriate speed to drive through turns ahead. + + + + Enable Speed Limit Control (SLC) + + + + Use speed limit signs information from map data and car interface (if applicable) to automatically adapt cruise speed to road limits. + + + + Enable Speed Limit % Offset + + + + Set speed limit slightly higher than actual speed limit for a more natural drive. + + + + Enable Map Data Turn Speed Control (M-TSC) + + + + Use curvature information from map data to define speed limits to take turns ahead. + + + + ACC +/-: Long Press Reverse + + + + Change the ACC +/- buttons behavior with cruise speed change in sunnypilot. + + + + Disabled (Stock): Short=1, Long = 5 (imperial) / 10 (metric) + + + + Enabled: Short = 5 (imperial) / 10 (metric), Long=1 + + + + OSM: Use Offline Database + + + + + SPGeneralPanel + + Quiet Drive 🤫 + + + + sunnypilot will display alerts but only play the most important warning sounds. This feature can be toggled while the car is on. + + + + Green Traffic Light Chime (Beta) + + + + A chime will play when the traffic light you are waiting for turns green and you have no vehicle in front of you. If you are waiting behind another vehicle, the chime will play once the vehicle advances unless ACC is engaged. + + + + Note: This chime is only designed as a notification. It is the driver's responsibility to observe their environment and make decisions accordingly. + + + + Custom Boot Screen + + + + Display sunnypilot welcome screen while booting the device. + + + + Disable Onroad Uploads + + + + Disable uploads completely when onroad. Necessary to avoid high data usage when connected to Wi-Fi hotspot. Turn on this feature if you are looking to utilize map-based features, such as Speed Limit Control (SLC) and Map-based Turn Speed Control (MTSC). + + + + Error Troubleshoot + + + + VIEW + ANSEHEN + + + Display error from the tmux session when an error has occurred from a system process. + + + + Debug snapshot on screen center tap + + + + Stores snapshot file with current state of some modules. + + + + + SPVehiclesPanel + + Hyundai/Kia/Genesis (HKG) + + + + Enhanced SCC Radar Interceptor ℹ + + + + sunnypilot will take over control of gas and brakes and will <b>NOT</b> disable the car's radar. This preserves AEB. + + + + Note: Only enable this feature if you have the Enhanced SCC Radar Interceptor hardware installed. + + + + Want to get one for your car? Reach out to sunnyhaibin#0865 on Discord for more information. + + + + Toyota/Lexus + + + + Volkswagen MQB/PQ + + + + + SPVisualsPanel + + Display Braking Status + + + + Enable this will turn the current speed value to red while the brake is used. + + + + Display Stand Still Timer + + + + Enable this will display time spent at a stop (i.e., at a stop lights, stop signs, traffic congestions). + + + + OSM: Show debug UI elements + + + + OSM: Show UI elements that aid debugging. + + + + Enable Mapbox Navigation* + + + + Enable built-in navigation on sunnypilot, powered by Mapbox. + + + + Access via the web interface: "http://<device_ip>:8082" + + + + If you do not have comma Prime, you will need to provide your own Mapbox token at https://mapbox.com/. Reach out to sunnyhaibin#0865 on Discord for more information. + + + + Huge thanks to the dragonpilot team for making this possible! + + + + "Enable Mapbox Navigation" +You must restart your car or your device to apply these changes. +Reboot now? + + + + Show Developer UI + + + + Show developer UI (Dev UI) for real-time parameters from various sources. + + + SettingsWindow @@ -643,6 +1160,22 @@ location set Navigation Navigation + + SP - General + + + + SP - Controls + + + + SP - Vehicles + + + + SP - Visuals + + Setup @@ -882,6 +1415,44 @@ location set Deinstallieren + + SpeedLimitStyle + + Speed Limit Style + + + + MUTCD: US/Canada + + + + Vienna: Europe/Asia/etc. + + + + MUTCD + + + + Vienna + + + + + SpeedLimitValueOffset + + Speed Limit Offset (MPH / KM/H) ℹ + + + + Set speed limit higher or lower than actual speed limit for a more personalized drive. + + + + To use this feature, turn off "Enable Speed Limit % Offset". + + + SshControl @@ -949,14 +1520,6 @@ location set TogglesPanel - - Enable openpilot - Openpilot aktivieren - - - Use the openpilot system for adaptive cruise control and lane keep driver assistance. Your attention is required at all times to use this feature. Changing this setting takes effect when the car is powered off. - Benutze das Openpilot System als adaptiven Tempomaten und Spurhalteassistenten. Deine Aufmerksamkeit ist jederzeit erforderlich, um diese Funktion zu nutzen. Diese Einstellung wird übernommen, wenn das Auto aus ist. - Enable Lane Departure Warnings Spurverlassenswarnungen aktivieren @@ -981,10 +1544,6 @@ location set Upload data from the driver facing camera and help improve the driver monitoring algorithm. Lade Daten der Fahreraufmerksamkeitsüberwachungskamera hoch, um die Fahreraufmerksamkeitsüberwachungsalgorithmen zu verbessern. - - When enabled, pressing the accelerator pedal will disengage openpilot. - Wenn aktiviert, deaktiviert sich Openpilot sobald das Gaspedal betätigt wird. - Use 24h format instead of am/pm Benutze das 24Stunden Format anstatt am/pm @@ -1059,6 +1618,40 @@ location set Enable experimental longitudinal control to allow Experimental mode. Aktiviere den experimentellen Openpilot Tempomaten für experimentelle Funktionen. + + Enable sunnypilot + + + + Use the sunnypilot system for adaptive cruise control and lane keep driver assistance. Your attention is required at all times to use this feature. Changing this setting takes effect when the car is powered off. + + + + When enabled, pressing the accelerator pedal will disengage sunnypilot. + + + + + TorqueFriction + + FRICTION + + + + Adjust Friction for the Torque Lateral Controller + + + + + TorqueMaxLatAccel + + LAT_ACCEL_FACTOR + + + + Adjust Max Lateral Acceleration for the Torque Lateral Controller + + Updater @@ -1095,6 +1688,25 @@ location set Aktualisierung fehlgeschlagen + + VwAccType + + Short Press +1/-1 Type + + + + Define the type of ACC control your car has with short press to +1 or -1. + + + + +/- + + + + RES/SET + + + WifiUI diff --git a/selfdrive/ui/translations/main_ja.ts b/selfdrive/ui/translations/main_ja.ts index 16f35dffaa..12b5b692fa 100644 --- a/selfdrive/ui/translations/main_ja.ts +++ b/selfdrive/ui/translations/main_ja.ts @@ -89,6 +89,71 @@ LIMIT 制限速度 + + Lane +only + + + + Lane +less + + + + Auto +Lane + + + + + AutoLaneChangeTimer + + Auto Lane Change Timer + + + + Set a timer to delay the auto lane change operation when the blinker is used. No nudge on the steering wheel is required to auto lane change if a timer is set. +Please use caution when using this feature. Only use the blinker when traffic and road conditions permit. + + + + Nudge + + + + Nudgeless + + + + s + + + + + BrightnessControl + + Brightness Control (Global, %) + + + + Manually adjusts the global brightness of the screen. + + + + Auto + + + + + CameraOffset + + Camera Offset (cm) + + + + Hack to trick vehicle to be left or right biased in its lane. Decreasing the value will make the car keep more left, increasing will make it keep more right. Changes take effect immediately. + + ConfirmationDialog @@ -116,6 +181,25 @@ 拒否して %1 をアンインストール + + DevUiRow + + Developer UI List + + + + Select the number of lists of real-time parameters you would like to display on the sunnypilot screen while driving. + + + + 1-Row + + + + 2-Row + + + DevicePanel @@ -162,10 +246,6 @@ REVIEW 見る - - Review the rules, features, and limitations of openpilot - openpilot の特徴を見る - Are you sure you want to review the training guide? 使い方の確認をしますか? @@ -198,10 +278,6 @@ Power Off 電源を切る - - openpilot requires the device to be mounted within 4° left or right and within 5° up or 8° down. openpilot is continuously calibrating, resetting is rarely required. - openpilotの本体は、左右4°以内、上5°、下8°以内の角度で取付ける必要があります。継続してキャリブレーションを続けているので、手動でリセットを行う必要はほぼありません。 - Your device is pointed %1° %2 and %3° %4. このデバイスは%2 %1°、%4 %3°の向きに設置されています。 @@ -246,6 +322,14 @@ Review 確認 + + Review the rules, features, and limitations of sunnypilot + + + + sunnypilot requires the device to be mounted within 4° left or right and within 5° up or 8° down. sunnypilot is continuously calibrating, resetting is rarely required. + + DriveStats @@ -292,6 +376,37 @@ チルモード + + GapAdjustCruiseMode + + Mode + + + + SW: Steering Wheel Button only + + + + UI: User Interface Button on screen only + + + + SW + UI: Steering Wheel Button + User Interface Button on screen + + + + S.W. + + + + UI + + + + S.W. + UI + + + InputDialog @@ -418,6 +533,37 @@ location set GPS信号を探しています + + MaxTimeOffroad + + Max Time Offroad + + + + Device is automatically turned off after a set time when the engine is turned off (off-road) after driving (on-road). + + + + Always On + + + + Immediate + + + + s + + + + m + + + + h + + + MultiOptionDialog @@ -463,6 +609,40 @@ location set 警告 + + OnroadScreenOff + + Driving Screen Off Timer + + + + Turn off the device screen or reduce brightness to protect the screen after driving starts. It automatically brightens or turns on when a touch or event occurs. + + + + Always On + + + + s + + + + + OnroadScreenOffBrightness + + Driving Screen Off Brightness (%) + + + + When using the Driving Screen Off feature, the brightness is reduced according to the automatic brightness ratio. + + + + Dark + + + PairingPopup @@ -493,6 +673,17 @@ location set を有効化 + + PathOffset + + Path Offset (cm) + + + + Hack to trick the model path to be left or right biased of the lane. Decreasing the value will shift the model more left, increasing will shift the model more right. Changes take effect immediately. + + + PrimeAdWidget @@ -553,10 +744,6 @@ location set dashcam ドライブレコーダー - - openpilot - openpilot - %n minute(s) ago @@ -575,6 +762,10 @@ location set %n 日前 + + sunnypilot + + Reset @@ -615,6 +806,332 @@ location set 「data」パーティションをマウントできません。「確認」ボタンを押すとデバイスが初期化されます。 + + SPControlsPanel + + Enable M.A.D.S. + + + + Enable the beloved M.A.D.S. feature. Disable toggle to revert back to stock openpilot engagement/disengagement. + + + + Disengage ALC On Brake Pedal ℹ + + + + Define brake pedal interactions with sunnypilot when M.A.D.S. is enabled. + + + + Enabled: Pressing the brake pedal will disengage Automatic Lane Centering (ALC) on sunnypilot. + + + + Disabled: Pressing the brake pedal will <b>NOT</b> disengage Automatic Lane Centering (ALC) on sunnypilot. + + + + Enable ACC+MADS with RES+/SET- + + + + Engage both M.A.D.S. and ACC with a single press of RES+ or SET- button. + + + + Note: Once M.A.D.S. is engaged via this mode, it will remain engaged until it is manually disabled via the M.A.D.S. button or car shut off. + + + + Pause Lateral Below Speed w/ Blinker + + + + Enable this toggle to pause lateral actuation with blinker when traveling below 30 MPH or 50 KM/H. + + + + Enable Dynamic Lane Profile + + + + Enable toggle to use Dynamic Lane Profile. Disable toggle to use Laneless only. + + + + Laneless for Curves in "Auto lane" + + + + While in Auto Lane, switch to Laneless for current/future curves. + + + + Custom Offsets + + + + Add custom offsets to Camera and Path in sunnypilot. + + + + Enable Gap Adjust Cruise ℹ + + + + Enable the Interval button on the steering wheel to adjust the cruise gap. + + + + Only available to cars with openpilot Longitudinal Control + + + + Enforce Torque Lateral Control + + + + Enable this to enforce sunnypilot to steer with Torque lateral control. + + + + Torque Lateral Control Live Tune + + + + Enables live tune for Torque lateral control. + + + + "Torque Lateral Control Live Tune"<br>You must restart your car or your device to apply these changes. + + + + Torque Lateral Controller Self-Tune + + + + Enables self-tune for Torque lateral control. + + + + "Torque Lateral Controller Self-Tune"<br>You must restart your car or your device to apply these changes. + + + + Enable Hands on Wheel Monitoring + + + + Monitor and alert when driver is not keeping the hands on the steering wheel. + + + + Enable Vision Based Turn Speed Control (V-TSC) + + + + Use vision path predictions to estimate the appropriate speed to drive through turns ahead. + + + + Enable Speed Limit Control (SLC) + + + + Use speed limit signs information from map data and car interface (if applicable) to automatically adapt cruise speed to road limits. + + + + Enable Speed Limit % Offset + + + + Set speed limit slightly higher than actual speed limit for a more natural drive. + + + + Enable Map Data Turn Speed Control (M-TSC) + + + + Use curvature information from map data to define speed limits to take turns ahead. + + + + ACC +/-: Long Press Reverse + + + + Change the ACC +/- buttons behavior with cruise speed change in sunnypilot. + + + + Disabled (Stock): Short=1, Long = 5 (imperial) / 10 (metric) + + + + Enabled: Short = 5 (imperial) / 10 (metric), Long=1 + + + + OSM: Use Offline Database + + + + + SPGeneralPanel + + Quiet Drive 🤫 + + + + sunnypilot will display alerts but only play the most important warning sounds. This feature can be toggled while the car is on. + + + + Green Traffic Light Chime (Beta) + + + + A chime will play when the traffic light you are waiting for turns green and you have no vehicle in front of you. If you are waiting behind another vehicle, the chime will play once the vehicle advances unless ACC is engaged. + + + + Note: This chime is only designed as a notification. It is the driver's responsibility to observe their environment and make decisions accordingly. + + + + Custom Boot Screen + + + + Display sunnypilot welcome screen while booting the device. + + + + Disable Onroad Uploads + + + + Disable uploads completely when onroad. Necessary to avoid high data usage when connected to Wi-Fi hotspot. Turn on this feature if you are looking to utilize map-based features, such as Speed Limit Control (SLC) and Map-based Turn Speed Control (MTSC). + + + + Error Troubleshoot + + + + VIEW + 見る + + + Display error from the tmux session when an error has occurred from a system process. + + + + Debug snapshot on screen center tap + + + + Stores snapshot file with current state of some modules. + + + + + SPVehiclesPanel + + Hyundai/Kia/Genesis (HKG) + + + + Enhanced SCC Radar Interceptor ℹ + + + + sunnypilot will take over control of gas and brakes and will <b>NOT</b> disable the car's radar. This preserves AEB. + + + + Note: Only enable this feature if you have the Enhanced SCC Radar Interceptor hardware installed. + + + + Want to get one for your car? Reach out to sunnyhaibin#0865 on Discord for more information. + + + + Toyota/Lexus + + + + Volkswagen MQB/PQ + + + + + SPVisualsPanel + + Display Braking Status + + + + Enable this will turn the current speed value to red while the brake is used. + + + + Display Stand Still Timer + + + + Enable this will display time spent at a stop (i.e., at a stop lights, stop signs, traffic congestions). + + + + OSM: Show debug UI elements + + + + OSM: Show UI elements that aid debugging. + + + + Enable Mapbox Navigation* + + + + Enable built-in navigation on sunnypilot, powered by Mapbox. + + + + Access via the web interface: "http://<device_ip>:8082" + + + + If you do not have comma Prime, you will need to provide your own Mapbox token at https://mapbox.com/. Reach out to sunnyhaibin#0865 on Discord for more information. + + + + Huge thanks to the dragonpilot team for making this possible! + + + + "Enable Mapbox Navigation" +You must restart your car or your device to apply these changes. +Reboot now? + + + + Show Developer UI + + + + Show developer UI (Dev UI) for real-time parameters from various sources. + + + SettingsWindow @@ -641,6 +1158,22 @@ location set Navigation ナビゲーション + + SP - General + + + + SP - Controls + + + + SP - Vehicles + + + + SP - Visuals + + Setup @@ -878,6 +1411,44 @@ location set アンインストール + + SpeedLimitStyle + + Speed Limit Style + + + + MUTCD: US/Canada + + + + Vienna: Europe/Asia/etc. + + + + MUTCD + + + + Vienna + + + + + SpeedLimitValueOffset + + Speed Limit Offset (MPH / KM/H) ℹ + + + + Set speed limit higher or lower than actual speed limit for a more personalized drive. + + + + To use this feature, turn off "Enable Speed Limit % Offset". + + + SshControl @@ -945,14 +1516,6 @@ location set TogglesPanel - - Enable openpilot - openpilot を有効化 - - - Use the openpilot system for adaptive cruise control and lane keep driver assistance. Your attention is required at all times to use this feature. Changing this setting takes effect when the car is powered off. - openpilotによるアダプティブクルーズコントロールとレーンキーピングドライバーアシストを利用します。この機能を利用する際は、常に前方への注意が必要です。この設定を変更すると、車の電源が切れた時に反映されます。 - Enable Lane Departure Warnings 車線逸脱警報機能を有効化 @@ -985,10 +1548,6 @@ location set Disengage on Accelerator Pedal アクセルを踏むと openpilot を中断 - - When enabled, pressing the accelerator pedal will disengage openpilot. - この機能を有効化すると、openpilotを利用中にアクセルを踏むとopenpilotによる運転サポートを中断します。 - Show ETA in 24h Format 24時間表示 @@ -1053,6 +1612,40 @@ location set Enable experimental longitudinal control to allow Experimental mode. 実験段階のopenpilotによるアクセル制御を有効にしてください。 + + Enable sunnypilot + + + + Use the sunnypilot system for adaptive cruise control and lane keep driver assistance. Your attention is required at all times to use this feature. Changing this setting takes effect when the car is powered off. + + + + When enabled, pressing the accelerator pedal will disengage sunnypilot. + + + + + TorqueFriction + + FRICTION + + + + Adjust Friction for the Torque Lateral Controller + + + + + TorqueMaxLatAccel + + LAT_ACCEL_FACTOR + + + + Adjust Max Lateral Acceleration for the Torque Lateral Controller + + Updater @@ -1089,6 +1682,25 @@ location set 更新失敗 + + VwAccType + + Short Press +1/-1 Type + + + + Define the type of ACC control your car has with short press to +1 or -1. + + + + +/- + + + + RES/SET + + + WifiUI diff --git a/selfdrive/ui/translations/main_ko.ts b/selfdrive/ui/translations/main_ko.ts index f50d2d9b3f..9fe24d4a3b 100644 --- a/selfdrive/ui/translations/main_ko.ts +++ b/selfdrive/ui/translations/main_ko.ts @@ -89,6 +89,71 @@ LIMIT LIMIT + + Lane +only + + + + Lane +less + + + + Auto +Lane + + + + + AutoLaneChangeTimer + + Auto Lane Change Timer + + + + Set a timer to delay the auto lane change operation when the blinker is used. No nudge on the steering wheel is required to auto lane change if a timer is set. +Please use caution when using this feature. Only use the blinker when traffic and road conditions permit. + + + + Nudge + + + + Nudgeless + + + + s + + + + + BrightnessControl + + Brightness Control (Global, %) + + + + Manually adjusts the global brightness of the screen. + + + + Auto + + + + + CameraOffset + + Camera Offset (cm) + + + + Hack to trick vehicle to be left or right biased in its lane. Decreasing the value will make the car keep more left, increasing will make it keep more right. Changes take effect immediately. + + ConfirmationDialog @@ -116,6 +181,25 @@ 거절, %1 제거 + + DevUiRow + + Developer UI List + + + + Select the number of lists of real-time parameters you would like to display on the sunnypilot screen while driving. + + + + 1-Row + + + + 2-Row + + + DevicePanel @@ -162,10 +246,6 @@ REVIEW 다시보기 - - Review the rules, features, and limitations of openpilot - openpilot의 규칙, 기능 및 제한 다시보기 - Are you sure you want to review the training guide? 트레이닝 가이드를 다시보시겠습니까? @@ -198,10 +278,6 @@ Power Off 전원 종료 - - openpilot requires the device to be mounted within 4° left or right and within 5° up or 8° down. openpilot is continuously calibrating, resetting is rarely required. - openpilot은 좌우측은 4° 이내, 위쪽은 5° 아래쪽은 8° 이내로 장치를 설치해야 합니다. openpilot은 지속적으로 보정되므로 리셋은 거의 필요하지 않습니다. - Your device is pointed %1° %2 and %3° %4. 사용자의 장치가 %1° %2 및 %3° %4 위치에 설치되어있습니다. @@ -246,6 +322,14 @@ Review 다시보기 + + Review the rules, features, and limitations of sunnypilot + + + + sunnypilot requires the device to be mounted within 4° left or right and within 5° up or 8° down. sunnypilot is continuously calibrating, resetting is rarely required. + + DriveStats @@ -292,6 +376,37 @@ 안정적 모드 사용 + + GapAdjustCruiseMode + + Mode + + + + SW: Steering Wheel Button only + + + + UI: User Interface Button on screen only + + + + SW + UI: Steering Wheel Button + User Interface Button on screen + + + + S.W. + + + + UI + + + + S.W. + UI + + + InputDialog @@ -418,6 +533,37 @@ location set GPS를 기다리는 중 + + MaxTimeOffroad + + Max Time Offroad + + + + Device is automatically turned off after a set time when the engine is turned off (off-road) after driving (on-road). + + + + Always On + + + + Immediate + + + + s + + + + m + + + + h + + + MultiOptionDialog @@ -463,6 +609,40 @@ location set 알림 + + OnroadScreenOff + + Driving Screen Off Timer + + + + Turn off the device screen or reduce brightness to protect the screen after driving starts. It automatically brightens or turns on when a touch or event occurs. + + + + Always On + + + + s + + + + + OnroadScreenOffBrightness + + Driving Screen Off Brightness (%) + + + + When using the Driving Screen Off feature, the brightness is reduced according to the automatic brightness ratio. + + + + Dark + + + PairingPopup @@ -493,6 +673,17 @@ location set 사용 + + PathOffset + + Path Offset (cm) + + + + Hack to trick the model path to be left or right biased of the lane. Decreasing the value will shift the model more left, increasing will shift the model more right. Changes take effect immediately. + + + PrimeAdWidget @@ -553,10 +744,6 @@ location set dashcam dashcam - - openpilot - openpilot - %n minute(s) ago @@ -575,6 +762,10 @@ location set %n 일전 + + sunnypilot + + Reset @@ -615,6 +806,332 @@ location set 데이터 파티션을 마운트할 수 없습니다. 확인 버튼을 눌러 장치를 리셋합니다. + + SPControlsPanel + + Enable M.A.D.S. + + + + Enable the beloved M.A.D.S. feature. Disable toggle to revert back to stock openpilot engagement/disengagement. + + + + Disengage ALC On Brake Pedal ℹ + + + + Define brake pedal interactions with sunnypilot when M.A.D.S. is enabled. + + + + Enabled: Pressing the brake pedal will disengage Automatic Lane Centering (ALC) on sunnypilot. + + + + Disabled: Pressing the brake pedal will <b>NOT</b> disengage Automatic Lane Centering (ALC) on sunnypilot. + + + + Enable ACC+MADS with RES+/SET- + + + + Engage both M.A.D.S. and ACC with a single press of RES+ or SET- button. + + + + Note: Once M.A.D.S. is engaged via this mode, it will remain engaged until it is manually disabled via the M.A.D.S. button or car shut off. + + + + Pause Lateral Below Speed w/ Blinker + + + + Enable this toggle to pause lateral actuation with blinker when traveling below 30 MPH or 50 KM/H. + + + + Enable Dynamic Lane Profile + + + + Enable toggle to use Dynamic Lane Profile. Disable toggle to use Laneless only. + + + + Laneless for Curves in "Auto lane" + + + + While in Auto Lane, switch to Laneless for current/future curves. + + + + Custom Offsets + + + + Add custom offsets to Camera and Path in sunnypilot. + + + + Enable Gap Adjust Cruise ℹ + + + + Enable the Interval button on the steering wheel to adjust the cruise gap. + + + + Only available to cars with openpilot Longitudinal Control + + + + Enforce Torque Lateral Control + + + + Enable this to enforce sunnypilot to steer with Torque lateral control. + + + + Torque Lateral Control Live Tune + + + + Enables live tune for Torque lateral control. + + + + "Torque Lateral Control Live Tune"<br>You must restart your car or your device to apply these changes. + + + + Torque Lateral Controller Self-Tune + + + + Enables self-tune for Torque lateral control. + + + + "Torque Lateral Controller Self-Tune"<br>You must restart your car or your device to apply these changes. + + + + Enable Hands on Wheel Monitoring + + + + Monitor and alert when driver is not keeping the hands on the steering wheel. + + + + Enable Vision Based Turn Speed Control (V-TSC) + + + + Use vision path predictions to estimate the appropriate speed to drive through turns ahead. + + + + Enable Speed Limit Control (SLC) + + + + Use speed limit signs information from map data and car interface (if applicable) to automatically adapt cruise speed to road limits. + + + + Enable Speed Limit % Offset + + + + Set speed limit slightly higher than actual speed limit for a more natural drive. + + + + Enable Map Data Turn Speed Control (M-TSC) + + + + Use curvature information from map data to define speed limits to take turns ahead. + + + + ACC +/-: Long Press Reverse + + + + Change the ACC +/- buttons behavior with cruise speed change in sunnypilot. + + + + Disabled (Stock): Short=1, Long = 5 (imperial) / 10 (metric) + + + + Enabled: Short = 5 (imperial) / 10 (metric), Long=1 + + + + OSM: Use Offline Database + + + + + SPGeneralPanel + + Quiet Drive 🤫 + + + + sunnypilot will display alerts but only play the most important warning sounds. This feature can be toggled while the car is on. + + + + Green Traffic Light Chime (Beta) + + + + A chime will play when the traffic light you are waiting for turns green and you have no vehicle in front of you. If you are waiting behind another vehicle, the chime will play once the vehicle advances unless ACC is engaged. + + + + Note: This chime is only designed as a notification. It is the driver's responsibility to observe their environment and make decisions accordingly. + + + + Custom Boot Screen + + + + Display sunnypilot welcome screen while booting the device. + + + + Disable Onroad Uploads + + + + Disable uploads completely when onroad. Necessary to avoid high data usage when connected to Wi-Fi hotspot. Turn on this feature if you are looking to utilize map-based features, such as Speed Limit Control (SLC) and Map-based Turn Speed Control (MTSC). + + + + Error Troubleshoot + + + + VIEW + 보기 + + + Display error from the tmux session when an error has occurred from a system process. + + + + Debug snapshot on screen center tap + + + + Stores snapshot file with current state of some modules. + + + + + SPVehiclesPanel + + Hyundai/Kia/Genesis (HKG) + + + + Enhanced SCC Radar Interceptor ℹ + + + + sunnypilot will take over control of gas and brakes and will <b>NOT</b> disable the car's radar. This preserves AEB. + + + + Note: Only enable this feature if you have the Enhanced SCC Radar Interceptor hardware installed. + + + + Want to get one for your car? Reach out to sunnyhaibin#0865 on Discord for more information. + + + + Toyota/Lexus + + + + Volkswagen MQB/PQ + + + + + SPVisualsPanel + + Display Braking Status + + + + Enable this will turn the current speed value to red while the brake is used. + + + + Display Stand Still Timer + + + + Enable this will display time spent at a stop (i.e., at a stop lights, stop signs, traffic congestions). + + + + OSM: Show debug UI elements + + + + OSM: Show UI elements that aid debugging. + + + + Enable Mapbox Navigation* + + + + Enable built-in navigation on sunnypilot, powered by Mapbox. + + + + Access via the web interface: "http://<device_ip>:8082" + + + + If you do not have comma Prime, you will need to provide your own Mapbox token at https://mapbox.com/. Reach out to sunnyhaibin#0865 on Discord for more information. + + + + Huge thanks to the dragonpilot team for making this possible! + + + + "Enable Mapbox Navigation" +You must restart your car or your device to apply these changes. +Reboot now? + + + + Show Developer UI + + + + Show developer UI (Dev UI) for real-time parameters from various sources. + + + SettingsWindow @@ -641,6 +1158,22 @@ location set Navigation 네비게이션 + + SP - General + + + + SP - Controls + + + + SP - Vehicles + + + + SP - Visuals + + Setup @@ -878,6 +1411,44 @@ location set 제거 + + SpeedLimitStyle + + Speed Limit Style + + + + MUTCD: US/Canada + + + + Vienna: Europe/Asia/etc. + + + + MUTCD + + + + Vienna + + + + + SpeedLimitValueOffset + + Speed Limit Offset (MPH / KM/H) ℹ + + + + Set speed limit higher or lower than actual speed limit for a more personalized drive. + + + + To use this feature, turn off "Enable Speed Limit % Offset". + + + SshControl @@ -945,14 +1516,6 @@ location set TogglesPanel - - Enable openpilot - openpilot 사용 - - - Use the openpilot system for adaptive cruise control and lane keep driver assistance. Your attention is required at all times to use this feature. Changing this setting takes effect when the car is powered off. - 어댑티브 크루즈 컨트롤 및 차선 유지 운전자 보조를 위해 openpilot 시스템을 사용하십시오. 이 기능을 사용하려면 항상 주의를 기울여야 합니다. 설정변경은 장치 재부팅후 적용됩니다. - Enable Lane Departure Warnings 차선 이탈 경고 사용 @@ -985,10 +1548,6 @@ location set Disengage on Accelerator Pedal 가속페달 조작시 해제 - - When enabled, pressing the accelerator pedal will disengage openpilot. - 활성화된 경우 가속 페달을 누르면 openpilot이 해제됩니다. - Show ETA in 24h Format 24시간 형식으로 도착예정시간 표시 @@ -1053,6 +1612,40 @@ location set Enable experimental longitudinal control to allow Experimental mode. 실험적 롱컨트롤을 사용하려면 실험적 모드를 활성화 하세요. + + Enable sunnypilot + + + + Use the sunnypilot system for adaptive cruise control and lane keep driver assistance. Your attention is required at all times to use this feature. Changing this setting takes effect when the car is powered off. + + + + When enabled, pressing the accelerator pedal will disengage sunnypilot. + + + + + TorqueFriction + + FRICTION + + + + Adjust Friction for the Torque Lateral Controller + + + + + TorqueMaxLatAccel + + LAT_ACCEL_FACTOR + + + + Adjust Max Lateral Acceleration for the Torque Lateral Controller + + Updater @@ -1089,6 +1682,25 @@ location set 업데이트 실패 + + VwAccType + + Short Press +1/-1 Type + + + + Define the type of ACC control your car has with short press to +1 or -1. + + + + +/- + + + + RES/SET + + + WifiUI diff --git a/selfdrive/ui/translations/main_pt-BR.ts b/selfdrive/ui/translations/main_pt-BR.ts index 445de72fc3..89ef52990d 100644 --- a/selfdrive/ui/translations/main_pt-BR.ts +++ b/selfdrive/ui/translations/main_pt-BR.ts @@ -89,6 +89,71 @@ LIMIT VELO + + Lane +only + + + + Lane +less + + + + Auto +Lane + + + + + AutoLaneChangeTimer + + Auto Lane Change Timer + + + + Set a timer to delay the auto lane change operation when the blinker is used. No nudge on the steering wheel is required to auto lane change if a timer is set. +Please use caution when using this feature. Only use the blinker when traffic and road conditions permit. + + + + Nudge + + + + Nudgeless + + + + s + + + + + BrightnessControl + + Brightness Control (Global, %) + + + + Manually adjusts the global brightness of the screen. + + + + Auto + + + + + CameraOffset + + Camera Offset (cm) + + + + Hack to trick vehicle to be left or right biased in its lane. Decreasing the value will make the car keep more left, increasing will make it keep more right. Changes take effect immediately. + + ConfirmationDialog @@ -116,6 +181,25 @@ Rejeitar, desintalar %1 + + DevUiRow + + Developer UI List + + + + Select the number of lists of real-time parameters you would like to display on the sunnypilot screen while driving. + + + + 1-Row + + + + 2-Row + + + DevicePanel @@ -162,10 +246,6 @@ REVIEW REVISAR - - Review the rules, features, and limitations of openpilot - Revisar regras, aprimoramentos e limitações do openpilot - Are you sure you want to review the training guide? Tem certeza que quer rever o treinamento? @@ -198,10 +278,6 @@ Power Off Desligar - - openpilot requires the device to be mounted within 4° left or right and within 5° up or 8° down. openpilot is continuously calibrating, resetting is rarely required. - O openpilot requer que o dispositivo seja montado dentro de 4° esquerda ou direita e dentro de 5° para cima ou 8° para baixo. O openpilot está continuamente calibrando, resetar raramente é necessário. - Your device is pointed %1° %2 and %3° %4. Seu dispositivo está montado %1° %2 e %3° %4. @@ -246,6 +322,14 @@ Review Revisar + + Review the rules, features, and limitations of sunnypilot + + + + sunnypilot requires the device to be mounted within 4° left or right and within 5° up or 8° down. sunnypilot is continuously calibrating, resetting is rarely required. + + DriveStats @@ -292,6 +376,37 @@ MODO CHILL ATIVADO + + GapAdjustCruiseMode + + Mode + + + + SW: Steering Wheel Button only + + + + UI: User Interface Button on screen only + + + + SW + UI: Steering Wheel Button + User Interface Button on screen + + + + S.W. + + + + UI + + + + S.W. + UI + + + InputDialog @@ -419,6 +534,37 @@ trabalho definido Esperando por GPS + + MaxTimeOffroad + + Max Time Offroad + + + + Device is automatically turned off after a set time when the engine is turned off (off-road) after driving (on-road). + + + + Always On + + + + Immediate + + + + s + + + + m + + + + h + + + MultiOptionDialog @@ -464,6 +610,40 @@ trabalho definido ALERTA + + OnroadScreenOff + + Driving Screen Off Timer + + + + Turn off the device screen or reduce brightness to protect the screen after driving starts. It automatically brightens or turns on when a touch or event occurs. + + + + Always On + + + + s + + + + + OnroadScreenOffBrightness + + Driving Screen Off Brightness (%) + + + + When using the Driving Screen Off feature, the brightness is reduced according to the automatic brightness ratio. + + + + Dark + + + PairingPopup @@ -494,6 +674,17 @@ trabalho definido Ativar + + PathOffset + + Path Offset (cm) + + + + Hack to trick the model path to be left or right biased of the lane. Decreasing the value will shift the model more left, increasing will shift the model more right. Changes take effect immediately. + + + PrimeAdWidget @@ -554,10 +745,6 @@ trabalho definido dashcam dashcam - - openpilot - openpilot - %n minute(s) ago @@ -579,6 +766,10 @@ trabalho definido há %n dias + + sunnypilot + + Reset @@ -619,6 +810,332 @@ trabalho definido Não foi possível montar a partição de dados. Pressione confirmar para resetar seu dispositivo. + + SPControlsPanel + + Enable M.A.D.S. + + + + Enable the beloved M.A.D.S. feature. Disable toggle to revert back to stock openpilot engagement/disengagement. + + + + Disengage ALC On Brake Pedal ℹ + + + + Define brake pedal interactions with sunnypilot when M.A.D.S. is enabled. + + + + Enabled: Pressing the brake pedal will disengage Automatic Lane Centering (ALC) on sunnypilot. + + + + Disabled: Pressing the brake pedal will <b>NOT</b> disengage Automatic Lane Centering (ALC) on sunnypilot. + + + + Enable ACC+MADS with RES+/SET- + + + + Engage both M.A.D.S. and ACC with a single press of RES+ or SET- button. + + + + Note: Once M.A.D.S. is engaged via this mode, it will remain engaged until it is manually disabled via the M.A.D.S. button or car shut off. + + + + Pause Lateral Below Speed w/ Blinker + + + + Enable this toggle to pause lateral actuation with blinker when traveling below 30 MPH or 50 KM/H. + + + + Enable Dynamic Lane Profile + + + + Enable toggle to use Dynamic Lane Profile. Disable toggle to use Laneless only. + + + + Laneless for Curves in "Auto lane" + + + + While in Auto Lane, switch to Laneless for current/future curves. + + + + Custom Offsets + + + + Add custom offsets to Camera and Path in sunnypilot. + + + + Enable Gap Adjust Cruise ℹ + + + + Enable the Interval button on the steering wheel to adjust the cruise gap. + + + + Only available to cars with openpilot Longitudinal Control + + + + Enforce Torque Lateral Control + + + + Enable this to enforce sunnypilot to steer with Torque lateral control. + + + + Torque Lateral Control Live Tune + + + + Enables live tune for Torque lateral control. + + + + "Torque Lateral Control Live Tune"<br>You must restart your car or your device to apply these changes. + + + + Torque Lateral Controller Self-Tune + + + + Enables self-tune for Torque lateral control. + + + + "Torque Lateral Controller Self-Tune"<br>You must restart your car or your device to apply these changes. + + + + Enable Hands on Wheel Monitoring + + + + Monitor and alert when driver is not keeping the hands on the steering wheel. + + + + Enable Vision Based Turn Speed Control (V-TSC) + + + + Use vision path predictions to estimate the appropriate speed to drive through turns ahead. + + + + Enable Speed Limit Control (SLC) + + + + Use speed limit signs information from map data and car interface (if applicable) to automatically adapt cruise speed to road limits. + + + + Enable Speed Limit % Offset + + + + Set speed limit slightly higher than actual speed limit for a more natural drive. + + + + Enable Map Data Turn Speed Control (M-TSC) + + + + Use curvature information from map data to define speed limits to take turns ahead. + + + + ACC +/-: Long Press Reverse + + + + Change the ACC +/- buttons behavior with cruise speed change in sunnypilot. + + + + Disabled (Stock): Short=1, Long = 5 (imperial) / 10 (metric) + + + + Enabled: Short = 5 (imperial) / 10 (metric), Long=1 + + + + OSM: Use Offline Database + + + + + SPGeneralPanel + + Quiet Drive 🤫 + + + + sunnypilot will display alerts but only play the most important warning sounds. This feature can be toggled while the car is on. + + + + Green Traffic Light Chime (Beta) + + + + A chime will play when the traffic light you are waiting for turns green and you have no vehicle in front of you. If you are waiting behind another vehicle, the chime will play once the vehicle advances unless ACC is engaged. + + + + Note: This chime is only designed as a notification. It is the driver's responsibility to observe their environment and make decisions accordingly. + + + + Custom Boot Screen + + + + Display sunnypilot welcome screen while booting the device. + + + + Disable Onroad Uploads + + + + Disable uploads completely when onroad. Necessary to avoid high data usage when connected to Wi-Fi hotspot. Turn on this feature if you are looking to utilize map-based features, such as Speed Limit Control (SLC) and Map-based Turn Speed Control (MTSC). + + + + Error Troubleshoot + + + + VIEW + VER + + + Display error from the tmux session when an error has occurred from a system process. + + + + Debug snapshot on screen center tap + + + + Stores snapshot file with current state of some modules. + + + + + SPVehiclesPanel + + Hyundai/Kia/Genesis (HKG) + + + + Enhanced SCC Radar Interceptor ℹ + + + + sunnypilot will take over control of gas and brakes and will <b>NOT</b> disable the car's radar. This preserves AEB. + + + + Note: Only enable this feature if you have the Enhanced SCC Radar Interceptor hardware installed. + + + + Want to get one for your car? Reach out to sunnyhaibin#0865 on Discord for more information. + + + + Toyota/Lexus + + + + Volkswagen MQB/PQ + + + + + SPVisualsPanel + + Display Braking Status + + + + Enable this will turn the current speed value to red while the brake is used. + + + + Display Stand Still Timer + + + + Enable this will display time spent at a stop (i.e., at a stop lights, stop signs, traffic congestions). + + + + OSM: Show debug UI elements + + + + OSM: Show UI elements that aid debugging. + + + + Enable Mapbox Navigation* + + + + Enable built-in navigation on sunnypilot, powered by Mapbox. + + + + Access via the web interface: "http://<device_ip>:8082" + + + + If you do not have comma Prime, you will need to provide your own Mapbox token at https://mapbox.com/. Reach out to sunnyhaibin#0865 on Discord for more information. + + + + Huge thanks to the dragonpilot team for making this possible! + + + + "Enable Mapbox Navigation" +You must restart your car or your device to apply these changes. +Reboot now? + + + + Show Developer UI + + + + Show developer UI (Dev UI) for real-time parameters from various sources. + + + SettingsWindow @@ -645,6 +1162,22 @@ trabalho definido Navigation Navegação + + SP - General + + + + SP - Controls + + + + SP - Vehicles + + + + SP - Visuals + + Setup @@ -882,6 +1415,44 @@ trabalho definido Desinstalar + + SpeedLimitStyle + + Speed Limit Style + + + + MUTCD: US/Canada + + + + Vienna: Europe/Asia/etc. + + + + MUTCD + + + + Vienna + + + + + SpeedLimitValueOffset + + Speed Limit Offset (MPH / KM/H) ℹ + + + + Set speed limit higher or lower than actual speed limit for a more personalized drive. + + + + To use this feature, turn off "Enable Speed Limit % Offset". + + + SshControl @@ -949,14 +1520,6 @@ trabalho definido TogglesPanel - - Enable openpilot - Ativar openpilot - - - Use the openpilot system for adaptive cruise control and lane keep driver assistance. Your attention is required at all times to use this feature. Changing this setting takes effect when the car is powered off. - Use o sistema openpilot para controle de cruzeiro adaptativo e assistência ao motorista de manutenção de faixa. Sua atenção é necessária o tempo todo para usar esse recurso. A alteração desta configuração tem efeito quando o carro é desligado. - Enable Lane Departure Warnings Ativar Avisos de Saída de Faixa @@ -989,10 +1552,6 @@ trabalho definido Disengage on Accelerator Pedal Desacionar com Pedal do Acelerador - - When enabled, pressing the accelerator pedal will disengage openpilot. - Quando ativado, pressionar o pedal do acelerador desacionará o openpilot. - Show ETA in 24h Format Mostrar ETA em Formato 24h @@ -1057,6 +1616,40 @@ trabalho definido Enable experimental longitudinal control to allow Experimental mode. Ative o controle longitudinal experimental para permitir o modo Experimental. + + Enable sunnypilot + + + + Use the sunnypilot system for adaptive cruise control and lane keep driver assistance. Your attention is required at all times to use this feature. Changing this setting takes effect when the car is powered off. + + + + When enabled, pressing the accelerator pedal will disengage sunnypilot. + + + + + TorqueFriction + + FRICTION + + + + Adjust Friction for the Torque Lateral Controller + + + + + TorqueMaxLatAccel + + LAT_ACCEL_FACTOR + + + + Adjust Max Lateral Acceleration for the Torque Lateral Controller + + Updater @@ -1093,6 +1686,25 @@ trabalho definido Falha na atualização + + VwAccType + + Short Press +1/-1 Type + + + + Define the type of ACC control your car has with short press to +1 or -1. + + + + +/- + + + + RES/SET + + + WifiUI diff --git a/selfdrive/ui/translations/main_zh-CHS.ts b/selfdrive/ui/translations/main_zh-CHS.ts index 792a918770..d5feee5797 100644 --- a/selfdrive/ui/translations/main_zh-CHS.ts +++ b/selfdrive/ui/translations/main_zh-CHS.ts @@ -89,6 +89,71 @@ LIMIT LIMIT + + Lane +only + + + + Lane +less + + + + Auto +Lane + + + + + AutoLaneChangeTimer + + Auto Lane Change Timer + + + + Set a timer to delay the auto lane change operation when the blinker is used. No nudge on the steering wheel is required to auto lane change if a timer is set. +Please use caution when using this feature. Only use the blinker when traffic and road conditions permit. + + + + Nudge + + + + Nudgeless + + + + s + + + + + BrightnessControl + + Brightness Control (Global, %) + + + + Manually adjusts the global brightness of the screen. + + + + Auto + + + + + CameraOffset + + Camera Offset (cm) + + + + Hack to trick vehicle to be left or right biased in its lane. Decreasing the value will make the car keep more left, increasing will make it keep more right. Changes take effect immediately. + + ConfirmationDialog @@ -116,6 +181,25 @@ 拒绝并卸载%1 + + DevUiRow + + Developer UI List + + + + Select the number of lists of real-time parameters you would like to display on the sunnypilot screen while driving. + + + + 1-Row + + + + 2-Row + + + DevicePanel @@ -162,10 +246,6 @@ REVIEW 查看 - - Review the rules, features, and limitations of openpilot - 查看openpilot的使用规则,以及其功能和限制。 - Are you sure you want to review the training guide? 您确定要查看新手指南吗? @@ -198,10 +278,6 @@ Power Off 关机 - - openpilot requires the device to be mounted within 4° left or right and within 5° up or 8° down. openpilot is continuously calibrating, resetting is rarely required. - openpilot要求设备安装的偏航角在左4°和右4°之间,俯仰角在上5°和下8°之间。一般来说,openpilot会持续更新校准,很少需要重置。 - Your device is pointed %1° %2 and %3° %4. 您的设备校准为%1° %2、%3° %4。 @@ -246,6 +322,14 @@ Review 预览 + + Review the rules, features, and limitations of sunnypilot + + + + sunnypilot requires the device to be mounted within 4° left or right and within 5° up or 8° down. sunnypilot is continuously calibrating, resetting is rarely required. + + DriveStats @@ -292,6 +376,37 @@ 轻松模式运行 + + GapAdjustCruiseMode + + Mode + + + + SW: Steering Wheel Button only + + + + UI: User Interface Button on screen only + + + + SW + UI: Steering Wheel Button + User Interface Button on screen + + + + S.W. + + + + UI + + + + S.W. + UI + + + InputDialog @@ -416,6 +531,37 @@ location set 等待 GPS + + MaxTimeOffroad + + Max Time Offroad + + + + Device is automatically turned off after a set time when the engine is turned off (off-road) after driving (on-road). + + + + Always On + + + + Immediate + + + + s + + + + m + + + + h + + + MultiOptionDialog @@ -461,6 +607,40 @@ location set 警报 + + OnroadScreenOff + + Driving Screen Off Timer + + + + Turn off the device screen or reduce brightness to protect the screen after driving starts. It automatically brightens or turns on when a touch or event occurs. + + + + Always On + + + + s + + + + + OnroadScreenOffBrightness + + Driving Screen Off Brightness (%) + + + + When using the Driving Screen Off feature, the brightness is reduced according to the automatic brightness ratio. + + + + Dark + + + PairingPopup @@ -491,6 +671,17 @@ location set 启用 + + PathOffset + + Path Offset (cm) + + + + Hack to trick the model path to be left or right biased of the lane. Decreasing the value will shift the model more left, increasing will shift the model more right. Changes take effect immediately. + + + PrimeAdWidget @@ -551,10 +742,6 @@ location set dashcam 行车记录仪 - - openpilot - openpilot - %n minute(s) ago @@ -573,6 +760,10 @@ location set %n 天前 + + sunnypilot + + Reset @@ -613,6 +804,332 @@ location set 无法挂载数据分区。 确认以重置您的设备。 + + SPControlsPanel + + Enable M.A.D.S. + + + + Enable the beloved M.A.D.S. feature. Disable toggle to revert back to stock openpilot engagement/disengagement. + + + + Disengage ALC On Brake Pedal ℹ + + + + Define brake pedal interactions with sunnypilot when M.A.D.S. is enabled. + + + + Enabled: Pressing the brake pedal will disengage Automatic Lane Centering (ALC) on sunnypilot. + + + + Disabled: Pressing the brake pedal will <b>NOT</b> disengage Automatic Lane Centering (ALC) on sunnypilot. + + + + Enable ACC+MADS with RES+/SET- + + + + Engage both M.A.D.S. and ACC with a single press of RES+ or SET- button. + + + + Note: Once M.A.D.S. is engaged via this mode, it will remain engaged until it is manually disabled via the M.A.D.S. button or car shut off. + + + + Pause Lateral Below Speed w/ Blinker + + + + Enable this toggle to pause lateral actuation with blinker when traveling below 30 MPH or 50 KM/H. + + + + Enable Dynamic Lane Profile + + + + Enable toggle to use Dynamic Lane Profile. Disable toggle to use Laneless only. + + + + Laneless for Curves in "Auto lane" + + + + While in Auto Lane, switch to Laneless for current/future curves. + + + + Custom Offsets + + + + Add custom offsets to Camera and Path in sunnypilot. + + + + Enable Gap Adjust Cruise ℹ + + + + Enable the Interval button on the steering wheel to adjust the cruise gap. + + + + Only available to cars with openpilot Longitudinal Control + + + + Enforce Torque Lateral Control + + + + Enable this to enforce sunnypilot to steer with Torque lateral control. + + + + Torque Lateral Control Live Tune + + + + Enables live tune for Torque lateral control. + + + + "Torque Lateral Control Live Tune"<br>You must restart your car or your device to apply these changes. + + + + Torque Lateral Controller Self-Tune + + + + Enables self-tune for Torque lateral control. + + + + "Torque Lateral Controller Self-Tune"<br>You must restart your car or your device to apply these changes. + + + + Enable Hands on Wheel Monitoring + + + + Monitor and alert when driver is not keeping the hands on the steering wheel. + + + + Enable Vision Based Turn Speed Control (V-TSC) + + + + Use vision path predictions to estimate the appropriate speed to drive through turns ahead. + + + + Enable Speed Limit Control (SLC) + + + + Use speed limit signs information from map data and car interface (if applicable) to automatically adapt cruise speed to road limits. + + + + Enable Speed Limit % Offset + + + + Set speed limit slightly higher than actual speed limit for a more natural drive. + + + + Enable Map Data Turn Speed Control (M-TSC) + + + + Use curvature information from map data to define speed limits to take turns ahead. + + + + ACC +/-: Long Press Reverse + + + + Change the ACC +/- buttons behavior with cruise speed change in sunnypilot. + + + + Disabled (Stock): Short=1, Long = 5 (imperial) / 10 (metric) + + + + Enabled: Short = 5 (imperial) / 10 (metric), Long=1 + + + + OSM: Use Offline Database + + + + + SPGeneralPanel + + Quiet Drive 🤫 + + + + sunnypilot will display alerts but only play the most important warning sounds. This feature can be toggled while the car is on. + + + + Green Traffic Light Chime (Beta) + + + + A chime will play when the traffic light you are waiting for turns green and you have no vehicle in front of you. If you are waiting behind another vehicle, the chime will play once the vehicle advances unless ACC is engaged. + + + + Note: This chime is only designed as a notification. It is the driver's responsibility to observe their environment and make decisions accordingly. + + + + Custom Boot Screen + + + + Display sunnypilot welcome screen while booting the device. + + + + Disable Onroad Uploads + + + + Disable uploads completely when onroad. Necessary to avoid high data usage when connected to Wi-Fi hotspot. Turn on this feature if you are looking to utilize map-based features, such as Speed Limit Control (SLC) and Map-based Turn Speed Control (MTSC). + + + + Error Troubleshoot + + + + VIEW + 查看 + + + Display error from the tmux session when an error has occurred from a system process. + + + + Debug snapshot on screen center tap + + + + Stores snapshot file with current state of some modules. + + + + + SPVehiclesPanel + + Hyundai/Kia/Genesis (HKG) + + + + Enhanced SCC Radar Interceptor ℹ + + + + sunnypilot will take over control of gas and brakes and will <b>NOT</b> disable the car's radar. This preserves AEB. + + + + Note: Only enable this feature if you have the Enhanced SCC Radar Interceptor hardware installed. + + + + Want to get one for your car? Reach out to sunnyhaibin#0865 on Discord for more information. + + + + Toyota/Lexus + + + + Volkswagen MQB/PQ + + + + + SPVisualsPanel + + Display Braking Status + + + + Enable this will turn the current speed value to red while the brake is used. + + + + Display Stand Still Timer + + + + Enable this will display time spent at a stop (i.e., at a stop lights, stop signs, traffic congestions). + + + + OSM: Show debug UI elements + + + + OSM: Show UI elements that aid debugging. + + + + Enable Mapbox Navigation* + + + + Enable built-in navigation on sunnypilot, powered by Mapbox. + + + + Access via the web interface: "http://<device_ip>:8082" + + + + If you do not have comma Prime, you will need to provide your own Mapbox token at https://mapbox.com/. Reach out to sunnyhaibin#0865 on Discord for more information. + + + + Huge thanks to the dragonpilot team for making this possible! + + + + "Enable Mapbox Navigation" +You must restart your car or your device to apply these changes. +Reboot now? + + + + Show Developer UI + + + + Show developer UI (Dev UI) for real-time parameters from various sources. + + + SettingsWindow @@ -639,6 +1156,22 @@ location set Navigation 导航 + + SP - General + SP - 通用 + + + SP - Controls + SP - 控制 + + + SP - Vehicles + SP - 车辆 + + + SP - Visuals + SP - 界面 + Setup @@ -876,6 +1409,44 @@ location set 卸载 + + SpeedLimitStyle + + Speed Limit Style + + + + MUTCD: US/Canada + + + + Vienna: Europe/Asia/etc. + + + + MUTCD + + + + Vienna + + + + + SpeedLimitValueOffset + + Speed Limit Offset (MPH / KM/H) ℹ + + + + Set speed limit higher or lower than actual speed limit for a more personalized drive. + + + + To use this feature, turn off "Enable Speed Limit % Offset". + + + SshControl @@ -943,14 +1514,6 @@ location set TogglesPanel - - Enable openpilot - 启用openpilot - - - Use the openpilot system for adaptive cruise control and lane keep driver assistance. Your attention is required at all times to use this feature. Changing this setting takes effect when the car is powered off. - 使用openpilot进行自适应巡航和车道保持辅助。使用此功能时您必须时刻保持注意力。该设置的更改在熄火时生效。 - Enable Lane Departure Warnings 启用车道偏离警告 @@ -983,10 +1546,6 @@ location set Disengage on Accelerator Pedal 踩油门时取消控制 - - When enabled, pressing the accelerator pedal will disengage openpilot. - 启用后,踩下油门踏板将取消openpilot。 - Show ETA in 24h Format 以24小时格式显示预计到达时间 @@ -1051,6 +1610,40 @@ location set Enable experimental longitudinal control to allow Experimental mode. 启用试验性的纵向控制,以便允许使用试验模式。 + + Enable sunnypilot + + + + Use the sunnypilot system for adaptive cruise control and lane keep driver assistance. Your attention is required at all times to use this feature. Changing this setting takes effect when the car is powered off. + + + + When enabled, pressing the accelerator pedal will disengage sunnypilot. + + + + + TorqueFriction + + FRICTION + + + + Adjust Friction for the Torque Lateral Controller + + + + + TorqueMaxLatAccel + + LAT_ACCEL_FACTOR + + + + Adjust Max Lateral Acceleration for the Torque Lateral Controller + + Updater @@ -1087,6 +1680,25 @@ location set 更新失败 + + VwAccType + + Short Press +1/-1 Type + + + + Define the type of ACC control your car has with short press to +1 or -1. + + + + +/- + + + + RES/SET + + + WifiUI diff --git a/selfdrive/ui/translations/main_zh-CHT.ts b/selfdrive/ui/translations/main_zh-CHT.ts index e8e2ab6bd3..56efd383df 100644 --- a/selfdrive/ui/translations/main_zh-CHT.ts +++ b/selfdrive/ui/translations/main_zh-CHT.ts @@ -89,6 +89,71 @@ LIMIT 速限 + + Lane +only + + + + Lane +less + + + + Auto +Lane + + + + + AutoLaneChangeTimer + + Auto Lane Change Timer + + + + Set a timer to delay the auto lane change operation when the blinker is used. No nudge on the steering wheel is required to auto lane change if a timer is set. +Please use caution when using this feature. Only use the blinker when traffic and road conditions permit. + + + + Nudge + + + + Nudgeless + + + + s + + + + + BrightnessControl + + Brightness Control (Global, %) + + + + Manually adjusts the global brightness of the screen. + + + + Auto + + + + + CameraOffset + + Camera Offset (cm) + + + + Hack to trick vehicle to be left or right biased in its lane. Decreasing the value will make the car keep more left, increasing will make it keep more right. Changes take effect immediately. + + ConfirmationDialog @@ -116,6 +181,25 @@ 拒絕並解除安裝 %1 + + DevUiRow + + Developer UI List + + + + Select the number of lists of real-time parameters you would like to display on the sunnypilot screen while driving. + + + + 1-Row + + + + 2-Row + + + DevicePanel @@ -162,10 +246,6 @@ REVIEW 觀看 - - Review the rules, features, and limitations of openpilot - 觀看 openpilot 的使用規則、功能和限制 - Are you sure you want to review the training guide? 您確定要觀看使用教學嗎? @@ -198,10 +278,6 @@ Power Off 關機 - - openpilot requires the device to be mounted within 4° left or right and within 5° up or 8° down. openpilot is continuously calibrating, resetting is rarely required. - openpilot 需要將裝置固定在左右偏差 4° 以內,朝上偏差 5° 以内或朝下偏差 8° 以内。鏡頭在後台會持續自動校準,很少有需要重置的情况。 - Your device is pointed %1° %2 and %3° %4. 你的設備目前朝%2 %1° 以及朝%4 %3° 。 @@ -246,6 +322,14 @@ Review 回顧 + + Review the rules, features, and limitations of sunnypilot + + + + sunnypilot requires the device to be mounted within 4° left or right and within 5° up or 8° down. sunnypilot is continuously calibrating, resetting is rarely required. + + DriveStats @@ -292,6 +376,37 @@ 輕鬆模式 ON + + GapAdjustCruiseMode + + Mode + + + + SW: Steering Wheel Button only + + + + UI: User Interface Button on screen only + + + + SW + UI: Steering Wheel Button + User Interface Button on screen + + + + S.W. + + + + UI + + + + S.W. + UI + + + InputDialog @@ -418,6 +533,37 @@ location set 等待 GPS + + MaxTimeOffroad + + Max Time Offroad + + + + Device is automatically turned off after a set time when the engine is turned off (off-road) after driving (on-road). + + + + Always On + + + + Immediate + + + + s + + + + m + + + + h + + + MultiOptionDialog @@ -463,6 +609,40 @@ location set 提醒 + + OnroadScreenOff + + Driving Screen Off Timer + + + + Turn off the device screen or reduce brightness to protect the screen after driving starts. It automatically brightens or turns on when a touch or event occurs. + + + + Always On + + + + s + + + + + OnroadScreenOffBrightness + + Driving Screen Off Brightness (%) + + + + When using the Driving Screen Off feature, the brightness is reduced according to the automatic brightness ratio. + + + + Dark + + + PairingPopup @@ -493,6 +673,17 @@ location set 啟用 + + PathOffset + + Path Offset (cm) + + + + Hack to trick the model path to be left or right biased of the lane. Decreasing the value will shift the model more left, increasing will shift the model more right. Changes take effect immediately. + + + PrimeAdWidget @@ -553,10 +744,6 @@ location set dashcam 行車記錄器 - - openpilot - openpilot - %n minute(s) ago @@ -575,6 +762,10 @@ location set %n 天前 + + sunnypilot + + Reset @@ -615,6 +806,332 @@ location set 無法掛載數據分區。請按確認重置您的設備。 + + SPControlsPanel + + Enable M.A.D.S. + + + + Enable the beloved M.A.D.S. feature. Disable toggle to revert back to stock openpilot engagement/disengagement. + + + + Disengage ALC On Brake Pedal ℹ + + + + Define brake pedal interactions with sunnypilot when M.A.D.S. is enabled. + + + + Enabled: Pressing the brake pedal will disengage Automatic Lane Centering (ALC) on sunnypilot. + + + + Disabled: Pressing the brake pedal will <b>NOT</b> disengage Automatic Lane Centering (ALC) on sunnypilot. + + + + Enable ACC+MADS with RES+/SET- + + + + Engage both M.A.D.S. and ACC with a single press of RES+ or SET- button. + + + + Note: Once M.A.D.S. is engaged via this mode, it will remain engaged until it is manually disabled via the M.A.D.S. button or car shut off. + + + + Pause Lateral Below Speed w/ Blinker + + + + Enable this toggle to pause lateral actuation with blinker when traveling below 30 MPH or 50 KM/H. + + + + Enable Dynamic Lane Profile + + + + Enable toggle to use Dynamic Lane Profile. Disable toggle to use Laneless only. + + + + Laneless for Curves in "Auto lane" + + + + While in Auto Lane, switch to Laneless for current/future curves. + + + + Custom Offsets + + + + Add custom offsets to Camera and Path in sunnypilot. + + + + Enable Gap Adjust Cruise ℹ + + + + Enable the Interval button on the steering wheel to adjust the cruise gap. + + + + Only available to cars with openpilot Longitudinal Control + + + + Enforce Torque Lateral Control + + + + Enable this to enforce sunnypilot to steer with Torque lateral control. + + + + Torque Lateral Control Live Tune + + + + Enables live tune for Torque lateral control. + + + + "Torque Lateral Control Live Tune"<br>You must restart your car or your device to apply these changes. + + + + Torque Lateral Controller Self-Tune + + + + Enables self-tune for Torque lateral control. + + + + "Torque Lateral Controller Self-Tune"<br>You must restart your car or your device to apply these changes. + + + + Enable Hands on Wheel Monitoring + + + + Monitor and alert when driver is not keeping the hands on the steering wheel. + + + + Enable Vision Based Turn Speed Control (V-TSC) + + + + Use vision path predictions to estimate the appropriate speed to drive through turns ahead. + + + + Enable Speed Limit Control (SLC) + + + + Use speed limit signs information from map data and car interface (if applicable) to automatically adapt cruise speed to road limits. + + + + Enable Speed Limit % Offset + + + + Set speed limit slightly higher than actual speed limit for a more natural drive. + + + + Enable Map Data Turn Speed Control (M-TSC) + + + + Use curvature information from map data to define speed limits to take turns ahead. + + + + ACC +/-: Long Press Reverse + + + + Change the ACC +/- buttons behavior with cruise speed change in sunnypilot. + + + + Disabled (Stock): Short=1, Long = 5 (imperial) / 10 (metric) + + + + Enabled: Short = 5 (imperial) / 10 (metric), Long=1 + + + + OSM: Use Offline Database + + + + + SPGeneralPanel + + Quiet Drive 🤫 + + + + sunnypilot will display alerts but only play the most important warning sounds. This feature can be toggled while the car is on. + + + + Green Traffic Light Chime (Beta) + + + + A chime will play when the traffic light you are waiting for turns green and you have no vehicle in front of you. If you are waiting behind another vehicle, the chime will play once the vehicle advances unless ACC is engaged. + + + + Note: This chime is only designed as a notification. It is the driver's responsibility to observe their environment and make decisions accordingly. + + + + Custom Boot Screen + + + + Display sunnypilot welcome screen while booting the device. + + + + Disable Onroad Uploads + + + + Disable uploads completely when onroad. Necessary to avoid high data usage when connected to Wi-Fi hotspot. Turn on this feature if you are looking to utilize map-based features, such as Speed Limit Control (SLC) and Map-based Turn Speed Control (MTSC). + + + + Error Troubleshoot + + + + VIEW + 觀看 + + + Display error from the tmux session when an error has occurred from a system process. + + + + Debug snapshot on screen center tap + + + + Stores snapshot file with current state of some modules. + + + + + SPVehiclesPanel + + Hyundai/Kia/Genesis (HKG) + + + + Enhanced SCC Radar Interceptor ℹ + + + + sunnypilot will take over control of gas and brakes and will <b>NOT</b> disable the car's radar. This preserves AEB. + + + + Note: Only enable this feature if you have the Enhanced SCC Radar Interceptor hardware installed. + + + + Want to get one for your car? Reach out to sunnyhaibin#0865 on Discord for more information. + + + + Toyota/Lexus + + + + Volkswagen MQB/PQ + + + + + SPVisualsPanel + + Display Braking Status + + + + Enable this will turn the current speed value to red while the brake is used. + + + + Display Stand Still Timer + + + + Enable this will display time spent at a stop (i.e., at a stop lights, stop signs, traffic congestions). + + + + OSM: Show debug UI elements + + + + OSM: Show UI elements that aid debugging. + + + + Enable Mapbox Navigation* + + + + Enable built-in navigation on sunnypilot, powered by Mapbox. + + + + Access via the web interface: "http://<device_ip>:8082" + + + + If you do not have comma Prime, you will need to provide your own Mapbox token at https://mapbox.com/. Reach out to sunnyhaibin#0865 on Discord for more information. + + + + Huge thanks to the dragonpilot team for making this possible! + + + + "Enable Mapbox Navigation" +You must restart your car or your device to apply these changes. +Reboot now? + + + + Show Developer UI + + + + Show developer UI (Dev UI) for real-time parameters from various sources. + + + SettingsWindow @@ -641,6 +1158,22 @@ location set Navigation 導航 + + SP - General + SP - 通用 + + + SP - Controls + SP - 控制 + + + SP - Vehicles + SP - 車輛 + + + SP - Visuals + SP - 界面 + Setup @@ -878,6 +1411,44 @@ location set 解除安裝 + + SpeedLimitStyle + + Speed Limit Style + + + + MUTCD: US/Canada + + + + Vienna: Europe/Asia/etc. + + + + MUTCD + + + + Vienna + + + + + SpeedLimitValueOffset + + Speed Limit Offset (MPH / KM/H) ℹ + + + + Set speed limit higher or lower than actual speed limit for a more personalized drive. + + + + To use this feature, turn off "Enable Speed Limit % Offset". + + + SshControl @@ -945,14 +1516,6 @@ location set TogglesPanel - - Enable openpilot - 啟用 openpilot - - - Use the openpilot system for adaptive cruise control and lane keep driver assistance. Your attention is required at all times to use this feature. Changing this setting takes effect when the car is powered off. - 使用 openpilot 的主動式巡航和車道保持功能,開啟後您需要持續集中注意力,設定變更在重新啟動車輛後生效。 - Enable Lane Departure Warnings 啟用車道偏離警告 @@ -985,10 +1548,6 @@ location set Disengage on Accelerator Pedal 油門取消控車 - - When enabled, pressing the accelerator pedal will disengage openpilot. - 啟用後,踩踏油門將會取消 openpilot 控制。 - Show ETA in 24h Format 預計到達時間單位改用 24 小時制 @@ -1053,6 +1612,40 @@ location set Enable experimental longitudinal control to allow Experimental mode. 啟用實驗性縱向控制以使用實驗模式。 + + Enable sunnypilot + + + + Use the sunnypilot system for adaptive cruise control and lane keep driver assistance. Your attention is required at all times to use this feature. Changing this setting takes effect when the car is powered off. + + + + When enabled, pressing the accelerator pedal will disengage sunnypilot. + + + + + TorqueFriction + + FRICTION + + + + Adjust Friction for the Torque Lateral Controller + + + + + TorqueMaxLatAccel + + LAT_ACCEL_FACTOR + + + + Adjust Max Lateral Acceleration for the Torque Lateral Controller + + Updater @@ -1089,6 +1682,25 @@ location set 更新失敗 + + VwAccType + + Short Press +1/-1 Type + + + + Define the type of ACC control your car has with short press to +1 or -1. + + + + +/- + + + + RES/SET + + + WifiUI