CC longitudinal control

Co-Authored-By: Eric Brown <13560103+nworb-cire@users.noreply.github.com>
This commit is contained in:
FrogAi
2024-02-27 16:34:47 -07:00
parent 4b511bb036
commit c7de259c83
6 changed files with 112 additions and 19 deletions

View File

@@ -10,6 +10,8 @@ from openpilot.selfdrive.car.gm.values import DBC, CanBus, CarControllerParams,
VisualAlert = car.CarControl.HUDControl.VisualAlert
NetworkLocation = car.CarParams.NetworkLocation
LongCtrlState = car.CarControl.Actuators.LongControlState
GearShifter = car.CarState.GearShifter
TransmissionType = car.CarParams.TransmissionType
# Camera cancels up to 0.1s after brake is pressed, ECM allows 0.5s
CAMERA_CANCEL_DELAY_FRAMES = 10
@@ -24,10 +26,12 @@ class CarController:
self.apply_steer_last = 0
self.apply_gas = 0
self.apply_brake = 0
self.apply_speed = 0
self.frame = 0
self.last_steer_frame = 0
self.last_button_frame = 0
self.cancel_counter = 0
self.pedal_steady = 0.
self.lka_steering_cmd_counter = 0
self.lka_icon_status_last = (False, False)
@@ -107,6 +111,10 @@ class CarController:
at_full_stop = CC.longActive and CS.out.standstill
near_stop = CC.longActive and (CS.out.vEgo < self.params.NEAR_STOP_BRAKE_PHASE)
if self.CP.flags & GMFlags.CC_LONG.value:
if CC.longActive and CS.out.vEgo > self.CP.minEnableSpeed:
# Using extend instead of append since the message is only sent intermittently
can_sends.extend(gmcan.create_gm_cc_spam_command(self.packer_pt, self, CS, actuators))
if self.CP.carFingerprint not in CC_ONLY_CAR:
friction_brake_bus = CanBus.CHASSIS
# GM Camera exceptions
@@ -168,6 +176,7 @@ class CarController:
new_actuators.steerOutputCan = self.apply_steer_last
new_actuators.gas = self.apply_gas
new_actuators.brake = self.apply_brake
new_actuators.speed = self.apply_speed
self.frame += 1
return new_actuators, can_sends

View File

@@ -1,5 +1,9 @@
import math
from openpilot.common.conversions import Conversions as CV
from openpilot.common.realtime import DT_CTRL
from openpilot.selfdrive.car import make_can_msg
from openpilot.selfdrive.car.gm.values import CAR
from openpilot.selfdrive.car.gm.values import CAR, CruiseButtons, CanBus
def create_buttons(packer, bus, idx, button):
@@ -171,3 +175,45 @@ def create_lka_icon_command(bus, active, critical, steer):
else:
dat = b"\x00\x00\x00"
return make_can_msg(0x104c006c, dat, bus)
def create_gm_cc_spam_command(packer, controller, CS, actuators):
# TODO: Cleanup the timing - normal is every 30ms...
cruiseBtn = CruiseButtons.INIT
# if controller.params_.get_bool("IsMetric"):
# accel = actuators.accel * CV.MS_TO_KPH # m/s/s to km/h/s
# else:
# accel = actuators.accel * CV.MS_TO_MPH # m/s/s to mph/s
accel = actuators.accel * CV.MS_TO_MPH # m/s/s to mph/s
speedSetPoint = int(round(CS.out.cruiseState.speed * CV.MS_TO_MPH))
RATE_UP_MAX = 0.2 # may be lower on new/euro cars
RATE_DOWN_MAX = 0.2 # may be lower on new/euro cars
if speedSetPoint == CS.CP.minEnableSpeed and accel < -1:
cruiseBtn = CruiseButtons.CANCEL
controller.apply_speed = 0
rate = 0.04
elif accel < 0:
cruiseBtn = CruiseButtons.DECEL_SET
rate = max(-1 / accel, RATE_DOWN_MAX)
controller.apply_speed = speedSetPoint - 1
elif accel > 0:
cruiseBtn = CruiseButtons.RES_ACCEL
rate = max(1 / accel, RATE_UP_MAX)
controller.apply_speed = speedSetPoint + 1
else:
controller.apply_speed = speedSetPoint
rate = float('inf')
# Check rlogs closely - our message shouldn't show up on the pt bus for us
# Or bus 2, since we're forwarding... but I think it does
# TODO: Cleanup the timing - normal is every 30ms...
if (cruiseBtn != CruiseButtons.INIT) and ((controller.frame - controller.last_button_frame) * DT_CTRL > rate):
controller.last_button_frame = controller.frame
idx = (CS.buttons_counter + 1) % 4 # Need to predict the next idx for '22-23 EUV
return [create_buttons(packer, CanBus.POWERTRAIN, idx, cruiseBtn)]
else:
return []

View File

@@ -107,7 +107,7 @@ class CarInterface(CarInterfaceBase):
ret.longitudinalTuning.kiBP = [0.]
if candidate in CAMERA_ACC_CAR:
ret.experimentalLongitudinalAvailable = True
ret.experimentalLongitudinalAvailable = candidate not in CC_ONLY_CAR
ret.networkLocation = NetworkLocation.fwdCamera
ret.radarUnavailable = True # no radar
ret.pcmCruise = True
@@ -316,6 +316,26 @@ class CarInterface(CarInterfaceBase):
ret.steerRatio = 17.7
CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning)
elif candidate in CC_ONLY_CAR:
ret.flags |= GMFlags.CC_LONG.value
ret.safetyConfigs[0].safetyParam |= Panda.FLAG_GM_CC_LONG
ret.radarUnavailable = True
ret.experimentalLongitudinalAvailable = False
ret.minEnableSpeed = 24 * CV.MPH_TO_MS
ret.openpilotLongitudinalControl = True
ret.pcmCruise = False
ret.longitudinalTuning.deadzoneBP = [0.]
ret.longitudinalTuning.deadzoneV = [0.56] # == 2 km/h/s, 1.25 mph/s
ret.stoppingDecelRate = 11.18 # == 25 mph/s (.04 rate)
ret.longitudinalActuatorDelayLowerBound = 1. # TODO: measure this
ret.longitudinalActuatorDelayUpperBound = 2.
ret.longitudinalTuning.kpBP = [10.7, 10.8, 28.] # 10.7 m/s == 24 mph
ret.longitudinalTuning.kpV = [0., 20., 20.] # set lower end to 0 since we can't drive below that speed
ret.longitudinalTuning.kiBP = [0.]
ret.longitudinalTuning.kiV = [0.1]
if candidate in CC_ONLY_CAR:
ret.safetyConfigs[0].safetyParam |= Panda.FLAG_GM_NO_ACC
@@ -352,6 +372,9 @@ class CarInterface(CarInterfaceBase):
if ret.vEgo < self.CP.minSteerSpeed:
events.add(EventName.belowSteerSpeed)
if (self.CP.flags & GMFlags.CC_LONG.value) and ret.vEgo < self.CP.minEnableSpeed and ret.cruiseState.enabled:
events.add(EventName.speedTooLow)
ret.events = events.to_msg()
return ret

View File

@@ -179,6 +179,7 @@ class CanBus:
DROPPED = 192
class GMFlags(IntFlag):
CC_LONG = 2
NO_ACCELERATOR_POS_MSG = 8