Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions opendbc/car/body/interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,23 @@
from opendbc.car import get_safety_config, structs
from opendbc.car.body.carcontroller import CarController
from opendbc.car.body.carstate import CarState
from opendbc.car.body.values import SPEED_FROM_RPM
from opendbc.car.body.fingerprints import FW_VERSIONS, FINGERPRINTS
from opendbc.car.body.values import FW_QUERY_CONFIG, CAR, SPEED_FROM_RPM
from opendbc.car.interfaces import CarInterfaceBase


class CarInterface(CarInterfaceBase):
class BodyInterface(CarInterfaceBase):
CarState = CarState
CarController = CarController
CAR = CAR
BRAND = "body"
FW_QUERY_CONFIG = FW_QUERY_CONFIG
FW_VERSIONS = FW_VERSIONS
FINGERPRINTS = FINGERPRINTS

@staticmethod
def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams:
ret.notCar = True
ret.brand = "body"
ret.safetyConfigs = [get_safety_config(structs.CarParams.SafetyModel.body)]

ret.minSteerSpeed = -math.inf
Expand Down
43 changes: 12 additions & 31 deletions opendbc/car/car_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,36 +7,17 @@
from opendbc.car.structs import CarParams, CarParamsT
from opendbc.car.fingerprints import eliminate_incompatible_cars, all_legacy_fingerprint_cars
from opendbc.car.fw_versions import ObdCallback, get_fw_versions_ordered, get_present_ecus, match_fw_to_car
from opendbc.car.mock.values import CAR as MOCK
from opendbc.car.values import BRANDS
from opendbc.car.mock.interface import MockInterface
from opendbc.car.values import ALL_INTERFACES
from opendbc.car.vin import get_vin, is_valid_vin, VIN_UNKNOWN

FRAME_FINGERPRINT = 100 # 1s


def load_interfaces(brand_names):
ret = {}
for brand_name in brand_names:
path = f'opendbc.car.{brand_name}'
CarInterface = __import__(path + '.interface', fromlist=['CarInterface']).CarInterface
for model_name in brand_names[brand_name]:
ret[model_name] = CarInterface
return ret


def _get_interface_names() -> dict[str, list[str]]:
# returns a dict of brand name and its respective models
brand_names = {}
for brand in BRANDS:
brand_name = brand.__module__.split('.')[-2]
brand_names[brand_name] = [model.value for model in brand]

return brand_names


# imports from directory opendbc/car/<name>/
interface_names = _get_interface_names()
interfaces = load_interfaces(interface_names)
# Map every platform string to its brand's Interface. Interface carries
# its platform enum as a class attribute (CAR), so no dynamic import is needed.
interfaces: dict[str, type] = {
platform.value: ci for ci in ALL_INTERFACES for platform in ci.CAR
}


