diff --git a/panda/board/safety/safety_honda.h b/panda/board/safety/safety_honda.h index 25879718..c6a907fb 100644 --- a/panda/board/safety/safety_honda.h +++ b/panda/board/safety/safety_honda.h @@ -82,6 +82,7 @@ const uint16_t HONDA_PARAM_BOSCH_LONG = 2; const uint16_t HONDA_PARAM_NIDEC_ALT = 4; const uint16_t HONDA_PARAM_RADARLESS = 8; const uint16_t HONDA_PARAM_GAS_INTERCEPTOR = 16; +const uint16_t HONDA_PARAM_CLARITY = 32; enum { HONDA_BTN_NONE = 0, @@ -97,6 +98,7 @@ bool honda_alt_brake_msg = false; bool honda_fwd_brake = false; bool honda_bosch_long = false; bool honda_bosch_radarless = false; +bool honda_clarity_brake_msg = false; typedef enum {HONDA_NIDEC, HONDA_BOSCH} HondaHw; HondaHw honda_hw = HONDA_NIDEC; @@ -238,6 +240,9 @@ static void honda_rx_hook(const CANPacket_t *to_push) { bool honda_stock_aeb = GET_BIT(to_push, 29U); int honda_stock_brake = (GET_BYTE(to_push, 0) << 2) | (GET_BYTE(to_push, 1) >> 6); + if (honda_clarity_brake_msg) { + honda_stock_brake = (GET_BYTE(to_push, 6) << 2) + ((GET_BYTE(to_push, 7) >> 6) & 0x3U); + } // Forward AEB when stock braking is higher than openpilot braking // only stop forwarding when AEB event is over if (!honda_stock_aeb) { @@ -294,6 +299,9 @@ static bool honda_tx_hook(const CANPacket_t *to_send) { // BRAKE: safety check (nidec) if ((addr == 0x1FA) && (bus == bus_pt)) { honda_brake = (GET_BYTE(to_send, 0) << 2) + ((GET_BYTE(to_send, 1) >> 6) & 0x3U); + if (honda_clarity_brake_msg) { + honda_brake = (GET_BYTE(to_send, 6) << 2) + ((GET_BYTE(to_send, 7) >> 6) & 0x3U); + } if (longitudinal_brake_checks(honda_brake, HONDA_NIDEC_LONG_LIMITS)) { tx = false; } @@ -382,6 +390,7 @@ static safety_config honda_nidec_init(uint16_t param) { honda_bosch_long = false; honda_bosch_radarless = false; enable_gas_interceptor = GET_FLAG(param, HONDA_PARAM_GAS_INTERCEPTOR); + honda_clarity_brake_msg = GET_FLAG(param, HONDA_PARAM_CLARITY); safety_config ret; diff --git a/panda/python/__init__.py b/panda/python/__init__.py index 9504d791..5728cfad 100644 --- a/panda/python/__init__.py +++ b/panda/python/__init__.py @@ -198,6 +198,7 @@ class Panda: FLAG_HONDA_NIDEC_ALT = 4 FLAG_HONDA_RADARLESS = 8 FLAG_HONDA_GAS_INTERCEPTOR = 16 + FLAG_HONDA_CLARITY = 32 FLAG_HYUNDAI_EV_GAS = 1 FLAG_HYUNDAI_HYBRID_GAS = 2 diff --git a/selfdrive/car/honda/carstate.py b/selfdrive/car/honda/carstate.py index d3013664..18ec601c 100644 --- a/selfdrive/car/honda/carstate.py +++ b/selfdrive/car/honda/carstate.py @@ -47,7 +47,7 @@ def get_can_messages(CP, gearbox_msg): if CP.flags & HondaFlags.BOSCH_ALT_BRAKE: messages.append(("BRAKE_MODULE", 50)) - if CP.carFingerprint in (HONDA_BOSCH | {CAR.HONDA_CIVIC, CAR.HONDA_ODYSSEY, CAR.HONDA_ODYSSEY_CHN}): + if CP.carFingerprint in (HONDA_BOSCH | {CAR.HONDA_CIVIC, CAR.HONDA_CLARITY, CAR.HONDA_ODYSSEY, CAR.HONDA_ODYSSEY_CHN}): messages.append(("EPB_STATUS", 50)) if CP.carFingerprint in HONDA_BOSCH: @@ -78,6 +78,8 @@ def get_can_messages(CP, gearbox_msg): if CP.carFingerprint in HONDA_BOSCH_RADARLESS: messages.append(("CRUISE_FAULT_STATUS", 50)) + elif CP.carFingerprint == CAR.HONDA_CLARITY: + messages.append(("BRAKE_ERROR", 100)), elif CP.openpilotLongitudinalControl: messages.append(("STANDSTILL", 50)) @@ -148,6 +150,8 @@ class CarState(CarStateBase): if self.CP.carFingerprint in HONDA_BOSCH_RADARLESS: ret.accFaulted = bool(cp.vl["CRUISE_FAULT_STATUS"]["CRUISE_FAULT"]) + elif self.CP.carFingerprint == CAR.HONDA_CLARITY: + ret.accFaulted = bool(cp.vl["BRAKE_ERROR"]["BRAKE_ERROR_1"] or cp.vl["BRAKE_ERROR"]["BRAKE_ERROR_2"]) else: # On some cars, these two signals are always 1, this flag is masking a bug in release # FIXME: find and set the ACC faulted signals on more platforms @@ -186,7 +190,7 @@ class CarState(CarStateBase): ret.brakeHoldActive = cp.vl["VSA_STATUS"]["BRAKE_HOLD_ACTIVE"] == 1 # TODO: set for all cars - if self.CP.carFingerprint in (HONDA_BOSCH | {CAR.HONDA_CIVIC, CAR.HONDA_ODYSSEY, CAR.HONDA_ODYSSEY_CHN}): + if self.CP.carFingerprint in (HONDA_BOSCH | {CAR.HONDA_CIVIC, CAR.HONDA_CLARITY, CAR.HONDA_ODYSSEY, CAR.HONDA_ODYSSEY_CHN}): ret.parkingBrake = cp.vl["EPB_STATUS"]["EPB_STATE"] != 0 gear = int(cp.vl[self.gearbox_msg]["GEAR_SHIFTER"]) @@ -251,7 +255,8 @@ class CarState(CarStateBase): if self.CP.carFingerprint not in HONDA_BOSCH_RADARLESS: ret.stockAeb = (not self.CP.openpilotLongitudinalControl) and bool(cp.vl["ACC_CONTROL"]["AEB_STATUS"] and cp.vl["ACC_CONTROL"]["ACCEL_COMMAND"] < -1e-5) else: - ret.stockAeb = bool(cp_cam.vl["BRAKE_COMMAND"]["AEB_REQ_1"] and cp_cam.vl["BRAKE_COMMAND"]["COMPUTER_BRAKE"] > 1e-5) + aeb_sig = "COMPUTER_BRAKE_ALT" if self.CP.carFingerprint == CAR.HONDA_CLARITY else "COMPUTER_BRAKE" + ret.stockAeb = bool(cp_cam.vl["BRAKE_COMMAND"]["AEB_REQ_1"] and cp_cam.vl["BRAKE_COMMAND"][aeb_sig] > 1e-5) self.acc_hud = False self.lkas_hud = False diff --git a/selfdrive/car/honda/fingerprints.py b/selfdrive/car/honda/fingerprints.py index e8d6f067..3074bc89 100644 --- a/selfdrive/car/honda/fingerprints.py +++ b/selfdrive/car/honda/fingerprints.py @@ -902,4 +902,29 @@ FW_VERSIONS = { b'28101-65J-N010\x00\x00', ], }, + CAR.HONDA_CLARITY: { + (Ecu.shiftByWire, 0x18da0bf1, None): [ + b'54008-TRW-A910\x00\x00', + ], + (Ecu.vsa, 0x18da28f1, None): [ + b'57114-TRW-A010\x00\x00', + b'57114-TRW-A020\x00\x00', + ], + (Ecu.eps, 0x18da30f1, None): [ + b'39990-TRW-A020\x00\x00', + b'39990-TRW,A020\x00\x00', # modified firmware + b'39990,TRW,A020\x00\x00', # extra modified firmware + ], + (Ecu.srs, 0x18da53f1, None): [ + b'77959-TRW-A210\x00\x00', + b'77959-TRW-A220\x00\x00', + ], + (Ecu.gateway, 0x18daeff1, None): [ + b'38897-TRW-A010\x00\x00', + ], + (Ecu.combinationMeter, 0x18da60f1, None): [ + b'78109-TRW-A020\x00\x00', + b'78109-TRW-A030\x00\x00', + ], + }, } diff --git a/selfdrive/car/honda/hondacan.py b/selfdrive/car/honda/hondacan.py index 1be496d9..656f1818 100644 --- a/selfdrive/car/honda/hondacan.py +++ b/selfdrive/car/honda/hondacan.py @@ -53,8 +53,6 @@ def create_brake_command(packer, CAN, apply_brake, pump_on, pcm_override, pcm_ca pcm_fault_cmd = False values = { - "COMPUTER_BRAKE": apply_brake, - "BRAKE_PUMP_REQUEST": pump_on, "CRUISE_OVERRIDE": pcm_override, "CRUISE_FAULT_CMD": pcm_fault_cmd, "CRUISE_CANCEL_CMD": pcm_cancel_cmd, @@ -67,6 +65,14 @@ def create_brake_command(packer, CAN, apply_brake, pump_on, pcm_override, pcm_ca "AEB_REQ_2": 0, "AEB_STATUS": 0, } + + if car_fingerprint == CAR.HONDA_CLARITY: + values["COMPUTER_BRAKE_ALT"] = apply_brake + values["BRAKE_PUMP_REQUEST_ALT"] = apply_brake > 0 + else: + values["COMPUTER_BRAKE"] = apply_brake + values["BRAKE_PUMP_REQUEST"] = pump_on + return packer.make_can_msg("BRAKE_COMMAND", CAN.pt, values) diff --git a/selfdrive/car/honda/interface.py b/selfdrive/car/honda/interface.py index 63f2f243..389bc0ea 100755 --- a/selfdrive/car/honda/interface.py +++ b/selfdrive/car/honda/interface.py @@ -191,6 +191,21 @@ class CarInterface(CarInterfaceBase): ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 4096], [0, 4096]] # TODO: determine if there is a dead zone at the top end ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.6], [0.18]] # TODO: can probably use some tuning + elif candidate == CAR.HONDA_CLARITY: + ret.safetyConfigs[0].safetyParam |= Panda.FLAG_HONDA_CLARITY + if eps_modified: + for fw in car_fw: + if fw.ecu == "eps" and b"-" not in fw.fwVersion and b"," in fw.fwVersion: + ret.lateralTuning.pid.kf = 0.00004 + ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 0xA00, 0x3C00], [0, 2560, 3840]] + ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.1575], [0.05175]] + elif fw.ecu == "eps" and b"-" in fw.fwVersion and b"," in fw.fwVersion: + ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 0xA00, 0x2800], [0, 2560, 3840]] + ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.3], [0.1]] + else: + ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 2560], [0, 2560]] + ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.8], [0.24]] + else: raise ValueError(f"unsupported car {candidate}") @@ -218,7 +233,7 @@ class CarInterface(CarInterfaceBase): # min speed to enable ACC. if car can do stop and go, then set enabling speed # to a negative value, so it won't matter. Otherwise, add 0.5 mph margin to not # conflict with PCM acc - ret.autoResumeSng = candidate in (HONDA_BOSCH | {CAR.HONDA_CIVIC}) or ret.enableGasInterceptor + ret.autoResumeSng = candidate in (HONDA_BOSCH | {CAR.HONDA_CIVIC, CAR.HONDA_CLARITY}) or ret.enableGasInterceptor ret.minEnableSpeed = -1. if ret.autoResumeSng else 25.5 * CV.MPH_TO_MS ret.steerActuatorDelay = 0.1 diff --git a/selfdrive/car/honda/values.py b/selfdrive/car/honda/values.py index c3005c66..7c2e3d8b 100644 --- a/selfdrive/car/honda/values.py +++ b/selfdrive/car/honda/values.py @@ -191,6 +191,11 @@ class CAR(Platforms): dbc_dict('acura_ilx_2016_can_generated', 'acura_ilx_2016_nidec'), flags=HondaFlags.NIDEC_ALT_SCM_MESSAGES, ) + HONDA_CLARITY = HondaNidecPlatformConfig( + [HondaCarDocs("Honda Clarity 2018-22", "All", min_steer_speed=3. * CV.MPH_TO_MS)], + CarSpecs(mass=4052. * CV.LB_TO_KG, wheelbase=2.75, centerToFrontRatio=0.41, steerRatio=16.50, tireStiffnessFactor=1.), + dbc_dict('honda_clarity_hybrid_2018_can_generated', 'acura_ilx_2016_nidec'), + ) HONDA_CRV = HondaNidecPlatformConfig( [HondaCarDocs("Honda CR-V 2015-16", "Touring Trim", min_steer_speed=12. * CV.MPH_TO_MS)], CarSpecs(mass=3572 * CV.LB_TO_KG, wheelbase=2.62, steerRatio=16.89, centerToFrontRatio=0.41, tireStiffnessFactor=0.444), # as spec diff --git a/selfdrive/car/torque_data/params.toml b/selfdrive/car/torque_data/params.toml index 34cfd0e0..b0ac39f3 100644 --- a/selfdrive/car/torque_data/params.toml +++ b/selfdrive/car/torque_data/params.toml @@ -14,6 +14,7 @@ legend = ["LAT_ACCEL_FACTOR", "MAX_LAT_ACCEL_MEASURED", "FRICTION"] "HONDA_ACCORD" = [1.6893333799149202, 0.3246749081720698, 0.2120497022936265] "HONDA_CIVIC_BOSCH" = [1.691708637466905, 0.40132900729454185, 0.25460295304024094] "HONDA_CIVIC" = [1.6528895627785531, 0.4018518740819229, 0.25458812851328544] +"HONDA_CLARITY" = [1.6528895627785531, 0.4018518740819229, 0.25458812851328544] "HONDA_CRV" = [0.7667141440182675, 0.5927571534745969, 0.40909087636157127] "HONDA_CRV_5G" = [2.01323205142022, 0.2700612209345081, 0.2238412881331528] "HONDA_CRV_HYBRID" = [2.072034634644233, 0.7152085160516978, 0.20237105008376083]