From e4c4253964a25ff980520b70ea9f50aede4a1db6 Mon Sep 17 00:00:00 2001 From: Jason Young <46612682+jyoung8607@users.noreply.github.com> Date: Tue, 22 Nov 2022 17:27:52 -0500 Subject: [PATCH] VW MQB: Redundant brake pressed signals (#1137) * VW MQB: Redundant brake pressed signals * bump timer for safety tests in CI * use nicer f-string syntax * don't need that --- board/safety/safety_volkswagen_mqb.h | 27 ++++++++++++++++++++------- tests/safety/test_volkswagen_mqb.py | 24 ++++++++++++++++++++++-- 2 files changed, 42 insertions(+), 9 deletions(-) diff --git a/board/safety/safety_volkswagen_mqb.h b/board/safety/safety_volkswagen_mqb.h index b0ecf98566..0371d41c40 100644 --- a/board/safety/safety_volkswagen_mqb.h +++ b/board/safety/safety_volkswagen_mqb.h @@ -27,6 +27,7 @@ const int VOLKSWAGEN_MQB_MIN_ACCEL = -3500; #define MSG_GRA_ACC_01 0x12B // TX by OP, ACC control buttons for cancel/resume #define MSG_ACC_07 0x12E // TX by OP, ACC control instructions to the drivetrain coordinator #define MSG_ACC_02 0x30C // TX by OP, ACC HUD data to the instrument cluster +#define MSG_MOTOR_14 0x3BE // RX from ECU, for brake switch status #define MSG_LDW_02 0x397 // TX by OP, Lane line recognition and text alerts // Transmit of GRA_ACC_01 is allowed on bus 0 and 2 to keep compatibility with gateway and camera integration @@ -35,16 +36,19 @@ const CanMsg VOLKSWAGEN_MQB_LONG_TX_MSGS[] = {{MSG_HCA_01, 0, 8}, {MSG_LDW_02, 0 {MSG_ACC_02, 0, 8}, {MSG_ACC_06, 0, 8}, {MSG_ACC_07, 0, 8}}; AddrCheckStruct volkswagen_mqb_addr_checks[] = { - {.msg = {{MSG_ESP_19, 0, 8, .check_checksum = false, .max_counter = 0U, .expected_timestep = 10000U}, { 0 }, { 0 }}}, - {.msg = {{MSG_LH_EPS_03, 0, 8, .check_checksum = true, .max_counter = 15U, .expected_timestep = 10000U}, { 0 }, { 0 }}}, - {.msg = {{MSG_ESP_05, 0, 8, .check_checksum = true, .max_counter = 15U, .expected_timestep = 20000U}, { 0 }, { 0 }}}, - {.msg = {{MSG_TSK_06, 0, 8, .check_checksum = true, .max_counter = 15U, .expected_timestep = 20000U}, { 0 }, { 0 }}}, - {.msg = {{MSG_MOTOR_20, 0, 8, .check_checksum = true, .max_counter = 15U, .expected_timestep = 20000U}, { 0 }, { 0 }}}, + {.msg = {{MSG_ESP_19, 0, 8, .check_checksum = false, .max_counter = 0U, .expected_timestep = 10000U}, { 0 }, { 0 }}}, + {.msg = {{MSG_LH_EPS_03, 0, 8, .check_checksum = true, .max_counter = 15U, .expected_timestep = 10000U}, { 0 }, { 0 }}}, + {.msg = {{MSG_ESP_05, 0, 8, .check_checksum = true, .max_counter = 15U, .expected_timestep = 20000U}, { 0 }, { 0 }}}, + {.msg = {{MSG_TSK_06, 0, 8, .check_checksum = true, .max_counter = 15U, .expected_timestep = 20000U}, { 0 }, { 0 }}}, + {.msg = {{MSG_MOTOR_20, 0, 8, .check_checksum = true, .max_counter = 15U, .expected_timestep = 20000U}, { 0 }, { 0 }}}, + {.msg = {{MSG_MOTOR_14, 0, 8, .check_checksum = false, .max_counter = 0U, .expected_timestep = 100000U}, { 0 }, { 0 }}}, }; #define VOLKSWAGEN_MQB_ADDR_CHECKS_LEN (sizeof(volkswagen_mqb_addr_checks) / sizeof(volkswagen_mqb_addr_checks[0])) addr_checks volkswagen_mqb_rx_checks = {volkswagen_mqb_addr_checks, VOLKSWAGEN_MQB_ADDR_CHECKS_LEN}; uint8_t volkswagen_crc8_lut_8h2f[256]; // Static lookup table for CRC8 poly 0x2F, aka 8H2F/AUTOSAR +bool volkswagen_mqb_brake_pedal_switch = false; +bool volkswagen_mqb_brake_pressure_detected = false; static uint32_t volkswagen_mqb_get_checksum(CANPacket_t *to_push) { return (uint8_t)GET_BYTE(to_push, 0); @@ -95,6 +99,8 @@ static const addr_checks* volkswagen_mqb_init(uint16_t param) { volkswagen_set_button_prev = false; volkswagen_resume_button_prev = false; + volkswagen_mqb_brake_pedal_switch = false; + volkswagen_mqb_brake_pressure_detected = false; #ifdef ALLOW_DEBUG volkswagen_longitudinal = GET_FLAG(param, FLAG_VOLKSWAGEN_LONG_CONTROL); @@ -176,11 +182,18 @@ static int volkswagen_mqb_rx_hook(CANPacket_t *to_push) { gas_pressed = ((GET_BYTES_04(to_push) >> 12) & 0xFFU) != 0U; } - // Signal: ESP_05.ESP_Fahrer_bremst + // Signal: Motor_14.MO_Fahrer_bremst (ECU detected brake pedal switch F63) + if (addr == MSG_MOTOR_14) { + volkswagen_mqb_brake_pedal_switch = (GET_BYTE(to_push, 3) & 0x10U) >> 4; + } + + // Signal: ESP_05.ESP_Fahrer_bremst (ESP detected driver brake pressure above platform specified threshold) if (addr == MSG_ESP_05) { - brake_pressed = (GET_BYTE(to_push, 3) & 0x4U) >> 2; + volkswagen_mqb_brake_pressure_detected = (GET_BYTE(to_push, 3) & 0x4U) >> 2; } + brake_pressed = volkswagen_mqb_brake_pedal_switch || volkswagen_mqb_brake_pressure_detected; + generic_rx_checks((addr == MSG_HCA_01)); } return valid; diff --git a/tests/safety/test_volkswagen_mqb.py b/tests/safety/test_volkswagen_mqb.py index 5cdaa08bbe..5ac1cb9fd8 100755 --- a/tests/safety/test_volkswagen_mqb.py +++ b/tests/safety/test_volkswagen_mqb.py @@ -48,11 +48,19 @@ def _speed_msg(self, speed): values = {"ESP_%s_Radgeschw_02" % s: speed for s in ["HL", "HR", "VL", "VR"]} return self.packer.make_can_msg_panda("ESP_19", 0, values) - # Brake light switch _esp_05_msg - def _user_brake_msg(self, brake): + # Driver brake pressure over threshold + def _esp_05_msg(self, brake): values = {"ESP_Fahrer_bremst": brake} return self.packer.make_can_msg_panda("ESP_05", 0, values) + # Brake pedal switch + def _motor_14_msg(self, brake): + values = {"MO_Fahrer_bremst": brake} + return self.packer.make_can_msg_panda("Motor_14", 0, values) + + def _user_brake_msg(self, brake): + return self._motor_14_msg(brake) + # Driver throttle input def _user_gas_msg(self, gas): values = {"MO_Fahrpedalrohwert_01": gas} @@ -95,6 +103,18 @@ def _acc_07_msg(self, accel, secondary_accel=3.02): values = {"ACC_Sollbeschleunigung_02": accel, "ACC_Folgebeschl": secondary_accel} return self.packer.make_can_msg_panda("ACC_07", 0, values) + # Verify brake_pressed is true if either the switch or pressure threshold signals are true + def test_redundant_brake_signals(self): + test_combinations = [(True, True, True), (True, True, False), (True, False, True), (False, False, False)] + for brake_pressed, motor_14_signal, esp_05_signal in test_combinations: + self._rx(self._motor_14_msg(False)) + self._rx(self._esp_05_msg(False)) + self.assertFalse(self.safety.get_brake_pressed_prev()) + self._rx(self._motor_14_msg(motor_14_signal)) + self._rx(self._esp_05_msg(esp_05_signal)) + self.assertEqual(brake_pressed, self.safety.get_brake_pressed_prev(), + f"expected {brake_pressed=} with {motor_14_signal=} and {esp_05_signal=}") + def test_torque_measurements(self): # TODO: make this test work with all cars self._rx(self._torque_driver_msg(50))