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
This commit is contained in:
j3dok3do
2026-08-25 16:45:58 -05:00
committed by firestar5683
parent 68cef2d360
commit 1a3b243233
27 changed files with 695 additions and 75 deletions
@@ -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
+126 -15
View File
@@ -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)
+95 -2
View File
@@ -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
@@ -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: {
+112 -11
View File
@@ -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
+16 -3
View File
@@ -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,
@@ -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()
+6 -2
View File
@@ -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(
[
@@ -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";
@@ -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";
@@ -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";
@@ -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
@@ -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";
@@ -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";
@@ -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";
@@ -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";
@@ -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";
@@ -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";
@@ -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";
@@ -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";
@@ -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";
@@ -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";
@@ -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";
@@ -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";
+67 -7
View File
@@ -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,
@@ -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()
+4
View File
@@ -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()