openpilot is an open source driver assistance system. openpilot performs the functions of Automated Lane Centering and Adaptive Cruise Control for over 200 supported car makes and models.
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.

90 lines
3.3 KiB

5 years ago
from cereal import car
from common.numpy_fast import clip, interp
from opendbc.can.packer import CANPacker
from selfdrive.car.ford import fordcan
from selfdrive.car.ford.values import CarControllerParams
5 years ago
VisualAlert = car.CarControl.HUDControl.VisualAlert
5 years ago
def apply_ford_steer_angle_limits(apply_steer, apply_steer_last, vEgo):
# rate limit
steer_up = apply_steer * apply_steer_last > 0. and abs(apply_steer) > abs(apply_steer_last)
rate_limit = CarControllerParams.STEER_RATE_LIMIT_UP if steer_up else CarControllerParams.STEER_RATE_LIMIT_DOWN
max_angle_diff = interp(vEgo, rate_limit.speed_points, rate_limit.max_angle_diff_points)
apply_steer = clip(apply_steer, (apply_steer_last - max_angle_diff), (apply_steer_last + max_angle_diff))
return apply_steer
5 years ago
class CarController:
def __init__(self, dbc_name, CP, VM):
self.CP = CP
self.VM = VM
5 years ago
self.packer = CANPacker(dbc_name)
self.frame = 0
self.apply_steer_last = 0
5 years ago
self.main_on_last = False
self.lkas_enabled_last = False
5 years ago
self.steer_alert_last = False
def update(self, CC, CS):
5 years ago
can_sends = []
actuators = CC.actuators
hud_control = CC.hudControl
5 years ago
main_on = CS.out.cruiseState.available
steer_alert = hud_control.visualAlert in (VisualAlert.steerRequired, VisualAlert.ldw)
5 years ago
if CC.cruiseControl.cancel:
# cancel stock ACC
can_sends.append(fordcan.spam_cancel_button(self.packer))
5 years ago
# apply rate limits
new_steer = actuators.steeringAngleDeg
apply_steer = apply_ford_steer_angle_limits(new_steer, self.apply_steer_last, CS.out.vEgo)
5 years ago
# send steering commands at 20Hz
if (self.frame % CarControllerParams.LKAS_STEER_STEP) == 0:
lca_rq = 1 if CC.latActive else 0
5 years ago
# use LatCtlPath_An_Actl to actuate steering for now until curvature control is implemented
path_angle = apply_steer
5 years ago
# convert steer angle to curvature
curvature = self.VM.calc_curvature(apply_steer, CS.out.vEgo, 0.0)
5 years ago
# TODO: get other actuators
curvature_rate = 0
path_offset = 0
5 years ago
ramp_type = 3 # 0=Slow, 1=Medium, 2=Fast, 3=Immediately
precision = 0 # 0=Comfortable, 1=Precise
5 years ago
self.apply_steer_last = apply_steer
can_sends.append(fordcan.create_lkas_command(self.packer, apply_steer, curvature))
can_sends.append(fordcan.create_tja_command(self.packer, lca_rq, ramp_type, precision,
path_offset, path_angle, curvature_rate, curvature))
5 years ago
send_ui = (self.main_on_last != main_on) or (self.lkas_enabled_last != CC.latActive) or (self.steer_alert_last != steer_alert)
5 years ago
# send lkas ui command at 1Hz or if ui state changes
if (self.frame % CarControllerParams.LKAS_UI_STEP) == 0 or send_ui:
can_sends.append(fordcan.create_lkas_ui_command(self.packer, main_on, CC.latActive, steer_alert, CS.lkas_status_stock_values))
5 years ago
# send acc ui command at 20Hz or if ui state changes
if (self.frame % CarControllerParams.ACC_UI_STEP) == 0 or send_ui:
can_sends.append(fordcan.create_acc_ui_command(self.packer, main_on, CC.latActive, CS.acc_tja_status_stock_values))
5 years ago
self.main_on_last = main_on
self.lkas_enabled_last = CC.latActive
self.steer_alert_last = steer_alert
5 years ago
new_actuators = actuators.copy()
new_actuators.steeringAngleDeg = apply_steer
self.frame += 1
return new_actuators, can_sends