From de710b066a41ccf71696583f4a858fa4f415557b Mon Sep 17 00:00:00 2001 From: Test User Date: Thu, 22 Jan 2026 19:47:56 -0600 Subject: [PATCH] Add BrakeDisablesLateral toggle option and implement related functionality --- common/params_keys.h | 1 + opendbc_repo/opendbc/safety/safety.h | 5 +++-- panda/board/main_comms.h | 4 ++++ selfdrive/pandad/panda.cc | 4 ++++ selfdrive/pandad/panda.h | 1 + selfdrive/pandad/pandad.cc | 8 ++++++++ selfdrive/ui/layouts/settings/toggles.py | 7 +++++++ selfdrive/ui/mici/layouts/settings/toggles.py | 3 +++ 8 files changed, 31 insertions(+), 2 deletions(-) diff --git a/common/params_keys.h b/common/params_keys.h index 5d40d33788..e9697d576b 100644 --- a/common/params_keys.h +++ b/common/params_keys.h @@ -135,4 +135,5 @@ inline static std::unordered_map keys = { {"NoFSC", {PERSISTENT, BOOL}}, {"BlendedACC", {PERSISTENT, BOOL}}, {"ManualTransmission", {PERSISTENT, BOOL}}, + {"BrakeDisablesLateral", {PERSISTENT, BOOL, "1"}}, }; diff --git a/opendbc_repo/opendbc/safety/safety.h b/opendbc_repo/opendbc/safety/safety.h index 87c41cbaba..8ea491a5f1 100644 --- a/opendbc_repo/opendbc/safety/safety.h +++ b/opendbc_repo/opendbc/safety/safety.h @@ -79,6 +79,7 @@ struct sample_t angle_meas; // last 6 steer angles/curvatures int alternative_experience = 0; +bool brake_disables_lateral = true; // whether brake press disables lateral control (true = brake does disable) // time since safety mode has been changed uint32_t safety_mode_cnt = 0U; @@ -341,8 +342,8 @@ static void relay_malfunction_set(void) { static void generic_rx_checks(void) { gas_pressed_prev = gas_pressed; - // exit controls on rising edge of brake press - if (brake_pressed && (!brake_pressed_prev || vehicle_moving)) { + // exit controls on rising edge of brake press (unless brake_disables_lateral is false) + if (brake_pressed && (!brake_pressed_prev || vehicle_moving) && brake_disables_lateral) { controls_allowed = false; } brake_pressed_prev = brake_pressed; diff --git a/panda/board/main_comms.h b/panda/board/main_comms.h index ce61f625dd..4f85aa672c 100644 --- a/panda/board/main_comms.h +++ b/panda/board/main_comms.h @@ -319,6 +319,10 @@ int comms_control_handler(ControlPacket_t *req, uint8_t *resp) { UNUSED(ret); } break; + // **** 0xfd: set brake disables lateral + case 0xfd: + brake_disables_lateral = (req->param1 != 0U); + break; default: print("NO HANDLER "); puth(req->request); diff --git a/selfdrive/pandad/panda.cc b/selfdrive/pandad/panda.cc index 93e139f0ec..ea466b0956 100644 --- a/selfdrive/pandad/panda.cc +++ b/selfdrive/pandad/panda.cc @@ -176,6 +176,10 @@ void Panda::set_canfd_non_iso(uint16_t bus, bool non_iso) { handle->control_write(0xfc, bus, non_iso); } +void Panda::set_brake_disables_lateral(bool brake_disables_lateral) { + handle->control_write(0xfd, brake_disables_lateral, 0); +} + static uint8_t len_to_dlc(uint8_t len) { if (len <= 8) { return len; diff --git a/selfdrive/pandad/panda.h b/selfdrive/pandad/panda.h index 5cbce44f28..79539c1ecd 100644 --- a/selfdrive/pandad/panda.h +++ b/selfdrive/pandad/panda.h @@ -82,6 +82,7 @@ public: void set_can_fd_auto(uint16_t bus, bool enabled); void set_data_speed_kbps(uint16_t bus, uint16_t speed); void set_canfd_non_iso(uint16_t bus, bool non_iso); + void set_brake_disables_lateral(bool brake_disables_lateral); void can_send(const capnp::List::Reader &can_data_list); bool can_receive(std::vector& out_vec); void can_reset_communications(); diff --git a/selfdrive/pandad/pandad.cc b/selfdrive/pandad/pandad.cc index 2fd4a4def2..122e48e6a9 100644 --- a/selfdrive/pandad/pandad.cc +++ b/selfdrive/pandad/pandad.cc @@ -375,6 +375,7 @@ void process_peripheral_state(Panda *panda, PubMaster *pm, bool no_fan_control) static int prev_ir_pwr = 999; static uint32_t prev_frame_id = UINT32_MAX; static bool driver_view = false; + static bool prev_brake_disables_lateral = true; // TODO: can we merge these? static FirstOrderFilter integ_lines_filter(0, 30.0, 0.05); @@ -391,6 +392,13 @@ void process_peripheral_state(Panda *panda, PubMaster *pm, bool no_fan_control) } } + // Brake disables lateral control setting + bool brake_disables_lateral = params.getBool("BrakeDisablesLateral"); + if (brake_disables_lateral != prev_brake_disables_lateral || sm.frame % 100 == 0) { + panda->set_brake_disables_lateral(brake_disables_lateral); + prev_brake_disables_lateral = brake_disables_lateral; + } + if (sm.updated("driverCameraState")) { auto event = sm["driverCameraState"]; int cur_integ_lines = event.getDriverCameraState().getIntegLines(); diff --git a/selfdrive/ui/layouts/settings/toggles.py b/selfdrive/ui/layouts/settings/toggles.py index 78859d70a8..c54af9515f 100644 --- a/selfdrive/ui/layouts/settings/toggles.py +++ b/selfdrive/ui/layouts/settings/toggles.py @@ -36,6 +36,7 @@ DESCRIPTIONS = { "NoMRCC": tr_noop("Enable if your car does not have stock MRCC."), "NoFSC": tr_noop("Enable if your car does not have stock FSC."), "ManualTransmission": tr_noop("Enable if your car has a manual transmission."), + "BrakeDisablesLateral": tr_noop("When disabled, lateral control will not be disabled when the brake is pressed."), } @@ -125,6 +126,12 @@ class TogglesLayout(Widget): "chffr_wheel.png", True, ), + "BrakeDisablesLateral": ( + lambda: tr("Brake Disables Lateral Control"), + DESCRIPTIONS["BrakeDisablesLateral"], + "chffr_wheel.png", + False, + ), } self._long_personality_setting = multiple_button_item( diff --git a/selfdrive/ui/mici/layouts/settings/toggles.py b/selfdrive/ui/mici/layouts/settings/toggles.py index 0772694513..2d531e4679 100644 --- a/selfdrive/ui/mici/layouts/settings/toggles.py +++ b/selfdrive/ui/mici/layouts/settings/toggles.py @@ -30,6 +30,7 @@ class TogglesLayoutMici(NavWidget): enable_no_mrcc = BigParamControl("no stock MRCC", "NoMRCC", toggle_callback=restart_needed_callback) enable_no_fsc = BigParamControl("no stock FSC", "NoFSC", toggle_callback=restart_needed_callback) enable_manual_transmission = BigParamControl("manual transmission", "ManualTransmission", toggle_callback=restart_needed_callback) + brake_disables_lateral = BigParamControl("brake disables lateral", "BrakeDisablesLateral") self._scroller = Scroller([ self._personality_toggle, @@ -45,6 +46,7 @@ class TogglesLayoutMici(NavWidget): enable_no_mrcc, enable_no_fsc, enable_manual_transmission, + brake_disables_lateral, ], snap_items=False) # Toggle lists @@ -61,6 +63,7 @@ class TogglesLayoutMici(NavWidget): ("NoMRCC", enable_no_mrcc), ("NoFSC", enable_no_fsc), ("ManualTransmission", enable_manual_transmission), + ("BrakeDisablesLateral", brake_disables_lateral), ) enable_openpilot.set_enabled(lambda: not ui_state.engaged)