def can_fingerprint(can_recv: CanRecvCallable) -> tuple[str | None, dict[int, dict]]:
Expand Down Expand Up @@ -156,8 +137,8 @@ def get_car(can_recv: CanRecvCallable, can_send: CanSendCallable, set_obd_multip
carlog.error({"event": "car doesn't match any fingerprints", "fingerprints": repr(fingerprints)})
candidate = "MOCK"

CarInterface = interfaces[candidate]
CP: CarParams = CarInterface.get_params(candidate, fingerprints, car_fw, alpha_long_allowed, is_release, docs=False)
Interface = interfaces[candidate]
CP: CarParams = Interface.get_params(candidate, fingerprints, car_fw, alpha_long_allowed, is_release, docs=False)
CP.carVin = vin
CP.carFw = car_fw
CP.fingerprintSource = source
Expand All @@ -167,7 +148,7 @@ def get_car(can_recv: CanRecvCallable, can_send: CanSendCallable, set_obd_multip


def get_demo_car_params():
platform = MOCK.MOCK
CarInterface = interfaces[platform]
CP = CarInterface.get_non_essential_params(platform)
platform = MockInterface.CAR.MOCK
Interface = interfaces[platform]
CP = Interface.get_non_essential_params(platform)
return CP
10 changes: 7 additions & 3 deletions opendbc/car/chrysler/interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,24 @@
from opendbc.car.chrysler.carcontroller import CarController
from opendbc.car.chrysler.carstate import CarState
from opendbc.car.chrysler.radar_interface import RadarInterface
from opendbc.car.chrysler.values import CAR, CUSW_CARS, RAM_HD, RAM_DT, RAM_CARS, ChryslerFlags, ChryslerSafetyFlags
from opendbc.car.chrysler.fingerprints import FW_VERSIONS
from opendbc.car.chrysler.values import FW_QUERY_CONFIG, CAR, CUSW_CARS, RAM_HD, RAM_DT, RAM_CARS, ChryslerFlags, ChryslerSafetyFlags
from opendbc.car.interfaces import CarInterfaceBase


class CarInterface(CarInterfaceBase):
class ChryslerInterface(CarInterfaceBase):
CarState = CarState
CarController = CarController
RadarInterface = RadarInterface
CAR = CAR
BRAND = "chrysler"
FW_QUERY_CONFIG = FW_QUERY_CONFIG
FW_VERSIONS = FW_VERSIONS

DRIVABLE_GEARS = (structs.CarState.GearShifter.low,)

@staticmethod
def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams:
ret.brand = "chrysler"

# TODO: Chrysler CUSW in dashcam pending comma safety validation and a fix for LKAS fault on disengage
ret.dashcamOnly = candidate in (RAM_HD | CUSW_CARS)
Expand Down
8 changes: 4 additions & 4 deletions opendbc/car/docs.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@
from opendbc.car.structs import CarParams
from opendbc.car.docs_definitions import CarDocs, ExtraCarDocs, ExtraCarsColumn, CommonFootnote
from opendbc.car.car_helpers import interfaces
from opendbc.car.interfaces import get_interface_attr
from opendbc.car.values import FOOTNOTES
from opendbc.car.values import Platform
from opendbc.car.mock.values import CAR as MOCK
from opendbc.car.mock.interface import MockInterface
from opendbc.car.extra_cars import CAR as EXTRA


Expand All @@ -30,7 +30,7 @@


def get_params_for_docs(platform) -> CarParams:
cp_platform = platform if platform in interfaces else MOCK.MOCK
cp_platform = platform if platform in interfaces else MockInterface.CAR.MOCK
CP: CarParams = interfaces[cp_platform].get_params(cp_platform, fingerprint=gen_empty_fingerprint(),
car_fw=[CarParams.CarFw(ecu=CarParams.Ecu.unknown)],
alpha_long=True, is_release=True, docs=True)
Expand All @@ -39,7 +39,7 @@ def get_params_for_docs(platform) -> CarParams:

def get_all_footnotes() -> dict[Enum, int]:
all_footnotes = list(CommonFootnote)
for footnotes in get_interface_attr("Footnote", ignore_none=True).values():
for footnotes in FOOTNOTES:
all_footnotes.extend(footnotes)
return {fn: idx + 1 for idx, fn in enumerate(all_footnotes)}

Expand Down
5 changes: 1 addition & 4 deletions opendbc/car/fingerprints.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from opendbc.car.interfaces import get_interface_attr
from opendbc.car.values import FINGERPRINTS as _FINGERPRINTS
from opendbc.car.body.values import CAR as BODY
from opendbc.car.chrysler.values import CAR as CHRYSLER
from opendbc.car.ford.values import CAR as FORD
Expand All @@ -13,9 +13,6 @@
from opendbc.car.toyota.values import CAR as TOYOTA
from opendbc.car.volkswagen.values import CAR as VW

FW_VERSIONS = get_interface_attr('FW_VERSIONS', combine_brands=True, ignore_none=True)
_FINGERPRINTS = get_interface_attr('FINGERPRINTS', combine_brands=True, ignore_none=True)

_DEBUG_ADDRESS = {1880: 8} # reserved for debug purposes


Expand Down
11 changes: 8 additions & 3 deletions opendbc/car/ford/interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,22 @@
from opendbc.car.ford.carstate import CarState
from opendbc.car.ford.fordcan import CanBus
from opendbc.car.ford.radar_interface import RadarInterface
from opendbc.car.ford.values import CarControllerParams, DBC, Ecu, FordFlags, RADAR, FordSafetyFlags
from opendbc.car.ford.fingerprints import FW_VERSIONS
from opendbc.car.ford.values import Footnote, FW_QUERY_CONFIG, CAR, CarControllerParams, DBC, Ecu, FordFlags, RADAR, FordSafetyFlags
from opendbc.car.interfaces import CarInterfaceBase

TransmissionType = structs.CarParams.TransmissionType


class CarInterface(CarInterfaceBase):
class FordInterface(CarInterfaceBase):
CarState = CarState
CarController = CarController
RadarInterface = RadarInterface
CAR = CAR
BRAND = "ford"
FW_QUERY_CONFIG = FW_QUERY_CONFIG
FW_VERSIONS = FW_VERSIONS
Footnote = Footnote

DRIVABLE_GEARS = (structs.CarState.GearShifter.low, structs.CarState.GearShifter.manumatic)

Expand All @@ -29,7 +35,6 @@ def get_pid_accel_limits(CP, current_speed, cruise_speed):

@staticmethod
def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams:
ret.brand = "ford"

ret.radarUnavailable = Bus.radar not in DBC[candidate]
ret.steerControlType = structs.CarParams.SteerControlType.angle
Expand Down
8 changes: 2 additions & 6 deletions opendbc/car/fw_versions.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,13 @@
from opendbc.car.carlog import carlog
from opendbc.car.structs import CarParams
from opendbc.car.ecu_addrs import get_ecu_addrs
from opendbc.car.fingerprints import FW_VERSIONS
from opendbc.car.fw_query_definitions import ESSENTIAL_ECUS, AddrType, EcuAddrBusType, FwQueryConfig, LiveFwVersions, OfflineFwVersions
from opendbc.car.interfaces import get_interface_attr
from opendbc.car.values import FW_VERSIONS, FW_QUERY_CONFIGS, VERSIONS
from opendbc.car.fw_query_definitions import ESSENTIAL_ECUS, AddrType, EcuAddrBusType, LiveFwVersions, OfflineFwVersions
from opendbc.car.isotp_parallel_query import IsoTpParallelQuery

Ecu = CarParams.Ecu
FUZZY_EXCLUDE_ECUS = [Ecu.fwdCamera, Ecu.fwdRadar, Ecu.eps, Ecu.debug]

FW_QUERY_CONFIGS: dict[str, FwQueryConfig] = get_interface_attr('FW_QUERY_CONFIG', ignore_none=True)
VERSIONS = get_interface_attr('FW_VERSIONS', ignore_none=True)

MODEL_TO_BRAND = {c: b for b, e in VERSIONS.items() for c in e}
REQUESTS = [(brand, config, r) for brand, config in FW_QUERY_CONFIGS.items() for r in config.requests]

Expand Down
12 changes: 9 additions & 3 deletions opendbc/car/gm/interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
from opendbc.car.gm.carcontroller import CarController
from opendbc.car.gm.carstate import CarState
from opendbc.car.gm.radar_interface import RadarInterface, RADAR_HEADER_MSG, CAMERA_DATA_HEADER_MSG
from opendbc.car.gm.values import CAR, CarControllerParams, EV_CAR, CAMERA_ACC_CAR, SDGM_CAR, ALT_ACCS, CanBus, GMSafetyFlags
from opendbc.car.gm.fingerprints import FW_VERSIONS, FINGERPRINTS
from opendbc.car.gm.values import Footnote, FW_QUERY_CONFIG, CAR, CarControllerParams, EV_CAR, CAMERA_ACC_CAR, SDGM_CAR, ALT_ACCS, CanBus, GMSafetyFlags
from opendbc.car.interfaces import CarInterfaceBase, TorqueFromLateralAccelCallbackType, LateralAccelFromTorqueCallbackType

TransmissionType = structs.CarParams.TransmissionType
Expand All @@ -20,10 +21,16 @@
}


class CarInterface(CarInterfaceBase):
class GMInterface(CarInterfaceBase):
CarState = CarState
CarController = CarController
RadarInterface = RadarInterface
CAR = CAR
BRAND = "gm"
FW_QUERY_CONFIG = FW_QUERY_CONFIG
FW_VERSIONS = FW_VERSIONS
FINGERPRINTS = FINGERPRINTS
Footnote = Footnote

DRIVABLE_GEARS = (structs.CarState.GearShifter.sport, structs.CarState.GearShifter.low,
structs.CarState.GearShifter.eco, structs.CarState.GearShifter.manumatic)
Expand Down Expand Up @@ -86,7 +93,6 @@ def lateral_accel_from_torque_siglin(torque: float, torque_params: structs.CarPa

@staticmethod
def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams:
ret.brand = "gm"
ret.safetyConfigs = [get_safety_config(structs.CarParams.SafetyModel.gm)]
ret.autoResumeSng = False
ret.enableBsm = 0x142 in fingerprint[CanBus.POWERTRAIN]
Expand Down
13 changes: 9 additions & 4 deletions opendbc/car/honda/interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
from opendbc.car.common.conversions import Conversions as CV
from opendbc.car.disable_ecu import disable_ecu
from opendbc.car.honda.hondacan import CanBus
from opendbc.car.honda.values import CarControllerParams, HondaFlags, CAR, HondaSafetyFlags
from opendbc.car.honda.fingerprints import FW_VERSIONS
from opendbc.car.honda.values import Footnote, FW_QUERY_CONFIG, CarControllerParams, HondaFlags, CAR, HondaSafetyFlags
from opendbc.car.honda.carcontroller import CarController
from opendbc.car.honda.carstate import CarState
from opendbc.car.honda.radar_interface import RadarInterface
Expand All @@ -13,10 +14,15 @@
TransmissionType = structs.CarParams.TransmissionType


class CarInterface(CarInterfaceBase):
class HondaInterface(CarInterfaceBase):
CarState = CarState
CarController = CarController
RadarInterface = RadarInterface
CAR = CAR
BRAND = "honda"
FW_QUERY_CONFIG = FW_QUERY_CONFIG
FW_VERSIONS = FW_VERSIONS
Footnote = Footnote

DRIVABLE_GEARS = (structs.CarState.GearShifter.sport,)

Expand All @@ -33,7 +39,6 @@ def get_pid_accel_limits(CP, current_speed, cruise_speed):

@staticmethod
def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams:
ret.brand = "honda"

CAN = CanBus(ret, fingerprint)

Expand Down Expand Up @@ -252,4 +257,4 @@ def init(CP, can_recv, can_send, communication_control=None):
def deinit(CP, can_recv, can_send):
communication_control = bytes([uds.SERVICE_TYPE.COMMUNICATION_CONTROL, 0x80 | uds.CONTROL_TYPE.ENABLE_RX_ENABLE_TX,
uds.MESSAGE_TYPE.NORMAL_AND_NETWORK_MANAGEMENT])
CarInterface.init(CP, can_recv, can_send, communication_control)
HondaInterface.init(CP, can_recv, can_send, communication_control)
12 changes: 8 additions & 4 deletions opendbc/car/hyundai/interface.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from opendbc.car import Bus, get_safety_config, structs, uds
from opendbc.car.hyundai.hyundaicanfd import CanBus
from opendbc.car.hyundai.values import HyundaiFlags, CAR, DBC, HyundaiSafetyFlags
from opendbc.car.hyundai.fingerprints import FW_VERSIONS
from opendbc.car.hyundai.values import FW_QUERY_CONFIG, HyundaiFlags, CAR, DBC, HyundaiSafetyFlags
from opendbc.car.hyundai.radar_interface import RADAR_START_ADDR
from opendbc.car.interfaces import CarInterfaceBase
from opendbc.car.disable_ecu import disable_ecu
Expand All @@ -15,16 +16,19 @@
ENABLE_BUTTONS = (ButtonType.accelCruise, ButtonType.decelCruise, ButtonType.cancel, ButtonType.mainCruise)


class CarInterface(CarInterfaceBase):
class HyundaiInterface(CarInterfaceBase):
CarState = CarState
CarController = CarController
RadarInterface = RadarInterface
CAR = CAR
BRAND = "hyundai"
FW_QUERY_CONFIG = FW_QUERY_CONFIG
FW_VERSIONS = FW_VERSIONS

DRIVABLE_GEARS = (structs.CarState.GearShifter.sport, structs.CarState.GearShifter.manumatic)

@staticmethod
def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams:
ret.brand = "hyundai"

if ret.flags & HyundaiFlags.CANFD:
# Shared configuration for CAN-FD cars
Expand Down Expand Up @@ -171,4 +175,4 @@ def init(CP, can_recv, can_send, communication_control=None):
@staticmethod
def deinit(CP, can_recv, can_send):
communication_control = bytes([uds.SERVICE_TYPE.COMMUNICATION_CONTROL, 0x80 | uds.CONTROL_TYPE.ENABLE_RX_ENABLE_TX, uds.MESSAGE_TYPE.NORMAL])
CarInterface.init(CP, can_recv, can_send, communication_control)
HyundaiInterface.init(CP, can_recv, can_send, communication_control)
8 changes: 4 additions & 4 deletions opendbc/car/hyundai/tests/test_hyundai.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from opendbc.car import gen_empty_fingerprint
from opendbc.car.structs import CarParams
from opendbc.car.fw_versions import build_fw_dict
from opendbc.car.hyundai.interface import CarInterface
from opendbc.car.hyundai.interface import HyundaiInterface
from opendbc.car.hyundai.hyundaicanfd import CanBus
from opendbc.car.hyundai.radar_interface import RADAR_START_ADDR
from opendbc.car.hyundai.values import CAR, DATE_FW_ECUS, FW_QUERY_CONFIG, CANFD_FUZZY_WHITELIST, \
Expand Down Expand Up @@ -58,22 +58,22 @@ def test_feature_detection(self):
if lka_steering:
cam_can = CanBus(None, fingerprint).CAM
fingerprint[cam_can] = [0x50, 0x110] # LKA steering messages
CP = CarInterface.get_params(CAR.KIA_EV6, fingerprint, [], False, False, False)
CP = HyundaiInterface.get_params(CAR.KIA_EV6, fingerprint, [], False, False, False)
assert bool(CP.flags & HyundaiFlags.CANFD_LKA_STEER_MSG) == lka_steering

# radar available
for radar in (True, False):
fingerprint = gen_empty_fingerprint()
if radar:
fingerprint[1][RADAR_START_ADDR] = 8
CP = CarInterface.get_params(CAR.HYUNDAI_SONATA, fingerprint, [], False, False, False)
CP = HyundaiInterface.get_params(CAR.HYUNDAI_SONATA, fingerprint, [], False, False, False)
assert CP.radarUnavailable != radar

def test_alternate_limits(self):
# Alternate lateral control limits, for high torque cars, verify Panda safety mode flag is set
fingerprint = gen_empty_fingerprint()
for car_model in CAR:
CP = CarInterface.get_params(car_model, fingerprint, [], False, False, False)
CP = HyundaiInterface.get_params(car_model, fingerprint, [], False, False, False)
assert bool(CP.flags & HyundaiFlags.ALT_LIMITS) == bool(CP.safetyConfigs[-1].safetyParam & HyundaiSafetyFlags.ALT_LIMITS)

def test_can_features(self):
Expand Down
Loading
Loading