mirror of
https://github.com/sunnypilot/sunnypilot.git
synced 2026-02-18 22:23:56 +08:00
GM: prep and cleanup for future ports (#24910)
* Interface radarOffCan set, comments * pass pcmCruise value to common events * add transType and networkLoc to iface * carstate use transtype to detect EV * ctrl: limit sends by config * Add clarifying comments for new vals * clean up * comment on new line * these have the same frequency * remove 25hz * add to upper comment * update refs * update refs * move into same block move into same block Co-authored-by: Shane Smiskol <shane@smiskol.com>
This commit is contained in:
@@ -8,10 +8,12 @@ from selfdrive.car.gm import gmcan
|
||||
from selfdrive.car.gm.values import DBC, CanBus, CarControllerParams
|
||||
|
||||
VisualAlert = car.CarControl.HUDControl.VisualAlert
|
||||
NetworkLocation = car.CarParams.NetworkLocation
|
||||
|
||||
|
||||
class CarController:
|
||||
def __init__(self, dbc_name, CP, VM):
|
||||
self.CP = CP
|
||||
self.start_time = 0.
|
||||
self.apply_steer_last = 0
|
||||
self.apply_gas = 0
|
||||
@@ -24,9 +26,9 @@ class CarController:
|
||||
|
||||
self.params = CarControllerParams()
|
||||
|
||||
self.packer_pt = CANPacker(DBC[CP.carFingerprint]['pt'])
|
||||
self.packer_obj = CANPacker(DBC[CP.carFingerprint]['radar'])
|
||||
self.packer_ch = CANPacker(DBC[CP.carFingerprint]['chassis'])
|
||||
self.packer_pt = CANPacker(DBC[self.CP.carFingerprint]['pt'])
|
||||
self.packer_obj = CANPacker(DBC[self.CP.carFingerprint]['radar'])
|
||||
self.packer_ch = CANPacker(DBC[self.CP.carFingerprint]['chassis'])
|
||||
|
||||
def update(self, CC, CS):
|
||||
actuators = CC.actuators
|
||||
@@ -60,48 +62,48 @@ class CarController:
|
||||
|
||||
can_sends.append(gmcan.create_steering_control(self.packer_pt, CanBus.POWERTRAIN, apply_steer, idx, lkas_enabled))
|
||||
|
||||
# Gas/regen and brakes - all at 25Hz
|
||||
if (self.frame % 4) == 0:
|
||||
if not CC.longActive:
|
||||
# Stock ECU sends max regen when not enabled
|
||||
self.apply_gas = self.params.MAX_ACC_REGEN
|
||||
self.apply_brake = 0
|
||||
else:
|
||||
self.apply_gas = int(round(interp(actuators.accel, self.params.GAS_LOOKUP_BP, self.params.GAS_LOOKUP_V)))
|
||||
self.apply_brake = int(round(interp(actuators.accel, self.params.BRAKE_LOOKUP_BP, self.params.BRAKE_LOOKUP_V)))
|
||||
if self.CP.openpilotLongitudinalControl:
|
||||
# Gas/regen, brakes, and UI commands - all at 25Hz
|
||||
if self.frame % 4 == 0:
|
||||
if not CC.longActive:
|
||||
# Stock ECU sends max regen when not enabled
|
||||
self.apply_gas = self.params.MAX_ACC_REGEN
|
||||
self.apply_brake = 0
|
||||
else:
|
||||
self.apply_gas = int(round(interp(actuators.accel, self.params.GAS_LOOKUP_BP, self.params.GAS_LOOKUP_V)))
|
||||
self.apply_brake = int(round(interp(actuators.accel, self.params.BRAKE_LOOKUP_BP, self.params.BRAKE_LOOKUP_V)))
|
||||
|
||||
idx = (self.frame // 4) % 4
|
||||
idx = (self.frame // 4) % 4
|
||||
|
||||
at_full_stop = CC.longActive and CS.out.standstill
|
||||
near_stop = CC.longActive and (CS.out.vEgo < self.params.NEAR_STOP_BRAKE_PHASE)
|
||||
# GasRegenCmdActive needs to be 1 to avoid cruise faults. It describes the ACC state, not actuation
|
||||
can_sends.append(gmcan.create_gas_regen_command(self.packer_pt, CanBus.POWERTRAIN, self.apply_gas, idx, CC.enabled, at_full_stop))
|
||||
can_sends.append(gmcan.create_friction_brake_command(self.packer_ch, CanBus.CHASSIS, self.apply_brake, idx, near_stop, at_full_stop))
|
||||
at_full_stop = CC.longActive and CS.out.standstill
|
||||
near_stop = CC.longActive and (CS.out.vEgo < self.params.NEAR_STOP_BRAKE_PHASE)
|
||||
# GasRegenCmdActive needs to be 1 to avoid cruise faults. It describes the ACC state, not actuation
|
||||
can_sends.append(gmcan.create_gas_regen_command(self.packer_pt, CanBus.POWERTRAIN, self.apply_gas, idx, CC.enabled, at_full_stop))
|
||||
can_sends.append(gmcan.create_friction_brake_command(self.packer_ch, CanBus.CHASSIS, self.apply_brake, idx, near_stop, at_full_stop))
|
||||
|
||||
# Send dashboard UI commands (ACC status), 25hz
|
||||
if (self.frame % 4) == 0:
|
||||
send_fcw = hud_alert == VisualAlert.fcw
|
||||
can_sends.append(gmcan.create_acc_dashboard_command(self.packer_pt, CanBus.POWERTRAIN, CC.enabled,
|
||||
hud_v_cruise * CV.MS_TO_KPH, hud_control.leadVisible, send_fcw))
|
||||
# Send dashboard UI commands (ACC status)
|
||||
send_fcw = hud_alert == VisualAlert.fcw
|
||||
can_sends.append(gmcan.create_acc_dashboard_command(self.packer_pt, CanBus.POWERTRAIN, CC.enabled,
|
||||
hud_v_cruise * CV.MS_TO_KPH, hud_control.leadVisible, send_fcw))
|
||||
|
||||
# Radar needs to know current speed and yaw rate (50hz),
|
||||
# and that ADAS is alive (10hz)
|
||||
time_and_headlights_step = 10
|
||||
tt = self.frame * DT_CTRL
|
||||
# Radar needs to know current speed and yaw rate (50hz),
|
||||
# and that ADAS is alive (10hz)
|
||||
if not self.CP.radarOffCan:
|
||||
tt = self.frame * DT_CTRL
|
||||
time_and_headlights_step = 10
|
||||
if self.frame % time_and_headlights_step == 0:
|
||||
idx = (self.frame // time_and_headlights_step) % 4
|
||||
can_sends.append(gmcan.create_adas_time_status(CanBus.OBSTACLE, int((tt - self.start_time) * 60), idx))
|
||||
can_sends.append(gmcan.create_adas_headlights_status(self.packer_obj, CanBus.OBSTACLE))
|
||||
|
||||
if self.frame % time_and_headlights_step == 0:
|
||||
idx = (self.frame // time_and_headlights_step) % 4
|
||||
can_sends.append(gmcan.create_adas_time_status(CanBus.OBSTACLE, int((tt - self.start_time) * 60), idx))
|
||||
can_sends.append(gmcan.create_adas_headlights_status(self.packer_obj, CanBus.OBSTACLE))
|
||||
speed_and_accelerometer_step = 2
|
||||
if self.frame % speed_and_accelerometer_step == 0:
|
||||
idx = (self.frame // speed_and_accelerometer_step) % 4
|
||||
can_sends.append(gmcan.create_adas_steering_status(CanBus.OBSTACLE, idx))
|
||||
can_sends.append(gmcan.create_adas_accelerometer_speed_status(CanBus.OBSTACLE, CS.out.vEgo, idx))
|
||||
|
||||
speed_and_accelerometer_step = 2
|
||||
if self.frame % speed_and_accelerometer_step == 0:
|
||||
idx = (self.frame // speed_and_accelerometer_step) % 4
|
||||
can_sends.append(gmcan.create_adas_steering_status(CanBus.OBSTACLE, idx))
|
||||
can_sends.append(gmcan.create_adas_accelerometer_speed_status(CanBus.OBSTACLE, CS.out.vEgo, idx))
|
||||
|
||||
if self.frame % self.params.ADAS_KEEPALIVE_STEP == 0:
|
||||
can_sends += gmcan.create_adas_keepalive(CanBus.POWERTRAIN)
|
||||
if self.CP.networkLocation == NetworkLocation.gateway and self.frame % self.params.ADAS_KEEPALIVE_STEP == 0:
|
||||
can_sends += gmcan.create_adas_keepalive(CanBus.POWERTRAIN)
|
||||
|
||||
# Show green icon when LKA torque is applied, and
|
||||
# alarming orange icon when approaching torque limit.
|
||||
@@ -110,7 +112,7 @@ class CarController:
|
||||
lka_active = CS.lkas_status == 1
|
||||
lka_critical = lka_active and abs(actuators.steer) > 0.9
|
||||
lka_icon_status = (lka_active, lka_critical)
|
||||
if self.frame % self.params.CAMERA_KEEPALIVE_STEP == 0 or lka_icon_status != self.lka_icon_status_last:
|
||||
if self.CP.networkLocation != NetworkLocation.fwdCamera and (self.frame % self.params.CAMERA_KEEPALIVE_STEP == 0 or lka_icon_status != self.lka_icon_status_last):
|
||||
steer_alert = hud_alert in (VisualAlert.steerRequired, VisualAlert.ldw)
|
||||
can_sends.append(gmcan.create_lka_icon_command(CanBus.SW_GMLAN, lka_active, lka_critical, steer_alert))
|
||||
self.lka_icon_status_last = lka_icon_status
|
||||
|
||||
@@ -3,7 +3,9 @@ from common.numpy_fast import mean
|
||||
from opendbc.can.can_define import CANDefine
|
||||
from opendbc.can.parser import CANParser
|
||||
from selfdrive.car.interfaces import CarStateBase
|
||||
from selfdrive.car.gm.values import DBC, CAR, AccState, CanBus, STEER_THRESHOLD
|
||||
from selfdrive.car.gm.values import DBC, AccState, CanBus, STEER_THRESHOLD
|
||||
|
||||
TransmissionType = car.CarParams.TransmissionType
|
||||
|
||||
|
||||
class CarState(CarStateBase):
|
||||
@@ -35,7 +37,7 @@ class CarState(CarStateBase):
|
||||
ret.brakePressed = pt_cp.vl["EBCMBrakePedalPosition"]["BrakePedalPosition"] >= 10
|
||||
|
||||
# Regen braking is braking
|
||||
if self.car_fingerprint == CAR.VOLT:
|
||||
if self.CP.transmissionType == TransmissionType.direct:
|
||||
ret.brakePressed = ret.brakePressed or pt_cp.vl["EBCMRegenPaddle"]["RegenPaddle"] != 0
|
||||
|
||||
ret.gas = pt_cp.vl["AcceleratorPedal2"]["AcceleratorPedal2"] / 254.
|
||||
@@ -120,7 +122,7 @@ class CarState(CarStateBase):
|
||||
("EBCMBrakePedalPosition", 100),
|
||||
]
|
||||
|
||||
if CP.carFingerprint == CAR.VOLT:
|
||||
if CP.transmissionType == TransmissionType.direct:
|
||||
signals.append(("RegenPaddle", "EBCMRegenPaddle"))
|
||||
checks.append(("EBCMRegenPaddle", 50))
|
||||
|
||||
|
||||
@@ -9,6 +9,8 @@ from selfdrive.car.interfaces import CarInterfaceBase
|
||||
|
||||
ButtonType = car.CarState.ButtonEvent.Type
|
||||
EventName = car.CarEvent.EventName
|
||||
TransmissionType = car.CarParams.TransmissionType
|
||||
NetworkLocation = car.CarParams.NetworkLocation
|
||||
BUTTONS_DICT = {CruiseButtons.RES_ACCEL: ButtonType.accelCruise, CruiseButtons.DECEL_SET: ButtonType.decelCruise,
|
||||
CruiseButtons.MAIN: ButtonType.altButton3, CruiseButtons.CANCEL: ButtonType.cancel}
|
||||
|
||||
@@ -45,7 +47,11 @@ class CarInterface(CarInterfaceBase):
|
||||
ret = CarInterfaceBase.get_std_params(candidate, fingerprint)
|
||||
ret.carName = "gm"
|
||||
ret.safetyConfigs = [get_safety_config(car.CarParams.SafetyModel.gm)]
|
||||
ret.pcmCruise = False # stock cruise control is kept off
|
||||
ret.pcmCruise = False # For ASCM, stock non-adaptive cruise control is kept off
|
||||
ret.radarOffCan = False # For ASCM, radar exists
|
||||
ret.transmissionType = TransmissionType.automatic
|
||||
# NetworkLocation.gateway: OBD-II harness (typically ASCM), NetworkLocation.fwdCamera: non-ASCM
|
||||
ret.networkLocation = NetworkLocation.gateway
|
||||
|
||||
# These cars have been put into dashcam only due to both a lack of users and test coverage.
|
||||
# These cars likely still work fine. Once a user confirms each car works and a test route is
|
||||
@@ -77,17 +83,18 @@ class CarInterface(CarInterfaceBase):
|
||||
ret.minEnableSpeed = 18 * CV.MPH_TO_MS
|
||||
|
||||
if candidate == CAR.VOLT:
|
||||
ret.transmissionType = TransmissionType.direct
|
||||
ret.mass = 1607. + STD_CARGO_KG
|
||||
ret.wheelbase = 2.69
|
||||
ret.steerRatio = 17.7 # Stock 15.7, LiveParameters
|
||||
tire_stiffness_factor = 0.469 # Stock Michelin Energy Saver A/S, LiveParameters
|
||||
ret.centerToFront = ret.wheelbase * 0.45 # Volt Gen 1, TODO corner weigh
|
||||
tire_stiffness_factor = 0.469 # Stock Michelin Energy Saver A/S, LiveParameters
|
||||
ret.centerToFront = ret.wheelbase * 0.45 # Volt Gen 1, TODO corner weigh
|
||||
|
||||
ret.lateralTuning.pid.kpBP = [0., 40.]
|
||||
ret.lateralTuning.pid.kpV = [0., 0.17]
|
||||
ret.lateralTuning.pid.kiBP = [0.]
|
||||
ret.lateralTuning.pid.kiV = [0.]
|
||||
ret.lateralTuning.pid.kf = 1. # get_steer_feedforward_volt()
|
||||
ret.lateralTuning.pid.kf = 1. # get_steer_feedforward_volt()
|
||||
ret.steerActuatorDelay = 0.2
|
||||
|
||||
elif candidate == CAR.MALIBU:
|
||||
@@ -160,7 +167,7 @@ class CarInterface(CarInterfaceBase):
|
||||
|
||||
ret.buttonEvents = [be]
|
||||
|
||||
events = self.create_common_events(ret, pcm_enable=False)
|
||||
events = self.create_common_events(ret, pcm_enable=self.CP.pcmCruise)
|
||||
|
||||
if ret.vEgo < self.CP.minEnableSpeed:
|
||||
events.add(EventName.belowEngageSpeed)
|
||||
@@ -170,7 +177,7 @@ class CarInterface(CarInterfaceBase):
|
||||
events.add(car.CarEvent.EventName.belowSteerSpeed)
|
||||
|
||||
# handle button presses
|
||||
events.events.extend(create_button_enable_events(ret.buttonEvents))
|
||||
events.events.extend(create_button_enable_events(ret.buttonEvents, pcm_cruise=self.CP.pcmCruise))
|
||||
|
||||
ret.events = events.to_msg()
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
a98dfc72bb4c5624c2223ca65d52b151f419460c
|
||||
d7c610172f3ff10b68403abc19b260c91c848ebb
|
||||
Reference in New Issue
Block a user