diff --git a/selfdrive/car/subaru/carcontroller.py b/selfdrive/car/subaru/carcontroller.py index 05524d4524..6de5bf89e2 100644 --- a/selfdrive/car/subaru/carcontroller.py +++ b/selfdrive/car/subaru/carcontroller.py @@ -2,8 +2,7 @@ from openpilot.common.numpy_fast import clip, interp from opendbc.can.packer import CANPacker from openpilot.selfdrive.car import apply_driver_steer_torque_limits from openpilot.selfdrive.car.subaru import subarucan -from openpilot.selfdrive.car.subaru.values import DBC, GLOBAL_GEN2, PREGLOBAL_CARS, CanBus, CarControllerParams, SubaruFlags -from selfdrive.car.subaru.values import HYBRID_CARS +from openpilot.selfdrive.car.subaru.values import DBC, GLOBAL_GEN2, PREGLOBAL_CARS, HYBRID_CARS, CanBus, CarControllerParams, SubaruFlags class CarController: diff --git a/selfdrive/car/subaru/carstate.py b/selfdrive/car/subaru/carstate.py index 80eab10eba..ff203f387d 100644 --- a/selfdrive/car/subaru/carstate.py +++ b/selfdrive/car/subaru/carstate.py @@ -4,9 +4,8 @@ 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, CAR, GLOBAL_GEN2, PREGLOBAL_CARS, CanBus, SubaruFlags +from openpilot.selfdrive.car.subaru.values import DBC, CAR, GLOBAL_GEN2, PREGLOBAL_CARS, HYBRID_CARS, CanBus, SubaruFlags from openpilot.selfdrive.car import CanSignalRateCalculator -from selfdrive.car.subaru.values import HYBRID_CARS class CarState(CarStateBase): @@ -101,17 +100,18 @@ class CarState(CarStateBase): 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 - if self.car_fingerprint not in HYBRID_CARS: # Hybrid cars don't have es_distance, need a replacement + # TODO: Hybrid cars don't have ES_Distance, need a replacement + if self.car_fingerprint not in HYBRID_CARS: # 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) - self.es_distance_msg = copy.copy(cp_es_distance.vl["ES_Distance"]) + (cp_es_distance.vl["ES_Brake"]["Brake_Pressure"] != 0) 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: self.es_distance_msg = copy.copy(cp_es_distance.vl["ES_Distance"]) + self.es_dashstatus_msg = copy.copy(cp_cam.vl["ES_DashStatus"]) if self.CP.flags & SubaruFlags.SEND_INFOTAINMENT: self.es_infotainment_msg = copy.copy(cp_cam.vl["ES_Infotainment"]) diff --git a/selfdrive/car/subaru/interface.py b/selfdrive/car/subaru/interface.py index e6e69316f8..d9f3c5f41d 100644 --- a/selfdrive/car/subaru/interface.py +++ b/selfdrive/car/subaru/interface.py @@ -13,9 +13,9 @@ class CarInterface(CarInterfaceBase): 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) + # - 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.autoResumeSng = False @@ -79,7 +79,7 @@ class CarInterface(CarInterfaceBase): ret.steerRatio = 17 ret.steerActuatorDelay = 0.1 - elif candidate in (CAR.FORESTER, CAR.FORESTER_2022): + elif candidate in (CAR.FORESTER, CAR.FORESTER_2022, CAR.FORESTER_HYBRID): ret.mass = 1568. ret.wheelbase = 2.67 ret.centerToFront = ret.wheelbase * 0.5 diff --git a/selfdrive/car/subaru/values.py b/selfdrive/car/subaru/values.py index 4cc1df9754..33ac2b390e 100644 --- a/selfdrive/car/subaru/values.py +++ b/selfdrive/car/subaru/values.py @@ -71,6 +71,7 @@ class CAR: FORESTER = "SUBARU FORESTER 2019" OUTBACK = "SUBARU OUTBACK 6TH GEN" CROSSTREK_HYBRID = "SUBARU CROSSTREK HYBRID 2020" + FORESTER_HYBRID = "SUBARU FORESTER HYBRID 2020" LEGACY = "SUBARU LEGACY 7TH GEN" FORESTER_2022 = "SUBARU FORESTER 2022" OUTBACK_2023 = "SUBARU OUTBACK 7TH GEN" @@ -113,6 +114,7 @@ CAR_INFO: Dict[str, Union[SubaruCarInfo, List[SubaruCarInfo]]] = { ], # TODO: is there an XV and Impreza too? CAR.CROSSTREK_HYBRID: SubaruCarInfo("Subaru Crosstrek Hybrid 2020"), + CAR.FORESTER_HYBRID: SubaruCarInfo("Subaru Forester Hybrid 2020"), CAR.FORESTER: SubaruCarInfo("Subaru Forester 2019-21", "All"), CAR.FORESTER_PREGLOBAL: SubaruCarInfo("Subaru Forester 2017-18"), CAR.LEGACY_PREGLOBAL: SubaruCarInfo("Subaru Legacy 2015-18"), @@ -389,6 +391,23 @@ FW_VERSIONS = { b'\x1a\xe6F1\x00', ], }, + CAR.FORESTER_HYBRID: { + (Ecu.abs, 0x7b0, None): [ + b'\xa3 \x19T\x00', + ], + (Ecu.eps, 0x746, None): [ + b'\x8d\xc2\x00\x00', + ], + (Ecu.fwdCamera, 0x787, None): [ + b'\x00\x00eY\x1f@ !', + ], + (Ecu.engine, 0x7e0, None): [ + b'\xd2\xa1`r\x07', + ], + (Ecu.transmission, 0x7e1, None): [ + b'\x1b\xa7@a\x00', + ], + }, CAR.FORESTER_PREGLOBAL: { (Ecu.abs, 0x7b0, None): [ b'\x7d\x97\x14\x40', @@ -649,6 +668,7 @@ DBC = { CAR.FORESTER: dbc_dict('subaru_global_2017_generated', None), CAR.FORESTER_2022: dbc_dict('subaru_global_2017_generated', None), CAR.OUTBACK: dbc_dict('subaru_global_2017_generated', None), + CAR.FORESTER_HYBRID: dbc_dict('subaru_global_2020_hybrid_generated', None), CAR.CROSSTREK_HYBRID: dbc_dict('subaru_global_2020_hybrid_generated', None), CAR.OUTBACK_2023: dbc_dict('subaru_global_2017_generated', None), CAR.LEGACY: dbc_dict('subaru_global_2017_generated', None), @@ -661,4 +681,4 @@ DBC = { LKAS_ANGLE = {CAR.FORESTER_2022, CAR.OUTBACK_2023} GLOBAL_GEN2 = {CAR.OUTBACK, CAR.LEGACY, CAR.OUTBACK_2023} PREGLOBAL_CARS = {CAR.FORESTER_PREGLOBAL, CAR.LEGACY_PREGLOBAL, CAR.OUTBACK_PREGLOBAL, CAR.OUTBACK_PREGLOBAL_2018} -HYBRID_CARS = {CAR.CROSSTREK_HYBRID, } \ No newline at end of file +HYBRID_CARS = {CAR.CROSSTREK_HYBRID, CAR.FORESTER_HYBRID} diff --git a/selfdrive/car/tests/routes.py b/selfdrive/car/tests/routes.py index 4ecf6e192a..2c6a7472b5 100644 --- a/selfdrive/car/tests/routes.py +++ b/selfdrive/car/tests/routes.py @@ -28,6 +28,7 @@ non_tested_cars = [ VOLKSWAGEN.CRAFTER_MK2, # need a route from an ACC-equipped Crafter TOYOTA.RAV4_TSS2_2023, TOYOTA.RAV4H_TSS2_2023, + SUBARU.FORESTER_HYBRID, ] diff --git a/selfdrive/car/torque_data/substitute.yaml b/selfdrive/car/torque_data/substitute.yaml index 0f742e6f39..f02af01609 100644 --- a/selfdrive/car/torque_data/substitute.yaml +++ b/selfdrive/car/torque_data/substitute.yaml @@ -77,6 +77,7 @@ SEAT LEON 3RD GEN: VOLKSWAGEN GOLF 7TH GEN SEAT ATECA 1ST GEN: VOLKSWAGEN GOLF 7TH GEN SUBARU CROSSTREK HYBRID 2020: SUBARU IMPREZA SPORT 2020 +SUBARU FORESTER HYBRID 2020: SUBARU IMPREZA SPORT 2020 SUBARU LEGACY 7TH GEN: SUBARU OUTBACK 6TH GEN # Old subarus don't have much data guessing it's like low torque impreza