My username was friar carl

This commit is contained in:
firestar5683
2026-03-28 18:35:40 -05:00
parent 0f70d061e8
commit 58504c5a0f
41 changed files with 387 additions and 56 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -1,2 +1,2 @@
extern const uint8_t gitversion[19];
const uint8_t gitversion[19] = "DEV-82619bd7-DEBUG";
const uint8_t gitversion[19] = "DEV-277b2255-DEBUG";
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -1 +1 @@
DEV-82619bd7-DEBUG
DEV-277b2255-DEBUG
@@ -128,17 +128,38 @@ class ToggleTile(MetroTile):
class ValueTile(MetroTile):
def __init__(self, title: str, get_value: Callable[[], str], on_click: Callable, icon_path: str | None = None, bg_color: rl.Color | str | None = None):
def __init__(self, title: str, get_value: Callable[[], str], on_click: Callable, icon_path: str | None = None,
bg_color: rl.Color | str | None = None, is_enabled: Callable[[], bool] | None = None):
super().__init__(bg_color=bg_color, on_click=on_click)
self.title = title
self.get_value = get_value
self.is_enabled = is_enabled or (lambda: True)
self._icon = gui_app.starpilot_texture(icon_path, 80, 80) if icon_path else None
self._font = gui_app.font(FontWeight.BOLD)
self._active_color = self.bg_color
self._disabled_color = rl.Color(120, 120, 120, 255)
def _enabled(self) -> bool:
return self.is_enabled() if callable(self.is_enabled) else bool(self.is_enabled)
def _handle_mouse_press(self, mouse_pos: MousePos):
if not self._enabled():
self._is_pressed = False
return
super()._handle_mouse_press(mouse_pos)
def _handle_mouse_release(self, mouse_pos: MousePos):
if not self._enabled():
self._is_pressed = False
return
super()._handle_mouse_release(mouse_pos)
def _render(self, rect: rl.Rectangle):
self.set_rect(rect)
r, g, b = max(0, self.bg_color.r - 20), max(0, self.bg_color.g - 20), max(0, self.bg_color.b - 20)
color = rl.Color(r, g, b, 255) if self._is_pressed else self.bg_color
enabled = self._enabled()
base_color = self._active_color if enabled else self._disabled_color
r, g, b = max(0, base_color.r - 20), max(0, base_color.g - 20), max(0, base_color.b - 20)
color = rl.Color(r, g, b, 255) if self._is_pressed and enabled else base_color
rl.draw_rectangle_rounded(rect, 0.15, 10, color)
self._draw_watermark(rect, self._icon)
padding = 25
@@ -29,7 +29,7 @@ class StarPilotWheelLayout(StarPilotPanel):
"title": tr_noop("Remap Cancel Button"),
"type": "toggle",
"get_state": lambda: self._params.get_bool("RemapCancelToDistance"),
"set_state": lambda s: self._params.put_bool("RemapCancelToDistance", s),
"set_state": self._set_cancel_remap_state,
"color": "#FFC40D",
},
{
@@ -58,17 +58,39 @@ class StarPilotWheelLayout(StarPilotPanel):
"type": "value",
"get_value": lambda: self._get_action_name("LKASButtonControl"),
"on_click": lambda: self._show_action_picker("LKASButtonControl"),
"is_enabled": lambda: not self._lkas_locked(),
"key": "LKASButtonControl",
"color": "#FFC40D",
},
]
self._rebuild_grid()
def _lkas_locked(self):
return self._params.get_bool("RemapCancelToDistance")
def _force_lkas_no_action(self):
if self._params.get_int("LKASButtonControl") != 0:
self._params.put_int("LKASButtonControl", 0)
self._params_memory.put_bool("StarPilotTogglesUpdated", True)
def _set_cancel_remap_state(self, state):
self._params.put_bool("RemapCancelToDistance", state)
if state:
self._force_lkas_no_action()
self._rebuild_grid()
def _get_action_name(self, key):
if key == "LKASButtonControl" and self._lkas_locked():
self._force_lkas_no_action()
return ACTION_NAME_BY_ID[0]
idx = self._params.get_int(key)
return ACTION_NAME_BY_ID.get(idx, ACTION_NAMES[0])
def _get_available_actions(self):
def _get_available_actions(self, key=None):
if key == "LKASButtonControl" and self._lkas_locked():
return [ACTION_NAME_BY_ID[0]]
cs = starpilot_state.car_state
return [
option["name"] for option in ACTION_OPTIONS
@@ -76,7 +98,12 @@ class StarPilotWheelLayout(StarPilotPanel):
]
def _show_action_picker(self, key):
actions = self._get_available_actions()
if key == "LKASButtonControl" and self._lkas_locked():
self._force_lkas_no_action()
self._rebuild_grid()
return
actions = self._get_available_actions(key)
current = self._get_action_name(key)
if current not in actions:
current = actions[0]
@@ -84,6 +111,7 @@ class StarPilotWheelLayout(StarPilotPanel):
def on_select(res, val):
if res == DialogResult.CONFIRM:
self._params.put_int(key, ACTION_IDS.get(val, 0))
self._params_memory.put_bool("StarPilotTogglesUpdated", True)
self._rebuild_grid()
gui_app.set_modal_overlay(SelectionDialog(tr(key), actions, current, on_close=on_select))
@@ -91,6 +119,8 @@ class StarPilotWheelLayout(StarPilotPanel):
def _rebuild_grid(self):
if not self.CATEGORIES:
return
if self._lkas_locked():
self._force_lkas_no_action()
if self._tile_grid is None:
self._tile_grid = __import__('openpilot.selfdrive.ui.layouts.settings.starpilot.metro', fromlist=['TileGrid']).TileGrid(columns=None, padding=20)
self._tile_grid.clear()
@@ -110,7 +140,7 @@ class StarPilotWheelLayout(StarPilotPanel):
elif tile_type == "value":
from openpilot.selfdrive.ui.layouts.settings.starpilot.metro import ValueTile
tile = ValueTile(title=tr(cat["title"]), get_value=cat["get_value"], on_click=cat["on_click"], bg_color=cat.get("color"))
tile = ValueTile(title=tr(cat["title"]), get_value=cat["get_value"], on_click=cat["on_click"], bg_color=cat.get("color"), is_enabled=cat.get("is_enabled"))
else:
continue
self._tile_grid.add_tile(tile)
BIN
View File
Binary file not shown.
@@ -565,6 +565,13 @@ function clearSearchFilter() {
scheduleSyncInputs()
}
function getSettingLockReason(param) {
if (param?.key === "LKASButtonControl" && !!state.values.RemapCancelToDistance) {
return "Cancel remap requires the LKAS button to stay on No Action."
}
return ""
}
function handleSectionTabClick(sectionSlug, event) {
if (!sectionSlug || sectionSlug === state.activeSectionSlug) return
@@ -590,6 +597,8 @@ function renderSettingRow(p) {
const isNumeric = p.ui_type === "numeric"
const isChild = p.parent_key ? "ds-child-modifier" : ""
const lockReason = getSettingLockReason(p)
const isLocked = lockReason !== ""
return html`
<div class="ds-row ${isNumeric ? "ds-row-numeric" : ""} ${isChild}">
@@ -597,6 +606,7 @@ function renderSettingRow(p) {
<div class="ds-row-text">
<span class="ds-row-label">${p.label}</span>
${p.description ? html`<div class="ds-row-desc">${p.description}</div>` : ""}
${lockReason ? html`<div class="ds-row-desc"><strong>Locked:</strong> ${lockReason}</div>` : ""}
${() => p.is_parent_toggle && state.values[p.key] ? html`
<div class="ds-manage-btn" @click="${() => toggleManage(p.key)}">
@@ -675,6 +685,7 @@ function renderSettingRow(p) {
class="ds-select"
id="ds-${p.key}"
data-endpoint="${p.options_endpoint || ""}"
?disabled="${isLocked}"
@change="${() => updateParam(p.key, "dropdown")}">
<option value="">Loading...</option>
</select>
@@ -1724,13 +1724,6 @@
"data_type": "bool",
"ui_type": "toggle"
},
{
"key": "RemapCancelToDistance",
"label": "Remap Cancel To Distance",
"description": "On pedal-interceptor Bolts, remap the steering-wheel CANCEL button to distance/personality input.",
"data_type": "bool",
"ui_type": "toggle"
},
{
"key": "VoltSNG",
"label": "Stop-and-Go Hack",
@@ -1771,6 +1764,183 @@
}
]
},
{
"name": "Wheel Controls",
"icon": "bi-controller",
"params": [
{
"key": "RemapCancelToDistance",
"label": "Remap Cancel To Distance",
"description": "On pedal-interceptor Bolts, remap the steering-wheel CANCEL button to distance/personality input.",
"data_type": "bool",
"ui_type": "toggle"
},
{
"key": "DistanceButtonControl",
"label": "Distance Button (Short Press)",
"description": "Action performed when the \"Distance\" button is pressed.",
"data_type": "int",
"ui_type": "dropdown",
"options": [
{
"value": 0,
"label": "No Action"
},
{
"value": 1,
"label": "Change Personality"
},
{
"value": 2,
"label": "Force Coast"
},
{
"value": 3,
"label": "Pause Steering"
},
{
"value": 4,
"label": "Pause Accel/Brake"
},
{
"value": 5,
"label": "Toggle Experimental"
},
{
"value": 6,
"label": "Toggle Traffic"
},
{
"value": 7,
"label": "Toggle Switchback"
}
]
},
{
"key": "LongDistanceButtonControl",
"label": "Distance Button (Long Press)",
"description": "Action performed when the \"Distance\" button is pressed for more than 0.5 seconds.",
"data_type": "int",
"ui_type": "dropdown",
"options": [
{
"value": 0,
"label": "No Action"
},
{
"value": 1,
"label": "Change Personality"
},
{
"value": 2,
"label": "Force Coast"
},
{
"value": 3,
"label": "Pause Steering"
},
{
"value": 4,
"label": "Pause Accel/Brake"
},
{
"value": 5,
"label": "Toggle Experimental"
},
{
"value": 6,
"label": "Toggle Traffic"
},
{
"value": 7,
"label": "Toggle Switchback"
}
]
},
{
"key": "VeryLongDistanceButtonControl",
"label": "Distance Button (Extra Long Press)",
"description": "Action performed when the \"Distance\" button is pressed for more than 2.5 seconds.",
"data_type": "int",
"ui_type": "dropdown",
"options": [
{
"value": 0,
"label": "No Action"
},
{
"value": 1,
"label": "Change Personality"
},
{
"value": 2,
"label": "Force Coast"
},
{
"value": 3,
"label": "Pause Steering"
},
{
"value": 4,
"label": "Pause Accel/Brake"
},
{
"value": 5,
"label": "Toggle Experimental"
},
{
"value": 6,
"label": "Toggle Traffic"
},
{
"value": 7,
"label": "Toggle Switchback"
}
]
},
{
"key": "LKASButtonControl",
"label": "LKAS Button",
"description": "Action performed when the \"LKAS\" button is pressed.",
"data_type": "int",
"ui_type": "dropdown",
"options": [
{
"value": 0,
"label": "No Action"
},
{
"value": 1,
"label": "Change Personality"
},
{
"value": 2,
"label": "Force Coast"
},
{
"value": 3,
"label": "Pause Steering"
},
{
"value": 4,
"label": "Pause Accel/Brake"
},
{
"value": 5,
"label": "Toggle Experimental"
},
{
"value": 6,
"label": "Toggle Traffic"
},
{
"value": 7,
"label": "Toggle Switchback"
}
]
}
]
},
{
"name": "Device & Data",
"icon": "bi-hdd",
@@ -20,16 +20,16 @@ const SVG_WIDTH = 1000
const SVG_HEIGHT = 260
const ADVANCED_TERMS_KEY = "plotsShowAdvancedTerms"
const QUALITY_WINDOW_SECONDS = 30
const QUALITY_MIN_SAMPLES = 12
const QUALITY_MIN_SAMPLES = 8
const LATERAL_QUALITY_CONFIG = {
desiredKey: "desiredLateralAccel",
actualKey: "actualLateralAccel",
minSpeedMps: 0.5,
minDemand: 0.015,
minDemand: 0.008,
allowLowDemandFallback: true,
fallbackMinSpeedMps: 1.0,
fallbackMinPeakDemand: 0.03,
fallbackMinSpeedMps: 0.5,
fallbackMinPeakDemand: 0.01,
great: 0.15,
good: 0.30,
fair: 0.50,
@@ -39,8 +39,10 @@ const LONGITUDINAL_QUALITY_CONFIG = {
desiredKey: "desiredLongitudinalAccel",
actualKey: "actualLongitudinalAccel",
minSpeedMps: 0.0,
minDemand: 0.08,
allowLowDemandFallback: false,
minDemand: 0.05,
allowLowDemandFallback: true,
fallbackMinSpeedMps: 1.5,
fallbackMinPeakDemand: 0.04,
applyPersistenceRules: true,
warnError: 0.50,
severeError: 0.90,
@@ -114,6 +116,12 @@ function formatQualityLabel(label) {
return text || "N/A"
}
function signalMagnitude(sample, config) {
const desired = Math.abs(toNumber(sample?.[config.desiredKey], 0))
const actual = Math.abs(toNumber(sample?.[config.actualKey], 0))
return Math.max(desired, actual)
}
function computeMatchQuality(samples, config) {
const safeSamples = Array.isArray(samples) ? samples : []
if (safeSamples.length < 2) {
@@ -124,25 +132,22 @@ function computeMatchQuality(samples, config) {
const cutoffTs = latestTs > 0 ? latestTs - QUALITY_WINDOW_SECONDS : 0
const recentSamples = safeSamples.filter((sample) => toNumber(sample?.timestamp, 0) >= cutoffTs)
const demandEligibleSamples = recentSamples.filter((sample) => {
const eligibleSignalSamples = recentSamples.filter((sample) => {
const speed = Math.abs(toNumber(sample?.speed, 0))
const desired = Math.abs(toNumber(sample?.[config.desiredKey], 0))
const signal = signalMagnitude(sample, config)
const speedOk = config.minSpeedMps <= 0 ? true : speed >= config.minSpeedMps
const demandOk = config.minDemand <= 0 ? true : desired >= config.minDemand
const demandOk = config.minDemand <= 0 ? true : signal >= config.minDemand
return speedOk && demandOk
})
let eligibleSamples = demandEligibleSamples
let eligibleSamples = eligibleSignalSamples
let usedLowDemandFallback = false
const allowLowDemandFallback = config.allowLowDemandFallback !== false
if (allowLowDemandFallback && eligibleSamples.length < QUALITY_MIN_SAMPLES && recentSamples.length >= QUALITY_MIN_SAMPLES) {
const totalSpeed = recentSamples.reduce((sum, sample) => sum + Math.abs(toNumber(sample?.speed, 0)), 0)
const avgSpeed = recentSamples.length > 0 ? (totalSpeed / recentSamples.length) : 0
const peakDemand = recentSamples.reduce((peak, sample) => {
const desired = Math.abs(toNumber(sample?.[config.desiredKey], 0))
return Math.max(peak, desired)
}, 0)
const peakDemand = recentSamples.reduce((peak, sample) => Math.max(peak, signalMagnitude(sample, config)), 0)
const fallbackMinSpeed = Math.max(0, toNumber(config.fallbackMinSpeedMps, 0))
const fallbackMinPeakDemand = Math.max(0, toNumber(config.fallbackMinPeakDemand, 0))
@@ -164,7 +169,7 @@ function computeMatchQuality(samples, config) {
return {
label: "N/A",
value: null,
detail: `Need ${QUALITY_MIN_SAMPLES} demand samples (${eligibleSamples.length} demand / ${recentSamples.length} total)`,
detail: `Need ${QUALITY_MIN_SAMPLES} signal samples (${eligibleSamples.length} signal / ${recentSamples.length} total)`,
}
}
@@ -622,7 +627,7 @@ export function LivePlots() {
${state.error ? html`<p class="plotError"><strong>Error:</strong> ${state.error}</p>` : ""}
${state.live?.lastError ? html`<p class="plotError"><strong>Source Error:</strong> ${state.live.lastError}</p>` : ""}
<p class="qualityMethodNote">
Match rating uses a 30-second rolling window. Lateral prefers true steering-demand moments, and longitudinal also checks how much of the window stays above error limits so brief spikes are less likely to mark "Poor."
Match rating uses a 30-second rolling window. Strong steering or accel moments are preferred, but gentler windows can still earn a rating so normal driving does not sit at N/A. Longitudinal also checks how much of the window stays above error limits so brief spikes are less likely to mark "Poor."
</p>
</section>
+37 -1
View File
@@ -674,6 +674,26 @@ def _safe_float(value, default=0.0):
except Exception:
return float(default)
def _get_param_int_value(key, default=0):
try:
raw_value = params.get(key)
if isinstance(raw_value, bytes):
raw_value = raw_value.decode("utf-8", errors="replace")
return int(float(str(raw_value or default)))
except Exception:
return int(default)
def _enforce_cancel_remap_lkas_lock():
if not params.get_bool("RemapCancelToDistance"):
return False
if _get_param_int_value("LKASButtonControl", 0) == 0:
return False
params.put("LKASButtonControl", "0")
update_starpilot_toggles()
return True
def _get_system_uptime_seconds():
try:
with open("/proc/uptime", "r", encoding="utf-8") as uptime_file:
@@ -2803,15 +2823,30 @@ def setup(app):
metered_enabled = str_val.strip() in ("1", "true", "True")
gsm_metered_apply_result = _apply_cellular_metered_setting(metered_enabled)
locked_lkas = _enforce_cancel_remap_lkas_lock()
update_starpilot_toggles()
response = {"message": f"Parameter '{key}' updated successfully."}
updated = {}
if key == "RemapCancelToDistance" and params.get_bool("RemapCancelToDistance"):
updated["RemapCancelToDistance"] = True
updated["LKASButtonControl"] = 0
response["message"] = "Remap Cancel To Distance enabled. LKAS Button has been locked to No Action."
elif key == "LKASButtonControl" and params.get_bool("RemapCancelToDistance"):
updated["LKASButtonControl"] = 0
updated["RemapCancelToDistance"] = True
response["message"] = "LKAS Button is locked to No Action while Remap Cancel To Distance is enabled."
elif locked_lkas:
updated["LKASButtonControl"] = 0
if gsm_metered_apply_result is not None:
response["updated"] = {"GsmMetered": str_val.strip() in ("1", "true", "True")}
updated["GsmMetered"] = str_val.strip() in ("1", "true", "True")
response["networkProfilesUpdated"] = gsm_metered_apply_result.get("profiles", [])
warnings = gsm_metered_apply_result.get("warnings", [])
if warnings:
response["warning"] = " ".join(warnings)
if updated:
response["updated"] = updated
return jsonify(response), 200
@@ -2819,6 +2854,7 @@ def setup(app):
@app.route("/api/params/all", methods=["GET"])
def get_all_params():
_enforce_cancel_remap_lkas_lock()
allowed_keys, types = _get_param_type_info()
result = {}
@@ -305,6 +305,11 @@ StarPilotVehiclesPanel::StarPilotVehiclesPanel(StarPilotSettingsWindow *parent,
QSet<QString> rebootKeys = {"RemapCancelToDistance", "TacoTuneHacks"};
for (const QString &key : rebootKeys) {
QObject::connect(static_cast<ToggleControl*>(toggles[key]), &ToggleControl::toggleFlipped, [key, this](bool state) {
if (key == "RemapCancelToDistance" && state && params.getInt("LKASButtonControl") != 0) {
params.putInt("LKASButtonControl", 0);
updateStarPilotToggles();
}
if (started) {
if (key == "TacoTuneHacks" && state) {
if (StarPilotConfirmationDialog::toggleReboot(this)) {
+76 -23
View File
@@ -1,5 +1,54 @@
#include "starpilot/ui/qt/offroad/wheel_settings.h"
namespace {
QMap<int, QString> getWheelFunctionsMap() {
return {
{0, QObject::tr("No Action")},
{3, QObject::tr("Pause Steering")},
{7, QObject::tr("Toggle \"Switchback Mode\" On/Off")},
};
}
QMap<int, QString> getLongitudinalWheelFunctionsMap() {
return {
{1, QObject::tr("Change \"Personality Profile\"")},
{2, QObject::tr("Force openpilot to Coast")},
{4, QObject::tr("Pause Acceleration/Braking")},
{5, QObject::tr("Toggle \"Experimental Mode\" On/Off")},
{6, QObject::tr("Toggle \"Traffic Mode\" On/Off")},
};
}
QMap<int, QString> getMergedWheelFunctionsMap() {
QMap<int, QString> functionsMap = getWheelFunctionsMap();
const QMap<int, QString> longitudinalFunctionsMap = getLongitudinalWheelFunctionsMap();
for (auto it = longitudinalFunctionsMap.constBegin(); it != longitudinalFunctionsMap.constEnd(); ++it) {
functionsMap[it.key()] = it.value();
}
return functionsMap;
}
QString getWheelFunctionLabel(Params &params, const QString &key) {
const QMap<int, QString> functionsMap = getMergedWheelFunctionsMap();
return functionsMap.value(params.getInt(key.toStdString()), QObject::tr("No Action"));
}
bool lockLkasButtonIfNeeded(Params &params) {
if (!params.getBool("RemapCancelToDistance")) {
return false;
}
if (params.getInt("LKASButtonControl") != 0) {
params.putInt("LKASButtonControl", 0);
updateStarPilotToggles();
}
return true;
}
} // namespace
StarPilotWheelPanel::StarPilotWheelPanel(StarPilotSettingsWindow *parent, bool forceOpen) : StarPilotListWidget(parent), parent(parent) {
forceOpenDescriptions = forceOpen;
@@ -11,25 +60,18 @@ StarPilotWheelPanel::StarPilotWheelPanel(StarPilotSettingsWindow *parent, bool f
};
for (const auto &[param, title, desc, icon] : wheelToggles) {
QMap<int, QString> functionsMap {
{0, tr("No Action")},
{3, tr("Pause Steering")},
{7, tr("Toggle \"Switchback Mode\" On/Off")}
};
QMap<int, QString> longitudinalFunctionsMap {
{1, tr("Change \"Personality Profile\"")},
{2, tr("Force openpilot to Coast")},
{4, tr("Pause Acceleration/Braking")},
{5, tr("Toggle \"Experimental Mode\" On/Off")},
{6, tr("Toggle \"Traffic Mode\" On/Off")}
};
ButtonControl *wheelToggle = new ButtonControl(title, tr("SELECT"), desc);
QObject::connect(wheelToggle, &ButtonControl::clicked, [functionsMap, longitudinalFunctionsMap, key = param, parent, wheelToggle, this]() mutable {
QObject::connect(wheelToggle, &ButtonControl::clicked, [key = param, parent, wheelToggle, this]() {
if (key == "LKASButtonControl" && lockLkasButtonIfNeeded(params)) {
wheelToggle->setValue(tr("No Action"));
wheelToggle->setEnabled(false);
return;
}
QMap<int, QString> functionsMap = getWheelFunctionsMap();
if (parent->hasOpenpilotLongitudinal) {
QMap<int, QString>::const_iterator it;
for (it = longitudinalFunctionsMap.constBegin(); it != longitudinalFunctionsMap.constEnd(); ++it) {
const QMap<int, QString> longitudinalFunctionsMap = getLongitudinalWheelFunctionsMap();
for (auto it = longitudinalFunctionsMap.constBegin(); it != longitudinalFunctionsMap.constEnd(); ++it) {
functionsMap[it.key()] = it.value();
}
}
@@ -37,16 +79,17 @@ StarPilotWheelPanel::StarPilotWheelPanel(StarPilotSettingsWindow *parent, bool f
QString selection = MultiOptionDialog::getSelection(tr("Select a function to assign to this button"), functionsMap.values(), functionsMap[params.getInt(key.toStdString())], this);
if (!selection.isEmpty()) {
params.putInt(key.toStdString(), functionsMap.key(selection));
wheelToggle->setValue(selection);
updateStarPilotToggles();
}
});
QMap<int, QString> mergedFunctionsMap = functionsMap;
QMap<int, QString>::const_iterator it;
for (it = longitudinalFunctionsMap.constBegin(); it != longitudinalFunctionsMap.constEnd(); ++it) {
mergedFunctionsMap[it.key()] = it.value();
if (param == "LKASButtonControl" && lockLkasButtonIfNeeded(params)) {
wheelToggle->setValue(tr("No Action"));
wheelToggle->setEnabled(false);
} else {
wheelToggle->setValue(getWheelFunctionLabel(params, param));
}
wheelToggle->setValue(mergedFunctionsMap[params.getInt(param.toStdString())]);
toggles[param] = wheelToggle;
@@ -78,6 +121,16 @@ void StarPilotWheelPanel::updateToggles() {
setVisible &= !parent->lkasAllowedForAOL || !(params.getBool("AlwaysOnLateral") && params.getBool("AlwaysOnLateralLKAS"));
}
if (ButtonControl *wheelToggle = qobject_cast<ButtonControl*>(toggle)) {
if (key == "LKASButtonControl") {
const bool lkasLocked = lockLkasButtonIfNeeded(params);
wheelToggle->setEnabled(!lkasLocked);
wheelToggle->setValue(lkasLocked ? tr("No Action") : getWheelFunctionLabel(params, key));
} else {
wheelToggle->setValue(getWheelFunctionLabel(params, key));
}
}
toggle->setVisible(setVisible);
}