GM(safety) (#207)

* GM(safety)

* Update carstate.py

---------

Co-authored-by: carrot <43668841+ajouatom@users.noreply.github.com>
This commit is contained in:
kans
2025-08-14 13:55:31 +09:00
committed by GitHub
parent b548ea5677
commit 401c8b52ac
8 changed files with 139 additions and 119 deletions

View File

@@ -302,7 +302,7 @@ class CarController(CarControllerBase):
if (self.frame - self.last_button_frame) * DT_CTRL > 0.04:
if self.cancel_counter > CAMERA_CANCEL_DELAY_FRAMES:
self.last_button_frame = self.frame
can_sends.append(gmcan.create_buttons(self.packer_pt, CanBus.CAMERA, CS.buttons_counter, CruiseButtons.CANCEL))
can_sends.append(gmcan.create_buttons(self.packer_pt, CanBus.CAMERA, (CS.buttons_counter + 1) % 4, CruiseButtons.CANCEL))
if self.CP.networkLocation == NetworkLocation.fwdCamera:
# Silence "Take Steering" alert sent by camera, forward PSCMStatus with HandsOffSWlDetectionStatus=1
@@ -323,10 +323,10 @@ class CarController(CarControllerBase):
# GM: AutoResume
def brake_input(self, brake_force):
MAX_BRAKE = 400
ZERO_GAS = 2048
ZERO_GAS = 0.0
if brake_force > 0.0:
raise ValueError("brake_force는 0.0이하라야 됨.")
scaled_brake = max(0, min(MAX_BRAKE, int(brake_force * -100))) # -를 +로 변환
return ZERO_GAS - scaled_brake
return -scaled_brake

View File

@@ -13,7 +13,7 @@ TransmissionType = structs.CarParams.TransmissionType
NetworkLocation = structs.CarParams.NetworkLocation
GearShifter = structs.CarState.GearShifter
STANDSTILL_THRESHOLD = 10 * 0.0311 * CV.KPH_TO_MS
LongCtrlState = car.CarControl.Actuators.LongControlState # kans
BUTTONS_DICT = {CruiseButtons.RES_ACCEL: ButtonType.accelCruise, CruiseButtons.DECEL_SET: ButtonType.decelCruise,
CruiseButtons.MAIN: ButtonType.mainCruise, CruiseButtons.CANCEL: ButtonType.cancel,
CruiseButtons.GAP_DIST: ButtonType.gapAdjustCruise}
@@ -32,15 +32,12 @@ class CarState(CarStateBase):
self.cam_lka_steering_cmd_counter = 0
self.is_metric = False
# GAP_DIST
self.prev_distance_button = False
self.distance_button_pressed = False
self.cruise_buttons = 0
self.buttons_counter = 0
self.single_pedal_mode = False
self.pedal_steady = 0.
self.cruise_buttons = 0
# GAP_DIST
self.distance_button = 0
# cruiseMain default(test from nd0706-vision)
self.cruiseMain_on = True if Params().get_int("AutoEngage") == 2 else False
@@ -62,14 +59,14 @@ class CarState(CarStateBase):
ret = structs.CarState()
prev_cruise_buttons = self.cruise_buttons
self.prev_distance_button = self.distance_button_pressed
prev_distance_button = self.distance_button
self.cruise_buttons = pt_cp.vl["ASCMSteeringButton"]["ACCButtons"]
self.distance_button_pressed = pt_cp.vl["ASCMSteeringButton"]["DistanceButton"] != 0
self.distance_button = pt_cp.vl["ASCMSteeringButton"]["DistanceButton"]
self.buttons_counter = pt_cp.vl["ASCMSteeringButton"]["RollingCounter"]
self.pscm_status = copy.copy(pt_cp.vl["PSCMStatus"])
# GAP_DIST
if self.cruise_buttons in [CruiseButtons.UNPRESS, CruiseButtons.INIT] and self.distance_button_pressed:
if self.cruise_buttons in [CruiseButtons.UNPRESS, CruiseButtons.INIT] and self.distance_button:
self.cruise_buttons = CruiseButtons.GAP_DIST
if self.CP.enableBsm:
@@ -168,7 +165,7 @@ class CarState(CarStateBase):
if self.CP.networkLocation == NetworkLocation.fwdCamera and not self.CP.flags & GMFlags.NO_CAMERA.value:
if self.CP.carFingerprint not in CC_ONLY_CAR:
ret.cruiseState.speed = cam_cp.vl["ASCMActiveCruiseControlStatus"]["ACCSpeedSetpoint"] * CV.KPH_TO_MS
ret.stockAeb = cam_cp.vl["AEBCmd"]["AEBCmdActive"] != 0
ret.stockAeb = False
# openpilot controls nonAdaptive when not pcmCruise
if self.CP.pcmCruise and self.CP.carFingerprint not in CC_ONLY_CAR:
ret.cruiseState.nonAdaptive = cam_cp.vl["ASCMActiveCruiseControlStatus"]["ACCCruiseState"] not in (2, 3)
@@ -176,6 +173,8 @@ class CarState(CarStateBase):
ret.accFaulted = False
ret.cruiseState.speed = pt_cp.vl["ECMCruiseControl"]["CruiseSetSpeed"] * CV.KPH_TO_MS
ret.cruiseState.enabled = pt_cp.vl["ECMCruiseControl"]["CruiseActive"] != 0
prev_lkas_enabled = self.lkas_enabled
self.lkas_enabled = pt_cp.vl["ASCMSteeringButton"]["LKAButton"]
self.pcm_acc_status = pt_cp.vl["AcceleratorPedal2"]["CruiseState"]
if self.CP.carFingerprint in (CAR.CHEVROLET_TRAX, CAR.CHEVROLET_TRAILBLAZER, CAR.CHEVROLET_TRAILBLAZER_CC):
@@ -193,15 +192,15 @@ class CarState(CarStateBase):
ret.vCluRatio = 0.96
# Don't add event if transitioning from INIT, unless it's to an actual button
buttonEvents = [] # kans
if self.cruise_buttons != CruiseButtons.UNPRESS or prev_cruise_buttons != CruiseButtons.INIT:
buttonEvents.extend(create_button_events(self.cruise_buttons, prev_cruise_buttons, BUTTONS_DICT,
unpressed_btn=CruiseButtons.UNPRESS)) # kans
# kans : long_button GAP for cruise Mode(safety, ecco, high-speed..)
if self.distance_button_pressed:
buttonEvents.append(car.CarState.ButtonEvent(pressed=True, type=ButtonType.gapAdjustCruise))
ret.buttonEvents = buttonEvents # kans
ret.buttonEvents = [
*create_button_events(self.cruise_buttons, prev_cruise_buttons, BUTTONS_DICT,
unpressed_btn=CruiseButtons.UNPRESS),
*create_button_events(self.distance_button, prev_distance_button,
{1: ButtonType.gapAdjustCruise}),
*create_button_events(self.lkas_enabled, prev_lkas_enabled,
{1: ButtonType.lkas})
]
return ret
@@ -217,7 +216,6 @@ class CarState(CarStateBase):
("EBCMRegenPaddle", 50),
("EVDriveMode", 0),
]
loopback_messages = [
("ASCMLKASteeringCmd", float('nan')),
]

