IQ.Pilot Release Commit @ 2b39aa6

This commit is contained in:
IQ.Lvbs CI [bot]
2026-07-29 00:19:10 -05:00
parent 8f052b6f93
commit c7908ad2e0
226 changed files with 11978 additions and 11349 deletions
+2 -1
View File
@@ -47,6 +47,7 @@ class LongControl:
(CP.longitudinalTuning.kiBP, CP.longitudinalTuning.kiV),
rate=1 / DT_CTRL)
self.last_output_accel = 0.0
self.stopping_decel_rate = CP_IQ.stoppingDecelRateOverride or 1.0
self.smooth = SmoothStopController()
def reset(self):
@@ -75,7 +76,7 @@ class LongControl:
if output_accel > self.CP.stopAccel:
output_accel = min(output_accel, 0.0)
# TODO: can we just go straight to stopAccel?
output_accel -= 1.0 * DT_CTRL # m/s^2/s while trying to stop
output_accel -= self.stopping_decel_rate * DT_CTRL # m/s^2/s while trying to stop
self.reset()
self.smooth.reset()
+10 -1
View File
@@ -745,7 +745,16 @@ class SelfdriveD(GapButtonActions):
self.is_ldw_enabled = self.params.get_bool("IsLdwEnabled")
self.disengage_on_accelerator = self.params.get_bool("DisengageOnAccelerator")
self.experimental_mode = self.params.get_bool("ExperimentalMode") and self.CP.openpilotLongitudinalControl
self.personality = self.params.get("LongitudinalPersonality", return_default=True)
# Params can be changed while selfdrived is running. Keep the live value in
# the same valid enum range enforced during startup; otherwise a stale value
# (for example 3) makes the alert callback lookup raise KeyError and kills
# selfdrived.
self.personality = get_sanitize_int_param(
"LongitudinalPersonality",
min(log.LongitudinalPersonality.schema.enumerants.values()),
max(log.LongitudinalPersonality.schema.enumerants.values()),
self.params,
)
self.nav_exit_lane_change = self._read_nav_exit_lane_change()
self.model_download_pending = self.params.get("ModelManager_DownloadIndex") is not None
@@ -1,6 +1,6 @@
from cereal import car
from openpilot.selfdrive.selfdrived.selfdrived import _cleanup_startup_params
from openpilot.selfdrive.selfdrived.selfdrived import _cleanup_startup_params, get_sanitize_int_param
class DummyParams:
@@ -21,3 +21,20 @@ class TestLongitudinalPrefPersistence:
_cleanup_startup_params(cp, params)
assert params.removed == []
def test_invalid_personality_is_clamped_before_use(self):
class ParamsWithInvalidPersonality:
def __init__(self):
self.value = 3
def get(self, key: str, return_default: bool = False) -> int:
assert key == "LongitudinalPersonality"
return self.value
def put(self, key: str, value: int) -> None:
assert key == "LongitudinalPersonality"
self.value = value
params = ParamsWithInvalidPersonality()
assert get_sanitize_int_param("LongitudinalPersonality", 0, 2, params) == 2
assert params.value == 2
@@ -24,6 +24,14 @@ DESCRIPTIONS = {
"Exposes a snapshot of recent dashcam clips and logs as a USB drive when connected to a computer. " +
"IQ.Pilot keeps running while this is enabled."
),
'long_maneuver': tr_noop(
"Commands a scripted sequence of acceleration steps to measure longitudinal actuator response. " +
"Requires IQ.Pilot longitudinal control. Only use on a clear, closed road."
),
'lat_maneuver': tr_noop(
"Commands a scripted sequence of lateral acceleration steps to measure steering actuator response. " +
"Only use on a straight, flat, clear road."
),
}
@@ -59,6 +67,20 @@ class DeveloperLayout(Widget):
)
self._ssh_keys = ssh_key_item(lambda: tr("SSH Keys"), description=lambda: tr(DESCRIPTIONS["ssh_key"]))
self._long_maneuver_toggle = toggle_item(
lambda: tr("Longitudinal Maneuver Mode"),
description=lambda: tr(DESCRIPTIONS["long_maneuver"]),
initial_state=self._params.get_bool("LongitudinalManeuverMode"),
callback=self._on_long_maneuver_mode,
)
self._lat_maneuver_toggle = toggle_item(
lambda: tr("Lateral Maneuver Mode"),
description=lambda: tr(DESCRIPTIONS["lat_maneuver"]),
initial_state=self._params.get_bool("LateralManeuverMode"),
callback=self._on_lat_maneuver_mode,
)
self._on_enable_ui_debug(self._params.get_bool("ShowDebugInfo"))
self._scroller = Scroller([
@@ -66,6 +88,8 @@ class DeveloperLayout(Widget):
self._usb_storage_toggle,
self._ssh_toggle,
self._ssh_keys,
self._long_maneuver_toggle,
self._lat_maneuver_toggle,
], line_separator=True, spacing=0)
# Toggles should be not available to change in onroad state
@@ -81,12 +105,24 @@ class DeveloperLayout(Widget):
def _update_toggles(self):
ui_state.update_params()
for item in (self._long_maneuver_toggle, self._lat_maneuver_toggle):
item.set_visible(not self._is_release)
if ui_state.CP is not None:
self._long_maneuver_toggle.action_item.set_enabled(ui_state.has_longitudinal_control and ui_state.is_offroad())
self._lat_maneuver_toggle.action_item.set_enabled(ui_state.is_offroad())
else:
self._long_maneuver_toggle.action_item.set_enabled(False)
self._lat_maneuver_toggle.action_item.set_enabled(False)
# TODO: make a param control list item so we don't need to manage internal state as much here
# refresh toggles from params to mirror external changes
for key, item in (
("AdbEnabled", self._adb_toggle),
("UsbStorageEnabled", self._usb_storage_toggle),
("SshEnabled", self._ssh_toggle),
("LongitudinalManeuverMode", self._long_maneuver_toggle),
("LateralManeuverMode", self._lat_maneuver_toggle),
):
item.action_item.set_state(self._params.get_bool(key))
@@ -108,7 +144,12 @@ class DeveloperLayout(Widget):
def _on_long_maneuver_mode(self, state: bool):
self._params.put_bool("LongitudinalManeuverMode", state)
self._params.put_bool("JoystickDebugMode", False)
self._params.put_bool("LateralManeuverMode", False)
self._lat_maneuver_toggle.action_item.set_state(False)
def _on_lat_maneuver_mode(self, state: bool):
self._params.put_bool("LateralManeuverMode", state)
self._params.put_bool("JoystickDebugMode", False)
self._params.put_bool("ExperimentalMode", False)
self._params.put_bool("LongitudinalManeuverMode", False)
self._long_maneuver_toggle.action_item.set_state(False)