open source driving agent
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

148 lines
6.6 KiB

6 years ago
from cereal import car
from opendbc.can.packer import CANPacker
from common.numpy_fast import clip
from common.conversions import Conversions as CV
6 years ago
from selfdrive.car import apply_std_steer_torque_limits
from selfdrive.car.volkswagen import mqbcan
from selfdrive.car.volkswagen.values import CANBUS, CarControllerParams
6 years ago
VisualAlert = car.CarControl.HUDControl.VisualAlert
4 years ago
LongCtrlState = car.CarControl.Actuators.LongControlState
6 years ago
class CarController:
def __init__(self, dbc_name, CP, VM):
self.CP = CP
self.CCP = CarControllerParams(CP)
self.CCS = mqbcan
self.packer_pt = CANPacker(dbc_name)
6 years ago
self.apply_steer_last = 0
self.frame = 0
6 years ago
self.hcaSameTorqueCount = 0
self.hcaEnabledFrameCount = 0
self.acc_starting = False
self.acc_stopping = False
6 years ago
def update(self, CC, CS, ext_bus):
actuators = CC.actuators
hud_control = CC.hudControl
6 years ago
can_sends = []
4 years ago
# **** Acceleration and Braking Controls ******************************** #
if CS.CP.openpilotLongitudinalControl:
if self.frame % self.CCP.ACC_CONTROL_STEP == 0:
if CS.tsk_status in [2, 3, 4, 5]:
acc_status = 3 if CC.longActive else 2
else:
acc_status = CS.tsk_status
accel = clip(actuators.accel, self.CCP.ACCEL_MIN, self.CCP.ACCEL_MAX) if CC.longActive else 0
# FIXME: this needs to become a proper state machine
acc_hold_request, acc_hold_release, acc_hold_type, stopping_distance = False, False, 0, 20.46
if actuators.longControlState == LongCtrlState.stopping and CS.out.vEgo < 0.2:
self.acc_stopping = True
4 years ago
acc_hold_request = True
if CS.out.cruiseState.standstill:
acc_hold_type = 1 # hold
stopping_distance = 3.5
else:
acc_hold_type = 3 # hold_standby
stopping_distance = 0.5
elif CC.longActive:
if self.acc_stopping:
self.acc_starting = True
self.acc_stopping = False
self.acc_starting &= CS.out.vEgo < 1.5
acc_hold_release = self.acc_starting
4 years ago
acc_hold_type = 4 if self.acc_starting and CS.out.vEgo < 0.1 else 0 # startup
else:
self.acc_stopping, self.acc_starting = False, False
4 years ago
3 years ago
cb_pos = 0.0 if hud_control.leadVisible or CS.out.vEgo < 2.0 else 0.1 # react faster to lead cars, also don't get hung up at DSG clutch release/kiss points when creeping to stop
cb_neg = 0.0 if accel < 0 else 0.2 # IDK why, but stock likes to zero this out when accel is negative
4 years ago
can_sends.append(self.CCS.create_acc_06_control(self.packer_pt, CANBUS.pt, CC.longActive, acc_status,
4 years ago
accel, self.acc_stopping, self.acc_starting,
cb_pos, cb_neg, CS.acc_type))
can_sends.append(self.CCS.create_acc_07_control(self.packer_pt, CANBUS.pt, CC.longActive,
accel, acc_hold_request, acc_hold_release,
acc_hold_type, stopping_distance))
4 years ago
if self.frame % self.CCP.ACC_HUD_STEP == 0:
3 years ago
if hud_control.leadVisible:
lead_distance = 512 if CS.digital_cluster_installed else 8 # TODO: look up actual distance to lead
else:
lead_distance = 0
can_sends.append(self.CCS.create_acc_02_control(self.packer_pt, CANBUS.pt, CS.tsk_status,
hud_control.set_speed * CV.MS_TO_KPH, lead_distance))
can_sends.append(self.CCS.create_acc_04_control(self.packer_pt, CANBUS.pt, CS.acc_04_stock_values))
# **** Steering Controls ************************************************ #
if self.frame % self.CCP.HCA_STEP == 0:
# Logic to avoid HCA state 4 "refused":
# * Don't steer unless HCA is in state 3 "ready" or 5 "active"
# * Don't steer at standstill
# * Don't send > 3.00 Newton-meters torque
# * Don't send the same torque for > 6 seconds
# * Don't send uninterrupted steering for > 360 seconds
# One frame of HCA disabled is enough to reset the timer, without zeroing the
# torque value. Do that anytime we happen to have 0 torque, or failing that,
# when exceeding ~1/3 the 360 second timer.
6 years ago
if CC.latActive:
new_steer = int(round(actuators.steer * self.CCP.STEER_MAX))
apply_steer = apply_std_steer_torque_limits(new_steer, self.apply_steer_last, CS.out.steeringTorque, self.CCP)
6 years ago
if apply_steer == 0:
hcaEnabled = False
self.hcaEnabledFrameCount = 0
else:
self.hcaEnabledFrameCount += 1
if self.hcaEnabledFrameCount >= 118 * (100 / self.CCP.HCA_STEP): # 118s
6 years ago
hcaEnabled = False
self.hcaEnabledFrameCount = 0
else:
hcaEnabled = True
if self.apply_steer_last == apply_steer:
self.hcaSameTorqueCount += 1
if self.hcaSameTorqueCount > 1.9 * (100 / self.CCP.HCA_STEP): # 1.9s
6 years ago
apply_steer -= (1, -1)[apply_steer < 0]
self.hcaSameTorqueCount = 0
else:
self.hcaSameTorqueCount = 0
else:
hcaEnabled = False
apply_steer = 0
self.apply_steer_last = apply_steer
can_sends.append(self.CCS.create_steering_control(self.packer_pt, CANBUS.pt, apply_steer, hcaEnabled))
6 years ago
# **** HUD Controls ***************************************************** #
6 years ago
if self.frame % self.CCP.LDW_STEP == 0:
hud_alert = 0
if hud_control.visualAlert in (VisualAlert.steerRequired, VisualAlert.ldw):
hud_alert = self.CCP.LDW_MESSAGES["laneAssistTakeOver"]
can_sends.append(self.CCS.create_lka_hud_control(self.packer_pt, CANBUS.pt, CS.ldw_stock_values, CC.enabled,
CS.out.steeringPressed, hud_alert, hud_control))
6 years ago
# **** Stock ACC Button Controls **************************************** #
6 years ago
if self.CP.pcmCruise and self.frame % self.CCP.GRA_ACC_STEP == 0:
idx = (CS.gra_stock_values["COUNTER"] + 1) % 16
if CC.cruiseControl.cancel:
can_sends.append(self.CCS.create_acc_buttons_control(self.packer_pt, ext_bus, CS.gra_stock_values, idx, cancel=True))
elif CC.cruiseControl.resume:
can_sends.append(self.CCS.create_acc_buttons_control(self.packer_pt, ext_bus, CS.gra_stock_values, idx, resume=True))
6 years ago
new_actuators = actuators.copy()
new_actuators.steer = self.apply_steer_last / self.CCP.STEER_MAX
self.frame += 1
return new_actuators, can_sends