View File

@@ -72,17 +72,14 @@ def create_gas_regen_command(packer, bus, throttle, idx, enabled, at_full_stop):
values = {
"GasRegenCmdActive": enabled,
"RollingCounter": idx,
"GasRegenCmdActiveInv": 1 - enabled,
"GasRegenCmd": throttle,
"GasRegenFullStopActive": at_full_stop,
"GasRegenAlwaysOne": 1,
"GasRegenAlwaysOne2": 1,
"GasRegenAlwaysOne3": 1,
#"NEW_SIGNAL_1" : 0 if at_full_stop else 3,
"GasRegenAccType": 1,
}
dat = packer.make_can_msg("ASCMGasRegenCmd", bus, values)[1]
values["GasRegenChecksum"] = (((0xff - dat[1]) & 0xff) << 16) | \
values["GasRegenChecksum"] = ((1 - enabled) << 24) | \
(((0xff - dat[1]) & 0xff) << 16) | \
(((0xff - dat[2]) & 0xff) << 8) | \
((0x100 - dat[3] - idx) & 0xff)
@@ -106,6 +103,7 @@ def create_friction_brake_command(packer, bus, apply_brake, idx, enabled, near_s
#elif near_stop:
# mode = 0xb
apply_brake = max(0, min(0xFFF, apply_brake))
brake = (0x1000 - apply_brake) & 0xfff
checksum = (0x10000 - (mode << 12) - brake - idx) & 0xffff
@@ -113,7 +111,7 @@ def create_friction_brake_command(packer, bus, apply_brake, idx, enabled, near_s
"RollingCounter": idx,
"FrictionBrakeMode": mode,
"FrictionBrakeChecksum": checksum,
"FrictionBrakeCmd": -apply_brake
"FrictionBrakeCmd": (0x1000 - apply_brake) & 0xfff,
}
return packer.make_can_msg("EBCMFrictionBrakeCmd", bus, values)

View File

@@ -104,6 +104,8 @@ class CarInterface(CarInterfaceBase):
ret.autoResumeSng = False
ret.enableBsm = 0x142 in fingerprint[CanBus.POWERTRAIN] or 0x142 in fingerprint[CanBus.CAMERA]
ret.startAccel = 1.0
ret.radarTimeStep = 0.067
ret.alternativeExperience = 0
useEVTables = Params().get_bool("EVTable")
@@ -120,7 +122,7 @@ class CarInterface(CarInterfaceBase):
ret.longitudinalTuning.kiBP = [0.]
if candidate in (CAMERA_ACC_CAR | SDGM_CAR):
ret.alphaLongitudinalAvailable = candidate not in (CC_ONLY_CAR | SDGM_CAR)
ret.alphaLongitudinalAvailable = candidate not in SDGM_CAR
ret.networkLocation = NetworkLocation.fwdCamera
ret.radarUnavailable = True # no radar
ret.pcmCruise = True
@@ -129,14 +131,13 @@ class CarInterface(CarInterfaceBase):
ret.minSteerSpeed = 10 * CV.KPH_TO_MS
# Tuning for experimental long
ret.longitudinalTuning.kpV = [1.0]
ret.longitudinalTuning.kiV = [1.0]
ret.longitudinalTuning.kiV = [1.7]
ret.stoppingDecelRate = 2.0 # reach brake quickly after enabling
ret.vEgoStopping = 0.25
ret.vEgoStarting = 0.25
ret.vEgoStopping = 0.5
ret.vEgoStarting = 0.4
ret.stopAccel = -0.4
ret.startingState = True
ret.startAccel = 1.5
ret.startAccel = 1.0
if alpha_long:
ret.pcmCruise = False
@@ -161,7 +162,6 @@ class CarInterface(CarInterfaceBase):
ret.longitudinalTuning.kpV = [1.0]
ret.longitudinalTuning.kiV = [0.3]
# TODO: Test for CADILLAC_CT6_ACC
if ret.enableGasInterceptorDEPRECATED:
# Need to set ASCM long limits when using pedal interceptor, instead of camera ACC long limits
ret.safetyConfigs[0].safetyParam |= GMSafetyFlags.HW_ASCM_LONG.value
@@ -186,8 +186,8 @@ class CarInterface(CarInterfaceBase):
ret.longitudinalTuning.kiV = [.35]
ret.longitudinalTuning.kf = 1.0
ret.stoppingDecelRate = 0.2 # brake_travel/s while trying to stop
ret.vEgoStopping = 0.1
ret.vEgoStarting = 0.05
ret.vEgoStopping = 0.25
ret.vEgoStarting = 0.15
ret.stopAccel = -0.5
ret.startingState = True
ret.startAccel = 1.9

View File

@@ -19,7 +19,7 @@ class CarControllerParams:
STEER_DRIVER_ALLOWANCE = 65
STEER_DRIVER_MULTIPLIER = 4
STEER_DRIVER_FACTOR = 100
NEAR_STOP_BRAKE_PHASE = 0.1 #0.5 # m/s
NEAR_STOP_BRAKE_PHASE = 0.4
SNG_INTERCEPTOR_GAS = 18. / 255.
SNG_TIME = 30 # frames until the above is reached
@@ -37,21 +37,21 @@ class CarControllerParams:
def __init__(self, CP):
# Gas/brake lookups
self.ZERO_GAS = 2048 # Coasting
self.ZERO_GAS = 0.0 # Coasting
self.MAX_BRAKE = 400 # ~ -4.0 m/s^2 with regen
if CP.carFingerprint in (CAMERA_ACC_CAR | SDGM_CAR) and CP.carFingerprint not in CC_ONLY_CAR:
self.MAX_GAS = 3400
self.MAX_ACC_REGEN = 1514
self.INACTIVE_REGEN = 1554
self.MAX_GAS = 1346.0
self.MAX_ACC_REGEN = -540.0
self.INACTIVE_REGEN = -500.0
# Camera ACC vehicles have no regen while enabled.
# Camera transitions to MAX_ACC_REGEN from ZERO_GAS and uses friction brakes instantly
max_regen_acceleration = 0.
else:
self.MAX_GAS = 3072 # Safety limit, not ACC max. Stock ACC >4096 from standstill.
self.MAX_ACC_REGEN = 1404 # Max ACC regen is slightly less than max paddle regen
self.INACTIVE_REGEN = 1404
self.MAX_GAS = 1018.0 # Safety limit, not ACC max. Stock ACC >2042 from standstill.
self.MAX_ACC_REGEN = -650.0 # Max ACC regen is slightly less than max paddle regen
self.INACTIVE_REGEN = -650.0
# ICE has much less engine braking force compared to regen in EVs,
# lower threshold removes some braking deadzone
max_regen_acceleration = -1. if CP.carFingerprint in EV_CAR else -0.1
@@ -268,6 +268,7 @@ class CruiseButtons:
class AccState:
OFF = 0
ACTIVE = 1
STANDBY = 2
FAULTED = 3
STANDSTILL = 4

View File

@@ -1,4 +1,5 @@
CM_ "IMPORT _community.dbc";
VERSION ""
@@ -194,15 +195,12 @@ BO_ 711 BECMBatteryVoltageCurrent: 6 K17_EBCM
SG_ HVBatteryCurrent : 12|13@0- (0.15,0) [-614.4|614.25] "A" NEO
BO_ 715 ASCMGasRegenCmd: 8 K124_ASCM
SG_ GasRegenAlwaysOne2 : 9|1@0+ (1,0) [0|1] "" NEO
SG_ GasRegenAlwaysOne : 14|1@0+ (1,0) [0|1] "" NEO
SG_ GasRegenChecksum : 47|24@0+ (1,0) [0|0] "" NEO
SG_ GasRegenCmdActiveInv : 32|1@0+ (1,0) [0|0] "" NEO
SG_ GasRegenAccType : 15|2@0+ (1,0) [0|3] "" NEO
SG_ GasRegenChecksum : 32|25@0+ (1,0) [0|0] "" NEO
SG_ GasRegenFullStopActive : 13|1@0+ (1,0) [0|0] "" NEO
SG_ GasRegenCmdActive : 0|1@0+ (1,0) [0|0] "" NEO
SG_ RollingCounter : 7|2@0+ (1,0) [0|0] "" NEO
SG_ GasRegenAlwaysOne3 : 23|1@0+ (1,0) [0|1] "" NEO
SG_ GasRegenCmd : 22|12@0+ (1,0) [0|0] "" NEO
SG_ GasRegenCmd : 10|19@0+ (0.125,-22534) [-22534|43001.875] "Nm" NEO
BO_ 717 ASCM_2CD: 5 K124_ASCM
@@ -330,7 +328,7 @@ VAL_ 481 DistanceButton 1 "Active" 0 "Inactive" ;
VAL_ 481 LKAButton 1 "Active" 0 "Inactive" ;
VAL_ 481 ACCButtons 6 "Cancel" 5 "Main" 3 "Set" 2 "Resume" 1 "None" ;
VAL_ 481 DriveModeButton 1 "Active" 0 "Inactive" ;
VAL_ 452 CruiseState 4 "Standstill" 3 "Faulted" 1 "Active" 0 "Off" ;
VAL_ 452 CruiseState 4 "Standstill" 3 "Faulted" 2 "Standby" 1 "Active" 0 "Off" ;
VAL_ 309 PRNDL 3 "R" 2 "D" 1 "N" 0 "P" ;
VAL_ 309 ESPButton 1 "Active" 0 "Inactive" ;
VAL_ 384 LKASteeringCmdActive 1 "Active" 0 "Inactive" ;

View File

@@ -1,25 +1,5 @@
CM_ "AUTOGENERATED FILE, DO NOT EDIT";
CM_ "Imported file _comma.dbc starts here";
BO_ 512 GAS_COMMAND: 6 NEO
SG_ GAS_COMMAND : 7|16@0+ (0.125677,-75.909) [0|1] "" INTERCEPTOR
SG_ GAS_COMMAND2 : 23|16@0+ (0.251976,-76.601) [0|1] "" INTERCEPTOR
SG_ ENABLE : 39|1@0+ (1,0) [0|1] "" INTERCEPTOR
SG_ COUNTER_PEDAL : 35|4@0+ (1,0) [0|15] "" INTERCEPTOR
SG_ CHECKSUM_PEDAL : 47|8@0+ (1,0) [0|255] "" INTERCEPTOR
BO_ 513 GAS_SENSOR: 6 INTERCEPTOR
SG_ INTERCEPTOR_GAS : 7|16@0+ (0.125677,-75.909) [0|1] "" NEO
SG_ INTERCEPTOR_GAS2 : 23|16@0+ (0.251976,-76.601) [0|1] "" NEO
SG_ STATE : 39|4@0+ (1,0) [0|15] "" NEO
SG_ COUNTER_PEDAL : 35|4@0+ (1,0) [0|15] "" NEO
SG_ CHECKSUM_PEDAL : 47|8@0+ (1,0) [0|255] "" NEO
VAL_ 513 STATE 5 "FAULT_TIMEOUT" 4 "FAULT_STARTUP" 3 "FAULT_SCE" 2 "FAULT_SEND" 1 "FAULT_BAD_CHECKSUM" 0 "NO_FAULT" ;
CM_ "gm_global_a_powertrain.dbc starts here";
CM_ "IMPORT _community.dbc";
VERSION ""
@@ -214,15 +194,12 @@ BO_ 711 BECMBatteryVoltageCurrent: 6 K17_EBCM
SG_ HVBatteryCurrent : 12|13@0- (0.15,0) [-614.4|614.25] "A" NEO
BO_ 715 ASCMGasRegenCmd: 8 K124_ASCM
SG_ GasRegenAlwaysOne2 : 9|1@0+ (1,0) [0|1] "" NEO
SG_ GasRegenAlwaysOne : 14|1@0+ (1,0) [0|1] "" NEO
SG_ GasRegenChecksum : 47|24@0+ (1,0) [0|0] "" NEO
SG_ GasRegenCmdActiveInv : 32|1@0+ (1,0) [0|0] "" NEO
SG_ GasRegenAccType : 15|2@0+ (1,0) [0|3] "" NEO
SG_ GasRegenChecksum : 32|25@0+ (1,0) [0|0] "" NEO
SG_ GasRegenFullStopActive : 13|1@0+ (1,0) [0|0] "" NEO
SG_ GasRegenCmdActive : 0|1@0+ (1,0) [0|0] "" NEO
SG_ RollingCounter : 7|2@0+ (1,0) [0|0] "" NEO
SG_ GasRegenAlwaysOne3 : 23|1@0+ (1,0) [0|1] "" NEO
SG_ GasRegenCmd : 22|12@0+ (1,0) [0|0] "" NEO
SG_ GasRegenCmd : 10|19@0+ (0.125,-22534) [-22534|43001.875] "Nm" NEO
BO_ 717 ASCM_2CD: 5 K124_ASCM
@@ -350,7 +327,7 @@ VAL_ 481 DistanceButton 1 "Active" 0 "Inactive" ;
VAL_ 481 LKAButton 1 "Active" 0 "Inactive" ;
VAL_ 481 ACCButtons 6 "Cancel" 5 "Main" 3 "Set" 2 "Resume" 1 "None" ;
VAL_ 481 DriveModeButton 1 "Active" 0 "Inactive" ;
VAL_ 452 CruiseState 4 "Standstill" 3 "Faulted" 1 "Active" 0 "Off" ;
VAL_ 452 CruiseState 4 "Standstill" 3 "Faulted" 2 "Standby" 1 "Active" 0 "Off" ;
VAL_ 309 PRNDL 3 "R" 2 "D" 1 "N" 0 "P" ;
VAL_ 309 ESPButton 1 "Active" 0 "Inactive" ;
VAL_ 384 LKASteeringCmdActive 1 "Active" 0 "Inactive" ;

View File

@@ -2,6 +2,19 @@
#include "safety_declarations.h"
// TODO: do checksum and counter checks. Add correct timestep, 0.1s for now.
#define GM_COMMON_RX_CHECKS \
{.msg = {{0x184, 0, 8, .ignore_checksum = true, .ignore_counter = true, .frequency = 10U}, { 0 }, { 0 }}}, \
{.msg = {{0x34A, 0, 5, .ignore_checksum = true, .ignore_counter = true, .frequency = 10U}, { 0 }, { 0 }}}, \
{.msg = {{0x1E1, 0, 7, .ignore_checksum = true, .ignore_counter = true, .frequency = 10U}, { 0 }, { 0 }}}, \
{.msg = {{0x1C4, 0, 8, .ignore_checksum = true, .ignore_counter = true, .frequency = 10U}, { 0 }, { 0 }}}, \
{.msg = {{0xC9, 0, 8, .ignore_checksum = true, .ignore_counter = true, .frequency = 10U}, { 0 }, { 0 }}}, \
#define GM_ACC_RX_CHECKS \
{.msg = {{0xBE, 0, 6, .ignore_checksum = true, .ignore_counter = true, .frequency = 10U}, /* Volt, Silverado, Acadia Denali */ \
{0xBE, 0, 7, .ignore_checksum = true, .ignore_counter = true, .frequency = 10U}, /* Bolt EUV */ \
{0xBE, 0, 8, .ignore_checksum = true, .ignore_counter = true, .frequency = 10U}}}, /* Escalade */ \
static const LongitudinalLimits *gm_long_limits;
enum {
@@ -76,9 +89,11 @@ static void gm_rx_hook(const CANPacket_t *to_push) {
if ((addr == 0xBE) && (gm_hw == GM_ASCM)) {
brake_pressed = GET_BYTE(to_push, 1) >= 10U;
}
if ((addr == 0xC9) && (gm_hw == GM_CAM)) {
brake_pressed = GET_BIT(to_push, 40U);
if (addr == 0xC9) {
if (gm_hw == GM_CAM) {
brake_pressed = (GET_BYTE(to_push, 5) & 0x01U) != 0U;
}
acc_main_on = (GET_BYTE(to_push, 3) & 0x20U) != 0U;
}
if (addr == 0x1C4) {
@@ -112,13 +127,13 @@ static void gm_rx_hook(const CANPacket_t *to_push) {
int gas_interceptor = GM_GET_INTERCEPTOR(to_push);
gas_pressed = gas_interceptor > GM_GAS_INTERCEPTOR_THRESHOLD;
gas_interceptor_prev = gas_interceptor;
// gm_pcm_cruise = false;
// gm_pcm_cruise = false;
}
bool stock_ecu_detected = (addr == 0x180); // ASCMLKASteeringCmd
// Check ASCMGasRegenCmd only if we're blocking it
if (!gm_pcm_cruise && !gm_pedal_long && (addr == 0x2CB)) {
if (!gm_pcm_cruise && (addr == 0x2CB)) {
stock_ecu_detected = true;
}
generic_rx_checks(stock_ecu_detected);
@@ -128,8 +143,8 @@ static void gm_rx_hook(const CANPacket_t *to_push) {
static bool gm_tx_hook(const CANPacket_t *to_send) {
const TorqueSteeringLimits GM_STEERING_LIMITS = {
.max_steer = 300,
.max_rate_up = 10,
.max_rate_down = 15,
.max_rate_up = 20,
.max_rate_down = 25,
.driver_torque_allowance = 65,
.driver_torque_multiplier = 4,
.max_rt_delta = 128,
@@ -171,11 +186,11 @@ static bool gm_tx_hook(const CANPacket_t *to_send) {
// GAS/REGEN: safety check
if (addr == 0x2CB) {
bool apply = GET_BIT(to_send, 0U);
if (apply) {
if(!controls_allowed) print("@@auto cruise control enabled....\n");
controls_allowed = true;
if (apply && !controls_allowed) {
controls_allowed = true;
}
int gas_regen = ((GET_BYTE(to_send, 2) & 0x7FU) << 5) + ((GET_BYTE(to_send, 3) & 0xF8U) >> 3);
// convert float CAN signal to an int for gas checks: 22534 / 0.125 = 180272
int gas_regen = (((GET_BYTE(to_send, 1) & 0x7U) << 16) | (GET_BYTE(to_send, 2) << 8) | GET_BYTE(to_send, 3)) - 180272U;
bool violation = false;
// Allow apply bit in pre-enabled and overriding states
@@ -188,13 +203,15 @@ static bool gm_tx_hook(const CANPacket_t *to_send) {
}
// BUTTONS: used for resume spamming and cruise cancellation with stock longitudinal
if ((addr == 0x1E1) && (gm_pcm_cruise || gm_pedal_long || gm_cc_long)) {
if (addr == 0x1E1) {
int button = (GET_BYTE(to_send, 5) >> 4) & 0x7U;
bool allowed_btn = (button == GM_BTN_CANCEL) && cruise_engaged_prev;
// For standard CC, allow spamming of SET / RESUME
if (!gm_pcm_cruise) {
allowed_btn |= (button == GM_BTN_SET || button == GM_BTN_RESUME || button == GM_BTN_UNPRESS);
}
if (gm_cc_long) {
allowed_btn |= cruise_engaged_prev && ((button == GM_BTN_SET) || (button == GM_BTN_RESUME) || (button == GM_BTN_UNPRESS));
allowed_btn |= cruise_engaged_prev && (button == GM_BTN_SET || button == GM_BTN_RESUME || button == GM_BTN_UNPRESS);
}
if (!allowed_btn) {
@@ -239,10 +256,13 @@ static safety_config gm_init(uint16_t param) {
const uint16_t GM_PARAM_NO_ACC = 32;
const uint16_t GM_PARAM_PEDAL_LONG = 64; // TODO: this can be inferred
// common safety checks assume unscaled integer values
static const int GM_GAS_TO_CAN = 8; // 1 / 0.125
static const LongitudinalLimits GM_ASCM_LONG_LIMITS = {
.max_gas = 3072,
.min_gas = 1404,
.inactive_gas = 1404,
.max_gas = 1018 * GM_GAS_TO_CAN,
.min_gas = -650 * GM_GAS_TO_CAN,
.inactive_gas = -650 * GM_GAS_TO_CAN,
.max_brake = 400,
};
@@ -251,38 +271,52 @@ static safety_config gm_init(uint16_t param) {
{0x315, 2, 5}}; // ch bus
static const CanMsg GM_CC_LONG_TX_MSGS[] = {{0x180, 0, 4}, {0x1E1, 0, 7}, // pt bus
{0x184, 2, 8}, {0x1E1, 2, 7}}; // camera bus
static const LongitudinalLimits GM_CAM_LONG_LIMITS = {
.max_gas = 3400,
.min_gas = 1514,
.inactive_gas = 1554,
.max_gas = 1346 * GM_GAS_TO_CAN,
.min_gas = -540 * GM_GAS_TO_CAN,
.inactive_gas = -500 * GM_GAS_TO_CAN,
.max_brake = 400,
};
static const CanMsg GM_CAM_LONG_TX_MSGS[] = {{0x180, 0, 4}, {0x315, 0, 5}, {0x2CB, 0, 8}, {0x370, 0, 6}, {0x200, 0, 6}, {0x1E1, 0, 7}, // pt bus
{0x184, 2, 8}}; // camera bus
// TODO: do checksum and counter checks. Add correct timestep, 0.1s for now.
static RxCheck gm_rx_checks[] = {
{.msg = {{0x184, 0, 8, .ignore_checksum = true, .ignore_counter = true, .frequency = 10U}, { 0 }, { 0 }}},
{.msg = {{0x34A, 0, 5, .ignore_checksum = true, .ignore_counter = true, .frequency = 10U}, { 0 }, { 0 }}},
{.msg = {{0x1E1, 0, 7, .ignore_checksum = true, .ignore_counter = true, .frequency = 10U}, { 0 }, { 0 }}},
{.msg = {{0xBE, 0, 6, .ignore_checksum = true, .ignore_counter = true, .frequency = 10U}, // Volt, Silverado, Acadia Denali
{0xBE, 0, 7, .ignore_checksum = true, .ignore_counter = true, .frequency = 10U}, // Bolt EUV
{0xBE, 0, 8, .ignore_checksum = true, .ignore_counter = true, .frequency = 10U}}}, // Escalade
{.msg = {{0xF1, 0, 6, .ignore_checksum = true, .ignore_counter = true, .frequency = 10U}, { 0 }, { 0 }}},
{.msg = {{0x1C4, 0, 8, .ignore_checksum = true, .ignore_counter = true, .frequency = 10U}, { 0 }, { 0 }}},
{.msg = {{0xC9, 0, 8, .ignore_checksum = true, .ignore_counter = true, .frequency = 10U}, { 0 }, { 0 }}},
GM_COMMON_RX_CHECKS
GM_ACC_RX_CHECKS
};
static RxCheck gm_ev_rx_checks[] = {
GM_COMMON_RX_CHECKS
GM_ACC_RX_CHECKS
{.msg = {{0xBD, 0, 7, .ignore_checksum = true, .ignore_counter = true, .frequency = 40U}, { 0 }, { 0 }}},
};
static RxCheck gm_no_acc_rx_checks[] = {
GM_COMMON_RX_CHECKS
{.msg = {{0x3D1, 0, 8, .ignore_checksum = true, .ignore_counter = true, .frequency = 10U}, { 0 }, { 0 }}}, // Non-ACC PCM
};
static RxCheck gm_no_acc_ev_rx_checks[] = {
GM_COMMON_RX_CHECKS
{.msg = {{0xBD, 0, 7, .ignore_checksum = true, .ignore_counter = true, .frequency = 40U}, { 0 }, { 0 }}},
{.msg = {{0x3D1, 0, 8, .ignore_checksum = true, .ignore_counter = true, .frequency = 10U}, { 0 }, { 0 }}}, // Non-ACC PCM
};
static RxCheck gm_pedal_rx_checks[] = {
GM_COMMON_RX_CHECKS
{.msg = {{0xBD, 0, 7, .ignore_checksum = true, .ignore_counter = true, .frequency = 40U}, { 0 }, { 0 }}},
{.msg = {{0x3D1, 0, 8, .ignore_checksum = true, .ignore_counter = true, .frequency = 10U}, { 0 }, { 0 }}}, // Non-ACC PCM
{.msg = {{0x201, 0, 6, .ignore_checksum = true, .ignore_counter = true, .frequency = 10U}, { 0 }, { 0 }}}, // pedal
};
static const CanMsg GM_CAM_TX_MSGS[] = {{0x180, 0, 4}, {0x200, 0, 6}, {0x1E1, 0, 7}, // pt bus
{0x1E1, 2, 7}, {0x184, 2, 8}}; // camera bus
static const CanMsg GM_CC_LONG_TX_MSGS[] = {{0x180, 0, 4}, {0x1E1, 0, 7}, // pt bus
{0x184, 2, 8}, {0x1E1, 2, 7}}; // camera bus
gm_hw = GET_FLAG(param, GM_PARAM_HW_CAM) ? GM_CAM : GM_ASCM;
gm_force_ascm = GET_FLAG(param, GM_PARAM_HW_ASCM_LONG);
@@ -299,7 +333,7 @@ static safety_config gm_init(uint16_t param) {
#endif
gm_pedal_long = GET_FLAG(param, GM_PARAM_PEDAL_LONG);
gm_cc_long = GET_FLAG(param, GM_PARAM_CC_LONG);
gm_pcm_cruise = (gm_hw == GM_CAM) && !gm_cam_long && !gm_force_ascm && !gm_pedal_long;
gm_pcm_cruise = (gm_hw == GM_CAM) && (!gm_cam_long || gm_cc_long) && !gm_force_ascm && !gm_pedal_long;
gm_skip_relay_check = GET_FLAG(param, GM_PARAM_NO_CAMERA);
gm_has_acc = !GET_FLAG(param, GM_PARAM_NO_ACC);
@@ -310,7 +344,7 @@ static safety_config gm_init(uint16_t param) {
}
else print("GM Pedal Interceptor Disabled\n");
safety_config ret = BUILD_SAFETY_CFG(gm_rx_checks, GM_ASCM_TX_MSGS);
safety_config ret;
if (gm_hw == GM_CAM) {
if (gm_cc_long) {
ret = BUILD_SAFETY_CFG(gm_rx_checks, GM_CC_LONG_TX_MSGS);
@@ -322,7 +356,21 @@ static safety_config gm_init(uint16_t param) {
ret = BUILD_SAFETY_CFG(gm_rx_checks, GM_CAM_TX_MSGS);
print("GM CAM\n");
}
} else {
ret = BUILD_SAFETY_CFG(gm_rx_checks, GM_ASCM_TX_MSGS);
}
const bool gm_ev = GET_FLAG(param, GM_PARAM_EV);
if (enable_gas_interceptor) {
SET_RX_CHECKS(gm_pedal_rx_checks, ret);
} else if (!gm_has_acc && gm_ev) {
SET_RX_CHECKS(gm_no_acc_ev_rx_checks, ret);
} else if (!gm_has_acc && !gm_ev) {
SET_RX_CHECKS(gm_no_acc_rx_checks, ret);
} else if (gm_ev) {
SET_RX_CHECKS(gm_ev_rx_checks, ret);
} else {}
return ret;
}