Subaru: move to flags within PlatformConfig (#31584)

* flags

* update ref

* use the flags directly

* use post_init (don't freeze)

* we can maintain frozen with custom class

* not preglobal

* move to common

* cleanup
old-commit-hash: 3a6c3315ab
chrysler-long2
Justin Newberry 1 year ago committed by GitHub
parent add26a5d1f
commit 9ccd7f15f9
  1. 11
      common/utils.py
  2. 22
      selfdrive/car/__init__.py
  3. 2
      selfdrive/car/chrysler/values.py
  4. 2
      selfdrive/car/ford/values.py
  5. 2
      selfdrive/car/gm/values.py
  6. 3
      selfdrive/car/interfaces.py
  7. 2
      selfdrive/car/nissan/values.py
  8. 13
      selfdrive/car/subaru/carcontroller.py
  9. 54
      selfdrive/car/subaru/carstate.py
  10. 23
      selfdrive/car/subaru/interface.py
  11. 42
      selfdrive/car/subaru/values.py
  12. 4
      selfdrive/car/volkswagen/values.py
  13. 2
      selfdrive/test/process_replay/ref_commit

@ -0,0 +1,11 @@
class Freezable:
_frozen: bool = False
def freeze(self):
if not self._frozen:
self._frozen = True
def __setattr__(self, *args, **kwargs):
if self._frozen:
raise Exception("cannot modify frozen object")
super().__setattr__(*args, **kwargs)

@ -1,12 +1,14 @@
# functions common among cars
from collections import namedtuple
from dataclasses import dataclass, field, replace
from enum import ReprEnum
from dataclasses import dataclass, field
from enum import IntFlag, ReprEnum
from dataclasses import replace
import capnp
from cereal import car
from openpilot.common.numpy_fast import clip, interp
from openpilot.common.utils import Freezable
from openpilot.selfdrive.car.docs_definitions import CarInfo
@ -256,11 +258,12 @@ class CarSpecs:
minEnableSpeed: float = field(default=-1.)
@dataclass(frozen=True, order=True)
class PlatformConfig:
@dataclass(order=True)
class PlatformConfig(Freezable):
platform_str: str
car_info: CarInfos
dbc_dict: DbcDict
flags: int = 0
specs: CarSpecs | None = None
@ -270,6 +273,13 @@ class PlatformConfig:
def override(self, **kwargs):
return replace(self, **kwargs)
def init(self):
pass
def __post_init__(self):
self.init()
self.freeze()
class Platforms(str, ReprEnum):
config: PlatformConfig
@ -287,3 +297,7 @@ class Platforms(str, ReprEnum):
@classmethod
def create_carinfo_map(cls) -> dict[str, CarInfos]:
return {p: p.config.car_info for p in cls}
@classmethod
def with_flags(cls, flags: IntFlag) -> set['Platforms']:
return {p for p in cls if p.config.flags & flags}

@ -19,7 +19,7 @@ class ChryslerCarInfo(CarInfo):
car_parts: CarParts = field(default_factory=CarParts.common([CarHarness.fca]))
@dataclass(frozen=True)
@dataclass
class ChryslerPlatformConfig(PlatformConfig):
dbc_dict: DbcDict = field(default_factory=lambda: dbc_dict('chrysler_pacifica_2017_hybrid_generated', None))

@ -64,7 +64,7 @@ class FordCarInfo(CarInfo):
self.car_parts = CarParts([Device.threex, harness])
@dataclass(frozen=True)
@dataclass
class FordPlatformConfig(PlatformConfig):
dbc_dict: DbcDict = field(default_factory=lambda: dbc_dict('ford_lincoln_base_pt', RADAR.DELPHI_MRR))

@ -79,7 +79,7 @@ class GMCarInfo(CarInfo):
self.footnotes.append(Footnote.OBD_II)
@dataclass(frozen=True)
@dataclass
class GMPlatformConfig(PlatformConfig):
dbc_dict: DbcDict = field(default_factory=lambda: dbc_dict('gm_global_a_powertrain_generated', 'gm_global_a_object', chassis_dbc='gm_global_a_chassis'))

@ -120,6 +120,7 @@ class CarInterfaceBase(ABC):
ret.centerToFront = ret.wheelbase * candidate.config.specs.centerToFrontRatio
ret.minEnableSpeed = candidate.config.specs.minEnableSpeed
ret.minSteerSpeed = candidate.config.specs.minSteerSpeed
ret.flags |= int(candidate.config.flags)
ret = cls._get_params(ret, candidate, fingerprint, car_fw, experimental_long, docs)
@ -135,7 +136,7 @@ class CarInterfaceBase(ABC):
@staticmethod
@abstractmethod
def _get_params(ret: car.CarParams, candidate: Platform, fingerprint: dict[int, dict[int, int]],
def _get_params(ret: car.CarParams, candidate, fingerprint: dict[int, dict[int, int]],
car_fw: list[car.CarParams.CarFw], experimental_long: bool, docs: bool):
raise NotImplementedError

@ -31,7 +31,7 @@ class NissanCarSpecs(CarSpecs):
steerRatio: float = 17.
@dataclass(frozen=True)
@dataclass
class NissanPlaformConfig(PlatformConfig):
dbc_dict: DbcDict = field(default_factory=lambda: dbc_dict('nissan_x_trail_2017_generated', None))

@ -3,8 +3,7 @@ from opendbc.can.packer import CANPacker
from openpilot.selfdrive.car import apply_driver_steer_torque_limits, common_fault_avoidance
from openpilot.selfdrive.car.interfaces import CarControllerBase
from openpilot.selfdrive.car.subaru import subarucan
from openpilot.selfdrive.car.subaru.values import DBC, GLOBAL_ES_ADDR, GLOBAL_GEN2, PREGLOBAL_CARS, HYBRID_CARS, STEER_RATE_LIMITED, \
CanBus, CarControllerParams, SubaruFlags
from openpilot.selfdrive.car.subaru.values import DBC, GLOBAL_ES_ADDR, CanBus, CarControllerParams, SubaruFlags
# FIXME: These limits aren't exact. The real limit is more than likely over a larger time period and
# involves the total steering angle change rather than rate, but these limits work well for now
@ -43,12 +42,12 @@ class CarController(CarControllerBase):
if not CC.latActive:
apply_steer = 0
if self.CP.carFingerprint in PREGLOBAL_CARS:
if self.CP.flags & SubaruFlags.PREGLOBAL:
can_sends.append(subarucan.create_preglobal_steering_control(self.packer, self.frame // self.p.STEER_STEP, apply_steer, CC.latActive))
else:
apply_steer_req = CC.latActive
if self.CP.carFingerprint in STEER_RATE_LIMITED:
if self.CP.flags & SubaruFlags.STEER_RATE_LIMITED:
# Steering rate fault prevention
self.steer_rate_counter, apply_steer_req = \
common_fault_avoidance(abs(CS.out.steeringRateDeg) > MAX_STEER_RATE, apply_steer_req,
@ -75,7 +74,7 @@ class CarController(CarControllerBase):
cruise_brake = CarControllerParams.BRAKE_MIN
# *** alerts and pcm cancel ***
if self.CP.carFingerprint in PREGLOBAL_CARS:
if self.CP.flags & SubaruFlags.PREGLOBAL:
if self.frame % 5 == 0:
# 1 = main, 2 = set shallow, 3 = set deep, 4 = resume shallow, 5 = resume deep
# disengage ACC when OP is disengaged
@ -118,8 +117,8 @@ class CarController(CarControllerBase):
self.CP.openpilotLongitudinalControl, cruise_brake > 0, cruise_throttle))
else:
if pcm_cancel_cmd:
if self.CP.carFingerprint not in HYBRID_CARS:
bus = CanBus.alt if self.CP.carFingerprint in GLOBAL_GEN2 else CanBus.main
if not (self.CP.flags & SubaruFlags.HYBRID):
bus = CanBus.alt if self.CP.flags & SubaruFlags.GLOBAL_GEN2 else CanBus.main
can_sends.append(subarucan.create_es_distance(self.packer, CS.es_distance_msg["COUNTER"] + 1, CS.es_distance_msg, bus, pcm_cancel_cmd))
if self.CP.flags & SubaruFlags.DISABLE_EYESIGHT:

@ -4,7 +4,7 @@ from opendbc.can.can_define import CANDefine
from openpilot.common.conversions import Conversions as CV
from openpilot.selfdrive.car.interfaces import CarStateBase
from opendbc.can.parser import CANParser
from openpilot.selfdrive.car.subaru.values import DBC, GLOBAL_GEN2, PREGLOBAL_CARS, HYBRID_CARS, CanBus, SubaruFlags
from openpilot.selfdrive.car.subaru.values import DBC, CanBus, SubaruFlags
from openpilot.selfdrive.car import CanSignalRateCalculator
@ -19,17 +19,17 @@ class CarState(CarStateBase):
def update(self, cp, cp_cam, cp_body):
ret = car.CarState.new_message()
throttle_msg = cp.vl["Throttle"] if self.car_fingerprint not in HYBRID_CARS else cp_body.vl["Throttle_Hybrid"]
throttle_msg = cp.vl["Throttle"] if not (self.CP.flags & SubaruFlags.HYBRID) else cp_body.vl["Throttle_Hybrid"]
ret.gas = throttle_msg["Throttle_Pedal"] / 255.
ret.gasPressed = ret.gas > 1e-5
if self.car_fingerprint in PREGLOBAL_CARS:
if self.CP.flags & SubaruFlags.PREGLOBAL:
ret.brakePressed = cp.vl["Brake_Pedal"]["Brake_Pedal"] > 0
else:
cp_brakes = cp_body if self.car_fingerprint in GLOBAL_GEN2 else cp
cp_brakes = cp_body if self.CP.flags & SubaruFlags.GLOBAL_GEN2 else cp
ret.brakePressed = cp_brakes.vl["Brake_Status"]["Brake"] == 1
cp_wheels = cp_body if self.car_fingerprint in GLOBAL_GEN2 else cp
cp_wheels = cp_body if self.CP.flags & SubaruFlags.GLOBAL_GEN2 else cp
ret.wheelSpeeds = self.get_wheel_speeds(
cp_wheels.vl["Wheel_Speeds"]["FL"],
cp_wheels.vl["Wheel_Speeds"]["FR"],
@ -48,24 +48,24 @@ class CarState(CarStateBase):
ret.leftBlindspot = (cp.vl["BSD_RCTA"]["L_ADJACENT"] == 1) or (cp.vl["BSD_RCTA"]["L_APPROACHING"] == 1)
ret.rightBlindspot = (cp.vl["BSD_RCTA"]["R_ADJACENT"] == 1) or (cp.vl["BSD_RCTA"]["R_APPROACHING"] == 1)
cp_transmission = cp_body if self.car_fingerprint in HYBRID_CARS else cp
cp_transmission = cp_body if self.CP.flags & SubaruFlags.HYBRID else cp
can_gear = int(cp_transmission.vl["Transmission"]["Gear"])
ret.gearShifter = self.parse_gear_shifter(self.shifter_values.get(can_gear, None))
ret.steeringAngleDeg = cp.vl["Steering_Torque"]["Steering_Angle"]
if self.car_fingerprint not in PREGLOBAL_CARS:
if not (self.CP.flags & SubaruFlags.PREGLOBAL):
# ideally we get this from the car, but unclear if it exists. diagnostic software doesn't even have it
ret.steeringRateDeg = self.angle_rate_calulator.update(ret.steeringAngleDeg, cp.vl["Steering_Torque"]["COUNTER"])
ret.steeringTorque = cp.vl["Steering_Torque"]["Steer_Torque_Sensor"]
ret.steeringTorqueEps = cp.vl["Steering_Torque"]["Steer_Torque_Output"]
steer_threshold = 75 if self.CP.carFingerprint in PREGLOBAL_CARS else 80
steer_threshold = 75 if self.CP.flags & SubaruFlags.PREGLOBAL else 80
ret.steeringPressed = abs(ret.steeringTorque) > steer_threshold
cp_cruise = cp_body if self.car_fingerprint in GLOBAL_GEN2 else cp
if self.car_fingerprint in HYBRID_CARS:
cp_cruise = cp_body if self.CP.flags & SubaruFlags.GLOBAL_GEN2 else cp
if self.CP.flags & SubaruFlags.HYBRID:
ret.cruiseState.enabled = cp_cam.vl["ES_DashStatus"]['Cruise_Activated'] != 0
ret.cruiseState.available = cp_cam.vl["ES_DashStatus"]['Cruise_On'] != 0
else:
@ -73,8 +73,8 @@ class CarState(CarStateBase):
ret.cruiseState.available = cp_cruise.vl["CruiseControl"]["Cruise_On"] != 0
ret.cruiseState.speed = cp_cam.vl["ES_DashStatus"]["Cruise_Set_Speed"] * CV.KPH_TO_MS
if (self.car_fingerprint in PREGLOBAL_CARS and cp.vl["Dash_State2"]["UNITS"] == 1) or \
(self.car_fingerprint not in PREGLOBAL_CARS and cp.vl["Dashlights"]["UNITS"] == 1):
if (self.CP.flags & SubaruFlags.PREGLOBAL and cp.vl["Dash_State2"]["UNITS"] == 1) or \
(not (self.CP.flags & SubaruFlags.PREGLOBAL) and cp.vl["Dashlights"]["UNITS"] == 1):
ret.cruiseState.speed *= CV.MPH_TO_KPH
ret.seatbeltUnlatched = cp.vl["Dashlights"]["SEATBELT_FL"] == 1
@ -84,8 +84,8 @@ class CarState(CarStateBase):
cp.vl["BodyInfo"]["DOOR_OPEN_FL"]])
ret.steerFaultPermanent = cp.vl["Steering_Torque"]["Steer_Error_1"] == 1
cp_es_distance = cp_body if self.car_fingerprint in (GLOBAL_GEN2 | HYBRID_CARS) else cp_cam
if self.car_fingerprint in PREGLOBAL_CARS:
cp_es_distance = cp_body if self.CP.flags & (SubaruFlags.GLOBAL_GEN2 | SubaruFlags.HYBRID) else cp_cam
if self.CP.flags & SubaruFlags.PREGLOBAL:
self.cruise_button = cp_cam.vl["ES_Distance"]["Cruise_Button"]
self.ready = not cp_cam.vl["ES_DashStatus"]["Not_Ready_Startup"]
else:
@ -96,12 +96,12 @@ class CarState(CarStateBase):
(cp_cam.vl["ES_LKAS_State"]["LKAS_Alert"] == 2)
self.es_lkas_state_msg = copy.copy(cp_cam.vl["ES_LKAS_State"])
cp_es_brake = cp_body if self.car_fingerprint in GLOBAL_GEN2 else cp_cam
cp_es_brake = cp_body if self.CP.flags & SubaruFlags.GLOBAL_GEN2 else cp_cam
self.es_brake_msg = copy.copy(cp_es_brake.vl["ES_Brake"])
cp_es_status = cp_body if self.car_fingerprint in GLOBAL_GEN2 else cp_cam
cp_es_status = cp_body if self.CP.flags & SubaruFlags.GLOBAL_GEN2 else cp_cam
# TODO: Hybrid cars don't have ES_Distance, need a replacement
if self.car_fingerprint not in HYBRID_CARS:
if not (self.CP.flags & SubaruFlags.HYBRID):
# 8 is known AEB, there are a few other values related to AEB we ignore
ret.stockAeb = (cp_es_distance.vl["ES_Brake"]["AEB_Status"] == 8) and \
(cp_es_distance.vl["ES_Brake"]["Brake_Pressure"] != 0)
@ -109,7 +109,7 @@ class CarState(CarStateBase):
self.es_status_msg = copy.copy(cp_es_status.vl["ES_Status"])
self.cruise_control_msg = copy.copy(cp_cruise.vl["CruiseControl"])
if self.car_fingerprint not in HYBRID_CARS:
if not (self.CP.flags & SubaruFlags.HYBRID):
self.es_distance_msg = copy.copy(cp_es_distance.vl["ES_Distance"])
self.es_dashstatus_msg = copy.copy(cp_cam.vl["ES_DashStatus"])
@ -125,7 +125,7 @@ class CarState(CarStateBase):
("Brake_Status", 50),
]
if CP.carFingerprint not in HYBRID_CARS:
if not (CP.flags & SubaruFlags.HYBRID):
messages.append(("CruiseControl", 20))
return messages
@ -136,7 +136,7 @@ class CarState(CarStateBase):
("ES_Brake", 20),
]
if CP.carFingerprint not in HYBRID_CARS:
if not (CP.flags & SubaruFlags.HYBRID):
messages += [
("ES_Distance", 20),
("ES_Status", 20)
@ -164,7 +164,7 @@ class CarState(CarStateBase):
("Brake_Pedal", 50),
]
if CP.carFingerprint not in HYBRID_CARS:
if not (CP.flags & SubaruFlags.HYBRID):
messages += [
("Throttle", 100),
("Transmission", 100)
@ -173,8 +173,8 @@ class CarState(CarStateBase):
if CP.enableBsm:
messages.append(("BSD_RCTA", 17))
if CP.carFingerprint not in PREGLOBAL_CARS:
if CP.carFingerprint not in GLOBAL_GEN2:
if not (CP.flags & SubaruFlags.PREGLOBAL):
if not (CP.flags & SubaruFlags.GLOBAL_GEN2):
messages += CarState.get_common_global_body_messages(CP)
else:
messages += CarState.get_common_preglobal_body_messages()
@ -183,7 +183,7 @@ class CarState(CarStateBase):
@staticmethod
def get_cam_can_parser(CP):
if CP.carFingerprint in PREGLOBAL_CARS:
if CP.flags & SubaruFlags.PREGLOBAL:
messages = [
("ES_DashStatus", 20),
("ES_Distance", 20),
@ -194,7 +194,7 @@ class CarState(CarStateBase):
("ES_LKAS_State", 10),
]
if CP.carFingerprint not in GLOBAL_GEN2:
if not (CP.flags & SubaruFlags.GLOBAL_GEN2):
messages += CarState.get_common_global_es_messages(CP)
if CP.flags & SubaruFlags.SEND_INFOTAINMENT:
@ -206,11 +206,11 @@ class CarState(CarStateBase):
def get_body_can_parser(CP):
messages = []
if CP.carFingerprint in GLOBAL_GEN2:
if CP.flags & SubaruFlags.GLOBAL_GEN2:
messages += CarState.get_common_global_body_messages(CP)
messages += CarState.get_common_global_es_messages(CP)
if CP.carFingerprint in HYBRID_CARS:
if CP.flags & SubaruFlags.HYBRID:
messages += [
("Throttle_Hybrid", 40),
("Transmission", 100)

@ -1,42 +1,43 @@
from cereal import car
from panda import Panda
from openpilot.selfdrive.car import get_safety_config
from openpilot.selfdrive.car.values import Platform
from openpilot.selfdrive.car.disable_ecu import disable_ecu
from openpilot.selfdrive.car.interfaces import CarInterfaceBase
from openpilot.selfdrive.car.subaru.values import CAR, GLOBAL_ES_ADDR, LKAS_ANGLE, GLOBAL_GEN2, PREGLOBAL_CARS, HYBRID_CARS, SubaruFlags
from openpilot.selfdrive.car.subaru.values import CAR, GLOBAL_ES_ADDR, SubaruFlags
class CarInterface(CarInterfaceBase):
@staticmethod
def _get_params(ret, candidate: Platform, fingerprint, car_fw, experimental_long, docs):
def _get_params(ret, candidate: CAR, fingerprint, car_fw, experimental_long, docs):
platform_flags = candidate.config.flags
ret.carName = "subaru"
ret.radarUnavailable = True
# for HYBRID CARS to be upstreamed, we need:
# - replacement for ES_Distance so we can cancel the cruise control
# - to find the Cruise_Activated bit from the car
# - proper panda safety setup (use the correct cruise_activated bit, throttle from Throttle_Hybrid, etc)
ret.dashcamOnly = candidate in (PREGLOBAL_CARS | LKAS_ANGLE | HYBRID_CARS)
ret.dashcamOnly = bool(platform_flags & (SubaruFlags.PREGLOBAL | SubaruFlags.LKAS_ANGLE | SubaruFlags.HYBRID))
ret.autoResumeSng = False
# Detect infotainment message sent from the camera
if candidate not in PREGLOBAL_CARS and 0x323 in fingerprint[2]:
if not (platform_flags & SubaruFlags.PREGLOBAL) and 0x323 in fingerprint[2]:
ret.flags |= SubaruFlags.SEND_INFOTAINMENT.value
if candidate in PREGLOBAL_CARS:
if platform_flags & SubaruFlags.PREGLOBAL:
ret.enableBsm = 0x25c in fingerprint[0]
ret.safetyConfigs = [get_safety_config(car.CarParams.SafetyModel.subaruPreglobal)]
else:
ret.enableBsm = 0x228 in fingerprint[0]
ret.safetyConfigs = [get_safety_config(car.CarParams.SafetyModel.subaru)]
if candidate in GLOBAL_GEN2:
if platform_flags & SubaruFlags.GLOBAL_GEN2:
ret.safetyConfigs[0].safetyParam |= Panda.FLAG_SUBARU_GEN2
ret.steerLimitTimer = 0.4
ret.steerActuatorDelay = 0.1
if candidate in LKAS_ANGLE:
if platform_flags & SubaruFlags.LKAS_ANGLE:
ret.steerControlType = car.CarParams.SteerControlType.angle
else:
CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning)
@ -84,10 +85,12 @@ class CarInterface(CarInterfaceBase):
else:
raise ValueError(f"unknown car: {candidate}")
ret.experimentalLongitudinalAvailable = candidate not in (GLOBAL_GEN2 | PREGLOBAL_CARS | LKAS_ANGLE | HYBRID_CARS)
LONG_UNAVAILABLE = SubaruFlags.GLOBAL_GEN2 | SubaruFlags.PREGLOBAL| SubaruFlags.LKAS_ANGLE | SubaruFlags.HYBRID
ret.experimentalLongitudinalAvailable = not (platform_flags & LONG_UNAVAILABLE)
ret.openpilotLongitudinalControl = experimental_long and ret.experimentalLongitudinalAvailable
if candidate in GLOBAL_GEN2 and ret.openpilotLongitudinalControl:
if platform_flags & SubaruFlags.GLOBAL_GEN2 and ret.openpilotLongitudinalControl:
ret.flags |= SubaruFlags.DISABLE_EYESIGHT.value
if ret.openpilotLongitudinalControl:

@ -19,7 +19,7 @@ class CarControllerParams:
self.STEER_DRIVER_MULTIPLIER = 50 # weight driver torque heavily
self.STEER_DRIVER_FACTOR = 1 # from dbc
if CP.carFingerprint in GLOBAL_GEN2:
if CP.flags & SubaruFlags.GLOBAL_GEN2:
self.STEER_MAX = 1000
self.STEER_DELTA_UP = 40
self.STEER_DELTA_DOWN = 40
@ -55,6 +55,14 @@ class CarControllerParams:
class SubaruFlags(IntFlag):
SEND_INFOTAINMENT = 1
DISABLE_EYESIGHT = 2
GLOBAL_GEN2 = 4
# Cars that temporarily fault when steering angle rate is greater than some threshold.
# Appears to be all torque-based cars produced around 2019 - present
STEER_RATE_LIMITED = 8
PREGLOBAL = 16
HYBRID = 32
LKAS_ANGLE = 64
GLOBAL_ES_ADDR = 0x787
@ -89,10 +97,14 @@ class SubaruCarInfo(CarInfo):
self.footnotes.append(Footnote.EXP_LONG)
@dataclass(frozen=True)
@dataclass
class SubaruPlatformConfig(PlatformConfig):
dbc_dict: DbcDict = field(default_factory=lambda: dbc_dict('subaru_global_2017_generated', None))
def init(self):
if self.flags & SubaruFlags.HYBRID:
self.dbc_dict = dbc_dict('subaru_global_2020_hybrid_generated', None)
class CAR(Platforms):
# Global platform
@ -105,11 +117,13 @@ class CAR(Platforms):
"SUBARU OUTBACK 6TH GEN",
SubaruCarInfo("Subaru Outback 2020-22", "All", car_parts=CarParts.common([CarHarness.subaru_b])),
specs=CarSpecs(mass=1568, wheelbase=2.67, steerRatio=17),
flags=SubaruFlags.GLOBAL_GEN2 | SubaruFlags.STEER_RATE_LIMITED,
)
LEGACY = SubaruPlatformConfig(
"SUBARU LEGACY 7TH GEN",
SubaruCarInfo("Subaru Legacy 2020-22", "All", car_parts=CarParts.common([CarHarness.subaru_b])),
specs=OUTBACK.specs,
flags=SubaruFlags.GLOBAL_GEN2 | SubaruFlags.STEER_RATE_LIMITED,
)
IMPREZA = SubaruPlatformConfig(
"SUBARU IMPREZA LIMITED 2019",
@ -128,24 +142,26 @@ class CAR(Platforms):
SubaruCarInfo("Subaru XV 2020-21"),
],
specs=CarSpecs(mass=1480, wheelbase=2.67, steerRatio=17),
flags=SubaruFlags.STEER_RATE_LIMITED,
)
# TODO: is there an XV and Impreza too?
CROSSTREK_HYBRID = SubaruPlatformConfig(
"SUBARU CROSSTREK HYBRID 2020",
SubaruCarInfo("Subaru Crosstrek Hybrid 2020", car_parts=CarParts.common([CarHarness.subaru_b])),
dbc_dict('subaru_global_2020_hybrid_generated', None),
specs=CarSpecs(mass=1668, wheelbase=2.67, steerRatio=17),
flags=SubaruFlags.HYBRID,
)
FORESTER = SubaruPlatformConfig(
"SUBARU FORESTER 2019",
SubaruCarInfo("Subaru Forester 2019-21", "All"),
specs=CarSpecs(mass=1568, wheelbase=2.67, steerRatio=17),
flags=SubaruFlags.STEER_RATE_LIMITED,
)
FORESTER_HYBRID = SubaruPlatformConfig(
"SUBARU FORESTER HYBRID 2020",
SubaruCarInfo("Subaru Forester Hybrid 2020"),
dbc_dict('subaru_global_2020_hybrid_generated', None),
specs=FORESTER.specs,
flags=SubaruFlags.HYBRID,
)
# Pre-global
FORESTER_PREGLOBAL = SubaruPlatformConfig(
@ -153,52 +169,50 @@ class CAR(Platforms):
SubaruCarInfo("Subaru Forester 2017-18"),
dbc_dict('subaru_forester_2017_generated', None),
specs=CarSpecs(mass=1568, wheelbase=2.67, steerRatio=20),
flags=SubaruFlags.PREGLOBAL,
)
LEGACY_PREGLOBAL = SubaruPlatformConfig(
"SUBARU LEGACY 2015 - 2018",
SubaruCarInfo("Subaru Legacy 2015-18"),
dbc_dict('subaru_outback_2015_generated', None),
specs=CarSpecs(mass=1568, wheelbase=2.67, steerRatio=12.5),
flags=SubaruFlags.PREGLOBAL,
)
OUTBACK_PREGLOBAL = SubaruPlatformConfig(
"SUBARU OUTBACK 2015 - 2017",
SubaruCarInfo("Subaru Outback 2015-17"),
dbc_dict('subaru_outback_2015_generated', None),
specs=FORESTER_PREGLOBAL.specs,
flags=SubaruFlags.PREGLOBAL,
)
OUTBACK_PREGLOBAL_2018 = SubaruPlatformConfig(
"SUBARU OUTBACK 2018 - 2019",
SubaruCarInfo("Subaru Outback 2018-19"),
dbc_dict('subaru_outback_2019_generated', None),
specs=FORESTER_PREGLOBAL.specs,
flags=SubaruFlags.PREGLOBAL,
)
# Angle LKAS
FORESTER_2022 = SubaruPlatformConfig(
"SUBARU FORESTER 2022",
SubaruCarInfo("Subaru Forester 2022-24", "All", car_parts=CarParts.common([CarHarness.subaru_c])),
specs=FORESTER.specs,
flags=SubaruFlags.LKAS_ANGLE,
)
OUTBACK_2023 = SubaruPlatformConfig(
"SUBARU OUTBACK 7TH GEN",
SubaruCarInfo("Subaru Outback 2023", "All", car_parts=CarParts.common([CarHarness.subaru_d])),
specs=OUTBACK.specs,
flags=SubaruFlags.GLOBAL_GEN2 | SubaruFlags.LKAS_ANGLE,
)
ASCENT_2023 = SubaruPlatformConfig(
"SUBARU ASCENT 2023",
SubaruCarInfo("Subaru Ascent 2023", "All", car_parts=CarParts.common([CarHarness.subaru_d])),
specs=ASCENT.specs,
flags=SubaruFlags.GLOBAL_GEN2 | SubaruFlags.LKAS_ANGLE,
)
LKAS_ANGLE = {CAR.FORESTER_2022, CAR.OUTBACK_2023, CAR.ASCENT_2023}
GLOBAL_GEN2 = {CAR.OUTBACK, CAR.LEGACY, CAR.OUTBACK_2023, CAR.ASCENT_2023}
PREGLOBAL_CARS = {CAR.FORESTER_PREGLOBAL, CAR.LEGACY_PREGLOBAL, CAR.OUTBACK_PREGLOBAL, CAR.OUTBACK_PREGLOBAL_2018}
HYBRID_CARS = {CAR.CROSSTREK_HYBRID, CAR.FORESTER_HYBRID}
# Cars that temporarily fault when steering angle rate is greater than some threshold.
# Appears to be all torque-based cars produced around 2019 - present
STEER_RATE_LIMITED = GLOBAL_GEN2 | {CAR.IMPREZA_2020, CAR.FORESTER}
SUBARU_VERSION_REQUEST = bytes([uds.SERVICE_TYPE.READ_DATA_BY_IDENTIFIER]) + \
p16(uds.DATA_IDENTIFIER_TYPE.APPLICATION_DATA_IDENTIFICATION)
SUBARU_VERSION_RESPONSE = bytes([uds.SERVICE_TYPE.READ_DATA_BY_IDENTIFIER + 0x40]) + \
@ -235,7 +249,7 @@ FW_QUERY_CONFIG = FwQueryConfig(
],
# We don't get the EPS from non-OBD queries on GEN2 cars. Note that we still attempt to match when it exists
non_essential_ecus={
Ecu.eps: list(GLOBAL_GEN2),
Ecu.eps: list(CAR.with_flags(SubaruFlags.GLOBAL_GEN2)),
}
)

@ -112,11 +112,11 @@ class CANBUS:
class VolkswagenFlags(IntFlag):
STOCK_HCA_PRESENT = 1
@dataclass(frozen=True)
@dataclass
class VolkswagenMQBPlatformConfig(PlatformConfig):
dbc_dict: DbcDict = field(default_factory=lambda: dbc_dict('vw_mqb_2010', None))
@dataclass(frozen=True)
@dataclass
class VolkswagenPQPlatformConfig(PlatformConfig):
dbc_dict: DbcDict = field(default_factory=lambda: dbc_dict('vw_golf_mk4', None))

@ -1 +1 @@
dab93e072903e80f91029a03600430c43c722cb7
b9d29ac9402cfc04bf3e48867415efa70c144029

Loading…
Cancel
Save