From 1a3b243233c3597da7dc64073b50c4be0f6ae8e2 Mon Sep 17 00:00:00 2001 From: j3dok3do Date: Tue, 25 Aug 2026 16:45:58 -0500 Subject: [PATCH] Honda Accord 11G: add scoped CAN-FD control integration Port the Accord 11G CAN-FD radar handover, vehicle-specific actuator tuning, and Honda safety permissions from PR #93 while keeping StarPilot\x27s shared planner and lead policy. Scope the replacement radar messages and B/regen gear behavior to the Accord platform, preserve generic Honda CAN-FD behavior, and add regression coverage. Source: https://github.com/firestar5683/StarPilot/pull/93 --- .../opendbc/can/tests/test_checksums.py | 8 + .../opendbc/car/honda/carcontroller.py | 141 ++++++++++++++++-- opendbc_repo/opendbc/car/honda/carstate.py | 97 +++++++++++- .../opendbc/car/honda/fingerprints.py | 2 + opendbc_repo/opendbc/car/honda/hondacan.py | 123 +++++++++++++-- opendbc_repo/opendbc/car/honda/interface.py | 19 ++- .../opendbc/car/honda/tests/test_honda.py | 12 +- opendbc_repo/opendbc/car/honda/values.py | 8 +- .../dbc/acura_ilx_2016_can_generated.dbc | 4 +- .../dbc/acura_mdx_2017_can_ext_generated.dbc | 4 +- .../dbc/acura_rdx_2020_can_generated.dbc | 5 +- .../dbc/generator/honda/_bosch_2018.dbc | 1 + .../dbc/generator/honda/_gearbox_common.dbc | 4 +- .../generator/honda/honda_common_canfd.dbc | 68 +++++++++ .../dbc/honda_bosch_radarless_generated.dbc | 5 +- ..._civic_hatchback_ex_2017_can_generated.dbc | 5 +- ...honda_civic_touring_2016_can_generated.dbc | 4 +- ...onda_clarity_hybrid_2018_can_generated.dbc | 4 +- .../dbc/honda_common_canfd_generated.dbc | 73 ++++++++- .../honda_crv_touring_2016_can_generated.dbc | 4 +- .../honda_e_advance_2020_can_generated.dbc | 5 +- .../honda_insight_ex_2019_can_generated.dbc | 5 +- .../dbc/honda_odyssey_exl_2018_generated.dbc | 4 +- .../dbc/honda_odyssey_twn_2018_generated.dbc | 4 +- opendbc_repo/opendbc/safety/modes/honda.h | 74 ++++++++- .../opendbc/safety/tests/test_honda.py | 83 ++++++++++- selfdrive/car/car_specific.py | 4 + 27 files changed, 695 insertions(+), 75 deletions(-) diff --git a/opendbc_repo/opendbc/can/tests/test_checksums.py b/opendbc_repo/opendbc/can/tests/test_checksums.py index a357819a0..7c17fc6f0 100644 --- a/opendbc_repo/opendbc/can/tests/test_checksums.py +++ b/opendbc_repo/opendbc/can/tests/test_checksums.py @@ -1,5 +1,6 @@ import copy from opendbc.can import CANPacker, CANParser +from opendbc.car.honda.hondacan import honda_checksum class TestCanChecksums: @@ -90,6 +91,13 @@ class TestCanChecksums: assert parser.vl['LKAS_HUD']['CHECKSUM'] == std assert parser.vl['LKAS_HUD_A']['CHECKSUM'] == ext + def test_honda_canfd_checksum_offset_is_scoped_to_mvl_messages(self): + # Existing high-ID Honda messages retain the legacy extended-ID offset; + # only the Accord MVL replacement-radar IDs use the CAN-FD offset. + payload = bytearray(8) + assert honda_checksum(0xF31AA54, None, payload) == 11 # existing radarless LKAS_HUD_2 + assert honda_checksum(0xF31AA52, None, payload) == 4 # Accord MVL RADAR_LEAD2 + def verify_volkswagen_mqb_crc(self, subtests, msg_name: str, msg_addr: int, test_messages: list[bytes], counter_field: str = 'COUNTER'): """Test AUTOSAR E2E Profile 2 CRCs""" assert len(test_messages) == 16 # All counter values must be tested diff --git a/opendbc_repo/opendbc/car/honda/carcontroller.py b/opendbc_repo/opendbc/car/honda/carcontroller.py index 56082ad68..c0d580d54 100644 --- a/opendbc_repo/opendbc/car/honda/carcontroller.py +++ b/opendbc_repo/opendbc/car/honda/carcontroller.py @@ -7,6 +7,7 @@ from opendbc.car.honda import hondacan from opendbc.car.honda.values import ( CAR, CruiseButtons, + CruiseSettings, HONDA_BOSCH, HONDA_BOSCH_CANFD, HONDA_BOSCH_RADARLESS, @@ -16,6 +17,7 @@ from opendbc.car.honda.values import ( HondaFlags, ) from opendbc.car.interfaces import CarControllerBase +from opendbc.car.common.pid import PIDController from openpilot.common.params import Params VisualAlert = structs.CarControl.HUDControl.VisualAlert @@ -211,6 +213,14 @@ class CarController(CarControllerBase): self.CAN = hondacan.CanBus(CP) self.tja_control = CP.carFingerprint in HONDA_BOSCH_TJA_CONTROL + # MVL CAN-FD ownership state. These do not affect non-CANFD vehicles. + self.radar_disable_counter = 0 + self.radar_mux = 0 + self.radar_hud_pulse = 0 + self.last_acc_enabled = False + self.lkas_button_send_remaining = 0 + self.last_lkas_button_frame = 0 + self.braking = False self.brake_steady = 0.0 self.brake_last = 0.0 @@ -234,6 +244,10 @@ class CarController(CarControllerBase): self.bosch_gas_factor_before_gasmax = self.bosch_gas_factor self.bosch_wind_factor_before_gasmax = self.bosch_wind_factor self.pitch = 0.0 + self.mvl_accord_mode = CP.carFingerprint == CAR.HONDA_ACCORD_11G + # MVL Bosch low-speed extra-brake integrator. Active only for Accord 11G MVL mode. + self.mvl_brake_pid = PIDController(k_p=0.0, k_i=1.0, pos_limit=0.0, neg_limit=-2.0, rate=50) + self.mvl_brake_pid.reset() def _modified_civic_standard_active(self) -> bool: return self.CP.carFingerprint == CAR.HONDA_CIVIC_BOSCH and bool(self.CP.flags & HondaFlags.EPS_MODIFIED) @@ -255,6 +269,7 @@ class CarController(CarControllerBase): hud_v_cruise = hud_control.setSpeed / CS.v_cruise_factor if hud_control.speedVisible else 255 pcm_cancel_cmd = CC.cruiseControl.cancel gas_interceptor_command = 0.0 + min_gas = self.params.BOSCH_GAS_LOOKUP_BP[0] if len(CC.orientationNED) == 3: self.pitch = CC.orientationNED[1] hill_brake = math.sin(self.pitch) * ACCELERATION_DUE_TO_GRAVITY @@ -308,11 +323,56 @@ class CarController(CarControllerBase): # Send CAN commands can_sends = [] - # tester present - w/ no response (keeps radar disabled) + # Bosch radar ownership. On CAN-FD, leave the stock radar active until the comma relay is open, + # then enter extended diagnostics and disable radar RX/TX. This prevents a gap between stock + # ACC_CONTROL disappearing and panda permitting openpilot's replacement stream. if self.CP.carFingerprint in (HONDA_BOSCH - HONDA_BOSCH_RADARLESS) and self.CP.openpilotLongitudinalControl: - if self.frame % 10 == 0: + if self.mvl_accord_mode and CS.stock_acc_alive: + if CS.canfd_relay_open: + if self.radar_disable_counter % 50 == 0: + can_sends.append((0x18DAB0F1, b'\x02\x10\x03\x00\x00\x00\x00\x00', self.CAN.pt)) + elif self.radar_disable_counter % 50 == 5: + can_sends.append((0x18DAB0F1, b'\x03\x28\x83\x03\x00\x00\x00\x00', self.CAN.pt)) + self.radar_disable_counter += 1 + elif self.frame % 10 == 0: can_sends.append(make_tester_present_msg(0x18DAB0F1, self.CAN.pt, suppress_response=True)) + # After the stock CAN-FD radar is silent, reproduce its low-rate/tick-aligned messages on both + # the PT and camera sides of the open relay. Pack once and mirror identical bytes so counters and + # checksums stay synchronized. v3 deliberately uses an idle lane/object payload first; model-based + # cluster rendering is deferred until the ownership/DTC handover is proven. + mvl_radar_owned = self.mvl_accord_mode and CS.canfd_relay_open and not CS.stock_acc_alive + if mvl_radar_owned and self.CP.openpilotLongitudinalControl: + if CC.enabled and not self.last_acc_enabled: + self.radar_hud_pulse = 30 + self.last_acc_enabled = CC.enabled + + radar_msgs = [] + if CS.hud_tick: + radar_msgs.append(hondacan.create_radar_hud_canfd(self.packer, self.CAN.pt, CC.enabled, self.radar_hud_pulse > 0)) + if self.radar_hud_pulse > 0: + self.radar_hud_pulse -= 1 + if CS.supp_tick: + radar_msgs.append(hondacan.create_canfd_supplemental(self.packer, self.CAN.pt)) + if CS.radar_50hz_tick: + if self.radar_mux >= 58: + self.radar_mux = 1 + elif self.radar_mux == 10: + self.radar_mux = 17 + elif self.radar_mux == 26: + self.radar_mux = 33 + elif self.radar_mux == 42: + self.radar_mux = 49 + else: + self.radar_mux += 1 + radar_msgs.extend(hondacan.create_canfd_50hz_radar_messages(self.packer, self.CAN.pt, self.radar_mux)) + if CS.radar_5hz_tick: + radar_msgs.extend(hondacan.create_canfd_5hz_radar_messages(self.packer, self.CAN.pt, CS.radar_ref_counter)) + + for addr, dat, _ in radar_msgs: + can_sends.append((addr, dat, self.CAN.pt)) + can_sends.append((addr, dat, self.CAN.camera)) + # Send steering command. can_sends.append(hondacan.create_steering_control(self.packer, self.CAN, apply_torque, CC.latActive, self.tja_control)) @@ -352,23 +412,37 @@ class CarController(CarControllerBase): ts = self.frame * DT_CTRL if self.CP.carFingerprint in HONDA_BOSCH: - self.accel = float(np.clip(accel, self.params.BOSCH_ACCEL_MIN, self.params.BOSCH_ACCEL_MAX)) - gas_pedal_force = self.accel + hill_brake + if self.mvl_accord_mode and (accel < min_gas) and (1e-3 < CS.out.vEgo < 3.0): + brake_addon = self.mvl_brake_pid.update(error=accel - CS.out.aEgo, speed=CS.out.vEgo) + target_accel = min(accel, accel + brake_addon) + else: + if self.mvl_accord_mode: + self.mvl_brake_pid.reset() + target_accel = accel + + self.accel = float(np.clip(target_accel, self.params.BOSCH_ACCEL_MIN, self.params.BOSCH_ACCEL_MAX)) + # MVL uses requested accel (not extra-brake-adjusted accel) to decide propulsion crossover. + gas_pedal_force = (accel if self.mvl_accord_mode else self.accel) + hill_brake if self.CP.carFingerprint not in HONDA_BOSCH_RADARLESS: gas_pedal_force += wind_brake_mps2 * self.bosch_wind_factor if actuators.longControlState == LongCtrlState.pid and not CS.out.gasPressed: - gas_error = self.accel - CS.out.aEgo + gas_error = (accel if self.mvl_accord_mode else self.accel) - CS.out.aEgo - if gas_error != 0.0 and gas_pedal_force > 0.0: + if gas_error != 0.0 and gas_pedal_force > min_gas: if self.CP.carFingerprint == CAR.HONDA_INSIGHT: gas_learn_speed = 150.0 elif self.CP.carFingerprint in (CAR.ACURA_RDX_3G, CAR.ACURA_RDX_3G_MMR): gas_learn_speed = 300.0 else: gas_learn_speed = 50.0 - self.bosch_gas_factor = float(np.clip(self.bosch_gas_factor + gas_error / gas_learn_speed * gas_pedal_force, 0.1, 3.0)) + gas_factor_floor = 0.01 if self.mvl_accord_mode else 0.1 + gas_learn_force = (gas_pedal_force - min_gas) if self.mvl_accord_mode else gas_pedal_force + self.bosch_gas_factor = float(np.clip( + self.bosch_gas_factor + gas_error / gas_learn_speed * gas_learn_force, + gas_factor_floor, 3.0, + )) if gas_error != 0.0 and not CS.out.brakePressed and CS.out.vEgo > 0.0: wind_learn_speed = 100.0 if self.CP.carFingerprint in (CAR.ACURA_RDX_3G, CAR.ACURA_RDX_3G_MMR) else 1000.0 @@ -378,7 +452,8 @@ class CarController(CarControllerBase): else: self.bosch_wind_factor = float(np.clip(self.bosch_wind_factor / wind_adjust, 0.1, 3.0)) - if gas_pedal_force <= 0.0: + wind_brake_threshold = min_gas if self.mvl_accord_mode else 0.0 + if gas_pedal_force <= wind_brake_threshold: self.bosch_wind_factor = max(self.bosch_wind_factor, self.bosch_wind_factor_before_brake) else: self.bosch_wind_factor_before_brake = self.bosch_wind_factor @@ -390,15 +465,21 @@ class CarController(CarControllerBase): self.bosch_gas_factor_before_gasmax = self.bosch_gas_factor self.bosch_wind_factor_before_gasmax = self.bosch_wind_factor - self.gas = float(np.interp(gas_pedal_force * self.bosch_gas_factor, self.params.BOSCH_GAS_LOOKUP_BP, self.params.BOSCH_GAS_LOOKUP_V)) + gas_lookup_input = ((gas_pedal_force - min_gas) * self.bosch_gas_factor + min_gas) if self.mvl_accord_mode else \ + gas_pedal_force * self.bosch_gas_factor + self.gas = float(np.interp(gas_lookup_input, self.params.BOSCH_GAS_LOOKUP_BP, self.params.BOSCH_GAS_LOOKUP_V)) self.gas = min(self.gas, max(60.0, self.bosch_last_gas + 60.0)) self.bosch_last_gas = self.gas stopping = actuators.longControlState == LongCtrlState.stopping self.stopping_counter = self.stopping_counter + 1 if stopping else 0 - can_sends.extend( - hondacan.create_acc_commands(self.packer, self.CAN, CC.enabled, CC.longActive, self.accel, self.gas, self.stopping_counter, self.CP.carFingerprint) - ) + if not self.mvl_accord_mode or mvl_radar_owned: + can_sends.extend( + hondacan.create_acc_commands( + self.packer, self.CAN, CC.enabled, CC.longActive, self.accel, self.gas, self.stopping_counter, self.CP, + gas_force=gas_pedal_force if self.mvl_accord_mode else None, + ) + ) else: apply_brake = np.clip(self.brake_last - wind_brake, 0.0, 1.0) apply_brake = int(np.clip(apply_brake * self.params.NIDEC_BRAKE_MAX, 0, self.params.NIDEC_BRAKE_MAX - 1)) @@ -440,9 +521,16 @@ class CarController(CarControllerBase): idx = (self.frame // 2) % 0x10 can_sends.append(create_gas_interceptor_command(self.packer, gas_interceptor_command, idx)) - # Send dashboard UI commands. + # Send dashboard UI commands. On CAN-FD, ACC_HUD is owned by the radar and must only start + # after the handover, aligned to the radar's 10 Hz HUD tick. + if (mvl_radar_owned and CS.hud_tick and self.CP.openpilotLongitudinalControl): + can_sends.append( + hondacan.create_acc_hud(self.packer, self.CAN.pt, self.CP, CC.enabled, pcm_speed, actuators.accel, + hud_control, hud_v_cruise, CS.is_metric, CS.acc_hud) + ) + if self.frame % 10 == 0: - if self.CP.openpilotLongitudinalControl: + if self.CP.openpilotLongitudinalControl and not self.mvl_accord_mode: # On Nidec, this also controls longitudinal positive acceleration can_sends.append( hondacan.create_acc_hud(self.packer, self.CAN.pt, self.CP, CC.enabled, pcm_speed, pcm_accel, hud_control, hud_v_cruise, CS.is_metric, CS.acc_hud) @@ -458,7 +546,7 @@ class CarController(CarControllerBase): if self.CP.openpilotLongitudinalControl: # TODO: combining with create_acc_hud block above will change message order and will need replay logs regenerated - if self.CP.carFingerprint in (HONDA_BOSCH - HONDA_BOSCH_RADARLESS): + if self.CP.carFingerprint in (HONDA_BOSCH - HONDA_BOSCH_RADARLESS - {CAR.HONDA_ACCORD_11G}): can_sends.append(hondacan.create_radar_hud(self.packer, self.CAN.pt)) if self.CP.carFingerprint == CAR.HONDA_CIVIC_BOSCH: can_sends.append(hondacan.create_legacy_brake_command(self.packer, self.CAN.pt)) @@ -469,6 +557,29 @@ class CarController(CarControllerBase): else: self.gas = pcm_accel / self.params.NIDEC_GAS_MAX + # CAN-FD: while engaged, the camera still needs a valid SCM_BUTTONS stream behind the open relay. + # Take over that stream, echoing the live ambient-light byte. Also send a short LKAS-setting pulse + # when stock LKAS is ready, matching MVL's workaround for the Honda touch-steering-wheel timer. + if (self.mvl_accord_mode and CC.enabled and self.frame % 4 == 0 + and not pcm_cancel_cmd and not CC.cruiseControl.resume): + if (self.lkas_button_send_remaining == 0 and CS.lkas_hud["LKAS_READY"] + and self.frame >= self.last_lkas_button_frame + 500): + self.lkas_button_send_remaining = 3 + + if self.lkas_button_send_remaining > 0: + self.last_lkas_button_frame = self.frame + self.lkas_button_send_remaining -= 1 + cruise_setting = CruiseSettings.LKAS + elif CS.cruise_setting == CruiseSettings.LKAS: + cruise_setting = 0 + else: + cruise_setting = CS.cruise_setting + + can_sends.append(hondacan.spam_buttons_command( + self.packer, self.CAN, CS.cruise_buttons, self.CP.carFingerprint, + cruise_setting=cruise_setting, ambient_light=CS.scm_ambient_light, bus=self.CAN.camera, + )) + if self.frame > 0 and self.frame % 6000 == 0: self.param_store.put_float("HondaGasFactorParams", self.bosch_gas_factor) self.param_store.put_float("HondaWindFactorParams", self.bosch_wind_factor) diff --git a/opendbc_repo/opendbc/car/honda/carstate.py b/opendbc_repo/opendbc/car/honda/carstate.py index 67886c447..a262cb47c 100644 --- a/opendbc_repo/opendbc/car/honda/carstate.py +++ b/opendbc_repo/opendbc/car/honda/carstate.py @@ -68,11 +68,33 @@ class CarState(CarStateBase): self.initial_accFault_cleared = False self.initial_accFault_cleared_timer = int(10 / DT_CTRL) + # CAN-FD deferred radar handover state. The stock radar remains responsible for ACC_CONTROL + # until the relay is open and the controller has silenced it; radar reference/tick messages are + # used to keep the replacement radar look-alikes on the stock cadence after the handover. + self.radar_ref_counter = 0 + self.radar_5hz_tick_counter = 0 + self.radar_5hz_tick = False + self.supp_tick_counter = 0 + self.supp_tick = False + self.hud_tick_counter = 0 + self.hud_tick = False + self.radar_50hz_tick_counter = 0 + self.radar_50hz_tick = False + self.scm_ambient_light = 0 + self.stock_acc_counter = 0 + self.stock_acc_alive = False + self.camera_steer_counter = 0 + self.camera_steer_seen = False + self.canfd_frames = 0 + self.canfd_relay_open = False + def update(self, can_parsers, starpilot_toggles) -> structs.CarState: cp = can_parsers[Bus.pt] cp_cam = can_parsers[Bus.cam] if self.CP.enableBsm: cp_body = can_parsers[Bus.body] + if self.CP.carFingerprint == CAR.HONDA_ACCORD_11G: + cp_radar = can_parsers[Bus.radar] ret = structs.CarState() @@ -85,6 +107,10 @@ class CarState(CarStateBase): prev_cruise_setting = self.cruise_setting self.cruise_setting = cp.vl["SCM_BUTTONS"]["CRUISE_SETTING"] self.cruise_buttons = cp.vl["SCM_BUTTONS"]["CRUISE_BUTTONS"] + if self.CP.carFingerprint in (HONDA_BOSCH_RADARLESS | {CAR.HONDA_ACCORD_11G}): + # The camera consumes this byte in SCM_BUTTONS too (adaptive high beam); preserve it when + # openpilot temporarily takes over SCM_BUTTONS toward the camera. + self.scm_ambient_light = cp.vl["SCM_BUTTONS"]["AMBIENT_LIGHT_MAYBE"] # used for car hud message self.is_metric = self.CP.carFingerprint in (CAR.HONDA_ODYSSEY_TWN,) or not cp.vl["CAR_SPEED"]["IMPERIAL_UNIT"] @@ -116,8 +142,8 @@ class CarState(CarStateBase): steer_status = self.steer_status_values[cp.vl["STEER_STATUS"]["STEER_STATUS"]] ret.steerFaultPermanent = steer_status not in ("NORMAL", "NO_TORQUE_ALERT_1", "NO_TORQUE_ALERT_2", "LOW_SPEED_LOCKOUT", "TJA_LOW_SPEED_LOCKOUT", "TMP_FAULT") - if self.CP.carFingerprint in HONDA_BOSCH_ALT_RADAR: - # TODO: See if this logic works for all other Honda + if self.CP.carFingerprint in (HONDA_BOSCH_ALT_RADAR | {CAR.HONDA_ACCORD_11G}): + # MVL treats CAN-FD low-speed lockout as an expected EPS state too. min_steer_speed = max(CarControllerParams.STEER_GLOBAL_MIN_SPEED, self.CP.minSteerSpeed) expected_low_speed_lockout = steer_status == "LOW_SPEED_LOCKOUT" and ret.vEgo < min_steer_speed ret.steerFaultTemporary = steer_status != "NORMAL" and not expected_low_speed_lockout @@ -249,6 +275,63 @@ class CarState(CarStateBase): if self.CP.carFingerprint in (HONDA_BOSCH_RADARLESS | HONDA_BOSCH_CANFD): self.lkas_hud = cp_cam.vl["LKAS_HUD"] + if self.CP.carFingerprint == CAR.HONDA_ACCORD_11G: + # Phase replacement radar messages from the stock radar's tick references. CarState reads the + # tick in one 100 Hz cycle and CarController transmits on the next, so pulse one frame before + # the expected next stock tick. + self.radar_ref_counter = cp.vl["RADAR_REFERENCE"]["COUNTER"] + + ref_tick_vals = cp.vl_all.get("RADAR_REFERENCE", {}).get("COUNTER", []) + if len(ref_tick_vals) > 0: + self.radar_5hz_tick_counter = 0 + else: + self.radar_5hz_tick_counter += 1 + self.radar_5hz_tick = self.radar_5hz_tick_counter == 11 + + supp_tick_vals = cp_radar.vl_all.get("RADAR_SUPP_TICK_REFERENCE", {}).get("IGNORE", []) + if len(supp_tick_vals) > 0: + self.supp_tick_counter = 0 + else: + self.supp_tick_counter += 1 + self.supp_tick = self.supp_tick_counter == 99 + + hud_tick_vals = cp_radar.vl_all.get("RADAR_HUD_TICK_REFERENCE", {}).get("IGNORE", []) + if len(hud_tick_vals) > 0: + self.hud_tick_counter = 0 + else: + self.hud_tick_counter += 1 + self.hud_tick = self.hud_tick_counter == 9 + + tick_50hz_vals = cp_radar.vl_all.get("RADAR_50HZ_TICK_REFERENCE", {}).get("IGNORE", []) + if len(tick_50hz_vals) > 0: + self.radar_50hz_tick_counter = 0 + else: + self.radar_50hz_tick_counter += 1 + self.radar_50hz_tick = self.radar_50hz_tick_counter == 1 + + # ACC_CONTROL is normally present every 2 frames. Keep treating the stock radar as alive until + # four consecutive frames have passed without it, preventing overlap between stock and OP ACC. + self.canfd_frames += 1 + if len(cp.vl_all.get("ACC_CONTROL", {}).get("COUNTER", [])) > 0: + self.stock_acc_counter = 0 + else: + self.stock_acc_counter += 1 + self.stock_acc_alive = self.stock_acc_counter < 4 + + # Before the relay opens, the camera's STEERING_CONTROL is physically visible on PT. Once the + # relay opens it disappears. Fallback to 5 seconds in case the camera frame was never observed. + if len(cp.vl_all.get("STEERING_CONTROL", {}).get("COUNTER", [])) > 0: + self.camera_steer_counter = 0 + self.camera_steer_seen = True + else: + self.camera_steer_counter += 1 + self.canfd_relay_open = (self.camera_steer_seen and self.camera_steer_counter >= 5) or self.canfd_frames >= 500 + else: + self.supp_tick = False + self.hud_tick = False + self.radar_5hz_tick = False + self.radar_50hz_tick = False + if self.CP.enableBsm: # BSM messages are on B-CAN, requires a panda forwarding B-CAN messages to CAN 0 # more info here: https://github.com/commaai/openpilot/pull/1867 @@ -271,6 +354,10 @@ class CarState(CarStateBase): def get_can_parsers(self, CP): pt_messages = [("GAS_SENSOR", 0)] if CP.enableGasInterceptorDEPRECATED else [] + if CP.carFingerprint == CAR.HONDA_ACCORD_11G: + # Both deliberately go silent during the handover, so skip alive/timeout checks. + pt_messages += [("ACC_CONTROL", float("nan")), ("STEERING_CONTROL", float("nan"))] + pt_parser = CANParser(DBC[CP.carFingerprint][Bus.pt], pt_messages, CanBus(CP).pt) if CP.enableGasInterceptorDEPRECATED: pt_parser.message_states[0x201].ignore_checksum = True @@ -282,5 +369,11 @@ class CarState(CarStateBase): } if CP.enableBsm: parsers[Bus.body] = CANParser(DBC[CP.carFingerprint][Bus.body], [], CanBus(CP).radar) + if CP.carFingerprint == CAR.HONDA_ACCORD_11G: + parsers[Bus.radar] = CANParser(DBC[CP.carFingerprint][Bus.radar], [ + ("RADAR_SUPP_TICK_REFERENCE", 0), + ("RADAR_HUD_TICK_REFERENCE", 0), + ("RADAR_50HZ_TICK_REFERENCE", 0), + ], CanBus(CP).radar) return parsers diff --git a/opendbc_repo/opendbc/car/honda/fingerprints.py b/opendbc_repo/opendbc/car/honda/fingerprints.py index c49891c12..760cd5205 100644 --- a/opendbc_repo/opendbc/car/honda/fingerprints.py +++ b/opendbc_repo/opendbc/car/honda/fingerprints.py @@ -1039,6 +1039,8 @@ FW_VERSIONS = { (Ecu.fwdCamera, 0x18dab5f1, None): [ b'8S102-30A-A050\x00\x00', b'8S102-30A-A060\x00\x00', + b'8S102-30A-A070\x00\x00', + b'8S102-30A-A080\x00\x00', ], }, CAR.HONDA_CRV_6G: { diff --git a/opendbc_repo/opendbc/car/honda/hondacan.py b/opendbc_repo/opendbc/car/honda/hondacan.py index 8b7da37f4..5169b9626 100644 --- a/opendbc_repo/opendbc/car/honda/hondacan.py +++ b/opendbc_repo/opendbc/car/honda/hondacan.py @@ -2,6 +2,7 @@ from opendbc.car import CanBusBase from opendbc.car.common.conversions import Conversions as CV from opendbc.car.honda.values import (HondaFlags, HONDA_BOSCH, HONDA_BOSCH_ALT_RADAR, HONDA_BOSCH_RADARLESS, HONDA_BOSCH_CANFD, CarControllerParams) +from opendbc.car.honda.values import CAR # CAN bus layout with relay # 0 = ACC-CAN - radar side @@ -70,14 +71,16 @@ def create_brake_command(packer, CAN, apply_brake, pump_on, pcm_override, pcm_ca return packer.make_can_msg("BRAKE_COMMAND", CAN.pt, values) -def create_acc_commands(packer, CAN, enabled, active, accel, gas, stopping_counter, car_fingerprint): +def create_acc_commands(packer, CAN, enabled, active, accel, gas, stopping_counter, CP, gas_force=None): commands = [] min_gas_accel = CarControllerParams.BOSCH_GAS_LOOKUP_BP[0] control_on = 5 if enabled else 0 - gas_command = gas if active and accel > min_gas_accel else -30000 + if gas_force is None: + gas_force = accel + gas_command = gas if active and gas_force > min_gas_accel else -30000 accel_command = accel if active else 0 - braking = 1 if active and accel < min_gas_accel else 0 + braking = 1 if active and gas_force < min_gas_accel else 0 standstill = 1 if active and stopping_counter > 0 else 0 standstill_release = 1 if active and stopping_counter == 0 else 0 @@ -87,7 +90,7 @@ def create_acc_commands(packer, CAN, enabled, active, accel, gas, stopping_count 'STANDSTILL': standstill, } - if car_fingerprint in HONDA_BOSCH_RADARLESS: + if CP.carFingerprint in HONDA_BOSCH_RADARLESS: acc_control_values.update({ "CONTROL_ON": enabled, "IDLESTOP_ALLOW": stopping_counter > 200, # allow idle stop after 4 seconds (50 Hz) @@ -147,10 +150,20 @@ def create_acc_hud(packer, bus, CP, enabled, pcm_speed, pcm_accel, hud_control, 'SET_ME_X01_2': 1, } + if CP.carFingerprint == CAR.HONDA_ACCORD_11G: + # Stock CAN-FD radar toggles these together with ACC/lead/braking state. Keeping them low when + # neither lead nor braking is present matches MVL's observed CAN-FD payload shape. + set_me = int(enabled and (bool(acc_hud_values['HUD_LEAD']) or (pcm_accel < 0.2))) + acc_hud_values['SET_ME_X01'] = set_me + acc_hud_values['SET_ME_X01_2'] = set_me + if CP.carFingerprint in HONDA_BOSCH: acc_hud_values['ACC_ON'] = int(enabled) - acc_hud_values['FCM_OFF'] = 1 - acc_hud_values['FCM_OFF_2'] = 1 + # Preserve StarPilot's existing Bosch HUD behavior outside CAN-FD. MVL's CAN-FD + # replacement radar expects FCW/CMBS enabled, while legacy Bosch keeps them off. + canfd = CP.carFingerprint == CAR.HONDA_ACCORD_11G + acc_hud_values['FCM_OFF'] = 0 if canfd else 1 + acc_hud_values['FCM_OFF_2'] = 0 if canfd else 1 else: # Shows the distance bars, TODO: stock camera shows updates temporarily while disabled acc_hud_values['ACC_ON'] = int(enabled) @@ -219,16 +232,104 @@ def create_legacy_brake_command(packer, bus): return packer.make_can_msg("LEGACY_BRAKE_COMMAND", bus, {}) -def spam_buttons_command(packer, CAN, button_val, car_fingerprint): +def spam_buttons_command(packer, CAN, button_val, car_fingerprint, cruise_setting=0, ambient_light=None, bus=None): values = { 'CRUISE_BUTTONS': button_val, - 'CRUISE_SETTING': 0, + 'CRUISE_SETTING': cruise_setting, } - # send buttons to camera on radarless (camera does ACC) cars - bus = CAN.camera if car_fingerprint in HONDA_BOSCH_RADARLESS else CAN.pt + # Existing StarPilot callers should retain their previous payload; only the CAN-FD camera + # takeover path explicitly echoes the live ambient-light byte. + if ambient_light is not None: + values['AMBIENT_LIGHT_MAYBE'] = ambient_light + if bus is None: + # send buttons to camera on radarless (camera does ACC) cars + bus = CAN.camera if car_fingerprint in HONDA_BOSCH_RADARLESS else CAN.pt return packer.make_can_msg("SCM_BUTTONS", bus, values) +def create_radar_hud_canfd(packer, bus, acc, acc_pulse=False): + values = { + 'CMBS_ENABLED_MAYBE': 1 if (acc and acc_pulse) else 0, + 'ACC_ON': acc, + 'SET_ME_X01': 0x01, + 'SET_ME_X01_2': 0x01, + } + return packer.make_can_msg("RADAR_HUD_CANFD", bus, values) + + +def create_canfd_supplemental(packer, bus): + values = { + 'SET_ME_X01': 0x01, + 'SET_ME_X41': 0x41, + } + return packer.make_can_msg("BOSCH_SUPPLEMENTAL_CANFD", bus, values) + + +RADAR_MUX_BANK_STARTS = (1, 17, 33, 49) +PATH_OFFSET_INVALID = 2047 +# These extended IDs use the CAN-FD checksum offset used by the Accord 11G +# replacement-radar stream. Keep the legacy Honda offset for existing high-ID +# messages on other Honda platforms. +HONDA_CANFD_MVL_CHECKSUM_IDS = frozenset(( + 0x6CD5558, 0x6CD5559, 0xF31AA52, 0xF31AA5C, 0x1A45AA4E, +)) + + +def _lane_path_offsets(radar_mux): + pos = next((radar_mux - start for start in RADAR_MUX_BANK_STARTS if start <= radar_mux <= start + 9), 0) + if pos == 0: + return (0, 0, 0, 0) + if pos == 1: + return (0, 0, PATH_OFFSET_INVALID, PATH_OFFSET_INVALID) + return (PATH_OFFSET_INVALID,) * 4 + + +def create_canfd_50hz_radar_messages(packer, bus, radar_mux): + offsets = _lane_path_offsets(radar_mux) + lane_path_values = { + 'MUX': radar_mux, + 'PATH_OFFSET_1': offsets[0], + 'PATH_OFFSET_2': offsets[1], + 'PATH_OFFSET_3': offsets[2], + 'PATH_OFFSET_4': offsets[3], + } + hud_objects_values = { + 'MUX': radar_mux, + 'OBJECT_ID': 0, + 'IS_LEAD_CAR': 0, + 'CAR_TYPE': -1, + 'ROTATION': -128, + 'LONG_DIST': 196.9, + 'LAT_DIST': 204.7, + } + return [ + packer.make_can_msg('LANE_PATH', bus, lane_path_values), + packer.make_can_msg('HUD_OBJECTS', bus, hud_objects_values), + ] + + +def create_canfd_5hz_radar_messages(packer, bus, radar_ref_cntr): + radar_lead_values = { + 'CNTR_REF': radar_ref_cntr, + 'SET_ME_X01': 0x01, + 'TARGET_SPEED_MAYBE': 140, + # v3 initially sends MVL's stock-like idle lane state. Model-derived dash rendering can be added + # separately after the DTC/ownership handover is proven on-car. + 'LEFT_LANE': 0, + 'RIGHT_LANE': 0, + 'LANE_PATH_LENGTH': 6, + } + radar_lead2_values = { + 'SET_ME_X88': 136, + 'SET_ME_X78': 120, + 'LEAD_DISTANCE_MAYBE': 0, + } + return [ + packer.make_can_msg('RADAR_LEAD', bus, radar_lead_values), + packer.make_can_msg('RADAR_LEAD2', bus, radar_lead2_values), + ] + + def honda_checksum(address: int, sig, d: bytearray) -> int: s = 0 extended = address > 0x7FF @@ -243,5 +344,5 @@ def honda_checksum(address: int, sig, d: bytearray) -> int: s += (x & 0xF) + (x >> 4) s = 8 - s if extended: - s += 3 + s += 10 if address in HONDA_CANFD_MVL_CHECKSUM_IDS else 3 return s & 0xF diff --git a/opendbc_repo/opendbc/car/honda/interface.py b/opendbc_repo/opendbc/car/honda/interface.py index 97779893d..b9ee522d2 100644 --- a/opendbc_repo/opendbc/car/honda/interface.py +++ b/opendbc_repo/opendbc/car/honda/interface.py @@ -143,9 +143,13 @@ class CarInterface(CarInterfaceBase): CarControllerParams.BOSCH_GAS_LOOKUP_BP = [-0.2, 2.0] elif candidate == CAR.HONDA_ACCORD_11G: - ret.steerActuatorDelay = 0.22 - ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 2560, 5200], [0, 2560, 12747]] - CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning) + # MVL Boston sp-honda-dev-202608 tuning (48211d6a63). + ret.longitudinalActuatorDelay = 0.05 + ret.steerActuatorDelay = 0.3 + ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 12789], [0, 12789]] + ret.lateralTuning.pid.kf = 0.000035 + ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.115], [0.052]] + CarControllerParams.BOSCH_GAS_LOOKUP_BP = [0.0, 2.0] elif candidate == CAR.ACURA_ILX: ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 3840], [0, 3840]] # TODO: determine if there is a dead zone at the top end @@ -314,6 +318,8 @@ class CarInterface(CarInterfaceBase): ret.safetyConfigs[-1].safetyParam |= HondaSafetyFlags.RADARLESS.value if candidate in HONDA_BOSCH_CANFD: ret.safetyConfigs[-1].safetyParam |= HondaSafetyFlags.BOSCH_CANFD.value + if candidate == CAR.HONDA_ACCORD_11G: + ret.safetyConfigs[-1].safetyParam |= HondaSafetyFlags.BOSCH_CANFD_MVL.value # 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 @@ -345,6 +351,13 @@ class CarInterface(CarInterfaceBase): @staticmethod def init(CP, can_recv, can_send, communication_control=None): if CP.carFingerprint in (HONDA_BOSCH - HONDA_BOSCH_RADARLESS) and CP.openpilotLongitudinalControl: + # CAN-FD radar ownership is handed over only after the comma relay is confirmed open. + # Disabling the radar here can create a gap before panda enters the Honda safety mode and + # replacement ACC_CONTROL is permitted, which can latch CRUISE_FAULT/DTCs in the brake module. + # deinit() still passes an explicit enable request and therefore falls through to disable_ecu. + if CP.carFingerprint == CAR.HONDA_ACCORD_11G and communication_control is None: + return + # 0x80 silences response if communication_control is None: communication_control = bytes([uds.SERVICE_TYPE.COMMUNICATION_CONTROL, 0x80 | uds.CONTROL_TYPE.DISABLE_RX_DISABLE_TX, diff --git a/opendbc_repo/opendbc/car/honda/tests/test_honda.py b/opendbc_repo/opendbc/car/honda/tests/test_honda.py index 86e62eb32..1118b03b1 100644 --- a/opendbc_repo/opendbc/car/honda/tests/test_honda.py +++ b/opendbc_repo/opendbc/car/honda/tests/test_honda.py @@ -2,7 +2,7 @@ import re from types import SimpleNamespace import pytest -from opendbc.car import structs +from opendbc.car import Bus, structs from opendbc.car.structs import CarParams from opendbc.car import gen_empty_fingerprint from opendbc.car.honda.interface import CarInterface @@ -196,6 +196,16 @@ class TestHondaFingerprint: assert CP.safetyConfigs[-1].safetyParam & HondaSafetyFlags.BOSCH_CANFD assert CP.safetyConfigs[-1].safetyParam & HondaSafetyFlags.BOSCH_LONG + def test_mvl_handover_is_scoped_to_accord_11g(self): + toggles = get_test_toggles() + accord_cp = CarInterface.get_params(CAR.HONDA_ACCORD_11G, gen_empty_fingerprint(), [], True, False, False, toggles) + crv_cp = CarInterface.get_params(CAR.HONDA_CRV_6G, gen_empty_fingerprint(), [], True, False, False, toggles) + + assert Bus.radar in DBC[accord_cp.carFingerprint] + assert Bus.radar not in DBC[crv_cp.carFingerprint] + assert accord_cp.safetyConfigs[-1].safetyParam & HondaSafetyFlags.BOSCH_CANFD_MVL + assert not crv_cp.safetyConfigs[-1].safetyParam & HondaSafetyFlags.BOSCH_CANFD_MVL + def test_nidec_pedal_detection_enables_interceptor_path(self): toggles = get_test_toggles() fingerprint = gen_empty_fingerprint() diff --git a/opendbc_repo/opendbc/car/honda/values.py b/opendbc_repo/opendbc/car/honda/values.py index 078a5de53..34fb86ab2 100644 --- a/opendbc_repo/opendbc/car/honda/values.py +++ b/opendbc_repo/opendbc/car/honda/values.py @@ -57,6 +57,9 @@ class HondaSafetyFlags(IntFlag): RADARLESS = 8 BOSCH_CANFD = 16 GAS_INTERCEPTOR = 32 + # Accord 11G MVL radar/camera handover messages. Keep the generic CAN-FD + # safety profile unchanged for other Honda CAN-FD platforms (for example CR-V 6G). + BOSCH_CANFD_MVL = 64 class HondaFlags(IntFlag): @@ -179,8 +182,9 @@ class CAR(Platforms): [ HondaCarDocs("Honda Accord 2023-25", "All"), HondaCarDocs("Honda Accord Hybrid 2023-25", "All"), - ], - CarSpecs(mass=3477 * CV.LB_TO_KG, wheelbase=2.83, steerRatio=16.0, centerToFrontRatio=0.39), + ], + CarSpecs(mass=3477 * CV.LB_TO_KG, wheelbase=2.83, steerRatio=16.7, centerToFrontRatio=0.39), + {Bus.pt: 'honda_common_canfd_generated', Bus.radar: 'honda_common_canfd_generated'}, ) HONDA_CIVIC_BOSCH = HondaBoschPlatformConfig( [ diff --git a/opendbc_repo/opendbc/dbc/acura_ilx_2016_can_generated.dbc b/opendbc_repo/opendbc/dbc/acura_ilx_2016_can_generated.dbc index 39419e0f6..fa0a7816e 100644 --- a/opendbc_repo/opendbc/dbc/acura_ilx_2016_can_generated.dbc +++ b/opendbc_repo/opendbc/dbc/acura_ilx_2016_can_generated.dbc @@ -430,8 +430,8 @@ CM_ SG_ 419 REGEN_STAGE_SELECTION "Driver-selected regenerative braking threshol CM_ SG_ 419 REGEN_MEMORY "Driver-selected persistence setting, M shown in instrument cluster"; CM_ SG_ 419 REGEN_UNKNOWN "Both bits set when user enables regen, otherwise zero"; -VAL_ 401 GEAR_SHIFTER 1 "P" 2 "R" 3 "N" 4 "D" 7 "L" 10 "S"; -VAL_ 419 GEAR_SHIFTER 1 "P" 2 "R" 3 "N" 4 "D" 7 "L" 10 "S"; +VAL_ 401 GEAR_SHIFTER 1 "P" 2 "R" 3 "N" 4 "D" 7 "L" 10 "S" 11 "B"; +VAL_ 419 GEAR_SHIFTER 1 "P" 2 "R" 3 "N" 4 "D" 7 "L" 10 "S" 11 "B"; VAL_ 419 TRANS_TARGET_GEAR 0 "None / Neutral / Park" 1 "1st" 2 "2nd" 3 "3rd" 4 "4th" 5 "5th" 6 "6th" 7 "7th" 8 "8th" 9 "9th" 10 "10th" 13 "Reverse"; VAL_ 419 REGEN_STAGE_SELECTION 0 "disabled" 1 "stage_1" 2 "stage_2" 3 "stage_3" 4 "stage_4" 5 "stage_5" 6 "stage_6"; VAL_ 419 REGEN_MEMORY 0 "disabled" 1 "persistent"; diff --git a/opendbc_repo/opendbc/dbc/acura_mdx_2017_can_ext_generated.dbc b/opendbc_repo/opendbc/dbc/acura_mdx_2017_can_ext_generated.dbc index 9f79ecad6..f8e35a433 100644 --- a/opendbc_repo/opendbc/dbc/acura_mdx_2017_can_ext_generated.dbc +++ b/opendbc_repo/opendbc/dbc/acura_mdx_2017_can_ext_generated.dbc @@ -431,8 +431,8 @@ CM_ SG_ 419 REGEN_STAGE_SELECTION "Driver-selected regenerative braking threshol CM_ SG_ 419 REGEN_MEMORY "Driver-selected persistence setting, M shown in instrument cluster"; CM_ SG_ 419 REGEN_UNKNOWN "Both bits set when user enables regen, otherwise zero"; -VAL_ 401 GEAR_SHIFTER 1 "P" 2 "R" 3 "N" 4 "D" 7 "L" 10 "S"; -VAL_ 419 GEAR_SHIFTER 1 "P" 2 "R" 3 "N" 4 "D" 7 "L" 10 "S"; +VAL_ 401 GEAR_SHIFTER 1 "P" 2 "R" 3 "N" 4 "D" 7 "L" 10 "S" 11 "B"; +VAL_ 419 GEAR_SHIFTER 1 "P" 2 "R" 3 "N" 4 "D" 7 "L" 10 "S" 11 "B"; VAL_ 419 TRANS_TARGET_GEAR 0 "None / Neutral / Park" 1 "1st" 2 "2nd" 3 "3rd" 4 "4th" 5 "5th" 6 "6th" 7 "7th" 8 "8th" 9 "9th" 10 "10th" 13 "Reverse"; VAL_ 419 REGEN_STAGE_SELECTION 0 "disabled" 1 "stage_1" 2 "stage_2" 3 "stage_3" 4 "stage_4" 5 "stage_5" 6 "stage_6"; VAL_ 419 REGEN_MEMORY 0 "disabled" 1 "persistent"; diff --git a/opendbc_repo/opendbc/dbc/acura_rdx_2020_can_generated.dbc b/opendbc_repo/opendbc/dbc/acura_rdx_2020_can_generated.dbc index 5889ed044..14c1c738a 100644 --- a/opendbc_repo/opendbc/dbc/acura_rdx_2020_can_generated.dbc +++ b/opendbc_repo/opendbc/dbc/acura_rdx_2020_can_generated.dbc @@ -349,6 +349,7 @@ BO_ 586 ADJACENT_RIGHT_LANE_LINE_2: 8 CAM BO_ 662 SCM_BUTTONS: 4 SCM SG_ CRUISE_BUTTONS : 7|3@0+ (1,0) [0|7] "" EON SG_ CRUISE_SETTING : 3|2@0+ (1,0) [0|3] "" EON + SG_ AMBIENT_LIGHT_MAYBE : 23|8@0+ (1,0) [0|255] "" EON SG_ COUNTER : 29|2@0+ (1,0) [0|3] "" EON SG_ CHECKSUM : 27|4@0+ (1,0) [0|15] "" EON @@ -560,8 +561,8 @@ CM_ SG_ 419 REGEN_STAGE_SELECTION "Driver-selected regenerative braking threshol CM_ SG_ 419 REGEN_MEMORY "Driver-selected persistence setting, M shown in instrument cluster"; CM_ SG_ 419 REGEN_UNKNOWN "Both bits set when user enables regen, otherwise zero"; -VAL_ 401 GEAR_SHIFTER 1 "P" 2 "R" 3 "N" 4 "D" 7 "L" 10 "S"; -VAL_ 419 GEAR_SHIFTER 1 "P" 2 "R" 3 "N" 4 "D" 7 "L" 10 "S"; +VAL_ 401 GEAR_SHIFTER 1 "P" 2 "R" 3 "N" 4 "D" 7 "L" 10 "S" 11 "B"; +VAL_ 419 GEAR_SHIFTER 1 "P" 2 "R" 3 "N" 4 "D" 7 "L" 10 "S" 11 "B"; VAL_ 419 TRANS_TARGET_GEAR 0 "None / Neutral / Park" 1 "1st" 2 "2nd" 3 "3rd" 4 "4th" 5 "5th" 6 "6th" 7 "7th" 8 "8th" 9 "9th" 10 "10th" 13 "Reverse"; VAL_ 419 REGEN_STAGE_SELECTION 0 "disabled" 1 "stage_1" 2 "stage_2" 3 "stage_3" 4 "stage_4" 5 "stage_5" 6 "stage_6"; VAL_ 419 REGEN_MEMORY 0 "disabled" 1 "persistent"; diff --git a/opendbc_repo/opendbc/dbc/generator/honda/_bosch_2018.dbc b/opendbc_repo/opendbc/dbc/generator/honda/_bosch_2018.dbc index d5171fdef..e3b37a197 100644 --- a/opendbc_repo/opendbc/dbc/generator/honda/_bosch_2018.dbc +++ b/opendbc_repo/opendbc/dbc/generator/honda/_bosch_2018.dbc @@ -128,6 +128,7 @@ BO_ 586 ADJACENT_RIGHT_LANE_LINE_2: 8 CAM BO_ 662 SCM_BUTTONS: 4 SCM SG_ CRUISE_BUTTONS : 7|3@0+ (1,0) [0|7] "" EON SG_ CRUISE_SETTING : 3|2@0+ (1,0) [0|3] "" EON + SG_ AMBIENT_LIGHT_MAYBE : 23|8@0+ (1,0) [0|255] "" EON SG_ COUNTER : 29|2@0+ (1,0) [0|3] "" EON SG_ CHECKSUM : 27|4@0+ (1,0) [0|15] "" EON diff --git a/opendbc_repo/opendbc/dbc/generator/honda/_gearbox_common.dbc b/opendbc_repo/opendbc/dbc/generator/honda/_gearbox_common.dbc index 6cd9ccb62..026089d71 100644 --- a/opendbc_repo/opendbc/dbc/generator/honda/_gearbox_common.dbc +++ b/opendbc_repo/opendbc/dbc/generator/honda/_gearbox_common.dbc @@ -34,8 +34,8 @@ CM_ SG_ 419 REGEN_STAGE_SELECTION "Driver-selected regenerative braking threshol CM_ SG_ 419 REGEN_MEMORY "Driver-selected persistence setting, M shown in instrument cluster"; CM_ SG_ 419 REGEN_UNKNOWN "Both bits set when user enables regen, otherwise zero"; -VAL_ 401 GEAR_SHIFTER 1 "P" 2 "R" 3 "N" 4 "D" 7 "L" 10 "S"; -VAL_ 419 GEAR_SHIFTER 1 "P" 2 "R" 3 "N" 4 "D" 7 "L" 10 "S"; +VAL_ 401 GEAR_SHIFTER 1 "P" 2 "R" 3 "N" 4 "D" 7 "L" 10 "S" 11 "B"; +VAL_ 419 GEAR_SHIFTER 1 "P" 2 "R" 3 "N" 4 "D" 7 "L" 10 "S" 11 "B"; VAL_ 419 TRANS_TARGET_GEAR 0 "None / Neutral / Park" 1 "1st" 2 "2nd" 3 "3rd" 4 "4th" 5 "5th" 6 "6th" 7 "7th" 8 "8th" 9 "9th" 10 "10th" 13 "Reverse"; VAL_ 419 REGEN_STAGE_SELECTION 0 "disabled" 1 "stage_1" 2 "stage_2" 3 "stage_3" 4 "stage_4" 5 "stage_5" 6 "stage_6"; VAL_ 419 REGEN_MEMORY 0 "disabled" 1 "persistent"; diff --git a/opendbc_repo/opendbc/dbc/generator/honda/honda_common_canfd.dbc b/opendbc_repo/opendbc/dbc/generator/honda/honda_common_canfd.dbc index cd7efe7be..4c19ed968 100644 --- a/opendbc_repo/opendbc/dbc/generator/honda/honda_common_canfd.dbc +++ b/opendbc_repo/opendbc/dbc/generator/honda/honda_common_canfd.dbc @@ -5,3 +5,71 @@ CM_ "IMPORT _lkas_hud_8byte.dbc"; CM_ "IMPORT _bosch_standstill.dbc"; CM_ "IMPORT _steering_sensors_a.dbc"; CM_ "IMPORT _gearbox_common.dbc"; + +BO_ 929 RADAR_REFERENCE: 8 XXX + SG_ CHECKSUM : 59|4@0+ (1,0) [0|15] "" EON + SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" EON + +BO_ 784 RADAR_HUD_CANFD: 8 XXX + SG_ SET_ME_X01 : 11|1@0+ (1,0) [0|1] "" XXX + SG_ SET_ME_X01_2 : 48|1@0+ (1,0) [0|1] "" XXX + SG_ CMBS_ENABLED_MAYBE : 53|1@0+ (1,0) [0|1] "" XXX + SG_ ACC_ON : 55|1@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 59|4@0+ (1,0) [0|15] "" EON + SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" EON + +BO_ 114120024 LANE_PATH: 8 XXX + SG_ MUX M : 7|6@0+ (1,0) [0|63] "" XXX + SG_ PATH_OFFSET_1 m1 : 15|12@0- (1,0) [-2048|2047] "" XXX + SG_ PATH_OFFSET_2 m1 : 19|12@0- (1,0) [-2048|2047] "" XXX + SG_ PATH_OFFSET_3 m1 : 39|12@0- (1,0) [-2048|2047] "" XXX + SG_ PATH_OFFSET_4 m1 : 43|12@0- (1,0) [-2048|2047] "" XXX + SG_ CHECKSUM : 59|4@0+ (1,0) [0|15] "" XXX + SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" XXX + +BO_ 114120025 HUD_OBJECTS: 8 XXX + SG_ MUX M : 7|6@0+ (1,0) [0|63] "" XXX + SG_ OBJECT_ID m1 : 15|5@0+ (1,0) [0|31] "" XXX + SG_ IS_LEAD_CAR m1 : 17|1@0+ (1,0) [0|1] "" XXX + SG_ CAR_TYPE m1 : 23|4@0- (1,0) [-8|7] "" XXX + SG_ ROTATION m1 : 31|8@0- (1,0) [-128|127] "" XXX + SG_ LONG_DIST m1 : 39|10@0+ (0.209,-16.9) [-16.9|196.9] "m" XXX + SG_ LAT_DIST m1 : 43|12@0- (0.1,0) [-204.8|204.7] "m" XXX + SG_ CHECKSUM : 59|4@0+ (1,0) [0|15] "" XXX + SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" XXX + +BO_ 254913106 RADAR_LEAD2: 8 XXX + SG_ SET_ME_X88 : 7|8@0+ (1,0) [0|255] "" XXX + SG_ SET_ME_X78 : 15|8@0+ (1,0) [0|255] "" XXX + SG_ LEAD_DISTANCE_MAYBE : 23|11@0+ (1,0) [0|2047] "" XXX + SG_ CHECKSUM : 59|4@0+ (1,0) [0|15] "" XXX + SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" XXX + +BO_ 254913116 RADAR_LEAD: 8 XXX + SG_ SET_ME_X01 : 5|1@0+ (1,0) [0|1] "" XXX + SG_ CNTR_REF : 7|2@0+ (1,0) [0|3] "" XXX + SG_ TARGET_SPEED_MAYBE : 15|8@0+ (1,0) [0|255] "" XXX + SG_ LEFT_LANE : 23|2@0+ (1,0) [0|3] "" XXX + SG_ RIGHT_LANE : 21|2@0+ (1,0) [0|3] "" XXX + SG_ LANE_PATH_LENGTH : 31|6@0+ (1,0) [0|63] "" XXX + SG_ CHECKSUM : 59|4@0+ (1,0) [0|15] "" XXX + SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" XXX + +BO_ 440773198 BOSCH_SUPPLEMENTAL_CANFD: 8 XXX + SG_ SET_ME_X01 : 7|8@0+ (1,0) [0|255] "" XXX + SG_ SET_ME_X41 : 23|8@0+ (1,0) [0|255] "" XXX + SG_ CHECKSUM : 59|4@0+ (1,0) [0|15] "" XXX + SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" XXX + +BO_ 1808 RADAR_SUPP_TICK_REFERENCE: 32 XXX + SG_ IGNORE : 11|1@0+ (1,0) [0|1] "" XXX + +BO_ 1840 RADAR_HUD_TICK_REFERENCE: 6 XXX + SG_ IGNORE : 11|1@0+ (1,0) [0|1] "" XXX + +BO_ 1872 RADAR_50HZ_TICK_REFERENCE: 16 XXX + SG_ IGNORE : 11|1@0+ (1,0) [0|1] "" XXX + +CM_ SG_ 254913116 LANE_PATH_LENGTH "number of valid LANE_PATH points in the current sweep (6 = idle/no lane, up to 23-24); the dash needs this to match the in-band 2047 terminator to draw the lane lines"; +CM_ SG_ 254913116 LEFT_LANE "3 = left lane line detected, 0 = none; tracks the camera's LKAS_HUD LANE_LINES bit 1 exactly in factory logs. The CAN FD equivalent of radarless LKAS_HUD_2 LEFT_LANE; the dash won't draw the lane lines while both are 0"; +CM_ SG_ 254913116 RIGHT_LANE "3 = right lane line detected, 0 = none; tracks the camera's LKAS_HUD LANE_LINES bit 0 exactly in factory logs. The CAN FD equivalent of radarless LKAS_HUD_2 RIGHT_LANE; the dash won't draw the lane lines while both are 0"; diff --git a/opendbc_repo/opendbc/dbc/honda_bosch_radarless_generated.dbc b/opendbc_repo/opendbc/dbc/honda_bosch_radarless_generated.dbc index 50da54396..e339d1689 100644 --- a/opendbc_repo/opendbc/dbc/honda_bosch_radarless_generated.dbc +++ b/opendbc_repo/opendbc/dbc/honda_bosch_radarless_generated.dbc @@ -349,6 +349,7 @@ BO_ 586 ADJACENT_RIGHT_LANE_LINE_2: 8 CAM BO_ 662 SCM_BUTTONS: 4 SCM SG_ CRUISE_BUTTONS : 7|3@0+ (1,0) [0|7] "" EON SG_ CRUISE_SETTING : 3|2@0+ (1,0) [0|3] "" EON + SG_ AMBIENT_LIGHT_MAYBE : 23|8@0+ (1,0) [0|255] "" EON SG_ COUNTER : 29|2@0+ (1,0) [0|3] "" EON SG_ CHECKSUM : 27|4@0+ (1,0) [0|15] "" EON @@ -532,8 +533,8 @@ CM_ SG_ 419 REGEN_STAGE_SELECTION "Driver-selected regenerative braking threshol CM_ SG_ 419 REGEN_MEMORY "Driver-selected persistence setting, M shown in instrument cluster"; CM_ SG_ 419 REGEN_UNKNOWN "Both bits set when user enables regen, otherwise zero"; -VAL_ 401 GEAR_SHIFTER 1 "P" 2 "R" 3 "N" 4 "D" 7 "L" 10 "S"; -VAL_ 419 GEAR_SHIFTER 1 "P" 2 "R" 3 "N" 4 "D" 7 "L" 10 "S"; +VAL_ 401 GEAR_SHIFTER 1 "P" 2 "R" 3 "N" 4 "D" 7 "L" 10 "S" 11 "B"; +VAL_ 419 GEAR_SHIFTER 1 "P" 2 "R" 3 "N" 4 "D" 7 "L" 10 "S" 11 "B"; VAL_ 419 TRANS_TARGET_GEAR 0 "None / Neutral / Park" 1 "1st" 2 "2nd" 3 "3rd" 4 "4th" 5 "5th" 6 "6th" 7 "7th" 8 "8th" 9 "9th" 10 "10th" 13 "Reverse"; VAL_ 419 REGEN_STAGE_SELECTION 0 "disabled" 1 "stage_1" 2 "stage_2" 3 "stage_3" 4 "stage_4" 5 "stage_5" 6 "stage_6"; VAL_ 419 REGEN_MEMORY 0 "disabled" 1 "persistent"; diff --git a/opendbc_repo/opendbc/dbc/honda_civic_hatchback_ex_2017_can_generated.dbc b/opendbc_repo/opendbc/dbc/honda_civic_hatchback_ex_2017_can_generated.dbc index 30fb0f098..790005509 100644 --- a/opendbc_repo/opendbc/dbc/honda_civic_hatchback_ex_2017_can_generated.dbc +++ b/opendbc_repo/opendbc/dbc/honda_civic_hatchback_ex_2017_can_generated.dbc @@ -349,6 +349,7 @@ BO_ 586 ADJACENT_RIGHT_LANE_LINE_2: 8 CAM BO_ 662 SCM_BUTTONS: 4 SCM SG_ CRUISE_BUTTONS : 7|3@0+ (1,0) [0|7] "" EON SG_ CRUISE_SETTING : 3|2@0+ (1,0) [0|3] "" EON + SG_ AMBIENT_LIGHT_MAYBE : 23|8@0+ (1,0) [0|255] "" EON SG_ COUNTER : 29|2@0+ (1,0) [0|3] "" EON SG_ CHECKSUM : 27|4@0+ (1,0) [0|15] "" EON @@ -564,8 +565,8 @@ CM_ SG_ 419 REGEN_STAGE_SELECTION "Driver-selected regenerative braking threshol CM_ SG_ 419 REGEN_MEMORY "Driver-selected persistence setting, M shown in instrument cluster"; CM_ SG_ 419 REGEN_UNKNOWN "Both bits set when user enables regen, otherwise zero"; -VAL_ 401 GEAR_SHIFTER 1 "P" 2 "R" 3 "N" 4 "D" 7 "L" 10 "S"; -VAL_ 419 GEAR_SHIFTER 1 "P" 2 "R" 3 "N" 4 "D" 7 "L" 10 "S"; +VAL_ 401 GEAR_SHIFTER 1 "P" 2 "R" 3 "N" 4 "D" 7 "L" 10 "S" 11 "B"; +VAL_ 419 GEAR_SHIFTER 1 "P" 2 "R" 3 "N" 4 "D" 7 "L" 10 "S" 11 "B"; VAL_ 419 TRANS_TARGET_GEAR 0 "None / Neutral / Park" 1 "1st" 2 "2nd" 3 "3rd" 4 "4th" 5 "5th" 6 "6th" 7 "7th" 8 "8th" 9 "9th" 10 "10th" 13 "Reverse"; VAL_ 419 REGEN_STAGE_SELECTION 0 "disabled" 1 "stage_1" 2 "stage_2" 3 "stage_3" 4 "stage_4" 5 "stage_5" 6 "stage_6"; VAL_ 419 REGEN_MEMORY 0 "disabled" 1 "persistent"; diff --git a/opendbc_repo/opendbc/dbc/honda_civic_touring_2016_can_generated.dbc b/opendbc_repo/opendbc/dbc/honda_civic_touring_2016_can_generated.dbc index 12ecbd992..c4e638cc8 100644 --- a/opendbc_repo/opendbc/dbc/honda_civic_touring_2016_can_generated.dbc +++ b/opendbc_repo/opendbc/dbc/honda_civic_touring_2016_can_generated.dbc @@ -434,8 +434,8 @@ CM_ SG_ 419 REGEN_STAGE_SELECTION "Driver-selected regenerative braking threshol CM_ SG_ 419 REGEN_MEMORY "Driver-selected persistence setting, M shown in instrument cluster"; CM_ SG_ 419 REGEN_UNKNOWN "Both bits set when user enables regen, otherwise zero"; -VAL_ 401 GEAR_SHIFTER 1 "P" 2 "R" 3 "N" 4 "D" 7 "L" 10 "S"; -VAL_ 419 GEAR_SHIFTER 1 "P" 2 "R" 3 "N" 4 "D" 7 "L" 10 "S"; +VAL_ 401 GEAR_SHIFTER 1 "P" 2 "R" 3 "N" 4 "D" 7 "L" 10 "S" 11 "B"; +VAL_ 419 GEAR_SHIFTER 1 "P" 2 "R" 3 "N" 4 "D" 7 "L" 10 "S" 11 "B"; VAL_ 419 TRANS_TARGET_GEAR 0 "None / Neutral / Park" 1 "1st" 2 "2nd" 3 "3rd" 4 "4th" 5 "5th" 6 "6th" 7 "7th" 8 "8th" 9 "9th" 10 "10th" 13 "Reverse"; VAL_ 419 REGEN_STAGE_SELECTION 0 "disabled" 1 "stage_1" 2 "stage_2" 3 "stage_3" 4 "stage_4" 5 "stage_5" 6 "stage_6"; VAL_ 419 REGEN_MEMORY 0 "disabled" 1 "persistent"; diff --git a/opendbc_repo/opendbc/dbc/honda_clarity_hybrid_2018_can_generated.dbc b/opendbc_repo/opendbc/dbc/honda_clarity_hybrid_2018_can_generated.dbc index 8802cb52a..1d727a814 100644 --- a/opendbc_repo/opendbc/dbc/honda_clarity_hybrid_2018_can_generated.dbc +++ b/opendbc_repo/opendbc/dbc/honda_clarity_hybrid_2018_can_generated.dbc @@ -434,8 +434,8 @@ CM_ SG_ 419 REGEN_STAGE_SELECTION "Driver-selected regenerative braking threshol CM_ SG_ 419 REGEN_MEMORY "Driver-selected persistence setting, M shown in instrument cluster"; CM_ SG_ 419 REGEN_UNKNOWN "Both bits set when user enables regen, otherwise zero"; -VAL_ 401 GEAR_SHIFTER 1 "P" 2 "R" 3 "N" 4 "D" 7 "L" 10 "S"; -VAL_ 419 GEAR_SHIFTER 1 "P" 2 "R" 3 "N" 4 "D" 7 "L" 10 "S"; +VAL_ 401 GEAR_SHIFTER 1 "P" 2 "R" 3 "N" 4 "D" 7 "L" 10 "S" 11 "B"; +VAL_ 419 GEAR_SHIFTER 1 "P" 2 "R" 3 "N" 4 "D" 7 "L" 10 "S" 11 "B"; VAL_ 419 TRANS_TARGET_GEAR 0 "None / Neutral / Park" 1 "1st" 2 "2nd" 3 "3rd" 4 "4th" 5 "5th" 6 "6th" 7 "7th" 8 "8th" 9 "9th" 10 "10th" 13 "Reverse"; VAL_ 419 REGEN_STAGE_SELECTION 0 "disabled" 1 "stage_1" 2 "stage_2" 3 "stage_3" 4 "stage_4" 5 "stage_5" 6 "stage_6"; VAL_ 419 REGEN_MEMORY 0 "disabled" 1 "persistent"; diff --git a/opendbc_repo/opendbc/dbc/honda_common_canfd_generated.dbc b/opendbc_repo/opendbc/dbc/honda_common_canfd_generated.dbc index 228dc11ae..528c61224 100644 --- a/opendbc_repo/opendbc/dbc/honda_common_canfd_generated.dbc +++ b/opendbc_repo/opendbc/dbc/honda_common_canfd_generated.dbc @@ -349,6 +349,7 @@ BO_ 586 ADJACENT_RIGHT_LANE_LINE_2: 8 CAM BO_ 662 SCM_BUTTONS: 4 SCM SG_ CRUISE_BUTTONS : 7|3@0+ (1,0) [0|7] "" EON SG_ CRUISE_SETTING : 3|2@0+ (1,0) [0|3] "" EON + SG_ AMBIENT_LIGHT_MAYBE : 23|8@0+ (1,0) [0|255] "" EON SG_ COUNTER : 29|2@0+ (1,0) [0|3] "" EON SG_ CHECKSUM : 27|4@0+ (1,0) [0|15] "" EON @@ -565,10 +566,78 @@ CM_ SG_ 419 REGEN_STAGE_SELECTION "Driver-selected regenerative braking threshol CM_ SG_ 419 REGEN_MEMORY "Driver-selected persistence setting, M shown in instrument cluster"; CM_ SG_ 419 REGEN_UNKNOWN "Both bits set when user enables regen, otherwise zero"; -VAL_ 401 GEAR_SHIFTER 1 "P" 2 "R" 3 "N" 4 "D" 7 "L" 10 "S"; -VAL_ 419 GEAR_SHIFTER 1 "P" 2 "R" 3 "N" 4 "D" 7 "L" 10 "S"; +VAL_ 401 GEAR_SHIFTER 1 "P" 2 "R" 3 "N" 4 "D" 7 "L" 10 "S" 11 "B"; +VAL_ 419 GEAR_SHIFTER 1 "P" 2 "R" 3 "N" 4 "D" 7 "L" 10 "S" 11 "B"; VAL_ 419 TRANS_TARGET_GEAR 0 "None / Neutral / Park" 1 "1st" 2 "2nd" 3 "3rd" 4 "4th" 5 "5th" 6 "6th" 7 "7th" 8 "8th" 9 "9th" 10 "10th" 13 "Reverse"; VAL_ 419 REGEN_STAGE_SELECTION 0 "disabled" 1 "stage_1" 2 "stage_2" 3 "stage_3" 4 "stage_4" 5 "stage_5" 6 "stage_6"; VAL_ 419 REGEN_MEMORY 0 "disabled" 1 "persistent"; CM_ "honda_common_canfd.dbc starts here"; + +BO_ 929 RADAR_REFERENCE: 8 XXX + SG_ CHECKSUM : 59|4@0+ (1,0) [0|15] "" EON + SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" EON + +BO_ 784 RADAR_HUD_CANFD: 8 XXX + SG_ SET_ME_X01 : 11|1@0+ (1,0) [0|1] "" XXX + SG_ SET_ME_X01_2 : 48|1@0+ (1,0) [0|1] "" XXX + SG_ CMBS_ENABLED_MAYBE : 53|1@0+ (1,0) [0|1] "" XXX + SG_ ACC_ON : 55|1@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 59|4@0+ (1,0) [0|15] "" EON + SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" EON + +BO_ 114120024 LANE_PATH: 8 XXX + SG_ MUX M : 7|6@0+ (1,0) [0|63] "" XXX + SG_ PATH_OFFSET_1 m1 : 15|12@0- (1,0) [-2048|2047] "" XXX + SG_ PATH_OFFSET_2 m1 : 19|12@0- (1,0) [-2048|2047] "" XXX + SG_ PATH_OFFSET_3 m1 : 39|12@0- (1,0) [-2048|2047] "" XXX + SG_ PATH_OFFSET_4 m1 : 43|12@0- (1,0) [-2048|2047] "" XXX + SG_ CHECKSUM : 59|4@0+ (1,0) [0|15] "" XXX + SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" XXX + +BO_ 114120025 HUD_OBJECTS: 8 XXX + SG_ MUX M : 7|6@0+ (1,0) [0|63] "" XXX + SG_ OBJECT_ID m1 : 15|5@0+ (1,0) [0|31] "" XXX + SG_ IS_LEAD_CAR m1 : 17|1@0+ (1,0) [0|1] "" XXX + SG_ CAR_TYPE m1 : 23|4@0- (1,0) [-8|7] "" XXX + SG_ ROTATION m1 : 31|8@0- (1,0) [-128|127] "" XXX + SG_ LONG_DIST m1 : 39|10@0+ (0.209,-16.9) [-16.9|196.9] "m" XXX + SG_ LAT_DIST m1 : 43|12@0- (0.1,0) [-204.8|204.7] "m" XXX + SG_ CHECKSUM : 59|4@0+ (1,0) [0|15] "" XXX + SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" XXX + +BO_ 254913106 RADAR_LEAD2: 8 XXX + SG_ SET_ME_X88 : 7|8@0+ (1,0) [0|255] "" XXX + SG_ SET_ME_X78 : 15|8@0+ (1,0) [0|255] "" XXX + SG_ LEAD_DISTANCE_MAYBE : 23|11@0+ (1,0) [0|2047] "" XXX + SG_ CHECKSUM : 59|4@0+ (1,0) [0|15] "" XXX + SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" XXX + +BO_ 254913116 RADAR_LEAD: 8 XXX + SG_ SET_ME_X01 : 5|1@0+ (1,0) [0|1] "" XXX + SG_ CNTR_REF : 7|2@0+ (1,0) [0|3] "" XXX + SG_ TARGET_SPEED_MAYBE : 15|8@0+ (1,0) [0|255] "" XXX + SG_ LEFT_LANE : 23|2@0+ (1,0) [0|3] "" XXX + SG_ RIGHT_LANE : 21|2@0+ (1,0) [0|3] "" XXX + SG_ LANE_PATH_LENGTH : 31|6@0+ (1,0) [0|63] "" XXX + SG_ CHECKSUM : 59|4@0+ (1,0) [0|15] "" XXX + SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" XXX + +BO_ 440773198 BOSCH_SUPPLEMENTAL_CANFD: 8 XXX + SG_ SET_ME_X01 : 7|8@0+ (1,0) [0|255] "" XXX + SG_ SET_ME_X41 : 23|8@0+ (1,0) [0|255] "" XXX + SG_ CHECKSUM : 59|4@0+ (1,0) [0|15] "" XXX + SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" XXX + +BO_ 1808 RADAR_SUPP_TICK_REFERENCE: 32 XXX + SG_ IGNORE : 11|1@0+ (1,0) [0|1] "" XXX + +BO_ 1840 RADAR_HUD_TICK_REFERENCE: 6 XXX + SG_ IGNORE : 11|1@0+ (1,0) [0|1] "" XXX + +BO_ 1872 RADAR_50HZ_TICK_REFERENCE: 16 XXX + SG_ IGNORE : 11|1@0+ (1,0) [0|1] "" XXX + +CM_ SG_ 254913116 LANE_PATH_LENGTH "number of valid LANE_PATH points in the current sweep (6 = idle/no lane, up to 23-24); the dash needs this to match the in-band 2047 terminator to draw the lane lines"; +CM_ SG_ 254913116 LEFT_LANE "3 = left lane line detected, 0 = none; tracks the camera's LKAS_HUD LANE_LINES bit 1 exactly in factory logs. The CAN FD equivalent of radarless LKAS_HUD_2 LEFT_LANE; the dash won't draw the lane lines while both are 0"; +CM_ SG_ 254913116 RIGHT_LANE "3 = right lane line detected, 0 = none; tracks the camera's LKAS_HUD LANE_LINES bit 0 exactly in factory logs. The CAN FD equivalent of radarless LKAS_HUD_2 RIGHT_LANE; the dash won't draw the lane lines while both are 0"; diff --git a/opendbc_repo/opendbc/dbc/honda_crv_touring_2016_can_generated.dbc b/opendbc_repo/opendbc/dbc/honda_crv_touring_2016_can_generated.dbc index c8676afe0..50fe91be2 100644 --- a/opendbc_repo/opendbc/dbc/honda_crv_touring_2016_can_generated.dbc +++ b/opendbc_repo/opendbc/dbc/honda_crv_touring_2016_can_generated.dbc @@ -429,8 +429,8 @@ CM_ SG_ 419 REGEN_STAGE_SELECTION "Driver-selected regenerative braking threshol CM_ SG_ 419 REGEN_MEMORY "Driver-selected persistence setting, M shown in instrument cluster"; CM_ SG_ 419 REGEN_UNKNOWN "Both bits set when user enables regen, otherwise zero"; -VAL_ 401 GEAR_SHIFTER 1 "P" 2 "R" 3 "N" 4 "D" 7 "L" 10 "S"; -VAL_ 419 GEAR_SHIFTER 1 "P" 2 "R" 3 "N" 4 "D" 7 "L" 10 "S"; +VAL_ 401 GEAR_SHIFTER 1 "P" 2 "R" 3 "N" 4 "D" 7 "L" 10 "S" 11 "B"; +VAL_ 419 GEAR_SHIFTER 1 "P" 2 "R" 3 "N" 4 "D" 7 "L" 10 "S" 11 "B"; VAL_ 419 TRANS_TARGET_GEAR 0 "None / Neutral / Park" 1 "1st" 2 "2nd" 3 "3rd" 4 "4th" 5 "5th" 6 "6th" 7 "7th" 8 "8th" 9 "9th" 10 "10th" 13 "Reverse"; VAL_ 419 REGEN_STAGE_SELECTION 0 "disabled" 1 "stage_1" 2 "stage_2" 3 "stage_3" 4 "stage_4" 5 "stage_5" 6 "stage_6"; VAL_ 419 REGEN_MEMORY 0 "disabled" 1 "persistent"; diff --git a/opendbc_repo/opendbc/dbc/honda_e_advance_2020_can_generated.dbc b/opendbc_repo/opendbc/dbc/honda_e_advance_2020_can_generated.dbc index 9e2c765ad..fb28a0c97 100644 --- a/opendbc_repo/opendbc/dbc/honda_e_advance_2020_can_generated.dbc +++ b/opendbc_repo/opendbc/dbc/honda_e_advance_2020_can_generated.dbc @@ -349,6 +349,7 @@ BO_ 586 ADJACENT_RIGHT_LANE_LINE_2: 8 CAM BO_ 662 SCM_BUTTONS: 4 SCM SG_ CRUISE_BUTTONS : 7|3@0+ (1,0) [0|7] "" EON SG_ CRUISE_SETTING : 3|2@0+ (1,0) [0|3] "" EON + SG_ AMBIENT_LIGHT_MAYBE : 23|8@0+ (1,0) [0|255] "" EON SG_ COUNTER : 29|2@0+ (1,0) [0|3] "" EON SG_ CHECKSUM : 27|4@0+ (1,0) [0|15] "" EON @@ -561,8 +562,8 @@ CM_ SG_ 419 REGEN_STAGE_SELECTION "Driver-selected regenerative braking threshol CM_ SG_ 419 REGEN_MEMORY "Driver-selected persistence setting, M shown in instrument cluster"; CM_ SG_ 419 REGEN_UNKNOWN "Both bits set when user enables regen, otherwise zero"; -VAL_ 401 GEAR_SHIFTER 1 "P" 2 "R" 3 "N" 4 "D" 7 "L" 10 "S"; -VAL_ 419 GEAR_SHIFTER 1 "P" 2 "R" 3 "N" 4 "D" 7 "L" 10 "S"; +VAL_ 401 GEAR_SHIFTER 1 "P" 2 "R" 3 "N" 4 "D" 7 "L" 10 "S" 11 "B"; +VAL_ 419 GEAR_SHIFTER 1 "P" 2 "R" 3 "N" 4 "D" 7 "L" 10 "S" 11 "B"; VAL_ 419 TRANS_TARGET_GEAR 0 "None / Neutral / Park" 1 "1st" 2 "2nd" 3 "3rd" 4 "4th" 5 "5th" 6 "6th" 7 "7th" 8 "8th" 9 "9th" 10 "10th" 13 "Reverse"; VAL_ 419 REGEN_STAGE_SELECTION 0 "disabled" 1 "stage_1" 2 "stage_2" 3 "stage_3" 4 "stage_4" 5 "stage_5" 6 "stage_6"; VAL_ 419 REGEN_MEMORY 0 "disabled" 1 "persistent"; diff --git a/opendbc_repo/opendbc/dbc/honda_insight_ex_2019_can_generated.dbc b/opendbc_repo/opendbc/dbc/honda_insight_ex_2019_can_generated.dbc index b9d78e97a..52cd28b37 100644 --- a/opendbc_repo/opendbc/dbc/honda_insight_ex_2019_can_generated.dbc +++ b/opendbc_repo/opendbc/dbc/honda_insight_ex_2019_can_generated.dbc @@ -349,6 +349,7 @@ BO_ 586 ADJACENT_RIGHT_LANE_LINE_2: 8 CAM BO_ 662 SCM_BUTTONS: 4 SCM SG_ CRUISE_BUTTONS : 7|3@0+ (1,0) [0|7] "" EON SG_ CRUISE_SETTING : 3|2@0+ (1,0) [0|3] "" EON + SG_ AMBIENT_LIGHT_MAYBE : 23|8@0+ (1,0) [0|255] "" EON SG_ COUNTER : 29|2@0+ (1,0) [0|3] "" EON SG_ CHECKSUM : 27|4@0+ (1,0) [0|15] "" EON @@ -554,8 +555,8 @@ CM_ SG_ 419 REGEN_STAGE_SELECTION "Driver-selected regenerative braking threshol CM_ SG_ 419 REGEN_MEMORY "Driver-selected persistence setting, M shown in instrument cluster"; CM_ SG_ 419 REGEN_UNKNOWN "Both bits set when user enables regen, otherwise zero"; -VAL_ 401 GEAR_SHIFTER 1 "P" 2 "R" 3 "N" 4 "D" 7 "L" 10 "S"; -VAL_ 419 GEAR_SHIFTER 1 "P" 2 "R" 3 "N" 4 "D" 7 "L" 10 "S"; +VAL_ 401 GEAR_SHIFTER 1 "P" 2 "R" 3 "N" 4 "D" 7 "L" 10 "S" 11 "B"; +VAL_ 419 GEAR_SHIFTER 1 "P" 2 "R" 3 "N" 4 "D" 7 "L" 10 "S" 11 "B"; VAL_ 419 TRANS_TARGET_GEAR 0 "None / Neutral / Park" 1 "1st" 2 "2nd" 3 "3rd" 4 "4th" 5 "5th" 6 "6th" 7 "7th" 8 "8th" 9 "9th" 10 "10th" 13 "Reverse"; VAL_ 419 REGEN_STAGE_SELECTION 0 "disabled" 1 "stage_1" 2 "stage_2" 3 "stage_3" 4 "stage_4" 5 "stage_5" 6 "stage_6"; VAL_ 419 REGEN_MEMORY 0 "disabled" 1 "persistent"; diff --git a/opendbc_repo/opendbc/dbc/honda_odyssey_exl_2018_generated.dbc b/opendbc_repo/opendbc/dbc/honda_odyssey_exl_2018_generated.dbc index 16bcd14f7..25a9c8cee 100644 --- a/opendbc_repo/opendbc/dbc/honda_odyssey_exl_2018_generated.dbc +++ b/opendbc_repo/opendbc/dbc/honda_odyssey_exl_2018_generated.dbc @@ -430,8 +430,8 @@ CM_ SG_ 419 REGEN_STAGE_SELECTION "Driver-selected regenerative braking threshol CM_ SG_ 419 REGEN_MEMORY "Driver-selected persistence setting, M shown in instrument cluster"; CM_ SG_ 419 REGEN_UNKNOWN "Both bits set when user enables regen, otherwise zero"; -VAL_ 401 GEAR_SHIFTER 1 "P" 2 "R" 3 "N" 4 "D" 7 "L" 10 "S"; -VAL_ 419 GEAR_SHIFTER 1 "P" 2 "R" 3 "N" 4 "D" 7 "L" 10 "S"; +VAL_ 401 GEAR_SHIFTER 1 "P" 2 "R" 3 "N" 4 "D" 7 "L" 10 "S" 11 "B"; +VAL_ 419 GEAR_SHIFTER 1 "P" 2 "R" 3 "N" 4 "D" 7 "L" 10 "S" 11 "B"; VAL_ 419 TRANS_TARGET_GEAR 0 "None / Neutral / Park" 1 "1st" 2 "2nd" 3 "3rd" 4 "4th" 5 "5th" 6 "6th" 7 "7th" 8 "8th" 9 "9th" 10 "10th" 13 "Reverse"; VAL_ 419 REGEN_STAGE_SELECTION 0 "disabled" 1 "stage_1" 2 "stage_2" 3 "stage_3" 4 "stage_4" 5 "stage_5" 6 "stage_6"; VAL_ 419 REGEN_MEMORY 0 "disabled" 1 "persistent"; diff --git a/opendbc_repo/opendbc/dbc/honda_odyssey_twn_2018_generated.dbc b/opendbc_repo/opendbc/dbc/honda_odyssey_twn_2018_generated.dbc index a7a4658f7..19e397f0d 100644 --- a/opendbc_repo/opendbc/dbc/honda_odyssey_twn_2018_generated.dbc +++ b/opendbc_repo/opendbc/dbc/honda_odyssey_twn_2018_generated.dbc @@ -431,8 +431,8 @@ CM_ SG_ 419 REGEN_STAGE_SELECTION "Driver-selected regenerative braking threshol CM_ SG_ 419 REGEN_MEMORY "Driver-selected persistence setting, M shown in instrument cluster"; CM_ SG_ 419 REGEN_UNKNOWN "Both bits set when user enables regen, otherwise zero"; -VAL_ 401 GEAR_SHIFTER 1 "P" 2 "R" 3 "N" 4 "D" 7 "L" 10 "S"; -VAL_ 419 GEAR_SHIFTER 1 "P" 2 "R" 3 "N" 4 "D" 7 "L" 10 "S"; +VAL_ 401 GEAR_SHIFTER 1 "P" 2 "R" 3 "N" 4 "D" 7 "L" 10 "S" 11 "B"; +VAL_ 419 GEAR_SHIFTER 1 "P" 2 "R" 3 "N" 4 "D" 7 "L" 10 "S" 11 "B"; VAL_ 419 TRANS_TARGET_GEAR 0 "None / Neutral / Park" 1 "1st" 2 "2nd" 3 "3rd" 4 "4th" 5 "5th" 6 "6th" 7 "7th" 8 "8th" 9 "9th" 10 "10th" 13 "Reverse"; VAL_ 419 REGEN_STAGE_SELECTION 0 "disabled" 1 "stage_1" 2 "stage_2" 3 "stage_3" 4 "stage_4" 5 "stage_5" 6 "stage_6"; VAL_ 419 REGEN_MEMORY 0 "disabled" 1 "persistent"; diff --git a/opendbc_repo/opendbc/safety/modes/honda.h b/opendbc_repo/opendbc/safety/modes/honda.h index 5eaed9b41..443740264 100644 --- a/opendbc_repo/opendbc/safety/modes/honda.h +++ b/opendbc_repo/opendbc/safety/modes/honda.h @@ -44,6 +44,9 @@ static bool honda_fwd_brake = false; static bool honda_bosch_long = false; static bool honda_bosch_radarless = false; static bool honda_bosch_canfd = false; +static bool honda_bosch_canfd_mvl = false; +// Freshness of OP-authored SCM_BUTTONS toward camera on radarless/CANFD. +static int honda_op_buttons_fresh = 0; typedef enum {HONDA_NIDEC, HONDA_BOSCH} HondaHw; static HondaHw honda_hw = HONDA_NIDEC; @@ -126,6 +129,9 @@ static void honda_rx_hook(const CANPacket_t *msg) { // state machine to enter and exit controls for button enabling // 0x1A6 for the ILX, 0x296 for the Civic Touring if (((msg->addr == 0x1A6U) || (msg->addr == 0x296U)) && (msg->bus == pt_bus)) { + if (honda_op_buttons_fresh > 0) { + honda_op_buttons_fresh--; + } int button = (msg->data[0] & 0xE0U) >> 5; // enter controls on the falling edge of set or resume @@ -285,15 +291,28 @@ static bool honda_tx_hook(const CANPacket_t *msg) { // FORCE CANCEL: safety check only relevant when spamming the cancel button in Bosch HW // ensuring that only the cancel button press is sent (VAL 2) when controls are off. // This avoids unintended engagements while still allowing resume spam - if ((msg->addr == 0x296U) && !controls_allowed && (msg->bus == bus_buttons)) { + const bool is_buttons_bus = (msg->bus == bus_buttons) || (honda_bosch_canfd_mvl && (msg->bus == 2U)); + if ((msg->addr == 0x296U) && !controls_allowed && is_buttons_bus) { if (((msg->data[0] >> 5) & 0x7U) != 2U) { tx = false; } } - // Only tester present ("\x02\x3E\x80\x00\x00\x00\x00\x00") allowed on diagnostics address + if (tx && honda_bosch_canfd_mvl && (msg->addr == 0x296U) && (msg->bus == 2U)) { + honda_op_buttons_fresh = 10; + } + + // Normal Honda allows only tester-present to the radar. CAN-FD additionally needs exactly the + // extended-session and disableRxAndTx requests for the deferred handover; re-enable remains blocked + // during normal driving. if (msg->addr == 0x18DAB0F1U) { - if ((GET_BYTES(msg, 0, 4) != 0x00803E02U) || (GET_BYTES(msg, 4, 4) != 0x0U)) { + const uint32_t first_bytes = GET_BYTES(msg, 0, 4); + bool allowed = first_bytes == 0x00803E02U; + if (honda_bosch_canfd_mvl) { + allowed = allowed || (first_bytes == 0x00031002U); + allowed = allowed || (first_bytes == 0x03832803U); + } + if (!allowed || (GET_BYTES(msg, 4, 4) != 0x0U)) { tx = false; } } @@ -329,6 +348,7 @@ static safety_config honda_nidec_init(uint16_t param) { honda_bosch_long = false; honda_bosch_radarless = false; honda_bosch_canfd = false; + honda_bosch_canfd_mvl = false; enable_gas_interceptor = GET_FLAG(param, HONDA_PARAM_GAS_INTERCEPTOR); safety_config ret; @@ -390,15 +410,26 @@ static safety_config honda_bosch_init(uint16_t param) { static CanMsg HONDA_RADARLESS_LONG_TX_MSGS[] = {{0xE4, 0, 5, .check_relay = true}, {0x33D, 0, 8, .check_relay = true}, {0x1C8, 0, 8, .check_relay = true}, {0x30C, 0, 8, .check_relay = true}}; // Bosch radarless w/ gas and brakes + // Keep generic CAN-FD safety unchanged for non-Accord Honda platforms. static CanMsg HONDA_CANFD_TX_MSGS[] = {{0xE4, 0, 5, .check_relay = true}, {0x296, 0, 4, .check_relay = false}, {0x33D, 0, 8, .check_relay = true}}; static CanMsg HONDA_CANFD_LONG_TX_MSGS[] = {{0xE4, 0, 5, .check_relay = true}, {0x1DF, 0, 8, .check_relay = false}, {0x1EF, 0, 8, .check_relay = false}, - {0x30C, 0, 8, .check_relay = false}, {0x33D, 0, 8, .check_relay = true}, {0x18DAB0F1, 0, 8, .check_relay = false}, - {0x39F, 0, 8, .check_relay = false}}; + {0x30C, 0, 8, .check_relay = false}, {0x33D, 0, 8, .check_relay = true}, {0x39F, 0, 8, .check_relay = false}, + {0x18DAB0F1, 0, 8, .check_relay = false}}; + static CanMsg HONDA_CANFD_MVL_TX_MSGS[] = {{0xE4, 0, 5, .check_relay = true}, {0x296, 0, 4, .check_relay = false}, + {0x296, 2, 4, .check_relay = false}, {0x33D, 0, 8, .check_relay = true}}; + static CanMsg HONDA_CANFD_MVL_LONG_TX_MSGS[] = {{0xE4, 0, 5, .check_relay = true}, {0x1DF, 0, 8, .check_relay = true}, {0x1EF, 0, 8, .check_relay = false}, + {0x30C, 0, 8, .check_relay = false}, {0x33D, 0, 8, .check_relay = true}, {0x296, 2, 4, .check_relay = false}, + {0x39F, 0, 8, .check_relay = false}, {0x18DAB0F1, 0, 8, .check_relay = false}, + {0x310, 0, 8, .check_relay = false}, {0x6CD5558, 0, 8, .check_relay = true}, {0x6CD5559, 0, 8, .check_relay = false}, + {0xF31AA52, 0, 8, .check_relay = false}, {0xF31AA5C, 0, 8, .check_relay = true}, {0x1A45AA4E, 0, 8, .check_relay = false}, + {0x310, 2, 8, .check_relay = false}, {0x6CD5558, 2, 8, .check_relay = true}, {0x6CD5559, 2, 8, .check_relay = false}, + {0xF31AA52, 2, 8, .check_relay = false}, {0xF31AA5C, 2, 8, .check_relay = true}, {0x1A45AA4E, 2, 8, .check_relay = false}}; const uint16_t HONDA_PARAM_ALT_BRAKE = 1; const uint16_t HONDA_PARAM_RADARLESS = 8; const uint16_t HONDA_PARAM_BOSCH_CANFD = 16; + const uint16_t HONDA_PARAM_BOSCH_CANFD_MVL = 64; // Bosch radarless has the powertrain bus on bus 0 static RxCheck honda_bosch_pt0_rx_checks[] = { @@ -424,6 +455,8 @@ static safety_config honda_bosch_init(uint16_t param) { honda_brake_switch_prev = false; honda_bosch_radarless = GET_FLAG(param, HONDA_PARAM_RADARLESS); honda_bosch_canfd = GET_FLAG(param, HONDA_PARAM_BOSCH_CANFD); + honda_bosch_canfd_mvl = GET_FLAG(param, HONDA_PARAM_BOSCH_CANFD_MVL); + honda_op_buttons_fresh = 0; // Checking for alternate brake override from safety parameter honda_alt_brake_msg = GET_FLAG(param, HONDA_PARAM_ALT_BRAKE); enable_gas_interceptor = false; @@ -457,9 +490,17 @@ static safety_config honda_bosch_init(uint16_t param) { } } else if (honda_bosch_canfd) { if (honda_bosch_long) { - SET_TX_MSGS(HONDA_CANFD_LONG_TX_MSGS, ret); + if (honda_bosch_canfd_mvl) { + SET_TX_MSGS(HONDA_CANFD_MVL_LONG_TX_MSGS, ret); + } else { + SET_TX_MSGS(HONDA_CANFD_LONG_TX_MSGS, ret); + } } else { - SET_TX_MSGS(HONDA_CANFD_TX_MSGS, ret); + if (honda_bosch_canfd_mvl) { + SET_TX_MSGS(HONDA_CANFD_MVL_TX_MSGS, ret); + } else { + SET_TX_MSGS(HONDA_CANFD_TX_MSGS, ret); + } } } else { if (honda_bosch_long) { @@ -493,10 +534,29 @@ const safety_hooks honda_nidec_hooks = { .compute_checksum = honda_compute_checksum, }; +static bool honda_bosch_fwd_hook(int bus_num, int addr) { + bool block_msg = false; + + // When OP is actively replacing SCM_BUTTONS toward the camera, block the forwarded stock copy. + // Freshness makes this fail-safe: if OP stops transmitting, stock forwarding resumes quickly. + if (honda_bosch_canfd_mvl && controls_allowed && (honda_op_buttons_fresh > 0) && + (bus_num == 0) && (addr == 0x296)) { + block_msg = true; + } + + // Deferred CAN-FD radar UDS responses do not belong on the camera side of the open relay. + if (honda_bosch_canfd_mvl && (bus_num == 0) && (addr == 0x18DAF1B0)) { + block_msg = true; + } + + return block_msg; +} + const safety_hooks honda_bosch_hooks = { .init = honda_bosch_init, .rx = honda_rx_hook, .tx = honda_tx_hook, + .fwd = honda_bosch_fwd_hook, .get_counter = honda_get_counter, .get_checksum = honda_get_checksum, .compute_checksum = honda_compute_checksum, diff --git a/opendbc_repo/opendbc/safety/tests/test_honda.py b/opendbc_repo/opendbc/safety/tests/test_honda.py index bc9897122..2ad793bff 100755 --- a/opendbc_repo/opendbc/safety/tests/test_honda.py +++ b/opendbc_repo/opendbc/safety/tests/test_honda.py @@ -622,7 +622,7 @@ class TestHondaBoschCANFDSafetyBase(TestHondaBoschSafetyBase): STEER_BUS = 0 BUTTONS_BUS = 0 - TX_MSGS = [[0xE4, 0], [0x296, 0], [0x33D, 0]] + TX_MSGS = [[0xE4, 0], [0x296, 0], [0x296, 2], [0x33D, 0]] FWD_BLACKLISTED_ADDRS = {2: [0xE4, 0x33D]} RELAY_MALFUNCTION_ADDRS = {0: (0xE4, 0x33D)} @@ -630,17 +630,73 @@ class TestHondaBoschCANFDSafetyBase(TestHondaBoschSafetyBase): self.packer = CANPackerSafety("honda_common_canfd_generated") self.safety = libsafety_py.libsafety + def test_buttons_fwd(self): + self.safety.set_controls_allowed(True) + self.assertEqual(2, self.safety.safety_fwd_hook(0, 0x296)) + + self.assertTrue(self._tx(self._button_msg(Btn.NONE, bus=2))) + self.assertEqual(-1, self.safety.safety_fwd_hook(0, 0x296)) + + self.safety.set_controls_allowed(False) + self.assertEqual(2, self.safety.safety_fwd_hook(0, 0x296)) + + self.safety.set_controls_allowed(True) + for _ in range(10): + self._rx(self._button_msg(Btn.NONE, main_on=True)) + self.assertEqual(2, self.safety.safety_fwd_hook(0, 0x296)) + + def test_radar_diag_response_fwd(self): + self.safety.set_controls_allowed(False) + self.assertEqual(-1, self.safety.safety_fwd_hook(0, 0x18DAF1B0)) + self.safety.set_controls_allowed(True) + self.assertEqual(-1, self.safety.safety_fwd_hook(0, 0x18DAF1B0)) + + def test_buttons_tx_camera_bus(self): + self.safety.set_controls_allowed(0) + self.assertTrue(self._tx(self._button_msg(Btn.CANCEL, bus=2))) + self.assertFalse(self._tx(self._button_msg(Btn.RESUME, bus=2))) + self.assertFalse(self._tx(self._button_msg(Btn.SET, bus=2))) + self.safety.set_controls_allowed(1) + self.assertTrue(self._tx(self._button_msg(Btn.NONE, bus=2))) + self.assertTrue(self._tx(self._button_msg(Btn.RESUME, bus=2))) + class TestHondaBoschCANFDSafety(HondaPcmEnableBase, TestHondaBoschCANFDSafetyBase): """ Covers the Honda Bosch CANFD safety mode with stock longitudinal """ + def setUp(self): + super().setUp() + self.safety.set_safety_hooks(CarParams.SafetyModel.hondaBosch, HondaSafetyFlags.BOSCH_CANFD | HondaSafetyFlags.BOSCH_CANFD_MVL) + self.safety.init_tests() + + +class TestHondaBoschCANFDGenericSafety(HondaPcmEnableBase, TestHondaBoschCANFDSafetyBase): + """Non-MVL CAN-FD Hondas retain the original narrow TX profile.""" + + TX_MSGS = [[0xE4, 0], [0x296, 0], [0x33D, 0]] + def setUp(self): super().setUp() self.safety.set_safety_hooks(CarParams.SafetyModel.hondaBosch, HondaSafetyFlags.BOSCH_CANFD) self.safety.init_tests() + def test_mvl_messages_are_not_whitelisted(self): + self.safety.set_controls_allowed(True) + self.assertFalse(self._tx(self._button_msg(Btn.NONE, bus=2))) + for addr in (0x310, 0x6CD5558, 0xF31AA52, 0x1A45AA4E): + self.assertFalse(self._tx(libsafety_py.make_CANPacket(addr, 0, bytes(8)))) + + def test_buttons_fwd(self): + pass + + def test_radar_diag_response_fwd(self): + pass + + def test_buttons_tx_camera_bus(self): + pass + class TestHondaBoschCANFDAltBrakeSafety(HondaPcmEnableBase, TestHondaBoschCANFDSafetyBase, TestHondaBoschAltBrakeSafetyBase): """ @@ -649,7 +705,7 @@ class TestHondaBoschCANFDAltBrakeSafety(HondaPcmEnableBase, TestHondaBoschCANFDS def setUp(self): super().setUp() - self.safety.set_safety_hooks(CarParams.SafetyModel.hondaBosch, HondaSafetyFlags.BOSCH_CANFD | HondaSafetyFlags.ALT_BRAKE) + self.safety.set_safety_hooks(CarParams.SafetyModel.hondaBosch, HondaSafetyFlags.BOSCH_CANFD | HondaSafetyFlags.BOSCH_CANFD_MVL | HondaSafetyFlags.ALT_BRAKE) self.safety.init_tests() @@ -662,14 +718,29 @@ class TestHondaBoschCANFDLongSafety(TestHondaBoschLongSafety, TestHondaBoschCANF STEER_BUS = 0 BUTTONS_BUS = 0 - TX_MSGS = [[0xE4, 0], [0x1DF, 0], [0x1EF, 0], [0x30C, 0], [0x33D, 0], [0x39F, 0], [0x18DAB0F1, 0]] - FWD_BLACKLISTED_ADDRS = {2: [0xE4, 0x33D]} - RELAY_MALFUNCTION_ADDRS = {0: (0xE4, 0x33D)} + TX_MSGS = [[0xE4, 0], [0x1DF, 0], [0x1EF, 0], [0x30C, 0], [0x33D, 0], [0x39F, 0], [0x296, 2], [0x18DAB0F1, 0], [0x310, 0], [0x310, 2]] + FWD_BLACKLISTED_ADDRS = {2: [0xE4, 0x1DF, 0x33D]} + RELAY_MALFUNCTION_ADDRS = {0: (0xE4, 0x1DF, 0x33D)} def setUp(self): super().setUp() - self.safety.set_safety_hooks(CarParams.SafetyModel.hondaBosch, HondaSafetyFlags.BOSCH_CANFD | HondaSafetyFlags.BOSCH_LONG) + self.safety.set_safety_hooks(CarParams.SafetyModel.hondaBosch, HondaSafetyFlags.BOSCH_CANFD | HondaSafetyFlags.BOSCH_CANFD_MVL | HondaSafetyFlags.BOSCH_LONG) self.safety.init_tests() + def test_diagnostics(self): + tester_present = libsafety_py.make_CANPacket(0x18DAB0F1, self.PT_BUS, b"\x02\x3E\x80\x00\x00\x00\x00\x00") + self.assertTrue(self._tx(tester_present)) + ext_diag = libsafety_py.make_CANPacket(0x18DAB0F1, self.PT_BUS, b"\x02\x10\x03\x00\x00\x00\x00\x00") + self.assertTrue(self._tx(ext_diag)) + comm_control_disable = libsafety_py.make_CANPacket(0x18DAB0F1, self.PT_BUS, b"\x03\x28\x83\x03\x00\x00\x00\x00") + self.assertTrue(self._tx(comm_control_disable)) + + comm_control_enable = libsafety_py.make_CANPacket(0x18DAB0F1, self.PT_BUS, b"\x03\x28\x80\x03\x00\x00\x00\x00") + self.assertFalse(self._tx(comm_control_enable)) + not_tester_present = libsafety_py.make_CANPacket(0x18DAB0F1, self.PT_BUS, b"\x03\xAA\xAA\x00\x00\x00\x00\x00") + self.assertFalse(self._tx(not_tester_present)) + trailing_bytes = libsafety_py.make_CANPacket(0x18DAB0F1, self.PT_BUS, b"\x02\x10\x03\x00\x00\x00\x00\x01") + self.assertFalse(self._tx(trailing_bytes)) + if __name__ == "__main__": unittest.main() diff --git a/selfdrive/car/car_specific.py b/selfdrive/car/car_specific.py index e48a90fa0..872048d76 100644 --- a/selfdrive/car/car_specific.py +++ b/selfdrive/car/car_specific.py @@ -84,6 +84,10 @@ class CarSpecificEvents: def update(self, CS: car.CarState, CS_prev: car.CarState, CC: car.CarControl): extra_gears = BRAND_EXTRA_GEARS.get(self.CP.brand, None) + # The Accord 11G is the only Honda currently using the B/regen gear in + # StarPilot. Do not change wrong-gear handling for other Honda models. + if self.CP.brand == 'honda' and self.CP.carFingerprint == 'HONDA_ACCORD_11G': + extra_gears = [GearShifter.sport, GearShifter.brake] if self.CP.brand in ('body', 'mock'): events = Events()