carrot/selfdrive/frogpilot/ui/qt/offroad/control_settings.cc

1214 lines
73 KiB
C++
Raw Normal View History

2024-05-09 19:49:07 -07:00
#include <filesystem>
#include <iostream>
#include "selfdrive/frogpilot/ui/qt/offroad/control_settings.h"
namespace fs = std::filesystem;
bool checkCommaNNFFSupport(const std::string &carFingerprint) {
const std::string filePath = "../car/torque_data/neural_ff_weights.json";
if (!std::filesystem::exists(filePath)) {
return false;
}
std::ifstream file(filePath);
std::string line;
while (std::getline(file, line)) {
if (line.find(carFingerprint) != std::string::npos) {
std::cout << "comma's NNFF supports fingerprint: " << carFingerprint << std::endl;
return true;
}
}
return false;
}
bool checkNNFFLogFileExists(const std::string &carFingerprint) {
const fs::path dirPath("../car/torque_data/lat_models");
if (!fs::exists(dirPath)) {
std::cerr << "Directory does not exist: " << fs::absolute(dirPath) << std::endl;
return false;
}
for (const auto &entry : fs::directory_iterator(dirPath)) {
if (entry.path().filename().string().find(carFingerprint) == 0) {
std::cout << "NNFF supports fingerprint: " << entry.path().filename() << std::endl;
return true;
}
}
return false;
}
FrogPilotControlsPanel::FrogPilotControlsPanel(SettingsWindow *parent) : FrogPilotListWidget(parent) {
std::string branch = params.get("GitBranch");
isRelease = branch == "FrogPilot";
const std::vector<std::tuple<QString, QString, QString, QString>> controlToggles {
{"AlwaysOnLateral", tr("始终开启横向控制"), tr("在使用刹车或油门踏板时保持openpilot的横向控制。\n\n仅通过'巡航控制'按钮停用。"), "../frogpilot/assets/toggle_icons/icon_always_on_lateral.png"},
{"AlwaysOnLateralMain", tr("启用巡航主控"), tr("通过点击'巡航控制'按钮启用'Always On Lateral'无需先启用openpilot。"), ""},
{"PauseAOLOnBrake", tr("刹车时暂停"), tr("当刹车踏板在设定速度以下被按下时暂停'Always On Lateral'。"), ""},
{"HideAOLStatusBar", tr("隐藏状态栏"), tr("不使用'Always On Lateral'的状态栏。"), ""},
{"ConditionalExperimental", tr("条件实验模式"), tr("在预定义条件下自动切换到'实验模式'。"), "../frogpilot/assets/toggle_icons/icon_conditional.png"},
{"CECurves", tr("检测到曲线"), tr("检测到曲线时切换到'实验模式'。"), ""},
{"CENavigation", tr("基于导航"), tr("基于导航数据切换到'实验模式'。(例如:交叉路口、停车标志、即将转弯等)"), ""},
{"CESlowerLead", tr("检测到较慢/停止的前车"), tr("检测到前方有较慢或停止的前车时切换到'实验模式'。"), ""},
{"CEStopLights", tr("红绿灯和停车标志"), tr("检测到红绿灯或停车标志时切换到'实验模式'。"), ""},
{"CESignal", tr("低速时使用转向灯"), tr("在高速公路速度以下使用转向灯时切换到'实验模式'以帮助转弯。"), ""},
{"HideCEMStatusBar", tr("隐藏状态栏"), tr("不使用'条件实验模式'的状态栏。"), ""},
{"DeviceManagement", tr("设备管理"), tr("根据个人喜好调整设备的行为。"), "../frogpilot/assets/toggle_icons/icon_device.png"},
{"DeviceShutdown", tr("设备关闭计时器"), tr("配置设备在离开道路后多快关闭。"), ""},
{"NoLogging", tr("禁用日志记录"), tr("关闭所有数据跟踪以增强隐私或减少热负荷。"), ""},
{"NoUploads", tr("禁用上传"), tr("关闭所有数据上传到comma的服务器。"), ""},
{"IncreaseThermalLimits", tr("提高热安全限制"), tr("允许设备在高于comma推荐的热限温度下运行。"), ""},
{"LowVoltageShutdown", tr("低电压关闭阈值"), tr("当电池达到特定电压水平时自动关闭设备以防止电池损坏。"), ""},
{"OfflineMode", tr("离线模式"), tr("允许设备无限期离线。"), ""},
{"DrivingPersonalities", tr("驾驶个性化"), tr("管理comma的'个性化配置文件'的驾驶行为。"), "../frogpilot/assets/toggle_icons/icon_personality.png"},
{"CustomPersonalities", tr("自定义个性化"), tr("根据您的驾驶风格自定义驾驶个性化配置文件。"), ""},
{"TrafficPersonalityProfile", tr("交通个性化"), tr("自定义'Traffic'个性化配置文件。"), "../frogpilot/assets/other_images/traffic.png"},
{"TrafficFollow", tr("跟车距离"), tr("设置使用'Traffic Mode'时的最小跟车距离。您的跟车距离将在0到%1之间动态调整介于此距离和'Aggressive'配置文件的跟车距离之间。\n\n例如:\n\nTraffic Mode: 0.5秒\nAggressive: 1.0秒\n\n0%2 = 0.5秒\n%3 = 0.75秒\n%1 = 1.0秒"), ""},
{"TrafficJerkAcceleration", tr("加速/减速响应偏移"), tr("自定义使用'Traffic Mode'时的加速响应率。"), ""},
{"TrafficJerkSpeed", tr("速度控制响应偏移"), tr("自定义使用'Traffic Mode'时保持速度(包括制动)的响应率。"), ""},
{"ResetTrafficPersonality", tr("重置设置"), tr("将'Traffic Mode'个性化配置的值重置为默认值。"), ""},
{"AggressivePersonalityProfile", tr("激进个性化"), tr("自定义'Aggressive'个性化配置文件。"), "../frogpilot/assets/other_images/aggressive.png"},
{"AggressiveFollow", tr("跟车距离"), tr("设置'Aggressive'个性化配置的跟车距离。表示跟随前车的秒数。\n\n默认值1.25秒。"), ""},
{"AggressiveJerkAcceleration", tr("加速/减速响应偏移"), tr("自定义使用'Aggressive'个性化配置时的加速响应率。"), ""},
{"AggressiveJerkSpeed", tr("速度控制响应偏移"), tr("自定义使用'Aggressive'个性化配置时保持速度(包括制动)的响应率。"), ""},
{"ResetAggressivePersonality", tr("重置设置"), tr("将'Aggressive'个性化配置的值重置为默认值。"), ""},
{"StandardPersonalityProfile", tr("标准个性化"), tr("自定义'Standard'个性化配置文件。"), "../frogpilot/assets/other_images/standard.png"},
{"StandardFollow", tr("跟车距离"), tr("设置'Standard'个性化配置的跟车距离。表示跟随前车的秒数。\n\n默认值1.45秒。"), ""},
{"StandardJerkAcceleration", tr("加速/减速响应偏移"), tr("自定义使用'Standard'个性化配置时的加速响应率。"), ""},
{"StandardJerkSpeed", tr("速度控制响应偏移"), tr("自定义使用'Standard'个性化配置时保持速度(包括制动)的响应率。"), ""},
{"ResetStandardPersonality", tr("重置设置"), tr("将'Standard'个性化配置的值重置为默认值。"), ""},
{"RelaxedPersonalityProfile", tr("放松个性化"), tr("自定义'Relaxed'个性化配置文件。"), "../frogpilot/assets/other_images/relaxed.png"},
{"RelaxedFollow", tr("跟车距离"), tr("设置'Relaxed'个性化配置的跟车距离。表示跟随前车的秒数。\n\n默认值1.75秒。"), ""},
{"RelaxedJerkAcceleration", tr("加速/减速响应偏移"), tr("自定义使用'Relaxed'个性化配置时的加速响应率。"), ""},
{"RelaxedJerkSpeed", tr("速度控制响应偏移"), tr("自定义使用'Relaxed'个性化配置时保持速度(包括制动)的响应率。"), ""},
{"ResetRelaxedPersonality", tr("重置设置"), tr("将'Relaxed'个性化配置的值重置为默认值。"), ""},
{"OnroadDistanceButton", tr("道路距离按钮"), tr("通过onroad UI模拟一个距离按钮来控制个性化配置、'实验模式'和'Traffic Mode'。"), ""},
{"ExperimentalModeActivation", tr("实验模式激活"), tr("通过方向盘或屏幕上的按钮切换实验模式。\n\n覆盖'条件实验模式'。"), "../assets/img_experimental_white.svg"},
{"ExperimentalModeViaLKAS", tr("双击LKAS"), tr("通过双击方向盘上的'LKAS'按钮启用/禁用'实验模式'。"), ""},
{"ExperimentalModeViaTap", tr("双击UI"), tr("通过在0.5秒内双击onroad UI启用/禁用'实验模式'。"), ""},
{"ExperimentalModeViaDistance", tr("长按距离"), tr("通过在方向盘上长按'distance'按钮0.5秒启用/禁用'实验模式'。"), ""},
{"LaneChangeCustomizations", tr("变道自定义"), tr("自定义openpilot中的变道行为。"), "../frogpilot/assets/toggle_icons/icon_lane.png"},
{"MinimumLaneChangeSpeed", tr("最小变道速度"), tr("自定义允许openpilot变道的最小驾驶速度。"), ""},
{"NudgelessLaneChange", tr("无推挤变道"), tr("启用无需手动转向输入的变道。"), ""},
{"LaneChangeTime", tr("变道计时器"), tr("设置执行变道前的延迟。"), ""},
{"LaneDetectionWidth", tr("车道检测阈值"), tr("设置被视为车道所需的车道宽度。"), ""},
{"OneLaneChange", tr("每个信号一个变道"), tr("每次转向信号激活只允许一次变道。"), ""},
{"LateralTune", tr("横向调节"), tr("修改openpilot的转向行为。"), "../frogpilot/assets/toggle_icons/icon_lateral_tune.png"},
{"ForceAutoTune", tr("强制自动调节"), tr("强制comma的自动横向调节以支持不受支持的车辆。"), ""},
{"NNFF", tr("NNFF"), tr("使用Twilsonco的神经网络前馈以增强横向控制的精度。"), ""},
{"NNFFLite", tr("NNFF-Lite"), tr("为没有可用NNFF日志的车辆使用Twilsonco的神经网络前馈以增强横向控制的精度。"), ""},
{"SteerRatio", steerRatioStock != 0 ? QString(tr("转向比(默认值:%1")).arg(QString::number(steerRatioStock, 'f', 2)) : tr("转向比"), tr("使用自定义转向比而不是comma的自动调节值。"), ""},
{"TacoTune", tr("Taco调节"), tr("使用comma的'Taco调节',旨在处理左转和右转。"), ""},
{"TurnDesires", tr("使用转向期望"), tr("在低于最小变道速度的转弯中使用转向期望以提高精度。"), ""},
{"LongitudinalTune", tr("纵向调节"), tr("修改openpilot的加速和制动行为。"), "../frogpilot/assets/toggle_icons/icon_longitudinal_tune.png"},
{"AccelerationProfile", tr("加速配置文件"), tr("将加速率更改为运动型或环保型。"), ""},
{"DecelerationProfile", tr("减速配置文件"), tr("将减速率更改为运动型或环保型。"), ""},
{"AggressiveAcceleration", tr("增加跟随前车的加速"), tr("在跟随更快的前车时增加攻击性。"), ""},
{"StoppingDistance", tr("增加跟随前车的停止距离"), tr("增加停止距离,以便更舒适地停靠在前车后。"), ""},
{"LeadDetectionThreshold", tr("前车检测阈值"), tr("增加或减少前车检测阈值,以便更早检测前车或提高模型信心。"), ""},
{"SmoothBraking", tr("更平稳的制动"), tr("在接近较慢的车辆时平滑制动行为。"), ""},
{"TrafficMode", tr("交通模式"), tr("通过长按'distance'按钮2.5秒启用'交通模式'。当'交通模式'处于活动状态时onroad UI将变为红色openpilot将针对停走交通进行驾驶。"), ""},
{"MTSCEnabled", tr("地图转弯速度控制"), tr("为下载地图检测到的预期曲线减速。"), "../frogpilot/assets/toggle_icons/icon_speed_map.png"},
{"DisableMTSCSmoothing", tr("禁用MTSC UI平滑"), tr("禁用onroad UI中请求速度的平滑以准确显示MTSC当前请求的速度。"), ""},
{"MTSCCurvatureCheck", tr("模型曲率检测故障安全"), tr("仅在模型检测到道路曲线时触发MTSC。纯粹用作故障安全以防止误报。如果您从未遇到误报请将其关闭。"), ""},
{"MTSCAggressiveness", tr("转弯速度攻击性"), tr("设置转弯速度的攻击性。更高的值会导致更快的转弯,较低的值会导致更温和的转弯。\n\n+-1%的变化会导致速度大约提高或降低1 mph。"), ""},
{"ModelSelector", tr("模型选择器"), tr("管理openpilot的驾驶模型。"), "../assets/offroad/icon_calibration.png"},
{"QOLControls", tr("生活质量"), tr("各种生活质量的改进以提升您整体的openpilot体验。"), "../frogpilot/assets/toggle_icons/quality_of_life.png"},
{"CustomCruise", tr("巡航加速间隔"), tr("设置一个自定义间隔来增加最大设定速度。"), ""},
{"CustomCruiseLong", tr("巡航加速间隔(长按)"), tr("在按住巡航加速按钮时设置一个自定义间隔来增加最大设定速度。"), ""},
{"MapGears", tr("将加速/减速映射到档位"), tr("将您的加速/减速配置映射到您的'Eco'和/或'Sport'档位。"), ""},
{"PauseLateralSpeed", tr("低于设定速度暂停横向控制"), tr("在所有低于设定速度的速度下暂停横向控制。"), ""},
{"ReverseCruise", tr("反向巡航加速"), tr("反转'长按'功能逻辑以将最大设定速度增加5而不是1。适合快速增加最大速度。"), ""},
{"SetSpeedOffset", tr("设置速度偏移"), tr("为您期望的设定速度设置一个偏移。"), ""},
{"SpeedLimitController", tr("速度限制控制器"), tr("使用'开放街道地图'、'在openpilot上导航'或您汽车的仪表盘(仅限丰田/雷克萨斯/HKG自动调整最大速度以匹配当前速度限制。"), "../assets/offroad/icon_speed_limit.png"},
{"SLCControls", tr("控制设置"), tr("管理与'速度限制控制器'相关的切换。"), ""},
{"Offset1", tr("速度限制偏移0-34 mph"), tr("适用于速度限制在0-34 mph之间的速度限制偏移。"), ""},
{"Offset2", tr("速度限制偏移35-54 mph"), tr("适用于速度限制在35-54 mph之间的速度限制偏移。"), ""},
{"Offset3", tr("速度限制偏移55-64 mph"), tr("适用于速度限制在55-64 mph之间的速度限制偏移。"), ""},
{"Offset4", tr("速度限制偏移65-99 mph"), tr("适用于速度限制在65-99 mph之间的速度限制偏移。"), ""},
{"SLCFallback", tr("回退方法"), tr("选择在没有可用速度限制时的回退方法。"), ""},
{"SLCOverride", tr("覆盖方法"), tr("选择您首选的覆盖当前速度限制的方法。"), ""},
{"SLCPriority", tr("优先顺序"), tr("配置速度限制的优先顺序。"), ""},
{"SLCQOL", tr("生活质量设置"), tr("管理与'速度限制控制器'的生活质量功能相关的切换。"), ""},
{"SLCConfirmation", tr("确认新速度限制"), tr("在手动确认之前,不要自动开始使用新的速度限制。"), ""},
{"ForceMPHDashboard", tr("强制从仪表盘读取MPH"), tr("强制从仪表盘读取MPH。仅在您居住的地区仪表盘的速度限制为KPH但您使用MPH时使用此功能。"), ""},
{"SLCLookaheadHigher", tr("为更高的速度限制做准备"), tr("设置一个'前瞻'值,以准备即将到来的高于您当前速度限制的速度限制,使用存储在'开放街道地图'中的数据。"), ""},
{"SLCLookaheadLower", tr("为更低的速度限制做准备"), tr("设置一个'前瞻'值,以准备即将到来的低于您当前速度限制的速度限制,使用存储在'开放街道地图'中的数据。"), ""},
{"SetSpeedLimit", tr("将当前速度限制用作设定速度"), tr("如果在您最初启用openpilot时有一个速度限制则将您的最大速度设置为当前速度限制。"), ""},
{"SLCVisuals", tr("视觉设置"), tr("管理与'速度限制控制器'的视觉相关的切换。"), ""},
{"ShowSLCOffset", tr("显示速度限制偏移"), tr("在使用'速度限制控制器'时在onroad UI中显示与速度限制分开的速度限制偏移。"), ""},
{"SpeedLimitChangedAlert", tr("速度限制变更警报"), tr("每当速度限制变化时触发警报。"), ""},
{"UseVienna", tr("使用维也纳速度限制标志"), tr("使用维也纳欧盟速度限制样式标志而不是MUTCD美国"), ""},
{"VisionTurnControl", tr("视觉转向速度控制器"), tr("在检测到道路曲线时减速。"), "../frogpilot/assets/toggle_icons/icon_vtc.png"},
{"DisableVTSCSmoothing", tr("禁用VTSC UI平滑"), tr("禁用onroad UI中请求速度的平滑。"), ""},
{"CurveSensitivity", tr("曲线检测灵敏度"), tr("设置曲线检测灵敏度。更高的值会促使更早的响应,较低的值会导致更平滑但较晚的反应。"), ""},
{"TurnAggressiveness", tr("转向速度攻击性"), tr("设置转向速度的攻击性。更高的值会导致更快的转弯,较低的值会导致更温和的转弯。"), ""},
2024-05-09 19:49:07 -07:00
};
for (const auto &[param, title, desc, icon] : controlToggles) {
AbstractControl *toggle;
if (param == "AlwaysOnLateral") {
FrogPilotParamManageControl *aolToggle = new FrogPilotParamManageControl(param, title, desc, icon, this);
QObject::connect(aolToggle, &FrogPilotParamManageControl::manageButtonClicked, this, [this]() {
openParentToggle();
for (auto &[key, toggle] : toggles) {
toggle->setVisible(aolKeys.find(key.c_str()) != aolKeys.end());
}
});
toggle = aolToggle;
} else if (param == "PauseAOLOnBrake") {
toggle = new FrogPilotParamValueControl(param, title, desc, icon, 0, 99, std::map<int, QString>(), this, false, tr(" mph"));
} else if (param == "ConditionalExperimental") {
FrogPilotParamManageControl *conditionalExperimentalToggle = new FrogPilotParamManageControl(param, title, desc, icon, this);
QObject::connect(conditionalExperimentalToggle, &FrogPilotParamManageControl::manageButtonClicked, this, [this]() {
openParentToggle();
conditionalSpeedsImperial->setVisible(!isMetric);
conditionalSpeedsMetric->setVisible(isMetric);
for (auto &[key, toggle] : toggles) {
toggle->setVisible(conditionalExperimentalKeys.find(key.c_str()) != conditionalExperimentalKeys.end());
}
});
toggle = conditionalExperimentalToggle;
} else if (param == "CECurves") {
FrogPilotParamValueControl *CESpeedImperial = new FrogPilotParamValueControl("CESpeed", tr("Below"), tr("Switch to 'Experimental Mode' below this speed when not following a lead vehicle."), "", 0, 99,
std::map<int, QString>(), this, false, tr(" mph"));
FrogPilotParamValueControl *CESpeedLeadImperial = new FrogPilotParamValueControl("CESpeedLead", tr(" w/Lead"), tr("Switch to 'Experimental Mode' below this speed when following a lead vehicle."), "", 0, 99,
std::map<int, QString>(), this, false, tr(" mph"));
conditionalSpeedsImperial = new FrogPilotDualParamControl(CESpeedImperial, CESpeedLeadImperial, this);
addItem(conditionalSpeedsImperial);
FrogPilotParamValueControl *CESpeedMetric = new FrogPilotParamValueControl("CESpeed", tr("Below"), tr("Switch to 'Experimental Mode' below this speed in absence of a lead vehicle."), "", 0, 150,
std::map<int, QString>(), this, false, tr(" kph"));
FrogPilotParamValueControl *CESpeedLeadMetric = new FrogPilotParamValueControl("CESpeedLead", tr(" w/Lead"), tr("Switch to 'Experimental Mode' below this speed when following a lead vehicle."), "", 0, 150,
std::map<int, QString>(), this, false, tr(" kph"));
conditionalSpeedsMetric = new FrogPilotDualParamControl(CESpeedMetric, CESpeedLeadMetric, this);
addItem(conditionalSpeedsMetric);
std::vector<QString> curveToggles{"CECurvesLead"};
std::vector<QString> curveToggleNames{tr("With Lead")};
toggle = new FrogPilotParamToggleControl(param, title, desc, icon, curveToggles, curveToggleNames);
} else if (param == "CENavigation") {
std::vector<QString> navigationToggles{"CENavigationIntersections", "CENavigationTurns", "CENavigationLead"};
std::vector<QString> navigationToggleNames{tr("Intersections"), tr("Turns"), tr("With Lead")};
toggle = new FrogPilotParamToggleControl(param, title, desc, icon, navigationToggles, navigationToggleNames);
} else if (param == "CEStopLights") {
std::vector<QString> stopLightToggles{"CEStopLightsLead"};
std::vector<QString> stopLightToggleNames{tr("With Lead")};
toggle = new FrogPilotParamToggleControl(param, title, desc, icon, stopLightToggles, stopLightToggleNames);
} else if (param == "DeviceManagement") {
FrogPilotParamManageControl *deviceManagementToggle = new FrogPilotParamManageControl(param, title, desc, icon, this);
QObject::connect(deviceManagementToggle, &FrogPilotParamManageControl::manageButtonClicked, this, [this]() {
openParentToggle();
for (auto &[key, toggle] : toggles) {
toggle->setVisible(deviceManagementKeys.find(key.c_str()) != deviceManagementKeys.end());
}
});
toggle = deviceManagementToggle;
} else if (param == "DeviceShutdown") {
std::map<int, QString> shutdownLabels;
for (int i = 0; i <= 33; ++i) {
shutdownLabels[i] = i == 0 ? tr("5 mins") : i <= 3 ? QString::number(i * 15) + tr(" mins") : QString::number(i - 3) + (i == 4 ? tr(" hour") : tr(" hours"));
}
toggle = new FrogPilotParamValueControl(param, title, desc, icon, 0, 33, shutdownLabels, this, false);
} else if (param == "NoUploads") {
std::vector<QString> uploadsToggles{"DisableOnroadUploads"};
std::vector<QString> uploadsToggleNames{tr("Only Onroad")};
toggle = new FrogPilotParamToggleControl(param, title, desc, icon, uploadsToggles, uploadsToggleNames);
} else if (param == "LowVoltageShutdown") {
toggle = new FrogPilotParamValueControl(param, title, desc, icon, 11.8, 12.5, std::map<int, QString>(), this, false, tr(" volts"), 1, 0.01);
} else if (param == "DrivingPersonalities") {
FrogPilotParamManageControl *drivingPersonalitiesToggle = new FrogPilotParamManageControl(param, title, desc, icon, this);
QObject::connect(drivingPersonalitiesToggle, &FrogPilotParamManageControl::manageButtonClicked, this, [this]() {
openParentToggle();
for (auto &[key, toggle] : toggles) {
toggle->setVisible(drivingPersonalityKeys.find(key.c_str()) != drivingPersonalityKeys.end());
}
});
toggle = drivingPersonalitiesToggle;
} else if (param == "CustomPersonalities") {
FrogPilotParamManageControl *customPersonalitiesToggle = new FrogPilotParamManageControl(param, title, desc, icon, this);
QObject::connect(customPersonalitiesToggle, &FrogPilotParamManageControl::manageButtonClicked, this, [this]() {
customPersonalitiesOpen = true;
for (auto &[key, toggle] : toggles) {
toggle->setVisible(customdrivingPersonalityKeys.find(key.c_str()) != customdrivingPersonalityKeys.end());
openSubParentToggle();
}
});
personalitiesInfoBtn = new ButtonControl(tr("What Do All These Do?"), tr("VIEW"), tr("Learn what all the values in 'Custom Personality Profiles' do on openpilot's driving behaviors."));
connect(personalitiesInfoBtn, &ButtonControl::clicked, [=]() {
const std::string txt = util::read_file("../frogpilot/ui/qt/offroad/personalities_info.txt");
ConfirmationDialog::rich(QString::fromStdString(txt), this);
});
addItem(personalitiesInfoBtn);
toggle = customPersonalitiesToggle;
} else if (param == "ResetTrafficPersonality" || param == "ResetAggressivePersonality" || param == "ResetStandardPersonality" || param == "ResetRelaxedPersonality") {
std::vector<QString> personalityOptions{tr("Reset")};
FrogPilotButtonsControl *profileBtn = new FrogPilotButtonsControl(title, desc, icon, personalityOptions);
toggle = profileBtn;
} else if (param == "TrafficPersonalityProfile") {
FrogPilotParamManageControl *trafficPersonalityToggle = new FrogPilotParamManageControl(param, title, desc, icon, this);
QObject::connect(trafficPersonalityToggle, &FrogPilotParamManageControl::manageButtonClicked, this, [this]() {
for (auto &[key, toggle] : toggles) {
toggle->setVisible(trafficPersonalityKeys.find(key.c_str()) != trafficPersonalityKeys.end());
}
openSubSubParentToggle();
personalitiesInfoBtn->setVisible(true);
});
toggle = trafficPersonalityToggle;
} else if (param == "AggressivePersonalityProfile") {
FrogPilotParamManageControl *aggressivePersonalityToggle = new FrogPilotParamManageControl(param, title, desc, icon, this);
QObject::connect(aggressivePersonalityToggle, &FrogPilotParamManageControl::manageButtonClicked, this, [this]() {
for (auto &[key, toggle] : toggles) {
toggle->setVisible(aggressivePersonalityKeys.find(key.c_str()) != aggressivePersonalityKeys.end());
}
openSubSubParentToggle();
personalitiesInfoBtn->setVisible(true);
});
toggle = aggressivePersonalityToggle;
} else if (param == "StandardPersonalityProfile") {
FrogPilotParamManageControl *standardPersonalityToggle = new FrogPilotParamManageControl(param, title, desc, icon, this);
QObject::connect(standardPersonalityToggle, &FrogPilotParamManageControl::manageButtonClicked, this, [this]() {
for (auto &[key, toggle] : toggles) {
toggle->setVisible(standardPersonalityKeys.find(key.c_str()) != standardPersonalityKeys.end());
}
openSubSubParentToggle();
personalitiesInfoBtn->setVisible(true);
});
toggle = standardPersonalityToggle;
} else if (param == "RelaxedPersonalityProfile") {
FrogPilotParamManageControl *relaxedPersonalityToggle = new FrogPilotParamManageControl(param, title, desc, icon, this);
QObject::connect(relaxedPersonalityToggle, &FrogPilotParamManageControl::manageButtonClicked, this, [this]() {
for (auto &[key, toggle] : toggles) {
toggle->setVisible(relaxedPersonalityKeys.find(key.c_str()) != relaxedPersonalityKeys.end());
}
openSubSubParentToggle();
personalitiesInfoBtn->setVisible(true);
});
toggle = relaxedPersonalityToggle;
} else if (trafficPersonalityKeys.find(param) != trafficPersonalityKeys.end() ||
aggressivePersonalityKeys.find(param) != aggressivePersonalityKeys.end() ||
standardPersonalityKeys.find(param) != standardPersonalityKeys.end() ||
relaxedPersonalityKeys.find(param) != relaxedPersonalityKeys.end()) {
if (param == "TrafficFollow" || param == "AggressiveFollow" || param == "StandardFollow" || param == "RelaxedFollow") {
if (param == "TrafficFollow") {
toggle = new FrogPilotParamValueControl(param, title, desc, icon, 0.5, 5, std::map<int, QString>(), this, false, tr(" seconds"), 1, 0.01);
} else {
toggle = new FrogPilotParamValueControl(param, title, desc, icon, 1, 5, std::map<int, QString>(), this, false, tr(" seconds"), 1, 0.01);
}
} else {
toggle = new FrogPilotParamValueControl(param, title, desc, icon, 1, 500, std::map<int, QString>(), this, false, "%");
}
} else if (param == "OnroadDistanceButton") {
std::vector<QString> onroadDistanceToggles{"KaofuiIcons"};
std::vector<QString> onroadDistanceToggleNames{tr("Kaofui's Icons")};
toggle = new FrogPilotParamToggleControl(param, title, desc, icon, onroadDistanceToggles, onroadDistanceToggleNames);
} else if (param == "ExperimentalModeActivation") {
FrogPilotParamManageControl *experimentalModeActivationToggle = new FrogPilotParamManageControl(param, title, desc, icon, this);
QObject::connect(experimentalModeActivationToggle, &FrogPilotParamManageControl::manageButtonClicked, this, [this]() {
openParentToggle();
for (auto &[key, toggle] : toggles) {
toggle->setVisible(experimentalModeActivationKeys.find(key.c_str()) != experimentalModeActivationKeys.end());
}
});
toggle = experimentalModeActivationToggle;
} else if (param == "LateralTune") {
FrogPilotParamManageControl *lateralTuneToggle = new FrogPilotParamManageControl(param, title, desc, icon, this);
QObject::connect(lateralTuneToggle, &FrogPilotParamManageControl::manageButtonClicked, this, [this]() {
openParentToggle();
for (auto &[key, toggle] : toggles) {
std::set<QString> modifiedLateralTuneKeys = lateralTuneKeys;
if (hasAutoTune || params.getBool("LateralTune") && params.getBool("NNFF")) {
modifiedLateralTuneKeys.erase("ForceAutoTune");
}
if (hasCommaNNFFSupport) {
modifiedLateralTuneKeys.erase("NNFF");
modifiedLateralTuneKeys.erase("NNFFLite");
} else if (hasNNFFLog) {
modifiedLateralTuneKeys.erase("NNFFLite");
} else {
modifiedLateralTuneKeys.erase("NNFF");
}
toggle->setVisible(modifiedLateralTuneKeys.find(key.c_str()) != modifiedLateralTuneKeys.end());
}
});
toggle = lateralTuneToggle;
} else if (param == "SteerRatio") {
std::vector<QString> steerRatioToggles{"ResetSteerRatio"};
std::vector<QString> steerRatioToggleNames{"Reset"};
toggle = new FrogPilotParamValueToggleControl(param, title, desc, icon, steerRatioStock * 0.75, steerRatioStock * 1.25, std::map<int, QString>(), this, false, "", 1, 0.01, steerRatioToggles, steerRatioToggleNames);
} else if (param == "LongitudinalTune") {
FrogPilotParamManageControl *longitudinalTuneToggle = new FrogPilotParamManageControl(param, title, desc, icon, this);
QObject::connect(longitudinalTuneToggle, &FrogPilotParamManageControl::manageButtonClicked, this, [this]() {
openParentToggle();
for (auto &[key, toggle] : toggles) {
std::set<QString> modifiedLongitudinalTuneKeys = longitudinalTuneKeys;
if (params.get("Model") == "radical-turtle") {
modifiedLongitudinalTuneKeys.erase("LeadDetectionThreshold");
}
toggle->setVisible(modifiedLongitudinalTuneKeys.find(key.c_str()) != modifiedLongitudinalTuneKeys.end());
}
});
toggle = longitudinalTuneToggle;
} else if (param == "AccelerationProfile") {
std::vector<QString> profileOptions{tr("Standard"), tr("Eco"), tr("Sport"), tr("Sport+")};
FrogPilotButtonParamControl *profileSelection = new FrogPilotButtonParamControl(param, title, desc, icon, profileOptions);
toggle = profileSelection;
QObject::connect(static_cast<FrogPilotButtonParamControl*>(toggle), &FrogPilotButtonParamControl::buttonClicked, [this](int id) {
if (id == 3) {
FrogPilotConfirmationDialog::toggleAlert(tr("WARNING: This maxes out openpilot's acceleration from 2.0 m/s to 4.0 m/s and may cause oscillations when accelerating!"),
tr("I understand the risks."), this);
}
});
} else if (param == "AggressiveAcceleration") {
std::vector<QString> accelerationToggles{"AggressiveAccelerationExperimental"};
std::vector<QString> accelerationToggleNames{tr("Experimental")};
toggle = new FrogPilotParamToggleControl(param, title, desc, icon, accelerationToggles, accelerationToggleNames);
QObject::connect(static_cast<FrogPilotParamToggleControl*>(toggle), &FrogPilotParamToggleControl::buttonClicked, [this](bool checked) {
if (checked) {
FrogPilotConfirmationDialog::toggleAlert(
tr("WARNING: This is very experimental and may cause the car to not brake or stop safely! Please report any issues in the FrogPilot Discord!"),
tr("I understand the risks."), this);
}
});
} else if (param == "DecelerationProfile") {
std::vector<QString> profileOptions{tr("Standard"), tr("Eco"), tr("Sport")};
FrogPilotButtonParamControl *profileSelection = new FrogPilotButtonParamControl(param, title, desc, icon, profileOptions);
toggle = profileSelection;
} else if (param == "StoppingDistance") {
toggle = new FrogPilotParamValueControl(param, title, desc, icon, 0, 10, std::map<int, QString>(), this, false, tr(" feet"));
} else if (param == "LeadDetectionThreshold") {
toggle = new FrogPilotParamValueControl(param, title, desc, icon, 1, 99, std::map<int, QString>(), this, false, "%");
} else if (param == "SmoothBraking") {
std::vector<QString> brakingToggles{"SmoothBrakingJerk", "SmoothBrakingFarLead"};
std::vector<QString> brakingToggleNames{tr("Apply to Jerk"), tr("Far Lead Offset")};
toggle = new FrogPilotParamToggleControl(param, title, desc, icon, brakingToggles, brakingToggleNames);
QObject::connect(static_cast<FrogPilotParamToggleControl*>(toggle), &FrogPilotParamToggleControl::buttonClicked, [this](bool checked) {
if (checked) {
FrogPilotConfirmationDialog::toggleAlert(
tr("WARNING: This is very experimental and may cause the car to not brake or stop safely! Please report any issues in the FrogPilot Discord!"),
tr("I understand the risks."), this);
}
});
} else if (param == "MTSCEnabled") {
FrogPilotParamManageControl *mtscToggle = new FrogPilotParamManageControl(param, title, desc, icon, this);
QObject::connect(mtscToggle, &FrogPilotParamManageControl::manageButtonClicked, this, [this]() {
openParentToggle();
for (auto &[key, toggle] : toggles) {
toggle->setVisible(mtscKeys.find(key.c_str()) != mtscKeys.end());
}
});
toggle = mtscToggle;
} else if (param == "MTSCAggressiveness") {
toggle = new FrogPilotParamValueControl(param, title, desc, icon, 1, 200, std::map<int, QString>(), this, false, "%");
} else if (param == "ModelSelector") {
FrogPilotParamManageControl *modelsToggle = new FrogPilotParamManageControl(param, title, desc, icon, this);
QObject::connect(modelsToggle, &FrogPilotParamManageControl::manageButtonClicked, this, [this]() {
openParentToggle();
for (auto &[key, toggle] : toggles) {
toggle->setVisible(false);
}
deleteModelBtn->setVisible(true);
downloadModelBtn->setVisible(true);
selectModelBtn->setVisible(true);
});
toggle = modelsToggle;
QDir modelDir("/data/models/");
deleteModelBtn = new ButtonControl(tr("Delete Model"), tr("DELETE"), "");
QObject::connect(deleteModelBtn, &ButtonControl::clicked, [=]() {
std::string currentModel = params.get("Model") + ".thneed";
QStringList availableModels = QString::fromStdString(params.get("AvailableModels")).split(",");
QStringList modelLabels = QString::fromStdString(params.get("AvailableModelsNames")).split(",");
QStringList existingModelFiles = modelDir.entryList({"*.thneed"}, QDir::Files);
QMap<QString, QString> labelToFileMap;
QStringList deletableModelLabels;
for (int i = 0; i < availableModels.size(); ++i) {
QString modelFileName = availableModels[i] + ".thneed";
if (existingModelFiles.contains(modelFileName) && modelFileName != QString::fromStdString(currentModel)) {
QString readableName = modelLabels[i];
deletableModelLabels.append(readableName);
labelToFileMap[readableName] = modelFileName;
}
}
QString selectedModel = MultiOptionDialog::getSelection(tr("Select a model to delete"), deletableModelLabels, "", this);
if (!selectedModel.isEmpty() && ConfirmationDialog::confirm(tr("Are you sure you want to delete this model?"), tr("Delete"), this)) {
std::thread([=]() {
deleteModelBtn->setValue(tr("Deleting..."));
deleteModelBtn->setEnabled(false);
downloadModelBtn->setEnabled(false);
selectModelBtn->setEnabled(false);
QString modelToDelete = labelToFileMap[selectedModel];
QFile::remove(modelDir.absoluteFilePath(modelToDelete));
deleteModelBtn->setEnabled(true);
downloadModelBtn->setEnabled(true);
selectModelBtn->setEnabled(true);
deleteModelBtn->setValue(tr("Deleted!"));
std::this_thread::sleep_for(std::chrono::seconds(3));
deleteModelBtn->setValue("");
}).detach();
}
});
addItem(deleteModelBtn);
downloadModelBtn = new ButtonControl(tr("Download Model"), tr("DOWNLOAD"), "");
QObject::connect(downloadModelBtn, &ButtonControl::clicked, [=]() {
QStringList availableModels = QString::fromStdString(params.get("AvailableModels")).split(",");
QStringList modelLabels = QString::fromStdString(params.get("AvailableModelsNames")).split(",");
QMap<QString, QString> labelToModelMap;
QStringList downloadableModelLabels;
QStringList existingModelFiles = modelDir.entryList({"*.thneed"}, QDir::Files);
for (int i = 0; i < availableModels.size(); ++i) {
QString modelFileName = availableModels.at(i) + ".thneed";
if (!existingModelFiles.contains(modelFileName)) {
QString readableName = modelLabels.at(i);
if (!readableName.contains("(Default)")) {
downloadableModelLabels.append(readableName);
labelToModelMap.insert(readableName, availableModels.at(i));
}
}
}
QString modelToDownload = MultiOptionDialog::getSelection(tr("Select a driving model to download"), downloadableModelLabels, "", this);
if (!modelToDownload.isEmpty()) {
QString selectedModelValue = labelToModelMap.value(modelToDownload);
paramsMemory.put("ModelToDownload", selectedModelValue.toStdString());
deleteModelBtn->setEnabled(false);
downloadModelBtn->setEnabled(false);
selectModelBtn->setEnabled(false);
QTimer *failureTimer = new QTimer(this);
failureTimer->setSingleShot(true);
QTimer *progressTimer = new QTimer(this);
progressTimer->setInterval(100);
connect(failureTimer, &QTimer::timeout, this, [=]() {
deleteModelBtn->setEnabled(true);
downloadModelBtn->setEnabled(true);
selectModelBtn->setEnabled(true);
downloadModelBtn->setValue(tr("Download failed..."));
paramsMemory.remove("ModelDownloadProgress");
paramsMemory.remove("ModelToDownload");
progressTimer->stop();
progressTimer->deleteLater();
QTimer::singleShot(3000, this, [this]() {
downloadModelBtn->setValue("");
});
});
connect(progressTimer, &QTimer::timeout, this, [=]() mutable {
static int lastProgress = -1;
int progress = paramsMemory.getInt("ModelDownloadProgress");
if (progress == lastProgress) {
if (!failureTimer->isActive()) {
failureTimer->start(30000);
}
} else {
lastProgress = progress;
downloadModelBtn->setValue(QString::number(progress) + "%");
failureTimer->stop();
if (progress == 100) {
deleteModelBtn->setEnabled(true);
downloadModelBtn->setEnabled(true);
selectModelBtn->setEnabled(true);
downloadModelBtn->setValue(tr("Downloaded!"));
paramsMemory.remove("ModelDownloadProgress");
paramsMemory.remove("ModelToDownload");
progressTimer->stop();
progressTimer->deleteLater();
QTimer::singleShot(3000, this, [this]() {
if (paramsMemory.get("ModelDownloadProgress").empty()) {
downloadModelBtn->setValue("");
}
});
}
}
});
progressTimer->start();
}
});
addItem(downloadModelBtn);
selectModelBtn = new ButtonControl(tr("Select Model"), tr("SELECT"), "");
QObject::connect(selectModelBtn, &ButtonControl::clicked, [=]() {
QStringList availableModels = QString::fromStdString(params.get("AvailableModels")).split(",");
QStringList modelLabels = QString::fromStdString(params.get("AvailableModelsNames")).split(",");
QStringList modelFiles = modelDir.entryList({"*.thneed"}, QDir::Files);
QSet<QString> modelFilesBaseNames;
for (const QString &modelFile : modelFiles) {
modelFilesBaseNames.insert(modelFile.section('.', 0, 0));
}
QStringList selectableModelLabels;
for (int i = 0; i < availableModels.size(); ++i) {
if (modelFilesBaseNames.contains(availableModels[i]) || modelLabels[i].contains("(Default)")) {
selectableModelLabels.append(modelLabels[i]);
}
}
QString modelToSelect = MultiOptionDialog::getSelection(tr("Select a model - 🗺️ = Navigation | 📡 = Radar | 👀 = VOACC"), selectableModelLabels, "", this);
if (!modelToSelect.isEmpty()) {
selectModelBtn->setValue(modelToSelect);
int modelIndex = modelLabels.indexOf(modelToSelect);
if (modelIndex != -1) {
QString selectedModel = availableModels.at(modelIndex);
params.putNonBlocking("Model", selectedModel.toStdString());
params.putNonBlocking("ModelName", modelToSelect.toStdString());
}
if (FrogPilotConfirmationDialog::yesorno(tr("Do you want to start with a fresh calibration for the newly selected model?"), this)) {
params.remove("CalibrationParams");
params.remove("LiveTorqueParameters");
}
if (started) {
if (FrogPilotConfirmationDialog::toggle(tr("Reboot required to take effect."), tr("Reboot Now"), this)) {
Hardware::reboot();
}
}
}
});
addItem(selectModelBtn);
selectModelBtn->setValue(QString::fromStdString(params.get("ModelName")));
} else if (param == "QOLControls") {
FrogPilotParamManageControl *qolToggle = new FrogPilotParamManageControl(param, title, desc, icon, this);
QObject::connect(qolToggle, &FrogPilotParamManageControl::manageButtonClicked, this, [this]() {
openParentToggle();
for (auto &[key, toggle] : toggles) {
std::set<QString> modifiedQolKeys = qolKeys;
if (!hasPCMCruise) {
modifiedQolKeys.erase("ReverseCruise");
} else {
modifiedQolKeys.erase("CustomCruise");
modifiedQolKeys.erase("CustomCruiseLong");
modifiedQolKeys.erase("SetSpeedOffset");
}
if (!isToyota && !isGM && !isHKGCanFd) {
modifiedQolKeys.erase("MapGears");
}
toggle->setVisible(modifiedQolKeys.find(key.c_str()) != modifiedQolKeys.end());
}
});
toggle = qolToggle;
} else if (param == "CustomCruise") {
toggle = new FrogPilotParamValueControl(param, title, desc, icon, 1, 99, std::map<int, QString>(), this, false, tr(" mph"));
} else if (param == "CustomCruiseLong") {
toggle = new FrogPilotParamValueControl(param, title, desc, icon, 1, 99, std::map<int, QString>(), this, false, tr(" mph"));
} else if (param == "MapGears") {
std::vector<QString> mapGearsToggles{"MapAcceleration", "MapDeceleration"};
std::vector<QString> mapGearsToggleNames{tr("Acceleration"), tr("Deceleration")};
toggle = new FrogPilotParamToggleControl(param, title, desc, icon, mapGearsToggles, mapGearsToggleNames);
} else if (param == "PauseLateralSpeed") {
std::vector<QString> pauseLateralToggles{"PauseLateralOnSignal"};
std::vector<QString> pauseLateralToggleNames{"Turn Signal Only"};
toggle = new FrogPilotParamValueToggleControl(param, title, desc, icon, 0, 99, std::map<int, QString>(), this, false, tr(" mph"), 1, 1, pauseLateralToggles, pauseLateralToggleNames);
} else if (param == "PauseLateralOnSignal") {
toggle = new FrogPilotParamValueControl(param, title, desc, icon, 0, 99, std::map<int, QString>(), this, false, tr(" mph"));
} else if (param == "ReverseCruise") {
std::vector<QString> reverseCruiseToggles{"ReverseCruiseUI"};
std::vector<QString> reverseCruiseNames{tr("Control Via UI")};
toggle = new FrogPilotParamToggleControl(param, title, desc, icon, reverseCruiseToggles, reverseCruiseNames);
} else if (param == "SetSpeedOffset") {
toggle = new FrogPilotParamValueControl(param, title, desc, icon, 0, 99, std::map<int, QString>(), this, false, tr(" mph"));
} else if (param == "LaneChangeCustomizations") {
FrogPilotParamManageControl *laneChangeToggle = new FrogPilotParamManageControl(param, title, desc, icon, this);
QObject::connect(laneChangeToggle, &FrogPilotParamManageControl::manageButtonClicked, this, [this]() {
openParentToggle();
for (auto &[key, toggle] : toggles) {
toggle->setVisible(laneChangeKeys.find(key.c_str()) != laneChangeKeys.end());
}
});
toggle = laneChangeToggle;
} else if (param == "MinimumLaneChangeSpeed") {
toggle = new FrogPilotParamValueControl(param, title, desc, icon, 0, 99, std::map<int, QString>(), this, false, tr(" mph"));
} else if (param == "LaneChangeTime") {
std::map<int, QString> laneChangeTimeLabels;
for (int i = 0; i <= 10; ++i) {
laneChangeTimeLabels[i] = i == 0 ? "Instant" : QString::number(i / 2.0) + " seconds";
}
toggle = new FrogPilotParamValueControl(param, title, desc, icon, 0, 10, laneChangeTimeLabels, this, false);
} else if (param == "LaneDetectionWidth") {
toggle = new FrogPilotParamValueControl(param, title, desc, icon, 0, 100, std::map<int, QString>(), this, false, " feet", 10);
} else if (param == "SpeedLimitController") {
FrogPilotParamManageControl *speedLimitControllerToggle = new FrogPilotParamManageControl(param, title, desc, icon, this);
QObject::connect(speedLimitControllerToggle, &FrogPilotParamManageControl::manageButtonClicked, this, [this]() {
slcOpen = true;
openParentToggle();
for (auto &[key, toggle] : toggles) {
toggle->setVisible(speedLimitControllerKeys.find(key.c_str()) != speedLimitControllerKeys.end());
}
});
toggle = speedLimitControllerToggle;
} else if (param == "SLCControls") {
FrogPilotParamManageControl *manageSLCControlsToggle = new FrogPilotParamManageControl(param, title, desc, icon, this, true);
QObject::connect(manageSLCControlsToggle, &FrogPilotParamManageControl::manageButtonClicked, this, [this]() {
for (auto &[key, toggle] : toggles) {
toggle->setVisible(speedLimitControllerControlsKeys.find(key.c_str()) != speedLimitControllerControlsKeys.end());
openSubParentToggle();
}
});
toggle = manageSLCControlsToggle;
} else if (param == "SLCQOL") {
FrogPilotParamManageControl *manageSLCQOLToggle = new FrogPilotParamManageControl(param, title, desc, icon, this, true);
QObject::connect(manageSLCQOLToggle, &FrogPilotParamManageControl::manageButtonClicked, this, [this]() {
for (auto &[key, toggle] : toggles) {
std::set<QString> modifiedSpeedLimitControllerQOLKeys = speedLimitControllerQOLKeys;
if (hasPCMCruise) {
modifiedSpeedLimitControllerQOLKeys.erase("SetSpeedLimit");
}
if (!isToyota) {
modifiedSpeedLimitControllerQOLKeys.erase("ForceMPHDashboard");
}
toggle->setVisible(modifiedSpeedLimitControllerQOLKeys.find(key.c_str()) != modifiedSpeedLimitControllerQOLKeys.end());
openSubParentToggle();
}
});
toggle = manageSLCQOLToggle;
} else if (param == "SLCConfirmation") {
std::vector<QString> slcConfirmationToggles{"SLCConfirmationLower", "SLCConfirmationHigher"};
std::vector<QString> slcConfirmationNames{tr("Lower Limits"), tr("Higher Limits")};
toggle = new FrogPilotParamToggleControl(param, title, desc, icon, slcConfirmationToggles, slcConfirmationNames);
} else if (param == "SLCLookaheadHigher" || param == "SLCLookaheadLower") {
toggle = new FrogPilotParamValueControl(param, title, desc, icon, 0, 60, std::map<int, QString>(), this, false, " seconds");
} else if (param == "SLCVisuals") {
FrogPilotParamManageControl *manageSLCVisualsToggle = new FrogPilotParamManageControl(param, title, desc, icon, this, true);
QObject::connect(manageSLCVisualsToggle, &FrogPilotParamManageControl::manageButtonClicked, this, [this]() {
for (auto &[key, toggle] : toggles) {
toggle->setVisible(speedLimitControllerVisualsKeys.find(key.c_str()) != speedLimitControllerVisualsKeys.end());
openSubParentToggle();
}
});
toggle = manageSLCVisualsToggle;
} else if (param == "Offset1" || param == "Offset2" || param == "Offset3" || param == "Offset4") {
toggle = new FrogPilotParamValueControl(param, title, desc, icon, -99, 99, std::map<int, QString>(), this, false, tr(" mph"));
} else if (param == "ShowSLCOffset") {
std::vector<QString> slcOffsetToggles{"ShowSLCOffsetUI"};
std::vector<QString> slcOffsetToggleNames{tr("Control Via UI")};
toggle = new FrogPilotParamToggleControl(param, title, desc, icon, slcOffsetToggles, slcOffsetToggleNames);
} else if (param == "SLCFallback") {
std::vector<QString> fallbackOptions{tr("Set Speed"), tr("Experimental Mode"), tr("Previous Limit")};
FrogPilotButtonParamControl *fallbackSelection = new FrogPilotButtonParamControl(param, title, desc, icon, fallbackOptions);
toggle = fallbackSelection;
} else if (param == "SLCOverride") {
std::vector<QString> overrideOptions{tr("None"), tr("Manual Set Speed"), tr("Set Speed")};
FrogPilotButtonParamControl *overrideSelection = new FrogPilotButtonParamControl(param, title, desc, icon, overrideOptions);
toggle = overrideSelection;
} else if (param == "SLCPriority") {
ButtonControl *slcPriorityButton = new ButtonControl(title, tr("SELECT"), desc);
QStringList primaryPriorities = {tr("None"), tr("Dashboard"), tr("Navigation"), tr("Offline Maps"), tr("Highest"), tr("Lowest")};
QStringList secondaryTertiaryPriorities = {tr("None"), tr("Dashboard"), tr("Navigation"), tr("Offline Maps")};
QStringList priorityPrompts = {tr("Select your primary priority"), tr("Select your secondary priority"), tr("Select your tertiary priority")};
QObject::connect(slcPriorityButton, &ButtonControl::clicked, [=]() {
QStringList selectedPriorities;
for (int i = 1; i <= 3; ++i) {
QStringList currentPriorities = (i == 1) ? primaryPriorities : secondaryTertiaryPriorities;
QStringList prioritiesToDisplay = currentPriorities;
for (const auto &selectedPriority : qAsConst(selectedPriorities)) {
prioritiesToDisplay.removeAll(selectedPriority);
}
if (!hasDashSpeedLimits) {
prioritiesToDisplay.removeAll(tr("Dashboard"));
}
if (prioritiesToDisplay.size() == 1 && prioritiesToDisplay.contains(tr("None"))) {
break;
}
QString priorityKey = QString("SLCPriority%1").arg(i);
QString selection = MultiOptionDialog::getSelection(priorityPrompts[i - 1], prioritiesToDisplay, "", this);
if (selection.isEmpty()) break;
params.putNonBlocking(priorityKey.toStdString(), selection.toStdString());
selectedPriorities.append(selection);
if (selection == tr("Lowest") || selection == tr("Highest") || selection == tr("None")) break;
updateFrogPilotToggles();
}
selectedPriorities.removeAll(tr("None"));
slcPriorityButton->setValue(selectedPriorities.join(", "));
});
QStringList initialPriorities;
for (int i = 1; i <= 3; ++i) {
QString priorityKey = QString("SLCPriority%1").arg(i);
QString priority = QString::fromStdString(params.get(priorityKey.toStdString()));
if (!priority.isEmpty() && primaryPriorities.contains(priority) && priority != tr("None")) {
initialPriorities.append(priority);
}
}
slcPriorityButton->setValue(initialPriorities.join(", "));
toggle = slcPriorityButton;
} else if (param == "VisionTurnControl") {
FrogPilotParamManageControl *visionTurnControlToggle = new FrogPilotParamManageControl(param, title, desc, icon, this);
QObject::connect(visionTurnControlToggle, &FrogPilotParamManageControl::manageButtonClicked, this, [this]() {
openParentToggle();
for (auto &[key, toggle] : toggles) {
toggle->setVisible(visionTurnControlKeys.find(key.c_str()) != visionTurnControlKeys.end());
}
});
toggle = visionTurnControlToggle;
} else if (param == "CurveSensitivity" || param == "TurnAggressiveness") {
toggle = new FrogPilotParamValueControl(param, title, desc, icon, 1, 200, std::map<int, QString>(), this, false, "%");
} else {
toggle = new ParamControl(param, title, desc, icon, this);
}
addItem(toggle);
toggles[param.toStdString()] = toggle;
QObject::connect(static_cast<ToggleControl*>(toggle), &ToggleControl::toggleFlipped, &updateFrogPilotToggles);
QObject::connect(static_cast<FrogPilotParamValueControl*>(toggle), &FrogPilotParamValueControl::valueChanged, &updateFrogPilotToggles);
ParamWatcher *param_watcher = new ParamWatcher(this);
param_watcher->addParam("CESpeed");
param_watcher->addParam("CESpeedLead");
QObject::connect(param_watcher, &ParamWatcher::paramChanged, [=](const QString &param_name, const QString &param_value) {
updateFrogPilotToggles();
});
QObject::connect(toggle, &AbstractControl::showDescriptionEvent, [this]() {
update();
});
QObject::connect(static_cast<FrogPilotParamManageControl*>(toggle), &FrogPilotParamManageControl::manageButtonClicked, this, [this]() {
update();
});
}
QObject::connect(static_cast<ToggleControl*>(toggles["IncreaseThermalLimits"]), &ToggleControl::toggleFlipped, [this]() {
if (params.getBool("IncreaseThermalLimits")) {
FrogPilotConfirmationDialog::toggleAlert(
tr("WARNING: This can cause premature wear or damage by running the device over comma's recommended temperature limits!"),
tr("I understand the risks."), this);
}
});
QObject::connect(static_cast<ToggleControl*>(toggles["NoLogging"]), &ToggleControl::toggleFlipped, [this]() {
if (params.getBool("NoLogging")) {
FrogPilotConfirmationDialog::toggleAlert(
tr("WARNING: This will prevent your drives from being recorded and the data will be unobtainable!"),
tr("I understand the risks."), this);
}
});
QObject::connect(static_cast<ToggleControl*>(toggles["NoUploads"]), &ToggleControl::toggleFlipped, [this]() {
if (params.getBool("NoUploads")) {
FrogPilotConfirmationDialog::toggleAlert(
tr("WARNING: This will prevent your drives from appearing on comma connect which may impact debugging and support!"),
tr("I understand the risks."), this);
}
});
QObject::connect(static_cast<ToggleControl*>(toggles["TrafficMode"]), &ToggleControl::toggleFlipped, [this]() {
if (params.getBool("TrafficMode")) {
FrogPilotConfirmationDialog::toggleAlert(
tr("To activate 'Traffic Mode' you hold down the 'distance' button on your steering wheel for 2.5 seconds."),
tr("Sounds good!"), this);
}
});
std::set<QString> rebootKeys = {"AlwaysOnLateral", "NNFF", "NNFFLite"};
for (const QString &key : rebootKeys) {
QObject::connect(static_cast<ToggleControl*>(toggles[key.toStdString().c_str()]), &ToggleControl::toggleFlipped, [this]() {
if (started) {
if (FrogPilotConfirmationDialog::toggle(tr("Reboot required to take effect."), tr("Reboot Now"), this)) {
Hardware::reboot();
}
}
});
}
FrogPilotParamValueControl *trafficFollowToggle = static_cast<FrogPilotParamValueControl*>(toggles["TrafficFollow"]);
FrogPilotParamValueControl *trafficAccelerationoggle = static_cast<FrogPilotParamValueControl*>(toggles["TrafficJerkAcceleration"]);
FrogPilotParamValueControl *trafficSpeedToggle = static_cast<FrogPilotParamValueControl*>(toggles["TrafficJerkSpeed"]);
FrogPilotButtonsControl *trafficResetButton = static_cast<FrogPilotButtonsControl*>(toggles["ResetTrafficPersonality"]);
QObject::connect(trafficResetButton, &FrogPilotButtonsControl::buttonClicked, this, [=]() {
if (FrogPilotConfirmationDialog::yesorno(tr("Are you sure you want to completely reset your settings for the 'Traffic Mode' personality?"), this)) {
params.putFloat("TrafficFollow", 0.5);
params.putFloat("TrafficJerkAcceleration", 50);
params.putFloat("TrafficJerkSpeed", 75);
trafficFollowToggle->refresh();
trafficAccelerationoggle->refresh();
trafficSpeedToggle->refresh();
updateFrogPilotToggles();
}
});
FrogPilotParamValueControl *aggressiveFollowToggle = static_cast<FrogPilotParamValueControl*>(toggles["AggressiveFollow"]);
FrogPilotParamValueControl *aggressiveAccelerationoggle = static_cast<FrogPilotParamValueControl*>(toggles["AggressiveJerkAcceleration"]);
FrogPilotParamValueControl *aggressiveSpeedToggle = static_cast<FrogPilotParamValueControl*>(toggles["AggressiveJerkSpeed"]);
FrogPilotButtonsControl *aggressiveResetButton = static_cast<FrogPilotButtonsControl*>(toggles["ResetAggressivePersonality"]);
QObject::connect(aggressiveResetButton, &FrogPilotButtonsControl::buttonClicked, this, [=]() {
if (FrogPilotConfirmationDialog::yesorno(tr("Are you sure you want to completely reset your settings for the 'Aggressive' personality?"), this)) {
params.putFloat("AggressiveFollow", 1.25);
params.putFloat("AggressiveJerkAcceleration", 50);
params.putFloat("AggressiveJerkSpeed", 50);
aggressiveFollowToggle->refresh();
aggressiveAccelerationoggle->refresh();
aggressiveSpeedToggle->refresh();
updateFrogPilotToggles();
}
});
FrogPilotParamValueControl *standardFollowToggle = static_cast<FrogPilotParamValueControl*>(toggles["StandardFollow"]);
FrogPilotParamValueControl *standardAccelerationoggle = static_cast<FrogPilotParamValueControl*>(toggles["StandardJerkAcceleration"]);
FrogPilotParamValueControl *standardSpeedToggle = static_cast<FrogPilotParamValueControl*>(toggles["StandardJerkSpeed"]);
FrogPilotButtonsControl *standardResetButton = static_cast<FrogPilotButtonsControl*>(toggles["ResetStandardPersonality"]);
QObject::connect(standardResetButton, &FrogPilotButtonsControl::buttonClicked, this, [=]() {
if (FrogPilotConfirmationDialog::yesorno(tr("Are you sure you want to completely reset your settings for the 'Standard' personality?"), this)) {
params.putFloat("StandardFollow", 1.45);
params.putFloat("StandardJerkAcceleration", 100);
params.putFloat("StandardJerkSpeed", 100);
standardFollowToggle->refresh();
standardAccelerationoggle->refresh();
standardSpeedToggle->refresh();
updateFrogPilotToggles();
}
});
FrogPilotParamValueControl *relaxedFollowToggle = static_cast<FrogPilotParamValueControl*>(toggles["RelaxedFollow"]);
FrogPilotParamValueControl *relaxedAccelerationoggle = static_cast<FrogPilotParamValueControl*>(toggles["RelaxedJerkAcceleration"]);
FrogPilotParamValueControl *relaxedSpeedToggle = static_cast<FrogPilotParamValueControl*>(toggles["RelaxedJerkSpeed"]);
FrogPilotButtonsControl *relaxedResetButton = static_cast<FrogPilotButtonsControl*>(toggles["ResetRelaxedPersonality"]);
QObject::connect(relaxedResetButton, &FrogPilotButtonsControl::buttonClicked, this, [=]() {
if (FrogPilotConfirmationDialog::yesorno(tr("Are you sure you want to completely reset your settings for the 'Relaxed' personality?"), this)) {
params.putFloat("RelaxedFollow", 1.75);
params.putFloat("RelaxedJerkAcceleration", 100);
params.putFloat("RelaxedJerkSpeed", 100);
relaxedFollowToggle->refresh();
relaxedAccelerationoggle->refresh();
relaxedSpeedToggle->refresh();
updateFrogPilotToggles();
}
});
modelManagerToggle = static_cast<FrogPilotParamManageControl*>(toggles["ModelSelector"]);
steerRatioToggle = static_cast<FrogPilotParamValueToggleControl*>(toggles["SteerRatio"]);
QObject::connect(steerRatioToggle, &FrogPilotParamValueToggleControl::buttonClicked, this, [this]() {
params.putFloat("SteerRatio", steerRatioStock);
params.putBool("ResetSteerRatio", false);
steerRatioToggle->refresh();
updateFrogPilotToggles();
});
QObject::connect(parent, &SettingsWindow::closeParentToggle, this, &FrogPilotControlsPanel::hideToggles);
QObject::connect(parent, &SettingsWindow::closeSubParentToggle, this, &FrogPilotControlsPanel::hideSubToggles);
QObject::connect(parent, &SettingsWindow::closeSubSubParentToggle, this, &FrogPilotControlsPanel::hideSubSubToggles);
QObject::connect(parent, &SettingsWindow::updateMetric, this, &FrogPilotControlsPanel::updateMetric);
QObject::connect(uiState(), &UIState::offroadTransition, this, &FrogPilotControlsPanel::updateCarToggles);
QObject::connect(uiState(), &UIState::uiUpdate, this, &FrogPilotControlsPanel::updateState);
updateMetric();
}
void FrogPilotControlsPanel::showEvent(QShowEvent *event, const UIState &s) {
hasOpenpilotLongitudinal = hasOpenpilotLongitudinal && !params.getBool("DisableOpenpilotLongitudinal");
downloadModelBtn->setEnabled(s.scene.online);
}
void FrogPilotControlsPanel::updateState(const UIState &s) {
if (!isVisible()) return;
started = s.scene.started;
modelManagerToggle->setEnabled(!s.scene.started || s.scene.parked);
}
void FrogPilotControlsPanel::updateCarToggles() {
auto carParams = params.get("CarParamsPersistent");
if (!carParams.empty()) {
AlignedBuffer aligned_buf;
capnp::FlatArrayMessageReader cmsg(aligned_buf.align(carParams.data(), carParams.size()));
cereal::CarParams::Reader CP = cmsg.getRoot<cereal::CarParams>();
auto carFingerprint = CP.getCarFingerprint();
auto carName = CP.getCarName();
auto safetyConfigs = CP.getSafetyConfigs();
auto safetyModel = safetyConfigs[0].getSafetyModel();
hasAutoTune = (carName == "hyundai" || carName == "toyota") && CP.getLateralTuning().which() == cereal::CarParams::LateralTuning::TORQUE;
uiState()->scene.has_auto_tune = hasAutoTune;
hasCommaNNFFSupport = checkCommaNNFFSupport(carFingerprint);
hasDashSpeedLimits = carName == "hyundai" || carName == "toyota";
hasNNFFLog = checkNNFFLogFileExists(carFingerprint);
hasOpenpilotLongitudinal = (CP.getOpenpilotLongitudinalControl() && !params.getBool("DisableOpenpilotLongitudinal")) || params.getBool("CSLCEnabled");
hasPCMCruise = CP.getPcmCruise() && !params.getBool("CSLCEnabled");
2024-05-09 19:49:07 -07:00
isGM = carName == "gm";
isHKGCanFd = (carName == "hyundai") && (safetyModel == cereal::CarParams::SafetyModel::HYUNDAI_CANFD);
isToyota = carName == "toyota";
steerRatioStock = CP.getSteerRatio();
steerRatioToggle->setTitle(QString(tr("Steer Ratio (Default: %1)")).arg(QString::number(steerRatioStock, 'f', 2)));
steerRatioToggle->updateControl(steerRatioStock * 0.75, steerRatioStock * 1.25, "", 0.01);
steerRatioToggle->refresh();
} else {
hasAutoTune = false;
hasCommaNNFFSupport = false;
hasDashSpeedLimits = true;
hasNNFFLog = true;
hasOpenpilotLongitudinal = true;
hasPCMCruise = true;
isGM = true;
isHKGCanFd = true;
isToyota = true;
}
hideToggles();
}
void FrogPilotControlsPanel::updateMetric() {
bool previousIsMetric = isMetric;
isMetric = params.getBool("IsMetric");
if (isMetric != previousIsMetric) {
double distanceConversion = isMetric ? FOOT_TO_METER : METER_TO_FOOT;
double speedConversion = isMetric ? MILE_TO_KM : KM_TO_MILE;
params.putIntNonBlocking("CESpeed", std::nearbyint(params.getInt("CESpeed") * speedConversion));
params.putIntNonBlocking("CESpeedLead", std::nearbyint(params.getInt("CESpeedLead") * speedConversion));
params.putIntNonBlocking("CustomCruise", std::nearbyint(params.getInt("CustomCruise") * speedConversion));
params.putIntNonBlocking("CustomCruiseLong", std::nearbyint(params.getInt("CustomCruiseLong") * speedConversion));
params.putIntNonBlocking("LaneDetectionWidth", std::nearbyint(params.getInt("LaneDetectionWidth") * distanceConversion));
params.putIntNonBlocking("MinimumLaneChangeSpeed", std::nearbyint(params.getInt("MinimumLaneChangeSpeed") * speedConversion));
params.putIntNonBlocking("Offset1", std::nearbyint(params.getInt("Offset1") * speedConversion));
params.putIntNonBlocking("Offset2", std::nearbyint(params.getInt("Offset2") * speedConversion));
params.putIntNonBlocking("Offset3", std::nearbyint(params.getInt("Offset3") * speedConversion));
params.putIntNonBlocking("Offset4", std::nearbyint(params.getInt("Offset4") * speedConversion));
params.putIntNonBlocking("PauseAOLOnBrake", std::nearbyint(params.getInt("PauseAOLOnBrake") * speedConversion));
params.putIntNonBlocking("PauseLateralOnSignal", std::nearbyint(params.getInt("PauseLateralOnSignal") * speedConversion));
params.putIntNonBlocking("PauseLateralSpeed", std::nearbyint(params.getInt("PauseLateralSpeed") * speedConversion));
params.putIntNonBlocking("SetSpeedOffset", std::nearbyint(params.getInt("SetSpeedOffset") * speedConversion));
params.putIntNonBlocking("StoppingDistance", std::nearbyint(params.getInt("StoppingDistance") * distanceConversion));
}
FrogPilotParamValueControl *customCruiseToggle = static_cast<FrogPilotParamValueControl*>(toggles["CustomCruise"]);
FrogPilotParamValueControl *customCruiseLongToggle = static_cast<FrogPilotParamValueControl*>(toggles["CustomCruiseLong"]);
FrogPilotParamValueControl *laneWidthToggle = static_cast<FrogPilotParamValueControl*>(toggles["LaneDetectionWidth"]);
FrogPilotParamValueControl *minimumLaneChangeSpeedToggle = static_cast<FrogPilotParamValueControl*>(toggles["MinimumLaneChangeSpeed"]);
FrogPilotParamValueControl *offset1Toggle = static_cast<FrogPilotParamValueControl*>(toggles["Offset1"]);
FrogPilotParamValueControl *offset2Toggle = static_cast<FrogPilotParamValueControl*>(toggles["Offset2"]);
FrogPilotParamValueControl *offset3Toggle = static_cast<FrogPilotParamValueControl*>(toggles["Offset3"]);
FrogPilotParamValueControl *offset4Toggle = static_cast<FrogPilotParamValueControl*>(toggles["Offset4"]);
FrogPilotParamValueControl *pauseAOLOnBrakeToggle = static_cast<FrogPilotParamValueControl*>(toggles["PauseAOLOnBrake"]);
FrogPilotParamValueControl *pauseLateralToggle = static_cast<FrogPilotParamValueControl*>(toggles["PauseLateralSpeed"]);
FrogPilotParamValueControl *setSpeedOffsetToggle = static_cast<FrogPilotParamValueControl*>(toggles["SetSpeedOffset"]);
FrogPilotParamValueControl *stoppingDistanceToggle = static_cast<FrogPilotParamValueControl*>(toggles["StoppingDistance"]);
if (isMetric) {
offset1Toggle->setTitle(tr("Speed Limit Offset (0-34 kph)"));
offset2Toggle->setTitle(tr("Speed Limit Offset (35-54 kph)"));
offset3Toggle->setTitle(tr("Speed Limit Offset (55-64 kph)"));
offset4Toggle->setTitle(tr("Speed Limit Offset (65-99 kph)"));
offset1Toggle->setDescription(tr("Set speed limit offset for limits between 0-34 kph."));
offset2Toggle->setDescription(tr("Set speed limit offset for limits between 35-54 kph."));
offset3Toggle->setDescription(tr("Set speed limit offset for limits between 55-64 kph."));
offset4Toggle->setDescription(tr("Set speed limit offset for limits between 65-99 kph."));
customCruiseToggle->updateControl(1, 150, tr(" kph"));
customCruiseLongToggle->updateControl(1, 150, tr(" kph"));
minimumLaneChangeSpeedToggle->updateControl(0, 150, tr(" kph"));
offset1Toggle->updateControl(-99, 99, tr(" kph"));
offset2Toggle->updateControl(-99, 99, tr(" kph"));
offset3Toggle->updateControl(-99, 99, tr(" kph"));
offset4Toggle->updateControl(-99, 99, tr(" kph"));
pauseAOLOnBrakeToggle->updateControl(0, 99, tr(" kph"));
pauseLateralToggle->updateControl(0, 99, tr(" kph"));
setSpeedOffsetToggle->updateControl(0, 150, tr(" kph"));
laneWidthToggle->updateControl(0, 30, tr(" meters"), 10);
stoppingDistanceToggle->updateControl(0, 5, tr(" meters"));
} else {
offset1Toggle->setTitle(tr("Speed Limit Offset (0-34 mph)"));
offset2Toggle->setTitle(tr("Speed Limit Offset (35-54 mph)"));
offset3Toggle->setTitle(tr("Speed Limit Offset (55-64 mph)"));
offset4Toggle->setTitle(tr("Speed Limit Offset (65-99 mph)"));
offset1Toggle->setDescription(tr("Set speed limit offset for limits between 0-34 mph."));
offset2Toggle->setDescription(tr("Set speed limit offset for limits between 35-54 mph."));
offset3Toggle->setDescription(tr("Set speed limit offset for limits between 55-64 mph."));
offset4Toggle->setDescription(tr("Set speed limit offset for limits between 65-99 mph."));
customCruiseToggle->updateControl(1, 99, tr(" mph"));
customCruiseLongToggle->updateControl(1, 99, tr(" mph"));
minimumLaneChangeSpeedToggle->updateControl(0, 99, tr(" mph"));
offset1Toggle->updateControl(-99, 99, tr(" mph"));
offset2Toggle->updateControl(-99, 99, tr(" mph"));
offset3Toggle->updateControl(-99, 99, tr(" mph"));
offset4Toggle->updateControl(-99, 99, tr(" mph"));
pauseAOLOnBrakeToggle->updateControl(0, 99, tr(" mph"));
pauseLateralToggle->updateControl(0, 99, tr(" mph"));
setSpeedOffsetToggle->updateControl(0, 99, tr(" mph"));
laneWidthToggle->updateControl(0, 100, tr(" feet"), 10);
stoppingDistanceToggle->updateControl(0, 10, tr(" feet"));
}
customCruiseToggle->refresh();
customCruiseLongToggle->refresh();
laneWidthToggle->refresh();
minimumLaneChangeSpeedToggle->refresh();
offset1Toggle->refresh();
offset2Toggle->refresh();
offset3Toggle->refresh();
offset4Toggle->refresh();
pauseAOLOnBrakeToggle->refresh();
pauseLateralToggle->refresh();
setSpeedOffsetToggle->refresh();
stoppingDistanceToggle->refresh();
}
void FrogPilotControlsPanel::hideToggles() {
customPersonalitiesOpen = false;
slcOpen = false;
conditionalSpeedsImperial->setVisible(false);
conditionalSpeedsMetric->setVisible(false);
deleteModelBtn->setVisible(false);
downloadModelBtn->setVisible(false);
personalitiesInfoBtn->setVisible(false);
selectModelBtn->setVisible(false);
std::set<QString> longitudinalKeys = {"ConditionalExperimental", "DrivingPersonalities", "ExperimentalModeActivation",
"LongitudinalTune", "MTSCEnabled", "SpeedLimitController", "VisionTurnControl"};
for (auto &[key, toggle] : toggles) {
toggle->setVisible(false);
if (!hasOpenpilotLongitudinal && longitudinalKeys.find(key.c_str()) != longitudinalKeys.end()) {
continue;
}
bool subToggles = aggressivePersonalityKeys.find(key.c_str()) != aggressivePersonalityKeys.end() ||
aolKeys.find(key.c_str()) != aolKeys.end() ||
conditionalExperimentalKeys.find(key.c_str()) != conditionalExperimentalKeys.end() ||
customdrivingPersonalityKeys.find(key.c_str()) != customdrivingPersonalityKeys.end() ||
relaxedPersonalityKeys.find(key.c_str()) != relaxedPersonalityKeys.end() ||
deviceManagementKeys.find(key.c_str()) != deviceManagementKeys.end() ||
drivingPersonalityKeys.find(key.c_str()) != drivingPersonalityKeys.end() ||
experimentalModeActivationKeys.find(key.c_str()) != experimentalModeActivationKeys.end() ||
laneChangeKeys.find(key.c_str()) != laneChangeKeys.end() ||
lateralTuneKeys.find(key.c_str()) != lateralTuneKeys.end() ||
longitudinalTuneKeys.find(key.c_str()) != longitudinalTuneKeys.end() ||
mtscKeys.find(key.c_str()) != mtscKeys.end() ||
qolKeys.find(key.c_str()) != qolKeys.end() ||
relaxedPersonalityKeys.find(key.c_str()) != relaxedPersonalityKeys.end() ||
speedLimitControllerKeys.find(key.c_str()) != speedLimitControllerKeys.end() ||
speedLimitControllerControlsKeys.find(key.c_str()) != speedLimitControllerControlsKeys.end() ||
speedLimitControllerQOLKeys.find(key.c_str()) != speedLimitControllerQOLKeys.end() ||
speedLimitControllerVisualsKeys.find(key.c_str()) != speedLimitControllerVisualsKeys.end() ||
standardPersonalityKeys.find(key.c_str()) != standardPersonalityKeys.end() ||
relaxedPersonalityKeys.find(key.c_str()) != relaxedPersonalityKeys.end() ||
trafficPersonalityKeys.find(key.c_str()) != trafficPersonalityKeys.end() ||
tuningKeys.find(key.c_str()) != tuningKeys.end() ||
visionTurnControlKeys.find(key.c_str()) != visionTurnControlKeys.end();
toggle->setVisible(!subToggles);
}
update();
}
void FrogPilotControlsPanel::hideSubToggles() {
if (customPersonalitiesOpen) {
for (auto &[key, toggle] : toggles) {
bool isVisible = drivingPersonalityKeys.find(key.c_str()) != drivingPersonalityKeys.end();
toggle->setVisible(isVisible);
}
} else if (slcOpen) {
for (auto &[key, toggle] : toggles) {
bool isVisible = speedLimitControllerKeys.find(key.c_str()) != speedLimitControllerKeys.end();
toggle->setVisible(isVisible);
}
}
update();
}
void FrogPilotControlsPanel::hideSubSubToggles() {
personalitiesInfoBtn->setVisible(false);
for (auto &[key, toggle] : toggles) {
bool isVisible = customdrivingPersonalityKeys.find(key.c_str()) != customdrivingPersonalityKeys.end();
toggle->setVisible(isVisible);
}
update();
}