Tesla AP2 port (#20074)
* squashed the PR * remove AP passthrough * disengage on steer override * bump panda * add test routes * bump panda * tesla is still dashcam only * dashcam only * rerun CI * add to release filespull/21385/head
parent
7e6a9ce9a5
commit
cdfba105ed
11 changed files with 410 additions and 2 deletions
@ -1 +1 @@ |
|||||||
Subproject commit d7b3ae02824fe67f88ee408e0d7540c1ec5bceab |
Subproject commit d8385413c3ecc59799f0909c7384f385a71c4431 |
@ -0,0 +1,53 @@ |
|||||||
|
from common.numpy_fast import clip, interp |
||||||
|
from selfdrive.car.tesla.teslacan import TeslaCAN |
||||||
|
from opendbc.can.packer import CANPacker |
||||||
|
from selfdrive.car.tesla.values import CANBUS, CarControllerParams |
||||||
|
|
||||||
|
class CarController(): |
||||||
|
def __init__(self, dbc_name, CP, VM): |
||||||
|
self.CP = CP |
||||||
|
self.last_angle = 0 |
||||||
|
self.packer = CANPacker(dbc_name) |
||||||
|
self.tesla_can = TeslaCAN(dbc_name, self.packer) |
||||||
|
|
||||||
|
def update(self, enabled, CS, frame, actuators, cruise_cancel): |
||||||
|
can_sends = [] |
||||||
|
|
||||||
|
# Temp disable steering on a hands_on_fault, and allow for user override |
||||||
|
hands_on_fault = (CS.steer_warning == "EAC_ERROR_HANDS_ON" and CS.hands_on_level >= 3) |
||||||
|
lkas_enabled = enabled and (not hands_on_fault) |
||||||
|
|
||||||
|
if lkas_enabled: |
||||||
|
apply_angle = actuators.steeringAngleDeg |
||||||
|
|
||||||
|
# Angular rate limit based on speed |
||||||
|
steer_up = (self.last_angle * apply_angle > 0. and abs(apply_angle) > abs(self.last_angle)) |
||||||
|
rate_limit = CarControllerParams.RATE_LIMIT_UP if steer_up else CarControllerParams.RATE_LIMIT_DOWN |
||||||
|
max_angle_diff = interp(CS.out.vEgo, rate_limit.speed_points, rate_limit.max_angle_diff_points) |
||||||
|
apply_angle = clip(apply_angle, (self.last_angle - max_angle_diff), (self.last_angle + max_angle_diff)) |
||||||
|
|
||||||
|
# To not fault the EPS |
||||||
|
apply_angle = clip(apply_angle, (CS.out.steeringAngleDeg - 20), (CS.out.steeringAngleDeg + 20)) |
||||||
|
else: |
||||||
|
apply_angle = CS.out.steeringAngleDeg |
||||||
|
|
||||||
|
self.last_angle = apply_angle |
||||||
|
can_sends.append(self.tesla_can.create_steering_control(apply_angle, lkas_enabled, frame)) |
||||||
|
|
||||||
|
# Cancel on user steering override, since there is no steering torque blending |
||||||
|
if hands_on_fault: |
||||||
|
cruise_cancel = True |
||||||
|
|
||||||
|
# Cancel when openpilot is not enabled anymore |
||||||
|
if not enabled and bool(CS.out.cruiseState.enabled): |
||||||
|
cruise_cancel = True |
||||||
|
|
||||||
|
if ((frame % 10) == 0 and cruise_cancel): |
||||||
|
# Spam every possible counter value, otherwise it might not be accepted |
||||||
|
for counter in range(16): |
||||||
|
can_sends.append(self.tesla_can.create_action_request(CS.msg_stw_actn_req, cruise_cancel, CANBUS.chassis, counter)) |
||||||
|
can_sends.append(self.tesla_can.create_action_request(CS.msg_stw_actn_req, cruise_cancel, CANBUS.autopilot, counter)) |
||||||
|
|
||||||
|
# TODO: HUD control |
||||||
|
|
||||||
|
return can_sends |
@ -0,0 +1,181 @@ |
|||||||
|
import copy |
||||||
|
from cereal import car |
||||||
|
from selfdrive.car.tesla.values import DBC, CANBUS, GEAR_MAP, DOORS, BUTTONS |
||||||
|
from selfdrive.car.interfaces import CarStateBase |
||||||
|
from opendbc.can.parser import CANParser |
||||||
|
from opendbc.can.can_define import CANDefine |
||||||
|
from selfdrive.config import Conversions as CV |
||||||
|
|
||||||
|
class CarState(CarStateBase): |
||||||
|
def __init__(self, CP): |
||||||
|
super().__init__(CP) |
||||||
|
self.button_states = {button.event_type: False for button in BUTTONS} |
||||||
|
self.can_define = CANDefine(DBC[CP.carFingerprint]['chassis']) |
||||||
|
|
||||||
|
# Needed by carcontroller |
||||||
|
self.msg_stw_actn_req = None |
||||||
|
self.hands_on_level = 0 |
||||||
|
self.steer_warning = None |
||||||
|
|
||||||
|
def update(self, cp, cp_cam): |
||||||
|
ret = car.CarState.new_message() |
||||||
|
|
||||||
|
# Vehicle speed |
||||||
|
ret.vEgoRaw = cp.vl["ESP_B"]["ESP_vehicleSpeed"] * CV.KPH_TO_MS |
||||||
|
ret.vEgo, ret.aEgo = self.update_speed_kf(ret.vEgoRaw) |
||||||
|
ret.standstill = (ret.vEgo < 0.1) |
||||||
|
|
||||||
|
# Gas pedal |
||||||
|
ret.gas = cp.vl["DI_torque1"]["DI_pedalPos"] / 100.0 |
||||||
|
ret.gasPressed = (ret.gas > 0) |
||||||
|
|
||||||
|
# Brake pedal |
||||||
|
ret.brake = 0 |
||||||
|
ret.brakePressed = bool(cp.vl["BrakeMessage"]["driverBrakeStatus"] != 1) |
||||||
|
|
||||||
|
# Steering wheel |
||||||
|
self.hands_on_level = cp.vl["EPAS_sysStatus"]["EPAS_handsOnLevel"] |
||||||
|
self.steer_warning = self.can_define.dv["EPAS_sysStatus"]["EPAS_eacErrorCode"].get(int(cp.vl["EPAS_sysStatus"]["EPAS_eacErrorCode"]), None) |
||||||
|
steer_status = self.can_define.dv["EPAS_sysStatus"]["EPAS_eacStatus"].get(int(cp.vl["EPAS_sysStatus"]["EPAS_eacStatus"]), None) |
||||||
|
|
||||||
|
ret.steeringAngleDeg = -cp.vl["EPAS_sysStatus"]["EPAS_internalSAS"] |
||||||
|
ret.steeringRateDeg = -cp.vl["STW_ANGLHP_STAT"]["StW_AnglHP_Spd"] # This is from a different angle sensor, and at different rate |
||||||
|
ret.steeringTorque = -cp.vl["EPAS_sysStatus"]["EPAS_torsionBarTorque"] |
||||||
|
ret.steeringPressed = (self.hands_on_level > 0) |
||||||
|
ret.steerError = steer_status in ["EAC_FAULT", "EAC_INHIBITED"] |
||||||
|
ret.steerWarning = self.steer_warning in ["EAC_ERROR_MAX_SPEED", "EAC_ERROR_MIN_SPEED", "EAC_ERROR_TMP_FAULT", "SNA"] # TODO: not sure if this list is complete |
||||||
|
|
||||||
|
# Cruise state |
||||||
|
cruise_state = self.can_define.dv["DI_state"]["DI_cruiseState"].get(int(cp.vl["DI_state"]["DI_cruiseState"]), None) |
||||||
|
speed_units = self.can_define.dv["DI_state"]["DI_speedUnits"].get(int(cp.vl["DI_state"]["DI_speedUnits"]), None) |
||||||
|
|
||||||
|
acc_enabled = (cruise_state in ["ENABLED", "STANDSTILL", "OVERRIDE", "PRE_FAULT", "PRE_CANCEL"]) |
||||||
|
|
||||||
|
ret.cruiseState.enabled = acc_enabled |
||||||
|
if speed_units == "KPH": |
||||||
|
ret.cruiseState.speed = cp.vl["DI_state"]["DI_digitalSpeed"] * CV.KPH_TO_MS |
||||||
|
elif speed_units == "MPH": |
||||||
|
ret.cruiseState.speed = cp.vl["DI_state"]["DI_digitalSpeed"] * CV.MPH_TO_MS |
||||||
|
ret.cruiseState.available = ((cruise_state == "STANDBY") or ret.cruiseState.enabled) |
||||||
|
ret.cruiseState.standstill = (cruise_state == "STANDSTILL") |
||||||
|
|
||||||
|
# Gear |
||||||
|
ret.gearShifter = GEAR_MAP[self.can_define.dv["DI_torque2"]["DI_gear"].get(int(cp.vl["DI_torque2"]["DI_gear"]), "DI_GEAR_INVALID")] |
||||||
|
|
||||||
|
# Buttons |
||||||
|
buttonEvents = [] |
||||||
|
for button in BUTTONS: |
||||||
|
state = (cp.vl[button.can_addr][button.can_msg] in button.values) |
||||||
|
if self.button_states[button.event_type] != state: |
||||||
|
event = car.CarState.ButtonEvent.new_message() |
||||||
|
event.type = button.event_type |
||||||
|
event.pressed = state |
||||||
|
buttonEvents.append(event) |
||||||
|
self.button_states[button.event_type] = state |
||||||
|
ret.buttonEvents = buttonEvents |
||||||
|
|
||||||
|
# Doors |
||||||
|
ret.doorOpen = any([(self.can_define.dv["GTW_carState"][door].get(int(cp.vl["GTW_carState"][door]), "OPEN") == "OPEN") for door in DOORS]) |
||||||
|
|
||||||
|
# Blinkers |
||||||
|
ret.leftBlinker = (cp.vl["GTW_carState"]["BC_indicatorLStatus"] == 1) |
||||||
|
ret.rightBlinker = (cp.vl["GTW_carState"]["BC_indicatorRStatus"] == 1) |
||||||
|
|
||||||
|
# Seatbelt |
||||||
|
ret.seatbeltUnlatched = (cp.vl["SDM1"]["SDM_bcklDrivStatus"] != 1) |
||||||
|
|
||||||
|
# TODO: blindspot |
||||||
|
|
||||||
|
# Messages needed by carcontroller |
||||||
|
self.msg_stw_actn_req = copy.copy(cp.vl["STW_ACTN_RQ"]) |
||||||
|
|
||||||
|
return ret |
||||||
|
|
||||||
|
@staticmethod |
||||||
|
def get_can_parser(CP): |
||||||
|
signals = [ |
||||||
|
# sig_name, sig_address, default |
||||||
|
("ESP_vehicleSpeed", "ESP_B", 0), |
||||||
|
("DI_pedalPos", "DI_torque1", 0), |
||||||
|
("DI_brakePedal", "DI_torque2", 0), |
||||||
|
("StW_AnglHP", "STW_ANGLHP_STAT", 0), |
||||||
|
("StW_AnglHP_Spd", "STW_ANGLHP_STAT", 0), |
||||||
|
("EPAS_handsOnLevel", "EPAS_sysStatus", 0), |
||||||
|
("EPAS_torsionBarTorque", "EPAS_sysStatus", 0), |
||||||
|
("EPAS_internalSAS", "EPAS_sysStatus", 0), |
||||||
|
("EPAS_eacStatus", "EPAS_sysStatus", 1), |
||||||
|
("EPAS_eacErrorCode", "EPAS_sysStatus", 0), |
||||||
|
("DI_cruiseState", "DI_state", 0), |
||||||
|
("DI_digitalSpeed", "DI_state", 0), |
||||||
|
("DI_speedUnits", "DI_state", 0), |
||||||
|
("DI_gear", "DI_torque2", 0), |
||||||
|
("DOOR_STATE_FL", "GTW_carState", 1), |
||||||
|
("DOOR_STATE_FR", "GTW_carState", 1), |
||||||
|
("DOOR_STATE_RL", "GTW_carState", 1), |
||||||
|
("DOOR_STATE_RR", "GTW_carState", 1), |
||||||
|
("DOOR_STATE_FrontTrunk", "GTW_carState", 1), |
||||||
|
("BOOT_STATE", "GTW_carState", 1), |
||||||
|
("BC_indicatorLStatus", "GTW_carState", 1), |
||||||
|
("BC_indicatorRStatus", "GTW_carState", 1), |
||||||
|
("SDM_bcklDrivStatus", "SDM1", 0), |
||||||
|
("driverBrakeStatus", "BrakeMessage", 0), |
||||||
|
|
||||||
|
# We copy this whole message when spamming cancel |
||||||
|
("SpdCtrlLvr_Stat", "STW_ACTN_RQ", 0), |
||||||
|
("VSL_Enbl_Rq", "STW_ACTN_RQ", 0), |
||||||
|
("SpdCtrlLvrStat_Inv", "STW_ACTN_RQ", 0), |
||||||
|
("DTR_Dist_Rq", "STW_ACTN_RQ", 0), |
||||||
|
("TurnIndLvr_Stat", "STW_ACTN_RQ", 0), |
||||||
|
("HiBmLvr_Stat", "STW_ACTN_RQ", 0), |
||||||
|
("WprWashSw_Psd", "STW_ACTN_RQ", 0), |
||||||
|
("WprWash_R_Sw_Posn_V2", "STW_ACTN_RQ", 0), |
||||||
|
("StW_Lvr_Stat", "STW_ACTN_RQ", 0), |
||||||
|
("StW_Cond_Flt", "STW_ACTN_RQ", 0), |
||||||
|
("StW_Cond_Psd", "STW_ACTN_RQ", 0), |
||||||
|
("HrnSw_Psd", "STW_ACTN_RQ", 0), |
||||||
|
("StW_Sw00_Psd", "STW_ACTN_RQ", 0), |
||||||
|
("StW_Sw01_Psd", "STW_ACTN_RQ", 0), |
||||||
|
("StW_Sw02_Psd", "STW_ACTN_RQ", 0), |
||||||
|
("StW_Sw03_Psd", "STW_ACTN_RQ", 0), |
||||||
|
("StW_Sw04_Psd", "STW_ACTN_RQ", 0), |
||||||
|
("StW_Sw05_Psd", "STW_ACTN_RQ", 0), |
||||||
|
("StW_Sw06_Psd", "STW_ACTN_RQ", 0), |
||||||
|
("StW_Sw07_Psd", "STW_ACTN_RQ", 0), |
||||||
|
("StW_Sw08_Psd", "STW_ACTN_RQ", 0), |
||||||
|
("StW_Sw09_Psd", "STW_ACTN_RQ", 0), |
||||||
|
("StW_Sw10_Psd", "STW_ACTN_RQ", 0), |
||||||
|
("StW_Sw11_Psd", "STW_ACTN_RQ", 0), |
||||||
|
("StW_Sw12_Psd", "STW_ACTN_RQ", 0), |
||||||
|
("StW_Sw13_Psd", "STW_ACTN_RQ", 0), |
||||||
|
("StW_Sw14_Psd", "STW_ACTN_RQ", 0), |
||||||
|
("StW_Sw15_Psd", "STW_ACTN_RQ", 0), |
||||||
|
("WprSw6Posn", "STW_ACTN_RQ", 0), |
||||||
|
("MC_STW_ACTN_RQ", "STW_ACTN_RQ", 0), |
||||||
|
("CRC_STW_ACTN_RQ", "STW_ACTN_RQ", 0), |
||||||
|
] |
||||||
|
|
||||||
|
checks = [ |
||||||
|
# sig_address, frequency |
||||||
|
("ESP_B", 50), |
||||||
|
("DI_torque1", 100), |
||||||
|
("DI_torque2", 100), |
||||||
|
("STW_ANGLHP_STAT", 100), |
||||||
|
("EPAS_sysStatus", 25), |
||||||
|
("DI_state", 10), |
||||||
|
("STW_ACTN_RQ", 10), |
||||||
|
("GTW_carState", 10), |
||||||
|
("SDM1", 10), |
||||||
|
("BrakeMessage", 50), |
||||||
|
] |
||||||
|
|
||||||
|
return CANParser(DBC[CP.carFingerprint]['chassis'], signals, checks, CANBUS.chassis) |
||||||
|
|
||||||
|
@staticmethod |
||||||
|
def get_cam_can_parser(CP): |
||||||
|
signals = [ |
||||||
|
# sig_name, sig_address, default |
||||||
|
] |
||||||
|
checks = [ |
||||||
|
# sig_address, frequency |
||||||
|
] |
||||||
|
return CANParser(DBC[CP.carFingerprint]['chassis'], signals, checks, CANBUS.autopilot) |
@ -0,0 +1,62 @@ |
|||||||
|
#!/usr/bin/env python3 |
||||||
|
from cereal import car |
||||||
|
from selfdrive.car.tesla.values import CAR |
||||||
|
from selfdrive.car import STD_CARGO_KG, gen_empty_fingerprint, scale_rot_inertia, scale_tire_stiffness |
||||||
|
from selfdrive.car.interfaces import CarInterfaceBase |
||||||
|
|
||||||
|
|
||||||
|
class CarInterface(CarInterfaceBase): |
||||||
|
@staticmethod |
||||||
|
def compute_gb(accel, speed): |
||||||
|
# TODO: is this correct? |
||||||
|
return accel |
||||||
|
|
||||||
|
@staticmethod |
||||||
|
def get_params(candidate, fingerprint=gen_empty_fingerprint(), car_fw=None): |
||||||
|
ret = CarInterfaceBase.get_std_params(candidate, fingerprint) |
||||||
|
ret.carName = "tesla" |
||||||
|
ret.safetyModel = car.CarParams.SafetyModel.tesla |
||||||
|
|
||||||
|
# There is no safe way to do steer blending with user torque, |
||||||
|
# so the steering behaves like autopilot. This is not |
||||||
|
# how openpilot should be, hence dashcamOnly |
||||||
|
ret.dashcamOnly = True |
||||||
|
|
||||||
|
ret.steerControlType = car.CarParams.SteerControlType.angle |
||||||
|
ret.enableCamera = True |
||||||
|
ret.openpilotLongitudinalControl = False |
||||||
|
ret.communityFeature = True |
||||||
|
|
||||||
|
ret.steerActuatorDelay = 0.1 |
||||||
|
ret.steerRateCost = 0.5 |
||||||
|
|
||||||
|
if candidate == CAR.AP2_MODELS: |
||||||
|
ret.mass = 2100. + STD_CARGO_KG |
||||||
|
ret.wheelbase = 2.959 |
||||||
|
ret.centerToFront = ret.wheelbase * 0.5 |
||||||
|
ret.steerRatio = 13.5 |
||||||
|
else: |
||||||
|
raise ValueError(f"Unsupported car: {candidate}") |
||||||
|
|
||||||
|
ret.rotationalInertia = scale_rot_inertia(ret.mass, ret.wheelbase) |
||||||
|
ret.tireStiffnessFront, ret.tireStiffnessRear = scale_tire_stiffness(ret.mass, ret.wheelbase, ret.centerToFront) |
||||||
|
|
||||||
|
return ret |
||||||
|
|
||||||
|
def update(self, c, can_strings): |
||||||
|
self.cp.update_strings(can_strings) |
||||||
|
self.cp_cam.update_strings(can_strings) |
||||||
|
|
||||||
|
ret = self.CS.update(self.cp, self.cp_cam) |
||||||
|
ret.canValid = self.cp.can_valid and self.cp_cam.can_valid |
||||||
|
|
||||||
|
events = self.create_common_events(ret) |
||||||
|
|
||||||
|
ret.events = events.to_msg() |
||||||
|
self.CS.out = ret.as_reader() |
||||||
|
return self.CS.out |
||||||
|
|
||||||
|
def apply(self, c): |
||||||
|
can_sends = self.CC.update(c.enabled, self.CS, self.frame, c.actuators, c.cruiseControl.cancel) |
||||||
|
self.frame += 1 |
||||||
|
return can_sends |
@ -0,0 +1,5 @@ |
|||||||
|
#!/usr/bin/env python3 |
||||||
|
from selfdrive.car.interfaces import RadarInterfaceBase |
||||||
|
|
||||||
|
class RadarInterface(RadarInterfaceBase): |
||||||
|
pass |
@ -0,0 +1,41 @@ |
|||||||
|
import copy |
||||||
|
import crcmod |
||||||
|
from opendbc.can.can_define import CANDefine |
||||||
|
from selfdrive.car.tesla.values import CANBUS |
||||||
|
|
||||||
|
|
||||||
|
class TeslaCAN: |
||||||
|
def __init__(self, dbc_name, packer): |
||||||
|
self.can_define = CANDefine(dbc_name) |
||||||
|
self.packer = packer |
||||||
|
self.crc = crcmod.mkCrcFun(0x11d, initCrc=0x00, rev=False, xorOut=0xff) |
||||||
|
|
||||||
|
@staticmethod |
||||||
|
def checksum(msg_id, dat): |
||||||
|
# TODO: get message ID from name instead |
||||||
|
ret = (msg_id & 0xFF) + ((msg_id >> 8) & 0xFF) |
||||||
|
ret += sum(dat) |
||||||
|
return ret & 0xFF |
||||||
|
|
||||||
|
def create_steering_control(self, angle, enabled, frame): |
||||||
|
values = { |
||||||
|
"DAS_steeringAngleRequest": -angle, |
||||||
|
"DAS_steeringHapticRequest": 0, |
||||||
|
"DAS_steeringControlType": 1 if enabled else 0, |
||||||
|
"DAS_steeringControlCounter": (frame % 16), |
||||||
|
} |
||||||
|
|
||||||
|
data = self.packer.make_can_msg("DAS_steeringControl", CANBUS.chassis, values)[2] |
||||||
|
values["DAS_steeringControlChecksum"] = self.checksum(0x488, data[:3]) |
||||||
|
return self.packer.make_can_msg("DAS_steeringControl", CANBUS.chassis, values) |
||||||
|
|
||||||
|
def create_action_request(self, msg_stw_actn_req, cancel, bus, counter): |
||||||
|
values = copy.copy(msg_stw_actn_req) |
||||||
|
|
||||||
|
if cancel: |
||||||
|
values["SpdCtrlLvr_Stat"] = 1 |
||||||
|
values["MC_STW_ACTN_RQ"] = counter |
||||||
|
|
||||||
|
data = self.packer.make_can_msg("STW_ACTN_RQ", bus, values)[2] |
||||||
|
values["CRC_STW_ACTN_RQ"] = self.crc(data[:7]) |
||||||
|
return self.packer.make_can_msg("STW_ACTN_RQ", bus, values) |
@ -0,0 +1,53 @@ |
|||||||
|
# flake8: noqa |
||||||
|
|
||||||
|
from collections import namedtuple |
||||||
|
from selfdrive.car import dbc_dict |
||||||
|
from cereal import car |
||||||
|
|
||||||
|
Button = namedtuple('Button', ['event_type', 'can_addr', 'can_msg', 'values']) |
||||||
|
AngleRateLimit = namedtuple('AngleRateLimit', ['speed_points', 'max_angle_diff_points']) |
||||||
|
|
||||||
|
class CAR: |
||||||
|
AP2_MODELS = 'TESLA AP2 MODEL S' |
||||||
|
|
||||||
|
FINGERPRINTS = { |
||||||
|
CAR.AP2_MODELS: [ |
||||||
|
{ |
||||||
|
1: 8, 3: 8, 14: 8, 21: 4, 69: 8, 109: 4, 257: 3, 264: 8, 277: 6, 280: 6, 293: 4, 296: 4, 309: 5, 325: 8, 328: 5, 336: 8, 341: 8, 360: 7, 373: 8, 389: 8, 415: 8, 513: 5, 516: 8, 518: 8, 520: 4, 522: 8, 524: 8, 526: 8, 532: 3, 536: 8, 537: 3, 542: 8, 551: 5, 552: 2, 556: 8, 558: 8, 568: 8, 569: 8, 574: 8, 577: 8, 582: 5, 583: 8, 584: 4, 585: 8, 590: 8, 601: 8, 606: 8, 608: 1, 622: 8, 627: 6, 638: 8, 641: 8, 643: 8, 692: 8, 693: 8, 695: 8, 696: 8, 697: 8, 699: 8, 700: 8, 701: 8, 702: 8, 703: 8, 704: 8, 708: 8, 709: 8, 710: 8, 711: 8, 712: 8, 728: 8, 744: 8, 760: 8, 772: 8, 775: 8, 776: 8, 777: 8, 778: 8, 782: 8, 788: 8, 791: 8, 792: 8, 796: 2, 797: 8, 798: 6, 799: 8, 804: 8, 805: 8, 807: 8, 808: 1, 811: 8, 812: 8, 813: 8, 814: 5, 815: 8, 820: 8, 823: 8, 824: 8, 829: 8, 830: 5, 836: 8, 840: 8, 845: 8, 846: 5, 848: 8, 852: 8, 853: 8, 856: 4, 857: 6, 861: 8, 862: 5, 872: 8, 876: 8, 877: 8, 879: 8, 880: 8, 882: 8, 884: 8, 888: 8, 893: 8, 894: 8, 901: 6, 904: 3, 905: 8, 906: 8, 908: 2, 909: 8, 910: 8, 912: 8, 920: 8, 921: 8, 925: 4, 926: 6, 936: 8, 941: 8, 949: 8, 952: 8, 953: 6, 968: 8, 969: 6, 970: 8, 971: 8, 977: 8, 984: 8, 987: 8, 990: 8, 1000: 8, 1001: 8, 1006: 8, 1007: 8, 1008: 8, 1010: 6, 1014: 1, 1015: 8, 1016: 8, 1017: 8, 1018: 8, 1020: 8, 1026: 8, 1028: 8, 1029: 8, 1030: 8, 1032: 1, 1033: 1, 1034: 8, 1048: 1, 1049: 8, 1061: 8, 1064: 8, 1065: 8, 1070: 8, 1080: 8, 1081: 8, 1097: 8, 1113: 8, 1129: 8, 1145: 8, 1160: 4, 1177: 8, 1281: 8, 1328: 8, 1329: 8, 1332: 8, 1335: 8, 1337: 8, 1353: 8, 1368: 8, 1412: 8, 1436: 8, 1476: 8, 1481: 8, 1497: 8, 1513: 8, 1519: 8, 1601: 8, 1605: 8, 1617: 8, 1621: 8, 1800: 4, 1804: 8, 1812: 8, 1815: 8, 1816: 8, 1824: 8, 1828: 8, 1831: 8, 1832: 8, 1864: 8, 1880: 8, 1892: 8, 1896: 8, 1912: 8, 1960: 8, 1992: 8, 2008: 3, 2043: 5, 2045: 4 |
||||||
|
}, |
||||||
|
], |
||||||
|
} |
||||||
|
|
||||||
|
DBC = { |
||||||
|
CAR.AP2_MODELS: dbc_dict(None, 'tesla_radar', chassis_dbc='tesla_can'), |
||||||
|
} |
||||||
|
|
||||||
|
class CANBUS: |
||||||
|
chassis = 0 |
||||||
|
autopilot = 2 |
||||||
|
radar = 1 |
||||||
|
|
||||||
|
GEAR_MAP = { |
||||||
|
"DI_GEAR_INVALID": car.CarState.GearShifter.unknown, |
||||||
|
"DI_GEAR_P": car.CarState.GearShifter.park, |
||||||
|
"DI_GEAR_R": car.CarState.GearShifter.reverse, |
||||||
|
"DI_GEAR_N": car.CarState.GearShifter.neutral, |
||||||
|
"DI_GEAR_D": car.CarState.GearShifter.drive, |
||||||
|
"DI_GEAR_SNA": car.CarState.GearShifter.unknown, |
||||||
|
} |
||||||
|
|
||||||
|
DOORS = ["DOOR_STATE_FL", "DOOR_STATE_FR", "DOOR_STATE_RL", "DOOR_STATE_RR", "DOOR_STATE_FrontTrunk", "BOOT_STATE"] |
||||||
|
|
||||||
|
# Make sure the message and addr is also in the CAN parser! |
||||||
|
BUTTONS = [ |
||||||
|
Button(car.CarState.ButtonEvent.Type.leftBlinker, "STW_ACTN_RQ", "TurnIndLvr_Stat", [1]), |
||||||
|
Button(car.CarState.ButtonEvent.Type.rightBlinker, "STW_ACTN_RQ", "TurnIndLvr_Stat", [2]), |
||||||
|
Button(car.CarState.ButtonEvent.Type.accelCruise, "STW_ACTN_RQ", "SpdCtrlLvr_Stat", [4, 16]), |
||||||
|
Button(car.CarState.ButtonEvent.Type.decelCruise, "STW_ACTN_RQ", "SpdCtrlLvr_Stat", [8, 32]), |
||||||
|
Button(car.CarState.ButtonEvent.Type.cancel, "STW_ACTN_RQ", "SpdCtrlLvr_Stat", [2]), |
||||||
|
Button(car.CarState.ButtonEvent.Type.resumeCruise, "STW_ACTN_RQ", "SpdCtrlLvr_Stat", [1]), |
||||||
|
] |
||||||
|
|
||||||
|
class CarControllerParams: |
||||||
|
RATE_LIMIT_UP = AngleRateLimit(speed_points=[0., 5., 15.], max_angle_diff_points=[5., .8, .15]) |
||||||
|
RATE_LIMIT_DOWN = AngleRateLimit(speed_points=[0., 5., 15.], max_angle_diff_points=[5., 3.5, 0.4]) |
Loading…
Reference in new issue