byd: add BYD car port (HAN EV 23 / Seal Performance 2025) with MADS support
Car port adapted from HotIce0/openpilot develop_byd_comma4 to sunnypilot's opendbc API (CP_SP signatures, (ret, ret_sp) carstate returns): - opendbc/car/byd/: interface, carstate, carcontroller, bydcan, values, fingerprints (BYD_SEAL_PERFORMANCE_25 with full 91-msg fingerprint) - opendbc/dbc/byd_common.dbc - Brand registration: car/values.py, car/fingerprints.py (+MIGRATION), car.capnp SafetyModel byd @35, torque_data/params.toml - safety/modes/byd.h: SAFETY_BYD 35U with real TX checks (steer torque cmd checks, longitudinal accel checks), MADS LKAS button from PCM_BUTTONS (944), pcm_cruise_check, ESC vehicle_moving. MISRA clean. - safety/tests/test_byd.py: 120 tests (stock + longitudinal variants) - opendbc/sunnypilot/car/byd/mads.py: MadsCarState tracking the dedicated LKAS steering wheel button - sunnypilot/mads/mads.py: allow_always for byd (dedicated LKAS button) - panda: restore SConstruct/SConscript build system, rebuild panda_h7.bin.signed (TIZI) with SAFETY_BYD + MADS lateral gating Known limitation: BYD_HAN_EV_23 fingerprint is a subset of the Seal's, so HAN requires FINGERPRINT=BYD_HAN_EV_23 env var (live fingerprint cannot distinguish it; Seal fingerprints natively).
This commit is contained in:
1 parent
de77c89cf6
commit
c8903e592c
44 files changed
+1480
-5
No files matched your search
@@ -57,6 +57,13 @@ opendbc/car/body/carstate.py
|
||||
opendbc/car/body/fingerprints.py
|
||||
opendbc/car/body/interface.py
|
||||
opendbc/car/body/values.py
|
||||
opendbc/car/byd/__init__.py
|
||||
opendbc/car/byd/bydcan.py
|
||||
opendbc/car/byd/carcontroller.py
|
||||
opendbc/car/byd/carstate.py
|
||||
opendbc/car/byd/fingerprints.py
|
||||
opendbc/car/byd/interface.py
|
||||
opendbc/car/byd/values.py
|
||||
opendbc/car/chrysler/__init__.py
|
||||
opendbc/car/chrysler/carcontroller.py
|
||||
opendbc/car/chrysler/carstate.py
|
||||
@@ -214,6 +221,7 @@ opendbc/dbc/FORD_CADS_64.dbc
|
||||
opendbc/dbc/__init__.py
|
||||
opendbc/dbc/acura_ilx_2016_nidec.dbc
|
||||
opendbc/dbc/bmw_e9x_e8x.dbc
|
||||
opendbc/dbc/byd_common.dbc
|
||||
opendbc/dbc/cadillac_ct6_chassis.dbc
|
||||
opendbc/dbc/cadillac_ct6_object.dbc
|
||||
opendbc/dbc/cadillac_ct6_powertrain.dbc
|
||||
@@ -345,6 +353,7 @@ opendbc/safety/lateral.h
|
||||
opendbc/safety/longitudinal.h
|
||||
opendbc/safety/safety.h
|
||||
opendbc/safety/modes/body.h
|
||||
opendbc/safety/modes/byd.h
|
||||
opendbc/safety/modes/chrysler.h
|
||||
opendbc/safety/modes/chrysler_common.h
|
||||
opendbc/safety/modes/chrysler_cusw.h
|
||||
@@ -416,6 +425,8 @@ opendbc/sunnypilot/car/intelligent_cruise_button_management_interface_base.py
|
||||
opendbc/sunnypilot/car/interfaces.py
|
||||
opendbc/sunnypilot/car/lateral_ext.py
|
||||
opendbc/sunnypilot/car/platform_list.py
|
||||
opendbc/sunnypilot/car/byd/__init__.py
|
||||
opendbc/sunnypilot/car/byd/mads.py
|
||||
opendbc/sunnypilot/car/chrysler/__init__.py
|
||||
opendbc/sunnypilot/car/chrysler/carcontroller_ext.py
|
||||
opendbc/sunnypilot/car/chrysler/carstate_ext.py
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
# byd
|
||||
Whitespace-only changes.
@@ -0,0 +1,161 @@
|
||||
from opendbc.car.byd.values import CANBUS
|
||||
|
||||
|
||||
def byd_checksum(data: bytearray) -> int:
|
||||
byte_key = 0xAF
|
||||
sum_first = sum(byte >> 4 for byte in data) # Extract upper nibble.
|
||||
sum_second = sum(byte & 0xF for byte in data) # Extract lower nibble.
|
||||
|
||||
remainder = sum_second >> 4
|
||||
|
||||
sum_first += (byte_key & 0xF) # Low nibble of byte_key.
|
||||
sum_second += (byte_key >> 4) # High nibble of byte_key.
|
||||
|
||||
# Inline inverse computation for each sum:
|
||||
# inv = (-sum + 0x9) & 0xF
|
||||
inv_first = ((-sum_first + 0x9) & 0xF)
|
||||
inv_second = ((-sum_second + 0x9) & 0xF)
|
||||
|
||||
return (((inv_first + (5 - remainder)) << 4) + inv_second) & 0xFF
|
||||
|
||||
|
||||
def byd_checksum_short(data: bytearray) -> int:
|
||||
# checksum for CHECKSUM_S 4byte
|
||||
pass
|
||||
|
||||
|
||||
class BydCAN:
|
||||
LKAS_MODE_ACTIVE2 = 3
|
||||
LKAS_MODE_PASSIVE = 1
|
||||
|
||||
def __init__(self, packer):
|
||||
self.packer = packer
|
||||
self.mpc_lkas_counter = 0
|
||||
self.eps_steering_torque_counter = 0
|
||||
self.mpc_acc_cmd_counter = 0
|
||||
|
||||
def update_mpc_lkas_counter(self, val):
|
||||
self.mpc_lkas_counter = val
|
||||
|
||||
def _generate_mpc_lkas_new_counter(self):
|
||||
counter = self.mpc_lkas_counter
|
||||
self.mpc_lkas_counter = int(self.mpc_lkas_counter + 1) & 0xF
|
||||
return counter
|
||||
|
||||
def update_eps_steering_torque_counter(self, val):
|
||||
self.eps_steering_torque_counter = val
|
||||
|
||||
def _generate_eps_steering_torque_new_counter(self):
|
||||
counter = self.eps_steering_torque_counter
|
||||
self.eps_steering_torque_counter = int(
|
||||
self.eps_steering_torque_counter + 1) & 0xF
|
||||
return counter
|
||||
|
||||
def update_acc_cmd_counter(self, val):
|
||||
self.mpc_acc_cmd_counter = val
|
||||
|
||||
def _generate_acc_cmd_new_counter(self):
|
||||
counter = self.mpc_acc_cmd_counter
|
||||
self.mpc_acc_cmd_counter = int(self.mpc_acc_cmd_counter + 1) & 0xF
|
||||
return counter
|
||||
|
||||
# MPC -> Panda -> EPS
|
||||
def create_steering_control_torque(self, mpc_lkas_cmd_msg, torque,
|
||||
request_prepare, active, mode,
|
||||
eps_active):
|
||||
lkas_output = torque if active and eps_active else 0
|
||||
lkas_prepare = request_prepare
|
||||
lkas_active = active
|
||||
lkas_mode = mode
|
||||
left_lane = mpc_lkas_cmd_msg["LeftLane"]
|
||||
right_lane = mpc_lkas_cmd_msg["RightLane"]
|
||||
if active or request_prepare:
|
||||
left_lane = 1
|
||||
right_lane = 1
|
||||
|
||||
values = {
|
||||
"SETME_0x1": mpc_lkas_cmd_msg["SETME_0x1"],
|
||||
"LeftLane": left_lane,
|
||||
"Config": mpc_lkas_cmd_msg["Config"],
|
||||
"SETME2_0x1": mpc_lkas_cmd_msg["SETME2_0x1"],
|
||||
"Keep_Hands_On_Wheel": 0,
|
||||
"MPCErr": mpc_lkas_cmd_msg["MPCErr"],
|
||||
"SETME3_0x1": mpc_lkas_cmd_msg["SETME3_0x1"],
|
||||
"LKAS_Output": lkas_output,
|
||||
"LKASPrepare": lkas_prepare,
|
||||
"LKAS_ACTIVE": lkas_active,
|
||||
"TSRStatus": mpc_lkas_cmd_msg["TSRStatus"],
|
||||
"SETME4_0x1": mpc_lkas_cmd_msg["SETME4_0x1"],
|
||||
"RightLane": right_lane,
|
||||
"LKAS_Mode": lkas_mode,
|
||||
"SETME_0x0": mpc_lkas_cmd_msg["SETME_0x0"],
|
||||
"TSRResult": mpc_lkas_cmd_msg["TSRResult"],
|
||||
"Unknow1": mpc_lkas_cmd_msg["Unknow1"],
|
||||
"COUNTER": self._generate_mpc_lkas_new_counter(),
|
||||
}
|
||||
data = self.packer.make_can_msg("MPC_LKAS_CMD", CANBUS.main_bus, values)[1]
|
||||
values["CHECKSUM"] = byd_checksum(data)
|
||||
return self.packer.make_can_msg("MPC_LKAS_CMD", CANBUS.main_bus, values)
|
||||
|
||||
def create_steering_torque(self, eps_steering_torque_msg, mpc_lkas_output,
|
||||
mpc_lkas_request_prepare, mpc_lkas_active):
|
||||
lks_prepared = eps_steering_torque_msg["LKSPrepare"]
|
||||
cruise_activated = eps_steering_torque_msg["Cruise_Activated"]
|
||||
main_torque = eps_steering_torque_msg["MAIN_TORQUE"]
|
||||
|
||||
if mpc_lkas_active:
|
||||
lks_prepared = 0
|
||||
cruise_activated = 1
|
||||
main_torque = mpc_lkas_output
|
||||
elif mpc_lkas_request_prepare:
|
||||
lks_prepared = 1
|
||||
cruise_activated = 0
|
||||
main_torque = 0
|
||||
else:
|
||||
lks_prepared = 0
|
||||
cruise_activated = 0
|
||||
main_torque = 0
|
||||
|
||||
values = {
|
||||
"LKSPrepare": lks_prepared,
|
||||
"Cruise_Activated": cruise_activated,
|
||||
"TORQUE_FAILED": eps_steering_torque_msg["TORQUE_FAILED"],
|
||||
"SET_ME_1_1": eps_steering_torque_msg["SET_ME_1_1"],
|
||||
"Steer_Warning": eps_steering_torque_msg["Steer_Warning"],
|
||||
"Steer_Error_1": eps_steering_torque_msg["Steer_Error_1"],
|
||||
"Steer_Error_2": eps_steering_torque_msg["Steer_Error_2"],
|
||||
"SET_ME_1": eps_steering_torque_msg["SET_ME_1"],
|
||||
"MAIN_TORQUE": main_torque,
|
||||
"SET_ME_1_2": eps_steering_torque_msg["SET_ME_1_2"],
|
||||
"Keep_Hands_On_Wheel": 0,
|
||||
"SET_ME_3": eps_steering_torque_msg["SET_ME_3"],
|
||||
"Steer_Torque_Sensor": eps_steering_torque_msg["Steer_Torque_Sensor"],
|
||||
"SET_ME_XF_1": eps_steering_torque_msg["SET_ME_XF_1"],
|
||||
"SET_ME_XFFF": eps_steering_torque_msg["SET_ME_XFFF"],
|
||||
"COUNTER": self._generate_eps_steering_torque_new_counter(),
|
||||
}
|
||||
data = self.packer.make_can_msg("STEERING_TORQUE", CANBUS.cam_bus, values)[1]
|
||||
values["CHECKSUM"] = byd_checksum(data)
|
||||
return self.packer.make_can_msg("STEERING_TORQUE", CANBUS.cam_bus, values)
|
||||
|
||||
def create_acc_cmd(self, acc_cmd_msg, accel):
|
||||
values = {
|
||||
"ACCEL_CMD": accel,
|
||||
"ComfortBandUpper": acc_cmd_msg["ComfortBandUpper"],
|
||||
"ComfortBandLower": acc_cmd_msg["ComfortBandLower"],
|
||||
"JerkUpperLimit": 1,
|
||||
"SET_ME_1": acc_cmd_msg["SET_ME_1"],
|
||||
"JerkLowerLimit": -1,
|
||||
"STANDSTILL_RESUME": 0,
|
||||
"STANDSTILL_STATE": 0,
|
||||
"BRAKE_BEHAVIOR": acc_cmd_msg["BRAKE_BEHAVIOR"],
|
||||
"ACC_REQ_NOT_STANDSTILL": acc_cmd_msg["ACC_REQ_NOT_STANDSTILL"],
|
||||
"ACC_CONTROLLABLE_AND_ON": acc_cmd_msg["ACC_CONTROLLABLE_AND_ON"],
|
||||
"ACC_OVERRIDE_OR_STANDSTILL": acc_cmd_msg["ACC_OVERRIDE_OR_STANDSTILL"],
|
||||
"ESP_BEHAVIOR": acc_cmd_msg["ESP_BEHAVIOR"],
|
||||
"COUNTER": self._generate_acc_cmd_new_counter(),
|
||||
"SET_ME_XF": acc_cmd_msg["SET_ME_XF"],
|
||||
}
|
||||
data = self.packer.make_can_msg("ACC_CMD", CANBUS.main_bus, values)[1]
|
||||
values["CHECKSUM"] = byd_checksum(data)
|
||||
return self.packer.make_can_msg("ACC_CMD", CANBUS.main_bus, values)
|
||||
@@ -0,0 +1,104 @@
|
||||
import numpy as np
|
||||
from opendbc.can.packer import CANPacker
|
||||
from opendbc.car import Bus, structs
|
||||
from opendbc.car.lateral import apply_meas_steer_torque_limits
|
||||
from opendbc.car.interfaces import CarControllerBase
|
||||
from opendbc.car.byd.bydcan import BydCAN
|
||||
from opendbc.car.byd.values import CarControllerParams
|
||||
|
||||
VisualAlert = structs.CarControl.HUDControl.VisualAlert
|
||||
ButtonType = structs.CarState.ButtonEvent.Type
|
||||
LongCtrlState = structs.CarControl.Actuators.LongControlState
|
||||
|
||||
|
||||
class LKASState:
|
||||
INACTIVE = 0
|
||||
PREPARING = 1
|
||||
ACTIVE = 2
|
||||
|
||||
|
||||
class CarController(CarControllerBase):
|
||||
def __init__(self, dbc_names, CP, CP_SP):
|
||||
super().__init__(dbc_names, CP, CP_SP)
|
||||
self.params = CarControllerParams(CP)
|
||||
self.packer = CANPacker(dbc_names[Bus.pt])
|
||||
self.can = BydCAN(self.packer)
|
||||
self.apply_torque_last = 0
|
||||
|
||||
self.lkas_state = LKASState.INACTIVE
|
||||
self.lkas_counter_updated = False
|
||||
|
||||
self.apply_accel_last = 0
|
||||
|
||||
def update(self, CC, CC_SP, CS, now_nanos):
|
||||
# car control running in 100Hz
|
||||
actuators = CC.actuators
|
||||
can_sends = []
|
||||
|
||||
if (self.frame % self.params.STEER_STEP) == 0:
|
||||
# steering control running in 50Hz
|
||||
if not self.lkas_counter_updated:
|
||||
self.lkas_counter_updated = True
|
||||
self.can.update_mpc_lkas_counter(
|
||||
int(CS.mpc_lkas_cmd_msg["COUNTER"] + 1) & 0xF)
|
||||
self.can.update_eps_steering_torque_counter(
|
||||
int(CS.eps_steering_torque_msg["COUNTER"] + 1) & 0xF)
|
||||
self.can.update_acc_cmd_counter(
|
||||
int(CS.acc_cmd_msg["COUNTER"] + 1) & 0xF)
|
||||
|
||||
# update lkas state
|
||||
if self.lkas_state == LKASState.INACTIVE:
|
||||
if CC.latActive:
|
||||
self.lkas_state = LKASState.PREPARING
|
||||
elif self.lkas_state == LKASState.PREPARING:
|
||||
if CS.eps_prepared:
|
||||
self.lkas_state = LKASState.ACTIVE
|
||||
elif self.lkas_state == LKASState.ACTIVE:
|
||||
if not CC.latActive:
|
||||
self.lkas_state = LKASState.INACTIVE
|
||||
|
||||
lkas_request_prepare = int(self.lkas_state == LKASState.PREPARING)
|
||||
lkas_active = int(self.lkas_state == LKASState.ACTIVE)
|
||||
if self.lkas_state in (LKASState.PREPARING, LKASState.ACTIVE):
|
||||
lkas_mode = BydCAN.LKAS_MODE_ACTIVE2
|
||||
else:
|
||||
lkas_mode = BydCAN.LKAS_MODE_PASSIVE
|
||||
|
||||
# calc apply torque
|
||||
apply_torque = 0
|
||||
if self.lkas_state == LKASState.ACTIVE:
|
||||
apply_torque = int(round(actuators.torque * self.params.STEER_MAX))
|
||||
apply_torque = apply_meas_steer_torque_limits(apply_torque, self.apply_torque_last,
|
||||
CS.out.steeringTorqueEps, self.params)
|
||||
|
||||
pack = self.can.create_steering_control_torque(CS.mpc_lkas_cmd_msg, apply_torque,
|
||||
lkas_request_prepare, lkas_active,
|
||||
lkas_mode, CS.eps_activated)
|
||||
can_sends.append(pack)
|
||||
pack = self.can.create_steering_torque(CS.eps_steering_torque_msg,
|
||||
CS.mpc_lkas_output,
|
||||
CS.mpc_lkas_request_prepare,
|
||||
CS.mpc_lkas_active)
|
||||
can_sends.append(pack)
|
||||
|
||||
self.apply_torque_last = apply_torque
|
||||
|
||||
# Longitudinal control
|
||||
if self.CP.openpilotLongitudinalControl:
|
||||
if (self.frame % self.params.ACC_SETP) == 0:
|
||||
accel = 0
|
||||
|
||||
if CC.longActive:
|
||||
accel = float(np.clip(actuators.accel, self.params.ACCEL_MIN, self.params.ACCEL_MAX))
|
||||
|
||||
pack = self.can.create_acc_cmd(CS.acc_cmd_msg, accel)
|
||||
can_sends.append(pack)
|
||||
self.apply_accel_last = accel
|
||||
|
||||
new_actuators = actuators.as_builder()
|
||||
new_actuators.torque = self.apply_torque_last / self.params.STEER_MAX
|
||||
new_actuators.torqueOutputCan = self.apply_torque_last
|
||||
new_actuators.accel = self.apply_accel_last
|
||||
|
||||
self.frame += 1
|
||||
return new_actuators, can_sends
|
||||
@@ -0,0 +1,125 @@
|
||||
import copy
|
||||
from opendbc.car import Bus, create_button_events, structs
|
||||
from opendbc.can.parser import CANParser
|
||||
from opendbc.car.common.conversions import Conversions as CV
|
||||
from opendbc.car.interfaces import CarStateBase
|
||||
from opendbc.car.byd.values import DBC, CANBUS, STEER_THRESHOLD, GEAR_MAP
|
||||
from opendbc.sunnypilot.car.byd.mads import MadsCarState
|
||||
|
||||
GearShifter = structs.CarState.GearShifter
|
||||
ButtonType = structs.CarState.ButtonEvent.Type
|
||||
|
||||
|
||||
class CarState(CarStateBase, MadsCarState):
|
||||
def __init__(self, CP, CP_SP):
|
||||
CarStateBase.__init__(self, CP, CP_SP)
|
||||
MadsCarState.__init__(self, CP, CP_SP)
|
||||
|
||||
self.mpc_lkas_cmd_msg = None
|
||||
self.eps_steering_torque_msg = None
|
||||
self.eps_prepared = False
|
||||
self.eps_activated = False
|
||||
self.acc_cmd_msg = None
|
||||
|
||||
self.mpc_lkas_output = 0
|
||||
self.mpc_lkas_active = False
|
||||
self.mpc_lkas_request_prepare = False
|
||||
|
||||
def update(self, can_parsers) -> tuple[structs.CarState, structs.CarStateSP]:
|
||||
cp = can_parsers[Bus.pt]
|
||||
cp_cam = can_parsers[Bus.cam]
|
||||
ret = structs.CarState()
|
||||
ret_sp = structs.CarStateSP()
|
||||
|
||||
# car Speed
|
||||
ret.vEgoRaw = cp.vl["ESC"]["VEHICLE_SPEED"] * CV.KPH_TO_MS
|
||||
ret.vEgo, ret.aEgo = self.update_speed_kf(ret.vEgoRaw)
|
||||
ret.standstill = cp.vl["BRAKE_APPLIED"]["STANDSTILL"] == 1
|
||||
|
||||
# Gas pedal
|
||||
ret.gasPressed = cp.vl["PEDAL"]["GAS_PEDAL"] > 0
|
||||
|
||||
# Brake pedal
|
||||
ret.brakePressed = cp.vl["PEDAL"]["BRAKE_PEDAL"] > 0
|
||||
|
||||
# Steering wheel
|
||||
ret.steeringAngleDeg = cp.vl["STEER_MODULE"]["STEER_ANGLE"]
|
||||
ret.steeringRateDeg = cp.vl["STEER_MODULE"]["STEERING_RATE"]
|
||||
ret.steeringTorque = cp.vl["STEERING_TORQUE"]["Steer_Torque_Sensor"]
|
||||
ret.steeringTorqueEps = cp.vl["STEERING_TORQUE"]["MAIN_TORQUE"]
|
||||
# TODO: looks like STEER_THRESHOLD is too small
|
||||
ret.steeringPressed = self.update_steering_pressed(abs(ret.steeringTorque) > STEER_THRESHOLD, 5)
|
||||
ret.steerFaultPermanent = cp.vl["STEERING_TORQUE"]["TORQUE_FAILED"] != 0
|
||||
ret.steerFaultTemporary = cp.vl["STEERING_TORQUE"]["TORQUE_FAILED"] != 0
|
||||
|
||||
ret.stockAeb = cp_cam.vl["ACC_HUD_ADAS"]["AEB"] == 1
|
||||
ret.stockFcw = cp_cam.vl["ACC_HUD_ADAS"]["FCW"] == 1 # Forward Collision Warning
|
||||
|
||||
# Cruise state
|
||||
ret.cruiseState.enabled = cp_cam.vl["ACC_HUD_ADAS"]["CRUISE_STATE"] in (3, 5) # (Active, Override)
|
||||
ret.cruiseState.speed = cp_cam.vl["ACC_HUD_ADAS"]["SET_SPEED"] * 10 * CV.KPH_TO_MS
|
||||
ret.cruiseState.available = cp_cam.vl["ACC_HUD_ADAS"]["CRUISE_STATE"] not in (8, 9) # (Failure, PermanentFailure)
|
||||
ret.cruiseState.standstill = False # This needs to be false, since we can resume from stop without sending anything special
|
||||
|
||||
# Gear
|
||||
ret.gearShifter = GEAR_MAP.get(int(cp.vl["DRIVE_STATE"]["GEAR"]), GearShifter.unknown)
|
||||
|
||||
# MADS: track the dedicated LKAS steering wheel button
|
||||
MadsCarState.update_mads(self, ret, can_parsers)
|
||||
|
||||
# button presses
|
||||
ret.leftBlinker = cp.vl["STALKS"]["TURN_SIGNAL_SWITCH"] == 3 # LeftSteeringLongLift
|
||||
ret.rightBlinker = cp.vl["STALKS"]["TURN_SIGNAL_SWITCH"] == 5 # RightSteeringLongLift
|
||||
|
||||
ret.buttonEvents = [*create_button_events(self.lkas_button, self.prev_lkas_button, {1: ButtonType.lkas})]
|
||||
|
||||
# lock info
|
||||
ret.doorOpen = any([cp.vl["METER_CLUSTER"]["FRONT_LEFT_DOOR"],
|
||||
cp.vl["METER_CLUSTER"]["FRONT_RIGHT_DOOR"],
|
||||
cp.vl["METER_CLUSTER"]["BACK_LEFT_DOOR"],
|
||||
cp.vl["METER_CLUSTER"]["BACK_RIGHT_DOOR"]])
|
||||
ret.seatbeltUnlatched = cp.vl["METER_CLUSTER"]["SEATBELT_DRIVER"] != 1
|
||||
|
||||
# blindspot sensors
|
||||
# ret.leftBlindspot = False
|
||||
# ret.rightBlindspot = False
|
||||
|
||||
# Messages needed by carcontroller
|
||||
# for generate MPC_LKAS_CMD
|
||||
self.mpc_lkas_cmd_msg = copy.copy(cp_cam.vl["MPC_LKAS_CMD"])
|
||||
self.eps_prepared = cp.vl["STEERING_TORQUE"]["LKSPrepare"] != 0
|
||||
self.eps_activated = cp.vl["STEERING_TORQUE"]["Cruise_Activated"] != 0
|
||||
# for generate STEERING_TORQUE
|
||||
self.eps_steering_torque_msg = copy.copy(cp.vl["STEERING_TORQUE"])
|
||||
self.mpc_lkas_output = cp_cam.vl["MPC_LKAS_CMD"]["LKAS_Output"]
|
||||
self.mpc_lkas_active = cp_cam.vl["MPC_LKAS_CMD"]["LKAS_ACTIVE"] != 0
|
||||
self.mpc_lkas_request_prepare = cp_cam.vl["MPC_LKAS_CMD"]["LKASPrepare"] != 0
|
||||
# for generate ACC_CMD
|
||||
self.acc_cmd_msg = copy.copy(cp_cam.vl["ACC_CMD"])
|
||||
return ret, ret_sp
|
||||
|
||||
@staticmethod
|
||||
def get_can_parsers(CP, CP_SP):
|
||||
pt_messages = [
|
||||
# sig_address, frequency
|
||||
("ESC", 50),
|
||||
("BRAKE_APPLIED", 50),
|
||||
("PEDAL", 50),
|
||||
("STEER_MODULE", 100),
|
||||
("STEERING_TORQUE", 50),
|
||||
("DRIVE_STATE", 50),
|
||||
("STALKS", 20),
|
||||
("METER_CLUSTER", 20),
|
||||
("PCM_BUTTONS", 20),
|
||||
]
|
||||
|
||||
cam_messages = [
|
||||
("ACC_HUD_ADAS", 50),
|
||||
("MPC_LKAS_CMD", 50),
|
||||
("ACC_CMD", 25),
|
||||
]
|
||||
|
||||
return {
|
||||
Bus.pt: CANParser(DBC[CP.carFingerprint][Bus.pt], pt_messages, CANBUS.main_bus),
|
||||
Bus.cam: CANParser(DBC[CP.carFingerprint][Bus.pt], cam_messages, CANBUS.cam_bus),
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
from opendbc.car.structs import CarParams
|
||||
from opendbc.car.byd.values import CAR
|
||||
|
||||
Ecu = CarParams.Ecu
|
||||
|
||||
FINGERPRINTS = {
|
||||
# NOTE: the HAN EV 23 fingerprint is a minimal subset of the SEAL fingerprint,
|
||||
# so a HAN cannot be uniquely identified by live CAN fingerprinting.
|
||||
# Set FINGERPRINT=BYD_HAN_EV_23 (and SKIP_FW_QUERY) to force it.
|
||||
CAR.BYD_HAN_EV_23: [{
|
||||
140: 8, 213: 8, 287: 5, 289: 8, 291: 8, 301: 8, 307: 8, 337: 8, 496: 8, 536: 8, 544: 8, 546: 8, 547: 8, 575: 8, 576: 8
|
||||
}],
|
||||
CAR.BYD_SEAL_PERFORMANCE_25: [{
|
||||
140: 8, 213: 8, 287: 5, 289: 8, 291: 8, 301: 8, 307: 8, 311: 8, 312: 8, 337: 8, 359: 8, 482: 8, 493: 8, 496: 8, 508: 8,
|
||||
511: 8, 536: 8, 544: 8, 546: 8, 547: 8, 567: 8, 575: 8, 576: 8, 578: 8, 588: 8, 604: 8, 612: 8, 626: 8, 657: 8, 660: 8,
|
||||
661: 8, 663: 8, 668: 8, 692: 8, 694: 8, 714: 8, 724: 8, 748: 8, 758: 8, 790: 8, 797: 8, 798: 8, 801: 8, 802: 8, 803: 8,
|
||||
813: 8, 814: 8, 815: 8, 833: 8, 834: 8, 836: 8, 837: 8, 854: 8, 860: 8, 868: 8, 877: 8, 904: 8, 906: 8, 944: 8, 948: 8,
|
||||
951: 8, 965: 8, 973: 8, 985: 8, 1023: 8, 1028: 8, 1031: 8, 1033: 8, 1040: 8, 1048: 8, 1058: 8, 1074: 8, 1092: 8, 1093: 8,
|
||||
1107: 8, 1108: 8, 1141: 8, 1166: 8, 1168: 8, 1178: 8, 1189: 8, 1193: 8, 1203: 64, 1204: 64, 1226: 16, 1246: 8, 1297: 8,
|
||||
1319: 8, 1322: 8, 1365: 8, 1366: 8
|
||||
}],
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
from opendbc.car import get_safety_config, structs
|
||||
from opendbc.car.common.conversions import Conversions as CV
|
||||
from opendbc.car.interfaces import CarInterfaceBase
|
||||
from opendbc.car.byd.carcontroller import CarController
|
||||
from opendbc.car.byd.carstate import CarState
|
||||
from opendbc.car.byd.values import CAR, BydFlags, BydSafetyFlags
|
||||
|
||||
|
||||
class CarInterface(CarInterfaceBase):
|
||||
CarState = CarState
|
||||
CarController = CarController
|
||||
|
||||
@staticmethod
|
||||
def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams:
|
||||
ret.brand = "byd"
|
||||
ret.dashcamOnly = False
|
||||
|
||||
ret.safetyConfigs = [get_safety_config(structs.CarParams.SafetyModel.byd)]
|
||||
|
||||
# lateral control parameters
|
||||
ret.steerActuatorDelay = 0.3
|
||||
ret.steerLimitTimer = 0.5
|
||||
|
||||
if candidate in (CAR.BYD_HAN_EV_23, CAR.BYD_SEAL_PERFORMANCE_25):
|
||||
ret.steerControlType = structs.CarParams.SteerControlType.torque
|
||||
|
||||
ret.minEnableSpeed = -1.
|
||||
ret.minSteerSpeed = 0.1 * CV.KPH_TO_MS
|
||||
ret.steerLimitTimer = 0.5
|
||||
|
||||
if ret.steerControlType == structs.CarParams.SteerControlType.torque:
|
||||
CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning)
|
||||
|
||||
# longitudinal control parameters
|
||||
ret.alphaLongitudinalAvailable = True
|
||||
if alpha_long:
|
||||
ret.openpilotLongitudinalControl = True
|
||||
ret.startingState = True
|
||||
ret.startAccel = 0.1
|
||||
ret.flags |= BydFlags.LONG_CONTROL.value
|
||||
ret.safetyConfigs[0].safetyParam |= BydSafetyFlags.LONG_CONTROL.value
|
||||
ret.vEgoStopping = 0.1
|
||||
ret.vEgoStarting = 0.1
|
||||
ret.stoppingDecelRate = 0.3
|
||||
|
||||
# TODO: add radar support
|
||||
ret.radarUnavailable = True
|
||||
|
||||
return ret
|
||||
@@ -0,0 +1,78 @@
|
||||
from dataclasses import dataclass, field
|
||||
from enum import IntFlag
|
||||
from opendbc.car import Bus, DbcDict, PlatformConfig, Platforms, CarSpecs, STD_CARGO_KG
|
||||
from opendbc.car.structs import CarParams, CarState
|
||||
from opendbc.car.docs_definitions import CarHarness, CarDocs, CarParts
|
||||
|
||||
Ecu = CarParams.Ecu
|
||||
|
||||
|
||||
class CANBUS:
|
||||
main_bus = 0
|
||||
radar_bus = 1
|
||||
cam_bus = 2
|
||||
|
||||
|
||||
class BydSafetyFlags(IntFlag):
|
||||
LONG_CONTROL = 1
|
||||
|
||||
|
||||
class BydFlags(IntFlag):
|
||||
LONG_CONTROL = 1
|
||||
|
||||
|
||||
@dataclass
|
||||
class BydCarDocs(CarDocs):
|
||||
package: str = "All"
|
||||
car_parts: CarParts = field(default_factory=CarParts.common([CarHarness.custom]))
|
||||
#todo add docs and harness info
|
||||
|
||||
|
||||
@dataclass
|
||||
class BydPlatformConfig(PlatformConfig):
|
||||
dbc_dict: DbcDict = field(default_factory=lambda: {Bus.pt: "byd_common"})
|
||||
|
||||
|
||||
class CAR(Platforms):
|
||||
BYD_HAN_EV_23 = BydPlatformConfig(
|
||||
[BydCarDocs("BYD HAN EV 2023")],
|
||||
CarSpecs(mass=1940 + STD_CARGO_KG, wheelbase=2.92, steerRatio=16.5,
|
||||
centerToFrontRatio=0.44, tireStiffnessFactor=1.0)
|
||||
)
|
||||
BYD_SEAL_PERFORMANCE_25 = BydPlatformConfig(
|
||||
[BydCarDocs("BYD SEAL PERFORMANCE 2025")],
|
||||
# TODO: verify steerRatio and centerToFrontRatio on a real car
|
||||
CarSpecs(mass=2100 + STD_CARGO_KG, wheelbase=2.92, steerRatio=16.0,
|
||||
centerToFrontRatio=0.44, tireStiffnessFactor=1.0)
|
||||
)
|
||||
|
||||
|
||||
class CarControllerParams:
|
||||
def __init__(self, CP):
|
||||
self.STEER_STEP = 2 # 50Hz
|
||||
self.ACC_SETP = 4 # 25Hz
|
||||
|
||||
self.STEER_ERROR_MAX = 46
|
||||
if CP.carFingerprint in (CAR.BYD_HAN_EV_23, CAR.BYD_SEAL_PERFORMANCE_25):
|
||||
self.STEER_MAX = 300
|
||||
self.STEER_DELTA_UP = 6
|
||||
self.STEER_DELTA_DOWN = 6
|
||||
|
||||
self.ACCEL_MAX = 2.0 # m/s^2
|
||||
self.ACCEL_MIN = -4.0 # m/s^2
|
||||
self.JERK_LIMIT_MAX = 4.0 # m/s^3
|
||||
self.JERK_LIMIT_MIN = -4.0 # m/s^3
|
||||
|
||||
|
||||
STEER_THRESHOLD = 1
|
||||
|
||||
GEAR_MAP = {
|
||||
4: CarState.GearShifter.drive,
|
||||
2: CarState.GearShifter.reverse,
|
||||
3: CarState.GearShifter.neutral,
|
||||
1: CarState.GearShifter.park,
|
||||
}
|
||||
|
||||
# TODO: Get a BYD VDS to see how firmware could be queried. Until then BYD is
|
||||
# identified by legacy CAN fingerprinting only.
|
||||
DBC = CAR.create_dbc_map()
|
||||
@@ -634,6 +634,7 @@ struct CarParams {
|
||||
fcaGiorgio @32;
|
||||
rivian @33;
|
||||
volkswagenMeb @34;
|
||||
byd @35;
|
||||
}
|
||||
|
||||
enum SteerControlType {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from opendbc.car.interfaces import get_interface_attr
|
||||
from opendbc.car.body.values import CAR as BODY
|
||||
from opendbc.car.byd.values import CAR as BYD
|
||||
from opendbc.car.chrysler.values import CAR as CHRYSLER
|
||||
from opendbc.car.ford.values import CAR as FORD
|
||||
from opendbc.car.gm.values import CAR as GM
|
||||
@@ -56,6 +57,8 @@ def all_legacy_fingerprint_cars():
|
||||
|
||||
# A dict that maps old platform strings to their latest representations
|
||||
MIGRATION = {
|
||||
"BYD HAN EV 23": BYD.BYD_HAN_EV_23,
|
||||
"BYD SEAL PERFORMANCE 2025": BYD.BYD_SEAL_PERFORMANCE_25,
|
||||
"ACURA ILX 2016 ACURAWATCH PLUS": HONDA.ACURA_ILX,
|
||||
"ACURA RDX 2018 ACURAWATCH PLUS": HONDA.ACURA_RDX,
|
||||
"ACURA RDX 2020 TECH": HONDA.ACURA_RDX_3G,
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
legend = ["LAT_ACCEL_FACTOR", "MAX_LAT_ACCEL_MEASURED", "FRICTION"]
|
||||
"BYD_HAN_EV_23" = [1.807, 1.674, 0.04]
|
||||
"BYD_SEAL_PERFORMANCE_25" = [1.807, 1.674, 0.04]
|
||||
"ACURA_ILX" = [1.524988973896102, 0.519011053086259, 0.34236219253028]
|
||||
"ACURA_RDX" = [0.9987728568686902, 0.5323765166196301, 0.303218805715844]
|
||||
"ACURA_RDX_3G" = [1.4314459806646749, 0.33874701282109954, 0.18048847083897598]
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from typing import get_args
|
||||
from opendbc.car.body.values import CAR as BODY
|
||||
from opendbc.car.byd.values import CAR as BYD
|
||||
from opendbc.car.chrysler.values import CAR as CHRYSLER
|
||||
from opendbc.car.ford.values import CAR as FORD
|
||||
from opendbc.car.gm.values import CAR as GM
|
||||
@@ -15,7 +16,7 @@ from opendbc.car.tesla.values import CAR as TESLA
|
||||
from opendbc.car.toyota.values import CAR as TOYOTA
|
||||
from opendbc.car.volkswagen.values import CAR as VOLKSWAGEN
|
||||
|
||||
Platform = BODY | CHRYSLER | FORD | GM | HONDA | HYUNDAI | MAZDA | MOCK | NISSAN | PSA | RIVIAN | SUBARU | TESLA | TOYOTA | VOLKSWAGEN
|
||||
Platform = BODY | BYD | CHRYSLER | FORD | GM | HONDA | HYUNDAI | MAZDA | MOCK | NISSAN | PSA | RIVIAN | SUBARU | TESLA | TOYOTA | VOLKSWAGEN
|
||||
BRANDS = get_args(Platform)
|
||||
|
||||
PLATFORMS: dict[str, Platform] = {str(platform): platform for brand in BRANDS for platform in brand}
|
||||
@@ -0,0 +1,375 @@
|
||||
VERSION ""
|
||||
|
||||
|
||||
NS_ :
|
||||
NS_DESC_
|
||||
CM_
|
||||
BA_DEF_
|
||||
BA_
|
||||
VAL_
|
||||
CAT_DEF_
|
||||
CAT_
|
||||
FILTER
|
||||
BA_DEF_DEF_
|
||||
EV_DATA_
|
||||
ENVVAR_DATA_
|
||||
SGTYPE_
|
||||
SGTYPE_VAL_
|
||||
BA_DEF_SGTYPE_
|
||||
BA_SGTYPE_
|
||||
SIG_TYPE_REF_
|
||||
VAL_TABLE_
|
||||
SIG_GROUP_
|
||||
SIG_VALTYPE_
|
||||
SIGTYPE_VALTYPE_
|
||||
BO_TX_BU_
|
||||
BA_DEF_REL_
|
||||
BA_REL_
|
||||
BA_DEF_DEF_REL_
|
||||
BU_SG_REL_
|
||||
BU_EV_REL_
|
||||
BU_BO_REL_
|
||||
SG_MUL_VAL_
|
||||
|
||||
BS_:
|
||||
|
||||
BU_: XXX
|
||||
|
||||
BO_ 85 EPB: 8 XXX
|
||||
SG_ EPB_ACTIVE : 40|1@1+ (1,0) [0|1] "" XXX
|
||||
|
||||
BO_ 234 STEERING_TORQUE_ALT: 8 XXX
|
||||
SG_ LKSPrepare : 0|1@1+ (1,0) [0|1] "" XXX
|
||||
SG_ Cruise_Activated : 1|1@1+ (1,0) [0|1] "" XXX
|
||||
SG_ TORQUE_FAILED : 4|1@1+ (1,0) [0|1] "" XXX
|
||||
SG_ Steer_Torque_Sensor : 8|12@1- (1,0) [0|4095] "" XXX
|
||||
SG_ MAIN_TORQUE : 24|12@1+ (0.15,-316) [0|4095] "" XXX
|
||||
SG_ WAIT_INIT : 36|1@1+ (1,0) [0|1] "" XXX
|
||||
SG_ COUNTER : 52|4@1+ (1,0) [0|15] "" XXX
|
||||
SG_ CHECKSUM : 56|8@1+ (1,0) [0|255] "" XXX
|
||||
|
||||
BO_ 235 MPC_LKAS_CMD_ALT: 8 XXX
|
||||
SG_ TORQUE_FACTOR : 0|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ LKAS_Output : 8|12@1- (0.15,0) [0|4095] "" XXX
|
||||
SG_ LKASPrepare : 20|1@1+ (1,0) [0|1] "" XXX
|
||||
SG_ LKAS_ACTIVE : 21|1@1+ (1,0) [0|1] "" XXX
|
||||
SG_ SET_ME_2 : 22|2@1+ (1,0) [0|1] "" XXX
|
||||
SG_ SET_ME_FF_1 : 24|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SET_ME_FF_2 : 32|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SET_ME_FF_3 : 40|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ SET_ME_F : 48|4@1+ (1,0) [0|15] "" XXX
|
||||
SG_ COUNTER : 52|4@1+ (1,0) [0|15] "" XXX
|
||||
SG_ CHECKSUM : 56|8@1+ (1,0) [0|255] "" XXX
|
||||
|
||||
BO_ 269 ECM: 8 XXX
|
||||
SG_ ENG_RPM : 0|16@1+ (0.25,0) [0|255] "" XXX
|
||||
SG_ GAS_PEDAL : 40|8@1+ (0.00392,0) [0|255] "" XXX
|
||||
|
||||
BO_ 287 STEER_MODULE: 5 XXX
|
||||
SG_ STEER_ANGLE : 0|16@1- (0.1,0) [-450|450] "" XXX
|
||||
SG_ STEERING_RATE : 16|8@1+ (4,0) [0|1020] "" XXX
|
||||
SG_ PAYLOAD : 24|8@1+ (1,0) [0|255] "" XXX
|
||||
SG_ COUNTER : 32|4@1+ (1,0) [0|255] "" XXX
|
||||
SG_ CHECKSUM_S : 36|4@1+ (1,0) [0|15] "" XXX
|
||||
|
||||
BO_ 289 ESC: 8 XXX
|
||||
SG_ VEHICLE_SPEED : 0|12@1+ (0.0725,0) [0|4095] "" XXX
|
||||
|
||||
BO_ 291 IPB: 8 XXX
|
||||
SG_ BRAKE_PRESSED : 43|1@0+ (1,0) [0|1] "" XXX
|
||||
|
||||
BO_ 301 BRAKE_PRESSED: 8 XXX
|
||||
SG_ BRAKE_PRESSED : 8|1@1+ (1,0) [0|1] "" XXX
|
||||
|
||||
BO_ 307 STALKS: 8 XXX
|
||||
SG_ EPB_ACTIVE : 1|1@1+ (1,0) [0|1] "" XXX
|
||||
SG_ HEADLIGHT : 2|1@1+ (1,0) [0|1] "" XXX
|
||||
SG_ HIGH_BEAM : 3|1@1+ (1,0) [0|1] "" XXX
|
||||
SG_ LEFT_BLINKER : 4|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ RIGHT_BLINKER : 5|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ TURN_SIGNAL_SWITCH : 36|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ AUTO_HEADLIGHT : 40|1@0+ (1,0) [0|1] "" XXX
|
||||
|
||||
BO_ 455 STEER_ANGLE_ALT: 8 XXX
|
||||
SG_ STEER_ANGLE : 0|16@1- (0.1,0) [0|4095] "" XXX
|
||||
SG_ STEER_RATE : 16|8@1+ (4,0) [0|255] "" XXX
|
||||
|
||||
BO_ 482 MPC_LKAS_CMD_ANGLE: 8 XXX
|
||||
SG_ JerkUpperLimit : 0|10@1- (1,0) [0|65535] "" XXX
|
||||
SG_ JerkLowerLimit : 10|10@1- (1,0) [0|15] "" XXX
|
||||
SG_ LKASPrepare : 20|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ LKAS_ACTIVE : 21|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ SET_ME_3 : 22|2@1+ (1,0) [0|1] "" XXX
|
||||
SG_ LKAS_Output : 24|16@1- (0.1,0) [0|255] "" XXX
|
||||
SG_ SET_ME_FF : 47|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ SET_ME_F : 48|4@1+ (1,0) [0|15] "" XXX
|
||||
SG_ COUNTER : 52|4@1+ (1,0) [0|15] "" XXX
|
||||
SG_ CHECKSUM : 56|8@1+ (1,0) [0|255] "" XXX
|
||||
|
||||
BO_ 496 WHEEL_SPEED: 8 XXX
|
||||
SG_ WHEELSPEED_FL : 0|12@1+ (0.0725,0) [0|281.4625] "km/h" XXX
|
||||
SG_ FAULT_FR : 12|1@1+ (1,0) [0|1] "" XXX
|
||||
SG_ FAULT_FL : 13|1@1+ (1,0) [0|1] "" XXX
|
||||
SG_ FAULT_BR : 14|1@1+ (1,0) [0|1] "" XXX
|
||||
SG_ FAULT_BL : 15|1@1+ (1,0) [0|1] "" XXX
|
||||
SG_ WHEELSPEED_FR : 16|12@1+ (0.0725,0) [0|281.4625] "km/h" XXX
|
||||
SG_ WHEELSPEED_BL : 28|12@1+ (0.0725,0) [0|281.4625] "km/h" XXX
|
||||
SG_ WHEELSPEED_BR : 40|12@1+ (0.0725,0) [0|281.4625] "km/h" XXX
|
||||
SG_ COUNTER : 52|4@1+ (1,0) [0|15] "" XXX
|
||||
SG_ CHECKSUM : 56|8@1+ (1,0) [0|255] "" XXX
|
||||
|
||||
BO_ 508 STEERING_TORQUE_ANGLE: 8 XXX
|
||||
SG_ LKSPrepare : 0|1@1+ (1,0) [0|1] "" XXX
|
||||
SG_ Cruise_Activated : 1|1@1+ (1,0) [0|1] "" XXX
|
||||
SG_ TORQUE_FAILED : 2|1@1+ (1,0) [0|1] "" XXX
|
||||
SG_ Steer_Torque_Sensor : 4|12@1- (0.1,0) [0|65535] "" XXX
|
||||
SG_ TARGET_ANGLE : 16|16@1- (0.1,0) [0|255] "" XXX
|
||||
SG_ MAIN_TORQUE : 32|12@1- (1,0) [0|63] "" XXX
|
||||
SG_ Keep_Hands_On_Wheel : 45|1@1+ (1,0) [0|255] "" XXX
|
||||
SG_ TORQUE_TEMP_FAILED : 46|2@1+ (1,0) [0|3] "" XXX
|
||||
SG_ COUNTER : 52|4@1+ (1,0) [0|15] "" XXX
|
||||
SG_ CHECKSUM : 56|8@1+ (1,0) [0|255] "" XXX
|
||||
|
||||
BO_ 522 ENGINE_RPM: 8 XXX
|
||||
SG_ ENG_RPM : 31|8@0+ (1,0) [0|255] "" XXX
|
||||
|
||||
BO_ 523 ENGINE_GAUGE: 8 XXX
|
||||
SG_ ENG_RPM : 15|8@0+ (12,0) [0|0] "" XXX
|
||||
|
||||
BO_ 530 TCU: 8 XXX
|
||||
SG_ GEAR : 48|4@1+ (1,0) [0|15] "" XXX
|
||||
|
||||
BO_ 536 EPB_NG: 8 XXX
|
||||
SG_ EPB_ACTIVE : 0|2@1+ (1,0) [0|3] "" XXX
|
||||
SG_ EPB_STATUS : 9|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ COUNTER : 48|4@1+ (1,0) [0|15] "" XXX
|
||||
SG_ CHECKSUM : 56|8@1+ (1,0) [0|255] "" XXX
|
||||
|
||||
BO_ 544 BRAKE_APPLIED: 8 XXX
|
||||
SG_ BRAKE_HOLD_ACTIVE : 8|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ BRAKE_APPLIED_ACTIVE_LOW : 12|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ STANDSTILL : 19|2@0+ (1,0) [0|3] "" XXX
|
||||
SG_ VLC_SENSOR : 24|8@1+ (0.05,-7) [0|255] "" XXX
|
||||
SG_ NEW_SIGNAL_2 : 32|13@1+ (1,0) [0|8191] "" XXX
|
||||
|
||||
BO_ 546 YAW_SENSOR: 8 XXX
|
||||
SG_ YAW_RATE : 0|12@1+ (0.002132603,-2.094216146) [0|4095] "" XXX
|
||||
SG_ YAW_OFFSET : 12|12@1+ (0.002132603,-0.130088783) [0|4095] "" XXX
|
||||
|
||||
BO_ 547 ACCEL_SENSOR: 8 XXX
|
||||
SG_ LONGITUDE : 0|12@1- (0.027126736,-21.592881856) [-2848|1247] "" XXX
|
||||
SG_ LONGITUDE_OFFSET : 12|12@1+ (0.027126736,-21.592881856) [0|4095] "" XXX
|
||||
SG_ LATERAL : 24|12@1- (0.027126736,-21.592881856) [-2848|1247] "" XXX
|
||||
SG_ LATERAL_OFFSET : 36|12@1+ (0.027126736,-21.592881856) [0|4095] "" XXX
|
||||
|
||||
BO_ 578 DRIVE_STATE: 8 XXX
|
||||
SG_ WHEELSPEED_HR : 0|16@1+ (0.01706666666,-512) [0|65535] "" XXX
|
||||
SG_ RAW_THROTTLE : 30|7@0+ (1,0) [0|127] "" XXX
|
||||
SG_ BRAKE_PRESSED : 37|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ GEAR : 40|3@1+ (1,0) [0|7] "" XXX
|
||||
|
||||
BO_ 660 METER_CLUSTER: 8 XXX
|
||||
SG_ FRONT_RIGHT_DOOR : 1|1@1+ (1,0) [0|511] "" XXX
|
||||
SG_ FRONT_LEFT_DOOR : 3|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ BACK_LEFT_DOOR : 5|1@1+ (1,0) [0|511] "" XXX
|
||||
SG_ BACK_RIGHT_DOOR : 7|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ SEATBELT_DRIVER : 17|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ BRAKE_PRESSED_ALT : 26|1@1+ (1,0) [0|1] "" XXX
|
||||
SG_ COUNTER : 48|4@1+ (1,0) [0|255] "" XXX
|
||||
SG_ CHECKSUM : 56|8@1+ (1,0) [0|255] "" XXX
|
||||
|
||||
BO_ 665 IKEY: 3 XXX
|
||||
SG_ IKEY_REVERT : 20|1@1+ (1,0) [0|1] "" XXX
|
||||
SG_ IKEY_MOVE_OR_STEERING : 21|1@1+ (1,0) [0|1] "" XXX
|
||||
SG_ IKEY_ENABLE : 22|1@1+ (1,0) [0|1] "" XXX
|
||||
|
||||
BO_ 790 MPC_LKAS_CMD: 8 XXX
|
||||
SG_ SETME_0x1 : 0|4@1+ (1,0) [0|3] "" XXX
|
||||
SG_ LeftLane : 4|2@1+ (1,0) [0|3] "" XXX
|
||||
SG_ Config : 6|2@1+ (1,0) [0|3] "" XXX
|
||||
SG_ SETME2_0x1 : 8|2@1+ (1,0) [0|3] "" XXX
|
||||
SG_ Keep_Hands_On_Wheel : 10|1@1+ (1,0) [0|1] "" XXX
|
||||
SG_ MPCErr : 11|4@1+ (1,0) [0|1] "" XXX
|
||||
SG_ SETME3_0x1 : 15|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ LKAS_Output : 16|11@1- (1,0) [-1024|1023] "" XXX
|
||||
SG_ LKASPrepare : 27|1@1+ (1,0) [0|1] "" XXX
|
||||
SG_ LKAS_ACTIVE : 28|1@1+ (1,0) [0|3] "" XXX
|
||||
SG_ TSRStatus : 29|3@1+ (1,0) [0|1] "" XXX
|
||||
SG_ SETME4_0x1 : 32|2@1+ (1,0) [0|3] "" XXX
|
||||
SG_ RightLane : 34|2@1+ (1,0) [0|3] "" XXX
|
||||
SG_ LKAS_Mode : 36|3@1+ (1,0) [0|3] "" XXX
|
||||
SG_ SETME_0x0 : 39|1@1+ (1,0) [0|3] "" XXX
|
||||
SG_ TSRResult : 40|8@1+ (5,-5) [-5|1270] "" XXX
|
||||
SG_ Unknow1 : 48|4@1+ (1,0) [0|15] "" XXX
|
||||
SG_ COUNTER : 52|4@1+ (1,0) [0|15] "" XXX
|
||||
SG_ CHECKSUM : 56|8@1+ (1,0) [0|255] "" XXX
|
||||
|
||||
BO_ 792 STEERING_TORQUE: 8 XXX
|
||||
SG_ LKSPrepare : 0|1@1+ (1,0) [0|1] "" XXX
|
||||
SG_ Cruise_Activated : 1|1@1+ (1,0) [0|1] "" XXX
|
||||
SG_ TORQUE_FAILED : 2|1@1+ (1,0) [0|1] "" XXX
|
||||
SG_ SET_ME_1_1 : 3|1@1+ (1,0) [0|1] "" XXX
|
||||
SG_ Steer_Warning : 4|1@1+ (1,0) [0|1] "" XXX
|
||||
SG_ Steer_Error_1 : 5|1@1+ (1,0) [0|1] "" XXX
|
||||
SG_ Steer_Error_2 : 6|1@1+ (1,0) [0|1] "" XXX
|
||||
SG_ SET_ME_1 : 7|1@1+ (1,0) [0|1] "" XXX
|
||||
SG_ MAIN_TORQUE : 8|12@1- (1,0) [-2048|2047] "" XXX
|
||||
SG_ SET_ME_1_2 : 20|1@1+ (1,0) [0|1] "" XXX
|
||||
SG_ Keep_Hands_On_Wheel : 21|1@1+ (1,0) [0|1] "" XXX
|
||||
SG_ SET_ME_3 : 22|2@1+ (1,0) [0|15] "" XXX
|
||||
SG_ Steer_Torque_Sensor : 24|12@1- (1,0) [-2048|2047] "" XXX
|
||||
SG_ SET_ME_XF_1 : 36|4@1+ (1,0) [0|15] "" XXX
|
||||
SG_ SET_ME_XFFF : 40|12@1+ (1,0) [0|4095] "" XXX
|
||||
SG_ COUNTER : 52|4@1+ (1,0) [0|15] "" XXX
|
||||
SG_ CHECKSUM : 56|8@1+ (1,0) [0|255] "" XXX
|
||||
|
||||
BO_ 801 BRAKE_PEDAL_LEG: 8 XXX
|
||||
SG_ BRAKE_PEDAL : 0|12@1+ (0.001,-0.278) [0|255] "" XXX
|
||||
SG_ COUNTER : 52|4@1+ (1,0) [0|15] "" XXX
|
||||
SG_ CHECKSUM : 56|8@1+ (1,0) [0|255] "" XXX
|
||||
|
||||
BO_ 813 ACC_HUD_ADAS: 8 XXX
|
||||
SG_ SET_SPEED : 0|9@1+ (0.5,0) [0|255.5] "" XXX
|
||||
SG_ HAS_LEAD : 9|1@1+ (1,0) [0|1] "" XXX
|
||||
SG_ SET_DISTANCE : 10|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ LEAD_DISTANCE : 13|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ AEB : 16|1@1+ (1,0) [0|1] "" XXX
|
||||
SG_ FCW : 17|1@1+ (1,0) [0|1] "" XXX
|
||||
SG_ SET_ME_1 : 18|1@1+ (1,0) [0|1] "" XXX
|
||||
SG_ ACC_ON2 : 19|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ ACC_CONTROLLABLE_AND_ON : 20|1@1+ (1,0) [0|1] "" XXX
|
||||
SG_ OVERRIDE : 21|1@1+ (1,0) [0|1] "" XXX
|
||||
SG_ ACC_ON1 : 22|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ TOO_CLOSE : 23|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ SET_ME_1_1 : 24|3@1+ (1,0) [0|1] "" XXX
|
||||
SG_ NOTIFY : 27|5@1+ (1,0) [0|127] "" XXX
|
||||
SG_ ERROR : 32|4@1+ (1,0) [0|15] "" XXX
|
||||
SG_ SET_ME_XFF : 36|8@1+ (1,0) [0|4095] "" XXX
|
||||
SG_ CRUISE_STATE : 44|4@1+ (1,0) [0|15] "" XXX
|
||||
SG_ COUNTER : 48|4@1+ (1,0) [0|15] "" XXX
|
||||
SG_ SET_ME_XF : 55|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ CHECKSUM : 56|8@1+ (1,0) [0|255] "" XXX
|
||||
|
||||
BO_ 814 ACC_CMD: 8 XXX
|
||||
SG_ ACCEL_CMD : 0|8@1+ (0.05,-5) [-100|155] "m/s^2" XXX
|
||||
SG_ ComfortBandUpper : 8|8@1+ (0.05,-5) [0|1.26] "m/s^2" XXX
|
||||
SG_ ComfortBandLower : 16|8@1+ (0.05,-5) [0|1.26] "m/s^2" XXX
|
||||
SG_ JerkUpperLimit : 24|7@1+ (0.2,0) [0|12.7] "m/s^3" XXX
|
||||
SG_ SET_ME_1 : 31|1@0+ (1,0) [0|3] "" XXX
|
||||
SG_ JerkLowerLimit : 32|7@1+ (0.2,-16) [0|12.7] "m/s^3" XXX
|
||||
SG_ STANDSTILL_RESUME : 39|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ STANDSTILL_STATE : 40|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ BRAKE_BEHAVIOR : 41|2@1+ (1,0) [0|3] "" XXX
|
||||
SG_ ACC_REQ_NOT_STANDSTILL : 43|1@1+ (1,0) [0|1] "" XXX
|
||||
SG_ ACC_CONTROLLABLE_AND_ON : 44|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ ACC_OVERRIDE_OR_STANDSTILL : 45|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ ESP_BEHAVIOR : 46|2@1+ (1,0) [0|3] "" XXX
|
||||
SG_ COUNTER : 48|4@1+ (1,0) [0|15] "" XXX
|
||||
SG_ SET_ME_XF : 55|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ CHECKSUM : 56|8@1+ (1,0) [0|255] "" XXX
|
||||
|
||||
BO_ 815 ACC_AEB: 8 XXX
|
||||
SG_ PAYLOAD : 0|48@1+ (1,0) [0|4.5035996273705e+15] "" XXX
|
||||
SG_ COUNTER : 48|4@1+ (1,0) [0|15] "" XXX
|
||||
SG_ SETME_0xF : 55|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ CHECKSUM : 56|8@1+ (1,0) [0|255] "" XXX
|
||||
|
||||
BO_ 834 PEDAL: 8 XXX
|
||||
SG_ GAS_PEDAL : 0|8@1+ (0.01,0) [0|2.55] "" XXX
|
||||
SG_ BRAKE_PEDAL : 8|8@1+ (0.01,0) [0|2.55] "" XXX
|
||||
SG_ STILL_GENERATOR : 19|1@1+ (1,0) [0|1] "" XXX
|
||||
SG_ DRIVE_MODE : 20|2@1+ (1,0) [0|255] "" XXX
|
||||
SG_ POWER_MODE : 28|2@1+ (1,0) [0|1] "" XXX
|
||||
|
||||
BO_ 848 RADAR_UNUSED_0: 8 XXX
|
||||
|
||||
BO_ 849 RADAR_TRACK_1: 8 XXX
|
||||
SG_ LONG_DIST : 16|12@1- (0.06,-4) [-61.44|61.41] "m" XXX
|
||||
SG_ LAT_DIST : 28|10@1+ (0.05,-25.6) [-15.36|15.33] "m" XXX
|
||||
SG_ TRACK_ID : 38|6@1+ (1,0) [0|63] "" XXX
|
||||
SG_ REL_SPEED : 44|10@1+ (1,-512) [-512|511] "km/s" XXX
|
||||
SG_ SETME_0x3 : 54|2@1+ (1,0) [0|3] "" XXX
|
||||
SG_ VALID : 56|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ SETME_0x0 : 57|7@1+ (1,0) [0|127] "" XXX
|
||||
|
||||
BO_ 850 RADAR_TRACK_2: 8 XXX
|
||||
SG_ LONG_DIST : 16|12@1- (0.06,-4) [-61.44|61.41] "m" XXX
|
||||
SG_ LAT_DIST : 28|10@1+ (-0.05,-25.6) [-15.36|15.33] "m" XXX
|
||||
SG_ TRACK_ID : 38|6@1+ (1,0) [0|63] "" XXX
|
||||
SG_ REL_SPEED : 44|10@1+ (1,-512) [-512|511] "km/s" XXX
|
||||
SG_ SETME_0x3 : 54|2@1+ (1,0) [0|3] "" XXX
|
||||
SG_ VALID : 56|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ SETME_0x0 : 57|7@1+ (1,0) [0|127] "" XXX
|
||||
|
||||
BO_ 851 RADAR_TRACK_3: 8 XXX
|
||||
SG_ LONG_DIST : 16|12@1- (0.06,-4) [-61.44|61.41] "m" XXX
|
||||
SG_ LAT_DIST : 28|10@1+ (0.05,-25.6) [-15.36|15.33] "m" XXX
|
||||
SG_ TRACK_ID : 38|6@1+ (1,0) [0|63] "" XXX
|
||||
SG_ REL_SPEED : 44|10@1+ (1,-512) [-512|511] "km/s" XXX
|
||||
SG_ SETME_0x3 : 54|2@1+ (1,0) [0|3] "" XXX
|
||||
SG_ VALID : 56|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ SETME_0x0 : 57|7@1+ (1,0) [0|127] "" XXX
|
||||
|
||||
BO_ 852 RADAR_TRACK_4: 8 XXX
|
||||
SG_ LONG_DIST : 16|12@1- (0.06,-4) [-61.44|61.41] "m" XXX
|
||||
SG_ LAT_DIST : 28|10@1+ (0.05,-25.6) [-15.36|15.33] "m" XXX
|
||||
SG_ TRACK_ID : 38|6@1+ (1,0) [0|63] "" XXX
|
||||
SG_ REL_SPEED : 44|10@1+ (1,-512) [-512|511] "km/s" XXX
|
||||
SG_ SETME_0x3 : 54|2@1+ (1,0) [0|3] "" XXX
|
||||
SG_ VALID : 56|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ SETME_0x0 : 57|7@1+ (1,0) [0|127] "" XXX
|
||||
|
||||
BO_ 884 RADAR_TRACK_COMBINE: 8 XXX
|
||||
SG_ TRACK_ID : 0|3@1+ (1,0) [0|7] "bit" XXX
|
||||
SG_ TargetType : 4|4@1+ (1,0) [0|8] "bit" XXX
|
||||
SG_ LAT_DIST : 8|8@1+ (0.1,-12) [-100|100] "bit" XXX
|
||||
SG_ LONG_DIST : 16|8@1+ (1,-100) [-100|100] "bit" XXX
|
||||
SG_ REL_SPEED : 24|8@1+ (1,0) [0|254] "km/h" XXX
|
||||
SG_ REL_SPEED_H : 32|8@1+ (1,0) [0|254] "km/h" XXX
|
||||
SG_ VALID : 40|2@1+ (1,0) [0|3] "bit" XXX
|
||||
SG_ COUNTER : 52|4@1+ (1,0) [0|15] "bit" XXX
|
||||
SG_ CHECKSUM : 56|8@1+ (1,0) [0|255] "bit" XXX
|
||||
|
||||
BO_ 926 GAUGE_SPEED: 8 XXX
|
||||
SG_ GAUGE_SPEED : 8|8@1+ (1,0) [0|255] "" XXX
|
||||
|
||||
BO_ 944 PCM_BUTTONS: 8 XXX
|
||||
SG_ DISTANCE_BTN : 0|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ BTN_ACC_DEC : 3|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ SET_BTN : 6|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ SET_ME_0_1 : 7|1@1+ (1,0) [0|1] "" XXX
|
||||
SG_ ACC_ON_BTN : 8|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ SET_ME_0 : 9|1@1+ (1,0) [0|1] "" XXX
|
||||
SG_ RES_BTN : 10|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ SET_ME_2 : 11|3@1+ (1,0) [0|7] "" XXX
|
||||
SG_ LKAS_ON_BTN : 14|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ BTN_DIST_DOWN : 15|1@1+ (1,0) [0|1] "" XXX
|
||||
SG_ BTN_DIST_UP : 16|1@1+ (1,0) [0|1] "" XXX
|
||||
SG_ SET_ME_0_2 : 17|2@1+ (1,0) [0|1] "" XXX
|
||||
SG_ ACC_SWITCH : 19|1@1+ (1,0) [0|1] "" XXX
|
||||
SG_ SET_ME_XFFFFF : 20|32@1+ (1,0) [0|68719476735] "" XXX
|
||||
SG_ COUNTER : 52|4@1+ (1,0) [0|15] "" XXX
|
||||
SG_ CHECKSUM : 56|8@1+ (1,0) [0|255] "" XXX
|
||||
|
||||
BO_ 1048 BSM: 8 XXX
|
||||
SG_ LEFT_APPROACH : 9|2@0+ (1,0) [0|1] "" XXX
|
||||
SG_ RIGHT_APPROACH : 11|2@0+ (1,0) [0|1] "" XXX
|
||||
SG_ APPROACH : 17|1@0+ (1,0) [0|1] "" XXX
|
||||
|
||||
BO_ 1172 BRAKE_APPLIED_2: 8 XXX
|
||||
SG_ BRAKE_APPLIED_ACTIVE_LOW : 47|1@1+ (1,0) [0|1] "" XXX
|
||||
|
||||
VAL_ 307 TURN_SIGNAL_SWITCH 0 "Invalid" 1 "OFFGear" 2 "LeftSteeringShortLift" 3 "LeftSteeringLongLift" 4 "RightSteeringShortLift" 5 "RightSteeringLongLift" 7 "Unavaliable";
|
||||
VAL_ 508 TORQUE_TEMP_FAILED 2 "TooFast" 1 "TooLarge" 3 "Both";
|
||||
VAL_ 530 GEAR 4 "D" 2 "R" 3 "N" 1 "P";
|
||||
VAL_ 536 EPB_ACTIVE 0 "NotActive" 1 "Release" 2 "Apply" 3 "Reserved";
|
||||
VAL_ 536 EPB_STATUS 0 "Releasing" 1 "Released" 2 "Applying" 3 "Applied" 4 "FaultProhibitionOfRemoteDriving";
|
||||
VAL_ 578 GEAR 4 "D" 2 "R" 3 "N" 1 "P";
|
||||
VAL_ 790 Config 3 "FULL_TERRAIN" 2 "LKAS" 1 "ALERT" 0 "DISABLE";
|
||||
VAL_ 790 LKAS_Mode 0 "OFF" 1 "Passive" 2 "Active1" 3 "Active2" 4 "Fault" 5 "StandBy";
|
||||
VAL_ 813 SET_DISTANCE 4 "4bar" 3 "3bar" 2 "2bar" 1 "1bar";
|
||||
VAL_ 813 NOTIFY 4 "OVERRIDE" 3 "ENGAGE" 2 "DISENGAGE" 7 "ACC_ON" 8 "ACC_OFF" 0 "NONE";
|
||||
VAL_ 813 CRUISE_STATE 0 "OFF" 1 "Passive" 2 "StandBy" 3 "Active" 4 "BrakeOnly" 5 "Override" 6 "StandStillActive" 7 "StandStillWait" 8 "Failure" 9 "PermanentFailure";
|
||||
VAL_ 834 DRIVE_MODE 3 "NORMAL" 2 "SPORT" 1 "ECO";
|
||||
VAL_ 834 POWER_MODE 3 "HEV" 2 "FORCE_EV" 1 "EV";
|
||||
VAL_ 944 BTN_ACC_DEC 4 "ACC 10" 3 "ACC 1" 2
|
||||
@@ -34,6 +34,7 @@
|
||||
#define SAFETY_PSA 31U
|
||||
#define SAFETY_RIVIAN 33U
|
||||
#define SAFETY_VOLKSWAGEN_MEB 34U
|
||||
#define SAFETY_BYD 35U
|
||||
|
||||
#define GET_BIT(msg, b) ((bool)!!(((msg)->data[((b) / 8U)] >> ((b) % 8U)) & 0x1U))
|
||||
#define GET_FLAG(value, mask) (((value) & (mask)) == (mask))
|
||||
@@ -368,3 +369,4 @@ extern const safety_hooks volkswagen_meb_hooks;
|
||||
extern const safety_hooks volkswagen_pq_hooks;
|
||||
extern const safety_hooks rivian_hooks;
|
||||
extern const safety_hooks psa_hooks;
|
||||
extern const safety_hooks byd_hooks;
|
||||
@@ -0,0 +1,145 @@
|
||||
#include "opendbc/safety/declarations.h"
|
||||
|
||||
// MPC_LKAS_CMD (790), little endian
|
||||
#define BYD_GET_LKAS_OUTPUT(msg) (to_signed((((msg)->data[3] & 0x7U) << 8U) | (msg)->data[2], 11))
|
||||
#define BYD_LKAS_ACTIVE_BIT 28U
|
||||
// STEERING_TORQUE (792), little endian
|
||||
#define BYD_GET_MAIN_TORQUE(msg) (to_signed((((msg)->data[2] & 0xFU) << 8U) | (msg)->data[1], 12))
|
||||
#define BYD_GET_DRIVER_TORQUE(msg) (to_signed((((msg)->data[4] & 0xFU) << 8U) | (msg)->data[3], 12))
|
||||
// PCM_BUTTONS (944)
|
||||
#define BYD_LKAS_ON_BTN_BIT 14U
|
||||
|
||||
static bool byd_tx_hook(const CANPacket_t *msg) {
|
||||
const TorqueSteeringLimits BYD_STEERING_LIMITS = {
|
||||
.max_torque = 300,
|
||||
.max_rate_up = 6,
|
||||
.max_rate_down = 6,
|
||||
.max_rt_delta = 112, // 75 per 250ms at 50Hz steer rate, plus 50% buffer
|
||||
.type = TorqueMotorLimited,
|
||||
.driver_torque_allowance = 46,
|
||||
.driver_torque_multiplier = 1,
|
||||
.max_torque_error = 46,
|
||||
};
|
||||
|
||||
const LongitudinalLimits BYD_LONG_LIMITS = {
|
||||
.max_accel = 140, // 2.0 m/s^2 (raw = (m/s^2 + 5) / 0.05)
|
||||
.min_accel = 20, // -4.0 m/s^2
|
||||
.inactive_accel = 100, // 0 m/s^2, sent when longitudinal control is inactive
|
||||
};
|
||||
|
||||
bool tx = true;
|
||||
|
||||
// MPC_LKAS_CMD: steering actuation towards the EPS
|
||||
if (msg->addr == 790U) {
|
||||
int desired_torque = BYD_GET_LKAS_OUTPUT(msg);
|
||||
bool steer_req = GET_BIT(msg, BYD_LKAS_ACTIVE_BIT);
|
||||
|
||||
if (steer_torque_cmd_checks(desired_torque, steer_req, BYD_STEERING_LIMITS)) {
|
||||
tx = false;
|
||||
}
|
||||
}
|
||||
|
||||
// STEERING_TORQUE: feedback message towards the camera, torque echoes the
|
||||
// camera's own request. Only sanity-check the absolute limit so stock LKAS
|
||||
// requests don't fault when openpilot is inactive.
|
||||
if (msg->addr == 792U) {
|
||||
int main_torque = BYD_GET_MAIN_TORQUE(msg);
|
||||
if (safety_max_limit_check(main_torque, BYD_STEERING_LIMITS.max_torque, -BYD_STEERING_LIMITS.max_torque)) {
|
||||
tx = false;
|
||||
}
|
||||
}
|
||||
|
||||
// ACC_CMD: longitudinal actuation
|
||||
if (msg->addr == 814U) {
|
||||
int desired_accel = msg->data[0];
|
||||
|
||||
if (longitudinal_accel_checks(desired_accel, BYD_LONG_LIMITS)) {
|
||||
tx = false;
|
||||
}
|
||||
}
|
||||
|
||||
return tx;
|
||||
}
|
||||
|
||||
static void byd_rx_hook(const CANPacket_t *msg) {
|
||||
// Main Bus
|
||||
if (msg->bus == 0U) {
|
||||
// PEDAL
|
||||
if (msg->addr == 834U) {
|
||||
gas_pressed = msg->data[0] != 0U;
|
||||
brake_pressed = msg->data[1] != 0U;
|
||||
}
|
||||
// ESC
|
||||
if (msg->addr == 289U) {
|
||||
vehicle_moving = (((msg->data[1] & 0x0FU) << 8U) | msg->data[0]) != 0U;
|
||||
}
|
||||
// STEERING_TORQUE: sample EPS output torque and driver torque
|
||||
if (msg->addr == 792U) {
|
||||
int torque_meas_new = BYD_GET_MAIN_TORQUE(msg);
|
||||
update_sample(&torque_meas, torque_meas_new);
|
||||
torque_meas.min--;
|
||||
torque_meas.max++;
|
||||
|
||||
int torque_driver_new = BYD_GET_DRIVER_TORQUE(msg);
|
||||
update_sample(&torque_driver, torque_driver_new);
|
||||
}
|
||||
// PCM_BUTTONS: dedicated LKAS steering wheel button for MADS
|
||||
if (msg->addr == 944U) {
|
||||
mads_button_press = GET_BIT(msg, BYD_LKAS_ON_BTN_BIT) ? MADS_BUTTON_PRESSED : MADS_BUTTON_NOT_PRESSED;
|
||||
}
|
||||
}
|
||||
// Cam Bus
|
||||
else if (msg->bus == 2U) {
|
||||
// ACC_HUD_ADAS
|
||||
if (msg->addr == 813U) {
|
||||
// CRUISE_STATE in (3, 5) == (Active, Override)
|
||||
uint8_t cruise_state = (msg->data[5] >> 4U) & 0x0FU;
|
||||
pcm_cruise_check((cruise_state == 3U) || (cruise_state == 5U));
|
||||
}
|
||||
} else {
|
||||
}
|
||||
}
|
||||
|
||||
static safety_config byd_init(uint16_t param) {
|
||||
static const CanMsg BYD_TX_MSGS[] = {
|
||||
{790, 0, 8, .check_relay = true}, // MPC_LKAS_CMD
|
||||
{792, 2, 8, .check_relay = true}, // STEERING_TORQUE
|
||||
};
|
||||
|
||||
static const CanMsg BYD_TX_LONG_MSGS[] = {
|
||||
{790, 0, 8, .check_relay = true}, // MPC_LKAS_CMD
|
||||
{792, 2, 8, .check_relay = true}, // STEERING_TORQUE
|
||||
{814, 0, 8, .check_relay = true}, // ACC_CMD
|
||||
};
|
||||
|
||||
static RxCheck byd_rx_checks[] = {
|
||||
{.msg = {{578, 0, 8, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // DRIVE_STATE
|
||||
{.msg = {{544, 0, 8, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // BRAKE_APPLIED
|
||||
{.msg = {{834, 0, 8, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // PEDAL
|
||||
{.msg = {{289, 0, 8, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // ESC
|
||||
{.msg = {{287, 0, 5, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // STEER_MODULE
|
||||
{.msg = {{792, 0, 8, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // STEERING_TORQUE
|
||||
{.msg = {{944, 0, 8, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // PCM_BUTTONS
|
||||
{.msg = {{813, 2, 8, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // ACC_HUD_ADAS
|
||||
{.msg = {{307, 0, 8, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // STALKS
|
||||
{.msg = {{660, 0, 8, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // METER_CLUSTER
|
||||
{.msg = {{790, 2, 8, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // MPC_LKAS_CMD
|
||||
};
|
||||
|
||||
const uint16_t BYD_FLAG_LONG_CONTROL = 1;
|
||||
const bool byd_longitudinal = GET_FLAG(param, BYD_FLAG_LONG_CONTROL);
|
||||
|
||||
safety_config ret;
|
||||
if (byd_longitudinal) {
|
||||
ret = BUILD_SAFETY_CFG(byd_rx_checks, BYD_TX_LONG_MSGS);
|
||||
} else {
|
||||
ret = BUILD_SAFETY_CFG(byd_rx_checks, BYD_TX_MSGS);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
const safety_hooks byd_hooks = {
|
||||
.init = byd_init,
|
||||
.rx = byd_rx_hook,
|
||||
.tx = byd_tx_hook,
|
||||
};
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "opendbc/safety/modes/body.h"
|
||||
#include "opendbc/safety/modes/psa.h"
|
||||
#include "opendbc/safety/modes/hyundai_canfd.h"
|
||||
#include "opendbc/safety/modes/byd.h"
|
||||
|
||||
uint32_t GET_BYTES(const CANPacket_t *msg, int start, int len) {
|
||||
uint32_t ret = 0U;
|
||||
@@ -419,6 +420,7 @@ int set_safety_hooks(uint16_t mode, uint16_t param) {
|
||||
{SAFETY_RIVIAN, &rivian_hooks},
|
||||
{SAFETY_TESLA, &tesla_hooks},
|
||||
{SAFETY_HYUNDAI_CANFD, &hyundai_canfd_hooks},
|
||||
{SAFETY_BYD, &byd_hooks},
|
||||
#ifdef ALLOW_DEBUG
|
||||
{SAFETY_CHRYSLER_CUSW, &chrysler_cusw_hooks},
|
||||
{SAFETY_PSA, &psa_hooks},
|
||||
|
||||
@@ -1017,6 +1017,8 @@ class SafetyTest(SafetyTestBase):
|
||||
continue
|
||||
if attr.startswith('TestFord') and current_test.startswith('TestFord'):
|
||||
continue
|
||||
if attr.startswith('TestByd') and current_test.startswith('TestByd'):
|
||||
continue
|
||||
if attr.startswith('TestHyundaiCanfd') and current_test.startswith('TestHyundaiCanfd'):
|
||||
continue
|
||||
if {attr, current_test}.issubset({'TestHyundaiLongitudinalSafety', 'TestHyundaiLongitudinalSafetyCameraSCC', 'TestHyundaiSafetyFCEVLong'}):
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
#!/usr/bin/env python3
|
||||
import unittest
|
||||
|
||||
from opendbc.car.structs import CarParams
|
||||
from opendbc.safety.tests.libsafety import libsafety_py
|
||||
import opendbc.safety.tests.common as common
|
||||
from opendbc.safety.tests.common import CANPackerSafety
|
||||
|
||||
MSG_MPC_LKAS_CMD = 790 # TX by OP, lateral actuation towards EPS
|
||||
MSG_STEERING_TORQUE = 792 # RX from EPS / TX by OP, torque feedback towards camera
|
||||
MSG_ACC_HUD_ADAS = 813 # RX from camera, ACC state
|
||||
MSG_ACC_CMD = 814 # TX by OP, longitudinal actuation
|
||||
MSG_PCM_BUTTONS = 944 # RX from PCM, steering wheel buttons
|
||||
|
||||
|
||||
def byd_checksum(msg):
|
||||
addr, dat, bus = msg
|
||||
ret = bytearray(dat)
|
||||
|
||||
if addr in (MSG_MPC_LKAS_CMD, MSG_STEERING_TORQUE, MSG_ACC_CMD):
|
||||
byte_key = 0xAF
|
||||
sum_first = sum(byte >> 4 for byte in ret) # upper nibbles
|
||||
sum_second = sum(byte & 0xF for byte in ret) # lower nibbles
|
||||
|
||||
remainder = sum_second >> 4
|
||||
|
||||
sum_first += (byte_key & 0xF)
|
||||
sum_second += (byte_key >> 4)
|
||||
|
||||
inv_first = ((-sum_first + 0x9) & 0xF)
|
||||
inv_second = ((-sum_second + 0x9) & 0xF)
|
||||
|
||||
ret[7] = (((inv_first + (5 - remainder)) << 4) + inv_second) & 0xFF
|
||||
|
||||
return addr, ret, bus
|
||||
|
||||
|
||||
class TestBydSafetyBase(common.CarSafetyTest, common.MotorTorqueSteeringSafetyTest):
|
||||
TX_MSGS = [[MSG_MPC_LKAS_CMD, 0], [MSG_STEERING_TORQUE, 2]]
|
||||
STANDSTILL_THRESHOLD = 0
|
||||
RELAY_MALFUNCTION_ADDRS = {0: (MSG_MPC_LKAS_CMD,), 2: (MSG_STEERING_TORQUE,)}
|
||||
FWD_BLACKLISTED_ADDRS = {0: [MSG_STEERING_TORQUE], 2: [MSG_MPC_LKAS_CMD]}
|
||||
|
||||
MAX_TORQUE_LOOKUP = ([0], [300])
|
||||
MAX_RATE_UP = 6
|
||||
MAX_RATE_DOWN = 6
|
||||
MAX_RT_DELTA = 112
|
||||
MAX_TORQUE_ERROR = 46
|
||||
TORQUE_MEAS_TOLERANCE = 1
|
||||
|
||||
def setUp(self):
|
||||
self.packer = CANPackerSafety("byd_common")
|
||||
self.safety = libsafety_py.libsafety
|
||||
self.safety.set_safety_hooks(CarParams.SafetyModel.byd, 0)
|
||||
self.safety.init_tests()
|
||||
|
||||
def _torque_cmd_msg(self, torque, steer_req=1):
|
||||
values = {"LKAS_Output": torque, "LKAS_ACTIVE": steer_req}
|
||||
return self.packer.make_can_msg_safety("MPC_LKAS_CMD", 0, values, byd_checksum)
|
||||
|
||||
def _torque_meas_msg(self, torque):
|
||||
values = {"MAIN_TORQUE": torque}
|
||||
return self.packer.make_can_msg_safety("STEERING_TORQUE", 0, values)
|
||||
|
||||
def _torque_driver_msg(self, torque):
|
||||
values = {"Steer_Torque_Sensor": torque}
|
||||
return self.packer.make_can_msg_safety("STEERING_TORQUE", 0, values)
|
||||
|
||||
def _speed_msg(self, speed):
|
||||
values = {"VEHICLE_SPEED": speed}
|
||||
return self.packer.make_can_msg_safety("ESC", 0, values)
|
||||
|
||||
def _user_brake_msg(self, brake):
|
||||
values = {"BRAKE_PEDAL": brake}
|
||||
return self.packer.make_can_msg_safety("PEDAL", 0, values)
|
||||
|
||||
def _user_gas_msg(self, gas):
|
||||
values = {"GAS_PEDAL": gas}
|
||||
return self.packer.make_can_msg_safety("PEDAL", 0, values)
|
||||
|
||||
def _pcm_status_msg(self, enable):
|
||||
# CRUISE_STATE: 3 == Active, 0 == Off
|
||||
values = {"CRUISE_STATE": 3 if enable else 0}
|
||||
return self.packer.make_can_msg_safety("ACC_HUD_ADAS", 2, values)
|
||||
|
||||
def _lkas_button_msg(self, enabled):
|
||||
values = {"LKAS_ON_BTN": enabled}
|
||||
return self.packer.make_can_msg_safety("PCM_BUTTONS", 0, values)
|
||||
|
||||
def _acc_state_msg(self, enable):
|
||||
# BYD has no separate ACC main switch state in panda; MADS is toggled
|
||||
# with the dedicated LKAS steering wheel button instead
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class TestBydStockSafety(TestBydSafetyBase):
|
||||
pass
|
||||
|
||||
|
||||
class TestBydLongitudinalSafety(TestBydSafetyBase):
|
||||
TX_MSGS = [[MSG_MPC_LKAS_CMD, 0], [MSG_STEERING_TORQUE, 2], [MSG_ACC_CMD, 0]]
|
||||
RELAY_MALFUNCTION_ADDRS = {0: (MSG_MPC_LKAS_CMD, MSG_ACC_CMD), 2: (MSG_STEERING_TORQUE,)}
|
||||
FWD_BLACKLISTED_ADDRS = {0: [MSG_STEERING_TORQUE], 2: [MSG_MPC_LKAS_CMD, MSG_ACC_CMD]}
|
||||
|
||||
MIN_ACCEL = 20 # -4.0 m/s^2, raw = (m/s^2 + 5) / 0.05
|
||||
MAX_ACCEL = 140 # 2.0 m/s^2
|
||||
INACTIVE_ACCEL = 100 # 0 m/s^2
|
||||
|
||||
def setUp(self):
|
||||
self.packer = CANPackerSafety("byd_common")
|
||||
self.safety = libsafety_py.libsafety
|
||||
self.safety.set_safety_hooks(CarParams.SafetyModel.byd, 1) # BydSafetyFlags.LONG_CONTROL
|
||||
self.safety.init_tests()
|
||||
|
||||
def _accel_msg(self, accel: float):
|
||||
# accel in m/s^2, ACCEL_CMD raw = (m/s^2 + 5) / 0.05
|
||||
values = {"ACCEL_CMD": accel}
|
||||
return self.packer.make_can_msg_safety("ACC_CMD", 0, values, byd_checksum)
|
||||
|
||||
def test_accel_actuation_limits(self):
|
||||
self.safety.set_controls_allowed(True)
|
||||
for accel in [self.MIN_ACCEL - 1, self.MIN_ACCEL, 100, self.MAX_ACCEL, self.MAX_ACCEL + 1]:
|
||||
send = self.MIN_ACCEL <= accel <= self.MAX_ACCEL
|
||||
self.assertEqual(send, self._tx(self._accel_raw_msg(accel)), f"{accel=}")
|
||||
|
||||
def _accel_raw_msg(self, raw: int):
|
||||
msg = self._accel_msg(0)
|
||||
msg[0].data[0] = raw & 0xFF
|
||||
return msg
|
||||
|
||||
def test_accel_when_not_allowed(self):
|
||||
# when controls are not allowed, only 0 m/s^2 (inactive) may be sent
|
||||
self.safety.set_controls_allowed(False)
|
||||
self.assertTrue(self._tx(self._accel_raw_msg(self.INACTIVE_ACCEL)))
|
||||
self.assertFalse(self._tx(self._accel_raw_msg(self.INACTIVE_ACCEL + 5)))
|
||||
self.assertFalse(self._tx(self._accel_raw_msg(self.INACTIVE_ACCEL - 5)))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Whitespace-only changes.
@@ -0,0 +1,24 @@
|
||||
"""
|
||||
Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors.
|
||||
|
||||
This file is part of sunnypilot and is licensed under the MIT License.
|
||||
See the LICENSE.md file in the root directory for more details.
|
||||
"""
|
||||
|
||||
from enum import StrEnum
|
||||
|
||||
from opendbc.car import Bus, structs
|
||||
|
||||
from opendbc.sunnypilot.mads_base import MadsCarStateBase
|
||||
from opendbc.can.parser import CANParser
|
||||
|
||||
|
||||
class MadsCarState(MadsCarStateBase):
|
||||
def __init__(self, CP: structs.CarParams, CP_SP: structs.CarParamsSP):
|
||||
super().__init__(CP, CP_SP)
|
||||
|
||||
def update_mads(self, ret: structs.CarState, can_parsers: dict[StrEnum, CANParser]) -> None:
|
||||
cp = can_parsers[Bus.pt]
|
||||
|
||||
self.prev_lkas_button = self.lkas_button
|
||||
self.lkas_button = cp.vl["PCM_BUTTONS"]["LKAS_ON_BTN"]
|
||||
Reference in new issue
Block a user