This commit is contained in:
firestarsdog
2026-08-05 11:06:29 -04:00
committed by firestar5683
parent 98a913693d
commit f7634ec761
16 changed files with 124 additions and 35 deletions
+16 -3
View File
@@ -421,20 +421,32 @@ class Car:
if self.redneck_cruise is None:
return
v_target_ms, lead_present = self._get_redneck_target_speed(CS)
v_target_ms, lead_present = self._get_redneck_target_speed(CS, CC)
send_button, v_target = self.redneck_cruise.run(CS, CC, v_target_ms, self.is_metric, lead_present=lead_present)
self.CI.CS.redneck_send_button = send_button
self.CI.CS.redneck_v_target = v_target
def _get_redneck_target_speed(self, CS: car.CarState) -> tuple[float, bool]:
def _get_redneck_target_speed(self, CS: car.CarState, CC: car.CarControl) -> tuple[float, bool]:
# With openpilot longitudinal active, project its acceleration demand into the stock cruise setpoint.
if self.CP.openpilotLongitudinalControl:
return CS.vEgo * 1.01 + 3 * CC.actuators.accel, bool(CC.hudControl.leadVisible)
# Preserve the existing button-only SLC path when LongControl is disabled.
starpilot_target_speed = 0.0
slc_target_speed = 0.0
allow_plan_decrease = False
lead_present = False
lead_distance_m = 0.0
lead_rel_speed_ms = 0.0
lookahead_points = REDNECK_DECREASE_LOOKAHEAD_POINTS
if self.sm.seen['starpilotPlan'] and self.sm.valid['starpilotPlan']:
starpilot_target_speed = float(self.sm['starpilotPlan'].vCruise)
starpilot_plan = self.sm['starpilotPlan']
starpilot_target_speed = float(starpilot_plan.vCruise)
if self.starpilot_toggles.speed_limit_controller:
slc_target_speed = max(
float(starpilot_plan.slcOverriddenSpeed),
float(starpilot_plan.slcSpeedLimit) + float(starpilot_plan.slcSpeedLimitOffset),
)
plan_speeds = []
if self.sm.seen['longitudinalPlan'] and self.sm.valid['longitudinalPlan']:
@@ -461,6 +473,7 @@ class Car:
lead_present=lead_present,
lead_distance_m=lead_distance_m,
lead_rel_speed_ms=lead_rel_speed_ms,
slc_target_speed_ms=slc_target_speed,
), lead_present
def step(self):
+5 -2
View File
@@ -45,9 +45,12 @@ def select_redneck_target_speed(v_cruise_kph: float, speed_cluster_ms: float,
starpilot_target_speed_ms: float, plan_speeds_ms: list[float],
lookahead_points: int, allow_plan_decrease: bool = True,
lead_present: bool = False, lead_distance_m: float = 0.0,
lead_rel_speed_ms: float = 0.0) -> float:
lead_rel_speed_ms: float = 0.0,
slc_target_speed_ms: float = 0.0) -> float:
target_speed_ms = float(speed_cluster_ms)
if v_cruise_kph > 0:
if slc_target_speed_ms > 0:
target_speed_ms = float(slc_target_speed_ms)
elif v_cruise_kph > 0:
target_speed_ms = float(v_cruise_kph) * CV.KPH_TO_MS
elif starpilot_target_speed_ms > 0:
target_speed_ms = float(starpilot_target_speed_ms)
@@ -4,6 +4,7 @@ from types import SimpleNamespace
from cereal import car
from openpilot.common.constants import CV
from openpilot.common.realtime import DT_CTRL
from openpilot.selfdrive.car.card import Car
from openpilot.selfdrive.car.redneck_cruise import (
DECREASE_INACTIVE_TIMER,
INCREASE_INACTIVE_TIMER,
@@ -168,6 +169,33 @@ class TestRedneckCruise(unittest.TestCase):
)
self.assertAlmostEqual(104.4 * CV.KPH_TO_MS, target_speed)
def test_target_speed_follows_resolved_slc_target(self):
for internal_mph, slc_mph in ((55.0, 65.0), (65.0, 55.0)):
with self.subTest(internal_mph=internal_mph, slc_mph=slc_mph):
target_speed = select_redneck_target_speed(
internal_mph * CV.MPH_TO_KPH,
internal_mph * CV.MPH_TO_MS,
0.0,
[],
10,
allow_plan_decrease=False,
slc_target_speed_ms=slc_mph * CV.MPH_TO_MS,
)
self.assertAlmostEqual(slc_mph * CV.MPH_TO_MS, target_speed)
def test_card_target_speed_uses_longitudinal_acceleration(self):
card = SimpleNamespace(CP=SimpleNamespace(openpilotLongitudinalControl=True))
car_state = SimpleNamespace(vEgo=55.0 * CV.MPH_TO_MS)
car_control = SimpleNamespace(
actuators=SimpleNamespace(accel=0.5),
hudControl=SimpleNamespace(leadVisible=True),
)
target_speed, lead_present = Car._get_redneck_target_speed(card, car_state, car_control)
self.assertAlmostEqual(55.0 * CV.MPH_TO_MS * 1.01 + 1.5, target_speed)
self.assertTrue(lead_present)
def test_target_speed_returns_plan_minimum_when_slowing_down(self):
target_speed = select_redneck_target_speed(
120.0,
@@ -46,6 +46,7 @@ from openpilot.selfdrive.ui.lib.fingerprint_catalog import (
shorten_model_label,
)
from openpilot.starpilot.common.starpilot_variables import migrate_cancel_button_controls
from openpilot.selfdrive.ui.layouts.settings.common import restart_needed_callback
ACTION_OPTIONS = [
@@ -420,6 +421,13 @@ class VehicleSettingsManagerView(PanelManagerView):
"get_state": lambda: self._controller._params.get_bool("NostalgiaMode"),
"set_state": lambda s: self._controller._on_toggle("NostalgiaMode"),
})
if cs.redneckCruiseAvailable:
toggles.append({
"title": tr("Redneck Cruise"),
"subtitle": tr("Use RES/SET button presses to match the stock cruise set speed to StarPilot's target."),
"get_state": lambda: self._controller._params.get_bool("RedneckCruise"),
"set_state": lambda s: self._controller._on_toggle("RedneckCruise"),
})
return toggles
@@ -679,6 +687,11 @@ class StarPilotVehicleSettingsLayout(_SettingsPage):
migrate_cancel_button_controls(self._params)
starpilot_state.update(force=True)
return
if param_key == "RedneckCruise":
self._params.put_bool("RedneckCruise", not self._params.get_bool("RedneckCruise"))
starpilot_state.update(force=True)
restart_needed_callback(None)
return
current = self._params.get_bool(param_key) if self._params.get(param_key) is not None else False
self._params.put_bool(param_key, not current)
starpilot_state.update(force=True)
+3
View File
@@ -38,6 +38,7 @@ class StarPilotCarState:
hasZSS: bool = False
canUsePedal: bool = False
canUseSDSU: bool = False
redneckCruiseAvailable: bool = False
# ========== Device/Car State ==========
isFrogsGoMoo: bool = False
@@ -206,12 +207,14 @@ class StarPilotState:
# 2. Parse StarPilotCarParamsPersistent
fpcp_bytes = self.params.get("StarPilotCarParamsPersistent")
self.car_state.redneckCruiseAvailable = False
if fpcp_bytes is not None:
try:
FPCP = messaging.log_from_bytes(fpcp_bytes, custom.StarPilotCarParams)
self.car_state.canUsePedal = FPCP.canUsePedal
self.car_state.canUseSDSU = FPCP.canUseSDSU
self.car_state.openpilotLongitudinalControlDisabled = FPCP.openpilotLongitudinalControlDisabled
self.car_state.redneckCruiseAvailable = bool(FPCP.redneckCruiseAvailable)
except Exception:
pass
@@ -9,6 +9,7 @@ from openpilot.selfdrive.ui.lib.fingerprint_catalog import (
shorten_model_label,
)
from openpilot.selfdrive.ui.layouts.settings.common import restart_needed_callback
from openpilot.selfdrive.ui.lib.starpilot_state import starpilot_state
from openpilot.selfdrive.ui.ui_state import ui_state
from openpilot.system.ui.lib.application import gui_app, FontWeight
from openpilot.system.ui.lib.multilang import tr
@@ -195,10 +196,10 @@ class VehicleLayoutMici(NavScroller):
fingerprint_btn = BigButton("fingerprint", "",gui_app.texture("icons_mici/settings/vehicle/fingerprint.png", 58, 64))
fingerprint_btn.set_click_callback(lambda: gui_app.push_widget(fingerprint_panel))
# TODO: make it reloadable without restarting ui
match ui_state.params.get("CarModel"):
case _:
vehicle_specific_widgets = tuple()
starpilot_state.update(force=True)
vehicle_specific_widgets = (
BigParamControl("redneck cruise", "RedneckCruise", toggle_callback=restart_needed_callback),
) if starpilot_state.car_state.redneckCruiseAvailable else tuple()
self._scroller.add_widgets([
fingerprint_btn,
@@ -206,4 +207,3 @@ class VehicleLayoutMici(NavScroller):
])
self._font_medium = gui_app.font(FontWeight.MEDIUM)