diff --git a/opendbc_repo/opendbc/car/car.capnp b/opendbc_repo/opendbc/car/car.capnp index 9086102f5..9e3df8423 100644 --- a/opendbc_repo/opendbc/car/car.capnp +++ b/opendbc_repo/opendbc/car/car.capnp @@ -469,7 +469,6 @@ struct CarParams { notCar @66 :Bool; # flag for non-car robotics platforms pcmCruise @3 :Bool; # is openpilot's state tied to the PCM's cruise state? - enableBsm @56 :Bool; # blind spot monitoring flags @64 :UInt32; # flags for car specific quirks alphaLongitudinalAvailable @71 :Bool; @@ -484,20 +483,17 @@ struct CarParams { autoResumeSng @69 :Bool; # describes whether car can resume from a stop automatically # things about the car in the manual - mass @17 :Float32; # [kg] curb weight: all fluids no cargo wheelbase @18 :Float32; # [m] distance from rear axle to front axle centerToFront @19 :Float32; # [m] distance from center of mass to front axle steerRatio @20 :Float32; # [] ratio of steering wheel angle to front wheel angle - steerRatioRear @21 :Float32; # [] ratio of steering wheel angle to rear wheel angle (usually 0) - # things we can derive - rotationalInertia @22 :Float32; # [kg*m2] body rotational inertia + # mass-normalized vehicle dynamics parameters + rotationalInertiaPerMass @22 :Float32; # [m^2] rotational inertia per unit mass tireStiffnessFactor @72 :Float32; # scaling factor used in calculating tireStiffness[Front,Rear] - tireStiffnessFront @23 :Float32; # [N/rad] front tire coeff of stiff - tireStiffnessRear @24 :Float32; # [N/rad] rear tire coeff of stiff + tireStiffnessFrontPerMass @23 :Float32; # [N/(rad*kg)] front tire stiffness per unit mass + tireStiffnessRearPerMass @24 :Float32; # [N/(rad*kg)] rear tire stiffness per unit mass longitudinalTuning @25 :LongitudinalPIDTuning; - lateralParams @48 :LateralParams; lateralTuning :union { pid @26 :LateralPIDTuning; indiDEPRECATED @27 :LateralINDITuningDEPRECATED; @@ -648,8 +644,11 @@ struct CarParams { fcaGiorgio @32; rivian @33; volkswagenMeb @34; - mg @35; - gwm @36; + byd @35; + volvo @36; + bmw @37; + mg @38; + gwm @39; } enum SteerControlType { @@ -724,6 +723,9 @@ struct CarParams { } deprecated :group { + mass @17 :Float32; + steerRatioRear @21 :Float32; + lateralParams @48 :LateralParams; enableGasInterceptor @2 :Bool; enableCamera @4 :Bool; enableApgs @6 :Bool; @@ -749,6 +751,7 @@ struct CarParams { stoppingControl @31 :Bool; # Does the car allow full control even at lows speeds when stopping radarTimeStep @45: Float32 = 0.05; # time delta between radar updates, 20Hz is very standard enableDsu @5 :Bool; # driving support unit + enableBsm @56 :Bool; # blind spot monitoring vEgoStarting @59 :Float32; # Speed at which the car goes into starting state startAccel @32 :Float32; # Required acceleration to get car moving startingState @70 :Bool; # Does this car make use of special starting state diff --git a/opendbc_repo/opendbc/safety/declarations.h b/opendbc_repo/opendbc/safety/declarations.h index 912513f8f..9c271be62 100644 --- a/opendbc_repo/opendbc/safety/declarations.h +++ b/opendbc_repo/opendbc/safety/declarations.h @@ -34,8 +34,11 @@ #define SAFETY_PSA 31U #define SAFETY_RIVIAN 33U #define SAFETY_VOLKSWAGEN_MEB 34U -#define SAFETY_MG 35U -#define SAFETY_GWM 36U +#define SAFETY_BYD 35U +#define SAFETY_VOLVO 36U +#define SAFETY_BMW 37U +#define SAFETY_MG 38U +#define SAFETY_GWM 39U #define GET_BIT(msg, b) ((bool)!!(((msg)->data[((b) / 8U)] >> ((b) % 8U)) & 0x1U)) #define GET_FLAG(value, mask) (((value) & (mask)) == (mask)) @@ -60,7 +63,8 @@ #define UPDATE_VEHICLE_SPEED(val_ms) (update_sample(&vehicle_speed, ROUND((val_ms) * VEHICLE_SPEED_FACTOR))) #define UPDATE_VEHICLE_SPEED_2(val_ms) (update_sample(&vehicle_speed_2, ROUND((val_ms) * VEHICLE_SPEED_FACTOR))) -uint32_t GET_BYTES(const CANPacket_t *msg, int start, int len); +uint32_t GET_BYTES_LE(const CANPacket_t *msg, int start, int len); +uint64_t GET_BYTES_64_LE(const CANPacket_t *msg, int start, int len); extern const int MAX_WRONG_COUNTERS; #define MAX_ADDR_CHECK_MSGS 3U @@ -256,7 +260,7 @@ bool longitudinal_interceptor_checks(const CANPacket_t *msg); // gas intercepto void pcm_cruise_check(bool cruise_engaged); void speed_mismatch_check(const float speed_2); -void safety_tick(const safety_config *safety_config); +void safety_tick(void); // This can be set by the safety hooks extern bool controls_allowed; @@ -371,5 +375,7 @@ extern const safety_hooks volkswagen_meb_hooks; extern const safety_hooks volkswagen_pq_hooks; extern const safety_hooks rivian_hooks; extern const safety_hooks psa_hooks; +extern const safety_hooks byd_hooks; extern const safety_hooks mg_hooks; extern const safety_hooks gwm_hooks; +#define GET_BYTES(msg, start, len) GET_BYTES_LE(msg, start, len) diff --git a/opendbc_repo/opendbc/safety/helpers.h b/opendbc_repo/opendbc/safety/helpers.h index 8f4d52880..932e6e6bc 100644 --- a/opendbc_repo/opendbc/safety/helpers.h +++ b/opendbc_repo/opendbc/safety/helpers.h @@ -1,3 +1,5 @@ +#pragma once + #include "opendbc/safety/declarations.h" // cppcheck-suppress-macro misra-c2012-1.2; allow __typeof__ extension @@ -34,6 +36,36 @@ #define SAFETY_UNUSED(x) ((void)(x)) +// Update an MSB-first CRC8 with one byte; callers choose the initial value and final XOR. +static uint8_t crc8_update(uint8_t initial_crc, uint8_t data, uint8_t poly) { + uint8_t crc = initial_crc ^ data; + for (int i = 0; i < 8; i++) { + if ((crc & 0x80U) != 0U) { + crc = (crc << 1) ^ poly; + } else { + crc <<= 1; + } + } + return crc; +} + +// Compare address and bus as one key: CANPacket_t has a 29-bit address and 3-bit bus. +static bool msg_matches_addr_bus(const CANPacket_t *msg, uint32_t addr, uint32_t bus) { + uint32_t actual = ((uint32_t)msg->addr << 3) | (uint32_t)msg->bus; + uint32_t expected = (addr << 3) | bus; + return actual == expected; +} + +// Compare address, bus, and decoded byte length as one key. +static bool msg_matches_addr_bus_len(const CANPacket_t *msg, uint32_t addr, uint32_t bus, uint32_t len) { + uint64_t actual = ((uint64_t)msg->addr << 10) | ((uint64_t)msg->bus << 7) | (uint64_t)dlc_to_len[msg->data_len_code]; + uint64_t expected = ((uint64_t)addr << 10) | ((uint64_t)bus << 7) | (uint64_t)len; + return actual == expected; +} + +#define MSG_MATCHES_SELECT(_msg, _addr, _bus, _len, NAME, ...) NAME +#define msg_matches(...) MSG_MATCHES_SELECT(__VA_ARGS__, msg_matches_addr_bus_len, msg_matches_addr_bus)(__VA_ARGS__) + // compute the time elapsed (in microseconds) from 2 counter samples // case where ts < ts_last is ok: overflow is properly re-casted into uint32_t static inline uint32_t safety_get_ts_elapsed(uint32_t ts, uint32_t ts_last) { diff --git a/opendbc_repo/opendbc/safety/ignition.h b/opendbc_repo/opendbc/safety/ignition.h index 2470530a7..7f499d629 100644 --- a/opendbc_repo/opendbc/safety/ignition.h +++ b/opendbc_repo/opendbc/safety/ignition.h @@ -4,6 +4,7 @@ #include #include "opendbc/safety/can.h" +#include "opendbc/safety/helpers.h" bool ignition_can = false; uint32_t ignition_can_cnt = 0U; @@ -77,10 +78,51 @@ void ignition_can_hook(const CANPacket_t *msg) { } } - // TODO: this is too loose, Teslas have 0x222 - // body v2 exception - // if (((msg->bus == 0U) || (msg->bus == 2U)) && (msg->addr == 0x222U)) { - // ignition_can = true; - // ignition_can_cnt = 0U; - // } + // Rivian R1S/T GEN1 exception + if (msg_matches(msg, 0x152U, 0U, 8U)) { + // 0x152 overlaps with Subaru pre-global which has this bit as the high beam + int counter = msg->data[1] & 0xFU; // max is only 14 + + static int prev_counter_rivian = -1; + if ((counter == ((prev_counter_rivian + 1) % 15)) && (prev_counter_rivian != -1)) { + // VDM_OutputSignals->VDM_EpasPowerMode + ignition_can = ((msg->data[7] >> 4U) & 0x3U) == 1U; // VDM_EpasPowerMode_Drive_On=1 + ignition_can_cnt = 0U; + } + prev_counter_rivian = counter; + } + + // Tesla Model 3/Y exception + if (msg_matches(msg, 0x221U, 0U, 8U)) { + // 0x221 overlaps with Rivian which has random data on byte 0 + int counter = msg->data[6] >> 4; + + static int prev_counter_tesla = -1; + if ((counter == ((prev_counter_tesla + 1) % 16)) && (prev_counter_tesla != -1)) { + // VCFRONT_LVPowerState->VCFRONT_vehiclePowerState + int power_state = (msg->data[0] >> 5U) & 0x3U; + ignition_can = power_state == 0x3; // VEHICLE_POWER_STATE_DRIVE=3 + ignition_can_cnt = 0U; + } + prev_counter_tesla = counter; + } + + // Mazda exception + if (msg_matches(msg, 0x9EU, 0U, 8U)) { + ignition_can = (msg->data[0] >> 5) == 0x6U; + ignition_can_cnt = 0U; + } + + // Volkswagen MEB exception + if (msg_matches(msg, 0x3C0U, 0U, 4U)) { + int counter = msg->data[1] & 0xFU; + + static int prev_counter_vw_meb = -1; + if ((counter == ((prev_counter_vw_meb + 1) % 16)) && (prev_counter_vw_meb != -1)) { + // Klemmen_Status_01->ZAS_Kl_15 + ignition_can = ((msg->data[2] >> 1) & 1U) != 0U; + ignition_can_cnt = 0U; + } + prev_counter_vw_meb = counter; + } } diff --git a/opendbc_repo/opendbc/safety/modes/body.h b/opendbc_repo/opendbc/safety/modes/body.h index e3d5c212c..00d05bd0e 100644 --- a/opendbc_repo/opendbc/safety/modes/body.h +++ b/opendbc_repo/opendbc/safety/modes/body.h @@ -2,10 +2,28 @@ #include "opendbc/safety/declarations.h" -static void body_rx_hook(const CANPacket_t *msg) { - if (msg->addr == 0x201U) { - controls_allowed = true; +static uint8_t body_get_counter(const CANPacket_t *msg) { + return msg->data[6] & 0xFU; +} + +static uint32_t body_get_checksum(const CANPacket_t *msg) { + return msg->data[7]; +} + +static uint32_t body_compute_checksum(const CANPacket_t *msg) { + uint8_t checksum = 0xFFU; + int len = GET_LEN(msg); + for (int i = len - 2; i >= 0; i--) { + checksum = crc8_update(checksum, msg->data[i], 0xD5U); } + return checksum; +} + +static void body_rx_hook(const CANPacket_t *msg) { + SAFETY_UNUSED(msg); + + // controls allowed as soon as RX is valid + controls_allowed = true; } static bool body_tx_hook(const CANPacket_t *msg) { @@ -17,7 +35,7 @@ static bool body_tx_hook(const CANPacket_t *msg) { // Allow going into CAN flashing mode even if controls are not allowed bool flash_msg = (msg->addr == 0x250U) && (GET_LEN(msg) == 8U); - if (!controls_allowed && (GET_BYTES(msg, 0, 4) == 0xdeadfaceU) && (GET_BYTES(msg, 4, 4) == 0x0ab00b1eU) && flash_msg) { + if (!controls_allowed && flash_msg && (GET_BYTES_64_LE(msg, 0, 8) == 0x0AB00B1EDEADFACEULL)) { tx = true; } @@ -26,11 +44,15 @@ static bool body_tx_hook(const CANPacket_t *msg) { static safety_config body_init(uint16_t param) { static RxCheck body_rx_checks[] = { - {.msg = {{0x201, 0, 8, 100U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, + {.msg = {{0x201, 0, 8, 100U, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, }; - static const CanMsg BODY_TX_MSGS[] = {{0x250, 0, 8, .check_relay = false}, {0x250, 0, 6, .check_relay = false}, {0x251, 0, 5, .check_relay = false}, // body - {0x1, 0, 8, .check_relay = false}}; // CAN flasher + static const CanMsg BODY_TX_MSGS[] = { + {0x250, 0, 8, .check_relay = false}, + {0x250, 0, 6, .check_relay = false}, + {0x251, 0, 5, .check_relay = false}, + {0x1, 0, 8, .check_relay = false}, // CAN flasher + }; SAFETY_UNUSED(param); safety_config ret = BUILD_SAFETY_CFG(body_rx_checks, BODY_TX_MSGS); @@ -42,4 +64,7 @@ const safety_hooks body_hooks = { .init = body_init, .rx = body_rx_hook, .tx = body_tx_hook, + .get_counter = body_get_counter, + .get_checksum = body_get_checksum, + .compute_checksum = body_compute_checksum, }; diff --git a/opendbc_repo/opendbc/safety/modes/byd.h b/opendbc_repo/opendbc/safety/modes/byd.h new file mode 100644 index 000000000..df00939bd --- /dev/null +++ b/opendbc_repo/opendbc/safety/modes/byd.h @@ -0,0 +1,119 @@ +#pragma once + +#include "opendbc/safety/declarations.h" + +static uint8_t byd_get_counter(const CANPacket_t *msg) { + // Speed uses the high nibble; cruise status uses the low nibble. + return (msg->addr == 0x1F0U) ? (msg->data[6] >> 4) : (msg->data[6] & 0xFU); +} + +static uint32_t byd_get_checksum(const CANPacket_t *msg) { + return msg->data[7]; +} + +static uint32_t byd_compute_checksum(const CANPacket_t *msg) { + uint8_t sum = 0; + for (int i = 0; i < 7; i++) { + sum += msg->data[i]; + } + return 0xFFU - sum; +} + +static void byd_rx_hook(const CANPacket_t *msg) { + if (msg->bus == 0U) { + // Steering angle: 0.1 deg/LSB, signed + if (msg->addr == 0x11FU) { + int angle_meas_new = to_signed((msg->data[1] << 8) | msg->data[0], 16); // STEER_ANGLE_2 + update_sample(&angle_meas, angle_meas_new); + } + + // Vehicle speed: 0.1 kph/LSB + if (msg->addr == 0x1F0U) { + int speed = (msg->data[1] << 8) | msg->data[0]; // WHEELSPEED_CLEAN + vehicle_moving = speed > 0; + UPDATE_VEHICLE_SPEED(speed * 0.1 * KPH_TO_MS); + } + + // Gas and brake pressed + if (msg->addr == 0x242U) { + brake_pressed = (msg->data[4] >> 5) & 0x1U; // BRAKE_PRESSED + gas_pressed = (msg->data[3] & 0x7FU) > 0U; // RAW_THROTTLE + } + } + + if (msg->bus == 2U) { + // Cruise state + if (msg->addr == 0x32DU) { + // ACC_STATE: 0=OFF, 2=ACC_ON, 3=ACC_ACTIVE, 5=FORCE_ACCEL, 7=ERROR + uint8_t acc_state = (msg->data[2] >> 3) & 0x7U; + bool acc_on = (acc_state == 3U) || (acc_state == 5U); + pcm_cruise_check(acc_on); + } + } +} + +static bool byd_tx_hook(const CANPacket_t *msg) { + const AngleSteeringLimits BYD_STEERING_LIMITS = { + .max_angle = 3900, // 390 deg + .angle_deg_to_can = 10, + .frequency = 50U, + }; + + // NOTE: based off BYD_ATTO_3 to match openpilot + const AngleSteeringParams BYD_STEERING_PARAMS = { + .slip_factor = -0.0006166479109059387, // calc_slip_factor(VM) + .steer_ratio = 14.8, + .wheelbase = 2.72, + }; + + bool tx = true; + + // Steering control: 0.1 deg/LSB, signed + if (msg->addr == 0x1E2U) { + int desired_angle = to_signed((msg->data[4] << 8) | msg->data[3], 16); // STEER_ANGLE + bool steer_req = ((msg->data[2] >> 5) & 0x1U) != 0U; // STEER_REQ + + if (steer_angle_cmd_checks_vm(desired_angle, steer_req, BYD_STEERING_LIMITS, BYD_STEERING_PARAMS)) { + tx = false; + } + } + + // Only allow cancel (ACC_ON_BTN) while stock cruise is engaged, or button release. + if (msg->addr == 0x3B0U) { + bool other_buttons = ((msg->data[0] & 0x58U) != 0U) || // SET, RES, LKAS_ON + ((msg->data[1] & 0x80U) != 0U) || // DEC_DISTANCE + ((msg->data[2] & 0x1U) != 0U); // INC_DISTANCE + bool cancel = (msg->data[2] & 0x8U) != 0U; // ACC_ON_BTN + tx = !other_buttons && (!cancel || cruise_engaged_prev); + } + + return tx; +} + +static safety_config byd_init(uint16_t param) { + SAFETY_UNUSED(param); + + static const CanMsg BYD_TX_MSGS[] = { + {0x1E2, 0, 8, .check_relay = true}, // STEERING_MODULE_ADAS (lateral steering command) + {0x316, 0, 8, .check_relay = true}, // LKAS_HUD_ADAS (dash HUD) + {0x3B0, 0, 8, .check_relay = false}, // PCM_BUTTONS (cruise cancel button spoof) + }; + + static RxCheck byd_rx_checks[] = { + {.msg = {{0x11F, 0, 5, 100U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // STEER_MODULE_2 (steering angle) + {.msg = {{0x1F0, 0, 8, 50U, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // WHEELSPEED_CLEAN (vehicle speed) + {.msg = {{0x242, 0, 8, 50U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // DRIVE_STATE (gas and brake pressed) + {.msg = {{0x32D, 2, 8, 50U, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // ACC_HUD_ADAS (cruise state) + }; + + return BUILD_SAFETY_CFG(byd_rx_checks, BYD_TX_MSGS); +} + +const safety_hooks byd_hooks = { + .init = byd_init, + .rx = byd_rx_hook, + .tx = byd_tx_hook, + .get_counter = byd_get_counter, + .get_checksum = byd_get_checksum, + .compute_checksum = byd_compute_checksum, +}; diff --git a/opendbc_repo/opendbc/safety/modes/chrysler.h b/opendbc_repo/opendbc/safety/modes/chrysler.h index c374b9760..684734861 100644 --- a/opendbc_repo/opendbc/safety/modes/chrysler.h +++ b/opendbc_repo/opendbc/safety/modes/chrysler.h @@ -52,21 +52,20 @@ static ChryslerPlatform chrysler_platform; #define CHRYSLER_ADDR(name) ((uint32_t)((chrysler_platform == CHRYSLER_RAM_DT) ? CHRYSLER_RAM_DT_##name : \ ((chrysler_platform == CHRYSLER_RAM_HD) ? CHRYSLER_RAM_HD_##name : CHRYSLER_##name))) - static uint8_t chrysler_get_counter(const CANPacket_t *msg) { return (uint8_t)(msg->data[6] >> 4); } static void chrysler_rx_hook(const CANPacket_t *msg) { // Measured EPS torque - if ((msg->bus == 0U) && (msg->addr == CHRYSLER_ADDR(EPS_2))) { + if (msg_matches(msg, CHRYSLER_ADDR(EPS_2), 0U)) { int torque_meas_new = ((msg->data[4] & 0x7U) << 8) + msg->data[5] - 1024U; update_sample(&torque_meas, torque_meas_new); } // enter controls on rising edge of ACC, exit controls on ACC off const unsigned int das_3_bus = (chrysler_platform == CHRYSLER_PACIFICA) ? 0U : 2U; - if ((msg->bus == das_3_bus) && (msg->addr == CHRYSLER_ADDR(DAS_3))) { + if (msg_matches(msg, CHRYSLER_ADDR(DAS_3), das_3_bus)) { bool cruise_engaged = GET_BIT(msg, 21U); pcm_cruise_check(cruise_engaged); acc_main_on = GET_BIT(msg, 20U); @@ -74,22 +73,22 @@ static void chrysler_rx_hook(const CANPacket_t *msg) { // TODO: use the same message for both // update vehicle moving - if ((chrysler_platform != CHRYSLER_PACIFICA) && (msg->bus == 0U) && (msg->addr == CHRYSLER_ADDR(ESP_8))) { + if ((chrysler_platform != CHRYSLER_PACIFICA) && msg_matches(msg, CHRYSLER_ADDR(ESP_8), 0U)) { vehicle_moving = ((msg->data[4] << 8) + msg->data[5]) != 0U; } - if ((chrysler_platform == CHRYSLER_PACIFICA) && (msg->bus == 0U) && (msg->addr == 514U)) { + if ((chrysler_platform == CHRYSLER_PACIFICA) && msg_matches(msg, 514U, 0U)) { int speed_l = (msg->data[0] << 4) + (msg->data[1] >> 4); int speed_r = (msg->data[2] << 4) + (msg->data[3] >> 4); - vehicle_moving = (speed_l != 0) || (speed_r != 0); + vehicle_moving = (speed_l | speed_r) != 0; } // exit controls on rising edge of gas press - if ((msg->bus == 0U) && (msg->addr == CHRYSLER_ADDR(ECM_5))) { + if (msg_matches(msg, CHRYSLER_ADDR(ECM_5), 0U)) { gas_pressed = msg->data[0U] != 0U; } // exit controls on rising edge of brake press - if ((msg->bus == 0U) && (msg->addr == CHRYSLER_ADDR(ESP_1))) { + if (msg_matches(msg, CHRYSLER_ADDR(ESP_1), 0U)) { brake_pressed = ((msg->data[0U] & 0xFU) >> 2U) == 1U; } diff --git a/opendbc_repo/opendbc/safety/modes/chrysler_common.h b/opendbc_repo/opendbc/safety/modes/chrysler_common.h index 29999b00e..5e99acedd 100644 --- a/opendbc_repo/opendbc/safety/modes/chrysler_common.h +++ b/opendbc_repo/opendbc/safety/modes/chrysler_common.h @@ -6,34 +6,10 @@ static uint32_t chrysler_get_checksum(const CANPacket_t *msg) { } static uint32_t chrysler_compute_checksum(const CANPacket_t *msg) { - // TODO: clean this up - // http://illmatics.com/Remote%20Car%20Hacking.pdf uint8_t checksum = 0xFFU; int len = GET_LEN(msg); for (int j = 0; j < (len - 1); j++) { - uint8_t shift = 0x80U; - uint8_t curr = (uint8_t)msg->data[j]; - for (int i=0; i<8; i++) { - uint8_t bit_sum = curr & shift; - uint8_t temp_chk = checksum & 0x80U; - if (bit_sum != 0U) { - bit_sum = 0x1C; - if (temp_chk != 0U) { - bit_sum = 1; - } - checksum = checksum << 1; - temp_chk = checksum | 1U; - bit_sum ^= temp_chk; - } else { - if (temp_chk != 0U) { - bit_sum = 0x1D; - } - checksum = checksum << 1; - bit_sum ^= checksum; - } - checksum = bit_sum; - shift = shift >> 1; - } + checksum = crc8_update(checksum, msg->data[j], 0x1DU); } return (uint8_t)(~checksum); } diff --git a/opendbc_repo/opendbc/safety/modes/chrysler_cusw.h b/opendbc_repo/opendbc/safety/modes/chrysler_cusw.h index a9fb94601..f3009e9da 100644 --- a/opendbc_repo/opendbc/safety/modes/chrysler_cusw.h +++ b/opendbc_repo/opendbc/safety/modes/chrysler_cusw.h @@ -1,6 +1,5 @@ #include "opendbc/safety/modes/chrysler_common.h" - static safety_config chrysler_cusw_init(uint16_t param) { SAFETY_UNUSED(param); @@ -22,33 +21,31 @@ static safety_config chrysler_cusw_init(uint16_t param) { } static void chrysler_cusw_rx_hook(const CANPacket_t *msg) { - if (msg->bus == 0U) { - if (msg->addr == 0x1ECU) { - // Signal: EPS_STATUS.TORQUE_MOTOR - int torque_meas_new = ((msg->data[3] & 0xFU) << 8) + msg->data[4] - 2048U; - update_sample(&torque_meas, torque_meas_new); - } + if (msg_matches(msg, 0x1ECU, 0U)) { + // Signal: EPS_STATUS.TORQUE_MOTOR + int torque_meas_new = ((msg->data[3] & 0xFU) << 8) + msg->data[4] - 2048U; + update_sample(&torque_meas, torque_meas_new); + } - if (msg->addr == 0x2ECU) { - // Signal: ACC_CONTROL.ACC_ACTIVE - bool cruise_engaged = GET_BIT(msg, 7U); - pcm_cruise_check(cruise_engaged); - } + if (msg_matches(msg, 0x2ECU, 0U)) { + // Signal: ACC_CONTROL.ACC_ACTIVE + bool cruise_engaged = GET_BIT(msg, 7U); + pcm_cruise_check(cruise_engaged); + } - if (msg->addr == 0x1E4U) { - // Signal: BRAKE_1.VEHICLE_SPEED - vehicle_moving = (((msg->data[4] & 0x7U) << 8) + msg->data[5]) != 0U; - } + if (msg_matches(msg, 0x1E4U, 0U)) { + // Signal: BRAKE_1.VEHICLE_SPEED + vehicle_moving = (((msg->data[4] & 0x7U) << 8) + msg->data[5]) != 0U; + } - if (msg->addr == 0x1FEU) { - // Signal: ACCEL_GAS.GAS_HUMAN - gas_pressed = msg->data[1] != 0U; - } + if (msg_matches(msg, 0x1FEU, 0U)) { + // Signal: ACCEL_GAS.GAS_HUMAN + gas_pressed = msg->data[1] != 0U; + } - if (msg->addr == 0x1E8U) { - // Signal: BRAKE_3.DRIVER_BRAKE_SWITCH - brake_pressed = GET_BIT(msg, 18U); - } + if (msg_matches(msg, 0x1E8U, 0U)) { + // Signal: BRAKE_3.DRIVER_BRAKE_SWITCH + brake_pressed = GET_BIT(msg, 18U); } } diff --git a/opendbc_repo/opendbc/safety/modes/defaults.h b/opendbc_repo/opendbc/safety/modes/defaults.h index 5f9d93761..56f2ba8fe 100644 --- a/opendbc_repo/opendbc/safety/modes/defaults.h +++ b/opendbc_repo/opendbc/safety/modes/defaults.h @@ -10,10 +10,9 @@ void default_rx_hook(const CANPacket_t *msg) { // GCOV_EXCL_STOP // *** no output safety mode *** - static safety_config nooutput_init(uint16_t param) { SAFETY_UNUSED(param); - return (safety_config){NULL, 0, NULL, 0, true}; // NOLINT(readability/braces) + return (safety_config){NULL, 0, NULL, 0, true}; // NOLINT(readability/braces) } // GCOV_EXCL_START @@ -36,7 +35,7 @@ static safety_config alloutput_init(uint16_t param) { const uint16_t ALLOUTPUT_PARAM_PASSTHROUGH = 1; controls_allowed = true; bool alloutput_passthrough = GET_FLAG(param, ALLOUTPUT_PARAM_PASSTHROUGH); - return (safety_config){NULL, 0, NULL, 0, !alloutput_passthrough}; // NOLINT(readability/braces) + return (safety_config){NULL, 0, NULL, 0, !alloutput_passthrough}; // NOLINT(readability/braces) } static bool alloutput_tx_hook(const CANPacket_t *msg) { diff --git a/opendbc_repo/opendbc/safety/modes/elm327.h b/opendbc_repo/opendbc/safety/modes/elm327.h index dbcc06012..eb8f2b06b 100644 --- a/opendbc_repo/opendbc/safety/modes/elm327.h +++ b/opendbc_repo/opendbc/safety/modes/elm327.h @@ -29,6 +29,7 @@ static bool elm327_tx_hook(const CANPacket_t *msg) { tx = false; } } + return tx; } diff --git a/opendbc_repo/opendbc/safety/modes/ford.h b/opendbc_repo/opendbc/safety/modes/ford.h index f71a0365a..a448442c4 100644 --- a/opendbc_repo/opendbc/safety/modes/ford.h +++ b/opendbc_repo/opendbc/safety/modes/ford.h @@ -26,10 +26,10 @@ static uint8_t ford_get_counter(const CANPacket_t *msg) { if (msg->addr == FORD_BrakeSysFeatures) { // Signal: VehVActlBrk_No_Cnt cnt = (msg->data[2] >> 2) & 0xFU; - } else if (msg->addr == FORD_Yaw_Data_FD1) { + } + if (msg->addr == FORD_Yaw_Data_FD1) { // Signal: VehRollYaw_No_Cnt cnt = msg->data[5]; - } else { } return cnt; } @@ -39,10 +39,10 @@ static uint32_t ford_get_checksum(const CANPacket_t *msg) { if (msg->addr == FORD_BrakeSysFeatures) { // Signal: VehVActlBrk_No_Cs chksum = msg->data[3]; - } else if (msg->addr == FORD_Yaw_Data_FD1) { + } + if (msg->addr == FORD_Yaw_Data_FD1) { // Signal: VehRollYawW_No_Cs chksum = msg->data[4]; - } else { } return chksum; } @@ -54,14 +54,14 @@ static uint32_t ford_compute_checksum(const CANPacket_t *msg) { chksum += msg->data[2] >> 6; // VehVActlBrk_D_Qf chksum += (msg->data[2] >> 2) & 0xFU; // VehVActlBrk_No_Cnt chksum = 0xFFU - chksum; - } else if (msg->addr == FORD_Yaw_Data_FD1) { + } + if (msg->addr == FORD_Yaw_Data_FD1) { chksum += msg->data[0] + msg->data[1]; // VehRol_W_Actl chksum += msg->data[2] + msg->data[3]; // VehYaw_W_Actl chksum += msg->data[5]; // VehRollYaw_No_Cnt chksum += msg->data[6] >> 6; // VehRolWActl_D_Qf chksum += (msg->data[6] >> 4) & 0x3U; // VehYawWActl_D_Qf chksum = 0xFFU - chksum; - } else { } return chksum; } @@ -70,11 +70,12 @@ static bool ford_get_quality_flag_valid(const CANPacket_t *msg) { bool valid = false; if (msg->addr == FORD_BrakeSysFeatures) { valid = (msg->data[2] >> 6) == 0x3U; // VehVActlBrk_D_Qf - } else if (msg->addr == FORD_EngVehicleSpThrottle2) { + } + if (msg->addr == FORD_EngVehicleSpThrottle2) { valid = ((msg->data[4] >> 5) & 0x3U) == 0x3U; // VehVActlEng_D_Qf - } else if (msg->addr == FORD_Yaw_Data_FD1) { + } + if (msg->addr == FORD_Yaw_Data_FD1) { valid = ((msg->data[6] >> 4) & 0x3U) == 0x3U; // VehYawWActl_D_Qf - } else { } return valid; } @@ -96,60 +97,58 @@ static const CurvatureSteeringLimits FORD_STEERING_LIMITS = { }; static void ford_rx_hook(const CANPacket_t *msg) { - if (msg->bus == FORD_MAIN_BUS) { - // Update in motion state from standstill signal - if (msg->addr == FORD_DesiredTorqBrk) { - // Signal: VehStop_D_Stat - vehicle_moving = ((msg->data[3] >> 3) & 0x3U) != 1U; - } + // Update in motion state from standstill signal + if (msg_matches(msg, FORD_DesiredTorqBrk, FORD_MAIN_BUS)) { + // Signal: VehStop_D_Stat + vehicle_moving = ((msg->data[3] >> 3) & 0x3U) != 1U; + } - // Update vehicle speed - if (msg->addr == FORD_BrakeSysFeatures) { - // Signal: Veh_V_ActlBrk - UPDATE_VEHICLE_SPEED(((msg->data[0] << 8) | msg->data[1]) * 0.01 * KPH_TO_MS); - } + // Update vehicle speed + if (msg_matches(msg, FORD_BrakeSysFeatures, FORD_MAIN_BUS)) { + // Signal: Veh_V_ActlBrk + UPDATE_VEHICLE_SPEED(((msg->data[0] << 8) | msg->data[1]) * 0.01 * KPH_TO_MS); + } - // Check vehicle speed against a second source - if (msg->addr == FORD_EngVehicleSpThrottle2) { - // Disable controls if speeds from ABS and PCM ECUs are too far apart. - // Signal: Veh_V_ActlEng - float filtered_pcm_speed = ((msg->data[6] << 8) | msg->data[7]) * 0.01 * KPH_TO_MS; - UPDATE_VEHICLE_SPEED_2(filtered_pcm_speed); - } + // Check vehicle speed against a second source + if (msg_matches(msg, FORD_EngVehicleSpThrottle2, FORD_MAIN_BUS)) { + // Disable controls if speeds from ABS and PCM ECUs are too far apart. + // Signal: Veh_V_ActlEng + float filtered_pcm_speed = ((msg->data[6] << 8) | msg->data[7]) * 0.01 * KPH_TO_MS; + UPDATE_VEHICLE_SPEED_2(filtered_pcm_speed); + } - // Update vehicle yaw rate - if (msg->addr == FORD_Yaw_Data_FD1) { - // FIXME: safety can receive yaw before new vehicle speed, it should recompute meas on either received - // Signal: VehYaw_W_Actl - // TODO: we should use the speed which results in the closest angle measurement to the desired angle - float ford_yaw_rate = (((msg->data[2] << 8U) | msg->data[3]) * 0.0002) - 6.5; - float current_curvature = ford_yaw_rate / SAFETY_MAX(vehicle_speed.values[0] / VEHICLE_SPEED_FACTOR, 0.1); - // convert current curvature into units on CAN for comparison with desired curvature - update_sample(&curvature_state.meas, ROUND(current_curvature * FORD_STEERING_LIMITS.curvature_to_can)); - } + // Update vehicle yaw rate + if (msg_matches(msg, FORD_Yaw_Data_FD1, FORD_MAIN_BUS)) { + // FIXME: safety can receive yaw before new vehicle speed, it should recompute meas on either received + // Signal: VehYaw_W_Actl + // TODO: we should use the speed which results in the closest angle measurement to the desired angle + float ford_yaw_rate = (((msg->data[2] << 8U) | msg->data[3]) * 0.0002) - 6.5; + float current_curvature = ford_yaw_rate / SAFETY_MAX(vehicle_speed.values[0] / VEHICLE_SPEED_FACTOR, 0.1); + // convert current curvature into units on CAN for comparison with desired curvature + update_sample(&curvature_state.meas, ROUND(current_curvature * FORD_STEERING_LIMITS.curvature_to_can)); + } - // Update gas pedal - if (msg->addr == FORD_EngVehicleSpThrottle) { - // Pedal position: (0.1 * val) in percent - // Signal: ApedPos_Pc_ActlArb - gas_pressed = (((msg->data[0] & 0x03U) << 8) | msg->data[1]) > 0U; - } + // Update gas pedal + if (msg_matches(msg, FORD_EngVehicleSpThrottle, FORD_MAIN_BUS)) { + // Pedal position: (0.1 * val) in percent + // Signal: ApedPos_Pc_ActlArb + gas_pressed = (((msg->data[0] & 0x03U) << 8) | msg->data[1]) > 0U; + } - // Update brake pedal and cruise state - if (msg->addr == FORD_EngBrakeData) { - // Signal: BpedDrvAppl_D_Actl - brake_pressed = ((msg->data[0] >> 4) & 0x3U) == 2U; + // Update brake pedal and cruise state + if (msg_matches(msg, FORD_EngBrakeData, FORD_MAIN_BUS)) { + // Signal: BpedDrvAppl_D_Actl + brake_pressed = ((msg->data[0] >> 4) & 0x3U) == 2U; - // Signal: CcStat_D_Actl - unsigned int cruise_state = msg->data[1] & 0x07U; - bool cruise_engaged = (cruise_state == 4U) || (cruise_state == 5U); - pcm_cruise_check(cruise_engaged); - acc_main_on = (cruise_state == 3U) || cruise_engaged; - } + // Signal: CcStat_D_Actl + unsigned int cruise_state = msg->data[1] & 0x07U; + bool cruise_engaged = (cruise_state == 4U) || (cruise_state == 5U); + pcm_cruise_check(cruise_engaged); + acc_main_on = (cruise_state == 3U) || cruise_engaged; + } - if (msg->addr == FORD_Steering_Data_FD1) { - mads_button_press = GET_BIT(msg, 40U) ? MADS_BUTTON_PRESSED : MADS_BUTTON_NOT_PRESSED; - } + if (msg_matches(msg, FORD_Steering_Data_FD1, FORD_MAIN_BUS)) { + mads_button_press = GET_BIT(msg, 40U) ? MADS_BUTTON_PRESSED : MADS_BUTTON_NOT_PRESSED; } } @@ -182,7 +181,7 @@ static bool ford_tx_hook(const CANPacket_t *msg) { bool cmbb_deny = (msg->data[4] >> 5) & 1U; // Signal: AccBrkPrchg_B_Rq & AccBrkDecel_B_Rq - bool brake_actuation = ((msg->data[6] >> 6) & 1U) || ((msg->data[6] >> 7) & 1U); + bool brake_actuation = (msg->data[6] & 0xC0U) != 0U; bool violation = false; violation |= longitudinal_accel_checks(accel, FORD_LONG_LIMITS); @@ -190,7 +189,7 @@ static bool ford_tx_hook(const CANPacket_t *msg) { violation |= longitudinal_gas_checks(gas_pred, FORD_LONG_LIMITS); // Safety check for stock AEB - violation |= cmbb_deny; // do not prevent stock AEB actuation + violation |= cmbb_deny; // do not prevent stock AEB actuation violation |= !get_longitudinal_allowed() && brake_actuation; diff --git a/opendbc_repo/opendbc/safety/modes/gm.h b/opendbc_repo/opendbc/safety/modes/gm.h index 832ea1b96..109b961c0 100644 --- a/opendbc_repo/opendbc/safety/modes/gm.h +++ b/opendbc_repo/opendbc/safety/modes/gm.h @@ -39,73 +39,71 @@ static bool gm_non_acc = false; static void gm_rx_hook(const CANPacket_t *msg) { const int GM_STANDSTILL_THRSLD = 10; // 0.311kph - if (msg->bus == 0U) { - if (msg->addr == 0x184U) { - int torque_driver_new = ((msg->data[6] & 0x7U) << 8) | msg->data[7]; - torque_driver_new = to_signed(torque_driver_new, 11); - // update array of samples - update_sample(&torque_driver, torque_driver_new); + if (msg_matches(msg, 0x184U, 0U)) { + int torque_driver_new = ((msg->data[6] & 0x7U) << 8) | msg->data[7]; + torque_driver_new = to_signed(torque_driver_new, 11); + // update array of samples + update_sample(&torque_driver, torque_driver_new); + } + + // sample rear wheel speeds + if (msg_matches(msg, 0x34AU, 0U)) { + int left_rear_speed = (msg->data[0] << 8) | msg->data[1]; + int right_rear_speed = (msg->data[2] << 8) | msg->data[3]; + vehicle_moving = (left_rear_speed > GM_STANDSTILL_THRSLD) || (right_rear_speed > GM_STANDSTILL_THRSLD); + } + + // ACC steering wheel buttons (GM_CAM is tied to the PCM) + if (msg_matches(msg, 0x1E1U, 0U) && !gm_pcm_cruise) { + int button = (msg->data[5] & 0x70U) >> 4; + + // enter controls on falling edge of set or rising edge of resume (avoids fault) + bool set = (button != GM_BTN_SET) && (cruise_button_prev == GM_BTN_SET); + bool res = (button == GM_BTN_RESUME) && (cruise_button_prev != GM_BTN_RESUME); + if (set || res) { + controls_allowed = true; } - // sample rear wheel speeds - if (msg->addr == 0x34AU) { - int left_rear_speed = (msg->data[0] << 8) | msg->data[1]; - int right_rear_speed = (msg->data[2] << 8) | msg->data[3]; - vehicle_moving = (left_rear_speed > GM_STANDSTILL_THRSLD) || (right_rear_speed > GM_STANDSTILL_THRSLD); + // exit controls on cancel press + if (button == GM_BTN_CANCEL) { + controls_allowed = false; } - // ACC steering wheel buttons (GM_CAM is tied to the PCM) - if ((msg->addr == 0x1E1U) && !gm_pcm_cruise) { - int button = (msg->data[5] & 0x70U) >> 4; + cruise_button_prev = button; + } - // enter controls on falling edge of set or rising edge of resume (avoids fault) - bool set = (button != GM_BTN_SET) && (cruise_button_prev == GM_BTN_SET); - bool res = (button == GM_BTN_RESUME) && (cruise_button_prev != GM_BTN_RESUME); - if (set || res) { - controls_allowed = true; - } + // Reference for brake pressed signals: + // https://github.com/commaai/openpilot/blob/master/selfdrive/car/gm/carstate.py + if (msg_matches(msg, 0xBEU, 0U) && (gm_hw == GM_ASCM)) { + brake_pressed = msg->data[1] >= 8U; + } - // exit controls on cancel press - if (button == GM_BTN_CANCEL) { - controls_allowed = false; - } + if (msg_matches(msg, 0xC9U, 0U) && (gm_hw == GM_CAM)) { + brake_pressed = GET_BIT(msg, 40U); + } - cruise_button_prev = button; - } + if (msg_matches(msg, 0x1C4U, 0U)) { + gas_pressed = msg->data[5] != 0U; - // Reference for brake pressed signals: - // https://github.com/commaai/openpilot/blob/master/selfdrive/car/gm/carstate.py - if ((msg->addr == 0xBEU) && (gm_hw == GM_ASCM)) { - brake_pressed = msg->data[1] >= 8U; - } - - if ((msg->addr == 0xC9U) && (gm_hw == GM_CAM)) { - brake_pressed = GET_BIT(msg, 40U); - } - - if (msg->addr == 0x1C4U) { - gas_pressed = msg->data[5] != 0U; - - // enter controls on rising edge of ACC, exit controls when ACC off - if (gm_pcm_cruise && !gm_non_acc) { - bool cruise_engaged = (msg->data[1] >> 5) != 0U; - pcm_cruise_check(cruise_engaged); - } - } - - if (msg->addr == 0xBDU) { - regen_braking = (msg->data[0] >> 4) != 0U; - } - - if (msg->addr == 0xC9U) { - acc_main_on = GET_BIT(msg, 29U); - } - - if (msg->addr == 0x3D1U) { - bool cruise_engaged = GET_BIT(msg, 39U); + // enter controls on rising edge of ACC, exit controls when ACC off + if (gm_pcm_cruise && !gm_non_acc) { + bool cruise_engaged = (msg->data[1] >> 5) != 0U; pcm_cruise_check(cruise_engaged); } } + + if (msg_matches(msg, 0xBDU, 0U)) { + regen_braking = (msg->data[0] >> 4) != 0U; + } + + if (msg_matches(msg, 0xC9U, 0U)) { + acc_main_on = GET_BIT(msg, 29U); + } + + if (msg_matches(msg, 0x3D1U, 0U)) { + bool cruise_engaged = GET_BIT(msg, 39U); + pcm_cruise_check(cruise_engaged); + } } static bool gm_tx_hook(const CANPacket_t *msg) { @@ -185,10 +183,18 @@ static safety_config gm_init(uint16_t param) { .max_brake = 400, }; - static const CanMsg GM_ASCM_TX_MSGS[] = {{0x180, 0, 4, .check_relay = true}, {0x409, 0, 7, .check_relay = false}, {0x40A, 0, 7, .check_relay = false}, {0x2CB, 0, 8, .check_relay = true}, {0x370, 0, 6, .check_relay = false}, // pt bus - {0xA1, 1, 7, .check_relay = false}, {0x306, 1, 8, .check_relay = false}, {0x308, 1, 7, .check_relay = false}, {0x310, 1, 2, .check_relay = false}, // obs bus - {0x315, 2, 5, .check_relay = false}}; // ch bus - + static const CanMsg GM_ASCM_TX_MSGS[] = { + {0x180, 0, 4, .check_relay = true}, + {0x409, 0, 7, .check_relay = false}, + {0x40A, 0, 7, .check_relay = false}, + {0x2CB, 0, 8, .check_relay = true}, + {0x370, 0, 6, .check_relay = false}, + {0xA1, 1, 7, .check_relay = false}, + {0x306, 1, 8, .check_relay = false}, + {0x308, 1, 7, .check_relay = false}, + {0x310, 1, 2, .check_relay = false}, + {0x315, 2, 5, .check_relay = false}, + }; static const LongitudinalLimits GM_CAM_LONG_LIMITS = { .max_gas = 1346 * GM_GAS_TO_CAN, @@ -199,11 +205,15 @@ static safety_config gm_init(uint16_t param) { #ifdef ALLOW_DEBUG // block PSCMStatus (0x184); forwarded through openpilot to hide an alert from the camera - static const CanMsg GM_CAM_LONG_TX_MSGS[] = {{0x180, 0, 4, .check_relay = true}, {0x315, 0, 5, .check_relay = true}, {0x2CB, 0, 8, .check_relay = true}, {0x370, 0, 6, .check_relay = true}, // pt bus - {0x184, 2, 8, .check_relay = true}}; // camera bus + static const CanMsg GM_CAM_LONG_TX_MSGS[] = { + {0x180, 0, 4, .check_relay = true}, + {0x315, 0, 5, .check_relay = true}, + {0x2CB, 0, 8, .check_relay = true}, + {0x370, 0, 6, .check_relay = true}, + {0x184, 2, 8, .check_relay = true}, + }; #endif - static RxCheck gm_rx_checks[] = { GM_COMMON_RX_CHECKS }; @@ -224,8 +234,11 @@ static safety_config gm_init(uint16_t param) { GM_NON_ACC_ADDR_CHECK }; - static const CanMsg GM_CAM_TX_MSGS[] = {{0x180, 0, 4, .check_relay = true}, // pt bus - {0x1E1, 2, 7, .check_relay = false}, {0x184, 2, 8, .check_relay = true}}; // camera bus + static const CanMsg GM_CAM_TX_MSGS[] = { + {0x180, 0, 4, .check_relay = true}, + {0x1E1, 2, 7, .check_relay = false}, + {0x184, 2, 8, .check_relay = true}, + }; if (GET_FLAG(param, GM_PARAM_HW_CAM)) { gm_hw = GM_CAM; diff --git a/opendbc_repo/opendbc/safety/modes/honda.h b/opendbc_repo/opendbc/safety/modes/honda.h index 4a7e64bd4..07c404aff 100644 --- a/opendbc_repo/opendbc/safety/modes/honda.h +++ b/opendbc_repo/opendbc/safety/modes/honda.h @@ -46,7 +46,6 @@ static bool honda_nidec_hybrid = false; typedef enum {HONDA_NIDEC, HONDA_BOSCH} HondaHw; static HondaHw honda_hw = HONDA_NIDEC; - static unsigned int honda_get_pt_bus(void) { return ((honda_hw == HONDA_BOSCH) && !honda_bosch_radarless && !honda_bosch_canfd) ? 1U : 0U; } @@ -129,7 +128,7 @@ static void honda_rx_hook(const CANPacket_t *msg) { // state machine to enter and exit controls for button enabling // 0x1A6 for the ILX, 0x296 for the Civic Touring - if (((msg->addr == 0x1A6U) || (msg->addr == 0x296U)) && (msg->bus == pt_bus)) { + if (msg_matches(msg, 0x1A6U, pt_bus) || msg_matches(msg, 0x296U, pt_bus)) { int button = (msg->data[0] & 0xE0U) >> 5; int cruise_setting = (msg->data[(msg->addr == 0x296U) ? 0U : 5U] & 0x0CU) >> 2U; @@ -194,7 +193,7 @@ static void honda_rx_hook(const CANPacket_t *msg) { // disable stock Honda AEB in alternative experience if (!(alternative_experience & ALT_EXP_DISABLE_STOCK_AEB)) { - if ((msg->bus == 2U) && (msg->addr == 0x1FAU)) { + if (msg_matches(msg, 0x1FAU, 2U)) { bool honda_stock_aeb = GET_BIT(msg, 29U); int honda_stock_brake = (msg->data[0] << 2) | (msg->data[1] >> 6); @@ -216,7 +215,6 @@ static void honda_rx_hook(const CANPacket_t *msg) { } static bool honda_tx_hook(const CANPacket_t *msg) { - const LongitudinalLimits HONDA_BOSCH_LONG_LIMITS = { .max_accel = 200, // accel is used for brakes .min_accel = -350, @@ -238,7 +236,7 @@ static bool honda_tx_hook(const CANPacket_t *msg) { unsigned int bus_buttons = (honda_bosch_radarless) ? 2U : bus_pt; // the camera controls ACC on radarless Bosch cars // ACC_HUD: safety check (nidec w/o pedal) - if ((msg->addr == 0x30CU) && (msg->bus == bus_pt)) { + if (msg_matches(msg, 0x30CU, bus_pt)) { int pcm_speed = (msg->data[0] << 8) | msg->data[1]; int pcm_gas = msg->data[2]; @@ -251,7 +249,7 @@ static bool honda_tx_hook(const CANPacket_t *msg) { } // BRAKE: safety check (nidec) - if ((msg->addr == 0x1FAU) && (msg->bus == bus_pt)) { + if (msg_matches(msg, 0x1FAU, bus_pt)) { honda_brake = (msg->data[0] << 2) + ((msg->data[1] >> 6) & 0x3U); if (honda_nidec_hybrid) { @@ -267,7 +265,7 @@ static bool honda_tx_hook(const CANPacket_t *msg) { } // BRAKE/GAS: safety check (bosch) - if ((msg->addr == 0x1DFU) && (msg->bus == bus_pt)) { + if (msg_matches(msg, 0x1DFU, bus_pt)) { int accel = (msg->data[3] << 3) | ((msg->data[4] >> 5) & 0x7U); accel = to_signed(accel, 11); @@ -283,7 +281,7 @@ static bool honda_tx_hook(const CANPacket_t *msg) { } // ACCEL: safety check (radarless) - if ((msg->addr == 0x1C8U) && (msg->bus == bus_pt)) { + if (msg_matches(msg, 0x1C8U, bus_pt)) { int accel = (msg->data[0] << 4) | (msg->data[1] >> 4); accel = to_signed(accel, 12); @@ -306,7 +304,7 @@ static bool honda_tx_hook(const CANPacket_t *msg) { // Bosch supplemental control check if (msg->addr == 0xE5U) { - if ((GET_BYTES(msg, 0, 4) != 0x10800004U) || ((GET_BYTES(msg, 4, 4) & 0x00FFFFFFU) != 0x0U)) { + if ((GET_BYTES_64_LE(msg, 0, 8) & 0x00FFFFFFFFFFFFFFULL) != 0x0000000010800004ULL) { tx = false; } } @@ -314,7 +312,7 @@ static bool honda_tx_hook(const CANPacket_t *msg) { // FORCE CANCEL: safety check only relevant when spamming the cancel button in Bosch HW // ensuring that only the cancel button press is sent (VAL 2) when controls are off. // This avoids unintended engagements while still allowing resume spam - if ((msg->addr == 0x296U) && !controls_allowed && (msg->bus == bus_buttons)) { + if (msg_matches(msg, 0x296U, bus_buttons) && !controls_allowed) { if (((msg->data[0] >> 5) & 0x7U) != 2U) { tx = false; } @@ -322,7 +320,7 @@ static bool honda_tx_hook(const CANPacket_t *msg) { // Only tester present ("\x02\x3E\x80\x00\x00\x00\x00\x00") allowed on diagnostics address if (msg->addr == 0x18DAB0F1U) { - if ((GET_BYTES(msg, 0, 4) != 0x00803E02U) || (GET_BYTES(msg, 4, 4) != 0x0U)) { + if (GET_BYTES_64_LE(msg, 0, 8) != 0x0000000000803E02ULL) { tx = false; } } @@ -415,21 +413,52 @@ static safety_config honda_nidec_init(uint16_t param) { } static safety_config honda_bosch_init(uint16_t param) { - static CanMsg HONDA_BOSCH_TX_MSGS[] = {{0xE4, 0, 5, .check_relay = true}, {0xE5, 0, 8, .check_relay = true}, {0x296, 1, 4, .check_relay = false}, - {0x33D, 0, 5, .check_relay = true}, {0x33D, 0, 8, .check_relay = true}, {0x33DA, 0, 5, .check_relay = true}, {0x33DB, 0, 8, .check_relay = true}}; // Bosch + // Bosch + static CanMsg HONDA_BOSCH_TX_MSGS[] = { + {0xE4, 0, 5, .check_relay = true}, + {0xE5, 0, 8, .check_relay = true}, + {0x296, 1, 4, .check_relay = false}, + {0x33D, 0, 5, .check_relay = true}, + {0x33D, 0, 8, .check_relay = true}, + {0x33DA, 0, 5, .check_relay = true}, + {0x33DB, 0, 8, .check_relay = true}, + }; - static CanMsg HONDA_BOSCH_LONG_TX_MSGS[] = {{0xE4, 1, 5, .check_relay = true}, {0x1DF, 1, 8, .check_relay = true}, {0x1EF, 1, 8, .check_relay = false}, - {0x1FA, 1, 8, .check_relay = false}, {0x30C, 1, 8, .check_relay = false}, {0x33D, 1, 5, .check_relay = true}, {0x33D, 1, 8, .check_relay = true}, - {0x33DA, 1, 5, .check_relay = true}, {0x33DB, 1, 8, .check_relay = true}, {0x39F, 1, 8, .check_relay = false}, - {0x18DAB0F1, 1, 8, .check_relay = false}}; // Bosch w/ gas and brakes + // Bosch w/ gas and brakes + static CanMsg HONDA_BOSCH_LONG_TX_MSGS[] = { + {0xE4, 1, 5, .check_relay = true}, + {0x1DF, 1, 8, .check_relay = true}, + {0x1EF, 1, 8, .check_relay = false}, + {0x1FA, 1, 8, .check_relay = false}, + {0x30C, 1, 8, .check_relay = false}, + {0x33D, 1, 5, .check_relay = true}, + {0x33D, 1, 8, .check_relay = true}, + {0x33DA, 1, 5, .check_relay = true}, + {0x33DB, 1, 8, .check_relay = true}, + {0x39F, 1, 8, .check_relay = false}, + {0x18DAB0F1, 1, 8, .check_relay = false}, + }; - static CanMsg HONDA_RADARLESS_TX_MSGS[] = {{0xE4, 0, 5, .check_relay = true}, {0x296, 2, 4, .check_relay = false}, {0x33D, 0, 8, .check_relay = true}}; // Bosch radarless + // Bosch radarless + static CanMsg HONDA_RADARLESS_TX_MSGS[] = { + {0xE4, 0, 5, .check_relay = true}, + {0x296, 2, 4, .check_relay = false}, + {0x33D, 0, 8, .check_relay = true}, + }; - static CanMsg HONDA_RADARLESS_LONG_TX_MSGS[] = {{0xE4, 0, 5, .check_relay = true}, {0x33D, 0, 8, .check_relay = true}, {0x1C8, 0, 8, .check_relay = true}, - {0x30C, 0, 8, .check_relay = true}}; // Bosch radarless w/ gas and brakes - - static CanMsg HONDA_CANFD_TX_MSGS[] = {{0xE4, 0, 5, .check_relay = true}, {0x296, 0, 4, .check_relay = false}, {0x33D, 0, 8, .check_relay = true}}; + // Bosch radarless w/ gas and brakes + static CanMsg HONDA_RADARLESS_LONG_TX_MSGS[] = { + {0xE4, 0, 5, .check_relay = true}, + {0x33D, 0, 8, .check_relay = true}, + {0x1C8, 0, 8, .check_relay = true}, + {0x30C, 0, 8, .check_relay = true}, + }; + static CanMsg HONDA_CANFD_TX_MSGS[] = { + {0xE4, 0, 5, .check_relay = true}, + {0x296, 0, 4, .check_relay = false}, + {0x33D, 0, 8, .check_relay = true}, + }; const uint16_t HONDA_PARAM_ALT_BRAKE = 1; const uint16_t HONDA_PARAM_RADARLESS = 8; diff --git a/opendbc_repo/opendbc/safety/modes/hyundai.h b/opendbc_repo/opendbc/safety/modes/hyundai.h index b4a1fe54f..8cc7b1e92 100644 --- a/opendbc_repo/opendbc/safety/modes/hyundai.h +++ b/opendbc_repo/opendbc/safety/modes/hyundai.h @@ -71,35 +71,38 @@ static const CanMsg HYUNDAI_TX_MSGS[] = { static bool hyundai_legacy = false; static uint8_t hyundai_get_counter(const CANPacket_t *msg) { - uint8_t cnt = 0; if (msg->addr == 0x260U) { cnt = (msg->data[7] >> 4) & 0x3U; - } else if (msg->addr == 0x386U) { + } + if (msg->addr == 0x386U) { cnt = ((msg->data[3] >> 6) << 2) | (msg->data[1] >> 6); - } else if (msg->addr == 0x394U) { + } + if (msg->addr == 0x394U) { cnt = (msg->data[1] >> 5) & 0x7U; - } else if (msg->addr == 0x421U) { + } + if (msg->addr == 0x421U) { cnt = msg->data[7] & 0xFU; - } else if (msg->addr == 0x4F1U) { + } + if (msg->addr == 0x4F1U) { cnt = (msg->data[3] >> 4) & 0xFU; - } else { } return cnt; } static uint32_t hyundai_get_checksum(const CANPacket_t *msg) { - uint8_t chksum = 0; if (msg->addr == 0x260U) { chksum = msg->data[7] & 0xFU; - } else if (msg->addr == 0x386U) { + } + if (msg->addr == 0x386U) { chksum = ((msg->data[7] >> 6) << 2) | (msg->data[5] >> 6); - } else if (msg->addr == 0x394U) { + } + if (msg->addr == 0x394U) { chksum = msg->data[6] & 0xFU; - } else if (msg->addr == 0x421U) { + } + if (msg->addr == 0x421U) { chksum = msg->data[7] >> 4; - } else { } return chksum; } @@ -124,11 +127,11 @@ static uint32_t hyundai_compute_checksum(const CANPacket_t *msg) { // sum of nibbles for (int i = 0; i < 8; i++) { if ((msg->addr == 0x394U) && (i == 7)) { - continue; // exclude + continue; // exclude } uint8_t b = msg->data[i]; if (((msg->addr == 0x260U) && (i == 7)) || ((msg->addr == 0x394U) && (i == 6)) || ((msg->addr == 0x421U) && (i == 7))) { - b &= (msg->addr == 0x421U) ? 0x0FU : 0xF0U; // remove checksum + b &= (msg->addr == 0x421U) ? 0x0FU : 0xF0U; // remove checksum } chksum += (b % 16U) + (b / 16U); } @@ -139,82 +142,75 @@ static uint32_t hyundai_compute_checksum(const CANPacket_t *msg) { } static void hyundai_rx_hook(const CANPacket_t *msg) { - // SCC12 is on bus 2 for camera-based SCC cars, bus 0 on all others - if (msg->addr == 0x421U) { - if (((msg->bus == 0U) && !hyundai_camera_scc) || ((msg->bus == 2U) && hyundai_camera_scc)) { - // 2 bits: 13-14 - int cruise_engaged = (GET_BYTES(msg, 0, 4) >> 13) & 0x3U; - hyundai_common_cruise_state_check(cruise_engaged); + if (msg_matches(msg, 0x421U, hyundai_camera_scc ? 2U : 0U)) { + // 2 bits: 13-14 + int cruise_engaged = (GET_BYTES_LE(msg, 0, 4) >> 13) & 0x3U; + hyundai_common_cruise_state_check(cruise_engaged); + } + + if (msg_matches(msg, 0x420U, hyundai_camera_scc ? 2U : 0U)) { + if (!hyundai_longitudinal) { + acc_main_on = GET_BIT(msg, 0U); } } - if (msg->addr == 0x420U) { - if (((msg->bus == 0U) && !hyundai_camera_scc) || ((msg->bus == 2U) && hyundai_camera_scc)) { - if (!hyundai_longitudinal) { - acc_main_on = GET_BIT(msg, 0U); - } - } + if (msg_matches(msg, 0x251U, 0U)) { + int torque_driver_new = (GET_BYTES_LE(msg, 0, 2) & 0x7ffU) - 1024U; + // update array of samples + update_sample(&torque_driver, torque_driver_new); } - if (msg->bus == 0U) { - if (msg->addr == 0x251U) { - int torque_driver_new = (GET_BYTES(msg, 0, 2) & 0x7ffU) - 1024U; - // update array of samples - update_sample(&torque_driver, torque_driver_new); - } + if (msg_matches(msg, 0x391U, 0U)) { + mads_button_press = GET_BIT(msg, 4U) ? MADS_BUTTON_PRESSED : MADS_BUTTON_NOT_PRESSED; + } - if (msg->addr == 0x391U) { - mads_button_press = GET_BIT(msg, 4U) ? MADS_BUTTON_PRESSED : MADS_BUTTON_NOT_PRESSED; - } + // ACC steering wheel buttons + if (msg_matches(msg, 0x4F1U, 0U)) { + int cruise_button = msg->data[0] & 0x7U; + bool main_button = GET_BIT(msg, 3U); + hyundai_common_cruise_buttons_check(cruise_button, main_button); + } - // ACC steering wheel buttons - if (msg->addr == 0x4F1U) { - int cruise_button = msg->data[0] & 0x7U; - bool main_button = GET_BIT(msg, 3U); - hyundai_common_cruise_buttons_check(cruise_button, main_button); - } + // gas press, different for EV, hybrid, and ICE models + if (msg_matches(msg, 0x371U, 0U) && hyundai_ev_gas_signal) { + gas_pressed = (((msg->data[4] & 0x7FU) << 1) | (msg->data[3] >> 7)) != 0U; + } else if (msg_matches(msg, 0x371U, 0U) && hyundai_hybrid_gas_signal) { + gas_pressed = msg->data[7] != 0U; + } else if (msg_matches(msg, 0x91U, 0U) && hyundai_fcev_gas_signal) { + gas_pressed = msg->data[6] != 0U; + } else if (msg_matches(msg, 0x260U, 0U) && !hyundai_ev_gas_signal && !hyundai_hybrid_gas_signal) { + gas_pressed = (msg->data[7] >> 6) != 0U; + } else { + } - // gas press, different for EV, hybrid, and ICE models - if ((msg->addr == 0x371U) && hyundai_ev_gas_signal) { - gas_pressed = (((msg->data[4] & 0x7FU) << 1) | (msg->data[3] >> 7)) != 0U; - } else if ((msg->addr == 0x371U) && hyundai_hybrid_gas_signal) { - gas_pressed = msg->data[7] != 0U; - } else if ((msg->addr == 0x91U) && hyundai_fcev_gas_signal) { - gas_pressed = msg->data[6] != 0U; - } else if ((msg->addr == 0x260U) && !hyundai_ev_gas_signal && !hyundai_hybrid_gas_signal) { - gas_pressed = (msg->data[7] >> 6) != 0U; - } else { - } + // sample wheel speed, averaging opposite corners + if (msg_matches(msg, 0x386U, 0U)) { + uint32_t front_left_speed = GET_BYTES_LE(msg, 0, 2) & 0x3FFFU; + uint32_t rear_right_speed = GET_BYTES_LE(msg, 6, 2) & 0x3FFFU; + vehicle_moving = (front_left_speed > HYUNDAI_STANDSTILL_THRSLD) || (rear_right_speed > HYUNDAI_STANDSTILL_THRSLD); + } - // sample wheel speed, averaging opposite corners - if (msg->addr == 0x386U) { - uint32_t front_left_speed = GET_BYTES(msg, 0, 2) & 0x3FFFU; - uint32_t rear_right_speed = GET_BYTES(msg, 6, 2) & 0x3FFFU; - vehicle_moving = (front_left_speed > HYUNDAI_STANDSTILL_THRSLD) || (rear_right_speed > HYUNDAI_STANDSTILL_THRSLD); - } + if (msg_matches(msg, 0x394U, 0U)) { + brake_pressed = ((msg->data[5] >> 5U) & 0x3U) == 0x2U; + } - if (msg->addr == 0x394U) { - brake_pressed = ((msg->data[5] >> 5U) & 0x3U) == 0x2U; - } + if (msg_matches(msg, 0x592U, 0U)) { + acc_main_on = GET_BIT(msg, 34U); + bool cruise_engaged = GET_BIT(msg, 35U); + hyundai_common_cruise_state_check(cruise_engaged); + } - if (msg->addr == 0x592U) { - acc_main_on = GET_BIT(msg, 34U); - bool cruise_engaged = GET_BIT(msg, 35U); - hyundai_common_cruise_state_check(cruise_engaged); - } + if (msg_matches(msg, 0x595U, 0U)) { + acc_main_on = GET_BIT(msg, 50U); + bool cruise_engaged = GET_BIT(msg, 51U); + hyundai_common_cruise_state_check(cruise_engaged); + } - if (msg->addr == 0x595U) { - acc_main_on = GET_BIT(msg, 50U); - bool cruise_engaged = GET_BIT(msg, 51U); - hyundai_common_cruise_state_check(cruise_engaged); - } - - if ((msg->addr == 0x260U) && hyundai_non_scc && !hyundai_ev_gas_signal && !hyundai_hybrid_gas_signal) { - acc_main_on = GET_BIT(msg, 25U); - bool cruise_engaged = GET_BIT(msg, 26U); - hyundai_common_cruise_state_check(cruise_engaged); - } + if (msg_matches(msg, 0x260U, 0U) && hyundai_non_scc && !hyundai_ev_gas_signal && !hyundai_hybrid_gas_signal) { + acc_main_on = GET_BIT(msg, 25U); + bool cruise_engaged = GET_BIT(msg, 26U); + hyundai_common_cruise_state_check(cruise_engaged); } hyundai_common_reset_acc_main_on_mismatches(); @@ -267,7 +263,7 @@ static bool hyundai_tx_hook(const CANPacket_t *msg) { // LKA STEER: safety check if (msg->addr == 0x340U) { - int desired_torque = ((GET_BYTES(msg, 0, 4) >> 16) & 0x7ffU) - 1024U; + int desired_torque = ((GET_BYTES_LE(msg, 0, 4) >> 16) & 0x7ffU) - 1024U; bool steer_req = GET_BIT(msg, 27U); const TorqueSteeringLimits limits = hyundai_alt_limits_2 ? HYUNDAI_STEERING_LIMITS_ALT_2 : @@ -280,7 +276,7 @@ static bool hyundai_tx_hook(const CANPacket_t *msg) { // UDS: Only tester present ("\x02\x3E\x80\x00\x00\x00\x00\x00") allowed on diagnostics address if (msg->addr == 0x7D0U) { - if ((GET_BYTES(msg, 0, 4) != 0x00803E02U) || (GET_BYTES(msg, 4, 4) != 0x0U)) { + if (GET_BYTES_64_LE(msg, 0, 8) != 0x0000000000803E02ULL) { tx = false; } } @@ -303,9 +299,9 @@ static bool hyundai_tx_hook(const CANPacket_t *msg) { static safety_config hyundai_init(uint16_t param) { static const CanMsg HYUNDAI_LONG_TX_MSGS[] = { HYUNDAI_LONG_COMMON_TX_MSGS(0) - {0x38D, 0, 8, .check_relay = false}, // FCA11 Bus 0 - {0x483, 0, 8, .check_relay = false}, // FCA12 Bus 0 - {0x7D0, 0, 8, .check_relay = false}, // radar UDS TX addr Bus 0 (for radar disable) + {0x38D, 0, 8, .check_relay = false}, // FCA11 Bus 0 + {0x483, 0, 8, .check_relay = false}, // FCA12 Bus 0 + {0x7D0, 0, 8, .check_relay = false}, // radar UDS TX addr Bus 0 (for radar disable) }; static const CanMsg HYUNDAI_CAMERA_SCC_TX_MSGS[] = { @@ -366,7 +362,6 @@ static safety_config hyundai_init(uint16_t param) { } else { SET_TX_MSGS(HYUNDAI_LONG_TX_MSGS, ret); } - } else if (hyundai_camera_scc) { static RxCheck hyundai_cam_scc_rx_checks[] = { HYUNDAI_COMMON_RX_CHECKS(false) diff --git a/opendbc_repo/opendbc/safety/modes/hyundai_canfd.h b/opendbc_repo/opendbc/safety/modes/hyundai_canfd.h index 44263fd5a..8f86b66ec 100644 --- a/opendbc_repo/opendbc/safety/modes/hyundai_canfd.h +++ b/opendbc_repo/opendbc/safety/modes/hyundai_canfd.h @@ -68,73 +68,69 @@ static uint32_t hyundai_canfd_get_checksum(const CANPacket_t *msg) { } static void hyundai_canfd_rx_hook(const CANPacket_t *msg) { - const unsigned pt_bus = hyundai_canfd_lka_steer_msg ? 1U : 0U; const unsigned int scc_bus = hyundai_camera_scc ? 2U : pt_bus; - if (msg->bus == pt_bus) { - // driver torque - if (msg->addr == 0xeaU) { - int torque_driver_new = ((msg->data[11] & 0x1fU) << 8U) | msg->data[10]; - torque_driver_new -= 4095; - update_sample(&torque_driver, torque_driver_new); - } - - // cruise buttons - const unsigned int button_addr = hyundai_canfd_alt_buttons ? 0x1aaU : 0x1cfU; - if (msg->addr == button_addr) { - bool main_button = false; - int cruise_button = 0; - if (msg->addr == 0x1cfU) { - cruise_button = msg->data[2] & 0x7U; - main_button = GET_BIT(msg, 19U); - mads_button_press = GET_BIT(msg, 23U) ? MADS_BUTTON_PRESSED : MADS_BUTTON_NOT_PRESSED; - } else { - cruise_button = (msg->data[4] >> 4) & 0x7U; - main_button = GET_BIT(msg, 34U); - mads_button_press = GET_BIT(msg, 39U) ? MADS_BUTTON_PRESSED : MADS_BUTTON_NOT_PRESSED; - } - hyundai_common_cruise_buttons_check(cruise_button, main_button); - } - - // gas press, different for EV, hybrid, and ICE models - if ((msg->addr == 0x35U) && hyundai_ev_gas_signal) { - gas_pressed = msg->data[5] != 0U; - } else if ((msg->addr == 0x105U) && hyundai_hybrid_gas_signal) { - gas_pressed = GET_BIT(msg, 103U) || (msg->data[13] != 0U) || GET_BIT(msg, 112U); - } else if ((msg->addr == 0x100U) && !hyundai_ev_gas_signal && !hyundai_hybrid_gas_signal) { - gas_pressed = GET_BIT(msg, 176U); - } else { - } - - // brake press - if (msg->addr == 0x175U) { - brake_pressed = GET_BIT(msg, 81U); - } - - // vehicle moving - if (msg->addr == 0xa0U) { - uint32_t fl = (GET_BYTES(msg, 8, 2)) & 0x3FFFU; - uint32_t fr = (GET_BYTES(msg, 10, 2)) & 0x3FFFU; - uint32_t rl = (GET_BYTES(msg, 12, 2)) & 0x3FFFU; - uint32_t rr = (GET_BYTES(msg, 14, 2)) & 0x3FFFU; - vehicle_moving = (fl > HYUNDAI_STANDSTILL_THRSLD) || (fr > HYUNDAI_STANDSTILL_THRSLD) || - (rl > HYUNDAI_STANDSTILL_THRSLD) || (rr > HYUNDAI_STANDSTILL_THRSLD); - - // average of all 4 wheel speeds. Conversion: raw * 0.03125 / 3.6 = m/s - UPDATE_VEHICLE_SPEED((fr + rr + rl + fl) / 4.0 * 0.03125 * KPH_TO_MS); - } + // driver torque + if (msg_matches(msg, 0xeaU, pt_bus)) { + int torque_driver_new = ((msg->data[11] & 0x1fU) << 8U) | msg->data[10]; + torque_driver_new -= 4095; + update_sample(&torque_driver, torque_driver_new); } - if (msg->bus == scc_bus) { - // cruise state - if ((msg->addr == 0x1a0U) && !hyundai_longitudinal) { - // 1=enabled, 2=driver override - int cruise_status = ((msg->data[8] >> 4) & 0x7U); - bool cruise_engaged = (cruise_status == 1) || (cruise_status == 2); - hyundai_common_cruise_state_check(cruise_engaged); - acc_main_on = GET_BIT(msg, 66U); + // cruise buttons + const unsigned int button_addr = hyundai_canfd_alt_buttons ? 0x1aaU : 0x1cfU; + if (msg_matches(msg, button_addr, pt_bus)) { + bool main_button = false; + int cruise_button = 0; + if (msg_matches(msg, 0x1cfU, pt_bus)) { + cruise_button = msg->data[2] & 0x7U; + main_button = GET_BIT(msg, 19U); + mads_button_press = GET_BIT(msg, 23U) ? MADS_BUTTON_PRESSED : MADS_BUTTON_NOT_PRESSED; + } else { + cruise_button = (msg->data[4] >> 4) & 0x7U; + main_button = GET_BIT(msg, 34U); + mads_button_press = GET_BIT(msg, 39U) ? MADS_BUTTON_PRESSED : MADS_BUTTON_NOT_PRESSED; } + hyundai_common_cruise_buttons_check(cruise_button, main_button); + } + + // gas press, different for EV, hybrid, and ICE models + if (msg_matches(msg, 0x35U, pt_bus) && hyundai_ev_gas_signal) { + gas_pressed = msg->data[5] != 0U; + } + if (msg_matches(msg, 0x105U, pt_bus) && hyundai_hybrid_gas_signal) { + gas_pressed = ((msg->data[12] >> 7) | msg->data[13] | (msg->data[14] & 1U)) != 0U; + } + if (msg_matches(msg, 0x100U, pt_bus) && !hyundai_ev_gas_signal && !hyundai_hybrid_gas_signal) { + gas_pressed = GET_BIT(msg, 176U); + } + + // brake press + if (msg_matches(msg, 0x175U, pt_bus)) { + brake_pressed = GET_BIT(msg, 81U); + } + + // vehicle moving + if (msg_matches(msg, 0xa0U, pt_bus)) { + uint32_t fl = (GET_BYTES_LE(msg, 8, 2)) & 0x3FFFU; + uint32_t fr = (GET_BYTES_LE(msg, 10, 2)) & 0x3FFFU; + uint32_t rl = (GET_BYTES_LE(msg, 12, 2)) & 0x3FFFU; + uint32_t rr = (GET_BYTES_LE(msg, 14, 2)) & 0x3FFFU; + vehicle_moving = (fl > HYUNDAI_STANDSTILL_THRSLD) || (fr > HYUNDAI_STANDSTILL_THRSLD) || + (rl > HYUNDAI_STANDSTILL_THRSLD) || (rr > HYUNDAI_STANDSTILL_THRSLD); + + // average of all 4 wheel speeds. Conversion: raw * 0.03125 / 3.6 = m/s + UPDATE_VEHICLE_SPEED((fr + rr + rl + fl) / 4.0 * 0.03125 * KPH_TO_MS); + } + + // cruise state + if (msg_matches(msg, 0x1a0U, scc_bus) && !hyundai_longitudinal) { + // 1=enabled, 2=driver override + int cruise_status = ((msg->data[8] >> 4) & 0x7U); + bool cruise_engaged = (cruise_status == 1) || (cruise_status == 2); + hyundai_common_cruise_state_check(cruise_engaged); + acc_main_on = GET_BIT(msg, 66U); } hyundai_common_reset_acc_main_on_mismatches(); @@ -186,7 +182,7 @@ static bool hyundai_canfd_tx_hook(const CANPacket_t *msg) { // UDS: only tester present ("\x02\x3E\x80\x00\x00\x00\x00\x00") allowed on diagnostics address if (((msg->addr == 0x730U) && hyundai_canfd_lka_steer_msg) || ((msg->addr == 0x7D0U) && !hyundai_camera_scc)) { - if ((GET_BYTES(msg, 0, 4) != 0x00803E02U) || (GET_BYTES(msg, 4, 4) != 0x0U)) { + if (GET_BYTES_64_LE(msg, 0, 8) != 0x0000000000803E02ULL) { tx = false; } } @@ -260,7 +256,7 @@ static safety_config hyundai_canfd_init(uint16_t param) { HYUNDAI_CANFD_CRUISE_BUTTON_TX_MSGS(2) HYUNDAI_CANFD_LFA_STEERING_COMMON_TX_MSGS(0) HYUNDAI_CANFD_SCC_CONTROL_COMMON_TX_MSGS(0, true) - {0x160, 0, 16, .check_relay = true}, // ADRV_0x160 + {0x160, 0, 16, .check_relay = true}, // ADRV_0x160 {0x7D0, 0, 8, .check_relay = false}, // tester present for radar ECU disable }; @@ -285,7 +281,6 @@ static safety_config hyundai_canfd_init(uint16_t param) { }; ret = BUILD_SAFETY_CFG(hyundai_canfd_lka_steer_msg_long_rx_checks, HYUNDAI_CANFD_LKA_STEER_MSG_LONG_TX_MSGS); - } else { // Longitudinal checks for LFA steering static RxCheck hyundai_canfd_long_rx_checks[] = { @@ -312,7 +307,6 @@ static safety_config hyundai_canfd_init(uint16_t param) { SET_TX_MSGS(HYUNDAI_CANFD_LFA_STEERING_LONG_TX_MSGS, ret); } } - } else { if (hyundai_canfd_lka_steer_msg) { // *** LKA steering checks *** @@ -329,7 +323,6 @@ static safety_config hyundai_canfd_init(uint16_t param) { } else { SET_TX_MSGS(HYUNDAI_CANFD_LKA_STEER_MSG_TX_MSGS, ret); } - } else if (!hyundai_camera_scc) { // Radar sends SCC messages on these cars instead of camera static RxCheck hyundai_canfd_radar_scc_rx_checks[] = { @@ -349,7 +342,6 @@ static safety_config hyundai_canfd_init(uint16_t param) { } else { SET_RX_CHECKS(hyundai_canfd_radar_scc_rx_checks, ret); } - } else { // *** LFA steering checks *** // Camera sends SCC messages on LFA steering cars. diff --git a/opendbc_repo/opendbc/safety/modes/hyundai_common.h b/opendbc_repo/opendbc/safety/modes/hyundai_common.h index 97e833021..8eaa2ca9e 100644 --- a/opendbc_repo/opendbc/safety/modes/hyundai_common.h +++ b/opendbc_repo/opendbc/safety/modes/hyundai_common.h @@ -74,7 +74,7 @@ void hyundai_common_init(uint16_t param) { const uint16_t HYUNDAI_PARAM_HYBRID_GAS = 2; const uint16_t HYUNDAI_PARAM_CAMERA_SCC = 8; const uint16_t HYUNDAI_PARAM_CANFD_LKA_STEER_MSG = 16; - const uint16_t HYUNDAI_PARAM_ALT_LIMITS = 64; // TODO: shift this down with the rest of the common flags + const uint16_t HYUNDAI_PARAM_ALT_LIMITS = 64; // TODO: shift this down with the rest of the common flags const uint16_t HYUNDAI_PARAM_FCEV_GAS = 256; const uint16_t HYUNDAI_PARAM_ALT_LIMITS_2 = 512; @@ -169,10 +169,9 @@ uint32_t hyundai_common_canfd_compute_checksum(const CANPacket_t *msg) { if (len == 24) { crc ^= 0x819dU; - } else if (len == 32) { + } + if (len == 32) { crc ^= 0x9f5bU; - } else { - } return crc; diff --git a/opendbc_repo/opendbc/safety/modes/mazda.h b/opendbc_repo/opendbc/safety/modes/mazda.h index 9838feccf..4b3838f6f 100644 --- a/opendbc_repo/opendbc/safety/modes/mazda.h +++ b/opendbc_repo/opendbc/safety/modes/mazda.h @@ -17,33 +17,31 @@ // track msgs coming from OP so that we know what CAM msgs to drop and what to forward static void mazda_rx_hook(const CANPacket_t *msg) { - if ((int)msg->bus == MAZDA_MAIN) { - if (msg->addr == MAZDA_ENGINE_DATA) { - // sample speed: scale by 0.01 to get kph - int speed = (msg->data[2] << 8) | msg->data[3]; - vehicle_moving = speed > 10; // moving when speed > 0.1 kph - } + if (msg_matches(msg, MAZDA_ENGINE_DATA, MAZDA_MAIN)) { + // sample speed: scale by 0.01 to get kph + int speed = (msg->data[2] << 8) | msg->data[3]; + vehicle_moving = speed > 10; // moving when speed > 0.1 kph + } - if (msg->addr == MAZDA_STEER_TORQUE) { - int torque_driver_new = msg->data[0] - 127U; - // update array of samples - update_sample(&torque_driver, torque_driver_new); - } + if (msg_matches(msg, MAZDA_STEER_TORQUE, MAZDA_MAIN)) { + int torque_driver_new = msg->data[0] - 127U; + // update array of samples + update_sample(&torque_driver, torque_driver_new); + } - // enter controls on rising edge of ACC, exit controls on ACC off - if (msg->addr == MAZDA_CRZ_CTRL) { - bool cruise_engaged = msg->data[0] & 0x8U; - pcm_cruise_check(cruise_engaged); - acc_main_on = GET_BIT(msg, 17U); - } + // enter controls on rising edge of ACC, exit controls on ACC off + if (msg_matches(msg, MAZDA_CRZ_CTRL, MAZDA_MAIN)) { + bool cruise_engaged = msg->data[0] & 0x8U; + pcm_cruise_check(cruise_engaged); + acc_main_on = GET_BIT(msg, 17U); + } - if (msg->addr == MAZDA_ENGINE_DATA) { - gas_pressed = (msg->data[4] || (msg->data[5] & 0xF0U)); - } + if (msg_matches(msg, MAZDA_ENGINE_DATA, MAZDA_MAIN)) { + gas_pressed = (msg->data[4] | (msg->data[5] & 0xF0U)) != 0U; + } - if (msg->addr == MAZDA_PEDALS) { - brake_pressed = (msg->data[0] & 0x10U); - } + if (msg_matches(msg, MAZDA_PEDALS, MAZDA_MAIN)) { + brake_pressed = (msg->data[0] & 0x10U); } } @@ -60,24 +58,22 @@ static bool mazda_tx_hook(const CANPacket_t *msg) { bool tx = true; // Check if msg is sent on the main BUS - if (msg->bus == (unsigned char)MAZDA_MAIN) { - // steer cmd checks - if (msg->addr == MAZDA_LKAS) { - int desired_torque = (((msg->data[0] & 0x0FU) << 8) | msg->data[1]) - 2048U; + // steer cmd checks + if (msg_matches(msg, MAZDA_LKAS, MAZDA_MAIN)) { + int desired_torque = (((msg->data[0] & 0x0FU) << 8) | msg->data[1]) - 2048U; - if (steer_torque_cmd_checks(desired_torque, -1, MAZDA_STEERING_LIMITS)) { - tx = false; - } + if (steer_torque_cmd_checks(desired_torque, -1, MAZDA_STEERING_LIMITS)) { + tx = false; } + } - // cruise buttons check - if (msg->addr == MAZDA_CRZ_BTNS) { - // allow resume spamming while controls allowed, but - // only allow cancel while controls not allowed - bool cancel_cmd = (msg->data[0] == 0x1U); - if (!controls_allowed && !cancel_cmd) { - tx = false; - } + // cruise buttons check + if (msg_matches(msg, MAZDA_CRZ_BTNS, MAZDA_MAIN)) { + // allow resume spamming while controls allowed, but + // only allow cancel while controls not allowed + bool cancel_cmd = (msg->data[0] == 0x1U); + if (!controls_allowed && !cancel_cmd) { + tx = false; } } @@ -85,7 +81,11 @@ static bool mazda_tx_hook(const CANPacket_t *msg) { } static safety_config mazda_init(uint16_t param) { - static const CanMsg MAZDA_TX_MSGS[] = {{MAZDA_LKAS, 0, 8, .check_relay = true}, {MAZDA_CRZ_BTNS, 0, 8, .check_relay = false}, {MAZDA_LKAS_HUD, 0, 8, .check_relay = true}}; + static const CanMsg MAZDA_TX_MSGS[] = { + {MAZDA_LKAS, 0, 8, .check_relay = true}, + {MAZDA_CRZ_BTNS, 0, 8, .check_relay = false}, + {MAZDA_LKAS_HUD, 0, 8, .check_relay = true}, + }; static RxCheck mazda_rx_checks[] = { {.msg = {{MAZDA_CRZ_CTRL, 0, 8, 50U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, diff --git a/opendbc_repo/opendbc/safety/modes/mg.h b/opendbc_repo/opendbc/safety/modes/mg.h index a41bfb7a0..d95820998 100644 --- a/opendbc_repo/opendbc/safety/modes/mg.h +++ b/opendbc_repo/opendbc/safety/modes/mg.h @@ -5,66 +5,82 @@ static uint8_t mg_crc_lut[256]; static uint32_t mg_get_checksum(const CANPacket_t *msg) { - return msg->data[7]; + uint32_t checksum = msg->data[7]; + if (msg->addr == 0x1ecU) { + checksum = ((msg->data[2] & 0x7FU) << 8) | msg->data[3]; + } + return checksum; } static uint32_t mg_compute_checksum(const CANPacket_t *msg) { - uint8_t checksum = 0xFFU; - for (int i = 0; i < 7; i++) { - checksum ^= msg->data[i]; - checksum = mg_crc_lut[checksum]; + uint32_t checksum; + if (msg->addr == 0x1ecU) { + uint32_t torque = ((msg->data[0] & 0x7U) << 8) | msg->data[1]; + uint32_t valid = (msg->data[0] >> 3) & 1U; + uint32_t status = (msg->data[6] >> 4) & 0x7U; + uint32_t counter = msg->data[0] >> 4; + checksum = (0U - ((torque << 1) + (status << 12) + valid + counter)) & 0x7FFFU; + } else { + checksum = 0xFFU; + for (int i = 0; i < 7; i++) { + checksum ^= msg->data[i]; + checksum = mg_crc_lut[checksum]; + } + checksum ^= 0xFFU; } - return checksum ^ 0xFFU; + return checksum; } static uint8_t mg_get_counter(const CANPacket_t *msg) { uint8_t counter = 0U; if (msg->addr == 0x23cU) { counter = (msg->data[4] >> 4) & 0xFU; - } else if (msg->addr == 0x1ecU) { + } + if (msg->addr == 0x1ecU) { counter = (msg->data[0] >> 4) & 0xFU; - } else if (msg->addr == 0x242U) { + } + if (msg->addr == 0x242U) { counter = (msg->data[0] >> 3) & 0xFU; - } else if (msg->addr == 0x1b6U) { + } + if (msg->addr == 0x1b6U) { counter = msg->data[6] & 0xFU; - } else { - // No counter for this message + } + if (msg->addr == 0xAFU) { + counter = msg->data[5] >> 4U; } return counter; } static void mg_rx_hook(const CANPacket_t *msg) { - if (msg->bus == 0U) { - // Vehicle speed - if (msg->addr == 0x23cU) { - float speed = (((msg->data[2] & 0x7FU) << 8) | msg->data[3]) * 0.015625; - vehicle_moving = speed > 0.0; - UPDATE_VEHICLE_SPEED(speed * KPH_TO_MS); - } + // Vehicle speed + if (msg_matches(msg, 0x23cU, 0U)) { + float speed = (((msg->data[2] & 0x7FU) << 8) | msg->data[3]) * 0.015625; + vehicle_moving = speed > 0.0; + UPDATE_VEHICLE_SPEED(speed * KPH_TO_MS); + } - // Gas pressed - if (msg->addr == 0xafU) { - gas_pressed = msg->data[0] != 0U; - } + // Gas pressed + if (msg_matches(msg, 0xafU, 0U)) { + gas_pressed = msg->data[0] != 0U; + } - // Driver torque - if (msg->addr == 0x1ecU) { - int torque_driver_new = (((msg->data[4] & 0x7U) << 8) | msg->data[5]) - 1024U; - update_sample(&torque_driver, torque_driver_new); - } + // Driver torque + if (msg_matches(msg, 0x1ecU, 0U)) { + int torque_driver_new = (((msg->data[4] & 0x7U) << 8) | msg->data[5]) - 1024U; + update_sample(&torque_driver, torque_driver_new); + } - // Brake pressed - if (msg->addr == 0x1b6U) { - brake_pressed = GET_BIT(msg, 10U); - } + // Brake pressed + if (msg_matches(msg, 0x1b6U, 0U)) { + brake_pressed = GET_BIT(msg, 10U); + } - // Cruise state - if (msg->addr == 0x242U) { - int cruise_state = (msg->data[5] & 0x38U) >> 3; - bool cruise_engaged = (cruise_state == 2) || // Active - (cruise_state == 3); // Override - pcm_cruise_check(cruise_engaged); - } + // Cruise state + if (msg_matches(msg, 0x242U, 0U)) { + int cruise_state = (msg->data[5] & 0x38U) >> 3; + bool cruise_engaged = (cruise_state == 2) || // Active + (cruise_state == 3); // Override + pcm_cruise_check(cruise_engaged); } } @@ -79,22 +95,10 @@ static bool mg_tx_hook(const CANPacket_t *msg) { .type = TorqueDriverLimited, }; - bool tx = true; - bool violation = false; - - // Steering control - if (msg->addr == 0x1fdU) { - int desired_torque = (((msg->data[0] & 0x7U) << 8) | msg->data[1]) - 1024U; - bool steer_req = GET_BIT(msg, 35U); - - violation |= steer_torque_cmd_checks(desired_torque, steer_req, MG_STEERING_LIMITS); - } - - if (violation) { - tx = false; - } - - return tx; + // The TX list dispatches only steering control (0x1fd, bus 0) to this hook. + int desired_torque = (((msg->data[0] & 0x7U) << 8) | msg->data[1]) - 1024U; + bool steer_req = GET_BIT(msg, 35U); + return !steer_torque_cmd_checks(desired_torque, steer_req, MG_STEERING_LIMITS); } static safety_config mg_init(uint16_t param) { @@ -105,9 +109,9 @@ static safety_config mg_init(uint16_t param) { static const CanMsg MG_TX_MSGS[] = {{0x1fd, 0, 8, .check_relay = true}}; static RxCheck mg_rx_checks[] = { - {.msg = {{0x23c, 0, 8, .frequency = 50U, .ignore_checksum = true, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // SCS_HSC2_FrP19 (speed) - {.msg = {{0xaf, 0, 8, .frequency = 100U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // GW_HSC2_HCU_FrP00 (gas pedal) - {.msg = {{0x1ec, 0, 8, .frequency = 50U, .ignore_checksum = true, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // EPS_HSC2_FrP03 (driver torque) + {.msg = {{0x23c, 0, 8, .frequency = 50U, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // SCS_HSC2_FrP19 (speed) + {.msg = {{0xaf, 0, 8, .frequency = 100U, .ignore_checksum = true, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // GW_HSC2_HCU_FrP00 (gas pedal) + {.msg = {{0x1ec, 0, 8, .frequency = 50U, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // EPS_HSC2_FrP03 (driver torque) {.msg = {{0x242, 0, 8, .frequency = 50U, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // RADAR_HSC2_FrP00 (cruise state) {.msg = {{0x1b6, 0, 8, .frequency = 50U, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // EHBS_HSC2_FrP00 (brake pedal) }; diff --git a/opendbc_repo/opendbc/safety/modes/nissan.h b/opendbc_repo/opendbc/safety/modes/nissan.h index a7201c837..2d7707bc6 100644 --- a/opendbc_repo/opendbc/safety/modes/nissan.h +++ b/opendbc_repo/opendbc/safety/modes/nissan.h @@ -25,59 +25,54 @@ static const AngleSteeringLimits NISSAN_STEERING_LIMITS = { .angle_deg_to_can = 100, .angle_rate_up_lookup = { {0., 5., 15.}, - {5., .8, .15} + {5., .8, .15}, }, .angle_rate_down_lookup = { {0., 5., 15.}, - {5., 3.5, .4} + {5., 3.5, .4}, }, }; static void nissan_rx_hook(const CANPacket_t *msg) { - // Altima: on camera bus, others: on pt bus - if (msg->bus == 0U) { - if (msg->addr == 0x185U) { - // Current steering angle - int angle_meas_new = (msg->data[2] << 10) | (msg->data[3] << 2) | (msg->data[4] >> 6); - // Factor is -0.01, offset is 1310. Flip to correct sign, but keep units in CAN scale - angle_meas_new = -angle_meas_new + (1310.0f * NISSAN_STEERING_LIMITS.angle_deg_to_can); + if (msg_matches(msg, 0x185U, 0U)) { + // Current steering angle + int angle_meas_new = (msg->data[2] << 10) | (msg->data[3] << 2) | (msg->data[4] >> 6); + // Factor is -0.01, offset is 1310. Flip to correct sign, but keep units in CAN scale + angle_meas_new = -angle_meas_new + (1310.0f * NISSAN_STEERING_LIMITS.angle_deg_to_can); - // update array of samples - update_sample(&angle_meas, angle_meas_new); + // update array of samples + update_sample(&angle_meas, angle_meas_new); + } + + if (msg_matches(msg, 0x285U, nissan_alt_eps ? 1U : 0U)) { + // Get current speed and standstill + uint16_t right_rear = (msg->data[0] << 8) | (msg->data[1]); + uint16_t left_rear = (msg->data[2] << 8) | (msg->data[3]); + vehicle_moving = (right_rear | left_rear) != 0U; + UPDATE_VEHICLE_SPEED((right_rear + left_rear) / 2.0 * 0.005 * KPH_TO_MS); + } + + // X-Trail 0x15c, Leaf 0x239 + if (msg_matches(msg, 0x15cU, nissan_alt_eps ? 1U : 0U) || msg_matches(msg, 0x239U, nissan_alt_eps ? 1U : 0U)) { + if (msg->addr == 0x15cU) { + gas_pressed = ((msg->data[5] << 2) | ((msg->data[6] >> 6) & 0x3U)) > 3U; + } else { + gas_pressed = msg->data[0] > 3U; } } - if (msg->bus == (nissan_alt_eps ? 1U : 0U)) { - if (msg->addr == 0x285U) { - // Get current speed and standstill - uint16_t right_rear = (msg->data[0] << 8) | (msg->data[1]); - uint16_t left_rear = (msg->data[2] << 8) | (msg->data[3]); - vehicle_moving = (right_rear | left_rear) != 0U; - UPDATE_VEHICLE_SPEED((right_rear + left_rear) / 2.0 * 0.005 * KPH_TO_MS); - } - - // X-Trail 0x15c, Leaf 0x239 - if ((msg->addr == 0x15cU) || (msg->addr == 0x239U)) { - if (msg->addr == 0x15cU){ - gas_pressed = ((msg->data[5] << 2) | ((msg->data[6] >> 6) & 0x3U)) > 3U; - } else { - gas_pressed = msg->data[0] > 3U; - } - } - - // X-trail 0x454, Leaf 0x239 - if ((msg->addr == 0x454U) || (msg->addr == 0x239U)) { - if (msg->addr == 0x454U){ - brake_pressed = (msg->data[2] & 0x80U) != 0U; - } else { - brake_pressed = ((msg->data[4] >> 5) & 1U) != 0U; - } + // X-trail 0x454, Leaf 0x239 + if (msg_matches(msg, 0x454U, nissan_alt_eps ? 1U : 0U) || msg_matches(msg, 0x239U, nissan_alt_eps ? 1U : 0U)) { + if (msg->addr == 0x454U) { + brake_pressed = (msg->data[2] & 0x80U) != 0U; + } else { + brake_pressed = ((msg->data[4] >> 5) & 1U) != 0U; } } // Handle cruise enabled - if ((msg->addr == 0x30fU) && (msg->bus == (nissan_alt_eps ? 1U : 2U))) { + if (msg_matches(msg, 0x30fU, nissan_alt_eps ? 1U : 2U)) { bool cruise_engaged = (msg->data[0] >> 3) & 1U; pcm_cruise_check(cruise_engaged); } @@ -91,7 +86,6 @@ static void nissan_rx_hook(const CANPacket_t *msg) { } } - static bool nissan_tx_hook(const CANPacket_t *msg) { bool tx = true; bool violation = false; @@ -116,7 +110,6 @@ static bool nissan_tx_hook(const CANPacket_t *msg) { return tx; } - static safety_config nissan_init(uint16_t param) { static const CanMsg NISSAN_TX_MSGS_LEAF[] = { {0x169, 0, 8, .check_relay = true}, // LKAS diff --git a/opendbc_repo/opendbc/safety/modes/psa.h b/opendbc_repo/opendbc/safety/modes/psa.h index 63026c3e1..115b16203 100644 --- a/opendbc_repo/opendbc/safety/modes/psa.h +++ b/opendbc_repo/opendbc/safety/modes/psa.h @@ -6,9 +6,9 @@ #define PSA_STEERING_ALT 773U // RX from EPS, steering angle #define PSA_DYN_CMM 520U // RX from CMM, gas pedal #define PSA_HS2_DYN_ABR_38D 909U // RX from UC_FREIN, speed -#define PSA_HS2_DAT_MDD_CMD_452 1106U // RX from BSI, cruise state -#define PSA_DAT_BSI 1042U // RX from BSI, brake -#define PSA_LANE_KEEP_ASSIST 1010U // TX from OP, EPS +#define PSA_HS2_DAT_MDD_CMD_452 1106U // RX from BSI, cruise state +#define PSA_DAT_BSI 1042U // RX from BSI, brake +#define PSA_LANE_KEEP_ASSIST 1010U // TX from OP, EPS // CAN bus #define PSA_MAIN_BUS 0U @@ -19,9 +19,9 @@ static uint8_t psa_get_counter(const CANPacket_t *msg) { uint8_t cnt = 0; if (msg->addr == PSA_HS2_DAT_MDD_CMD_452) { cnt = (msg->data[3] >> 4) & 0xFU; - } else if (msg->addr == PSA_HS2_DYN_ABR_38D) { + } + if (msg->addr == PSA_HS2_DYN_ABR_38D) { cnt = (msg->data[5] >> 4) & 0xFU; - } else { } return cnt; } @@ -50,45 +50,37 @@ static uint32_t psa_compute_checksum(const CANPacket_t *msg) { uint8_t chk = 0; if (msg->addr == PSA_HS2_DAT_MDD_CMD_452) { chk = _psa_compute_checksum(msg, 0x4, 5); - } else if (msg->addr == PSA_HS2_DYN_ABR_38D) { + } + if (msg->addr == PSA_HS2_DYN_ABR_38D) { chk = _psa_compute_checksum(msg, 0x7, 5); - } else { } return chk; } static void psa_rx_hook(const CANPacket_t *msg) { - if (msg->bus == PSA_MAIN_BUS) { - if (msg->addr == PSA_DYN_CMM) { - gas_pressed = msg->data[3] > 0U; // P002_Com_rAPP - } - if (msg->addr == PSA_STEERING_ALT) { - int angle_meas_new = to_signed((msg->data[0] << 8) | msg->data[1], 16); // ANGLE - update_sample(&angle_meas, angle_meas_new); - } - if (msg->addr == PSA_HS2_DYN_ABR_38D) { - int speed = (msg->data[0] << 8) | msg->data[1]; - vehicle_moving = speed > 0; - UPDATE_VEHICLE_SPEED(speed * 0.01 * KPH_TO_MS); // VITESSE_VEHICULE_ROUES - } + if (msg_matches(msg, PSA_DYN_CMM, PSA_MAIN_BUS)) { + gas_pressed = msg->data[3] > 0U; // P002_Com_rAPP + } + if (msg_matches(msg, PSA_STEERING_ALT, PSA_MAIN_BUS)) { + int angle_meas_new = to_signed((msg->data[0] << 8) | msg->data[1], 16); // ANGLE + update_sample(&angle_meas, angle_meas_new); + } + if (msg_matches(msg, PSA_HS2_DYN_ABR_38D, PSA_MAIN_BUS)) { + int speed = (msg->data[0] << 8) | msg->data[1]; + vehicle_moving = speed > 0; + UPDATE_VEHICLE_SPEED(speed * 0.01 * KPH_TO_MS); // VITESSE_VEHICULE_ROUES } - if (msg->bus == PSA_ADAS_BUS) { - if (msg->addr == PSA_HS2_DAT_MDD_CMD_452) { - pcm_cruise_check((msg->data[2U] >> 7U) & 1U); // RVV_ACC_ACTIVATION_REQ - } + if (msg_matches(msg, PSA_HS2_DAT_MDD_CMD_452, PSA_ADAS_BUS)) { + pcm_cruise_check((msg->data[2U] >> 7U) & 1U); // RVV_ACC_ACTIVATION_REQ } - - if (msg->bus == PSA_CAM_BUS) { - if (msg->addr == PSA_DAT_BSI) { - brake_pressed = (msg->data[0U] >> 5U) & 1U; // P013_MainBrake - } + if (msg_matches(msg, PSA_DAT_BSI, PSA_CAM_BUS)) { + brake_pressed = (msg->data[0U] >> 5U) & 1U; // P013_MainBrake } } static bool psa_tx_hook(const CANPacket_t *msg) { - bool tx = true; static const AngleSteeringLimits PSA_STEERING_LIMITS = { .max_angle = 3900, .angle_deg_to_can = 10, @@ -102,30 +94,25 @@ static bool psa_tx_hook(const CANPacket_t *msg) { }, }; - // Safety check for LKA - if (msg->addr == PSA_LANE_KEEP_ASSIST) { - // SET_ANGLE - int desired_angle = to_signed((msg->data[6] << 6) | ((msg->data[7] & 0xFCU) >> 2), 14); - // TORQUE_FACTOR - bool lka_active = ((msg->data[5] & 0xFEU) >> 1) == 100U; + // The TX list dispatches only PSA_LANE_KEEP_ASSIST on PSA_MAIN_BUS to this hook. + // SET_ANGLE + int desired_angle = to_signed((msg->data[6] << 6) | ((msg->data[7] & 0xFCU) >> 2), 14); + // TORQUE_FACTOR + bool lka_active = ((msg->data[5] & 0xFEU) >> 1) == 100U; - if (steer_angle_cmd_checks(desired_angle, lka_active, PSA_STEERING_LIMITS)) { - tx = false; - } - } - return tx; + return !steer_angle_cmd_checks(desired_angle, lka_active, PSA_STEERING_LIMITS); } static safety_config psa_init(uint16_t param) { SAFETY_UNUSED(param); static const CanMsg PSA_TX_MSGS[] = { - {PSA_LANE_KEEP_ASSIST, PSA_MAIN_BUS, 8, .check_relay = true}, // EPS steering + {PSA_LANE_KEEP_ASSIST, PSA_MAIN_BUS, 8, .check_relay = true}, // EPS steering }; static RxCheck psa_rx_checks[] = { {.msg = {{PSA_HS2_DAT_MDD_CMD_452, PSA_ADAS_BUS, 6, 20U, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // cruise state {.msg = {{PSA_HS2_DYN_ABR_38D, PSA_MAIN_BUS, 8, 25U, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // speed - {.msg = {{PSA_STEERING_ALT, PSA_MAIN_BUS, 7, 100U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // steering angle + {.msg = {{PSA_STEERING_ALT, PSA_MAIN_BUS, 7, 100U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // steering angle {.msg = {{PSA_STEERING, PSA_MAIN_BUS, 7, 100U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // driver torque {.msg = {{PSA_DYN_CMM, PSA_MAIN_BUS, 8, 100U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // gas pedal {.msg = {{PSA_DAT_BSI, PSA_CAM_BUS, 8, 20U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // brake diff --git a/opendbc_repo/opendbc/safety/modes/rivian.h b/opendbc_repo/opendbc/safety/modes/rivian.h index 1209937b4..58f317228 100644 --- a/opendbc_repo/opendbc/safety/modes/rivian.h +++ b/opendbc_repo/opendbc/safety/modes/rivian.h @@ -8,7 +8,6 @@ static uint8_t rivian_get_counter(const CANPacket_t *msg) { } static uint32_t rivian_get_checksum(const CANPacket_t *msg) { - // Signal: ESP_Status_Checksum, VDM_PropStatus_Checksum return msg->data[0]; } @@ -18,14 +17,7 @@ static uint8_t _rivian_compute_checksum(const CANPacket_t *msg, uint8_t poly, ui uint8_t crc = 0; // Skip the checksum byte for (int i = 1; i < len; i++) { - crc ^= msg->data[i]; - for (int j = 0; j < 8; j++) { - if ((crc & 0x80U) != 0U) { - crc = (crc << 1) ^ poly; - } else { - crc <<= 1; - } - } + crc = crc8_update(crc, msg->data[i], poly); } return crc ^ xor_output; } @@ -34,9 +26,18 @@ static uint32_t rivian_compute_checksum(const CANPacket_t *msg) { uint8_t chksum = 0; if (msg->addr == 0x208U) { chksum = _rivian_compute_checksum(msg, 0x1D, 0xB1); - } else if (msg->addr == 0x150U) { + } + if (msg->addr == 0x150U) { chksum = _rivian_compute_checksum(msg, 0x1D, 0x9A); - } else { + } + if (msg->addr == 0x380U) { + chksum = _rivian_compute_checksum(msg, 0x1D, 0x1E); + } + if (msg->addr == 0x38FU) { + chksum = _rivian_compute_checksum(msg, 0x1D, 0x37); + } + if (msg->addr == 0x100U) { + chksum = _rivian_compute_checksum(msg, 0x1D, 0x5F); } return chksum; } @@ -45,50 +46,48 @@ static bool rivian_get_quality_flag_valid(const CANPacket_t *msg) { bool valid = false; if (msg->addr == 0x208U) { valid = ((msg->data[3] >> 3) & 0x3U) == 0x1U; // ESP_Vehicle_Speed_Q - } else if (msg->addr == 0x150U) { + } + if (msg->addr == 0x150U) { valid = (msg->data[1] >> 6) == 0x1U; // VDM_VehicleSpeedQ - } else { + } + if (msg->addr == 0x38FU) { + valid = ((msg->data[2] >> 5) & 0x3U) == 0x1U; // iBESP2_BrakePedalApplied_Q } return valid; } static void rivian_rx_hook(const CANPacket_t *msg) { - - if (msg->bus == 0U) { - // Vehicle speed - if (msg->addr == 0x208U) { - float speed = ((msg->data[6] << 8) | msg->data[7]) * 0.01; - vehicle_moving = speed > 0.0; - UPDATE_VEHICLE_SPEED(speed * KPH_TO_MS); - } - - // Gas pressed and second speed source for variable torque limit - if (msg->addr == 0x150U) { - gas_pressed = msg->data[3] | (msg->data[4] & 0xC0U); - - // Disable controls if speeds from VDM and ESP ECUs are too far apart. - float vdm_speed = ((msg->data[5] << 8) | msg->data[6]) * 0.01 * KPH_TO_MS; - speed_mismatch_check(vdm_speed); - } - - // Driver torque - if (msg->addr == 0x380U) { - int torque_driver_new = (((msg->data[2] << 4) | (msg->data[3] >> 4))) - 2050U; - update_sample(&torque_driver, torque_driver_new); - } - - // Brake pressed - if (msg->addr == 0x38fU) { - brake_pressed = (msg->data[2] >> 7) & 1U; - } + // Vehicle speed + if (msg_matches(msg, 0x208U, 0U)) { + float speed = ((msg->data[6] << 8) | msg->data[7]) * 0.01; + vehicle_moving = speed > 0.0; + UPDATE_VEHICLE_SPEED(speed * KPH_TO_MS); } - if (msg->bus == 2U) { - // Cruise state - if (msg->addr == 0x100U) { - const int feature_status = msg->data[2] >> 5U; - pcm_cruise_check(feature_status == 1); - } + // Gas pressed and second speed source for variable torque limit + if (msg_matches(msg, 0x150U, 0U)) { + gas_pressed = msg->data[3] | (msg->data[4] & 0xC0U); + + // Disable controls if speeds from VDM and ESP ECUs are too far apart. + float vdm_speed = ((msg->data[5] << 8) | msg->data[6]) * 0.01 * KPH_TO_MS; + speed_mismatch_check(vdm_speed); + } + + // Driver torque + if (msg_matches(msg, 0x380U, 0U)) { + int torque_driver_new = (((msg->data[2] << 4) | (msg->data[3] >> 4))) - 2050U; + update_sample(&torque_driver, torque_driver_new); + } + + // Brake pressed + if (msg_matches(msg, 0x38fU, 0U)) { + brake_pressed = (msg->data[2] >> 7) & 1U; + } + + // Cruise state + if (msg_matches(msg, 0x100U, 2U)) { + const int feature_status = msg->data[2] >> 5U; + pcm_cruise_check(feature_status == 1); } } @@ -117,23 +116,21 @@ static bool rivian_tx_hook(const CANPacket_t *msg) { bool tx = true; - if (msg->bus == 0U) { - // Steering control - if (msg->addr == 0x120U) { - int desired_torque = ((msg->data[2] << 3U) | (msg->data[3] >> 5U)) - 1024U; - bool steer_req = (msg->data[3] >> 4) & 1U; + // Steering control + if (msg_matches(msg, 0x120U, 0U)) { + int desired_torque = ((msg->data[2] << 3U) | (msg->data[3] >> 5U)) - 1024U; + bool steer_req = (msg->data[3] >> 4) & 1U; - if (steer_torque_cmd_checks(desired_torque, steer_req, RIVIAN_STEERING_LIMITS)) { - tx = false; - } + if (steer_torque_cmd_checks(desired_torque, steer_req, RIVIAN_STEERING_LIMITS)) { + tx = false; } + } - // Longitudinal control - if (msg->addr == 0x160U) { - int raw_accel = ((msg->data[2] << 3) | (msg->data[3] >> 5)) - 1024U; - if (longitudinal_accel_checks(raw_accel, RIVIAN_LONG_LIMITS)) { - tx = false; - } + // Longitudinal control + if (msg_matches(msg, 0x160U, 0U)) { + int raw_accel = ((msg->data[2] << 3) | (msg->data[3] >> 5)) - 1024U; + if (longitudinal_accel_checks(raw_accel, RIVIAN_LONG_LIMITS)) { + tx = false; } } @@ -144,16 +141,24 @@ static safety_config rivian_init(uint16_t param) { // SCCM_WheelTouch: for hiding hold wheel alert // VDM_AdasSts: for canceling stock ACC // 0x120 = ACM_lkaHbaCmd, 0x321 = SCCM_WheelTouch, 0x162 = VDM_AdasSts - static const CanMsg RIVIAN_TX_MSGS[] = {{0x120, 0, 8, .check_relay = true}, {0x321, 2, 7, .check_relay = true}, {0x162, 2, 8, .check_relay = true}}; + static const CanMsg RIVIAN_TX_MSGS[] = { + {0x120, 0, 8, .check_relay = true}, + {0x321, 2, 7, .check_relay = true}, + {0x162, 2, 8, .check_relay = true}, + }; // 0x160 = ACM_longitudinalRequest - static const CanMsg RIVIAN_LONG_TX_MSGS[] = {{0x120, 0, 8, .check_relay = true}, {0x321, 2, 7, .check_relay = true}, {0x160, 0, 5, .check_relay = true}}; + static const CanMsg RIVIAN_LONG_TX_MSGS[] = { + {0x120, 0, 8, .check_relay = true}, + {0x321, 2, 7, .check_relay = true}, + {0x160, 0, 5, .check_relay = true}, + }; static RxCheck rivian_rx_checks[] = { - {.msg = {{0x208, 0, 8, 50U, .max_counter = 14U}, { 0 }, { 0 }}}, // ESP_Status (speed) - {.msg = {{0x150, 0, 7, 50U, .max_counter = 14U}, { 0 }, { 0 }}}, // VDM_PropStatus (gas pedal & 2nd speed) - {.msg = {{0x380, 0, 5, 100U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // EPAS_SystemStatus (driver torque) - {.msg = {{0x38f, 0, 6, 50U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // iBESP2 (brakes) - {.msg = {{0x100, 2, 8, 100U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // ACM_Status (cruise state) + {.msg = {{0x208, 0, 8, 50U, .max_counter = 14U}, { 0 }, { 0 }}}, // ESP_Status (speed) + {.msg = {{0x150, 0, 7, 50U, .max_counter = 14U}, { 0 }, { 0 }}}, // VDM_PropStatus (gas pedal & 2nd speed) + {.msg = {{0x38f, 0, 6, 50U, .max_counter = 14U}, { 0 }, { 0 }}}, // iBESP2 (brakes) + {.msg = {{0x380, 0, 5, 100U, .max_counter = 14U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // EPAS_SystemStatus (driver torque) + {.msg = {{0x100, 2, 8, 100U, .max_counter = 14U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // ACM_Status (cruise state) }; bool rivian_longitudinal = false; diff --git a/opendbc_repo/opendbc/safety/modes/subaru.h b/opendbc_repo/opendbc/safety/modes/subaru.h index c085c720b..b7cc45778 100644 --- a/opendbc_repo/opendbc/safety/modes/subaru.h +++ b/opendbc_repo/opendbc/safety/modes/subaru.h @@ -100,9 +100,9 @@ static uint32_t subaru_compute_checksum(const CANPacket_t *msg) { static void subaru_rx_hook(const CANPacket_t *msg) { const unsigned int alt_main_bus = subaru_gen2 ? SUBARU_ALT_BUS : SUBARU_MAIN_BUS; - if ((msg->addr == MSG_SUBARU_Steering_Torque) && (msg->bus == SUBARU_MAIN_BUS)) { + if (msg_matches(msg, MSG_SUBARU_Steering_Torque, SUBARU_MAIN_BUS)) { int torque_driver_new; - torque_driver_new = ((GET_BYTES(msg, 0, 4) >> 16) & 0x7FFU); + torque_driver_new = ((GET_BYTES_LE(msg, 0, 4) >> 16) & 0x7FFU); torque_driver_new = -1 * to_signed(torque_driver_new, 11); update_sample(&torque_driver, torque_driver_new); } @@ -115,29 +115,29 @@ static void subaru_rx_hook(const CANPacket_t *msg) { } // enter controls on rising edge of ACC, exit controls on ACC off - if ((msg->addr == MSG_SUBARU_CruiseControl) && (msg->bus == alt_main_bus)) { + if (msg_matches(msg, MSG_SUBARU_CruiseControl, alt_main_bus)) { bool cruise_engaged = (msg->data[5] >> 1) & 1U; pcm_cruise_check(cruise_engaged); acc_main_on = GET_BIT(msg, 40U); } // update vehicle moving with any non-zero wheel speed - if ((msg->addr == MSG_SUBARU_Wheel_Speeds) && (msg->bus == alt_main_bus)) { - uint32_t fr = (GET_BYTES(msg, 1, 3) >> 4) & 0x1FFFU; - uint32_t rr = (GET_BYTES(msg, 3, 3) >> 1) & 0x1FFFU; - uint32_t rl = (GET_BYTES(msg, 4, 3) >> 6) & 0x1FFFU; - uint32_t fl = (GET_BYTES(msg, 6, 2) >> 3) & 0x1FFFU; + if (msg_matches(msg, MSG_SUBARU_Wheel_Speeds, alt_main_bus)) { + uint32_t fr = (GET_BYTES_LE(msg, 1, 3) >> 4) & 0x1FFFU; + uint32_t rr = (GET_BYTES_LE(msg, 3, 3) >> 1) & 0x1FFFU; + uint32_t rl = (GET_BYTES_LE(msg, 4, 3) >> 6) & 0x1FFFU; + uint32_t fl = (GET_BYTES_LE(msg, 6, 2) >> 3) & 0x1FFFU; - vehicle_moving = (fr > 0U) || (rr > 0U) || (rl > 0U) || (fl > 0U); + vehicle_moving = (fr | rr | rl | fl) != 0U; UPDATE_VEHICLE_SPEED((fr + rr + rl + fl) / 4.0 * 0.057 * KPH_TO_MS); } - if ((msg->addr == MSG_SUBARU_Brake_Status) && (msg->bus == alt_main_bus)) { + if (msg_matches(msg, MSG_SUBARU_Brake_Status, alt_main_bus)) { brake_pressed = (msg->data[7] >> 6) & 1U; } - if ((msg->addr == MSG_SUBARU_Throttle) && (msg->bus == SUBARU_MAIN_BUS)) { + if (msg_matches(msg, MSG_SUBARU_Throttle, SUBARU_MAIN_BUS)) { gas_pressed = msg->data[4] != 0U; } } @@ -149,7 +149,7 @@ static bool subaru_tx_hook(const CANPacket_t *msg) { const LongitudinalLimits SUBARU_LONG_LIMITS = { .min_gas = 808, // appears to be engine braking .max_gas = 3400, // approx 2 m/s^2 when maxing cruise_rpm and cruise_throttle - .inactive_gas = 1818, // this is zero acceleration + .inactive_gas = 1818, // this is zero acceleration .max_brake = 600, // approx -3.5 m/s^2 .min_transmission_rpm = 0, @@ -161,7 +161,7 @@ static bool subaru_tx_hook(const CANPacket_t *msg) { // steer cmd checks if (msg->addr == MSG_SUBARU_ES_LKAS) { - int desired_torque = ((GET_BYTES(msg, 0, 4) >> 16) & 0x1FFFU); + int desired_torque = ((GET_BYTES_LE(msg, 0, 4) >> 16) & 0x1FFFU); desired_torque = -1 * to_signed(desired_torque, 13); bool steer_req = (msg->data[3] >> 5) & 1U; @@ -178,7 +178,7 @@ static bool subaru_tx_hook(const CANPacket_t *msg) { // check es_distance cruise_throttle limits if (msg->addr == MSG_SUBARU_ES_Distance) { - int cruise_throttle = (GET_BYTES(msg, 2, 2) & 0x1FFFU); + int cruise_throttle = (GET_BYTES_LE(msg, 2, 2) & 0x1FFFU); bool cruise_cancel = (msg->data[7] >> 0) & 1U; if (subaru_longitudinal) { @@ -207,9 +207,10 @@ static bool subaru_tx_hook(const CANPacket_t *msg) { violation |= !(is_tester_present || is_button_rdbi); } - if (violation){ + if (violation) { tx = false; } + return tx; } diff --git a/opendbc_repo/opendbc/safety/modes/subaru_preglobal.h b/opendbc_repo/opendbc/safety/modes/subaru_preglobal.h index 2fafd0182..28d945b2c 100644 --- a/opendbc_repo/opendbc/safety/modes/subaru_preglobal.h +++ b/opendbc_repo/opendbc/safety/modes/subaru_preglobal.h @@ -29,34 +29,32 @@ static bool subaru_pg_reversed_driver_torque = false; static void subaru_preglobal_rx_hook(const CANPacket_t *msg) { - if (msg->bus == SUBARU_PG_MAIN_BUS) { - if (msg->addr == MSG_SUBARU_PG_Steering_Torque) { - int torque_driver_new; - torque_driver_new = (msg->data[3] >> 5) + (msg->data[4] << 3); - torque_driver_new = to_signed(torque_driver_new, 11); - torque_driver_new = subaru_pg_reversed_driver_torque ? -torque_driver_new : torque_driver_new; - update_sample(&torque_driver, torque_driver_new); - } + if (msg_matches(msg, MSG_SUBARU_PG_Steering_Torque, SUBARU_PG_MAIN_BUS)) { + int torque_driver_new; + torque_driver_new = (msg->data[3] >> 5) + (msg->data[4] << 3); + torque_driver_new = to_signed(torque_driver_new, 11); + torque_driver_new = subaru_pg_reversed_driver_torque ? -torque_driver_new : torque_driver_new; + update_sample(&torque_driver, torque_driver_new); + } - // enter controls on rising edge of ACC, exit controls on ACC off - if (msg->addr == MSG_SUBARU_PG_CruiseControl) { - bool cruise_engaged = (msg->data[6] >> 1) & 1U; - pcm_cruise_check(cruise_engaged); - acc_main_on = GET_BIT(msg, 48U); - } + // enter controls on rising edge of ACC, exit controls on ACC off + if (msg_matches(msg, MSG_SUBARU_PG_CruiseControl, SUBARU_PG_MAIN_BUS)) { + bool cruise_engaged = (msg->data[6] >> 1) & 1U; + pcm_cruise_check(cruise_engaged); + acc_main_on = GET_BIT(msg, 48U); + } - // update vehicle moving with any non-zero wheel speed - if (msg->addr == MSG_SUBARU_PG_Wheel_Speeds) { - vehicle_moving = ((GET_BYTES(msg, 0, 4) >> 12) != 0U) || (GET_BYTES(msg, 4, 4) != 0U); - } + // update vehicle moving with any non-zero wheel speed + if (msg_matches(msg, MSG_SUBARU_PG_Wheel_Speeds, SUBARU_PG_MAIN_BUS)) { + vehicle_moving = ((GET_BYTES_LE(msg, 0, 4) >> 12) | GET_BYTES_LE(msg, 4, 4)) != 0U; + } - if (msg->addr == MSG_SUBARU_PG_Brake_Pedal) { - brake_pressed = ((GET_BYTES(msg, 0, 4) >> 16) & 0xFFU) > 0U; - } + if (msg_matches(msg, MSG_SUBARU_PG_Brake_Pedal, SUBARU_PG_MAIN_BUS)) { + brake_pressed = ((GET_BYTES_LE(msg, 0, 4) >> 16) & 0xFFU) > 0U; + } - if (msg->addr == MSG_SUBARU_PG_Throttle) { - gas_pressed = msg->data[0] != 0U; - } + if (msg_matches(msg, MSG_SUBARU_PG_Throttle, SUBARU_PG_MAIN_BUS)) { + gas_pressed = msg->data[0] != 0U; } } @@ -75,7 +73,7 @@ static bool subaru_preglobal_tx_hook(const CANPacket_t *msg) { // steer cmd checks if (msg->addr == MSG_SUBARU_PG_ES_LKAS) { - int desired_torque = ((GET_BYTES(msg, 0, 4) >> 8) & 0x1FFFU); + int desired_torque = ((GET_BYTES_LE(msg, 0, 4) >> 8) & 0x1FFFU); desired_torque = -1 * to_signed(desired_torque, 13); bool steer_req = (msg->data[3] >> 0) & 1U; @@ -84,6 +82,7 @@ static bool subaru_preglobal_tx_hook(const CANPacket_t *msg) { tx = false; } } + return tx; } @@ -99,7 +98,7 @@ static safety_config subaru_preglobal_init(uint16_t param) { // TODO: do checksum and counter checks after adding the signals to the outback dbc file static RxCheck subaru_preglobal_rx_checks[] = { - {.msg = {{MSG_SUBARU_PG_Throttle, SUBARU_PG_MAIN_BUS, 8, 100U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, + {.msg = {{MSG_SUBARU_PG_Throttle, SUBARU_PG_MAIN_BUS, 8, 100U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, {.msg = {{MSG_SUBARU_PG_Steering_Torque, SUBARU_PG_MAIN_BUS, 8, 50U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, {.msg = {{MSG_SUBARU_PG_CruiseControl, SUBARU_PG_MAIN_BUS, 8, 50U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, {.msg = {{MSG_SUBARU_PG_Wheel_Speeds, SUBARU_PG_MAIN_BUS, 8, 50U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, diff --git a/opendbc_repo/opendbc/safety/modes/tesla.h b/opendbc_repo/opendbc/safety/modes/tesla.h index f0c482854..cabd872aa 100644 --- a/opendbc_repo/opendbc/safety/modes/tesla.h +++ b/opendbc_repo/opendbc/safety/modes/tesla.h @@ -38,24 +38,26 @@ extern uint8_t tesla_mads_screen_button_fingers; uint8_t tesla_mads_screen_button_fingers = 0U; static uint8_t tesla_get_counter(const CANPacket_t *msg) { - uint8_t cnt = 0; if (msg->addr == 0x2b9U) { // Signal: DAS_controlCounter cnt = msg->data[6] >> 5; - } else if (msg->addr == 0x488U) { + } + if (msg->addr == 0x488U) { // Signal: DAS_steeringControlCounter cnt = msg->data[2] & 0x0FU; - } else if ((msg->addr == 0x257U) || (msg->addr == 0x118U) || (msg->addr == 0x145U) || (msg->addr == 0x286U) || (msg->addr == 0x311U)) { + } + if ((msg->addr == 0x257U) || (msg->addr == 0x118U) || (msg->addr == 0x145U) || (msg->addr == 0x286U) || (msg->addr == 0x311U)) { // Signal: DI_speedCounter, DI_systemStatusCounter, ESP_statusCounter, DI_locStatusCounter, UI_warningCounter cnt = msg->data[1] & 0x0FU; - } else if (msg->addr == 0x155U) { + } + if (msg->addr == 0x155U) { // Signal: ESP_wheelRotationCounter cnt = msg->data[6] >> 4; - } else if (msg->addr == 0x370U) { + } + if (msg->addr == 0x370U) { // Signal: EPAS3S_sysStatusCounter cnt = msg->data[6] & 0x0FU; - } else { } return cnt; } @@ -65,13 +67,14 @@ static int _tesla_get_checksum_byte(const int addr) { if ((addr == 0x370) || (addr == 0x2b9) || (addr == 0x155)) { // Signal: EPAS3S_sysStatusChecksum, DAS_controlChecksum, ESP_wheelRotationChecksum checksum_byte = 7; - } else if (addr == 0x488) { + } + if (addr == 0x488) { // Signal: DAS_steeringControlChecksum checksum_byte = 3; - } else if ((addr == 0x257) || (addr == 0x118) || (addr == 0x145) || (addr == 0x286) || (addr == 0x311)) { + } + if ((addr == 0x257) || (addr == 0x118) || (addr == 0x145) || (addr == 0x286) || (addr == 0x311)) { // Signal: DI_speedChecksum, DI_systemStatusChecksum, ESP_statusChecksum, DI_locStatusChecksum, UI_warningChecksum checksum_byte = 0; - } else { } return checksum_byte; } @@ -102,14 +105,13 @@ static uint32_t tesla_compute_checksum(const CANPacket_t *msg) { } static bool tesla_get_quality_flag_valid(const CANPacket_t *msg) { - bool valid = false; if (msg->addr == 0x155U) { valid = (msg->data[5] & 0x1U) == 0x1U; // ESP_wheelSpeedsQF - } else if (msg->addr == 0x145U) { + } + if (msg->addr == 0x145U) { int user_brake_status = (msg->data[3] >> 5) & 0x03U; valid = (user_brake_status != 0) && (user_brake_status != 3); // ESP_driverBrakeApply=NotInit_orOff, Faulty_SNA - } else { } return valid; } @@ -129,113 +131,105 @@ static int tesla_get_steer_ctrl_type(const int ctrl_type) { } static void tesla_rx_hook(const CANPacket_t *msg) { + // Steering angle: (0.1 * val) - 819.2 in deg. + if (msg_matches(msg, 0x370U, 0U)) { + // Store it 1/10 deg to match steering request + const int angle_meas_new = (((msg->data[4] & 0x3FU) << 8) | msg->data[5]) - 8192U; + update_sample(&angle_meas, angle_meas_new); - if (msg->bus == 0U) { - // Steering angle: (0.1 * val) - 819.2 in deg. - if (msg->addr == 0x370U) { - // Store it 1/10 deg to match steering request - const int angle_meas_new = (((msg->data[4] & 0x3FU) << 8) | msg->data[5]) - 8192U; - update_sample(&angle_meas, angle_meas_new); + const int hands_on_level = msg->data[4] >> 6; // EPAS3S_handsOnLevel + const int eac_status = msg->data[6] >> 5; // EPAS3S_eacStatus + const int eac_error_code = msg->data[2] >> 4; // EPAS3S_eacErrorCode - const int hands_on_level = msg->data[4] >> 6; // EPAS3S_handsOnLevel - const int eac_status = msg->data[6] >> 5; // EPAS3S_eacStatus - const int eac_error_code = msg->data[2] >> 4; // EPAS3S_eacErrorCode + // Disengage on normal user override, or if high angle rate fault from user overriding extremely quickly + steering_disengage = (hands_on_level >= 3) || ((eac_status == 0) && (eac_error_code == 9)); + } - // Disengage on normal user override, or if high angle rate fault from user overriding extremely quickly - steering_disengage = (hands_on_level >= 3) || ((eac_status == 0) && (eac_error_code == 9)); - } - - // Vehicle speed (DI_speed) - if (msg->addr == 0x257U) { - // Vehicle speed: ((val * 0.08) - 40) / MS_TO_KPH - float speed = ((((msg->data[2] << 4) | (msg->data[1] >> 4)) * 0.08) - 40.) * KPH_TO_MS; - UPDATE_VEHICLE_SPEED(speed); - } - - // 2nd vehicle speed (ESP_B) - if (msg->addr == 0x155U) { - // Disable controls if speeds from DI (Drive Inverter) and ESP ECUs are too far apart. - float esp_speed = (((msg->data[6] & 0x0FU) << 6) | (msg->data[5] >> 2)) * 0.5 * KPH_TO_MS; - speed_mismatch_check(esp_speed); - } - - // Gas pressed - if (msg->addr == 0x118U) { - gas_pressed = (msg->data[4] != 0U); - } - - // Brake pressed - if (msg->addr == 0x145U) { - brake_pressed = ((msg->data[3] >> 5) & 0x03U) == 2U; - } - - // Cruise and Autopark/Summon state - if (msg->addr == 0x286U) { - // Autopark state - int autopark_state = (msg->data[3] >> 1) & 0x0FU; // DI_autoparkState - bool tesla_autopark_now = (autopark_state == 3) || // ACTIVE - (autopark_state == 4) || // COMPLETE - (autopark_state == 9); // SELFPARK_STARTED - - // Only consider rising edges while controls are not allowed - if (tesla_autopark_now && !tesla_autopark_prev && !cruise_engaged_prev) { - tesla_autopark = true; - } - if (!tesla_autopark_now) { - tesla_autopark = false; - } - tesla_autopark_prev = tesla_autopark_now; - - // Cruise state - int cruise_state = (msg->data[1] >> 4) & 0x07U; - bool cruise_engaged = (cruise_state == 2) || // ENABLED - (cruise_state == 3) || // STANDSTILL - (cruise_state == 4) || // OVERRIDE - (cruise_state == 6) || // PRE_FAULT - (cruise_state == 7); // PRE_CANCEL - cruise_engaged = cruise_engaged && !tesla_autopark; - - pcm_cruise_check(cruise_engaged); - } - - if (msg->addr == 0x155U) { - vehicle_moving = !GET_BIT(msg, 41U); // ESP_vehicleStandstillSts + if (msg_matches(msg, 0x3DFU, 1U)) { + if (tesla_mads_screen_button_fingers != 0U) { + mads_button_press = (msg->data[3] == tesla_mads_screen_button_fingers) ? MADS_BUTTON_PRESSED : MADS_BUTTON_NOT_PRESSED; } } - if (msg->bus == 1U) { - if (msg->addr == 0x3DFU) { - if (tesla_mads_screen_button_fingers != 0U) { - mads_button_press = (msg->data[3] == tesla_mads_screen_button_fingers) ? MADS_BUTTON_PRESSED : MADS_BUTTON_NOT_PRESSED; - } - } + // Vehicle speed (DI_speed) + if (msg_matches(msg, 0x257U, 0U)) { + // Vehicle speed: ((val * 0.08) - 40) / MS_TO_KPH + float speed = ((((msg->data[2] << 4) | (msg->data[1] >> 4)) * 0.08) - 40.) * KPH_TO_MS; + UPDATE_VEHICLE_SPEED(speed); } - if (msg->bus == 2U) { - // DAS_control - if (msg->addr == 0x2b9U) { - // "AEB_ACTIVE" - tesla_stock_aeb = (msg->data[2] & 0x03U) == 1U; - } + // 2nd vehicle speed (ESP_B) + if (msg_matches(msg, 0x155U, 0U)) { + // Disable controls if speeds from DI (Drive Inverter) and ESP ECUs are too far apart. + float esp_speed = (((msg->data[6] & 0x0FU) << 6) | (msg->data[5] >> 2)) * 0.5 * KPH_TO_MS; + speed_mismatch_check(esp_speed); + } - // DAS_steeringControl - if (msg->addr == 0x488U) { - int steering_control_type = msg->data[2] >> 6; - bool tesla_stock_lkas_now = steering_control_type == tesla_get_steer_ctrl_type(2); // "LANE_KEEP_ASSIST" + // Gas pressed + if (msg_matches(msg, 0x118U, 0U)) { + gas_pressed = (msg->data[4] != 0U); + } - // Only consider rising edges while controls are not allowed - if (tesla_stock_lkas_now && !tesla_stock_lkas_prev && !(controls_allowed || controls_allowed_lateral)) { - tesla_stock_lkas = true; - } - if (!tesla_stock_lkas_now) { - tesla_stock_lkas = false; - } - tesla_stock_lkas_prev = tesla_stock_lkas_now; + // Brake pressed + if (msg_matches(msg, 0x145U, 0U)) { + brake_pressed = ((msg->data[3] >> 5) & 0x03U) == 2U; + } + + // Cruise and Autopark/Summon state + if (msg_matches(msg, 0x286U, 0U)) { + // Autopark state + int autopark_state = (msg->data[3] >> 1) & 0x0FU; // DI_autoparkState + bool tesla_autopark_now = (autopark_state == 3) || // ACTIVE + (autopark_state == 4) || // COMPLETE + (autopark_state == 9); // SELFPARK_STARTED + + // Only consider rising edges while controls are not allowed + if (tesla_autopark_now && !tesla_autopark_prev && !cruise_engaged_prev) { + tesla_autopark = true; } + if (!tesla_autopark_now) { + tesla_autopark = false; + } + tesla_autopark_prev = tesla_autopark_now; + + // Cruise state + int cruise_state = (msg->data[1] >> 4) & 0x07U; + bool cruise_engaged = (cruise_state == 2) || // ENABLED + (cruise_state == 3) || // STANDSTILL + (cruise_state == 4) || // OVERRIDE + (cruise_state == 6) || // PRE_FAULT + (cruise_state == 7); // PRE_CANCEL + cruise_engaged = cruise_engaged && !tesla_autopark; + + pcm_cruise_check(cruise_engaged); + } + + if (msg_matches(msg, 0x155U, 0U)) { + vehicle_moving = !GET_BIT(msg, 41U); // ESP_vehicleStandstillSts + } + + // DAS_control + if (msg_matches(msg, 0x2b9U, 2U)) { + // "AEB_ACTIVE" + tesla_stock_aeb = (msg->data[2] & 0x03U) == 1U; + } + + // DAS_steeringControl + if (msg_matches(msg, 0x488U, 2U)) { + int steering_control_type = msg->data[2] >> 5; // DAS_steeringControlType + bool tesla_stock_lkas_now = steering_control_type == tesla_get_steer_ctrl_type(2); // "LANE_KEEP_ASSIST" + + // Only consider rising edges while controls are not allowed + if (tesla_stock_lkas_now && !tesla_stock_lkas_prev && !(controls_allowed || controls_allowed_lateral)) { + tesla_stock_lkas = true; + } + if (!tesla_stock_lkas_now) { + tesla_stock_lkas = false; + } + tesla_stock_lkas_prev = tesla_stock_lkas_now; } } - static bool tesla_tx_hook(const CANPacket_t *msg) { const AngleSteeringLimits TESLA_STEERING_LIMITS = { .max_angle = 3600, // 360 deg, EPAS faults above this @@ -269,7 +263,7 @@ static bool tesla_tx_hook(const CANPacket_t *msg) { // We use 1/10 deg as a unit here int raw_angle_can = ((msg->data[0] & 0x7FU) << 8) | msg->data[1]; int desired_angle = raw_angle_can - 16384; - int steer_control_type = msg->data[2] >> 6; + int steer_control_type = msg->data[2] >> 5; const int angle_ctrl_type = tesla_get_steer_ctrl_type(1); const int lkas_ctrl_type = tesla_get_steer_ctrl_type(2); bool steer_control_enabled = (steer_control_type == angle_ctrl_type) || // ANGLE_CONTROL @@ -364,7 +358,6 @@ static bool tesla_fwd_hook(int bus_num, int addr) { } static safety_config tesla_init(uint16_t param) { - static const CanMsg TESLA_M3_Y_TX_MSGS[] = { {0x488, 0, 4, .check_relay = true, .disable_static_blocking = true}, // DAS_steeringControl {0x2b9, 0, 8, .check_relay = false}, // DAS_control (for cancel) @@ -380,6 +373,7 @@ static safety_config tesla_init(uint16_t param) { const uint16_t TESLA_FLAG_FSD_14 = 2; tesla_fsd_14 = GET_FLAG(param, TESLA_FLAG_FSD_14); + SAFETY_UNUSED(param); #ifdef ALLOW_DEBUG const uint16_t TESLA_FLAG_LONGITUDINAL_CONTROL = 1; tesla_longitudinal = GET_FLAG(param, TESLA_FLAG_LONGITUDINAL_CONTROL); diff --git a/opendbc_repo/opendbc/safety/modes/toyota.h b/opendbc_repo/opendbc/safety/modes/toyota.h index ae03e1f95..217df38d5 100644 --- a/opendbc_repo/opendbc/safety/modes/toyota.h +++ b/opendbc_repo/opendbc/safety/modes/toyota.h @@ -89,7 +89,8 @@ static bool toyota_get_quality_flag_valid(const CANPacket_t *msg) { bool valid = false; if (msg->addr == 0x260U) { valid = !GET_BIT(msg, 3U); // STEER_TORQUE_SENSOR.STEER_ANGLE_INITIALIZING - } else if (msg->addr == 0xaaU) { // WHEEL_SPEEDS + } + if (msg->addr == 0xaaU) { // WHEEL_SPEEDS // each wheel speed is 1-bit fault + 15-bit speed valid = true; for (uint8_t i = 0U; i < 4U; i += 1U) { @@ -98,7 +99,6 @@ static bool toyota_get_quality_flag_valid(const CANPacket_t *msg) { break; } } - } else { } return valid; } @@ -112,103 +112,100 @@ static int TOYOTA_GET_INTERCEPTOR(const CANPacket_t *msg) { } static void toyota_rx_hook(const CANPacket_t *msg) { - if (msg->bus == 0U) { + // get eps motor torque (0.66 factor in dbc) + if (msg_matches(msg, 0x260U, 0U)) { + int torque_meas_new = (msg->data[5] << 8) | msg->data[6]; + torque_meas_new = to_signed(torque_meas_new, 16); - // get eps motor torque (0.66 factor in dbc) - if (msg->addr == 0x260U) { - int torque_meas_new = (msg->data[5] << 8) | msg->data[6]; - torque_meas_new = to_signed(torque_meas_new, 16); + // scale by dbc_factor + torque_meas_new = (torque_meas_new * toyota_dbc_eps_torque_factor) / 100; - // scale by dbc_factor - torque_meas_new = (torque_meas_new * toyota_dbc_eps_torque_factor) / 100; + // update array of sample + update_sample(&torque_meas, torque_meas_new); - // update array of sample - update_sample(&torque_meas, torque_meas_new); + // increase torque_meas by 1 to be conservative on rounding + torque_meas.min--; + torque_meas.max++; - // increase torque_meas by 1 to be conservative on rounding - torque_meas.min--; - torque_meas.max++; + // driver torque for angle limiting + int torque_driver_new = (msg->data[1] << 8) | msg->data[2]; + torque_driver_new = to_signed(torque_driver_new, 16); + update_sample(&torque_driver, torque_driver_new); - // driver torque for angle limiting - int torque_driver_new = (msg->data[1] << 8) | msg->data[2]; - torque_driver_new = to_signed(torque_driver_new, 16); - update_sample(&torque_driver, torque_driver_new); + // LTA request angle should match current angle while inactive, clipped to max accepted angle. + // note that angle can be relative to init angle on some TSS2 platforms, LTA has the same offset + bool steer_angle_initializing = GET_BIT(msg, 3U); + if (!steer_angle_initializing) { + int angle_meas_new = (msg->data[3] << 8U) | msg->data[4]; + angle_meas_new = to_signed(angle_meas_new, 16); + update_sample(&angle_meas, angle_meas_new); + } + } - // LTA request angle should match current angle while inactive, clipped to max accepted angle. - // note that angle can be relative to init angle on some TSS2 platforms, LTA has the same offset - bool steer_angle_initializing = GET_BIT(msg, 3U); - if (!steer_angle_initializing) { - int angle_meas_new = (msg->data[3] << 8U) | msg->data[4]; - angle_meas_new = to_signed(angle_meas_new, 16); - update_sample(&angle_meas, angle_meas_new); + // enter controls on rising edge of ACC, exit controls on ACC off + // exit controls on rising edge of gas press, if not alternative experience + // exit controls on rising edge of brake press + if (toyota_secoc) { + if (msg_matches(msg, 0x176U, 0U)) { + bool cruise_engaged = GET_BIT(msg, 5U); // PCM_CRUISE.CRUISE_ACTIVE + pcm_cruise_check(cruise_engaged); + } + if (msg_matches(msg, 0x116U, 0U)) { + gas_pressed = msg->data[1] != 0U; // GAS_PEDAL.GAS_PEDAL_USER + } + if (msg_matches(msg, 0x101U, 0U)) { + brake_pressed = GET_BIT(msg, 3U); // BRAKE_MODULE.BRAKE_PRESSED (toyota_rav4_prime_generated.dbc) + } + } else { + if (msg_matches(msg, 0x1D2U, 0U)) { + bool cruise_engaged = GET_BIT(msg, 5U); // PCM_CRUISE.CRUISE_ACTIVE + pcm_cruise_check(cruise_engaged); + + if (!enable_gas_interceptor) { + gas_pressed = !GET_BIT(msg, 4U); // PCM_CRUISE.GAS_RELEASED } } - - // enter controls on rising edge of ACC, exit controls on ACC off - // exit controls on rising edge of gas press, if not alternative experience - // exit controls on rising edge of brake press - if (toyota_secoc) { - if (msg->addr == 0x176U) { - bool cruise_engaged = GET_BIT(msg, 5U); // PCM_CRUISE.CRUISE_ACTIVE - pcm_cruise_check(cruise_engaged); - } - if (msg->addr == 0x116U) { - gas_pressed = msg->data[1] != 0U; // GAS_PEDAL.GAS_PEDAL_USER - } - if (msg->addr == 0x101U) { - brake_pressed = GET_BIT(msg, 3U); // BRAKE_MODULE.BRAKE_PRESSED (toyota_rav4_prime_generated.dbc) - } - } else { - if (msg->addr == 0x1D2U) { - bool cruise_engaged = GET_BIT(msg, 5U); // PCM_CRUISE.CRUISE_ACTIVE - pcm_cruise_check(cruise_engaged); - - if (!enable_gas_interceptor) { - gas_pressed = !GET_BIT(msg, 4U); // PCM_CRUISE.GAS_RELEASED - } - } - if (!toyota_alt_brake && (msg->addr == 0x226U)) { - brake_pressed = GET_BIT(msg, 37U); // BRAKE_MODULE.BRAKE_PRESSED (toyota_nodsu_pt_generated.dbc) - } - if (toyota_alt_brake && (msg->addr == 0x224U)) { - brake_pressed = GET_BIT(msg, 5U); // BRAKE_MODULE.BRAKE_PRESSED (toyota_new_mc_pt_generated.dbc) - } + if (!toyota_alt_brake && msg_matches(msg, 0x226U, 0U)) { + brake_pressed = GET_BIT(msg, 37U); // BRAKE_MODULE.BRAKE_PRESSED (toyota_nodsu_pt_generated.dbc) } - - // sample speed - if (msg->addr == 0xaaU) { - int speed = 0; - // sum 4 wheel speeds. conversion: raw * 0.01 - 67.67 - for (uint8_t i = 0U; i < 8U; i += 2U) { - int wheel_speed = ((msg->data[i] & 0x7FU) << 8U) | msg->data[(i + 1U)]; - speed += wheel_speed - 6767; - } - // check that all wheel speeds are at zero value - vehicle_moving = speed != 0; - - UPDATE_VEHICLE_SPEED(speed / 4.0 * 0.01 * KPH_TO_MS); + if (toyota_alt_brake && msg_matches(msg, 0x224U, 0U)) { + brake_pressed = GET_BIT(msg, 5U); // BRAKE_MODULE.BRAKE_PRESSED (toyota_new_mc_pt_generated.dbc) } + } - if (msg->addr == 0x1D3U) { - acc_main_on = GET_BIT(msg, 15U); + if (msg_matches(msg, 0x1D3U, 0U)) { + acc_main_on = GET_BIT(msg, 15U); + } + + if (msg_matches(msg, 0x365U, 0U)) { + acc_main_on = GET_BIT(msg, 0U); + } + + // sample gas interceptor + if (msg_matches(msg, 0x201U, 0U)) { + // panda interceptor threshold needs to be equivalent to openpilot threshold to avoid controls mismatches + // If thresholds are mismatched then it is possible for panda to see the gas fall and rise while openpilot is in the pre-enabled state + // Threshold calculated from DBC gains: round((((15 + 75.555) / 0.159375) + ((15 + 151.111) / 0.159375)) / 2) = 805 + const int toyota_gas_interceptor_thrsld = 805; + + int gas_interceptor = TOYOTA_GET_INTERCEPTOR(msg); + gas_pressed = gas_interceptor > toyota_gas_interceptor_thrsld; + + gas_interceptor_prev = gas_interceptor; + } + + // sample speed + if (msg_matches(msg, 0xaaU, 0U)) { + int speed = 0; + // sum 4 wheel speeds. conversion: raw * 0.01 - 67.67 + for (uint8_t i = 0U; i < 8U; i += 2U) { + int wheel_speed = ((msg->data[i] & 0x7FU) << 8U) | msg->data[(i + 1U)]; + speed += wheel_speed - 6767; } + // check that all wheel speeds are at zero value + vehicle_moving = speed != 0; - if (msg->addr == 0x365U) { - acc_main_on = GET_BIT(msg, 0U); - } - - // sample gas interceptor - if (msg->addr == 0x201U) { - // panda interceptor threshold needs to be equivalent to openpilot threshold to avoid controls mismatches - // If thresholds are mismatched then it is possible for panda to see the gas fall and rise while openpilot is in the pre-enabled state - // Threshold calculated from DBC gains: round((((15 + 75.555) / 0.159375) + ((15 + 151.111) / 0.159375)) / 2) = 805 - const int toyota_gas_interceptor_thrsld = 805; - - int gas_interceptor = TOYOTA_GET_INTERCEPTOR(msg); - gas_pressed = gas_interceptor > toyota_gas_interceptor_thrsld; - - gas_interceptor_prev = gas_interceptor; - } + UPDATE_VEHICLE_SPEED(speed / 4.0 * 0.01 * KPH_TO_MS); } } @@ -256,142 +253,140 @@ static bool toyota_tx_hook(const CANPacket_t *msg) { bool tx = true; // Check if msg is sent on BUS 0 - if (msg->bus == 0U) { - // ACCEL: safety check on byte 1-2 - if (msg->addr == 0x343U) { - int desired_accel = (msg->data[0] << 8) | msg->data[1]; - desired_accel = to_signed(desired_accel, 16); + // ACCEL: safety check on byte 1-2 + if (msg_matches(msg, 0x343U, 0U)) { + int desired_accel = (msg->data[0] << 8) | msg->data[1]; + desired_accel = to_signed(desired_accel, 16); - bool violation = false; - if (toyota_secoc) { - // SecOC cars move accel to 0x183. Only allow inactive accel on 0x343 to match stock behavior - violation = desired_accel != TOYOTA_LONG_LIMITS.inactive_accel; + bool violation = false; + if (toyota_secoc) { + // SecOC cars move accel to 0x183. Only allow inactive accel on 0x343 to match stock behavior + violation = desired_accel != TOYOTA_LONG_LIMITS.inactive_accel; + } + violation |= longitudinal_accel_checks(desired_accel, TOYOTA_LONG_LIMITS); + + // only ACC messages that cancel are allowed when openpilot is not controlling longitudinal + if (toyota_stock_longitudinal) { + bool cancel_req = GET_BIT(msg, 24U); + if (!cancel_req) { + violation = true; } - violation |= longitudinal_accel_checks(desired_accel, TOYOTA_LONG_LIMITS); + if (desired_accel != TOYOTA_LONG_LIMITS.inactive_accel) { + violation = true; + } + } - // only ACC messages that cancel are allowed when openpilot is not controlling longitudinal - if (toyota_stock_longitudinal) { - bool cancel_req = GET_BIT(msg, 24U); - if (!cancel_req) { - violation = true; - } - if (desired_accel != TOYOTA_LONG_LIMITS.inactive_accel) { - violation = true; - } + if (violation) { + tx = false; + } + } + + if (msg_matches(msg, 0x183U, 0U)) { + int desired_accel = (msg->data[0] << 8) | msg->data[1]; + desired_accel = to_signed(desired_accel, 16); + + tx = !longitudinal_accel_checks(desired_accel, TOYOTA_LONG_LIMITS); + } + + // AEB: block all actuation. only used when DSU is unplugged + if (msg_matches(msg, 0x283U, 0U)) { + // only allow the checksum, which is the last byte + bool block = GET_BYTES_64_LE(msg, 0, 6) != 0U; + if (block) { + tx = false; + } + } + + // STEERING_LTA angle steering check + if (msg_matches(msg, 0x191U, 0U)) { + // check the STEER_REQUEST, STEER_REQUEST_2, TORQUE_WIND_DOWN, STEER_ANGLE_CMD signals + bool lta_request = GET_BIT(msg, 0U); + bool lta_request2 = GET_BIT(msg, 25U); + int torque_wind_down = msg->data[5]; + int lta_angle = (msg->data[1] << 8) | msg->data[2]; + lta_angle = to_signed(lta_angle, 16); + + bool steer_control_enabled = lta_request || lta_request2; + if (!toyota_lta) { + // using torque (LKA), block LTA msgs with actuation requests + if (steer_control_enabled || (lta_angle != 0) || (torque_wind_down != 0)) { + tx = false; + } + } else { + // check angle rate limits and inactive angle + if (steer_angle_cmd_checks(lta_angle, steer_control_enabled, TOYOTA_ANGLE_STEERING_LIMITS)) { + tx = false; } - if (violation) { + if (lta_request != lta_request2) { + tx = false; + } + + // TORQUE_WIND_DOWN is gated on steer request + if (!steer_control_enabled && (torque_wind_down != 0)) { + tx = false; + } + + // TORQUE_WIND_DOWN can only be no or full torque + if ((torque_wind_down != 0) && (torque_wind_down != 100)) { + tx = false; + } + + // check if we should wind down torque + int driver_torque = SAFETY_MIN(SAFETY_ABS(torque_driver.min), SAFETY_ABS(torque_driver.max)); + if ((driver_torque > TOYOTA_LTA_MAX_DRIVER_TORQUE) && (torque_wind_down != 0)) { + tx = false; + } + + int eps_torque = SAFETY_MIN(SAFETY_ABS(torque_meas.min), SAFETY_ABS(torque_meas.max)); + if ((eps_torque > TOYOTA_LTA_MAX_MEAS_TORQUE) && (torque_wind_down != 0)) { tx = false; } } + } - if (msg->addr == 0x183U) { - int desired_accel = (msg->data[0] << 8) | msg->data[1]; - desired_accel = to_signed(desired_accel, 16); + // STEERING_LTA_2 angle steering check (SecOC) + if (toyota_secoc && msg_matches(msg, 0x131U, 0U)) { + // SecOC cars block any form of LTA actuation for now + bool lta_request = GET_BIT(msg, 3U); // STEERING_LTA_2.STEER_REQUEST + bool lta_request2 = GET_BIT(msg, 0U); // STEERING_LTA_2.STEER_REQUEST_2 + int lta_angle_msb = msg->data[2]; // STEERING_LTA_2.STEER_ANGLE_CMD (MSB) + int lta_angle_lsb = msg->data[3]; // STEERING_LTA_2.STEER_ANGLE_CMD (LSB) - tx = !longitudinal_accel_checks(desired_accel, TOYOTA_LONG_LIMITS); + bool actuation = lta_request || lta_request2 || (lta_angle_msb != 0) || (lta_angle_lsb != 0); + if (actuation) { + tx = false; } + } - // AEB: block all actuation. only used when DSU is unplugged - if (msg->addr == 0x283U) { - // only allow the checksum, which is the last byte - bool block = (GET_BYTES(msg, 0, 4) != 0U) || (msg->data[4] != 0U) || (msg->data[5] != 0U); - if (block) { + // STEER: safety check on bytes 2-3 + if (msg_matches(msg, 0x2E4U, 0U)) { + int desired_torque = (msg->data[1] << 8) | msg->data[2]; + desired_torque = to_signed(desired_torque, 16); + bool steer_req = GET_BIT(msg, 0U); + // When using LTA (angle control), assert no actuation on LKA message + if (!toyota_lta) { + if (steer_torque_cmd_checks(desired_torque, steer_req, TOYOTA_TORQUE_STEERING_LIMITS)) { + tx = false; + } + } else { + if ((desired_torque != 0) || steer_req) { tx = false; } } + } - // STEERING_LTA angle steering check - if (msg->addr == 0x191U) { - // check the STEER_REQUEST, STEER_REQUEST_2, TORQUE_WIND_DOWN, STEER_ANGLE_CMD signals - bool lta_request = GET_BIT(msg, 0U); - bool lta_request2 = GET_BIT(msg, 25U); - int torque_wind_down = msg->data[5]; - int lta_angle = (msg->data[1] << 8) | msg->data[2]; - lta_angle = to_signed(lta_angle, 16); - - bool steer_control_enabled = lta_request || lta_request2; - if (!toyota_lta) { - // using torque (LKA), block LTA msgs with actuation requests - if (steer_control_enabled || (lta_angle != 0) || (torque_wind_down != 0)) { - tx = false; - } - } else { - // check angle rate limits and inactive angle - if (steer_angle_cmd_checks(lta_angle, steer_control_enabled, TOYOTA_ANGLE_STEERING_LIMITS)) { - tx = false; - } - - if (lta_request != lta_request2) { - tx = false; - } - - // TORQUE_WIND_DOWN is gated on steer request - if (!steer_control_enabled && (torque_wind_down != 0)) { - tx = false; - } - - // TORQUE_WIND_DOWN can only be no or full torque - if ((torque_wind_down != 0) && (torque_wind_down != 100)) { - tx = false; - } - - // check if we should wind down torque - int driver_torque = SAFETY_MIN(SAFETY_ABS(torque_driver.min), SAFETY_ABS(torque_driver.max)); - if ((driver_torque > TOYOTA_LTA_MAX_DRIVER_TORQUE) && (torque_wind_down != 0)) { - tx = false; - } - - int eps_torque = SAFETY_MIN(SAFETY_ABS(torque_meas.min), SAFETY_ABS(torque_meas.max)); - if ((eps_torque > TOYOTA_LTA_MAX_MEAS_TORQUE) && (torque_wind_down != 0)) { - tx = false; - } - } - } - - // STEERING_LTA_2 angle steering check (SecOC) - if (toyota_secoc && (msg->addr == 0x131U)) { - // SecOC cars block any form of LTA actuation for now - bool lta_request = GET_BIT(msg, 3U); // STEERING_LTA_2.STEER_REQUEST - bool lta_request2 = GET_BIT(msg, 0U); // STEERING_LTA_2.STEER_REQUEST_2 - int lta_angle_msb = msg->data[2]; // STEERING_LTA_2.STEER_ANGLE_CMD (MSB) - int lta_angle_lsb = msg->data[3]; // STEERING_LTA_2.STEER_ANGLE_CMD (LSB) - - bool actuation = lta_request || lta_request2 || (lta_angle_msb != 0) || (lta_angle_lsb != 0); - if (actuation) { - tx = false; - } - } - - // STEER: safety check on bytes 2-3 - if (msg->addr == 0x2E4U) { - int desired_torque = (msg->data[1] << 8) | msg->data[2]; - desired_torque = to_signed(desired_torque, 16); - bool steer_req = GET_BIT(msg, 0U); - // When using LTA (angle control), assert no actuation on LKA message - if (!toyota_lta) { - if (steer_torque_cmd_checks(desired_torque, steer_req, TOYOTA_TORQUE_STEERING_LIMITS)) { - tx = false; - } - } else { - if ((desired_torque != 0) || steer_req) { - tx = false; - } - } - } - - // GAS PEDAL: safety check - if (msg->addr == 0x200U) { - if (longitudinal_interceptor_checks(msg)) { - tx = false; - } + // GAS PEDAL: safety check (gas interceptor) + if (msg_matches(msg, 0x200U, 0U)) { + if (longitudinal_interceptor_checks(msg)) { + tx = false; } } // UDS: Only tester present ("\x0F\x02\x3E\x00\x00\x00\x00\x00") allowed on diagnostics address if (msg->addr == 0x750U) { // this address is sub-addressed. only allow tester present to radar (0xF) - bool invalid_uds_msg = (GET_BYTES(msg, 0, 4) != 0x003E020FU) || (GET_BYTES(msg, 4, 4) != 0x0U); + bool invalid_uds_msg = GET_BYTES_64_LE(msg, 0, 8) != 0x00000000003E020FULL; if (invalid_uds_msg) { tx = false; } diff --git a/opendbc_repo/opendbc/safety/modes/volkswagen_common.h b/opendbc_repo/opendbc/safety/modes/volkswagen_common.h index fc5516b3c..cd3b7a595 100644 --- a/opendbc_repo/opendbc/safety/modes/volkswagen_common.h +++ b/opendbc_repo/opendbc/safety/modes/volkswagen_common.h @@ -3,7 +3,7 @@ extern const uint16_t FLAG_VOLKSWAGEN_LONG_CONTROL; const uint16_t FLAG_VOLKSWAGEN_LONG_CONTROL = 1; -static uint8_t volkswagen_crc8_lut_8h2f[256]; // Static lookup table for CRC8 poly 0x2F, aka 8H2F/AUTOSAR +static uint8_t volkswagen_crc8_lut_8h2f[256]; // Static lookup table for CRC8 poly 0x2F, aka 8H2F/AUTOSAR extern bool volkswagen_longitudinal; bool volkswagen_longitudinal = false; @@ -48,44 +48,45 @@ static void volkswagen_common_init(void) { return; } -static uint32_t volkswagen_mqb_meb_get_checksum(const CANPacket_t *msg) { +static uint32_t volkswagen_mxb_get_checksum(const CANPacket_t *msg) { return (uint8_t)msg->data[0]; } -static uint8_t volkswagen_mqb_meb_get_counter(const CANPacket_t *msg) { - // MQB/MEB message counters are consistently found at LSB 8. +static uint8_t volkswagen_mxb_get_counter(const CANPacket_t *msg) { + // MQB/MLB/MEB message counters are consistently found at LSB 8. return (uint8_t)msg->data[1] & 0xFU; } -static uint32_t volkswagen_mqb_meb_compute_crc(const CANPacket_t *msg) { - int len = GET_LEN(msg); - - // This is CRC-8H2F/AUTOSAR with a twist. See the opendbc/car/volkswagen/ implementation - // of this algorithm for a version with explanatory comments. - +// This is CRC-8H2F/AUTOSAR with a counter-dependent data ID. See the +// opendbc/car/volkswagen/ implementation for explanatory comments. +static uint8_t volkswagen_compute_crc(const CANPacket_t *msg, int len, uint8_t salt) { uint8_t crc = 0xFFU; for (int i = 1; i < len; i++) { crc ^= (uint8_t)msg->data[i]; crc = volkswagen_crc8_lut_8h2f[crc]; } + return volkswagen_crc8_lut_8h2f[crc ^ salt] ^ 0xFFU; +} - uint8_t counter = volkswagen_mqb_meb_get_counter(msg); +static uint32_t volkswagen_mxb_compute_crc(const CANPacket_t *msg) { + uint8_t salt = 0; + uint8_t counter = volkswagen_mxb_get_counter(msg); if (msg->addr == MSG_LH_EPS_03) { - crc ^= (uint8_t[]){0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5}[counter]; - } else if (msg->addr == MSG_ESP_05) { - crc ^= (uint8_t[]){0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07}[counter]; - } else if (msg->addr == MSG_TSK_06) { - crc ^= (uint8_t[]){0xC4, 0xE2, 0x4F, 0xE4, 0xF8, 0x2F, 0x56, 0x81, 0x9F, 0xE5, 0x83, 0x44, 0x05, 0x3F, 0x97, 0xDF}[counter]; - } else if (msg->addr == MSG_MOTOR_20) { - crc ^= (uint8_t[]){0xE9, 0x65, 0xAE, 0x6B, 0x7B, 0x35, 0xE5, 0x5F, 0x4E, 0xC7, 0x86, 0xA2, 0xBB, 0xDD, 0xEB, 0xB4}[counter]; - } else if (msg->addr == MSG_GRA_ACC_01) { - crc ^= (uint8_t[]){0x6A, 0x38, 0xB4, 0x27, 0x22, 0xEF, 0xE1, 0xBB, 0xF8, 0x80, 0x84, 0x49, 0xC7, 0x9E, 0x1E, 0x2B}[counter]; - } else { - // Undefined CAN message, CRC check expected to fail + salt = 0xF5U; } - crc = volkswagen_crc8_lut_8h2f[crc]; - - return (uint8_t)(crc ^ 0xFFU); + if (msg->addr == MSG_ESP_05) { + salt = 0x07U; + } + if (msg->addr == MSG_TSK_06) { + salt = (uint8_t[]){0xC4, 0xE2, 0x4F, 0xE4, 0xF8, 0x2F, 0x56, 0x81, 0x9F, 0xE5, 0x83, 0x44, 0x05, 0x3F, 0x97, 0xDF}[counter]; + } + if (msg->addr == MSG_MOTOR_20) { + salt = (uint8_t[]){0xE9, 0x65, 0xAE, 0x6B, 0x7B, 0x35, 0xE5, 0x5F, 0x4E, 0xC7, 0x86, 0xA2, 0xBB, 0xDD, 0xEB, 0xB4}[counter]; + } + if (msg->addr == MSG_GRA_ACC_01) { + salt = (uint8_t[]){0x6A, 0x38, 0xB4, 0x27, 0x22, 0xEF, 0xE1, 0xBB, 0xF8, 0x80, 0x84, 0x49, 0xC7, 0x9E, 0x1E, 0x2B}[counter]; + } + return volkswagen_compute_crc(msg, GET_LEN(msg), salt); } static int volkswagen_mlb_mqb_driver_input_torque(const CANPacket_t *msg) { diff --git a/opendbc_repo/opendbc/safety/modes/volkswagen_meb.h b/opendbc_repo/opendbc/safety/modes/volkswagen_meb.h index adaef46f4..0eb2c12d2 100644 --- a/opendbc_repo/opendbc/safety/modes/volkswagen_meb.h +++ b/opendbc_repo/opendbc/safety/modes/volkswagen_meb.h @@ -33,35 +33,30 @@ static bool volkswagen_meb_alt_crc = false; {.msg = {{MSG_ESP_21, 0, 8, 50U, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, static uint32_t volkswagen_meb_compute_crc(const CANPacket_t *msg) { - int len = GET_LEN(msg); - - uint8_t crc = 0xFFU; - for (int i = 1; i < len; i++) { - crc ^= (uint8_t)msg->data[i]; - crc = volkswagen_crc8_lut_8h2f[crc]; - } - - uint8_t counter = volkswagen_mqb_meb_get_counter(msg); + uint8_t salt = 0; + uint8_t counter = volkswagen_mxb_get_counter(msg); if (msg->addr == MSG_LH_EPS_03) { - crc ^= (uint8_t[]){0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5}[counter]; - } else if (msg->addr == MSG_MOTOR_14) { - crc ^= (uint8_t[]){0x1F, 0x28, 0xC6, 0x85, 0xE6, 0xF8, 0xB0, 0x19, 0x5B, 0x64, 0x35, 0x21, 0xE4, 0xF7, 0x9C, 0x24}[counter]; - } else if (msg->addr == MSG_GRA_ACC_01) { - crc ^= (uint8_t[]){0x6A, 0x38, 0xB4, 0x27, 0x22, 0xEF, 0xE1, 0xBB, 0xF8, 0x80, 0x84, 0x49, 0xC7, 0x9E, 0x1E, 0x2B}[counter]; - } else if (msg->addr == MSG_QFK_01) { - crc ^= (uint8_t[]){0x20, 0xCA, 0x68, 0xD5, 0x1B, 0x31, 0xE2, 0xDA, 0x08, 0x0A, 0xD4, 0xDE, 0x9C, 0xE4, 0x35, 0x5B}[counter]; - } else if (msg->addr == MSG_ESC_51) { - crc ^= (uint8_t[]){0x77, 0x5C, 0xA0, 0x89, 0x4B, 0x7C, 0xBB, 0xD6, 0x1F, 0x6C, 0x4F, 0xF6, 0x20, 0x2B, 0x43, 0xDD}[counter]; - } else if (msg->addr == MSG_ESP_21) { - crc ^= (uint8_t[]){0xB4, 0xEF, 0xF8, 0x49, 0x1E, 0xE5, 0xC2, 0xC0, 0x97, 0x19, 0x3C, 0xC9, 0xF1, 0x98, 0xD6, 0x61}[counter]; - } else if (msg->addr == MSG_Motor_51) { - crc ^= (uint8_t[]){0x77, 0x5C, 0xA0, 0x89, 0x4B, 0x7C, 0xBB, 0xD6, 0x1F, 0x6C, 0x4F, 0xF6, 0x20, 0x2B, 0x43, 0xDD}[counter]; - } else { - // Undefined CAN message, CRC check expected to fail + salt = 0xF5U; } - crc = volkswagen_crc8_lut_8h2f[crc]; - - return (uint8_t)(crc ^ 0xFFU); + if (msg->addr == MSG_MOTOR_14) { + salt = (uint8_t[]){0x1F, 0x28, 0xC6, 0x85, 0xE6, 0xF8, 0xB0, 0x19, 0x5B, 0x64, 0x35, 0x21, 0xE4, 0xF7, 0x9C, 0x24}[counter]; + } + if (msg->addr == MSG_GRA_ACC_01) { + salt = (uint8_t[]){0x6A, 0x38, 0xB4, 0x27, 0x22, 0xEF, 0xE1, 0xBB, 0xF8, 0x80, 0x84, 0x49, 0xC7, 0x9E, 0x1E, 0x2B}[counter]; + } + if (msg->addr == MSG_QFK_01) { + salt = (uint8_t[]){0x20, 0xCA, 0x68, 0xD5, 0x1B, 0x31, 0xE2, 0xDA, 0x08, 0x0A, 0xD4, 0xDE, 0x9C, 0xE4, 0x35, 0x5B}[counter]; + } + if (msg->addr == MSG_ESC_51) { + salt = (uint8_t[]){0x77, 0x5C, 0xA0, 0x89, 0x4B, 0x7C, 0xBB, 0xD6, 0x1F, 0x6C, 0x4F, 0xF6, 0x20, 0x2B, 0x43, 0xDD}[counter]; + } + if (msg->addr == MSG_ESP_21) { + salt = (uint8_t[]){0xB4, 0xEF, 0xF8, 0x49, 0x1E, 0xE5, 0xC2, 0xC0, 0x97, 0x19, 0x3C, 0xC9, 0xF1, 0x98, 0xD6, 0x61}[counter]; + } + if (msg->addr == MSG_Motor_51) { + salt = (uint8_t[]){0x77, 0x5C, 0xA0, 0x89, 0x4B, 0x7C, 0xBB, 0xD6, 0x1F, 0x6C, 0x4F, 0xF6, 0x20, 0x2B, 0x43, 0xDD}[counter]; + } + return volkswagen_compute_crc(msg, GET_LEN(msg), salt); } static uint32_t volkswagen_meb_alt_crc_compute(const CANPacket_t *msg) { @@ -70,34 +65,29 @@ static uint32_t volkswagen_meb_alt_crc_compute(const CANPacket_t *msg) { if (volkswagen_meb_alt_crc) { if (msg->addr == MSG_QFK_01) { len = 28; - } else if (msg->addr == MSG_ESC_51) { + } + if (msg->addr == MSG_ESC_51) { len = 60; - } else if (msg->addr == MSG_Motor_51) { + } + if (msg->addr == MSG_Motor_51) { len = 44; - } else { - len = 0; } } if (len > 0) { - uint8_t crc = 0xFFU; - for (int i = 1; i < len; i++) { - crc ^= (uint8_t)msg->data[i]; - crc = volkswagen_crc8_lut_8h2f[crc]; - } - - uint8_t counter = volkswagen_mqb_meb_get_counter(msg); + uint8_t salt = 0; + uint8_t counter = volkswagen_mxb_get_counter(msg); if (msg->addr == MSG_QFK_01) { - crc ^= (uint8_t[]){0x18, 0x71, 0x10, 0x8D, 0xD7, 0xAA, 0xB0, 0x78, 0xAC, 0x12, 0xAE, 0x0C, 0xDD, 0xF1, 0x85, 0x68}[counter]; - } else if (msg->addr == MSG_ESC_51) { - crc ^= (uint8_t[]){0x69, 0xDC, 0xF9, 0x64, 0x6A, 0xCE, 0x55, 0x2C, 0xC4, 0x38, 0x8F, 0xD1, 0xC6, 0x43, 0xB4, 0xB1}[counter]; - } else if (msg->addr == MSG_Motor_51) { - crc ^= (uint8_t[]){0x2C, 0xB1, 0x1A, 0x75, 0xBB, 0x65, 0x79, 0x47, 0x81, 0x2B, 0xCC, 0x96, 0x17, 0xDB, 0xC0, 0x94}[counter]; - } else { - // Undefined CAN message, CRC check expected to fail + salt = (uint8_t[]){0x18, 0x71, 0x10, 0x8D, 0xD7, 0xAA, 0xB0, 0x78, 0xAC, 0x12, 0xAE, 0x0C, 0xDD, 0xF1, 0x85, 0x68}[counter]; + } + if (msg->addr == MSG_ESC_51) { + salt = (uint8_t[]){0x69, 0xDC, 0xF9, 0x64, 0x6A, 0xCE, 0x55, 0x2C, 0xC4, 0x38, 0x8F, 0xD1, 0xC6, 0x43, 0xB4, 0xB1}[counter]; + } + if (msg->addr == MSG_Motor_51) { + salt = (uint8_t[]){0x2C, 0xB1, 0x1A, 0x75, 0xBB, 0x65, 0x79, 0x47, 0x81, 0x2B, 0xCC, 0x96, 0x17, 0xDB, 0xC0, 0x94}[counter]; } - crc = (uint8_t)(volkswagen_crc8_lut_8h2f[crc] ^ 0xFFU); + uint8_t crc = volkswagen_compute_crc(msg, len, salt); if (crc == msg->data[0]) { ret = crc; } @@ -142,68 +132,66 @@ static safety_config volkswagen_meb_init(uint16_t param) { } static void volkswagen_meb_rx_hook(const CANPacket_t *msg) { - if (msg->bus == 0U) { - // Update in-motion state by sampling wheel speeds - if (msg->addr == MSG_ESC_51) { - uint32_t fl = msg->data[8] | (msg->data[9] << 8); - uint32_t fr = msg->data[10] | (msg->data[11] << 8); - uint32_t rl = msg->data[12] | (msg->data[13] << 8); - uint32_t rr = msg->data[14] | (msg->data[15] << 8); - vehicle_moving = (fr > 0U) || (rr > 0U) || (rl > 0U) || (fl > 0U); - UPDATE_VEHICLE_SPEED((fr + rr + rl + fl) / 4.0 * 0.0075 * KPH_TO_MS); + // Update in-motion state by sampling wheel speeds + if (msg_matches(msg, MSG_ESC_51, 0U)) { + uint32_t fl = msg->data[8] | (msg->data[9] << 8); + uint32_t fr = msg->data[10] | (msg->data[11] << 8); + uint32_t rl = msg->data[12] | (msg->data[13] << 8); + uint32_t rr = msg->data[14] | (msg->data[15] << 8); + vehicle_moving = (fr | rr | rl | fl) != 0U; + UPDATE_VEHICLE_SPEED((fr + rr + rl + fl) / 4.0 * 0.0075 * KPH_TO_MS); + } + + // Check vehicle speed with redundant source + if (msg_matches(msg, MSG_ESP_21, 0U)) { + // Signal: ESP_v_Signal + float esp_speed = ((msg->data[5] << 8) | msg->data[4]) * 0.01 * KPH_TO_MS; + UPDATE_VEHICLE_SPEED_2(esp_speed); + } + + if (msg_matches(msg, MSG_QFK_01, 0U)) { + int current_curvature = ((msg->data[6] & 0x7FU) << 8) | msg->data[5]; + current_curvature *= GET_BIT(msg, 55U) ? 1 : -1; + update_sample(&curvature_state.meas, current_curvature); + } + + if (msg_matches(msg, MSG_LH_EPS_03, 0U)) { + update_sample(&torque_driver, volkswagen_mlb_mqb_driver_input_torque(msg)); + } + + if (msg_matches(msg, MSG_Motor_51, 0U)) { + int acc_status = (msg->data[11] & 0x07U); + bool cruise_engaged = (acc_status == 3) || (acc_status == 4) || (acc_status == 5); + acc_main_on = cruise_engaged || (acc_status == 2); + + if (!acc_main_on) { + controls_allowed = false; } - // Check vehicle speed with redundant source - if (msg->addr == MSG_ESP_21) { - // Signal: ESP_v_Signal - float esp_speed = ((msg->data[5] << 8) | msg->data[4]) * 0.01 * KPH_TO_MS; - UPDATE_VEHICLE_SPEED_2(esp_speed); + int accel_pedal_value = ((msg->data[1] >> 4) & 0x0FU) | ((msg->data[2] & 0x1FU) << 4); + gas_pressed = accel_pedal_value > 0; + } + + if (msg_matches(msg, MSG_GRA_ACC_01, 0U)) { + // Enter controls on falling edge of Set or Resume with main switch on + // Signal: GRA_ACC_01.GRA_Tip_Setzen + // Signal: GRA_ACC_01.GRA_Tip_Wiederaufnahme + bool set_button = GET_BIT(msg, 16U); + bool resume_button = GET_BIT(msg, 19U); + if ((volkswagen_set_button_prev && !set_button) || (volkswagen_resume_button_prev && !resume_button)) { + controls_allowed = acc_main_on; } + volkswagen_set_button_prev = set_button; + volkswagen_resume_button_prev = resume_button; - if (msg->addr == MSG_QFK_01) { - int current_curvature = ((msg->data[6] & 0x7FU) << 8) | msg->data[5]; - current_curvature *= GET_BIT(msg, 55U) ? 1 : -1; - update_sample(&curvature_state.meas, current_curvature); + // Always exit controls on rising edge of Cancel + if (GET_BIT(msg, 13U)) { + controls_allowed = false; } + } - if (msg->addr == MSG_LH_EPS_03) { - update_sample(&torque_driver, volkswagen_mlb_mqb_driver_input_torque(msg)); - } - - if (msg->addr == MSG_Motor_51) { - int acc_status = (msg->data[11] & 0x07U); - bool cruise_engaged = (acc_status == 3) || (acc_status == 4) || (acc_status == 5); - acc_main_on = cruise_engaged || (acc_status == 2); - - if (!acc_main_on) { - controls_allowed = false; - } - - int accel_pedal_value = ((msg->data[1] >> 4) & 0x0FU) | ((msg->data[2] & 0x1FU) << 4); - gas_pressed = accel_pedal_value > 0; - } - - if (msg->addr == MSG_GRA_ACC_01) { - // Enter controls on falling edge of Set or Resume with main switch on - // Signal: GRA_ACC_01.GRA_Tip_Setzen - // Signal: GRA_ACC_01.GRA_Tip_Wiederaufnahme - bool set_button = GET_BIT(msg, 16U); - bool resume_button = GET_BIT(msg, 19U); - if ((volkswagen_set_button_prev && !set_button) || (volkswagen_resume_button_prev && !resume_button)) { - controls_allowed = acc_main_on; - } - volkswagen_set_button_prev = set_button; - volkswagen_resume_button_prev = resume_button; - - // Always exit controls on rising edge of Cancel - if (GET_BIT(msg, 13U)) { - controls_allowed = false; - } - } - - if (msg->addr == MSG_MOTOR_14) { - brake_pressed = GET_BIT(msg, 28U); - } + if (msg_matches(msg, MSG_MOTOR_14, 0U)) { + brake_pressed = GET_BIT(msg, 28U); } } @@ -270,7 +258,7 @@ static bool volkswagen_meb_tx_hook(const CANPacket_t *msg) { .max_steer_power = 125, }; - int desired_curvature_raw = GET_BYTES(msg, 3, 2) & 0x7FFFU; + int desired_curvature_raw = GET_BYTES_LE(msg, 3, 2) & 0x7FFFU; bool desired_curvature_sign = GET_BIT(msg, 39U); if (!desired_curvature_sign) { @@ -292,7 +280,7 @@ const safety_hooks volkswagen_meb_hooks = { .init = volkswagen_meb_init, .rx = volkswagen_meb_rx_hook, .tx = volkswagen_meb_tx_hook, - .get_counter = volkswagen_mqb_meb_get_counter, - .get_checksum = volkswagen_mqb_meb_get_checksum, + .get_counter = volkswagen_mxb_get_counter, + .get_checksum = volkswagen_mxb_get_checksum, .compute_checksum = volkswagen_meb_alt_crc_compute, }; diff --git a/opendbc_repo/opendbc/safety/modes/volkswagen_mlb.h b/opendbc_repo/opendbc/safety/modes/volkswagen_mlb.h index 1390ea7e5..25eeca9d1 100644 --- a/opendbc_repo/opendbc/safety/modes/volkswagen_mlb.h +++ b/opendbc_repo/opendbc/safety/modes/volkswagen_mlb.h @@ -3,11 +3,14 @@ #include "opendbc/safety/declarations.h" #include "opendbc/safety/modes/volkswagen_common.h" - static safety_config volkswagen_mlb_init(uint16_t param) { // Transmit of LS_01 is allowed on bus 0 and 2 to keep compatibility with gateway and camera integration - static const CanMsg VOLKSWAGEN_MLB_STOCK_TX_MSGS[] = {{MSG_HCA_01, 0, 8, .check_relay = true}, {MSG_LDW_02, 0, 8, .check_relay = true}, - {MSG_LS_01, 0, 4, .check_relay = false}, {MSG_LS_01, 2, 4, .check_relay = false}}; + static const CanMsg VOLKSWAGEN_MLB_STOCK_TX_MSGS[] = { + {MSG_HCA_01, 0, 8, .check_relay = true}, + {MSG_LDW_02, 0, 8, .check_relay = true}, + {MSG_LS_01, 0, 4, .check_relay = false}, + {MSG_LS_01, 2, 4, .check_relay = false}, + }; static RxCheck volkswagen_mlb_rx_checks[] = { // TODO: implement checksum validation @@ -26,56 +29,51 @@ static safety_config volkswagen_mlb_init(uint16_t param) { } static void volkswagen_mlb_rx_hook(const CANPacket_t *msg) { - if (msg->bus == 0U) { - // Check all wheel speeds for any movement - // Signals: ESP_03.ESP_[VL|VR|HL|HR]_Radgeschw - if (msg->addr == MSG_ESP_03) { - uint32_t speed = 0; - speed += ((msg->data[3] & 0xFU) << 8) | msg->data[2]; // FL - speed += (msg->data[4] << 4) | (msg->data[3] >> 4); // FR - speed += ((msg->data[6] & 0xFU) << 8) | msg->data[5]; // RL - speed += (msg->data[7] << 4) | (msg->data[6] >> 4); // RR - vehicle_moving = speed > 0U; - } - - // Update driver input torque - if (msg->addr == MSG_LH_EPS_03) { - update_sample(&torque_driver, volkswagen_mlb_mqb_driver_input_torque(msg)); - } - - if (msg->addr == MSG_LS_01) { - // Always exit controls on rising edge of Cancel - // Signal: LS_01.LS_Abbrechen - if (GET_BIT(msg, 13U)) { - controls_allowed = false; - } - } - - // Signal: Motor_03.MO_Fahrpedalrohwert_01 - // Signal: Motor_03.MO_Fahrer_bremst - if (msg->addr == MSG_MOTOR_03) { - gas_pressed = msg->data[6] != 0U; - volkswagen_brake_pedal_switch = GET_BIT(msg, 35U); - } - - if (msg->addr == MSG_ESP_05) { - volkswagen_brake_pressure_detected = GET_BIT(msg, 26U); - } - - brake_pressed = volkswagen_brake_pedal_switch || volkswagen_brake_pressure_detected; - + // Check all wheel speeds for any movement + // Signals: ESP_03.ESP_[VL|VR|HL|HR]_Radgeschw + if (msg_matches(msg, MSG_ESP_03, 0U)) { + uint32_t speed = 0; + speed += ((msg->data[3] & 0xFU) << 8) | msg->data[2]; // FL + speed += (msg->data[4] << 4) | (msg->data[3] >> 4); // FR + speed += ((msg->data[6] & 0xFU) << 8) | msg->data[5]; // RL + speed += (msg->data[7] << 4) | (msg->data[6] >> 4); // RR + vehicle_moving = speed > 0U; } - if (msg->bus == 1U) { - if (msg->addr == MSG_TSK_04) { - // When using stock ACC, enter controls on rising edge of stock ACC engage, exit on disengage - // Signal: TSK_04.TSK_Status_GRA_ACC_02 - int acc_status = (msg->data[7] & 0xC0U) >> 6; - bool cruise_engaged = (acc_status == 1) || (acc_status == 2); + // Update driver input torque + if (msg_matches(msg, MSG_LH_EPS_03, 0U)) { + update_sample(&torque_driver, volkswagen_mlb_mqb_driver_input_torque(msg)); + } - pcm_cruise_check(cruise_engaged); + if (msg_matches(msg, MSG_LS_01, 0U)) { + // Always exit controls on rising edge of Cancel + // Signal: LS_01.LS_Abbrechen + if (GET_BIT(msg, 13U)) { + controls_allowed = false; } } + + // Signal: Motor_03.MO_Fahrpedalrohwert_01 + // Signal: Motor_03.MO_Fahrer_bremst + if (msg_matches(msg, MSG_MOTOR_03, 0U)) { + gas_pressed = msg->data[6] != 0U; + volkswagen_brake_pedal_switch = GET_BIT(msg, 35U); + } + + if (msg_matches(msg, MSG_ESP_05, 0U)) { + volkswagen_brake_pressure_detected = GET_BIT(msg, 26U); + } + + brake_pressed = volkswagen_brake_pedal_switch || volkswagen_brake_pressure_detected; + + if (msg_matches(msg, MSG_TSK_04, 1U)) { + // When using stock ACC, enter controls on rising edge of stock ACC engage, exit on disengage + // Signal: TSK_04.TSK_Status_GRA_ACC_02 + int acc_status = (msg->data[7] & 0xC0U) >> 6; + bool cruise_engaged = (acc_status == 1) || (acc_status == 2); + + pcm_cruise_check(cruise_engaged); + } } static bool volkswagen_mlb_tx_hook(const CANPacket_t *msg) { @@ -116,12 +114,11 @@ static bool volkswagen_mlb_tx_hook(const CANPacket_t *msg) { return tx; } -// TODO: rename these functions to MXB or something const safety_hooks volkswagen_mlb_hooks = { .init = volkswagen_mlb_init, .rx = volkswagen_mlb_rx_hook, .tx = volkswagen_mlb_tx_hook, - .get_counter = volkswagen_mqb_meb_get_counter, - .get_checksum = volkswagen_mqb_meb_get_checksum, - .compute_checksum = volkswagen_mqb_meb_compute_crc, + .get_counter = volkswagen_mxb_get_counter, + .get_checksum = volkswagen_mxb_get_checksum, + .compute_checksum = volkswagen_mxb_compute_crc, }; diff --git a/opendbc_repo/opendbc/safety/modes/volkswagen_mqb.h b/opendbc_repo/opendbc/safety/modes/volkswagen_mqb.h index bf7274648..c0964d533 100644 --- a/opendbc_repo/opendbc/safety/modes/volkswagen_mqb.h +++ b/opendbc_repo/opendbc/safety/modes/volkswagen_mqb.h @@ -6,11 +6,22 @@ static safety_config volkswagen_mqb_init(uint16_t param) { // Transmit of GRA_ACC_01 is allowed on bus 0 and 2 to keep compatibility with gateway and camera integration // MSG_LH_EPS_03: openpilot needs to replace apparent driver steering input torque to pacify VW Emergency Assist - static const CanMsg VOLKSWAGEN_MQB_STOCK_TX_MSGS[] = {{MSG_HCA_01, 0, 8, .check_relay = true}, {MSG_GRA_ACC_01, 0, 8, .check_relay = false}, {MSG_GRA_ACC_01, 2, 8, .check_relay = false}, - {MSG_LDW_02, 0, 8, .check_relay = true}, {MSG_LH_EPS_03, 2, 8, .check_relay = true}}; + static const CanMsg VOLKSWAGEN_MQB_STOCK_TX_MSGS[] = { + {MSG_HCA_01, 0, 8, .check_relay = true}, + {MSG_GRA_ACC_01, 0, 8, .check_relay = false}, + {MSG_GRA_ACC_01, 2, 8, .check_relay = false}, + {MSG_LDW_02, 0, 8, .check_relay = true}, + {MSG_LH_EPS_03, 2, 8, .check_relay = true}, + }; - static const CanMsg VOLKSWAGEN_MQB_LONG_TX_MSGS[] = {{MSG_HCA_01, 0, 8, .check_relay = true}, {MSG_LDW_02, 0, 8, .check_relay = true}, {MSG_LH_EPS_03, 2, 8, .check_relay = true}, - {MSG_ACC_02, 0, 8, .check_relay = true}, {MSG_ACC_06, 0, 8, .check_relay = true}, {MSG_ACC_07, 0, 8, .check_relay = true}}; + static const CanMsg VOLKSWAGEN_MQB_LONG_TX_MSGS[] = { + {MSG_HCA_01, 0, 8, .check_relay = true}, + {MSG_LDW_02, 0, 8, .check_relay = true}, + {MSG_LH_EPS_03, 2, 8, .check_relay = true}, + {MSG_ACC_02, 0, 8, .check_relay = true}, + {MSG_ACC_06, 0, 8, .check_relay = true}, + {MSG_ACC_07, 0, 8, .check_relay = true}, + }; static RxCheck volkswagen_mqb_rx_checks[] = { {.msg = {{MSG_ESP_19, 0, 8, 100U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, @@ -35,80 +46,78 @@ static safety_config volkswagen_mqb_init(uint16_t param) { } static void volkswagen_mqb_rx_hook(const CANPacket_t *msg) { - if (msg->bus == 0U) { - // Update in-motion state by sampling wheel speeds - if (msg->addr == MSG_ESP_19) { - // sum 4 wheel speeds - int speed = 0; - for (uint8_t i = 0U; i < 8U; i += 2U) { - int wheel_speed = msg->data[i] | (msg->data[i + 1U] << 8); - speed += wheel_speed; - } - // Check all wheel speeds for any movement - vehicle_moving = speed > 0; + // Update in-motion state by sampling wheel speeds + if (msg_matches(msg, MSG_ESP_19, 0U)) { + // sum 4 wheel speeds + int speed = 0; + for (uint8_t i = 0U; i < 8U; i += 2U) { + int wheel_speed = msg->data[i] | (msg->data[i + 1U] << 8); + speed += wheel_speed; } - - // Update driver input torque samples - // Signal: LH_EPS_03.EPS_Lenkmoment (absolute torque) - // Signal: LH_EPS_03.EPS_VZ_Lenkmoment (direction) - if (msg->addr == MSG_LH_EPS_03) { - update_sample(&torque_driver, volkswagen_mlb_mqb_driver_input_torque(msg)); - } - - if (msg->addr == MSG_TSK_06) { - // When using stock ACC, enter controls on rising edge of stock ACC engage, exit on disengage - // Always exit controls on main switch off - // Signal: TSK_06.TSK_Status - int acc_status = (msg->data[3] & 0x7U); - bool cruise_engaged = (acc_status == 3) || (acc_status == 4) || (acc_status == 5); - acc_main_on = cruise_engaged || (acc_status == 2); - - if (!volkswagen_longitudinal) { - pcm_cruise_check(cruise_engaged); - } - - if (!acc_main_on) { - controls_allowed = false; - } - } - - if (msg->addr == MSG_GRA_ACC_01) { - // If using openpilot longitudinal, enter controls on falling edge of Set or Resume with main switch on - // Signal: GRA_ACC_01.GRA_Tip_Setzen - // Signal: GRA_ACC_01.GRA_Tip_Wiederaufnahme - if (volkswagen_longitudinal) { - bool set_button = GET_BIT(msg, 16U); - bool resume_button = GET_BIT(msg, 19U); - if ((volkswagen_set_button_prev && !set_button) || (volkswagen_resume_button_prev && !resume_button)) { - controls_allowed = acc_main_on; - } - volkswagen_set_button_prev = set_button; - volkswagen_resume_button_prev = resume_button; - } - // Always exit controls on rising edge of Cancel - // Signal: GRA_ACC_01.GRA_Abbrechen - if (GET_BIT(msg, 13U)) { - controls_allowed = false; - } - } - - // Signal: Motor_20.MO_Fahrpedalrohwert_01 - if (msg->addr == MSG_MOTOR_20) { - gas_pressed = ((GET_BYTES(msg, 0, 4) >> 12) & 0xFFU) != 0U; - } - - // Signal: Motor_14.MO_Fahrer_bremst (ECU detected brake pedal switch F63) - if (msg->addr == MSG_MOTOR_14) { - volkswagen_brake_pedal_switch = GET_BIT(msg, 28U); - } - - // Signal: ESP_05.ESP_Fahrer_bremst (ESP detected driver brake pressure above platform specified threshold) - if (msg->addr == MSG_ESP_05) { - volkswagen_brake_pressure_detected = GET_BIT(msg, 26U); - } - - brake_pressed = volkswagen_brake_pedal_switch || volkswagen_brake_pressure_detected; + // Check all wheel speeds for any movement + vehicle_moving = speed > 0; } + + // Update driver input torque samples + // Signal: LH_EPS_03.EPS_Lenkmoment (absolute torque) + // Signal: LH_EPS_03.EPS_VZ_Lenkmoment (direction) + if (msg_matches(msg, MSG_LH_EPS_03, 0U)) { + update_sample(&torque_driver, volkswagen_mlb_mqb_driver_input_torque(msg)); + } + + if (msg_matches(msg, MSG_TSK_06, 0U)) { + // When using stock ACC, enter controls on rising edge of stock ACC engage, exit on disengage + // Always exit controls on main switch off + // Signal: TSK_06.TSK_Status + int acc_status = (msg->data[3] & 0x7U); + bool cruise_engaged = (acc_status == 3) || (acc_status == 4) || (acc_status == 5); + acc_main_on = cruise_engaged || (acc_status == 2); + + if (!volkswagen_longitudinal) { + pcm_cruise_check(cruise_engaged); + } + + if (!acc_main_on) { + controls_allowed = false; + } + } + + if (msg_matches(msg, MSG_GRA_ACC_01, 0U)) { + // If using openpilot longitudinal, enter controls on falling edge of Set or Resume with main switch on + // Signal: GRA_ACC_01.GRA_Tip_Setzen + // Signal: GRA_ACC_01.GRA_Tip_Wiederaufnahme + if (volkswagen_longitudinal) { + bool set_button = GET_BIT(msg, 16U); + bool resume_button = GET_BIT(msg, 19U); + if ((volkswagen_set_button_prev && !set_button) || (volkswagen_resume_button_prev && !resume_button)) { + controls_allowed = acc_main_on; + } + volkswagen_set_button_prev = set_button; + volkswagen_resume_button_prev = resume_button; + } + // Always exit controls on rising edge of Cancel + // Signal: GRA_ACC_01.GRA_Abbrechen + if (GET_BIT(msg, 13U)) { + controls_allowed = false; + } + } + + // Signal: Motor_20.MO_Fahrpedalrohwert_01 + if (msg_matches(msg, MSG_MOTOR_20, 0U)) { + gas_pressed = ((GET_BYTES_LE(msg, 0, 4) >> 12) & 0xFFU) != 0U; + } + + // Signal: Motor_14.MO_Fahrer_bremst (ECU detected brake pedal switch F63) + if (msg_matches(msg, MSG_MOTOR_14, 0U)) { + volkswagen_brake_pedal_switch = GET_BIT(msg, 28U); + } + + // Signal: ESP_05.ESP_Fahrer_bremst (ESP detected driver brake pressure above platform specified threshold) + if (msg_matches(msg, MSG_ESP_05, 0U)) { + volkswagen_brake_pressure_detected = GET_BIT(msg, 26U); + } + + brake_pressed = volkswagen_brake_pedal_switch || volkswagen_brake_pressure_detected; } static bool volkswagen_mqb_tx_hook(const CANPacket_t *msg) { @@ -183,7 +192,7 @@ const safety_hooks volkswagen_mqb_hooks = { .init = volkswagen_mqb_init, .rx = volkswagen_mqb_rx_hook, .tx = volkswagen_mqb_tx_hook, - .get_counter = volkswagen_mqb_meb_get_counter, - .get_checksum = volkswagen_mqb_meb_get_checksum, - .compute_checksum = volkswagen_mqb_meb_compute_crc, + .get_counter = volkswagen_mxb_get_counter, + .get_checksum = volkswagen_mxb_get_checksum, + .compute_checksum = volkswagen_mxb_compute_crc, }; diff --git a/opendbc_repo/opendbc/safety/modes/volkswagen_pq.h b/opendbc_repo/opendbc/safety/modes/volkswagen_pq.h index c3b2184bd..ddad3f69b 100644 --- a/opendbc_repo/opendbc/safety/modes/volkswagen_pq.h +++ b/opendbc_repo/opendbc/safety/modes/volkswagen_pq.h @@ -23,9 +23,9 @@ static uint8_t volkswagen_pq_get_counter(const CANPacket_t *msg) { if (msg->addr == MSG_LENKHILFE_3) { counter = (uint8_t)(msg->data[1] & 0xF0U) >> 4; - } else if (msg->addr == MSG_GRA_NEU) { + } + if (msg->addr == MSG_GRA_NEU) { counter = (uint8_t)(msg->data[2] & 0xF0U) >> 4; - } else { } return counter; @@ -48,11 +48,19 @@ static uint32_t volkswagen_pq_compute_checksum(const CANPacket_t *msg) { static safety_config volkswagen_pq_init(uint16_t param) { // Transmit of GRA_Neu is allowed on bus 0 and 2 to keep compatibility with gateway and camera integration - static const CanMsg VOLKSWAGEN_PQ_STOCK_TX_MSGS[] = {{MSG_HCA_1, 0, 5, .check_relay = true}, {MSG_LDW_1, 0, 8, .check_relay = true}, - {MSG_GRA_NEU, 0, 4, .check_relay = false}, {MSG_GRA_NEU, 2, 4, .check_relay = false}}; + static const CanMsg VOLKSWAGEN_PQ_STOCK_TX_MSGS[] = { + {MSG_HCA_1, 0, 5, .check_relay = true}, + {MSG_LDW_1, 0, 8, .check_relay = true}, + {MSG_GRA_NEU, 0, 4, .check_relay = false}, + {MSG_GRA_NEU, 2, 4, .check_relay = false}, + }; - static const CanMsg VOLKSWAGEN_PQ_LONG_TX_MSGS[] = {{MSG_HCA_1, 0, 5, .check_relay = true}, {MSG_LDW_1, 0, 8, .check_relay = true}, - {MSG_ACC_SYSTEM, 0, 8, .check_relay = true}, {MSG_ACC_GRA_ANZEIGE, 0, 8, .check_relay = true}}; + static const CanMsg VOLKSWAGEN_PQ_LONG_TX_MSGS[] = { + {MSG_HCA_1, 0, 5, .check_relay = true}, + {MSG_LDW_1, 0, 8, .check_relay = true}, + {MSG_ACC_SYSTEM, 0, 8, .check_relay = true}, + {MSG_ACC_GRA_ANZEIGE, 0, 8, .check_relay = true}, + }; static RxCheck volkswagen_pq_rx_checks[] = { {.msg = {{MSG_LENKHILFE_3, 0, 6, 100U, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, @@ -75,72 +83,70 @@ static safety_config volkswagen_pq_init(uint16_t param) { } static void volkswagen_pq_rx_hook(const CANPacket_t *msg) { - if (msg->bus == 0U) { - // Update in-motion state from speed value. - // Signal: Bremse_1.BR1_Rad_kmh - if (msg->addr == MSG_BREMSE_1) { - int speed = ((msg->data[2] & 0xFEU) >> 1) | (msg->data[3] << 7); - vehicle_moving = speed > 0; + // Update in-motion state from speed value. + // Signal: Bremse_1.BR1_Rad_kmh + if (msg_matches(msg, MSG_BREMSE_1, 0U)) { + int speed = ((msg->data[2] & 0xFEU) >> 1) | (msg->data[3] << 7); + vehicle_moving = speed > 0; + } + + // Update driver input torque samples + // Signal: Lenkhilfe_3.LH3_LM (absolute torque) + // Signal: Lenkhilfe_3.LH3_LMSign (direction) + if (msg_matches(msg, MSG_LENKHILFE_3, 0U)) { + int torque_driver_new = msg->data[2] | ((msg->data[3] & 0x3U) << 8); + int sign = (msg->data[3] & 0x4U) >> 2; + if (sign == 1) { + torque_driver_new *= -1; } + update_sample(&torque_driver, torque_driver_new); + } - // Update driver input torque samples - // Signal: Lenkhilfe_3.LH3_LM (absolute torque) - // Signal: Lenkhilfe_3.LH3_LMSign (direction) - if (msg->addr == MSG_LENKHILFE_3) { - int torque_driver_new = msg->data[2] | ((msg->data[3] & 0x3U) << 8); - int sign = (msg->data[3] & 0x4U) >> 2; - if (sign == 1) { - torque_driver_new *= -1; - } - update_sample(&torque_driver, torque_driver_new); - } - - if (volkswagen_longitudinal) { - if (msg->addr == MSG_MOTOR_5) { - // ACC main switch on is a prerequisite to enter controls, exit controls immediately on main switch off - // Signal: Motor_5.MO5_GRA_Hauptsch - acc_main_on = GET_BIT(msg, 50U); - if (!acc_main_on) { - controls_allowed = false; - } - } - - if (msg->addr == MSG_GRA_NEU) { - // If ACC main switch is on, enter controls on falling edge of Set or Resume - // Signal: GRA_Neu.GRA_Neu_Setzen - // Signal: GRA_Neu.GRA_Neu_Recall - bool set_button = GET_BIT(msg, 16U); - bool resume_button = GET_BIT(msg, 17U); - if ((volkswagen_set_button_prev && !set_button) || (volkswagen_resume_button_prev && !resume_button)) { - controls_allowed = acc_main_on; - } - volkswagen_set_button_prev = set_button; - volkswagen_resume_button_prev = resume_button; - // Exit controls on rising edge of Cancel, override Set/Resume if present simultaneously - // Signal: GRA_ACC_01.GRA_Abbrechen - if (GET_BIT(msg, 9U)) { - controls_allowed = false; - } - } - } else { - if (msg->addr == MSG_MOTOR_2) { - // Enter controls on rising edge of stock ACC, exit controls if stock ACC disengages - // Signal: Motor_2.MO2_Sta_GRA - int acc_status = (msg->data[2] & 0xC0U) >> 6; - bool cruise_engaged = (acc_status == 1) || (acc_status == 2); - pcm_cruise_check(cruise_engaged); + if (volkswagen_longitudinal) { + if (msg_matches(msg, MSG_MOTOR_5, 0U)) { + // ACC main switch on is a prerequisite to enter controls, exit controls immediately on main switch off + // Signal: Motor_5.MO5_GRA_Hauptsch + acc_main_on = GET_BIT(msg, 50U); + if (!acc_main_on) { + controls_allowed = false; } } - // Signal: Motor_3.MO3_Pedalwert - if (msg->addr == MSG_MOTOR_3) { - gas_pressed = (msg->data[2]); + if (msg_matches(msg, MSG_GRA_NEU, 0U)) { + // If ACC main switch is on, enter controls on falling edge of Set or Resume + // Signal: GRA_Neu.GRA_Neu_Setzen + // Signal: GRA_Neu.GRA_Neu_Recall + bool set_button = GET_BIT(msg, 16U); + bool resume_button = GET_BIT(msg, 17U); + if ((volkswagen_set_button_prev && !set_button) || (volkswagen_resume_button_prev && !resume_button)) { + controls_allowed = acc_main_on; + } + volkswagen_set_button_prev = set_button; + volkswagen_resume_button_prev = resume_button; + // Exit controls on rising edge of Cancel, override Set/Resume if present simultaneously + // Signal: GRA_ACC_01.GRA_Abbrechen + if (GET_BIT(msg, 9U)) { + controls_allowed = false; + } } + } else { + if (msg_matches(msg, MSG_MOTOR_2, 0U)) { + // Enter controls on rising edge of stock ACC, exit controls if stock ACC disengages + // Signal: Motor_2.MO2_Sta_GRA + int acc_status = (msg->data[2] & 0xC0U) >> 6; + bool cruise_engaged = (acc_status == 1) || (acc_status == 2); + pcm_cruise_check(cruise_engaged); + } + } - // Signal: Motor_2.MO2_BLS - if (msg->addr == MSG_MOTOR_2) { - brake_pressed = (msg->data[2] & 0x1U); - } + // Signal: Motor_3.MO3_Pedalwert + if (msg_matches(msg, MSG_MOTOR_3, 0U)) { + gas_pressed = (msg->data[2]); + } + + // Signal: Motor_2.MO2_BLS + if (msg_matches(msg, MSG_MOTOR_2, 0U)) { + brake_pressed = (msg->data[2] & 0x1U); } } diff --git a/opendbc_repo/opendbc/safety/safety.h b/opendbc_repo/opendbc/safety/safety.h index 256480127..9b3da25f7 100644 --- a/opendbc_repo/opendbc/safety/safety.h +++ b/opendbc_repo/opendbc/safety/safety.h @@ -30,9 +30,10 @@ #include "opendbc/safety/modes/elm327.h" #include "opendbc/safety/modes/body.h" #include "opendbc/safety/modes/psa.h" +#include "opendbc/safety/modes/byd.h" #include "opendbc/safety/modes/hyundai_canfd.h" -uint32_t GET_BYTES(const CANPacket_t *msg, int start, int len) { +uint32_t GET_BYTES_LE(const CANPacket_t *msg, int start, int len) { uint32_t ret = 0U; for (int i = 0; i < len; i++) { const uint32_t shift = i * 8; @@ -41,6 +42,16 @@ uint32_t GET_BYTES(const CANPacket_t *msg, int start, int len) { return ret; } +// Read up to eight bytes in little-endian order, without alignment assumptions. +uint64_t GET_BYTES_64_LE(const CANPacket_t *msg, int start, int len) { + uint64_t ret = 0U; + for (int i = 0; i < len; i++) { + const uint32_t shift = i * 8; + ret |= ((uint64_t)msg->data[start + i]) << shift; + } + return ret; +} + const int MAX_WRONG_COUNTERS = 5; // This can be set by the safety hooks @@ -114,16 +125,12 @@ static bool is_msg_valid(RxCheck addr_list[], int index) { } static int get_addr_check_index(const CANPacket_t *msg, RxCheck addr_list[], const int len) { - int addr = msg->addr; - int length = GET_LEN(msg); - int index = -1; for (int i = 0; i < len; i++) { // if multiple msgs are allowed, determine which one is present on the bus if (!addr_list[i].status.msg_seen) { for (uint8_t j = 0U; (j < MAX_ADDR_CHECK_MSGS) && (addr_list[i].msg[j].addr != 0); j++) { - if ((addr == addr_list[i].msg[j].addr) && (msg->bus == addr_list[i].msg[j].bus) && - (length == addr_list[i].msg[j].len)) { + if (msg_matches(msg, addr_list[i].msg[j].addr, addr_list[i].msg[j].bus, addr_list[i].msg[j].len)) { addr_list[i].status.index = j; addr_list[i].status.msg_seen = true; break; @@ -133,8 +140,7 @@ static int get_addr_check_index(const CANPacket_t *msg, RxCheck addr_list[], con if (addr_list[i].status.msg_seen) { int idx = addr_list[i].status.index; - if ((addr == addr_list[i].msg[idx].addr) && (msg->bus == addr_list[i].msg[idx].bus) && - (length == addr_list[i].msg[idx].len)) { + if (msg_matches(msg, addr_list[i].msg[idx].addr, addr_list[i].msg[idx].bus, addr_list[i].msg[idx].len)) { index = i; break; } @@ -228,12 +234,9 @@ bool safety_rx_hook(const CANPacket_t *msg) { } static bool tx_msg_safety_check(const CANPacket_t *msg, const CanMsg msg_list[], int len) { - int addr = msg->addr; - int length = GET_LEN(msg); - bool whitelisted = false; for (int i = 0; i < len; i++) { - if ((addr == msg_list[i].addr) && (msg->bus == msg_list[i].bus) && (length == msg_list[i].len)) { + if (msg_matches(msg, msg_list[i].addr, msg_list[i].bus, msg_list[i].len)) { whitelisted = true; break; } @@ -321,31 +324,29 @@ void gen_crc_lookup_table_16(uint16_t poly, uint16_t crc_lut[]) { } // 1Hz safety function called by main. Now just a check for lagging safety messages -void safety_tick(const safety_config *cfg) { +void safety_tick(void) { const uint8_t MAX_MISSED_MSGS = 10U; bool rx_checks_invalid = false; uint32_t ts = microsecond_timer_get(); - if (cfg != NULL) { - for (int i=0; i < cfg->rx_checks_len; i++) { - uint32_t elapsed_time = safety_get_ts_elapsed(ts, cfg->rx_checks[i].status.last_timestamp); - // lag threshold is max of: 1s and MAX_MISSED_MSGS * expected timestep. - // Quite conservative to not risk false triggers. - // 2s of lag is worse case, since the function is called at 1Hz - uint32_t frequency = cfg->rx_checks[i].msg[cfg->rx_checks[i].status.index].frequency; - uint32_t timestep = 1e6 / frequency; - bool lagging = elapsed_time > SAFETY_MAX(timestep * MAX_MISSED_MSGS, 1e6); - cfg->rx_checks[i].status.lagging = lagging; - if (lagging) { - controls_allowed = false; - mads_exit_controls(MADS_DISENGAGE_REASON_LAG); - } + for (int i=0; i < current_safety_config.rx_checks_len; i++) { + uint32_t elapsed_time = safety_get_ts_elapsed(ts, current_safety_config.rx_checks[i].status.last_timestamp); + // lag threshold is max of: 1s and MAX_MISSED_MSGS * expected timestep. + // Quite conservative to not risk false triggers. + // 2s of lag is worse case, since the function is called at 1Hz + uint32_t frequency = current_safety_config.rx_checks[i].msg[current_safety_config.rx_checks[i].status.index].frequency; + uint32_t timestep = 1e6 / frequency; + bool lagging = elapsed_time > SAFETY_MAX(timestep * MAX_MISSED_MSGS, 1e6); + current_safety_config.rx_checks[i].status.lagging = lagging; + if (lagging) { + controls_allowed = false; + mads_exit_controls(MADS_DISENGAGE_REASON_LAG); + } - // enforce minimum frequency for safety-relevant messages - bool frequency_invalid = !cfg->rx_checks[i].msg[cfg->rx_checks[i].status.index].ignore_frequency_check && (frequency < 10U); - if (lagging || frequency_invalid || !is_msg_valid(cfg->rx_checks, i)) { - rx_checks_invalid = true; - controls_allowed = false; - } + // enforce minimum frequency for safety-relevant messages + bool frequency_invalid = !current_safety_config.rx_checks[i].msg[current_safety_config.rx_checks[i].status.index].ignore_frequency_check && (frequency < 10U); + if (lagging || frequency_invalid || !is_msg_valid(current_safety_config.rx_checks, i)) { + rx_checks_invalid = true; + controls_allowed = false; } } @@ -395,10 +396,7 @@ static void relay_malfunction_reset(void) { // resets values and min/max for sample_t struct static void reset_sample(struct sample_t *sample) { - for (int i = 0; i < MAX_SAMPLE_VALS; i++) { - sample->values[i] = 0; - } - update_sample(sample, 0); + *sample = (struct sample_t){0}; } int set_safety_hooks(uint16_t mode, uint16_t param) { @@ -428,6 +426,7 @@ int set_safety_hooks(uint16_t mode, uint16_t param) { {SAFETY_GWM, &gwm_hooks}, {SAFETY_CHRYSLER_CUSW, &chrysler_cusw_hooks}, {SAFETY_PSA, &psa_hooks}, + {SAFETY_BYD, &byd_hooks}, {SAFETY_SUBARU_PREGLOBAL, &subaru_preglobal_hooks}, {SAFETY_VOLKSWAGEN_MLB, &volkswagen_mlb_hooks}, {SAFETY_VOLKSWAGEN_PQ, &volkswagen_pq_hooks}, @@ -455,11 +454,7 @@ int set_safety_hooks(uint16_t mode, uint16_t param) { rt_angle_msgs = 0; ts_angle_check_last = 0; desired_angle_last = 0; - curvature_state.desired_last = 0; - curvature_state.rt_msgs = 0; - curvature_state.rt_msgs_prev = 0; - curvature_state.ts_check_last = 0; - curvature_state.steer_power_last = 0; + curvature_state = (CurvatureSteeringState){0}; ts_torque_check_last = 0; ts_steer_req_mismatch_last = 0; valid_steer_req_count = 0; @@ -475,17 +470,12 @@ int set_safety_hooks(uint16_t mode, uint16_t param) { reset_sample(&torque_meas); reset_sample(&torque_driver); reset_sample(&angle_meas); - reset_sample(&curvature_state.meas); controls_allowed = false; relay_malfunction_reset(); safety_rx_checks_invalid = false; - current_safety_config.rx_checks = NULL; - current_safety_config.rx_checks_len = 0; - current_safety_config.tx_msgs = NULL; - current_safety_config.tx_msgs_len = 0; - current_safety_config.disable_forwarding = false; + current_safety_config = (safety_config){0}; int set_status = -1; // not set int hook_config_count = sizeof(safety_hook_registry) / sizeof(safety_hook_config); @@ -498,12 +488,7 @@ int set_safety_hooks(uint16_t mode, uint16_t param) { } } if ((set_status == 0) && (current_hooks->init != NULL)) { - safety_config cfg = current_hooks->init(param); - current_safety_config.rx_checks = cfg.rx_checks; - current_safety_config.rx_checks_len = cfg.rx_checks_len; - current_safety_config.tx_msgs = cfg.tx_msgs; - current_safety_config.tx_msgs_len = cfg.tx_msgs_len; - current_safety_config.disable_forwarding = cfg.disable_forwarding; + current_safety_config = current_hooks->init(param); // reset all dynamic fields in addr struct for (int j = 0; j < current_safety_config.rx_checks_len; j++) { current_safety_config.rx_checks[j].status = (RxStatus){0}; diff --git a/opendbc_repo/opendbc/safety/tests/common.py b/opendbc_repo/opendbc/safety/tests/common.py index 90a0df3cf..d94bdf26c 100644 --- a/opendbc_repo/opendbc/safety/tests/common.py +++ b/opendbc_repo/opendbc/safety/tests/common.py @@ -75,12 +75,24 @@ def add_regen_tests(cls): class SafetyTestBase(unittest.TestCase): - safety: libsafety_py.LibSafety | None + safety: libsafety_py.LibSafety + DBC: str | None = None + packer: CANPackerSafety + SAFETY_MODEL: int | None + SAFETY_PARAM = 0 + + def setUp(self): + self.safety = libsafety_py.libsafety + if self.DBC is not None: + self.packer = CANPackerSafety(self.DBC) + if self.SAFETY_MODEL is not None: + self.safety.set_safety_hooks(self.SAFETY_MODEL, self.SAFETY_PARAM) + self.safety.init_tests() @classmethod def setUpClass(cls): - if cls.__name__ == "SafetyTestBase": - cls.safety = None + # Classes defined in this module and classes named *Base are shared test helpers. + if cls.__module__ == __name__ or cls.__name__.endswith('Base'): raise unittest.SkipTest def _reset_safety_hooks(self): @@ -157,12 +169,6 @@ class LongitudinalAccelSafetyTest(SafetyTestBase, abc.ABC): MIN_ACCEL: float = -3.5 INACTIVE_ACCEL: float = 0.0 - @classmethod - def setUpClass(cls): - if cls.__name__ == "LongitudinalAccelSafetyTest": - cls.safety = None - raise unittest.SkipTest - @abc.abstractmethod def _accel_msg(self, accel: float): pass @@ -235,12 +241,6 @@ class TorqueSteeringSafetyTestBase(SafetyTestBase, abc.ABC): NO_STEER_REQ_BIT = False - @classmethod - def setUpClass(cls): - if cls.__name__ == "TorqueSteeringSafetyTestBase": - cls.safety = None - raise unittest.SkipTest - @property def MAX_TORQUE(self): return max(self.MAX_TORQUE_LOOKUP[1]) @@ -322,12 +322,6 @@ class TorqueSteeringSafetyTestBase(SafetyTestBase, abc.ABC): class SteerRequestCutSafetyTest(TorqueSteeringSafetyTestBase, abc.ABC): - @classmethod - def setUpClass(cls): - if cls.__name__ == "SteerRequestCutSafetyTest": - cls.safety = None - raise unittest.SkipTest - # Safety around steering request bit mismatch tolerance MIN_VALID_STEERING_FRAMES: int MAX_INVALID_STEERING_FRAMES: int @@ -347,7 +341,9 @@ class SteerRequestCutSafetyTest(TorqueSteeringSafetyTestBase, abc.ABC): - We can always recover from violations if steer_req=1 """ - for min_valid_steer_frames in range(self.MIN_VALID_STEERING_FRAMES * 2): + # dense around the threshold, sparse elsewhere (the valid frame counter saturates at MIN_VALID_STEERING_FRAMES) + valid_frames = self._boundary_values([self.MIN_VALID_STEERING_FRAMES], 0, self.MIN_VALID_STEERING_FRAMES * 2, sparse_count=10) + for min_valid_steer_frames in map(int, valid_frames): # Reset match count and rt timer to allow cut (valid_steer_req_count, ts_steer_req_mismatch_last) self.safety.init_tests() self.safety.set_timer(self.MIN_VALID_STEERING_RT_INTERVAL) @@ -365,7 +361,7 @@ class SteerRequestCutSafetyTest(TorqueSteeringSafetyTestBase, abc.ABC): self.assertEqual(should_tx and idx < self.MAX_INVALID_STEERING_FRAMES, tx) # Keep blocking after one steer_req mismatch - for _ in range(100): + for _ in range(10): self.assertFalse(self._tx(self._torque_cmd_msg(self.MAX_TORQUE, steer_req=0))) # Make sure we can recover @@ -423,7 +419,7 @@ class SteerRequestCutSafetyTest(TorqueSteeringSafetyTestBase, abc.ABC): self.assertEqual(should_tx, self._tx(self._torque_cmd_msg(self.MAX_TORQUE, steer_req=0))) # Keep blocking after one steer_req mismatch - for _ in range(100): + for _ in range(10): self.assertFalse(self._tx(self._torque_cmd_msg(self.MAX_TORQUE, steer_req=0))) # Make sure we can recover @@ -437,12 +433,6 @@ class DriverTorqueSteeringSafetyTest(TorqueSteeringSafetyTestBase, abc.ABC): DRIVER_TORQUE_ALLOWANCE = 0 DRIVER_TORQUE_FACTOR = 0 - @classmethod - def setUpClass(cls): - if cls.__name__ == "DriverTorqueSteeringSafetyTest": - cls.safety = None - raise unittest.SkipTest - @abc.abstractmethod def _torque_driver_msg(self, torque): pass @@ -451,6 +441,21 @@ class DriverTorqueSteeringSafetyTest(TorqueSteeringSafetyTestBase, abc.ABC): for _ in range(MAX_SAMPLE_VALS): self._rx(self._torque_driver_msg(torque)) + def test_driver_torque_measurements(self): + for torque in (50, -50, *([0] * (MAX_SAMPLE_VALS - 2))): + self.assertTrue(self._rx(self._torque_driver_msg(torque))) + + self.assertEqual(-50, self.safety.get_torque_driver_min()) + self.assertEqual(50, self.safety.get_torque_driver_max()) + + self.assertTrue(self._rx(self._torque_driver_msg(0))) + self.assertEqual(0, self.safety.get_torque_driver_max()) + self.assertEqual(-50, self.safety.get_torque_driver_min()) + + self.assertTrue(self._rx(self._torque_driver_msg(0))) + self.assertEqual(0, self.safety.get_torque_driver_max()) + self.assertEqual(0, self.safety.get_torque_driver_min()) + def test_non_realtime_limit_up(self): self._reset_torque_driver_measurement(0) super().test_non_realtime_limit_up() @@ -538,12 +543,6 @@ class MotorTorqueSteeringSafetyTest(TorqueSteeringSafetyTestBase, abc.ABC): MAX_TORQUE_ERROR = 0 TORQUE_MEAS_TOLERANCE = 0 - @classmethod - def setUpClass(cls): - if cls.__name__ == "MotorTorqueSteeringSafetyTest": - cls.safety = None - raise unittest.SkipTest - @abc.abstractmethod def _torque_meas_msg(self, torque): pass @@ -571,23 +570,18 @@ class MotorTorqueSteeringSafetyTest(TorqueSteeringSafetyTestBase, abc.ABC): self.assertEqual(send, self._tx(self._torque_cmd_msg(torque))) def test_non_realtime_limit_down(self): - self.safety.set_controls_allowed(True) - for speed in self._torque_speed_range: self._reset_speed_measurement(speed) max_torque = self._get_max_torque(speed) - torque_meas = max_torque - self.MAX_TORQUE_ERROR - 50 - self.safety.set_rt_torque_last(max_torque) - self.safety.set_torque_meas(torque_meas, torque_meas) - self.safety.set_desired_torque_last(max_torque) - self.assertTrue(self._tx(self._torque_cmd_msg(max_torque - self.MAX_RATE_DOWN))) - - self.safety.set_rt_torque_last(max_torque) - self.safety.set_torque_meas(torque_meas, torque_meas) - self.safety.set_desired_torque_last(max_torque) - self.assertFalse(self._tx(self._torque_cmd_msg(max_torque - self.MAX_RATE_DOWN + 1))) + for sign in (-1, 1): + for delta in (self.MAX_RATE_DOWN, self.MAX_RATE_DOWN - 1): + self.safety.set_controls_allowed(True) + self.safety.set_rt_torque_last(sign * max_torque) + self.safety.set_torque_meas(sign * torque_meas, sign * torque_meas) + self.safety.set_desired_torque_last(sign * max_torque) + self.assertEqual(delta == self.MAX_RATE_DOWN, self._tx(self._torque_cmd_msg(sign * (max_torque - delta)))) def test_exceed_torque_sensor(self): self.safety.set_controls_allowed(True) @@ -659,12 +653,6 @@ class MotorTorqueSteeringSafetyTest(TorqueSteeringSafetyTestBase, abc.ABC): class VehicleSpeedSafetyTest(SafetyTestBase): - @classmethod - def setUpClass(cls): - if cls.__name__ == "VehicleSpeedSafetyTest": - cls.safety = None - raise unittest.SkipTest - @abc.abstractmethod def _speed_msg(self, speed): pass @@ -686,12 +674,6 @@ class AngleSteeringSafetyTest(VehicleSpeedSafetyTest): # Real time limits LATERAL_FREQUENCY: int = -1 # Hz - @classmethod - def setUpClass(cls): - if cls.__name__ == "AngleSteeringSafetyTest": - cls.safety = None - raise unittest.SkipTest - @abc.abstractmethod def _angle_cmd_msg(self, angle: float, enabled: bool, increment_timer: bool = True): pass @@ -831,12 +813,6 @@ class CurvatureSteeringSafetyTest(VehicleSpeedSafetyTest): CURVATURE_TO_CAN: float SEND_RATE: float - @classmethod - def setUpClass(cls): - if cls.__name__ == "CurvatureSteeringSafetyTest": - cls.safety = None - raise unittest.SkipTest - @abc.abstractmethod def _curvature_cmd_msg(self, curvature: float, steer_req: bool): pass @@ -942,12 +918,6 @@ class SafetyTest(SafetyTestBase): FWD_BLACKLISTED_ADDRS: dict[int, list[int]] = {} # {bus: [addr]} FWD_BUS_LOOKUP: dict[int, int] = {0: 2, 2: 0} - @classmethod - def setUpClass(cls): - if cls.__name__ == "SafetyTest" or cls.__name__.endswith('Base'): - cls.safety = None - raise unittest.SkipTest - # ***** standard tests for all safety modes ***** def test_tx_msg_in_scanned_range(self): @@ -969,9 +939,10 @@ class SafetyTest(SafetyTestBase): self.assertEqual(fwd_bus, self.safety.safety_fwd_hook(bus, addr), f"{addr=:#x} from {bus=} to {fwd_bus=}") def test_spam_can_buses(self): + tx_msgs = {(addr, bus) for addr, bus in self.TX_MSGS} for bus in range(4): for addr in self.SCANNED_ADDRS: - if [addr, bus] not in self.TX_MSGS: + if (addr, bus) not in tx_msgs: self.assertFalse(self._tx(make_msg(bus, addr, 8)), f"allowed TX {addr=} {bus=}") def test_default_controls_not_allowed(self): @@ -1074,12 +1045,6 @@ class CarSafetyTest(SafetyTest, MadsSafetyTestBase): GAS_PRESSED_THRESHOLD = 0 RELAY_MALFUNCTION_ADDRS: dict[int, tuple[int, ...]] | None = None - @classmethod - def setUpClass(cls): - if cls.__name__ == "CarSafetyTest" or cls.__name__.endswith('Base'): - cls.safety = None - raise unittest.SkipTest - @abc.abstractmethod def _user_brake_msg(self, brake): pass @@ -1251,10 +1216,12 @@ class CarSafetyTest(SafetyTest, MadsSafetyTestBase): self.assertEqual(self.safety.get_controls_allowed(), within_delta) def test_safety_tick(self): - self.safety.set_timer(int(2e6)) - self.safety.set_controls_allowed(True) - self.safety.set_controls_allowed_lateral(True) - self.safety.safety_tick_current_safety_config() - self.assertFalse(self.safety.get_controls_allowed()) - self.assertFalse(self.safety.get_controls_allowed_lateral()) - self.assertFalse(self.safety.safety_config_valid()) + # Missing valid RX messages must disable controls even before they time out. + for elapsed in (0, int(2e6)): + with self.subTest(elapsed=elapsed): + self._reset_safety_hooks() + self.safety.set_timer(elapsed) + self.safety.set_controls_allowed(True) + self.safety.safety_tick() + self.assertFalse(self.safety.get_controls_allowed()) + self.assertFalse(self.safety.safety_config_valid()) diff --git a/opendbc_repo/opendbc/safety/tests/hyundai_common.py b/opendbc_repo/opendbc/safety/tests/hyundai_common.py index 098806782..029c88933 100644 --- a/opendbc_repo/opendbc/safety/tests/hyundai_common.py +++ b/opendbc_repo/opendbc/safety/tests/hyundai_common.py @@ -1,5 +1,3 @@ -import unittest - from opendbc.sunnypilot.car.hyundai.values import HyundaiSafetyFlagsSP import opendbc.safety.tests.common as common from opendbc.safety.tests.libsafety import libsafety_py @@ -78,12 +76,6 @@ class HyundaiLongitudinalBase(common.LongitudinalAccelSafetyTest): DISABLED_ECU_UDS_MSG: tuple[int, int] DISABLED_ECU_ACTUATION_MSG: tuple[int, int] - @classmethod - def setUpClass(cls): - if cls.__name__ == "HyundaiLongitudinalBase": - cls.safety = None - raise unittest.SkipTest - # override these tests from CarSafetyTest, hyundai longitudinal uses button enable def test_disable_control_allowed_from_cruise(self): pass diff --git a/opendbc_repo/opendbc/safety/tests/libsafety/libsafety_py.py b/opendbc_repo/opendbc/safety/tests/libsafety/libsafety_py.py index b4e03d469..6146acbcc 100644 --- a/opendbc_repo/opendbc/safety/tests/libsafety/libsafety_py.py +++ b/opendbc_repo/opendbc/safety/tests/libsafety/libsafety_py.py @@ -1,4 +1,5 @@ import os +import re import subprocess import tempfile from pathlib import Path @@ -20,12 +21,14 @@ def _build_libsafety(release: bool = False) -> str: '-std=gnu11', '-Wfatal-errors', '-Wno-pointer-to-int-cast', '-g', '-O0', '-fno-omit-frame-pointer', ] - ldflags = [ - '-fsanitize=undefined', '-fno-sanitize-recover=undefined', - ] + # Coverage must exclude the branches inserted by UBSan. + if os.environ.get("SAFETY_COVERAGE") == "1": + ldflags = ['-fprofile-arcs', '-ftest-coverage'] if not release else [] + else: + ldflags = ['-fsanitize=undefined', '-fno-sanitize-recover=undefined'] + cflags += ldflags if not release: - cflags += ['-DALLOW_DEBUG', '-fprofile-arcs', '-ftest-coverage'] - ldflags += ['-fprofile-arcs', '-ftest-coverage'] + cflags += ['-DALLOW_DEBUG'] fd, safety_os = tempfile.mkstemp(suffix='.os', dir=libsafety_dir) os.close(fd) @@ -37,114 +40,38 @@ def _build_libsafety(release: bool = False) -> str: return libsafety_so +def cdef_from_file(path: Path) -> str: + source = path.read_text() + source = re.sub(r"//[^\n]*|/\*.*?\*/", "", source, flags=re.DOTALL) + source = re.sub(r"__attribute__\(\(.*\)\)", "", source) + + # Keep integer constants, type declarations, and function signatures, including definitions. + constants = re.findall(r"^#define \w+ \d+[UuLl]*[ \t]*$", source, re.MULTILINE) + types = re.findall(r"^(?:typedef|struct|enum)\b(?:[^;{]|\{[^}]*\})+;", source, re.MULTILINE) + functions = re.findall(r"^((?!typedef\b)\w[\w *]*\b\w+\([^;{}]*\))\s*[;{]", source, re.MULTILINE) + return "\n".join([*constants, *types, *(f"{signature};" for signature in dict.fromkeys(functions))]) + + ffi = FFI() +safety_dir = Path(libsafety_dir).parents[1] +ffi.cdef(cdef_from_file(safety_dir / "can.h"), packed=True) +for path in (safety_dir / "declarations.h", safety_dir / "ignition.h", safety_dir / "sunnypilot" / "mads_declarations.h", Path(libsafety_dir) / "safety.c"): + ffi.cdef(cdef_from_file(path)) -ffi.cdef(""" -typedef struct { - unsigned char fd : 1; - unsigned char bus : 3; - unsigned char data_len_code : 4; - unsigned char rejected : 1; - unsigned char returned : 1; - unsigned char extended : 1; - unsigned int addr : 29; - unsigned char checksum; - unsigned char data[64]; -} CANPacket_t; -""", packed=True) class CANPacket: pass +# Functions not captured by cdef_from_file (macros, non-standard formatting, or generated) ffi.cdef(""" -bool safety_rx_hook(CANPacket_t *msg); -bool safety_tx_hook(CANPacket_t *msg); -int safety_fwd_hook(int bus_num, int addr); -int set_safety_hooks(uint16_t mode, uint16_t param); - -void set_controls_allowed(bool c); -bool get_controls_allowed(void); -bool get_longitudinal_allowed(void); -void set_alternative_experience(int mode); int get_alternative_experience(void); -void set_relay_malfunction(bool c); -bool get_relay_malfunction(void); -bool get_gas_pressed_prev(void); -void set_gas_pressed_prev(bool); -bool get_brake_pressed_prev(void); -bool get_regen_braking_prev(void); -bool get_steering_disengage_prev(void); -bool get_acc_main_on(void); -float get_vehicle_speed_min(void); -float get_vehicle_speed_max(void); -int get_current_safety_mode(void); -int get_current_safety_param(void); - -void set_torque_meas(int min, int max); -int get_torque_meas_min(void); -int get_torque_meas_max(void); -void set_torque_driver(int min, int max); -int get_torque_driver_min(void); -int get_torque_driver_max(void); -void set_desired_torque_last(int t); -void set_rt_torque_last(int t); -void set_desired_angle_last(int t); -int get_desired_angle_last(); -void set_angle_meas(int min, int max); -int get_angle_meas_min(void); -int get_angle_meas_max(void); -void set_desired_curvature_last(int t); -int get_desired_curvature_last(); -void set_curvature_meas(int min, int max); -int get_curvature_meas_min(void); -int get_curvature_meas_max(void); - -bool get_cruise_engaged_prev(void); -void set_cruise_engaged_prev(bool engaged); -bool get_vehicle_moving(void); -void set_timer(uint32_t t); - -void safety_tick_current_safety_config(); -bool safety_config_valid(); - -void init_tests(void); - -void set_honda_fwd_brake(bool c); -bool get_honda_fwd_brake(void); -void set_honda_alt_brake_msg(bool c); +int get_desired_angle_last(void); void set_honda_bosch_long(bool c); int get_honda_hw(void); - +void set_ignition_can(bool c); +uint32_t get_acc_main_on_mismatches(void); +int get_temp_debug(void); void mutation_set_active_mutant(int id); int mutation_get_active_mutant(void); - -void ignition_can_hook(const CANPacket_t *msg); -bool get_ignition_can(void); -void set_ignition_can(bool c); - -bool get_controls_allowed_lateral(void); -bool get_controls_requested_lateral(void); -void set_current_safety_param_sp(uint16_t param); -uint16_t get_current_safety_param_sp(void); -bool get_enable_mads(void); -bool get_disengage_lateral_on_brake(void); -bool get_pause_lateral_on_brake(void); -void set_mads_button_press(int mads_button_press); -void set_controls_allowed_lateral(bool c); -void set_controls_requested_lateral(bool c); -bool get_mads_acc_main(void); -void set_acc_main_on(bool c); -int get_mads_button_press(void); -void mads_set_current_disengage_reason(int reason); -int mads_get_current_disengage_reason(void); -int get_temp_debug(void); -uint32_t get_acc_main_on_mismatches(void); -void set_mads_params(bool enable_mads, bool disengage_lateral_on_brake, bool pause_lateral_on_brake); -void mads_apply_alternative_experience(int mode); -void tick_mads_state(bool vm, bool acc_main, bool op_allowed, bool braking, bool steering_disengage); -void set_heartbeat_engaged_mads(bool c); -void mads_heartbeat_engaged_check(void); -void set_steering_disengage(bool c); -int get_gas_interceptor_prev(void); """) class LibSafety: diff --git a/opendbc_repo/opendbc/safety/tests/libsafety/safety.c b/opendbc_repo/opendbc/safety/tests/libsafety/safety.c index 89a2b04aa..834eca3c8 100644 --- a/opendbc_repo/opendbc/safety/tests/libsafety/safety.c +++ b/opendbc_repo/opendbc/safety/tests/libsafety/safety.c @@ -13,10 +13,6 @@ uint32_t microsecond_timer_get(void) { #include "opendbc/safety/safety.h" #include "opendbc/safety/ignition.h" -void safety_tick_current_safety_config() { - safety_tick(¤t_safety_config); -} - bool safety_config_valid() { if (current_safety_config.rx_checks_len <= 0) { printf("missing RX checks\n"); @@ -54,20 +50,16 @@ void set_relay_malfunction(bool c){ relay_malfunction = c; } -void set_ignition_can(bool c){ - ignition_can = c; -} - bool get_controls_allowed(void){ return controls_allowed; } -bool get_ignition_can(void){ - return ignition_can; +bool get_safety_rx_checks_invalid(void){ + return safety_rx_checks_invalid; } -int get_alternative_experience(void){ - return alternative_experience; +bool get_ignition_can(void){ + return ignition_can; } bool get_relay_malfunction(void){ @@ -168,10 +160,6 @@ void set_desired_angle_last(int t){ desired_angle_last = t; } -int get_desired_angle_last(void){ - return desired_angle_last; -} - void set_angle_meas(int min, int max){ angle_meas.min = min; angle_meas.max = max; @@ -213,14 +201,6 @@ void set_honda_alt_brake_msg(bool c){ honda_alt_brake_msg = c; } -void set_honda_bosch_long(bool c){ - honda_bosch_long = c; -} - -int get_honda_hw(void) { - return honda_hw; -} - void set_honda_fwd_brake(bool c){ honda_fwd_brake = c; } diff --git a/opendbc_repo/opendbc/safety/tests/mads_common.py b/opendbc_repo/opendbc/safety/tests/mads_common.py index 992a407b0..2c939a81f 100644 --- a/opendbc_repo/opendbc/safety/tests/mads_common.py +++ b/opendbc_repo/opendbc/safety/tests/mads_common.py @@ -573,7 +573,7 @@ class MadsSafetyTestBase(unittest.TestCase): # Simulate message lag — safety_tick clears both controls_allowed and controls_allowed_lateral self.safety.set_timer(int(2e6)) - self.safety.safety_tick_current_safety_config() + self.safety.safety_tick() self.assertFalse(self.safety.get_controls_allowed_lateral()) self.assertFalse(self.safety.get_controls_allowed_lateral()) self.assertFalse(self.safety.get_controls_allowed()) diff --git a/opendbc_repo/opendbc/safety/tests/mutation.py b/opendbc_repo/opendbc/safety/tests/mutation.py index 446bcfd4e..ea3365bf3 100755 --- a/opendbc_repo/opendbc/safety/tests/mutation.py +++ b/opendbc_repo/opendbc/safety/tests/mutation.py @@ -461,7 +461,6 @@ def compile_mutated_library(preprocessed_source, sites, output_so): prelude = """ static int __mutation_active_id = -1; void mutation_set_active_mutant(int id) { __mutation_active_id = id; } - int mutation_get_active_mutant(void) { return __mutation_active_id; } """ marker_re = re.compile(r'^\s*#\s+\d+\s+"[^\n]*\n?', re.MULTILINE) instrumented = prelude + marker_re.sub("", instrumented) diff --git a/opendbc_repo/opendbc/safety/tests/safety_replay/replay_drive.py b/opendbc_repo/opendbc/safety/tests/safety_replay/replay_drive.py index 5596e46d8..73b96d685 100755 --- a/opendbc_repo/opendbc/safety/tests/safety_replay/replay_drive.py +++ b/opendbc_repo/opendbc/safety/tests/safety_replay/replay_drive.py @@ -40,6 +40,9 @@ def replay_drive(msgs, safety_mode, param, alternative_experience, param_sp): print(f" disengage lateral on brake: {_disengage_lateral_on_brake}") print(f" pause lateral on brake: {_pause_lateral_on_brake}") + if not any(m.which() == "sentinel" and m.sentinel.type == "startOfRoute" for m in msgs): + print("WARNING: Replay starts mid-route; missing prior safety state may cause safety violations that did not appear in the route.") + init_segment(safety, msgs, safety_mode, param) rx_tot, rx_invalid, tx_tot, tx_blocked, tx_controls, tx_controls_lateral, tx_controls_blocked, tx_controls_lateral_blocked = 0, 0, 0, 0, 0, 0, 0, 0 @@ -62,7 +65,7 @@ def replay_drive(msgs, safety_mode, param, alternative_experience, param_sp): # skip start and end of route, warm up/down period if msg.logMonoTime - start_t > 1e9 and end_t - msg.logMonoTime > 1e9: - safety.safety_tick_current_safety_config() + safety.safety_tick() safety_tick_rx_invalid |= not safety.safety_config_valid() or safety_tick_rx_invalid if msg.which() == 'sendcan': diff --git a/opendbc_repo/opendbc/safety/tests/test.sh b/opendbc_repo/opendbc/safety/tests/test.sh index 491b9e3f3..0ae505cfb 100755 --- a/opendbc_repo/opendbc/safety/tests/test.sh +++ b/opendbc_repo/opendbc/safety/tests/test.sh @@ -6,11 +6,15 @@ cd $DIR source ../../../setup.sh -# reset coverage data -rm -f ./libsafety/*.gcda +# TODO: get UBSan and coverage without running the tests twice. +# Run UBSan separately so its checks do not count as coverage branches. +SAFETY_COVERAGE=0 python -m unittest discover -s . + +# reset coverage data, including metadata from previous builds +rm -f ./libsafety/*.gcda ./libsafety/*.gcno # run safety tests and generate coverage data -python -m unittest discover -s . +SAFETY_COVERAGE=1 python -m unittest discover -s . # NOTE: we accept that these tools will have slight differences, # and in return, we get to use the stock toolchain instead of diff --git a/opendbc_repo/opendbc/safety/tests/test_body.py b/opendbc_repo/opendbc/safety/tests/test_body.py index 8512221df..f6499bd96 100755 --- a/opendbc_repo/opendbc/safety/tests/test_body.py +++ b/opendbc_repo/opendbc/safety/tests/test_body.py @@ -3,21 +3,14 @@ import unittest from opendbc.car.structs import CarParams import opendbc.safety.tests.common as common -from opendbc.safety.tests.libsafety import libsafety_py -from opendbc.safety.tests.common import CANPackerSafety - - class TestBody(common.SafetyTest): + DBC = "comma_body" + SAFETY_MODEL = CarParams.SafetyModel.body + TX_MSGS = [[0x250, 0], [0x251, 0], [0x1, 0], [0x1, 1], [0x1, 2], [0x1, 3]] FWD_BUS_LOOKUP = {} - def setUp(self): - self.packer = CANPackerSafety("comma_body") - self.safety = libsafety_py.libsafety - self.safety.set_safety_hooks(CarParams.SafetyModel.body, 0) - self.safety.init_tests() - def _motors_data_msg(self, speed_l, speed_r): values = {"SPEED_L": speed_l, "SPEED_R": speed_r} return self.packer.make_can_msg_safety("MOTORS_DATA", 0, values) @@ -36,6 +29,23 @@ class TestBody(common.SafetyTest): self.assertTrue(self._rx(self._motors_data_msg(0, 0))) self.assertTrue(self.safety.get_controls_allowed()) + self._reset_safety_hooks() + for _ in range(16): + self.assertTrue(self._rx(self._motors_data_msg(0, 0))) + + msg = self._motors_data_msg(0, 0) + msg[0].data[7] ^= 0xff + self.assertFalse(self._rx(msg)) + + self._reset_safety_hooks() + for _ in range(16): + self.assertTrue(self._rx(self._motors_data_msg(0, 0))) + + msg = self._motors_data_msg(0, 0) + for _ in range(common.MAX_WRONG_COUNTERS + 1): + valid = self._rx(msg) + self.assertFalse(valid) + def test_tx_hook(self): self.assertFalse(self._tx(self._torque_cmd_msg(0, 0))) self.safety.set_controls_allowed(True) @@ -48,9 +58,8 @@ class TestBody(common.SafetyTest): # 0xdeadfaceU allowed for CAN flashing mode self.assertTrue(self._tx(common.make_msg(0, 0x250, dat=b'\xce\xfa\xad\xde\x1e\x0b\xb0\x0a'))) + self.assertFalse(self._tx(common.make_msg(0, 0x250, dat=b'\xcf\xfa\xad\xde\x1e\x0b\xb0\x0a'))) # wrong signature self.assertFalse(self._tx(common.make_msg(0, 0x250, dat=b'\xce\xfa\xad\xde\x1e\x0b\xb0'))) # not correct data/len self.assertFalse(self._tx(common.make_msg(0, 0x251, dat=b'\xce\xfa\xad\xde\x1e\x0b\xb0\x0a'))) # wrong address - - if __name__ == "__main__": unittest.main() diff --git a/opendbc_repo/opendbc/safety/tests/test_byd.py b/opendbc_repo/opendbc/safety/tests/test_byd.py new file mode 100644 index 000000000..5bde677fe --- /dev/null +++ b/opendbc_repo/opendbc/safety/tests/test_byd.py @@ -0,0 +1,212 @@ +#!/usr/bin/env python3 +import itertools +import unittest +import numpy as np + +from opendbc.car.byd.carcontroller import get_safety_CP +from opendbc.car.byd.values import CarControllerParams +from opendbc.car.lateral import get_max_angle_delta_vm, get_max_angle_vm +from opendbc.car.structs import CarParams +from opendbc.car.vehicle_model import VehicleModel +import opendbc.safety.tests.common as common +from opendbc.safety.tests.common import away_round + +STEERING_MODULE_ADAS = 0x1E2 +LKAS_HUD_ADAS = 0x316 +PCM_BUTTONS = 0x3B0 +def safety_max_can(max_angle_float, can_offset=0): + # Matches C: max_angle_can = (int)(max_angle * 10 + 1.) which is floor(max_angle * 10) + 1 + return int(max_angle_float * 10 + 1.) + can_offset +class TestBydSafety(common.CarSafetyTest, common.AngleSteeringSafetyTest): + DBC = "byd_atto3" + SAFETY_MODEL = CarParams.SafetyModel.byd + + RELAY_MALFUNCTION_ADDRS = {0: (STEERING_MODULE_ADAS, LKAS_HUD_ADAS)} + FWD_BLACKLISTED_ADDRS = {2: [STEERING_MODULE_ADAS, LKAS_HUD_ADAS]} + TX_MSGS = [[STEERING_MODULE_ADAS, 0], [LKAS_HUD_ADAS, 0], [PCM_BUTTONS, 0]] + + MAIN_BUS = 0 + CAM_BUS = 2 + + STEER_ANGLE_MAX = 390 # deg, EPS fault limit + DEG_TO_CAN = 10 + + # BYD uses get_max_angle_delta_vm and get_max_angle_vm for lateral accel and jerk limits + ANGLE_RATE_BP = None + ANGLE_RATE_UP = None + ANGLE_RATE_DOWN = None + + # Real time limits + LATERAL_FREQUENCY = 50 # Hz + + def _get_steer_cmd_angle_max(self, speed): + return get_max_angle_vm(max(speed, 1), self.VM, CarControllerParams) + + def setUp(self): + super().setUp() + self.VM = VehicleModel(get_safety_CP()) + + def _angle_cmd_msg(self, angle: float, enabled: bool, increment_timer: bool = True): + values = {"STEER_ANGLE": angle, "STEER_REQ": 1 if enabled else 0, "STEER_REQ_ACTIVE_LOW": 0 if enabled else 1} + if increment_timer: + self.safety.set_timer(self.__class__.cnt_angle_cmd * int(1e6 / self.LATERAL_FREQUENCY)) + self.__class__.cnt_angle_cmd += 1 + return self.packer.make_can_msg_safety("STEERING_MODULE_ADAS", self.MAIN_BUS, values) + + cnt_angle_cmd = 0 + + def _angle_meas_msg(self, angle: float): + values = {"STEER_ANGLE_2": angle} + return self.packer.make_can_msg_safety("STEER_MODULE_2", self.MAIN_BUS, values) + + def _pcm_status_msg(self, enable): + # ACC_STATE: 0=OFF, 3=ACC_ACTIVE + values = {"ACC_STATE": 3 if enable else 0} + return self.packer.make_can_msg_safety("ACC_HUD_ADAS", self.CAM_BUS, values) + + def _speed_msg(self, speed): + values = {"WHEELSPEED_CLEAN": speed * 3.6} + return self.packer.make_can_msg_safety("WHEELSPEED_CLEAN", self.MAIN_BUS, values) + + def _user_brake_msg(self, brake): + values = {"BRAKE_PRESSED": 1 if brake else 0} + return self.packer.make_can_msg_safety("DRIVE_STATE", self.MAIN_BUS, values) + + def _user_gas_msg(self, gas): + values = {"RAW_THROTTLE": int(gas * 100)} + return self.packer.make_can_msg_safety("DRIVE_STATE", self.MAIN_BUS, values) + + def test_cruise_buttons(self): + buttons = ("SET_BTN", "RES_BTN", "LKAS_ON_BTN", "DEC_DISTANCE_BTN", "INC_DISTANCE_BTN", "ACC_ON_BTN") + for cruise_engaged, controls_allowed in itertools.product((False, True), repeat=2): + self.assertTrue(self._rx(self._pcm_status_msg(cruise_engaged))) + self.safety.set_controls_allowed(controls_allowed) + for pressed in itertools.product((False, True), repeat=len(buttons)): + values = dict(zip(buttons, pressed, strict=True)) + values.update(SET_ME_1_1=1, SET_ME_1_2=1) + with self.subTest(cruise_engaged=cruise_engaged, controls_allowed=controls_allowed, buttons=pressed): + msg = self.packer.make_can_msg_safety("PCM_BUTTONS", self.MAIN_BUS, values) + should_tx = not any(pressed[:-1]) and (not pressed[-1] or cruise_engaged) + self.assertEqual(should_tx, self._tx(msg)) + + def test_rx_checksums(self): + for name, bus, signal, initial, corrupt in ( + ("WHEELSPEED_CLEAN", self.MAIN_BUS, "WHEELSPEED_CLEAN", 72, 0), + ("ACC_HUD_ADAS", self.CAM_BUS, "ACC_STATE", 0, 3), + ): + for byte in range(8): + with self.subTest(message=name, byte=byte): + self.safety.set_safety_hooks(CarParams.SafetyModel.byd, 0) + self.safety.init_tests() + for _ in range(16): + msg = self.packer.make_can_msg_safety(name, bus, {signal: initial}) + self.assertTrue(self._rx(msg)) + speed_min = self.safety.get_vehicle_speed_min() + speed_max = self.safety.get_vehicle_speed_max() + msg = self.packer.make_can_msg_safety(name, bus, {signal: corrupt}) + msg[0].data[byte] ^= 0xFF + self.safety.set_controls_allowed(name == "WHEELSPEED_CLEAN") + self.assertFalse(self._rx(msg)) + self.assertFalse(self.safety.get_controls_allowed()) + self.assertEqual(speed_min, self.safety.get_vehicle_speed_min()) + self.assertEqual(speed_max, self.safety.get_vehicle_speed_max()) + + def test_rx_counters(self): + for name, bus, signal, value in ( + ("WHEELSPEED_CLEAN", self.MAIN_BUS, "WHEELSPEED_CLEAN", 72), + ("ACC_HUD_ADAS", self.CAM_BUS, "ACC_STATE", 3), + ): + with self.subTest(message=name): + # Check both counter locations and rollover with valid checksums. + for _ in range(32): + msg = self.packer.make_can_msg_safety(name, bus, {signal: value}) + self.assertTrue(self._rx(msg)) + self.safety.set_controls_allowed(True) + # Replayed frames are rejected after the common counter tolerance. + for i in range(common.MAX_WRONG_COUNTERS + 1): + should_rx = i < common.MAX_WRONG_COUNTERS - 1 + self.assertEqual(should_rx, self._rx(msg)) + self.assertEqual(should_rx, self.safety.get_controls_allowed()) + # A valid sequence clears the counter faults. + for _ in range(common.MAX_WRONG_COUNTERS): + msg = self.packer.make_can_msg_safety(name, bus, {signal: 0}) + self.assertTrue(self._rx(msg)) + + def test_angle_cmd_when_enabled(self): + # We properly test lateral acceleration and jerk below + pass + + def test_lateral_accel_limit(self): + for speed in np.linspace(0, 40, 100): + speed = max(speed, 1) + # match both CAN encoding (0.1 kph/LSB) and VEHICLE_SPEED_FACTOR=1000 rounding in UPDATE_VEHICLE_SPEED + sent = speed + 1 + sent_can = away_round(sent / 0.1 * 3.6) * 0.1 / 3.6 + speed = round(sent_can * 1000) / 1000 - 1 + for sign in (-1, 1): + self.safety.set_controls_allowed(True) + self._reset_speed_measurement(speed + 1) # safety fudges the speed + + max_angle_float = get_max_angle_vm(speed, self.VM, CarControllerParams) + + # at limit (safety tolerance adds 1 CAN unit) + max_angle_can = safety_max_can(max_angle_float) + max_angle_can = min(max_angle_can, self.STEER_ANGLE_MAX * self.DEG_TO_CAN) + max_angle = sign * max_angle_can / self.DEG_TO_CAN + self.safety.set_desired_angle_last(sign * max_angle_can) + + self.assertTrue(self._tx(self._angle_cmd_msg(max_angle, True))) + + # 1 unit above limit + over_can = safety_max_can(max_angle_float, 1) + over_can_clipped = min(over_can, self.STEER_ANGLE_MAX * self.DEG_TO_CAN) + over_angle = sign * over_can_clipped / self.DEG_TO_CAN + self._tx(self._angle_cmd_msg(over_angle, True)) + + # at low speeds max angle is above STEER_ANGLE_MAX, so adding 1 has no effect + should_tx = over_can >= self.STEER_ANGLE_MAX * self.DEG_TO_CAN + self.assertEqual(should_tx, self._tx(self._angle_cmd_msg(over_angle, True))) + + def test_lateral_jerk_limit(self): + for speed in np.linspace(0, 40, 100): + speed = max(speed, 1) + # match both CAN encoding (0.1 kph/LSB) and VEHICLE_SPEED_FACTOR=1000 rounding in UPDATE_VEHICLE_SPEED + sent = speed + 1 + sent_can = away_round(sent / 0.1 * 3.6) * 0.1 / 3.6 + speed = round(sent_can * 1000) / 1000 - 1 + for sign in (-1, 1): + self.safety.set_controls_allowed(True) + self._reset_speed_measurement(speed + 1) # safety fudges the speed + self._tx(self._angle_cmd_msg(0, True)) + + max_delta_float = get_max_angle_delta_vm(speed, self.VM, CarControllerParams) + + # Stay within limits + # Up + max_delta_can = safety_max_can(max_delta_float) + max_angle_delta = sign * max_delta_can / self.DEG_TO_CAN + self.assertTrue(self._tx(self._angle_cmd_msg(max_angle_delta, True))) + + # Don't change + self.assertTrue(self._tx(self._angle_cmd_msg(max_angle_delta, True))) + + # Down + self.assertTrue(self._tx(self._angle_cmd_msg(0, True))) + + # Inject too high rates + # Up + over_delta_can = safety_max_can(max_delta_float, 1) + max_angle_delta = sign * over_delta_can / self.DEG_TO_CAN + self.assertFalse(self._tx(self._angle_cmd_msg(max_angle_delta, True))) + + # Don't change + self.safety.set_desired_angle_last(sign * over_delta_can) + self.assertTrue(self._tx(self._angle_cmd_msg(max_angle_delta, True))) + + # Down + self.assertFalse(self._tx(self._angle_cmd_msg(0, True))) + + # Recover + self.assertTrue(self._tx(self._angle_cmd_msg(0, True))) +if __name__ == "__main__": + unittest.main() diff --git a/opendbc_repo/opendbc/safety/tests/test_chrysler.py b/opendbc_repo/opendbc/safety/tests/test_chrysler.py index 4eb65335f..20bcf7ba7 100755 --- a/opendbc_repo/opendbc/safety/tests/test_chrysler.py +++ b/opendbc_repo/opendbc/safety/tests/test_chrysler.py @@ -3,12 +3,11 @@ import unittest from opendbc.car.chrysler.values import ChryslerSafetyFlags from opendbc.car.structs import CarParams -from opendbc.safety.tests.libsafety import libsafety_py import opendbc.safety.tests.common as common -from opendbc.safety.tests.common import CANPackerSafety - - class TestChryslerSafety(common.CarSafetyTest, common.MotorTorqueSteeringSafetyTest): + DBC = "chrysler_pacifica_2017_hybrid_generated" + SAFETY_MODEL = CarParams.SafetyModel.chrysler + TX_MSGS = [[0x23B, 0], [0x292, 0], [0x2A6, 0], [0x2D9, 0]] RELAY_MALFUNCTION_ADDRS = {0: (0x292, 0x2A6, 0x2D9)} FWD_BLACKLISTED_ADDRS = {2: [0x292, 0x2A6, 0x2D9]} @@ -23,12 +22,6 @@ class TestChryslerSafety(common.CarSafetyTest, common.MotorTorqueSteeringSafetyT DAS_BUS = 0 - def setUp(self): - self.packer = CANPackerSafety("chrysler_pacifica_2017_hybrid_generated") - self.safety = libsafety_py.libsafety - self.safety.set_safety_hooks(CarParams.SafetyModel.chrysler, 0) - self.safety.init_tests() - def _button_msg(self, cancel=False, resume=False, accel=False, decel=False): values = {"ACC_Cancel": cancel, "ACC_Resume": resume, "ACC_Accel": accel, "ACC_Decel": decel} return self.packer.make_can_msg_safety("CRUISE_BUTTONS", self.DAS_BUS, values) @@ -96,9 +89,11 @@ class TestChryslerSafety(common.CarSafetyTest, common.MotorTorqueSteeringSafetyT def _lkas_button_msg(self, enabled): values = {"TOGGLE_LKAS": enabled} return self.packer.make_can_msg_safety("TRACTION_BUTTON", 0, values) - - class TestChryslerRamDTSafety(TestChryslerSafety): + DBC = "chrysler_ram_dt_generated" + + SAFETY_PARAM = ChryslerSafetyFlags.RAM_DT + TX_MSGS = [[0xB1, 2], [0xA6, 0], [0xFA, 0]] RELAY_MALFUNCTION_ADDRS = {0: (0xA6, 0xFA)} FWD_BLACKLISTED_ADDRS = {2: [0xA6, 0xFA]} @@ -111,12 +106,6 @@ class TestChryslerRamDTSafety(TestChryslerSafety): LKAS_ACTIVE_VALUE = 2 - def setUp(self): - self.packer = CANPackerSafety("chrysler_ram_dt_generated") - self.safety = libsafety_py.libsafety - self.safety.set_safety_hooks(CarParams.SafetyModel.chrysler, ChryslerSafetyFlags.RAM_DT) - self.safety.init_tests() - def _speed_msg(self, speed): values = {"Vehicle_Speed": speed} return self.packer.make_can_msg_safety("ESP_8", 0, values) @@ -124,9 +113,11 @@ class TestChryslerRamDTSafety(TestChryslerSafety): def _lkas_button_msg(self, enabled): values = {"LKAS_Button": enabled} return self.packer.make_can_msg_safety("Center_Stack_2", 0, values) - - class TestChryslerRamHDSafety(TestChryslerSafety): + DBC = "chrysler_ram_hd_generated" + + SAFETY_PARAM = ChryslerSafetyFlags.RAM_HD + TX_MSGS = [[0x275, 0], [0x276, 0], [0x23A, 2]] RELAY_MALFUNCTION_ADDRS = {0: (0x276, 0x275)} FWD_BLACKLISTED_ADDRS = {2: [0x275, 0x276]} @@ -140,12 +131,6 @@ class TestChryslerRamHDSafety(TestChryslerSafety): LKAS_ACTIVE_VALUE = 2 - def setUp(self): - self.packer = CANPackerSafety("chrysler_ram_hd_generated") - self.safety = libsafety_py.libsafety - self.safety.set_safety_hooks(CarParams.SafetyModel.chrysler, ChryslerSafetyFlags.RAM_HD) - self.safety.init_tests() - def _speed_msg(self, speed): values = {"Vehicle_Speed": speed} return self.packer.make_can_msg_safety("ESP_8", 0, values) @@ -153,7 +138,5 @@ class TestChryslerRamHDSafety(TestChryslerSafety): def _lkas_button_msg(self, enabled): values = {"LKAS_Button": enabled} return self.packer.make_can_msg_safety("Center_Stack_2", 0, values) - - if __name__ == "__main__": unittest.main() diff --git a/opendbc_repo/opendbc/safety/tests/test_chrysler_cusw.py b/opendbc_repo/opendbc/safety/tests/test_chrysler_cusw.py index 3fe78c625..20bc35c8b 100644 --- a/opendbc_repo/opendbc/safety/tests/test_chrysler_cusw.py +++ b/opendbc_repo/opendbc/safety/tests/test_chrysler_cusw.py @@ -1,12 +1,11 @@ #!/usr/bin/env python3 import unittest from opendbc.car.structs import CarParams -from opendbc.safety.tests.libsafety import libsafety_py import opendbc.safety.tests.common as common -from opendbc.safety.tests.common import CANPackerSafety - - class TestChryslerCuswSafety(common.CarSafetyTest, common.MotorTorqueSteeringSafetyTest): + DBC = "chrysler_cusw" + SAFETY_MODEL = CarParams.SafetyModel.chryslerCusw + TX_MSGS = [[0x1F6, 0], [0x2FA, 0], [0x5DC, 0]] STANDSTILL_THRESHOLD = 0 RELAY_MALFUNCTION_ADDRS = {0: (0x1F6, 0x5DC)} @@ -18,12 +17,6 @@ class TestChryslerCuswSafety(common.CarSafetyTest, common.MotorTorqueSteeringSaf MAX_RT_DELTA = 150 MAX_TORQUE_ERROR = 80 - def setUp(self): - self.packer = CANPackerSafety("chrysler_cusw") - self.safety = libsafety_py.libsafety - self.safety.set_safety_hooks(CarParams.SafetyModel.chryslerCusw, 0) - self.safety.init_tests() - def _button_msg(self, cancel=False, resume=False): values = {"ACC_Cancel": cancel, "ACC_Resume": resume} return self.packer.make_can_msg_safety("CRUISE_BUTTONS", 0, values) @@ -56,6 +49,8 @@ class TestChryslerCuswSafety(common.CarSafetyTest, common.MotorTorqueSteeringSaf for controls_allowed in (True, False): self.safety.set_controls_allowed(controls_allowed) + self.assertFalse(self._tx(self._button_msg())) + # resume only while controls allowed self.assertEqual(controls_allowed, self._tx(self._button_msg(resume=True))) @@ -69,7 +64,5 @@ class TestChryslerCuswSafety(common.CarSafetyTest, common.MotorTorqueSteeringSaf self.assertTrue(self._rx(self._torque_meas_msg(0)), f"{count=}") self.assertTrue(self._rx(self._user_gas_msg(0)), f"{count=}") self.assertTrue(self._rx(self._pcm_status_msg(False)), f"{count=}") - - if __name__ == "__main__": unittest.main() diff --git a/opendbc_repo/opendbc/safety/tests/test_defaults.py b/opendbc_repo/opendbc/safety/tests/test_defaults.py index 4e5961544..ec6bb97f4 100755 --- a/opendbc_repo/opendbc/safety/tests/test_defaults.py +++ b/opendbc_repo/opendbc/safety/tests/test_defaults.py @@ -3,9 +3,6 @@ import unittest import opendbc.safety.tests.common as common from opendbc.car.structs import CarParams -from opendbc.safety.tests.libsafety import libsafety_py - - class TestDefaultRxHookBase(common.SafetyTest): FWD_BUS_LOOKUP = {} @@ -14,36 +11,20 @@ class TestDefaultRxHookBase(common.SafetyTest): for bus in range(4): for addr in self.SCANNED_ADDRS: self.assertTrue(self._rx(common.make_msg(bus, addr, 8)), f"failed RX {addr=}") - - class TestNoOutput(TestDefaultRxHookBase): + SAFETY_MODEL = CarParams.SafetyModel.noOutput + TX_MSGS = [] - - def setUp(self): - self.safety = libsafety_py.libsafety - self.safety.set_safety_hooks(CarParams.SafetyModel.noOutput, 0) - self.safety.init_tests() - - class TestSilent(TestNoOutput): """SILENT uses same hooks as NOOUTPUT""" - - def setUp(self): - self.safety = libsafety_py.libsafety - self.safety.set_safety_hooks(CarParams.SafetyModel.silent, 0) - self.safety.init_tests() - - + SAFETY_MODEL = CarParams.SafetyModel.silent class TestAllOutput(TestDefaultRxHookBase): + SAFETY_MODEL = CarParams.SafetyModel.allOutput + # Allow all messages TX_MSGS = [[addr, bus] for addr in common.SafetyTest.SCANNED_ADDRS for bus in range(4)] - def setUp(self): - self.safety = libsafety_py.libsafety - self.safety.set_safety_hooks(CarParams.SafetyModel.allOutput, 0) - self.safety.init_tests() - def test_spam_can_buses(self): # asserts tx allowed for all scanned addrs for bus in range(4): @@ -58,17 +39,18 @@ class TestAllOutput(TestDefaultRxHookBase): def test_tx_hook_on_wrong_safety_mode(self): # No point, since we allow all messages pass - - class TestAllOutputPassthrough(TestAllOutput): + SAFETY_PARAM = 1 + FWD_BLACKLISTED_ADDRS = {} FWD_BUS_LOOKUP = {0: 2, 2: 0} +class TestSafetyFramework(common.SafetyTestBase): + SAFETY_MODEL = CarParams.SafetyModel.noOutput - def setUp(self): - self.safety = libsafety_py.libsafety - self.safety.set_safety_hooks(CarParams.SafetyModel.allOutput, 1) - self.safety.init_tests() - - + def test_unsupported_safety_mode(self): + self.safety.set_controls_allowed(True) + self.assertEqual(self.safety.set_safety_hooks(0xFFFF, 0), -1) + self.assertFalse(self.safety.get_controls_allowed()) + self.assertFalse(self.safety.safety_tx_hook(common.make_msg(0, 0x123))) if __name__ == "__main__": unittest.main() diff --git a/opendbc_repo/opendbc/safety/tests/test_elm327.py b/opendbc_repo/opendbc/safety/tests/test_elm327.py index eb703e16d..0fe2ee49f 100755 --- a/opendbc_repo/opendbc/safety/tests/test_elm327.py +++ b/opendbc_repo/opendbc/safety/tests/test_elm327.py @@ -4,24 +4,18 @@ import unittest import opendbc.safety.tests.common as common from opendbc.car.structs import CarParams from opendbc.safety import DLC_TO_LEN -from opendbc.safety.tests.libsafety import libsafety_py from opendbc.safety.tests.test_defaults import TestDefaultRxHookBase GM_CAMERA_DIAG_ADDR = 0x24B - - class TestElm327(TestDefaultRxHookBase): + SAFETY_MODEL = CarParams.SafetyModel.elm327 + TX_MSGS = [[addr, bus] for addr in [GM_CAMERA_DIAG_ADDR, *range(0x600, 0x800), *range(0x18DA00F1, 0x18DB00F1, 0x100), # 29-bit UDS physical addressing *[0x18DB33F1], # 29-bit UDS functional address ] for bus in range(4)] FWD_BUS_LOOKUP = {} - def setUp(self): - self.safety = libsafety_py.libsafety - self.safety.set_safety_hooks(CarParams.SafetyModel.elm327, 0) - self.safety.init_tests() - def test_tx_hook(self): # ensure we can transmit arbitrary data on allowed addresses for bus in range(4): @@ -46,7 +40,5 @@ class TestElm327(TestDefaultRxHookBase): def test_tx_hook_on_wrong_safety_mode(self): # No point, since we allow many diagnostic addresses pass - - if __name__ == "__main__": unittest.main() diff --git a/opendbc_repo/opendbc/safety/tests/test_ford.py b/opendbc_repo/opendbc/safety/tests/test_ford.py index 07e8f8e6b..d62979b85 100755 --- a/opendbc_repo/opendbc/safety/tests/test_ford.py +++ b/opendbc_repo/opendbc/safety/tests/test_ford.py @@ -7,8 +7,6 @@ import opendbc.safety.tests.common as common from opendbc.car.lateral import MAX_LATERAL_ACCEL, MAX_LATERAL_JERK from opendbc.car.ford.values import FordSafetyFlags from opendbc.car.structs import CarParams -from opendbc.safety.tests.libsafety import libsafety_py -from opendbc.safety.tests.common import CANPackerSafety MSG_BrakeSysFeatures = 0x415 # RX from ABS, for vehicle speed MSG_EngVehicleSpThrottle2 = 0x202 # RX from PCM, for second vehicle speed @@ -20,50 +18,19 @@ MSG_Lane_Assist_Data1 = 0x3CA # TX by OP, Lane Keep Assist MSG_LateralMotionControl = 0x3D3 # TX by OP, Lateral Control message MSG_LateralMotionControl2 = 0x3D6 # TX by OP, alternate Lateral Control message MSG_IPMA_Data = 0x3D8 # TX by OP, IPMA and LKAS user interface - - -def checksum(msg): - addr, dat, bus = msg - ret = bytearray(dat) - - if addr == MSG_Yaw_Data_FD1: - chksum = dat[0] + dat[1] # VehRol_W_Actl - chksum += dat[2] + dat[3] # VehYaw_W_Actl - chksum += dat[5] # VehRollYaw_No_Cnt - chksum += dat[6] >> 6 # VehRolWActl_D_Qf - chksum += (dat[6] >> 4) & 0x3 # VehYawWActl_D_Qf - chksum = 0xff - (chksum & 0xff) - ret[4] = chksum - - elif addr == MSG_BrakeSysFeatures: - chksum = dat[0] + dat[1] # Veh_V_ActlBrk - chksum += (dat[2] >> 2) & 0xf # VehVActlBrk_No_Cnt - chksum += dat[2] >> 6 # VehVActlBrk_D_Qf - chksum = 0xff - (chksum & 0xff) - ret[3] = chksum - - elif addr == MSG_EngVehicleSpThrottle2: - chksum = (dat[2] >> 3) & 0xf # VehVActlEng_No_Cnt - chksum += (dat[4] >> 5) & 0x3 # VehVActlEng_D_Qf - chksum += dat[6] + dat[7] # Veh_V_ActlEng - chksum = 0xff - (chksum & 0xff) - ret[1] = chksum - - return addr, ret, bus - - class Buttons: CANCEL = 0 RESUME = 1 TJA_TOGGLE = 2 - - # Ford safety has four different configurations tested here: # * CAN with openpilot longitudinal # * CAN FD with stock longitudinal # * CAN FD with openpilot longitudinal class TestFordSafetyBase(common.CarSafetyTest): + DBC = "ford_lincoln_base_pt" + SAFETY_MODEL = CarParams.SafetyModel.ford + STANDSTILL_THRESHOLD = 1 RELAY_MALFUNCTION_ADDRS = {0: (MSG_ACCDATA_3, MSG_Lane_Assist_Data1, MSG_LateralMotionControl, MSG_LateralMotionControl2, MSG_IPMA_Data)} @@ -80,13 +47,7 @@ class TestFordSafetyBase(common.CarSafetyTest): CURVATURE_ERROR_MIN_SPEED = 10.0 # m/s LATERAL_FREQUENCY = 20 # Hz, for per-frame jerk limit - cnt_speed = 0 - cnt_speed_2 = 0 - cnt_yaw_rate = 0 - cnt_lat_ctl = 0 - - packer: CANPackerSafety - safety: libsafety_py.LibSafety + lat_ctl_frame = 0 def _get_max_curvature_can(self, speed): fudged_speed = max(speed - 1.0, 1.0) @@ -130,16 +91,14 @@ class TestFordSafetyBase(common.CarSafetyTest): # ABS vehicle speed def _speed_msg(self, speed: float, quality_flag=True): - values = {"Veh_V_ActlBrk": speed * 3.6, "VehVActlBrk_D_Qf": 3 if quality_flag else 0, "VehVActlBrk_No_Cnt": self.cnt_speed % 16} - self.__class__.cnt_speed += 1 - return self.packer.make_can_msg_safety("BrakeSysFeatures", 0, values, fix_checksum=checksum) + values = {"Veh_V_ActlBrk": speed * 3.6, "VehVActlBrk_D_Qf": 3 if quality_flag else 0} + return self.packer.make_can_msg_safety("BrakeSysFeatures", 0, values) # PCM vehicle speed def _speed_msg_2(self, speed: float, quality_flag=True): # Ford relies on speed for driver curvature limiting, so it checks two sources - values = {"Veh_V_ActlEng": speed * 3.6, "VehVActlEng_D_Qf": 3 if quality_flag else 0, "VehVActlEng_No_Cnt": self.cnt_speed_2 % 16} - self.__class__.cnt_speed_2 += 1 - return self.packer.make_can_msg_safety("EngVehicleSpThrottle2", 0, values, fix_checksum=checksum) + values = {"Veh_V_ActlEng": speed * 3.6, "VehVActlEng_D_Qf": 3 if quality_flag else 0} + return self.packer.make_can_msg_safety("EngVehicleSpThrottle2", 0, values) # Standstill state def _vehicle_moving_msg(self, speed: float): @@ -148,10 +107,8 @@ class TestFordSafetyBase(common.CarSafetyTest): # Current curvature def _yaw_rate_msg(self, curvature: float, speed: float, quality_flag=True): - values = {"VehYaw_W_Actl": curvature * speed, "VehYawWActl_D_Qf": 3 if quality_flag else 0, - "VehRollYaw_No_Cnt": self.cnt_yaw_rate % 256} - self.__class__.cnt_yaw_rate += 1 - return self.packer.make_can_msg_safety("Yaw_Data_FD1", 0, values, fix_checksum=checksum) + values = {"VehYaw_W_Actl": curvature * speed, "VehYawWActl_D_Qf": 3 if quality_flag else 0} + return self.packer.make_can_msg_safety("Yaw_Data_FD1", 0, values) # Drive throttle input def _user_gas_msg(self, gas: float): @@ -169,6 +126,11 @@ class TestFordSafetyBase(common.CarSafetyTest): } return self.packer.make_can_msg_safety("EngBrakeData", 0, values) + def test_enable_control_allowed_from_queue_assist(self): + msg = self.packer.make_can_msg_safety("EngBrakeData", 0, {"BpedDrvAppl_D_Actl": 1, "CcStat_D_Actl": 4}) + self.assertTrue(self._rx(msg)) + self.assertTrue(self.safety.get_controls_allowed()) + # LKAS command def _lkas_command_msg(self, action: int): values = { @@ -180,8 +142,8 @@ class TestFordSafetyBase(common.CarSafetyTest): def _lat_ctl_msg(self, enabled: bool, path_offset: float, path_angle: float, curvature: float, curvature_rate: float, increment_timer: bool = True): if increment_timer: - self.safety.set_timer(self.cnt_lat_ctl * int(1e6 / self.LATERAL_FREQUENCY)) - self.__class__.cnt_lat_ctl += 1 + self.safety.set_timer(self.lat_ctl_frame * int(1e6 / self.LATERAL_FREQUENCY)) + self.__class__.lat_ctl_frame += 1 if self.STEER_MESSAGE == MSG_LateralMotionControl: values = { "LatCtl_D_Rq": 1 if enabled else 0, @@ -467,9 +429,9 @@ class TestFordSafetyBase(common.CarSafetyTest): self.safety.set_mads_params(enable_mads, False, False) self._rx(self._pcm_status_msg(main_button_msg_valid)) self.assertEqual(enable_mads and main_button_msg_valid, self.safety.get_controls_allowed_lateral()) - - class TestFordCANFDStockSafety(TestFordSafetyBase): + SAFETY_PARAM = FordSafetyFlags.CANFD + STEER_MESSAGE = MSG_LateralMotionControl2 TX_MSGS = [ @@ -481,14 +443,6 @@ class TestFordCANFDStockSafety(TestFordSafetyBase): FWD_BLACKLISTED_ADDRS = {2: [MSG_ACCDATA_3, MSG_Lane_Assist_Data1, MSG_LateralMotionControl2, MSG_IPMA_Data]} - - def setUp(self): - self.packer = CANPackerSafety("ford_lincoln_base_pt") - self.safety = libsafety_py.libsafety - self.safety.set_safety_hooks(CarParams.SafetyModel.ford, FordSafetyFlags.CANFD) - self.safety.init_tests() - - class TestFordLongitudinalSafetyBase(TestFordSafetyBase): MAX_ACCEL = 2.0 # accel is used for brakes, but openpilot can set positive values MIN_ACCEL = -3.5 @@ -538,9 +492,9 @@ class TestFordLongitudinalSafetyBase(TestFordSafetyBase): should_tx = (controls_allowed and self.MIN_ACCEL <= brake <= self.MAX_ACCEL) or brake == self.INACTIVE_ACCEL should_tx = should_tx and (controls_allowed or not brake_actuation) self.assertEqual(should_tx, self._tx(self._acc_command_msg(self.INACTIVE_GAS, brake, brake_actuation))) - - class TestFordLongitudinalSafety(TestFordLongitudinalSafetyBase): + # Make sure we enforce long safety even without long flag for CAN + SAFETY_PARAM = 0 STEER_MESSAGE = MSG_LateralMotionControl TX_MSGS = [ @@ -552,16 +506,9 @@ class TestFordLongitudinalSafety(TestFordLongitudinalSafetyBase): FWD_BLACKLISTED_ADDRS = {2: [MSG_ACCDATA, MSG_ACCDATA_3, MSG_Lane_Assist_Data1, MSG_LateralMotionControl, MSG_IPMA_Data]} - - def setUp(self): - self.packer = CANPackerSafety("ford_lincoln_base_pt") - self.safety = libsafety_py.libsafety - # Make sure we enforce long safety even without long flag for CAN - self.safety.set_safety_hooks(CarParams.SafetyModel.ford, 0) - self.safety.init_tests() - - class TestFordCANFDLongitudinalSafety(TestFordLongitudinalSafetyBase): + SAFETY_PARAM = FordSafetyFlags.LONG_CONTROL | FordSafetyFlags.CANFD + STEER_MESSAGE = MSG_LateralMotionControl2 TX_MSGS = [ @@ -573,13 +520,5 @@ class TestFordCANFDLongitudinalSafety(TestFordLongitudinalSafetyBase): FWD_BLACKLISTED_ADDRS = {2: [MSG_ACCDATA, MSG_ACCDATA_3, MSG_Lane_Assist_Data1, MSG_LateralMotionControl2, MSG_IPMA_Data]} - - def setUp(self): - self.packer = CANPackerSafety("ford_lincoln_base_pt") - self.safety = libsafety_py.libsafety - self.safety.set_safety_hooks(CarParams.SafetyModel.ford, FordSafetyFlags.LONG_CONTROL | FordSafetyFlags.CANFD) - self.safety.init_tests() - - if __name__ == "__main__": unittest.main() diff --git a/opendbc_repo/opendbc/safety/tests/test_gm.py b/opendbc_repo/opendbc/safety/tests/test_gm.py index 2013fd843..bd90673eb 100755 --- a/opendbc_repo/opendbc/safety/tests/test_gm.py +++ b/opendbc_repo/opendbc/safety/tests/test_gm.py @@ -3,20 +3,15 @@ import unittest from opendbc.car.gm.values import GMSafetyFlags from opendbc.car.structs import CarParams -from opendbc.safety.tests.libsafety import libsafety_py import opendbc.safety.tests.common as common from opendbc.safety.tests.common import CANPackerSafety from opendbc.sunnypilot.car.gm.values_ext import GMSafetyFlagsSP - - class Buttons: UNPRESS = 1 RES_ACCEL = 2 DECEL_SET = 3 CANCEL = 6 - - class GmLongitudinalBase(common.CarSafetyTest, common.LongitudinalGasBrakeSafetyTest): RELAY_MALFUNCTION_ADDRS = {0: (0x180, 0x2CB), 2: (0x184,)} # ASCMLKASteeringCmd, ASCMGasRegenCmd, PSCMStatus @@ -71,9 +66,10 @@ class GmLongitudinalBase(common.CarSafetyTest, common.LongitudinalGasBrakeSafety self.safety.set_controls_allowed(1) self._rx(self._button_msg(Buttons.CANCEL)) self.assertFalse(self.safety.get_controls_allowed()) - - class TestGmSafetyBase(common.CarSafetyTest, common.DriverTorqueSteeringSafetyTest): + DBC = "gm_global_a_powertrain_generated" + SAFETY_MODEL = CarParams.SafetyModel.gm + STANDSTILL_THRESHOLD = 10 * 0.0311 # Ensures ASCM is off on ASCM cars, and relay is not malfunctioning for camera-ACC cars RELAY_MALFUNCTION_ADDRS = {0: (0x180,), 2: (0x184,)} # ASCMLKASteeringCmd, PSCMStatus @@ -92,11 +88,8 @@ class TestGmSafetyBase(common.CarSafetyTest, common.DriverTorqueSteeringSafetyTe EXTRA_SAFETY_PARAM = 0 def setUp(self): - self.packer = CANPackerSafety("gm_global_a_powertrain_generated") + super().setUp() self.packer_chassis = CANPackerSafety("gm_global_a_chassis") - self.safety = libsafety_py.libsafety - self.safety.set_safety_hooks(CarParams.SafetyModel.gm, 0) - self.safety.init_tests() def _pcm_status_msg(self, enable): if self.PCM_CRUISE: @@ -133,8 +126,6 @@ class TestGmSafetyBase(common.CarSafetyTest, common.DriverTorqueSteeringSafetyTe def _button_msg(self, buttons): values = {"ACCButtons": buttons} return self.packer.make_can_msg_safety("ASCMSteeringButton", self.BUTTONS_BUS, values) - - class TestGmEVSafetyBase(TestGmSafetyBase): EXTRA_SAFETY_PARAM = GMSafetyFlags.EV @@ -142,8 +133,6 @@ class TestGmEVSafetyBase(TestGmSafetyBase): def _user_regen_msg(self, regen): values = {"RegenPaddle": 2 if regen else 0} return self.packer.make_can_msg_safety("EBCMRegenPaddle", 0, values) - - class TestGmAscmSafety(GmLongitudinalBase, TestGmSafetyBase): TX_MSGS = [[0x180, 0], [0x409, 0], [0x40A, 0], [0x2CB, 0], [0x370, 0], # pt bus [0xA1, 1], [0x306, 1], [0x308, 1], [0x310, 1], # obs bus @@ -157,36 +146,24 @@ class TestGmAscmSafety(GmLongitudinalBase, TestGmSafetyBase): MIN_GAS = -650 # maximum regen INACTIVE_GAS = -650 - def setUp(self): - self.packer = CANPackerSafety("gm_global_a_powertrain_generated") - self.packer_chassis = CANPackerSafety("gm_global_a_chassis") - self.safety = libsafety_py.libsafety - self.safety.set_safety_hooks(CarParams.SafetyModel.gm, self.EXTRA_SAFETY_PARAM) - self.safety.init_tests() - - + @property + def SAFETY_PARAM(self): + return self.EXTRA_SAFETY_PARAM class TestGmAscmEVSafety(TestGmAscmSafety, TestGmEVSafetyBase): pass - - class TestGmCameraSafetyBase(TestGmSafetyBase): def _user_brake_msg(self, brake): values = {"BrakePressed": brake} return self.packer.make_can_msg_safety("ECMEngineStatus", 0, values) - - class TestGmCameraSafety(TestGmCameraSafetyBase): TX_MSGS = [[0x180, 0], # pt bus [0x184, 2]] # camera bus FWD_BLACKLISTED_ADDRS = {2: [0x180], 0: [0x184]} # block LKAS message and PSCMStatus BUTTONS_BUS = 2 # tx only - def setUp(self): - self.packer = CANPackerSafety("gm_global_a_powertrain_generated") - self.packer_chassis = CANPackerSafety("gm_global_a_chassis") - self.safety = libsafety_py.libsafety - self.safety.set_safety_hooks(CarParams.SafetyModel.gm, GMSafetyFlags.HW_CAM | self.EXTRA_SAFETY_PARAM) - self.safety.init_tests() + @property + def SAFETY_PARAM(self): + return GMSafetyFlags.HW_CAM | self.EXTRA_SAFETY_PARAM def test_buttons(self): # Only CANCEL button is allowed while cruise is enabled @@ -201,12 +178,8 @@ class TestGmCameraSafety(TestGmCameraSafetyBase): for enabled in (True, False): self._rx(self._pcm_status_msg(enabled)) self.assertEqual(enabled, self._tx(self._button_msg(Buttons.CANCEL))) - - class TestGmCameraEVSafety(TestGmCameraSafety, TestGmEVSafetyBase): pass - - class TestGmCameraLongitudinalSafety(GmLongitudinalBase, TestGmCameraSafetyBase): TX_MSGS = [[0x180, 0], [0x315, 0], [0x2CB, 0], [0x370, 0], # pt bus [0x184, 2]] # camera bus @@ -218,45 +191,31 @@ class TestGmCameraLongitudinalSafety(GmLongitudinalBase, TestGmCameraSafetyBase) MIN_GAS = -540 # maximum regen INACTIVE_GAS = -500 - def setUp(self): - self.packer = CANPackerSafety("gm_global_a_powertrain_generated") - self.packer_chassis = CANPackerSafety("gm_global_a_chassis") - self.safety = libsafety_py.libsafety - self.safety.set_safety_hooks(CarParams.SafetyModel.gm, GMSafetyFlags.HW_CAM | GMSafetyFlags.HW_CAM_LONG | self.EXTRA_SAFETY_PARAM) - self.safety.init_tests() - - + @property + def SAFETY_PARAM(self): + return GMSafetyFlags.HW_CAM | GMSafetyFlags.HW_CAM_LONG | self.EXTRA_SAFETY_PARAM class TestGmCameraLongitudinalEVSafety(TestGmCameraLongitudinalSafety, TestGmEVSafetyBase): pass - - class TestGmCameraNonACCSafety(TestGmCameraSafety): + @property + def SAFETY_PARAM(self): + return GMSafetyFlags.HW_CAM | self.EXTRA_SAFETY_PARAM def setUp(self): - self.packer = CANPackerSafety("gm_global_a_powertrain_generated") - self.packer_chassis = CANPackerSafety("gm_global_a_chassis") - self.safety = libsafety_py.libsafety + super().setUp() self.safety.set_current_safety_param_sp(GMSafetyFlagsSP.NON_ACC) - self.safety.set_safety_hooks(CarParams.SafetyModel.gm, GMSafetyFlags.HW_CAM | self.EXTRA_SAFETY_PARAM) - self.safety.init_tests() def _pcm_status_msg(self, enable): values = {"CruiseActive": enable} return self.packer.make_can_msg_safety("ECMCruiseControl", 0, values) - - class TestGmCameraEVNonACCSafety(TestGmCameraNonACCSafety, TestGmEVSafetyBase): pass +class TestGmIgnition(common.SafetyTestBase): + DBC = "gm_global_a_powertrain_generated" + SAFETY_MODEL = None - -class TestGmIgnition(unittest.TestCase): TX_MSGS: list = [] - def setUp(self): - self.safety = libsafety_py.libsafety - self.safety.init_tests() - self.packer = CANPackerSafety("gm_global_a_powertrain_generated") - def _msg(self, mode): return self.packer.make_can_msg_safety("BCMGeneralPlatformStatus", 0, {"SystemPowerMode": mode}) @@ -270,7 +229,5 @@ class TestGmIgnition(unittest.TestCase): self.assertTrue(self.safety.get_ignition_can()) self.safety.ignition_can_hook(self._msg(0)) self.assertFalse(self.safety.get_ignition_can()) - - if __name__ == "__main__": unittest.main() diff --git a/opendbc_repo/opendbc/safety/tests/test_honda.py b/opendbc_repo/opendbc/safety/tests/test_honda.py index 0e564286c..20337cbad 100755 --- a/opendbc_repo/opendbc/safety/tests/test_honda.py +++ b/opendbc_repo/opendbc/safety/tests/test_honda.py @@ -6,14 +6,12 @@ from opendbc.car.honda.values import HondaSafetyFlags from opendbc.safety.tests.libsafety import libsafety_py import opendbc.safety.tests.common as common from opendbc.car.structs import CarParams -from opendbc.safety.tests.common import CANPackerSafety, MAX_WRONG_COUNTERS +from opendbc.safety.tests.common import MAX_WRONG_COUNTERS from opendbc.safety.tests.gas_interceptor_common import GasInterceptorSafetyTest from opendbc.sunnypilot.car.honda.values_ext import HondaSafetyFlagsSP HONDA_N_COMMON_TX_MSGS = [[0xE4, 0], [0x194, 0], [0x1FA, 0], [0x30C, 0], [0x33D, 0]] - - class Btn: NONE = 0 MAIN = 1 @@ -31,8 +29,6 @@ class Btn: # * Bosch with Longitudinal Support # * Bosch Radarless # * Bosch Radarless with Longitudinal Support - - class HondaButtonEnableBase(common.CarSafetyTest): # override these inherited tests since we're using button enable @@ -113,11 +109,11 @@ class HondaButtonEnableBase(common.CarSafetyTest): self.assertFalse(self.safety.get_controls_allowed()) # counter - # reset wrong_counters to zero by sending valid messages + # Skip every other counter to trigger counter faults. for i in range(MAX_WRONG_COUNTERS + 1): - self.__class__.cnt_speed += 1 - self.__class__.cnt_button += 1 - self.__class__.cnt_powertrain_data += 1 + self._speed_msg(0) + self._button_msg(Btn.SET) + self._user_gas_msg(0) if i < MAX_WRONG_COUNTERS: self.safety.set_controls_allowed(1) self._rx(self._button_msg(Btn.SET)) @@ -137,8 +133,6 @@ class HondaButtonEnableBase(common.CarSafetyTest): self._rx(self._user_gas_msg(0)) self._rx(self._button_msg(Btn.SET, main_on=True)) self.assertTrue(self.safety.get_controls_allowed()) - - class HondaPcmEnableBase(common.CarSafetyTest): def test_buttons(self): @@ -164,8 +158,6 @@ class HondaPcmEnableBase(common.CarSafetyTest): self.assertFalse(self.safety.get_controls_allowed()) else: self.assertEqual(controls_allowed, self.safety.get_controls_allowed()) - - class HondaBase(common.CarSafetyTest): MAX_BRAKE = 255 PT_BUS: int | None = None # must be set when inherited @@ -194,28 +186,23 @@ class HondaBase(common.CarSafetyTest): "ACC_STATUS": cruise_on, "BRAKE_PRESSED": brake_pressed, "PEDAL_GAS": gas_pressed, - "COUNTER": self.cnt_powertrain_data % 4 } - self.__class__.cnt_powertrain_data += 1 return self.packer.make_can_msg_safety("POWERTRAIN_DATA", self.PT_BUS, values) def _pcm_status_msg(self, enable): return self._powertrain_data_msg(cruise_on=enable) def _speed_msg(self, speed): - values = {"XMISSION_SPEED": speed, "COUNTER": self.cnt_speed % 4} - self.__class__.cnt_speed += 1 + values = {"XMISSION_SPEED": speed} return self.packer.make_can_msg_safety("ENGINE_DATA", self.PT_BUS, values) def _acc_state_msg(self, main_on): - values = {"MAIN_ON": main_on, "COUNTER": self.cnt_acc_state % 4} - self.__class__.cnt_acc_state += 1 + values = {"MAIN_ON": main_on} return self.packer.make_can_msg_safety("SCM_FEEDBACK", self.PT_BUS, values) def _button_msg(self, buttons, main_on=False, bus=None): bus = self.PT_BUS if bus is None else bus - values = {"CRUISE_BUTTONS": buttons, "COUNTER": self.cnt_button % 4} - self.__class__.cnt_button += 1 + values = {"CRUISE_BUTTONS": buttons} return self.packer.make_can_msg_safety("SCM_BUTTONS", bus, values) def _user_brake_msg(self, brake): @@ -279,12 +266,11 @@ class HondaBase(common.CarSafetyTest): self.assertEqual(1, self.safety.get_mads_button_press()) self._rx(self._lkas_button_msg(False, 0)) self.assertEqual(0, self.safety.get_mads_button_press()) - - # ********************* Honda Nidec ********************** - - class TestHondaNidecSafetyBase(HondaBase): + DBC = "honda_civic_touring_2016_can_generated" + SAFETY_MODEL = CarParams.SafetyModel.hondaNidec + TX_MSGS = HONDA_N_COMMON_TX_MSGS FWD_BLACKLISTED_ADDRS = {2: [0xE4, 0x194, 0x33D, 0x30C]} RELAY_MALFUNCTION_ADDRS = {0: (0xE4, 0x194, 0x33D, 0x30C)} @@ -297,12 +283,6 @@ class TestHondaNidecSafetyBase(HondaBase): BRAKE_SIG = "COMPUTER_BRAKE" - def setUp(self): - self.packer = CANPackerSafety("honda_civic_touring_2016_can_generated") - self.safety = libsafety_py.libsafety - self.safety.set_safety_hooks(CarParams.SafetyModel.hondaNidec, 0) - self.safety.init_tests() - def _send_brake_msg(self, brake, aeb_req=0, bus=0): values = {self.BRAKE_SIG: brake, "AEB_REQ_1": aeb_req} return self.packer.make_can_msg_safety("BRAKE_COMMAND", bus, values) @@ -381,8 +361,6 @@ class TestHondaNidecPcmSafety(HondaPcmEnableBase, TestHondaNidecSafetyBase): # Nidec doesn't disengage on falling edge of cruise. See comment in safety_honda.h def test_disable_control_allowed_from_cruise(self): pass - - class TestHondaNidecGasInterceptorSafety(GasInterceptorSafetyTest, HondaButtonEnableBase, TestHondaNidecSafetyBase): """ Covers the Honda Nidec safety mode with a gas interceptor, switches to a button-enable car @@ -392,49 +370,37 @@ class TestHondaNidecGasInterceptorSafety(GasInterceptorSafetyTest, HondaButtonEn INTERCEPTOR_THRESHOLD = 492 def setUp(self): - self.packer = CANPackerSafety("honda_civic_touring_2016_can_generated") - self.safety = libsafety_py.libsafety + super().setUp() self.safety.set_current_safety_param_sp(HondaSafetyFlagsSP.GAS_INTERCEPTOR) - self.safety.set_safety_hooks(CarParams.SafetyModel.hondaNidec, 0) - self.safety.init_tests() - - class TestHondaNidecPcmAltSafety(TestHondaNidecPcmSafety): """ Covers the Honda Nidec safety mode with alt SCM messages """ - def setUp(self): - self.packer = CANPackerSafety("acura_ilx_2016_can_generated") - self.safety = libsafety_py.libsafety - self.safety.set_safety_hooks(CarParams.SafetyModel.hondaNidec, HondaSafetyFlags.NIDEC_ALT) - self.safety.init_tests() + DBC = "acura_ilx_2016_can_generated" + + SAFETY_PARAM = HondaSafetyFlags.NIDEC_ALT def _acc_state_msg(self, main_on): - values = {"MAIN_ON": main_on, "COUNTER": self.cnt_acc_state % 4} - self.__class__.cnt_acc_state += 1 + values = {"MAIN_ON": main_on} return self.packer.make_can_msg_safety("SCM_BUTTONS", self.PT_BUS, values) def _button_msg(self, buttons, main_on=False, bus=None): bus = self.PT_BUS if bus is None else bus - values = {"CRUISE_BUTTONS": buttons, "MAIN_ON": main_on, "COUNTER": self.cnt_button % 4} - self.__class__.cnt_button += 1 + values = {"CRUISE_BUTTONS": buttons, "MAIN_ON": main_on} return self.packer.make_can_msg_safety("SCM_BUTTONS", bus, values) - - class TestHondaNidecAltGasInterceptorSafety(GasInterceptorSafetyTest, HondaButtonEnableBase, TestHondaNidecSafetyBase): """ Covers the Honda Nidec safety mode with alt SCM messages and gas interceptor, switches to a button-enable car """ + DBC = "acura_ilx_2016_can_generated" + SAFETY_PARAM = HondaSafetyFlags.NIDEC_ALT TX_MSGS = HONDA_N_COMMON_TX_MSGS + [[0x200, 0]] INTERCEPTOR_THRESHOLD = 492 def setUp(self): - self.packer = CANPackerSafety("acura_ilx_2016_can_generated") - self.safety = libsafety_py.libsafety + super().setUp() self.safety.set_current_safety_param_sp(HondaSafetyFlagsSP.GAS_INTERCEPTOR) - self.safety.set_safety_hooks(CarParams.SafetyModel.hondaNidec, HondaSafetyFlags.NIDEC_ALT) - self.safety.init_tests() def _acc_state_msg(self, main_on): values = {"MAIN_ON": main_on, "COUNTER": self.cnt_acc_state % 4} @@ -446,12 +412,11 @@ class TestHondaNidecAltGasInterceptorSafety(GasInterceptorSafetyTest, HondaButto values = {"CRUISE_BUTTONS": buttons, "MAIN_ON": main_on, "COUNTER": self.cnt_button % 4} self.__class__.cnt_button += 1 return self.packer.make_can_msg_safety("SCM_BUTTONS", bus, values) - - # ********************* Honda Bosch ********************** - - class TestHondaBoschSafetyBase(HondaBase): + DBC = "honda_civic_hatchback_ex_2017_can_generated" + SAFETY_MODEL = CarParams.SafetyModel.hondaBosch + PT_BUS = 1 STEER_BUS = 0 BUTTONS_BUS = 1 @@ -460,13 +425,8 @@ class TestHondaBoschSafetyBase(HondaBase): FWD_BLACKLISTED_ADDRS = {2: [0xE4, 0xE5, 0x33D, 0x33DA, 0x33DB]} RELAY_MALFUNCTION_ADDRS = {0: (0xE4, 0xE5, 0x33D, 0x33DA, 0x33DB)} # STEERING_CONTROL, BOSCH_SUPPLEMENTAL_1 - def setUp(self): - self.packer = CANPackerSafety("honda_civic_hatchback_ex_2017_can_generated") - self.safety = libsafety_py.libsafety - def _alt_brake_msg(self, brake): - values = {"BRAKE_PRESSED": brake, "COUNTER": self.cnt_brake % 4} - self.__class__.cnt_brake += 1 + values = {"BRAKE_PRESSED": brake} return self.packer.make_can_msg_safety("BRAKE_MODULE", self.PT_BUS, values) def _send_brake_msg(self, brake): @@ -480,16 +440,11 @@ class TestHondaBoschSafetyBase(HondaBase): # do not block resume if we are engaged already self.safety.set_controls_allowed(1) self.assertTrue(self._tx(self._button_msg(Btn.RESUME, bus=self.BUTTONS_BUS))) - - class TestHondaBoschAltBrakeSafetyBase(TestHondaBoschSafetyBase): """ Base Bosch safety test class with an alternate brake message """ - def setUp(self): - super().setUp() - self.safety.set_safety_hooks(CarParams.SafetyModel.hondaBosch, HondaSafetyFlags.ALT_BRAKE) - self.safety.init_tests() + SAFETY_PARAM = HondaSafetyFlags.ALT_BRAKE def _user_brake_msg(self, brake): return self._alt_brake_msg(brake) @@ -513,28 +468,20 @@ class TestHondaBoschAltBrakeSafetyBase(TestHondaBoschSafetyBase): self.safety.set_controls_allowed(1) self._rx(self._alt_brake_msg(1)) self.assertTrue(self.safety.get_controls_allowed()) - - class TestHondaBoschSafety(HondaPcmEnableBase, TestHondaBoschSafetyBase): """ Covers the Honda Bosch safety mode with stock longitudinal """ - def setUp(self): - super().setUp() - self.safety.set_safety_hooks(CarParams.SafetyModel.hondaBosch, 0) - self.safety.init_tests() - - class TestHondaBoschAltBrakeSafety(HondaPcmEnableBase, TestHondaBoschAltBrakeSafetyBase): """ Covers the Honda Bosch safety mode with stock longitudinal and an alternate brake message """ - - class TestHondaBoschLongSafety(HondaButtonEnableBase, TestHondaBoschSafetyBase): """ Covers the Honda Bosch safety mode with longitudinal control """ + SAFETY_PARAM = HondaSafetyFlags.BOSCH_LONG + NO_GAS = -30000 MAX_GAS = 2000 MAX_ACCEL = 2.0 # accel is used for brakes, but openpilot can set positive values @@ -546,11 +493,6 @@ class TestHondaBoschLongSafety(HondaButtonEnableBase, TestHondaBoschSafetyBase): # 0x1DF is to test that radar is disabled RELAY_MALFUNCTION_ADDRS = {1: (0xE4, 0x1DF, 0x33D, 0x33DA, 0x33DB)} # STEERING_CONTROL, ACC_CONTROL - def setUp(self): - super().setUp() - self.safety.set_safety_hooks(CarParams.SafetyModel.hondaBosch, HondaSafetyFlags.BOSCH_LONG) - self.safety.init_tests() - def _send_gas_brake_msg(self, gas, accel): values = { "GAS_COMMAND": gas, @@ -589,6 +531,8 @@ class TestHondaBoschLongSafety(HondaButtonEnableBase, TestHondaBoschSafetyBase): class TestHondaBoschRadarlessSafetyBase(TestHondaBoschSafetyBase): """Base class for radarless Honda Bosch""" + DBC = "honda_bosch_radarless_generated" + PT_BUS = 0 STEER_BUS = 0 BUTTONS_BUS = 2 # camera controls ACC, need to send buttons on bus 2 @@ -596,48 +540,27 @@ class TestHondaBoschRadarlessSafetyBase(TestHondaBoschSafetyBase): TX_MSGS = [[0xE4, 0], [0x296, 2], [0x33D, 0]] FWD_BLACKLISTED_ADDRS = {2: [0xE4, 0x33D]} RELAY_MALFUNCTION_ADDRS = {0: (0xE4, 0x33D)} # STEERING_CONTROL - - def setUp(self): - self.packer = CANPackerSafety("honda_bosch_radarless_generated") - self.safety = libsafety_py.libsafety - - class TestHondaBoschRadarlessSafety(HondaPcmEnableBase, TestHondaBoschRadarlessSafetyBase): """ Covers the Honda Bosch Radarless safety mode with stock longitudinal """ - - def setUp(self): - super().setUp() - self.safety.set_safety_hooks(CarParams.SafetyModel.hondaBosch, HondaSafetyFlags.RADARLESS) - self.safety.init_tests() - - + SAFETY_PARAM = HondaSafetyFlags.RADARLESS class TestHondaBoschRadarlessAltBrakeSafety(HondaPcmEnableBase, TestHondaBoschRadarlessSafetyBase, TestHondaBoschAltBrakeSafetyBase): """ Covers the Honda Bosch Radarless safety mode with stock longitudinal and an alternate brake message """ - - def setUp(self): - super().setUp() - self.safety.set_safety_hooks(CarParams.SafetyModel.hondaBosch, HondaSafetyFlags.RADARLESS | HondaSafetyFlags.ALT_BRAKE) - self.safety.init_tests() - - + SAFETY_PARAM = HondaSafetyFlags.RADARLESS | HondaSafetyFlags.ALT_BRAKE class TestHondaBoschRadarlessLongSafety(common.LongitudinalAccelSafetyTest, HondaButtonEnableBase, TestHondaBoschRadarlessSafetyBase): """ Covers the Honda Bosch Radarless safety mode with longitudinal control """ + SAFETY_PARAM = HondaSafetyFlags.RADARLESS | HondaSafetyFlags.BOSCH_LONG + TX_MSGS = [[0xE4, 0], [0x33D, 0], [0x1C8, 0], [0x30C, 0]] FWD_BLACKLISTED_ADDRS = {2: [0xE4, 0x33D, 0x1C8, 0x30C]} RELAY_MALFUNCTION_ADDRS = {0: (0xE4, 0x1C8, 0x30C, 0x33D)} - def setUp(self): - super().setUp() - self.safety.set_safety_hooks(CarParams.SafetyModel.hondaBosch, HondaSafetyFlags.RADARLESS | HondaSafetyFlags.BOSCH_LONG) - self.safety.init_tests() - def _accel_msg(self, accel): values = { "ACCEL_COMMAND": accel, @@ -647,10 +570,10 @@ class TestHondaBoschRadarlessLongSafety(common.LongitudinalAccelSafetyTest, Hond # Longitudinal doesn't need to send buttons def test_spam_cancel_safety_check(self): pass - - class TestHondaBoschCANFDSafetyBase(TestHondaBoschSafetyBase): """Base class for CANFD Honda Bosch""" + DBC = "honda_common_canfd_generated" + PT_BUS = 0 STEER_BUS = 0 BUTTONS_BUS = 0 @@ -658,48 +581,26 @@ class TestHondaBoschCANFDSafetyBase(TestHondaBoschSafetyBase): TX_MSGS = [[0xE4, 0], [0x296, 0], [0x33D, 0]] FWD_BLACKLISTED_ADDRS = {2: [0xE4, 0x33D]} RELAY_MALFUNCTION_ADDRS = {0: (0xE4, 0x33D)} - - def setUp(self): - self.packer = CANPackerSafety("honda_common_canfd_generated") - self.safety = libsafety_py.libsafety - - class TestHondaBoschCANFDSafety(HondaPcmEnableBase, TestHondaBoschCANFDSafetyBase): """ Covers the Honda Bosch CANFD safety mode with stock longitudinal """ - - def setUp(self): - super().setUp() - self.safety.set_safety_hooks(CarParams.SafetyModel.hondaBosch, HondaSafetyFlags.BOSCH_CANFD) - self.safety.init_tests() - - + SAFETY_PARAM = HondaSafetyFlags.BOSCH_CANFD class TestHondaBoschCANFDAltBrakeSafety(HondaPcmEnableBase, TestHondaBoschCANFDSafetyBase, TestHondaBoschAltBrakeSafetyBase): """ Covers the Honda Bosch CANFD safety mode with stock longitudinal and an alternate brake message """ - - def setUp(self): - super().setUp() - self.safety.set_safety_hooks(CarParams.SafetyModel.hondaBosch, HondaSafetyFlags.BOSCH_CANFD | HondaSafetyFlags.ALT_BRAKE) - self.safety.init_tests() - - + SAFETY_PARAM = HondaSafetyFlags.BOSCH_CANFD | HondaSafetyFlags.ALT_BRAKE class TestHondaNidecHybridSafety(TestHondaNidecPcmSafety): """ Covers the Honda Nidec safety mode with hybrid brake """ BRAKE_SIG = "COMPUTER_BRAKE_HYBRID" + DBC = "honda_clarity_hybrid_2018_can_generated" def setUp(self): - self.packer = CANPackerSafety("honda_clarity_hybrid_2018_can_generated") - self.safety = libsafety_py.libsafety + super().setUp() self.safety.set_current_safety_param_sp(HondaSafetyFlagsSP.NIDEC_HYBRID) - self.safety.set_safety_hooks(CarParams.SafetyModel.hondaNidec, 0) - self.safety.init_tests() - - if __name__ == "__main__": unittest.main() diff --git a/opendbc_repo/opendbc/safety/tests/test_hyundai.py b/opendbc_repo/opendbc/safety/tests/test_hyundai.py index 333a0d93b..1920fcece 100755 --- a/opendbc_repo/opendbc/safety/tests/test_hyundai.py +++ b/opendbc_repo/opendbc/safety/tests/test_hyundai.py @@ -5,8 +5,8 @@ import unittest from opendbc.car.hyundai.values import HyundaiSafetyFlags from opendbc.car.structs import CarParams -from opendbc.safety.tests.libsafety import libsafety_py import opendbc.safety.tests.common as common +from opendbc.safety.tests.libsafety import libsafety_py from opendbc.safety.tests.common import CANPackerSafety from opendbc.safety.tests.hyundai_common import HyundaiButtonBase, HyundaiLongitudinalBase @@ -32,8 +32,6 @@ _ALL_NON_SCC_HEV_EV_COMBOS = [ "SAFETY_PARAM": HyundaiSafetyFlags.EV_GAS}, ] ALL_NON_SCC_HEV_EV_COMBOS = [{**p, **lda} for lda in LDA_BUTTON for p in _ALL_NON_SCC_HEV_EV_COMBOS] - - # 4 bit checkusm used in some hyundai messages # lives outside the can packer because we never send this msg def checksum(msg): @@ -67,10 +65,11 @@ def checksum(msg): ret[6 if addr == 0x394 else 7] |= chksum << (4 if addr == 0x421 else 0) return addr, ret, bus - - @parameterized_class(LDA_BUTTON) class TestHyundaiSafety(HyundaiButtonBase, common.CarSafetyTest, common.DriverTorqueSteeringSafetyTest, common.SteerRequestCutSafetyTest): + DBC = "hyundai_can_generated" + SAFETY_MODEL = CarParams.SafetyModel.hyundai + TX_MSGS = [[0x340, 0], [0x4F1, 0], [0x485, 0]] STANDSTILL_THRESHOLD = 12 # 0.375 kph RELAY_MALFUNCTION_ADDRS = {0: (0x340, 0x485)} # LKAS11 @@ -102,11 +101,8 @@ class TestHyundaiSafety(HyundaiButtonBase, common.CarSafetyTest, common.DriverTo raise unittest.SkipTest def setUp(self): - self.packer = CANPackerSafety("hyundai_can_generated") - self.safety = libsafety_py.libsafety + super().setUp() self.safety.set_current_safety_param_sp(self.SAFETY_PARAM_SP) - self.safety.set_safety_hooks(CarParams.SafetyModel.hyundai, 0) - self.safety.init_tests() def _button_msg(self, buttons, main_button=0, bus=0): values = {"CF_Clu_CruiseSwState": buttons, "CF_Clu_CruiseSwMain": main_button, "CF_Clu_AliveCnt1": self.cnt_button} @@ -224,10 +220,10 @@ class TestHyundaiSafety(HyundaiButtonBase, common.CarSafetyTest, common.DriverTo self.assertEqual(enable_mads and has_lda_button_param, self.safety.get_controls_allowed_lateral()) finally: self.safety.set_current_safety_param_sp(default_safety_param_sp) - - @parameterized_class(LDA_BUTTON) class TestHyundaiSafetyAltLimits(TestHyundaiSafety): + SAFETY_PARAM = HyundaiSafetyFlags.ALT_LIMITS + MAX_RATE_UP = 2 MAX_RATE_DOWN = 3 MAX_TORQUE_LOOKUP = [0], [270] @@ -239,15 +235,12 @@ class TestHyundaiSafetyAltLimits(TestHyundaiSafety): raise unittest.SkipTest def setUp(self): - self.packer = CANPackerSafety("hyundai_can_generated") - self.safety = libsafety_py.libsafety + super().setUp() self.safety.set_current_safety_param_sp(self.SAFETY_PARAM_SP) - self.safety.set_safety_hooks(CarParams.SafetyModel.hyundai, HyundaiSafetyFlags.ALT_LIMITS) - self.safety.init_tests() - - @parameterized_class(LDA_BUTTON) class TestHyundaiSafetyAltLimits2(TestHyundaiSafety): + SAFETY_PARAM = HyundaiSafetyFlags.ALT_LIMITS_2 + MAX_RATE_UP = 2 MAX_RATE_DOWN = 3 MAX_TORQUE_LOOKUP = [0], [170] @@ -259,15 +252,12 @@ class TestHyundaiSafetyAltLimits2(TestHyundaiSafety): raise unittest.SkipTest def setUp(self): - self.packer = CANPackerSafety("hyundai_can_generated") - self.safety = libsafety_py.libsafety + super().setUp() self.safety.set_current_safety_param_sp(self.SAFETY_PARAM_SP) - self.safety.set_safety_hooks(CarParams.SafetyModel.hyundai, HyundaiSafetyFlags.ALT_LIMITS_2) - self.safety.init_tests() - - @parameterized_class(LDA_BUTTON) class TestHyundaiSafetyCameraSCC(TestHyundaiSafety): + SAFETY_PARAM = HyundaiSafetyFlags.CAMERA_SCC + BUTTONS_TX_BUS = 2 # tx on 2, rx on 0 SCC_BUS = 2 # rx on 2 @@ -278,11 +268,8 @@ class TestHyundaiSafetyCameraSCC(TestHyundaiSafety): raise unittest.SkipTest def setUp(self): - self.packer = CANPackerSafety("hyundai_can_generated") - self.safety = libsafety_py.libsafety + super().setUp() self.safety.set_current_safety_param_sp(self.SAFETY_PARAM_SP) - self.safety.set_safety_hooks(CarParams.SafetyModel.hyundai, HyundaiSafetyFlags.CAMERA_SCC) - self.safety.init_tests() def test_pcm_main_cruise_state_availability(self): """ @@ -294,10 +281,10 @@ class TestHyundaiSafetyCameraSCC(TestHyundaiSafety): with self.subTest("acc_main_on", should_turn_acc_main_on=should_turn_acc_main_on): self._rx(self._acc_state_msg(should_turn_acc_main_on)) self.assertEqual(should_turn_acc_main_on, self.safety.get_acc_main_on()) - - @parameterized_class(LDA_BUTTON) class TestHyundaiSafetyFCEV(TestHyundaiSafety): + SAFETY_PARAM = HyundaiSafetyFlags.FCEV_GAS + @classmethod def setUpClass(cls): if cls.__name__ == "TestHyundaiSafetyFCEV": @@ -305,51 +292,32 @@ class TestHyundaiSafetyFCEV(TestHyundaiSafety): raise unittest.SkipTest def setUp(self): - self.packer = CANPackerSafety("hyundai_can_generated") - self.safety = libsafety_py.libsafety + super().setUp() self.safety.set_current_safety_param_sp(self.SAFETY_PARAM_SP) - self.safety.set_safety_hooks(CarParams.SafetyModel.hyundai, HyundaiSafetyFlags.FCEV_GAS) - self.safety.init_tests() def _user_gas_msg(self, gas): values = {"ACCELERATOR_PEDAL": gas} return self.packer.make_can_msg_safety("FCEV_ACCELERATOR", 0, values) - - class TestHyundaiLegacySafety(TestHyundaiSafety): - def setUp(self): - self.packer = CANPackerSafety("hyundai_can_generated") - self.safety = libsafety_py.libsafety - self.safety.set_safety_hooks(CarParams.SafetyModel.hyundaiLegacy, 0) - self.safety.init_tests() - - + SAFETY_MODEL = CarParams.SafetyModel.hyundaiLegacy class TestHyundaiLegacySafetyEV(TestHyundaiSafety): - def setUp(self): - self.packer = CANPackerSafety("hyundai_can_generated") - self.safety = libsafety_py.libsafety - self.safety.set_safety_hooks(CarParams.SafetyModel.hyundaiLegacy, HyundaiSafetyFlags.EV_GAS) - self.safety.init_tests() + SAFETY_MODEL = CarParams.SafetyModel.hyundaiLegacy + SAFETY_PARAM = HyundaiSafetyFlags.EV_GAS def _user_gas_msg(self, gas): values = {"Accel_Pedal_Pos": gas} return self.packer.make_can_msg_safety("E_EMS11", 0, values, fix_checksum=checksum) - - class TestHyundaiLegacySafetyHEV(TestHyundaiSafety): - def setUp(self): - self.packer = CANPackerSafety("hyundai_can_generated") - self.safety = libsafety_py.libsafety - self.safety.set_safety_hooks(CarParams.SafetyModel.hyundaiLegacy, HyundaiSafetyFlags.HYBRID_GAS) - self.safety.init_tests() + SAFETY_MODEL = CarParams.SafetyModel.hyundaiLegacy + SAFETY_PARAM = HyundaiSafetyFlags.HYBRID_GAS def _user_gas_msg(self, gas): values = {"CR_Vcu_AccPedDep_Pos": gas} return self.packer.make_can_msg_safety("E_EMS11", 0, values, fix_checksum=checksum) - - @parameterized_class(LDA_BUTTON) class TestHyundaiLongitudinalSafety(HyundaiLongitudinalBase, TestHyundaiSafety): + SAFETY_PARAM = HyundaiSafetyFlags.LONG + TX_MSGS = [[0x340, 0], [0x4F1, 0], [0x485, 0], [0x420, 0], [0x421, 0], [0x50A, 0], [0x389, 0], [0x4A2, 0], [0x38D, 0], [0x483, 0], [0x7D0, 0]] FWD_BLACKLISTED_ADDRS = {2: [0x340, 0x485, 0x421, 0x420, 0x50A, 0x389]} @@ -366,11 +334,8 @@ class TestHyundaiLongitudinalSafety(HyundaiLongitudinalBase, TestHyundaiSafety): raise unittest.SkipTest def setUp(self): - self.packer = CANPackerSafety("hyundai_can_generated") - self.safety = libsafety_py.libsafety + super().setUp() self.safety.set_current_safety_param_sp(self.SAFETY_PARAM_SP) - self.safety.set_safety_hooks(CarParams.SafetyModel.hyundai, HyundaiSafetyFlags.LONG) - self.safety.init_tests() def _accel_msg(self, accel, aeb_req=False, aeb_decel=0): values = { @@ -408,17 +373,16 @@ class TestHyundaiLongitudinalSafety(HyundaiLongitudinalBase, TestHyundaiSafety): class TestHyundaiLongitudinalSafetyCameraSCC(HyundaiLongitudinalBase, TestHyundaiSafety): + SAFETY_PARAM = HyundaiSafetyFlags.LONG | HyundaiSafetyFlags.CAMERA_SCC + TX_MSGS = [[0x340, 0], [0x4F1, 2], [0x485, 0], [0x420, 0], [0x421, 0], [0x50A, 0], [0x389, 0], [0x4A2, 0]] FWD_BLACKLISTED_ADDRS = {2: [0x340, 0x485, 0x420, 0x421, 0x50A, 0x389]} RELAY_MALFUNCTION_ADDRS = {0: (0x340, 0x485, 0x421, 0x420, 0x50A, 0x389)} # LKAS11, LFAHDA_MFC, SCC12, SCC11, SCC13, SCC14 def setUp(self): - self.packer = CANPackerSafety("hyundai_can_generated") - self.safety = libsafety_py.libsafety + super().setUp() self.safety.set_current_safety_param_sp(HyundaiSafetyFlagsSP.HAS_LDA_BUTTON) - self.safety.set_safety_hooks(CarParams.SafetyModel.hyundai, HyundaiSafetyFlags.LONG | HyundaiSafetyFlags.CAMERA_SCC) - self.safety.init_tests() def _accel_msg(self, accel, aeb_req=False, aeb_decel=0): values = { @@ -443,10 +407,10 @@ class TestHyundaiLongitudinalSafetyCameraSCC(HyundaiLongitudinalBase, TestHyunda def test_disabled_ecu_alive(self): pass - - @parameterized_class(LDA_BUTTON) class TestHyundaiSafetyFCEVLong(TestHyundaiLongitudinalSafety, TestHyundaiSafetyFCEV): + SAFETY_PARAM = HyundaiSafetyFlags.FCEV_GAS | HyundaiSafetyFlags.LONG + @classmethod def setUpClass(cls): if cls.__name__ == "TestHyundaiSafetyFCEVLong": @@ -454,13 +418,8 @@ class TestHyundaiSafetyFCEVLong(TestHyundaiLongitudinalSafety, TestHyundaiSafety raise unittest.SkipTest def setUp(self): - self.packer = CANPackerSafety("hyundai_can_generated") - self.safety = libsafety_py.libsafety + super().setUp() self.safety.set_current_safety_param_sp(self.SAFETY_PARAM_SP) - self.safety.set_safety_hooks(CarParams.SafetyModel.hyundai, HyundaiSafetyFlags.FCEV_GAS | HyundaiSafetyFlags.LONG) - self.safety.init_tests() - - @parameterized_class(LDA_BUTTON) class TestHyundaiLongitudinalESCCSafety(HyundaiLongitudinalBase, TestHyundaiSafety): TX_MSGS = [[0x340, 0], [0x4F1, 0], [0x485, 0], [0x420, 0], [0x421, 0], [0x50A, 0], [0x389, 0]] @@ -497,8 +456,6 @@ class TestHyundaiLongitudinalESCCSafety(HyundaiLongitudinalBase, TestHyundaiSafe def test_disabled_ecu_alive(self): pass - - @parameterized_class(LDA_BUTTON) class TestHyundaiNonSCCSafety(TestHyundaiSafety): @@ -548,8 +505,6 @@ class TestHyundaiNonSCCSafety(TestHyundaiSafety): # Make sure we can re-gain longitudinal actuation self._rx(self._user_gas_msg(0, self.safety.get_controls_allowed())) self.assertTrue(self.safety.get_longitudinal_allowed()) - - @parameterized_class(ALL_NON_SCC_HEV_EV_COMBOS) class TestHyundaiNonSCCSafety_HEV_EV(TestHyundaiSafety): @@ -582,7 +537,5 @@ class TestHyundaiNonSCCSafety_HEV_EV(TestHyundaiSafety): def _user_gas_msg(self, gas): values = {self.GAS_MSG[1]: gas} return self.packer.make_can_msg_safety(self.GAS_MSG[0], 0, values, fix_checksum=checksum) - - if __name__ == "__main__": unittest.main() diff --git a/opendbc_repo/opendbc/safety/tests/test_hyundai_canfd.py b/opendbc_repo/opendbc/safety/tests/test_hyundai_canfd.py index a5f7702f8..d7fbea930 100755 --- a/opendbc_repo/opendbc/safety/tests/test_hyundai_canfd.py +++ b/opendbc_repo/opendbc/safety/tests/test_hyundai_canfd.py @@ -4,26 +4,25 @@ import unittest from opendbc.car.hyundai.values import HyundaiSafetyFlags from opendbc.car.structs import CarParams -from opendbc.safety.tests.libsafety import libsafety_py import opendbc.safety.tests.common as common -from opendbc.safety.tests.common import CANPackerSafety from opendbc.safety.tests.hyundai_common import HyundaiButtonBase, HyundaiLongitudinalBase # All combinations of radar/camera-SCC and gas/hybrid/EV cars ALL_GAS_EV_HYBRID_COMBOS = [ # Radar SCC - {"GAS_MSG": ("ACCELERATOR_BRAKE_ALT", "ACCELERATOR_PEDAL_PRESSED"), "SCC_BUS": 0, "SAFETY_PARAM": 0}, - {"GAS_MSG": ("ACCELERATOR", "ACCELERATOR_PEDAL"), "SCC_BUS": 0, "SAFETY_PARAM": HyundaiSafetyFlags.EV_GAS}, - {"GAS_MSG": ("ACCELERATOR_ALT", "ACCELERATOR_PEDAL"), "SCC_BUS": 0, "SAFETY_PARAM": HyundaiSafetyFlags.HYBRID_GAS}, + {"GAS_MSG": ("ACCELERATOR_BRAKE_ALT", "ACCELERATOR_PEDAL_PRESSED"), "SCC_BUS": 0, "EXTRA_SAFETY_PARAM": 0}, + {"GAS_MSG": ("ACCELERATOR", "ACCELERATOR_PEDAL"), "SCC_BUS": 0, "EXTRA_SAFETY_PARAM": HyundaiSafetyFlags.EV_GAS}, + {"GAS_MSG": ("ACCELERATOR_ALT", "ACCELERATOR_PEDAL"), "SCC_BUS": 0, "EXTRA_SAFETY_PARAM": HyundaiSafetyFlags.HYBRID_GAS}, # Camera SCC - {"GAS_MSG": ("ACCELERATOR_BRAKE_ALT", "ACCELERATOR_PEDAL_PRESSED"), "SCC_BUS": 2, "SAFETY_PARAM": HyundaiSafetyFlags.CAMERA_SCC}, - {"GAS_MSG": ("ACCELERATOR", "ACCELERATOR_PEDAL"), "SCC_BUS": 2, "SAFETY_PARAM": HyundaiSafetyFlags.EV_GAS | HyundaiSafetyFlags.CAMERA_SCC}, - {"GAS_MSG": ("ACCELERATOR_ALT", "ACCELERATOR_PEDAL"), "SCC_BUS": 2, "SAFETY_PARAM": HyundaiSafetyFlags.HYBRID_GAS | HyundaiSafetyFlags.CAMERA_SCC}, + {"GAS_MSG": ("ACCELERATOR_BRAKE_ALT", "ACCELERATOR_PEDAL_PRESSED"), "SCC_BUS": 2, "EXTRA_SAFETY_PARAM": HyundaiSafetyFlags.CAMERA_SCC}, + {"GAS_MSG": ("ACCELERATOR", "ACCELERATOR_PEDAL"), "SCC_BUS": 2, "EXTRA_SAFETY_PARAM": HyundaiSafetyFlags.EV_GAS | HyundaiSafetyFlags.CAMERA_SCC}, + {"GAS_MSG": ("ACCELERATOR_ALT", "ACCELERATOR_PEDAL"), "SCC_BUS": 2, "EXTRA_SAFETY_PARAM": HyundaiSafetyFlags.HYBRID_GAS | HyundaiSafetyFlags.CAMERA_SCC}, ] - - class TestHyundaiCanfdBase(HyundaiButtonBase, common.CarSafetyTest, common.DriverTorqueSteeringSafetyTest, common.SteerRequestCutSafetyTest): + DBC = "hyundai_canfd_generated" + SAFETY_MODEL = CarParams.SafetyModel.hyundaiCanfd + TX_MSGS = [[0x50, 0], [0x1CF, 1], [0x2A4, 0]] STANDSTILL_THRESHOLD = 12 # 0.375 kph FWD_BLACKLISTED_ADDRS = {2: [0x50, 0x2a4]} @@ -91,8 +90,6 @@ class TestHyundaiCanfdBase(HyundaiButtonBase, common.CarSafetyTest, common.Drive def _main_cruise_button_msg(self, enabled): return self._button_msg(0, enabled) - - class TestHyundaiCanfdLFASteeringBase(TestHyundaiCanfdBase): TX_MSGS = [[0x12A, 0], [0x1A0, 1], [0x1CF, 0], [0x1E0, 0]] @@ -101,37 +98,28 @@ class TestHyundaiCanfdLFASteeringBase(TestHyundaiCanfdBase): STEER_MSG = "LFA" BUTTONS_TX_BUS = 2 - SAFETY_PARAM: int + EXTRA_SAFETY_PARAM: int @classmethod def setUpClass(cls): super().setUpClass() if cls.__name__ in ("TestHyundaiCanfdLFASteering", "TestHyundaiCanfdLFASteeringAltButtons"): cls.packer = None - cls.safety = None raise unittest.SkipTest - def setUp(self): - self.packer = CANPackerSafety("hyundai_canfd_generated") - self.safety = libsafety_py.libsafety - self.safety.set_safety_hooks(CarParams.SafetyModel.hyundaiCanfd, self.SAFETY_PARAM) - self.safety.init_tests() - - + @property + def SAFETY_PARAM(self): + return self.EXTRA_SAFETY_PARAM @parameterized_class(ALL_GAS_EV_HYBRID_COMBOS) class TestHyundaiCanfdLFASteering(TestHyundaiCanfdLFASteeringBase): pass - - class TestHyundaiCanfdLFASteeringAltButtonsBase(TestHyundaiCanfdLFASteeringBase): - SAFETY_PARAM: int + EXTRA_SAFETY_PARAM: int - def setUp(self): - self.packer = CANPackerSafety("hyundai_canfd_generated") - self.safety = libsafety_py.libsafety - self.safety.set_safety_hooks(CarParams.SafetyModel.hyundaiCanfd, HyundaiSafetyFlags.CANFD_ALT_BUTTONS | self.SAFETY_PARAM) - self.safety.init_tests() + @property + def SAFETY_PARAM(self): + return HyundaiSafetyFlags.CANFD_ALT_BUTTONS | self.EXTRA_SAFETY_PARAM def _button_msg(self, buttons, main_button=0, bus=1): values = { @@ -164,15 +152,13 @@ class TestHyundaiCanfdLFASteeringAltButtonsBase(TestHyundaiCanfdLFASteeringBase) self.assertTrue(self._tx(self._acc_cancel_msg(True))) self.assertFalse(self._tx(self._acc_cancel_msg(True, accel=1))) self.assertFalse(self._tx(self._acc_cancel_msg(False))) - - @parameterized_class(ALL_GAS_EV_HYBRID_COMBOS) class TestHyundaiCanfdLFASteeringAltButtons(TestHyundaiCanfdLFASteeringAltButtonsBase): pass - - class TestHyundaiCanfdLKASteeringEV(TestHyundaiCanfdBase): + SAFETY_PARAM = HyundaiSafetyFlags.CANFD_LKA_STEER_MSG | HyundaiSafetyFlags.EV_GAS + TX_MSGS = [[0x50, 0], [0x1CF, 1], [0x2A4, 0]] RELAY_MALFUNCTION_ADDRS = {0: (0x50, 0x2a4)} # LKAS, CAM_0x2A4 FWD_BLACKLISTED_ADDRS = {2: [0x50, 0x2a4]} @@ -181,17 +167,11 @@ class TestHyundaiCanfdLKASteeringEV(TestHyundaiCanfdBase): SCC_BUS = 1 STEER_MSG = "LKAS" GAS_MSG = ("ACCELERATOR", "ACCELERATOR_PEDAL") - - def setUp(self): - self.packer = CANPackerSafety("hyundai_canfd_generated") - self.safety = libsafety_py.libsafety - self.safety.set_safety_hooks(CarParams.SafetyModel.hyundaiCanfd, HyundaiSafetyFlags.CANFD_LKA_STEER_MSG | HyundaiSafetyFlags.EV_GAS) - self.safety.init_tests() - - # TODO: Handle ICE and HEV configurations once we see cars that use the new messages class TestHyundaiCanfdLKASteeringAltEV(TestHyundaiCanfdBase): + SAFETY_PARAM = HyundaiSafetyFlags.CANFD_LKA_STEER_MSG | HyundaiSafetyFlags.EV_GAS | HyundaiSafetyFlags.CANFD_LKA_STEER_MSG_ALT + TX_MSGS = [[0x110, 0], [0x1CF, 1], [0x362, 0]] RELAY_MALFUNCTION_ADDRS = {0: (0x110, 0x362)} # LKAS_ALT, CAM_0x362 FWD_BLACKLISTED_ADDRS = {2: [0x110, 0x362]} @@ -200,17 +180,10 @@ class TestHyundaiCanfdLKASteeringAltEV(TestHyundaiCanfdBase): SCC_BUS = 1 STEER_MSG = "LKAS_ALT" GAS_MSG = ("ACCELERATOR", "ACCELERATOR_PEDAL") - - def setUp(self): - self.packer = CANPackerSafety("hyundai_canfd_generated") - self.safety = libsafety_py.libsafety - self.safety.set_safety_hooks(CarParams.SafetyModel.hyundaiCanfd, HyundaiSafetyFlags.CANFD_LKA_STEER_MSG | HyundaiSafetyFlags.EV_GAS | - HyundaiSafetyFlags.CANFD_LKA_STEER_MSG_ALT) - self.safety.init_tests() - - class TestHyundaiCanfdLKASteeringLongEV(HyundaiLongitudinalBase, TestHyundaiCanfdLKASteeringEV): + SAFETY_PARAM = HyundaiSafetyFlags.CANFD_LKA_STEER_MSG | HyundaiSafetyFlags.LONG | HyundaiSafetyFlags.EV_GAS + TX_MSGS = [[0x50, 0], [0x1CF, 1], [0x2A4, 0], [0x51, 0], [0x730, 1], [0x12a, 1], [0x160, 1], [0x1e0, 1], [0x1a0, 1], [0x1ea, 1], [0x200, 1], [0x345, 1], [0x1da, 1]] @@ -223,13 +196,6 @@ class TestHyundaiCanfdLKASteeringLongEV(HyundaiLongitudinalBase, TestHyundaiCanf GAS_MSG = ("ACCELERATOR", "ACCELERATOR_PEDAL") STEER_BUS = 1 - def setUp(self): - self.packer = CANPackerSafety("hyundai_canfd_generated") - self.safety = libsafety_py.libsafety - self.safety.set_safety_hooks(CarParams.SafetyModel.hyundaiCanfd, HyundaiSafetyFlags.CANFD_LKA_STEER_MSG | - HyundaiSafetyFlags.LONG | HyundaiSafetyFlags.EV_GAS) - self.safety.init_tests() - def _accel_msg(self, accel, aeb_req=False, aeb_decel=0): values = { "aReqRaw": accel, @@ -240,8 +206,6 @@ class TestHyundaiCanfdLKASteeringLongEV(HyundaiLongitudinalBase, TestHyundaiCanf def _tx_acc_state_msg(self, enable): values = {"MainMode_ACC": enable} return self.packer.make_can_msg_safety("SCC_CONTROL", self.PT_BUS, values) - - # Tests longitudinal for ICE, hybrid, EV cars with LFA steering class TestHyundaiCanfdLFASteeringLongBase(HyundaiLongitudinalBase, TestHyundaiCanfdLFASteeringBase): @@ -252,17 +216,9 @@ class TestHyundaiCanfdLFASteeringLongBase(HyundaiLongitudinalBase, TestHyundaiCa DISABLED_ECU_UDS_MSG = (0x7D0, 0) DISABLED_ECU_ACTUATION_MSG = (0x1a0, 0) - @classmethod - def setUpClass(cls): - if cls.__name__ == "TestHyundaiCanfdLFASteeringLongBase": - cls.safety = None - raise unittest.SkipTest - - def setUp(self): - self.packer = CANPackerSafety("hyundai_canfd_generated") - self.safety = libsafety_py.libsafety - self.safety.set_safety_hooks(CarParams.SafetyModel.hyundaiCanfd, HyundaiSafetyFlags.LONG | self.SAFETY_PARAM) - self.safety.init_tests() + @property + def SAFETY_PARAM(self): + return HyundaiSafetyFlags.LONG | self.EXTRA_SAFETY_PARAM def _accel_msg(self, accel, aeb_req=False, aeb_decel=0): values = { @@ -275,38 +231,29 @@ class TestHyundaiCanfdLFASteeringLongBase(HyundaiLongitudinalBase, TestHyundaiCa values = {"MainMode_ACC": enable} return self.packer.make_can_msg_safety("SCC_CONTROL", self.PT_BUS, values) - # no knockout - def test_tester_present_allowed(self): - pass - - + def test_tester_present_allowed(self, ecu_disable: bool = True): + super().test_tester_present_allowed(ecu_disable=not self.EXTRA_SAFETY_PARAM & HyundaiSafetyFlags.CAMERA_SCC) @parameterized_class(ALL_GAS_EV_HYBRID_COMBOS) class TestHyundaiCanfdLFASteeringLong(TestHyundaiCanfdLFASteeringLongBase): @classmethod def setUpClass(cls): + super().setUpClass() if cls.__name__ == "TestHyundaiCanfdLFASteeringLong": - cls.safety = None raise unittest.SkipTest - - @parameterized_class(ALL_GAS_EV_HYBRID_COMBOS) class TestHyundaiCanfdLFASteeringLongAltButtons(TestHyundaiCanfdLFASteeringLongBase, TestHyundaiCanfdLFASteeringAltButtonsBase): @classmethod def setUpClass(cls): + super().setUpClass() if cls.__name__ == "TestHyundaiCanfdLFASteeringLongAltButtons": - cls.safety = None raise unittest.SkipTest - def setUp(self): - self.packer = CANPackerSafety("hyundai_canfd_generated") - self.safety = libsafety_py.libsafety - self.safety.set_safety_hooks(CarParams.SafetyModel.hyundaiCanfd, HyundaiSafetyFlags.LONG | HyundaiSafetyFlags.CANFD_ALT_BUTTONS | self.SAFETY_PARAM) - self.safety.init_tests() + @property + def SAFETY_PARAM(self): + return HyundaiSafetyFlags.LONG | HyundaiSafetyFlags.CANFD_ALT_BUTTONS | self.EXTRA_SAFETY_PARAM def test_acc_cancel(self): # Alt buttons does not use SCC_CONTROL to cancel if longitudinal pass - - if __name__ == "__main__": unittest.main() diff --git a/opendbc_repo/opendbc/safety/tests/test_mazda.py b/opendbc_repo/opendbc/safety/tests/test_mazda.py index 8fb77444a..70d901359 100755 --- a/opendbc_repo/opendbc/safety/tests/test_mazda.py +++ b/opendbc_repo/opendbc/safety/tests/test_mazda.py @@ -2,13 +2,13 @@ import unittest from opendbc.car.structs import CarParams -from opendbc.safety.tests.libsafety import libsafety_py import opendbc.safety.tests.common as common -from opendbc.safety.tests.common import CANPackerSafety, make_msg - - +from opendbc.safety.tests.common import make_msg class TestMazdaSafety(common.CarSafetyTest, common.DriverTorqueSteeringSafetyTest): + DBC = "mazda_2017" + SAFETY_MODEL = CarParams.SafetyModel.mazda + TX_MSGS = [[0x243, 0], [0x09d, 0], [0x440, 0]] STANDSTILL_THRESHOLD = .1 RELAY_MALFUNCTION_ADDRS = {0: (0x243, 0x440)} @@ -26,12 +26,6 @@ class TestMazdaSafety(common.CarSafetyTest, common.DriverTorqueSteeringSafetyTes # Mazda actually does not set any bit when requesting torque NO_STEER_REQ_BIT = True - def setUp(self): - self.packer = CANPackerSafety("mazda_2017") - self.safety = libsafety_py.libsafety - self.safety.set_safety_hooks(CarParams.SafetyModel.mazda, 0) - self.safety.init_tests() - def _torque_meas_msg(self, torque): values = {"STEER_TORQUE_MOTOR": torque} return self.packer.make_can_msg_safety("STEER_TORQUE", 0, values) @@ -79,15 +73,11 @@ class TestMazdaSafety(common.CarSafetyTest, common.DriverTorqueSteeringSafetyTes self.safety.set_controls_allowed(1) self.assertTrue(self._tx(self._button_msg(cancel=True))) self.assertTrue(self._tx(self._button_msg(resume=True))) +class TestMazdaIgnition(common.SafetyTestBase): + SAFETY_MODEL = None - -class TestMazdaIgnition(unittest.TestCase): TX_MSGS: list = [] - def setUp(self): - self.safety = libsafety_py.libsafety - self.safety.init_tests() - def _msg(self, byte0): return make_msg(0, 0x9E, dat=bytes([byte0]) + b"\x00" * 7) @@ -101,7 +91,5 @@ class TestMazdaIgnition(unittest.TestCase): self.assertTrue(self.safety.get_ignition_can()) self.safety.ignition_can_hook(self._msg(0x20)) self.assertFalse(self.safety.get_ignition_can()) - - if __name__ == "__main__": unittest.main() diff --git a/opendbc_repo/opendbc/safety/tests/test_nissan.py b/opendbc_repo/opendbc/safety/tests/test_nissan.py index f21c5c335..67107e8a3 100755 --- a/opendbc_repo/opendbc/safety/tests/test_nissan.py +++ b/opendbc_repo/opendbc/safety/tests/test_nissan.py @@ -4,14 +4,15 @@ import unittest from opendbc.car.nissan.values import NissanSafetyFlags from opendbc.sunnypilot.car.nissan.values import NissanSafetyFlagsSP from opendbc.car.structs import CarParams -from opendbc.safety.tests.libsafety import libsafety_py import opendbc.safety.tests.common as common +from opendbc.safety.tests.libsafety import libsafety_py from opendbc.safety.tests.common import CANPackerSafety - - class TestNissanSafety(common.CarSafetyTest, common.AngleSteeringSafetyTest): - TX_MSGS = [[0x169, 0], [0x2b1, 0], [0x4cc, 0], [0x20b, 2]] + DBC = "nissan_x_trail_2017_generated" + SAFETY_MODEL = CarParams.SafetyModel.nissan + + TX_MSGS = [[0x169, 0], [0x2b1, 0], [0x4cc, 0], [0x20b, 2], [0x280, 2]] GAS_PRESSED_THRESHOLD = 3 RELAY_MALFUNCTION_ADDRS = {0: (0x169, 0x2b1, 0x4cc), 2: (0x20b,)} FWD_BLACKLISTED_ADDRS = {0: [0x20b], 2: [0x169, 0x2b1, 0x4cc]} @@ -28,12 +29,6 @@ class TestNissanSafety(common.CarSafetyTest, common.AngleSteeringSafetyTest): ANGLE_RATE_UP = [5., .8, .15] # windup limit ANGLE_RATE_DOWN = [5., 3.5, .4] # unwind limit - def setUp(self): - self.packer = CANPackerSafety("nissan_x_trail_2017_generated") - self.safety = libsafety_py.libsafety - self.safety.set_safety_hooks(CarParams.SafetyModel.nissan, 0) - self.safety.init_tests() - def _angle_cmd_msg(self, angle: float, enabled: bool): values = {"DESIRED_ANGLE": angle, "LKA_ACTIVE": 1 if enabled else 0} return self.packer.make_can_msg_safety("LKAS", 0, values) @@ -84,10 +79,9 @@ class TestNissanSafety(common.CarSafetyTest, common.AngleSteeringSafetyTest): args = {} if btn is None else {btn: 1} tx = self._tx(self._acc_button_cmd(**args)) self.assertEqual(tx, should_tx) - - class TestNissanSafetyAltEpsBus(TestNissanSafety): """Altima uses different buses""" + SAFETY_PARAM = NissanSafetyFlags.ALT_EPS_BUS TX_MSGS = [[0x169, 0], [0x2b1, 0], [0x4cc, 0], [0x20b, 1]] RELAY_MALFUNCTION_ADDRS = {0: (0x169, 0x2b1, 0x4cc)} @@ -97,15 +91,10 @@ class TestNissanSafetyAltEpsBus(TestNissanSafety): CRUISE_BUS = 1 ACC_MAIN_BUS = 2 - def setUp(self): - self.packer = CANPackerSafety("nissan_x_trail_2017_generated") - self.safety = libsafety_py.libsafety - self.safety.set_safety_hooks(CarParams.SafetyModel.nissan, NissanSafetyFlags.ALT_EPS_BUS) - self.safety.init_tests() - - class TestNissanLeafSafety(TestNissanSafety): + DBC = "nissan_leaf_2018_generated" + TX_MSGS = [[0x169, 0], [0x2b1, 0], [0x4cc, 0], [0x239, 2]] RELAY_MALFUNCTION_ADDRS = {0: (0x169, 0x2b1, 0x4cc), 2: (0x239,)} FWD_BLACKLISTED_ADDRS = {0: [0x239], 2: [0x169, 0x2b1, 0x4cc]} @@ -146,7 +135,5 @@ class TestNissanLeafSafety(TestNissanSafety): args = {} if btn is None else {btn: 1} tx = self._tx(self._acc_button_cmd(**args)) self.assertEqual(tx, should_tx) - - if __name__ == "__main__": unittest.main() diff --git a/opendbc_repo/opendbc/safety/tests/test_psa.py b/opendbc_repo/opendbc/safety/tests/test_psa.py index ac4566630..5eeaa1dba 100644 --- a/opendbc_repo/opendbc/safety/tests/test_psa.py +++ b/opendbc_repo/opendbc/safety/tests/test_psa.py @@ -2,14 +2,13 @@ import unittest from opendbc.car.structs import CarParams -from opendbc.safety.tests.libsafety import libsafety_py import opendbc.safety.tests.common as common -from opendbc.safety.tests.common import CANPackerSafety LANE_KEEP_ASSIST = 0x3F2 - - class TestPsaSafetyBase(common.CarSafetyTest, common.AngleSteeringSafetyTest): + DBC = "psa_aee2010_r3" + SAFETY_MODEL = CarParams.SafetyModel.psa + RELAY_MALFUNCTION_ADDRS = {0: (LANE_KEEP_ASSIST,)} FWD_BLACKLISTED_ADDRS = {2: [LANE_KEEP_ASSIST]} TX_MSGS = [[1010, 0]] @@ -25,12 +24,6 @@ class TestPsaSafetyBase(common.CarSafetyTest, common.AngleSteeringSafetyTest): ANGLE_RATE_UP = [2.5, 1.5, .2] ANGLE_RATE_DOWN = [5., 2., .3] - def setUp(self): - self.packer = CANPackerSafety("psa_aee2010_r3") - self.safety = libsafety_py.libsafety - self.safety.set_safety_hooks(CarParams.SafetyModel.psa, 0) - self.safety.init_tests() - def _angle_cmd_msg(self, angle: float, enabled: bool): values = {"SET_ANGLE": angle, "TORQUE_FACTOR": 100 if enabled else 0} return self.packer.make_can_msg_safety("LANE_KEEP_ASSIST", self.MAIN_BUS, values) @@ -75,16 +68,7 @@ class TestPsaSafetyBase(common.CarSafetyTest, common.AngleSteeringSafetyTest): # write to unused payload byte msg[0].data[6] = 0xAB self.assertTrue(self._rx(msg)) - - class TestPsaStockSafety(TestPsaSafetyBase): - - def setUp(self): - self.packer = CANPackerSafety("psa_aee2010_r3") - self.safety = libsafety_py.libsafety - self.safety.set_safety_hooks(CarParams.SafetyModel.psa, 0) - self.safety.init_tests() - - + pass if __name__ == "__main__": unittest.main() diff --git a/opendbc_repo/opendbc/safety/tests/test_release_build.py b/opendbc_repo/opendbc/safety/tests/test_release_build.py index b1c44b136..3c027dec0 100644 --- a/opendbc_repo/opendbc/safety/tests/test_release_build.py +++ b/opendbc_repo/opendbc/safety/tests/test_release_build.py @@ -2,15 +2,11 @@ import unittest from opendbc.safety.tests.libsafety.libsafety_py import _build_libsafety - - class TestBuild(unittest.TestCase): def test_development_build(self): _build_libsafety(release=False) def test_release_build(self): _build_libsafety(release=True) - - if __name__ == "__main__": unittest.main() diff --git a/opendbc_repo/opendbc/safety/tests/test_rivian.py b/opendbc_repo/opendbc/safety/tests/test_rivian.py index 307e3237e..a4c15afe8 100755 --- a/opendbc_repo/opendbc/safety/tests/test_rivian.py +++ b/opendbc_repo/opendbc/safety/tests/test_rivian.py @@ -2,29 +2,14 @@ import unittest from opendbc.car.structs import CarParams -from opendbc.safety.tests.libsafety import libsafety_py import opendbc.safety.tests.common as common -from opendbc.safety.tests.common import CANPackerSafety from opendbc.car.rivian.values import RivianSafetyFlags -from opendbc.car.rivian.riviancan import checksum as _checksum - - -def checksum(msg): - addr, dat, bus = msg - ret = bytearray(dat) - - # ESP_Status - if addr == 0x208: - ret[0] = _checksum(ret[1:], 0x1D, 0xB1) - elif addr == 0x150: - ret[0] = _checksum(ret[1:], 0x1D, 0x9A) - - return addr, ret, bus - - class TestRivianSafetyBase(common.CarSafetyTest, common.DriverTorqueSteeringSafetyTest, common.LongitudinalAccelSafetyTest, common.VehicleSpeedSafetyTest): + DBC = "rivian_primary_actuator" + SAFETY_MODEL = CarParams.SafetyModel.rivian + TX_MSGS = [[0x120, 0], [0x321, 2], [0x162, 2]] RELAY_MALFUNCTION_ADDRS = {0: (0x120,), 2: (0x321, 0x162)} FWD_BLACKLISTED_ADDRS = {0: [0x321, 0x162], 2: [0x120]} @@ -41,9 +26,13 @@ class TestRivianSafetyBase(common.CarSafetyTest, common.DriverTorqueSteeringSafe cnt_speed = 0 cnt_speed_2 = 0 + cnt_torque = 0 + cnt_brake = 0 + cnt_pcm = 0 def _torque_driver_msg(self, torque): - values = {"EPAS_TorsionBarTorque": torque / 100.0} + values = {"EPAS_TorsionBarTorque": torque / 100.0, "EPAS_SystemStatus_Counter": self.cnt_torque % 15} + self.__class__.cnt_torque += 1 return self.packer.make_can_msg_safety("EPAS_SystemStatus", 0, values) def _torque_cmd_msg(self, torque, steer_req=1): @@ -54,24 +43,27 @@ class TestRivianSafetyBase(common.CarSafetyTest, common.DriverTorqueSteeringSafe values = {"ESP_Vehicle_Speed": speed * 3.6, "ESP_Status_Counter": self.cnt_speed % 15, "ESP_Vehicle_Speed_Q": 1 if quality_flag else 0} self.__class__.cnt_speed += 1 - return self.packer.make_can_msg_safety("ESP_Status", 0, values, fix_checksum=checksum) + return self.packer.make_can_msg_safety("ESP_Status", 0, values) def _speed_msg_2(self, speed, quality_flag=True): # Rivian has a dynamic max torque limit based on speed, so it checks two sources return self._user_gas_msg(0, speed, quality_flag) - def _user_brake_msg(self, brake): - values = {"iBESP2_BrakePedalApplied": brake} + def _user_brake_msg(self, brake, quality_flag=True): + values = {"iBESP2_BrakePedalApplied": brake, "iBESP2_BrakePedalApplied_Q": 1 if quality_flag else 2, + "iBESP2_AliveCounter": self.cnt_brake % 15} + self.__class__.cnt_brake += 1 return self.packer.make_can_msg_safety("iBESP2", 0, values) def _user_gas_msg(self, gas, speed=0, quality_flag=True): values = {"VDM_AcceleratorPedalPosition": gas, "VDM_VehicleSpeed": speed * 3.6, "VDM_PropStatus_Counter": self.cnt_speed_2 % 15, "VDM_VehicleSpeedQ": 1 if quality_flag else 0} self.__class__.cnt_speed_2 += 1 - return self.packer.make_can_msg_safety("VDM_PropStatus", 0, values, fix_checksum=checksum) + return self.packer.make_can_msg_safety("VDM_PropStatus", 0, values) def _pcm_status_msg(self, enable): - values = {"ACM_FeatureStatus": enable, "ACM_Unkown1": 1} + values = {"ACM_FeatureStatus": enable, "ACM_Unkown1": 1, "ACM_Status_Counter": self.cnt_pcm % 15} + self.__class__.cnt_pcm += 1 return self.packer.make_can_msg_safety("ACM_Status", 2, values) def _accel_msg(self, accel: float): @@ -109,17 +101,37 @@ class TestRivianSafetyBase(common.CarSafetyTest, common.DriverTorqueSteeringSafe self.assertFalse(self._rx(msg)) self.assertFalse(self.safety.get_controls_allowed()) + # The DBC defines counters for the remaining monitored RX messages too. + for make_msg in (self._torque_driver_msg, self._user_brake_msg, self._pcm_status_msg): + self._reset_safety_hooks() + self.safety.set_controls_allowed(True) + for _ in range(10): + self.assertTrue(self._rx(make_msg(0) if make_msg == self._torque_driver_msg else make_msg(False))) + msg = make_msg(0) if make_msg == self._torque_driver_msg else make_msg(False) + msg[0].data[0] ^= 0xff + self.assertFalse(self._rx(msg)) + self.assertFalse(self.safety.get_controls_allowed()) + + if make_msg == self._user_brake_msg: + self._reset_safety_hooks() + self.safety.set_controls_allowed(True) + self.assertFalse(self._rx(self._user_brake_msg(False, quality_flag=False))) + self.assertFalse(self.safety.get_controls_allowed()) + + # A single bad counter is tolerated, but repeated bad counters must disengage. + self._reset_safety_hooks() + self.safety.set_controls_allowed(True) + for _ in range(7): + msg = make_msg(0) if make_msg == self._torque_driver_msg else make_msg(False) + msg[0].data[1] &= 0xf0 + valid = self._rx(msg) + self.assertFalse(valid) + self.assertFalse(self.safety.get_controls_allowed()) class TestRivianStockSafety(TestRivianSafetyBase): LONGITUDINAL = False - def setUp(self): - self.packer = CANPackerSafety("rivian_primary_actuator") - self.safety = libsafety_py.libsafety - self.safety.set_safety_hooks(CarParams.SafetyModel.rivian, 0) - self.safety.init_tests() - def test_adas_status(self): # For canceling stock ACC for controls_allowed in (True, False): @@ -127,29 +139,19 @@ class TestRivianStockSafety(TestRivianSafetyBase): for interface_status in range(4): values = {"VDM_AdasInterfaceStatus": interface_status} self.assertTrue(self._tx(self.packer.make_can_msg_safety("VDM_AdasSts", 2, values))) - - class TestRivianLongitudinalSafety(TestRivianSafetyBase): + SAFETY_PARAM = RivianSafetyFlags.LONG_CONTROL + TX_MSGS = [[0x120, 0], [0x321, 2], [0x160, 0]] RELAY_MALFUNCTION_ADDRS = {0: (0x120, 0x160), 2: (0x321,)} FWD_BLACKLISTED_ADDRS = {0: [0x321], 2: [0x120, 0x160]} +class TestRivianIgnition(common.SafetyTestBase): + DBC = "rivian_primary_actuator" + SAFETY_MODEL = None - def setUp(self): - self.packer = CANPackerSafety("rivian_primary_actuator") - self.safety = libsafety_py.libsafety - self.safety.set_safety_hooks(CarParams.SafetyModel.rivian, RivianSafetyFlags.LONG_CONTROL) - self.safety.init_tests() - - -class TestRivianIgnition(unittest.TestCase): TX_MSGS: list = [] - def setUp(self): - self.safety = libsafety_py.libsafety - self.safety.init_tests() - self.packer = CANPackerSafety("rivian_primary_actuator") - def _msg(self, counter, mode): return self.packer.make_can_msg_safety("VDM_OutputSignals", 0, {"VDM_OutputSigs_Counter": counter, @@ -171,7 +173,5 @@ class TestRivianIgnition(unittest.TestCase): self.safety.ignition_can_hook(self._msg(2, 0)) self.safety.ignition_can_hook(self._msg(3, 0)) self.assertFalse(self.safety.get_ignition_can()) - - if __name__ == "__main__": unittest.main() diff --git a/opendbc_repo/opendbc/safety/tests/test_subaru.py b/opendbc_repo/opendbc/safety/tests/test_subaru.py index 4902efd95..28c24be84 100755 --- a/opendbc_repo/opendbc/safety/tests/test_subaru.py +++ b/opendbc_repo/opendbc/safety/tests/test_subaru.py @@ -4,12 +4,8 @@ import unittest from opendbc.car.subaru.values import SubaruSafetyFlags from opendbc.car.structs import CarParams -from opendbc.safety.tests.libsafety import libsafety_py import opendbc.safety.tests.common as common -from opendbc.safety.tests.common import CANPackerSafety from functools import partial - - class SubaruMsg(enum.IntEnum): Brake_Status = 0x13c CruiseControl = 0x240 @@ -33,8 +29,6 @@ class SubaruMsg(enum.IntEnum): SUBARU_MAIN_BUS = 0 SUBARU_ALT_BUS = 1 SUBARU_CAM_BUS = 2 - - def lkas_tx_msgs(alt_bus, lkas_msg=SubaruMsg.ES_LKAS): return [[lkas_msg, SUBARU_MAIN_BUS], [SubaruMsg.ES_Distance, alt_bus], @@ -57,10 +51,10 @@ def gen2_long_additional_tx_msgs(): def fwd_blacklisted_addr(lkas_msg=SubaruMsg.ES_LKAS): return {SUBARU_CAM_BUS: [lkas_msg, SubaruMsg.ES_DashStatus, SubaruMsg.ES_LKAS_State, SubaruMsg.ES_Infotainment]} - - class TestSubaruSafetyBase(common.CarSafetyTest): - FLAGS = 0 + DBC = "subaru_global_2017_generated" + SAFETY_MODEL = CarParams.SafetyModel.subaru + RELAY_MALFUNCTION_ADDRS = {SUBARU_MAIN_BUS: (SubaruMsg.ES_LKAS, SubaruMsg.ES_DashStatus, SubaruMsg.ES_LKAS_State, SubaruMsg.ES_Infotainment)} FWD_BLACKLISTED_ADDRS = fwd_blacklisted_addr() @@ -77,12 +71,6 @@ class TestSubaruSafetyBase(common.CarSafetyTest): INACTIVE_GAS = 1818 - def setUp(self): - self.packer = CANPackerSafety("subaru_global_2017_generated") - self.safety = libsafety_py.libsafety - self.safety.set_safety_hooks(CarParams.SafetyModel.subaru, self.FLAGS) - self.safety.init_tests() - def _set_prev_torque(self, t): self.safety.set_desired_torque_last(t) self.safety.set_rt_torque_last(t) @@ -121,8 +109,6 @@ class TestSubaruSafetyBase(common.CarSafetyTest): self._rx(self._lkas_button_msg(False, mads_button_press)) self.assertEqual(enable_mads and mads_button_press in range(1, 4), self.safety.get_controls_allowed_lateral()) - - class TestSubaruStockLongitudinalSafetyBase(TestSubaruSafetyBase): def _cancel_msg(self, cancel, cruise_throttle=0): values = {"Cruise_Cancel": cancel, "Cruise_Throttle": cruise_throttle} @@ -181,13 +167,8 @@ class TestSubaruTorqueSafetyBase(TestSubaruSafetyBase, common.DriverTorqueSteeri def _torque_cmd_msg(self, torque, steer_req=1): values = {"LKAS_Output": torque, "LKAS_Request": steer_req} return self.packer.make_can_msg_safety("ES_LKAS", SUBARU_MAIN_BUS, values) - - class TestSubaruGen1TorqueStockLongitudinalSafety(TestSubaruStockLongitudinalSafetyBase, TestSubaruTorqueSafetyBase): - FLAGS = 0 TX_MSGS = lkas_tx_msgs(SUBARU_MAIN_BUS) - - class TestSubaruGen2TorqueSafetyBase(TestSubaruTorqueSafetyBase): ALT_MAIN_BUS = SUBARU_ALT_BUS ALT_CAM_BUS = SUBARU_ALT_BUS @@ -195,10 +176,9 @@ class TestSubaruGen2TorqueSafetyBase(TestSubaruTorqueSafetyBase): MAX_RATE_UP = 35 MAX_RATE_DOWN = 50 MAX_TORQUE_LOOKUP = [0], [1500] - - class TestSubaruGen2TorqueStockLongitudinalSafety(TestSubaruStockLongitudinalSafetyBase, TestSubaruGen2TorqueSafetyBase): - FLAGS = SubaruSafetyFlags.GEN2 + SAFETY_PARAM = SubaruSafetyFlags.GEN2 + TX_MSGS = lkas_tx_msgs(SUBARU_ALT_BUS) diff --git a/opendbc_repo/opendbc/safety/tests/test_subaru_preglobal.py b/opendbc_repo/opendbc/safety/tests/test_subaru_preglobal.py index fb96de248..558543755 100755 --- a/opendbc_repo/opendbc/safety/tests/test_subaru_preglobal.py +++ b/opendbc_repo/opendbc/safety/tests/test_subaru_preglobal.py @@ -3,13 +3,10 @@ import unittest from opendbc.car.structs import CarParams from opendbc.car.subaru.values import SubaruSafetyFlags -from opendbc.safety.tests.libsafety import libsafety_py import opendbc.safety.tests.common as common -from opendbc.safety.tests.common import CANPackerSafety - - class TestSubaruPreglobalSafety(common.CarSafetyTest, common.DriverTorqueSteeringSafetyTest): - FLAGS = 0 + SAFETY_MODEL = CarParams.SafetyModel.subaruPreglobal + DBC = "subaru_outback_2015_generated" TX_MSGS = [[0x161, 0], [0x164, 0]] RELAY_MALFUNCTION_ADDRS = {0: (0x164, 0x161)} @@ -24,12 +21,6 @@ class TestSubaruPreglobalSafety(common.CarSafetyTest, common.DriverTorqueSteerin DRIVER_TORQUE_ALLOWANCE = 75 DRIVER_TORQUE_FACTOR = 10 - def setUp(self): - self.packer = CANPackerSafety(self.DBC) - self.safety = libsafety_py.libsafety - self.safety.set_safety_hooks(CarParams.SafetyModel.subaruPreglobal, self.FLAGS) - self.safety.init_tests() - def _set_prev_torque(self, t): self.safety.set_desired_torque_last(t) self.safety.set_rt_torque_last(t) @@ -58,12 +49,9 @@ class TestSubaruPreglobalSafety(common.CarSafetyTest, common.DriverTorqueSteerin def _pcm_status_msg(self, enable): values = {"Cruise_Activated": enable} return self.packer.make_can_msg_safety("CruiseControl", 0, values) - - class TestSubaruPreglobalReversedDriverTorqueSafety(TestSubaruPreglobalSafety): - FLAGS = SubaruSafetyFlags.PREGLOBAL_REVERSED_DRIVER_TORQUE + SAFETY_PARAM = SubaruSafetyFlags.PREGLOBAL_REVERSED_DRIVER_TORQUE + DBC = "subaru_outback_2019_generated" - - if __name__ == "__main__": unittest.main() diff --git a/opendbc_repo/opendbc/safety/tests/test_tesla.py b/opendbc_repo/opendbc/safety/tests/test_tesla.py index b8879c2f1..c18c4ca28 100755 --- a/opendbc_repo/opendbc/safety/tests/test_tesla.py +++ b/opendbc_repo/opendbc/safety/tests/test_tesla.py @@ -10,8 +10,8 @@ from opendbc.car.tesla.carcontroller import get_safety_CP from opendbc.car.structs import CarParams from opendbc.car.vehicle_model import VehicleModel from opendbc.can import CANDefine -from opendbc.safety.tests.libsafety import libsafety_py import opendbc.safety.tests.common as common +from opendbc.safety.tests.libsafety import libsafety_py from opendbc.safety.tests.common import CANPackerSafety, MAX_SPEED_DELTA, MAX_WRONG_COUNTERS, away_round, round_speed from opendbc.sunnypilot.car.tesla.values import TeslaSafetyFlagsSP @@ -19,17 +19,15 @@ from opendbc.sunnypilot.car.tesla.values import TeslaSafetyFlagsSP MSG_DAS_steeringControl = 0x488 MSG_APS_eacMonitor = 0x27d MSG_DAS_Control = 0x2b9 - - def round_angle(apply_angle, can_offset=0): apply_angle_can = (apply_angle + 1638.35) / 0.1 + can_offset # 0.49999_ == 0.5 rnd_offset = 1e-5 if apply_angle >= 0 else -1e-5 return away_round(apply_angle_can + rnd_offset) * 0.1 - 1638.35 - - class TestTeslaSafetyBase(common.CarSafetyTest, common.AngleSteeringSafetyTest, common.LongitudinalAccelSafetyTest): - SAFETY_PARAM = 0 + + DBC = "tesla_model3_party" + SAFETY_MODEL = CarParams.SafetyModel.tesla RELAY_MALFUNCTION_ADDRS = {0: (MSG_DAS_steeringControl, MSG_APS_eacMonitor)} FWD_BLACKLISTED_ADDRS = {2: [MSG_DAS_steeringControl, MSG_APS_eacMonitor]} @@ -56,34 +54,27 @@ class TestTeslaSafetyBase(common.CarSafetyTest, common.AngleSteeringSafetyTest, MIN_ACCEL = -3.48 INACTIVE_ACCEL = 0.0 - cnt_epas = 0 cnt_angle_cmd = 0 - packer: CANPackerSafety - def _get_steer_cmd_angle_max(self, speed): return get_max_angle_vm(max(speed, 1), self.VM, CarControllerParams) def setUp(self): + super().setUp() self.VM = VehicleModel(get_safety_CP()) - self.packer = CANPackerSafety("tesla_model3_party") - self.define = CANDefine("tesla_model3_party") + self.define = CANDefine(self.DBC) self.acc_states = {d: v for v, d in self.define.dv["DAS_control"]["DAS_accState"].items()} self.autopark_states = {d: v for v, d in self.define.dv["DI_state"]["DI_autoparkState"].items()} self.active_autopark_states = [self.autopark_states[s] for s in ('ACTIVE', 'COMPLETE', 'SELFPARK_STARTED')] self.steer_control_types = {d: v for v, d in self.define.dv["DAS_steeringControl"]["DAS_steeringControlType"].items()} - self.safety = libsafety_py.libsafety - self.safety.set_safety_hooks(CarParams.SafetyModel.tesla, self.SAFETY_PARAM) - self.safety.init_tests() - def _angle_cmd_msg(self, angle: float, state: bool | int, increment_timer: bool = True, bus: int = 0): # If FSD 14, translate steer control type to new flipped definition if self.safety.get_current_safety_param() & TeslaSafetyFlags.FSD_14: state = get_steer_ctrl_type(TeslaFlags.FSD_14, int(state)) - values = {"DAS_steeringAngleRequest": angle, "DAS_steeringControlType": state} + values = {"DAS_steeringAngleRequest": angle, "DAS_steeringControlType": int(state)} if increment_timer: self.safety.set_timer(self.cnt_angle_cmd * int(1e6 / self.LATERAL_FREQUENCY)) self.__class__.cnt_angle_cmd += 1 @@ -91,9 +82,7 @@ class TestTeslaSafetyBase(common.CarSafetyTest, common.AngleSteeringSafetyTest, def _angle_meas_msg(self, angle: float, hands_on_level: int = 0, eac_status: int = 1, eac_error_code: int = 0): values = {"EPAS3S_internalSAS": angle, "EPAS3S_handsOnLevel": hands_on_level, - "EPAS3S_eacStatus": eac_status, "EPAS3S_eacErrorCode": eac_error_code, - "EPAS3S_sysStatusCounter": self.cnt_epas % 16} - self.__class__.cnt_epas += 1 + "EPAS3S_eacStatus": eac_status, "EPAS3S_eacErrorCode": eac_error_code} return self.packer.make_can_msg_safety("EPAS3S_sysStatus", 0, values) def _user_brake_msg(self, brake, quality_flag: bool = True): @@ -272,9 +261,9 @@ class TestTeslaSafetyBase(common.CarSafetyTest, common.AngleSteeringSafetyTest, self.assertEqual(self.LONGITUDINAL, self._tx(self._long_control_msg(0, acc_state=self.acc_states["ACC_ON"]))) def test_steering_control_type(self): - # Only angle control is allowed (no LANE_KEEP_ASSIST or EMERGENCY_LANE_KEEP) + # Only angle control is allowed (no LANE_KEEP_ASSIST, EMERGENCY_LANE_KEEP, or FSD) self.safety.set_controls_allowed(True) - for steer_control_type in range(4): + for steer_control_type in range(8): should_tx = steer_control_type in (self.steer_control_types["NONE"], self.steer_control_types["ANGLE_CONTROL"], self.steer_control_types["LANE_KEEP_ASSIST"]) @@ -366,8 +355,6 @@ class TestTeslaSafetyBase(common.CarSafetyTest, common.AngleSteeringSafetyTest, # Recover self.assertTrue(self._tx(self._angle_cmd_msg(0, True))) - - class TestTeslaStockSafety(TestTeslaSafetyBase): LONGITUDINAL = False @@ -459,13 +446,11 @@ class TestTeslaFSD14LongitudinalSafety(TestTeslaLongitudinalSafety): SAFETY_PARAM = TeslaSafetyFlags.LONG_CONTROL | TeslaSafetyFlags.FSD_14 -class TestTeslaIgnition(unittest.TestCase): - TX_MSGS: list = [] +class TestTeslaIgnition(common.SafetyTestBase): + DBC = "tesla_model3_party" + SAFETY_MODEL = None - def setUp(self): - self.safety = libsafety_py.libsafety - self.safety.init_tests() - self.packer = CANPackerSafety("tesla_model3_party") + TX_MSGS: list = [] def _msg(self, counter, state): return self.packer.make_can_msg_safety("VCFRONT_LVPowerState", 0, @@ -488,8 +473,6 @@ class TestTeslaIgnition(unittest.TestCase): self.safety.ignition_can_hook(self._msg(2, 2)) self.safety.ignition_can_hook(self._msg(3, 2)) self.assertFalse(self.safety.get_ignition_can()) - - class TestTeslaVehicleBusSafety(TestTeslaSafetyBase): LONGITUDINAL = False @@ -540,6 +523,25 @@ class TestTeslaVehicleBusSafety(TestTeslaSafetyBase): self._rx(self._touch_points_msg(actual)) self.assertEqual(-1, self.safety.get_mads_button_press()) # UNAVAILABLE + def test_vehicle_bus_rx_checks_valid(self): + """The 2 Hz 0x3DF VEHICLE bus check must not flag the RX checks invalid.""" + # keep every message on the same fake clock, the shared safety lib carries time across tests + self.safety.set_timer(0) + # feed every message of the VEHICLE bus config so each RX check has been seen + self._rx(self._speed_msg(0)) + self._rx(self._speed_msg_2(0)) + self._rx(self._user_gas_msg(0)) + self._rx(self._user_brake_msg(False)) + self._rx(self._pcm_status_msg(False)) + self._rx(self._angle_meas_msg(0)) + self._rx(self.packer.make_can_msg_safety("UI_warning", 0, {})) + self._rx(self._long_control_msg(0, bus=2)) + self._rx(self._angle_cmd_msg(0, 0, increment_timer=False, bus=2)) + self._rx(self._touch_points_msg(0)) + + self.safety.safety_tick() + self.assertFalse(self.safety.get_safety_rx_checks_invalid()) + if __name__ == "__main__": unittest.main() diff --git a/opendbc_repo/opendbc/safety/tests/test_toyota.py b/opendbc_repo/opendbc/safety/tests/test_toyota.py index c849d602f..04a5dcb99 100755 --- a/opendbc_repo/opendbc/safety/tests/test_toyota.py +++ b/opendbc_repo/opendbc/safety/tests/test_toyota.py @@ -25,10 +25,11 @@ UNSUPPORTED_DSU = [ {"SAFETY_PARAM_SP": ToyotaSafetyFlagsSP.DEFAULT}, {"SAFETY_PARAM_SP": ToyotaSafetyFlagsSP.UNSUPPORTED_DSU}, ] - - class TestToyotaSafetyBase(common.CarSafetyTest, common.LongitudinalAccelSafetyTest): + DBC = "toyota_nodsu_pt_generated" + SAFETY_MODEL = CarParams.SafetyModel.toyota + TX_MSGS = TOYOTA_COMMON_TX_MSGS + TOYOTA_COMMON_LONG_TX_MSGS RELAY_MALFUNCTION_ADDRS = {0: (0x2E4, 0x191, 0x412, 0x343)} FWD_BLACKLISTED_ADDRS = {2: [0x2E4, 0x412, 0x191, 0x343]} @@ -151,8 +152,6 @@ class TestToyotaSafetyBase(common.CarSafetyTest, common.LongitudinalAccelSafetyT # OVERRIDDEN: 72.22_ is the max speed in m/s self._common_measurement_test(self._speed_msg, 0, 259 / 3.6, 1, self.safety.get_vehicle_speed_min, self.safety.get_vehicle_speed_max) - - class TestToyotaSafetyGasInterceptorBase(GasInterceptorSafetyTest, TestToyotaSafetyBase): TX_MSGS = TOYOTA_COMMON_TX_MSGS + TOYOTA_COMMON_LONG_TX_MSGS + GAS_INTERCEPTOR_TX_MSGS @@ -179,8 +178,6 @@ class TestToyotaSafetyGasInterceptorBase(GasInterceptorSafetyTest, TestToyotaSaf with self.subTest(test=test.__name__): with self.assertRaises(AssertionError): test() - - @parameterized_class(UNSUPPORTED_DSU) class TestToyotaSafetyTorque(TestToyotaSafetyBase, common.MotorTorqueSteeringSafetyTest, common.SteerRequestCutSafetyTest): @@ -195,6 +192,10 @@ class TestToyotaSafetyTorque(TestToyotaSafetyBase, common.MotorTorqueSteeringSaf MIN_VALID_STEERING_FRAMES = 17 MAX_INVALID_STEERING_FRAMES = 1 + @property + def SAFETY_PARAM(self): + return self.EPS_SCALE + @classmethod def setUpClass(cls): if cls.__name__ == "TestToyotaSafetyTorque": @@ -202,13 +203,8 @@ class TestToyotaSafetyTorque(TestToyotaSafetyBase, common.MotorTorqueSteeringSaf raise unittest.SkipTest def setUp(self): - self.packer = CANPackerSafety("toyota_nodsu_pt_generated") - self.safety = libsafety_py.libsafety + super().setUp() self.safety.set_current_safety_param_sp(self.SAFETY_PARAM_SP) - self.safety.set_safety_hooks(CarParams.SafetyModel.toyota, self.EPS_SCALE) - self.safety.init_tests() - - @parameterized_class(UNSUPPORTED_DSU) class TestToyotaSafetyTorqueGasInterceptor(TestToyotaSafetyGasInterceptorBase, TestToyotaSafetyTorque): @@ -217,8 +213,6 @@ class TestToyotaSafetyTorqueGasInterceptor(TestToyotaSafetyGasInterceptorBase, T if cls.__name__ == "TestToyotaSafetyTorqueGasInterceptor": cls.safety = None raise unittest.SkipTest - - class TestToyotaSafetyAngle(TestToyotaSafetyBase, common.AngleSteeringSafetyTest): # Angle control limits @@ -233,11 +227,9 @@ class TestToyotaSafetyAngle(TestToyotaSafetyBase, common.AngleSteeringSafetyTest MAX_MEAS_TORQUE = 1500 # max allowed measured EPS torque before wind down MAX_LTA_DRIVER_TORQUE = 150 # max allowed driver torque before wind down - def setUp(self): - self.packer = CANPackerSafety("toyota_nodsu_pt_generated") - self.safety = libsafety_py.libsafety - self.safety.set_safety_hooks(CarParams.SafetyModel.toyota, self.EPS_SCALE | ToyotaSafetyFlags.LTA) - self.safety.init_tests() + @property + def SAFETY_PARAM(self): + return self.EPS_SCALE | ToyotaSafetyFlags.LTA # Only allow LKA msgs with no actuation def test_lka_steer_cmd(self): @@ -328,15 +320,17 @@ class TestToyotaSafetyAngle(TestToyotaSafetyBase, common.AngleSteeringSafetyTest self._rx(self._angle_meas_msg(0)) self.assertEqual(self.safety.get_angle_meas_min(), 0) self.assertEqual(self.safety.get_angle_meas_max(), 0) - - class TestToyotaSafetyAngleGasInterceptor(TestToyotaSafetyGasInterceptorBase, TestToyotaSafetyAngle): pass - - @parameterized_class(UNSUPPORTED_DSU) class TestToyotaAltBrakeSafety(TestToyotaSafetyTorque): + DBC = "toyota_new_mc_pt_generated" + + @property + def SAFETY_PARAM(self): + return self.EPS_SCALE | ToyotaSafetyFlags.ALT_BRAKE + @classmethod def setUpClass(cls): if cls.__name__ == "TestToyotaAltBrakeSafety": @@ -344,11 +338,8 @@ class TestToyotaAltBrakeSafety(TestToyotaSafetyTorque): raise unittest.SkipTest def setUp(self): - self.packer = CANPackerSafety("toyota_new_mc_pt_generated") - self.safety = libsafety_py.libsafety + super().setUp() self.safety.set_current_safety_param_sp(self.SAFETY_PARAM_SP) - self.safety.set_safety_hooks(CarParams.SafetyModel.toyota, self.EPS_SCALE | ToyotaSafetyFlags.ALT_BRAKE) - self.safety.init_tests() def _user_brake_msg(self, brake): values = {"BRAKE_PRESSED": brake} @@ -357,8 +348,6 @@ class TestToyotaAltBrakeSafety(TestToyotaSafetyTorque): # No LTA message in the DBC def test_lta_steer_cmd(self): pass - - @parameterized_class(UNSUPPORTED_DSU) class TestToyotaAltBrakeSafetyGasInterceptor(TestToyotaSafetyGasInterceptorBase, TestToyotaAltBrakeSafety): @@ -371,8 +360,6 @@ class TestToyotaAltBrakeSafetyGasInterceptor(TestToyotaSafetyGasInterceptorBase, # No LTA message in the DBC def test_lta_steer_cmd(self): pass - - class TestToyotaStockLongitudinalBase(TestToyotaSafetyBase): TX_MSGS = TOYOTA_COMMON_TX_MSGS @@ -398,11 +385,13 @@ class TestToyotaStockLongitudinalBase(TestToyotaSafetyBase): self.assertFalse(self._tx(self._accel_msg_343(accel))) should_tx = np.isclose(accel, self.INACTIVE_ACCEL, atol=0.0001) self.assertEqual(should_tx, self._tx(self._accel_msg_343(accel, cancel_req=1))) - - @parameterized_class(UNSUPPORTED_DSU) class TestToyotaStockLongitudinalTorque(TestToyotaStockLongitudinalBase, TestToyotaSafetyTorque): + @property + def SAFETY_PARAM(self): + return self.EPS_SCALE | ToyotaSafetyFlags.STOCK_LONGITUDINAL + @classmethod def setUpClass(cls): if cls.__name__ == "TestToyotaStockLongitudinalTorque": @@ -410,35 +399,24 @@ class TestToyotaStockLongitudinalTorque(TestToyotaStockLongitudinalBase, TestToy raise unittest.SkipTest def setUp(self): - self.packer = CANPackerSafety("toyota_nodsu_pt_generated") - self.safety = libsafety_py.libsafety + super().setUp() self.safety.set_current_safety_param_sp(self.SAFETY_PARAM_SP) - self.safety.set_safety_hooks(CarParams.SafetyModel.toyota, self.EPS_SCALE | ToyotaSafetyFlags.STOCK_LONGITUDINAL) - self.safety.init_tests() - - class TestToyotaStockLongitudinalAngle(TestToyotaStockLongitudinalBase, TestToyotaSafetyAngle): - def setUp(self): - self.packer = CANPackerSafety("toyota_nodsu_pt_generated") - self.safety = libsafety_py.libsafety - self.safety.set_safety_hooks(CarParams.SafetyModel.toyota, - self.EPS_SCALE | ToyotaSafetyFlags.STOCK_LONGITUDINAL | ToyotaSafetyFlags.LTA) - self.safety.init_tests() - - + @property + def SAFETY_PARAM(self): + return self.EPS_SCALE | ToyotaSafetyFlags.STOCK_LONGITUDINAL | ToyotaSafetyFlags.LTA class TestToyotaSecOcSafetyBase(TestToyotaSafetyBase): + DBC = "toyota_secoc_pt_generated" + TX_MSGS = TOYOTA_SECOC_TX_MSGS RELAY_MALFUNCTION_ADDRS = {0: (0x2E4, 0x191, 0x412, 0x131)} FWD_BLACKLISTED_ADDRS = {2: [0x2E4, 0x191, 0x412, 0x131]} - def setUp(self): - self.packer = CANPackerSafety("toyota_secoc_pt_generated") - self.safety = libsafety_py.libsafety - self.safety.set_safety_hooks(CarParams.SafetyModel.toyota, - self.EPS_SCALE | ToyotaSafetyFlags.SECOC) - self.safety.init_tests() + @property + def SAFETY_PARAM(self): + return self.EPS_SCALE | ToyotaSafetyFlags.SECOC def test_diagnostics(self, ecu_disabled: bool = False): super().test_diagnostics(ecu_disabled=ecu_disabled) @@ -469,29 +447,16 @@ class TestToyotaSecOcSafetyBase(TestToyotaSafetyBase): def _accel_msg(self, accel, cancel_req=0): return self._accel_msg_183(accel) - - class TestToyotaSecOcSafetyStockLongitudinal(TestToyotaSecOcSafetyBase, TestToyotaStockLongitudinalBase): - def setUp(self): - self.packer = CANPackerSafety("toyota_secoc_pt_generated") - self.safety = libsafety_py.libsafety - self.safety.set_safety_hooks(CarParams.SafetyModel.toyota, - self.EPS_SCALE | ToyotaSafetyFlags.STOCK_LONGITUDINAL | ToyotaSafetyFlags.SECOC) - self.safety.init_tests() - - + @property + def SAFETY_PARAM(self): + return self.EPS_SCALE | ToyotaSafetyFlags.STOCK_LONGITUDINAL | ToyotaSafetyFlags.SECOC class TestToyotaSecOcSafety(TestToyotaSecOcSafetyBase): RELAY_MALFUNCTION_ADDRS = {0: (0x2E4, 0x191, 0x412, 0x131, 0x343, 0x183)} FWD_BLACKLISTED_ADDRS = {2: [0x2E4, 0x191, 0x412, 0x131, 0x343, 0x183]} - def setUp(self): - self.packer = CANPackerSafety("toyota_secoc_pt_generated") - self.safety = libsafety_py.libsafety - self.safety.set_safety_hooks(CarParams.SafetyModel.toyota, self.EPS_SCALE | ToyotaSafetyFlags.SECOC) - self.safety.init_tests() - @unittest.skip("test not applicable for cars without a DSU") def test_block_aeb(self, stock_longitudinal: bool = False): pass @@ -507,7 +472,5 @@ class TestToyotaSecOcSafety(TestToyotaSecOcSafetyBase): should_tx = np.isclose(accel, self.INACTIVE_ACCEL, atol=0.0001) self.assertEqual(should_tx, self._tx(self._accel_msg_343(accel))) self.assertEqual(should_tx, self._tx(self._accel_msg_343(accel, cancel_req=1))) - - if __name__ == "__main__": unittest.main() diff --git a/opendbc_repo/opendbc/safety/tests/test_volkswagen_meb.py b/opendbc_repo/opendbc/safety/tests/test_volkswagen_meb.py index e8475ac7f..3a706074b 100644 --- a/opendbc_repo/opendbc/safety/tests/test_volkswagen_meb.py +++ b/opendbc_repo/opendbc/safety/tests/test_volkswagen_meb.py @@ -4,9 +4,7 @@ import unittest from opendbc.car.structs import CarParams from opendbc.car.volkswagen.values import VolkswagenSafetyFlags -from opendbc.safety.tests.libsafety import libsafety_py import opendbc.safety.tests.common as common -from opendbc.safety.tests.common import CANPackerSafety MAX_ACCEL = 2.0 MIN_ACCEL = -3.5 @@ -28,8 +26,6 @@ MSG_TA_01 = 0x26B MSG_ACC_19 = 0x300 MSG_HCA_03 = 0x303 MSG_LDW_02 = 0x397 - - class TestVolkswagenMebSafetyBase(common.CarSafetyTest, common.CurvatureSteeringSafetyTest): STANDSTILL_THRESHOLD = 0 @@ -193,19 +189,19 @@ class TestVolkswagenMebSafetyBase(common.CarSafetyTest, common.CurvatureSteering for name in ("LH_EPS_03", "Motor_14", "GRA_ACC_01", "QFK_01", "ESP_21", "Motor_51", "ESC_51"): with self.subTest(msg=name): # an expected counter sequence is always accepted, and clears the wrong counter count - next_counter = common.MAX_WRONG_COUNTERS + 1 - for counter in range(next_counter): - self.assertTrue(self._rx(self.packer.make_can_msg_safety(name, 0, {"COUNTER": counter}))) + for _ in range(common.MAX_WRONG_COUNTERS + 1): + self.assertTrue(self._rx(self.packer.make_can_msg_safety(name, 0, {}))) # mess with the checksum to make it fail, it's the first byte of every MEB message - msg = self.packer.make_can_msg_safety(name, 0, {"COUNTER": next_counter}) + msg = self.packer.make_can_msg_safety(name, 0, {}) msg[0].data[0] ^= 0xFF self.assertFalse(self._rx(msg)) # a stuck counter fails as well, its checksum is still correct + msg[0].data[0] ^= 0xFF for i in range(common.MAX_WRONG_COUNTERS): should_rx = i < common.MAX_WRONG_COUNTERS - 1 - self.assertEqual(should_rx, self._rx(self.packer.make_can_msg_safety(name, 0, {"COUNTER": next_counter}))) + self.assertEqual(should_rx, self._rx(msg)) def test_main_switch_off_disables_controls(self): self.safety.set_controls_allowed(True) @@ -258,9 +254,10 @@ class TestVolkswagenMebSafetyBase(common.CarSafetyTest, common.CurvatureSteering # controls_allowed is checked if actuation bit is 1, else the curvature must be zero (inactive) should_tx = controls_allowed if steer_req else round(curvature_cmd * self.CURVATURE_TO_CAN) == 0 self.assertEqual(should_tx, self._tx(self._curvature_cmd_msg(curvature_cmd, steer_req=steer_req, power=50 if steer_req else 0))) - - class TestVolkswagenMebSafety(TestVolkswagenMebSafetyBase): + DBC = "vw_meb_generated" + SAFETY_MODEL = CarParams.SafetyModel.volkswagenMeb + TX_MSGS = [[MSG_HCA_03, 0], [MSG_LDW_02, 0], [MSG_ACC_19, 0], [MSG_ACC_18, 0], [MSG_TA_01, 0], [MSG_KLR_01, 0], [MSG_KLR_01, 2]] FWD_BLACKLISTED_ADDRS = {0: [MSG_KLR_01], @@ -271,12 +268,6 @@ class TestVolkswagenMebSafety(TestVolkswagenMebSafetyBase): ACCEL_OVERRIDE = 0 INACTIVE_ACCEL = 3.01 - def setUp(self): - self.packer = CANPackerSafety("vw_meb_generated") - self.safety = libsafety_py.libsafety - self.safety.set_safety_hooks(CarParams.SafetyModel.volkswagenMeb, 0) - self.safety.init_tests() - # stock cruise controls are entirely bypassed under openpilot longitudinal control def test_disable_control_allowed_from_cruise(self): pass @@ -357,24 +348,16 @@ class TestVolkswagenMebSafety(TestVolkswagenMebSafetyBase): self.safety.set_controls_allowed(controls_allowed) send = controls_allowed or acc_status not in (ACC_AKTIV_REGELT, ACC_OVERRIDE) self.assertEqual(send, self._tx(self._accel_msg(self.INACTIVE_ACCEL, acc_status=acc_status))) - - class TestVolkswagenMebGen2Safety(TestVolkswagenMebSafety): - def setUp(self): - self.packer = CANPackerSafety("vw_meb_2024_generated") - self.safety = libsafety_py.libsafety - self.safety.set_safety_hooks(CarParams.SafetyModel.volkswagenMeb, VolkswagenSafetyFlags.MEB_ALT_CRC) - self.safety.init_tests() - + DBC = "vw_meb_2024_generated" + SAFETY_PARAM = VolkswagenSafetyFlags.MEB_ALT_CRC # ZAS_Kl_15=1 -class TestVolkswagenMebIgnition(unittest.TestCase): - TX_MSGS: list = [] +class TestVolkswagenMebIgnition(common.SafetyTestBase): + DBC = "vw_meb_generated" + SAFETY_MODEL = None - def setUp(self): - self.safety = libsafety_py.libsafety - self.safety.init_tests() - self.packer = CANPackerSafety("vw_meb_generated") + TX_MSGS: list = [] def _msg(self, counter, ign): return self.packer.make_can_msg_safety("Klemmen_Status_01", 0, @@ -396,7 +379,5 @@ class TestVolkswagenMebIgnition(unittest.TestCase): self.safety.ignition_can_hook(self._msg(2, 0)) self.safety.ignition_can_hook(self._msg(3, 0)) self.assertFalse(self.safety.get_ignition_can()) - - if __name__ == "__main__": unittest.main() diff --git a/opendbc_repo/opendbc/safety/tests/test_volkswagen_mlb.py b/opendbc_repo/opendbc/safety/tests/test_volkswagen_mlb.py index 57bb93a77..f33239d99 100755 --- a/opendbc_repo/opendbc/safety/tests/test_volkswagen_mlb.py +++ b/opendbc_repo/opendbc/safety/tests/test_volkswagen_mlb.py @@ -1,15 +1,11 @@ #!/usr/bin/env python3 import unittest from opendbc.car.structs import CarParams -from opendbc.safety.tests.libsafety import libsafety_py import opendbc.safety.tests.common as common -from opendbc.safety.tests.common import CANPackerSafety MSG_LS_01 = 0x10B # TX by OP, ACC control buttons for cancel/resume MSG_HCA_01 = 0x126 # TX by OP, Heading Control Assist steering torque MSG_LDW_02 = 0x397 # TX by OP, Lane line recognition and text alerts - - class TestVolkswagenMlbSafetyBase(common.CarSafetyTest, common.DriverTorqueSteeringSafetyTest): RELAY_MALFUNCTION_ADDRS = {0: (MSG_HCA_01, MSG_LDW_02)} @@ -82,39 +78,14 @@ class TestVolkswagenMlbSafetyBase(common.CarSafetyTest, common.DriverTorqueSteer 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_03_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)) - self._rx(self._torque_driver_msg(-50)) - self._rx(self._torque_driver_msg(0)) - self._rx(self._torque_driver_msg(0)) - self._rx(self._torque_driver_msg(0)) - self._rx(self._torque_driver_msg(0)) - - self.assertEqual(-50, self.safety.get_torque_driver_min()) - self.assertEqual(50, self.safety.get_torque_driver_max()) - - self._rx(self._torque_driver_msg(0)) - self.assertEqual(0, self.safety.get_torque_driver_max()) - self.assertEqual(-50, self.safety.get_torque_driver_min()) - - self._rx(self._torque_driver_msg(0)) - self.assertEqual(0, self.safety.get_torque_driver_max()) - self.assertEqual(0, self.safety.get_torque_driver_min()) - - class TestVolkswagenMlbStockSafety(TestVolkswagenMlbSafetyBase): + DBC = "vw_mlb" + SAFETY_MODEL = CarParams.SafetyModel.volkswagenMlb + TX_MSGS = [[MSG_HCA_01, 0], [MSG_LDW_02, 0], [MSG_LS_01, 0], [MSG_LS_01, 2]] FWD_BLACKLISTED_ADDRS = {2: [MSG_HCA_01, MSG_LDW_02]} FWD_BUS_LOOKUP = {0: 2, 2: 0} - def setUp(self): - self.packer = CANPackerSafety("vw_mlb") - self.safety = libsafety_py.libsafety - self.safety.set_safety_hooks(CarParams.SafetyModel.volkswagenMlb, 0) - self.safety.init_tests() - def test_spam_cancel_safety_check(self): self.safety.set_controls_allowed(0) self.assertTrue(self._tx(self._ls_01_msg(cancel=1))) @@ -130,7 +101,5 @@ class TestVolkswagenMlbStockSafety(TestVolkswagenMlbSafetyBase): self.safety.set_controls_allowed(1) self._rx(self._ls_01_msg(cancel=True, bus=0)) self.assertFalse(self.safety.get_controls_allowed(), "controls allowed after cancel") - - if __name__ == "__main__": unittest.main() diff --git a/opendbc_repo/opendbc/safety/tests/test_volkswagen_mqb.py b/opendbc_repo/opendbc/safety/tests/test_volkswagen_mqb.py index 9ef7e261f..72249f879 100755 --- a/opendbc_repo/opendbc/safety/tests/test_volkswagen_mqb.py +++ b/opendbc_repo/opendbc/safety/tests/test_volkswagen_mqb.py @@ -2,9 +2,7 @@ import unittest import numpy as np from opendbc.car.structs import CarParams -from opendbc.safety.tests.libsafety import libsafety_py import opendbc.safety.tests.common as common -from opendbc.safety.tests.common import CANPackerSafety from opendbc.car.volkswagen.values import VolkswagenSafetyFlags MAX_ACCEL = 2.0 @@ -17,9 +15,8 @@ MSG_GRA_ACC_01 = 0x12B # TX by OP, ACC control buttons for cancel/resume MSG_ACC_07 = 0x12E # TX by OP, ACC control instructions to the drivetrain coordinator MSG_ACC_02 = 0x30C # TX by OP, ACC HUD data to the instrument cluster MSG_LDW_02 = 0x397 # TX by OP, Lane line recognition and text alerts - - class TestVolkswagenMqbSafetyBase(common.CarSafetyTest, common.DriverTorqueSteeringSafetyTest): + DBC = "vw_mqb" RELAY_MALFUNCTION_ADDRS = {0: (MSG_HCA_01, MSG_LDW_02), 2: (MSG_LH_EPS_03,)} MAX_RATE_UP = 4 @@ -101,38 +98,12 @@ class TestVolkswagenMqbSafetyBase(common.CarSafetyTest, common.DriverTorqueSteer 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)) - self._rx(self._torque_driver_msg(-50)) - self._rx(self._torque_driver_msg(0)) - self._rx(self._torque_driver_msg(0)) - self._rx(self._torque_driver_msg(0)) - self._rx(self._torque_driver_msg(0)) - - self.assertEqual(-50, self.safety.get_torque_driver_min()) - self.assertEqual(50, self.safety.get_torque_driver_max()) - - self._rx(self._torque_driver_msg(0)) - self.assertEqual(0, self.safety.get_torque_driver_max()) - self.assertEqual(-50, self.safety.get_torque_driver_min()) - - self._rx(self._torque_driver_msg(0)) - self.assertEqual(0, self.safety.get_torque_driver_max()) - self.assertEqual(0, self.safety.get_torque_driver_min()) - - class TestVolkswagenMqbStockSafety(TestVolkswagenMqbSafetyBase): + SAFETY_MODEL = CarParams.SafetyModel.volkswagen + TX_MSGS = [[MSG_HCA_01, 0], [MSG_LDW_02, 0], [MSG_LH_EPS_03, 2], [MSG_GRA_ACC_01, 0], [MSG_GRA_ACC_01, 2]] FWD_BLACKLISTED_ADDRS = {0: [MSG_LH_EPS_03], 2: [MSG_HCA_01, MSG_LDW_02]} - def setUp(self): - self.packer = CANPackerSafety("vw_mqb") - self.safety = libsafety_py.libsafety - self.safety.set_safety_hooks(CarParams.SafetyModel.volkswagen, 0) - self.safety.init_tests() - def test_spam_cancel_safety_check(self): self.safety.set_controls_allowed(0) self.assertTrue(self._tx(self._gra_acc_01_msg(cancel=1))) @@ -141,20 +112,15 @@ class TestVolkswagenMqbStockSafety(TestVolkswagenMqbSafetyBase): # do not block resume if we are engaged already self.safety.set_controls_allowed(1) self.assertTrue(self._tx(self._gra_acc_01_msg(resume=1))) - - class TestVolkswagenMqbLongSafety(TestVolkswagenMqbSafetyBase): + SAFETY_MODEL = CarParams.SafetyModel.volkswagen + SAFETY_PARAM = VolkswagenSafetyFlags.LONG_CONTROL + TX_MSGS = [[MSG_HCA_01, 0], [MSG_LDW_02, 0], [MSG_LH_EPS_03, 2], [MSG_ACC_02, 0], [MSG_ACC_06, 0], [MSG_ACC_07, 0]] FWD_BLACKLISTED_ADDRS = {0: [MSG_LH_EPS_03], 2: [MSG_HCA_01, MSG_LDW_02, MSG_ACC_02, MSG_ACC_06, MSG_ACC_07]} RELAY_MALFUNCTION_ADDRS = {0: (MSG_HCA_01, MSG_LDW_02, MSG_ACC_02, MSG_ACC_06, MSG_ACC_07), 2: (MSG_LH_EPS_03,)} INACTIVE_ACCEL = 3.01 - def setUp(self): - self.packer = CANPackerSafety("vw_mqb") - self.safety = libsafety_py.libsafety - self.safety.set_safety_hooks(CarParams.SafetyModel.volkswagen, VolkswagenSafetyFlags.LONG_CONTROL) - self.safety.init_tests() - # stock cruise controls are entirely bypassed under openpilot longitudinal control def test_disable_control_allowed_from_cruise(self): pass @@ -206,7 +172,5 @@ class TestVolkswagenMqbLongSafety(TestVolkswagenMqbSafetyBase): self.assertEqual(send, self._tx(self._acc_07_msg(accel)), (controls_allowed, accel)) # ensure the optional secondary accel field remains inactive for now self.assertEqual(is_inactive_accel, self._tx(self._acc_07_msg(accel, secondary_accel=accel)), (controls_allowed, accel)) - - if __name__ == "__main__": unittest.main() diff --git a/opendbc_repo/opendbc/safety/tests/test_volkswagen_pq.py b/opendbc_repo/opendbc/safety/tests/test_volkswagen_pq.py index b6b134b77..2dc16d4f1 100755 --- a/opendbc_repo/opendbc/safety/tests/test_volkswagen_pq.py +++ b/opendbc_repo/opendbc/safety/tests/test_volkswagen_pq.py @@ -3,18 +3,15 @@ import unittest from opendbc.car.volkswagen.values import VolkswagenSafetyFlags from opendbc.car.structs import CarParams -from opendbc.safety.tests.libsafety import libsafety_py import opendbc.safety.tests.common as common -from opendbc.safety.tests.common import CANPackerSafety MSG_HCA_1 = 0x0D2 # TX by OP, Heading Control Assist steering torque MSG_ACC_SYSTEM = 0x368 # TX by OP, longitudinal acceleration controls MSG_GRA_NEU = 0x38A # TX by OP, ACC control buttons for cancel/resume MSG_ACC_GRA_ANZEIGE = 0x56A # TX by OP, ACC HUD MSG_LDW_1 = 0x5BE # TX by OP, Lane line recognition and text alerts - - class TestVolkswagenPqSafetyBase(common.CarSafetyTest, common.DriverTorqueSteeringSafetyTest): + DBC = "vw_pq" cruise_engaged = False RELAY_MALFUNCTION_ADDRS = {0: (MSG_HCA_1, MSG_LDW_1)} @@ -82,39 +79,13 @@ class TestVolkswagenPqSafetyBase(common.CarSafetyTest, common.DriverTorqueSteeri def _button_msg(self, _set=False, resume=False, cancel=False, bus=2): values = {"GRA_Neu_Setzen": _set, "GRA_Recall": resume, "GRA_Abbrechen": cancel} return self.packer.make_can_msg_safety("GRA_Neu", bus, values) - - def test_torque_measurements(self): - # TODO: make this test work with all cars - self._rx(self._torque_driver_msg(50)) - self._rx(self._torque_driver_msg(-50)) - self._rx(self._torque_driver_msg(0)) - self._rx(self._torque_driver_msg(0)) - self._rx(self._torque_driver_msg(0)) - self._rx(self._torque_driver_msg(0)) - - self.assertEqual(-50, self.safety.get_torque_driver_min()) - self.assertEqual(50, self.safety.get_torque_driver_max()) - - self._rx(self._torque_driver_msg(0)) - self.assertEqual(0, self.safety.get_torque_driver_max()) - self.assertEqual(-50, self.safety.get_torque_driver_min()) - - self._rx(self._torque_driver_msg(0)) - self.assertEqual(0, self.safety.get_torque_driver_max()) - self.assertEqual(0, self.safety.get_torque_driver_min()) - - class TestVolkswagenPqStockSafety(TestVolkswagenPqSafetyBase): # Transmit of GRA_Neu is allowed on bus 0 and 2 to keep compatibility with gateway and camera integration + SAFETY_MODEL = CarParams.SafetyModel.volkswagenPq + TX_MSGS = [[MSG_HCA_1, 0], [MSG_GRA_NEU, 0], [MSG_GRA_NEU, 2], [MSG_LDW_1, 0]] FWD_BLACKLISTED_ADDRS = {2: [MSG_HCA_1, MSG_LDW_1]} - def setUp(self): - self.packer = CANPackerSafety("vw_pq") - self.safety = libsafety_py.libsafety - self.safety.set_safety_hooks(CarParams.SafetyModel.volkswagenPq, 0) - self.safety.init_tests() - def test_spam_cancel_safety_check(self): self.safety.set_controls_allowed(0) self.assertTrue(self._tx(self._button_msg(cancel=True))) @@ -123,20 +94,15 @@ class TestVolkswagenPqStockSafety(TestVolkswagenPqSafetyBase): # do not block resume if we are engaged already self.safety.set_controls_allowed(1) self.assertTrue(self._tx(self._button_msg(resume=True))) - - class TestVolkswagenPqLongSafety(TestVolkswagenPqSafetyBase, common.LongitudinalAccelSafetyTest): + SAFETY_MODEL = CarParams.SafetyModel.volkswagenPq + SAFETY_PARAM = VolkswagenSafetyFlags.LONG_CONTROL + TX_MSGS = [[MSG_HCA_1, 0], [MSG_LDW_1, 0], [MSG_ACC_SYSTEM, 0], [MSG_ACC_GRA_ANZEIGE, 0]] FWD_BLACKLISTED_ADDRS = {2: [MSG_HCA_1, MSG_LDW_1, MSG_ACC_SYSTEM, MSG_ACC_GRA_ANZEIGE]} RELAY_MALFUNCTION_ADDRS = {0: (MSG_HCA_1, MSG_LDW_1, MSG_ACC_SYSTEM, MSG_ACC_GRA_ANZEIGE)} INACTIVE_ACCEL = 3.01 - def setUp(self): - self.packer = CANPackerSafety("vw_pq") - self.safety = libsafety_py.libsafety - self.safety.set_safety_hooks(CarParams.SafetyModel.volkswagenPq, VolkswagenSafetyFlags.LONG_CONTROL) - self.safety.init_tests() - # stock cruise controls are entirely bypassed under openpilot longitudinal control def test_disable_control_allowed_from_cruise(self): pass @@ -181,7 +147,5 @@ class TestVolkswagenPqLongSafety(TestVolkswagenPqSafetyBase, common.Longitudinal for enabled_status in (5, 7): self.assertTrue(self._tx(self._torque_cmd_msg(self.MAX_RATE_UP, steer_req=1, hca_status=enabled_status)), f"torque cmd rejected with {enabled_status=}") - - if __name__ == "__main__": unittest.main()