IQ.Pilot Release Commit @ 24b1ade
This commit is contained in:
@@ -429,55 +429,38 @@ class CarController(CarControllerBase, AolCarController, GasInterceptorCarContro
|
||||
self.gas = pcm_accel / self.params.NIDEC_GAS_MAX
|
||||
|
||||
# Render OP's lane and lead cars on the dash. On CAN FD these are radar look-alikes that only
|
||||
# exist (and are only allowed by panda safety) when the radar is disabled; in stock ACC the real
|
||||
# radar still owns LANE_PATH/HUD_OBJECTS
|
||||
if ((self.frame % 2 == 0 and self.CP.carFingerprint in HONDA_BOSCH_RADARLESS) or
|
||||
(CS.radar_50hz_tick and self.CP.carFingerprint in HONDA_BOSCH_CANFD and self.CP.openpilotLongitudinalControl
|
||||
and not CS.stock_acc_alive)):
|
||||
# exist (and are only allowed by panda safety) when the radar is disabled. Radarless keeps the
|
||||
# camera as the dash authority (known-good), so OP does not author these there
|
||||
if (CS.radar_50hz_tick and self.CP.carFingerprint in HONDA_BOSCH_CANFD and self.CP.openpilotLongitudinalControl
|
||||
and not CS.stock_acc_alive):
|
||||
leads = dash_objects.leads_from_model(self.model, CS.out.vEgo)
|
||||
lead = leads[0]
|
||||
lead_d = lead.dRel if lead.status else 0.0
|
||||
self.rendered_lane = self.lane_renderer.update(self.model, CS.out.vEgo, lead_d)
|
||||
# the dash freezes the lane display if LANE_PATH and HUD_OBJECTS muxes don't match
|
||||
if self.CP.carFingerprint in HONDA_BOSCH_CANFD:
|
||||
mux = self.radar_mux
|
||||
# no LKAS_HUD_2 on CAN FD: the dash reads the lane length from the in-band terminator, so the
|
||||
# path is reshaped into the terminated-prefix form
|
||||
lane_offsets = dash_lane.canfd_lane_offsets(self.rendered_lane)
|
||||
else:
|
||||
mux = dash_lane.MUX_CYCLE[(self.frame // 2) % len(dash_lane.MUX_CYCLE)]
|
||||
lane_offsets = self.rendered_lane.offsets
|
||||
mux = self.radar_mux
|
||||
# no LKAS_HUD_2 on CAN FD: the dash reads the lane length from the in-band terminator, so the
|
||||
# path is reshaped into the terminated-prefix form
|
||||
lane_offsets = dash_lane.canfd_lane_offsets(self.rendered_lane)
|
||||
lane_msg = dash_lane.create_lane_path(self.packer, self.CAN.lkas, lane_offsets, mux)
|
||||
can_sends.append(lane_msg)
|
||||
|
||||
# CAN FD cars have no camera HUD_OBJECTS to poll (the disabled radar owned it): author OP's
|
||||
# lead in slot 0 with the other slots blank (tracks=None)
|
||||
tracks = CS.camera_object_tracker.snapshot() if CS.camera_object_tracker is not None else None
|
||||
if self.CP.openpilotLongitudinalControl:
|
||||
hud_msg = self.dash_object_author.create(self.packer, self.CAN.lkas, lead, tracks, mux, now_nanos * 1e-9,
|
||||
extra_leads=leads[1:])
|
||||
else:
|
||||
# for stock ACC, forward the camera's objects but with our mux
|
||||
hud_msg = dash_objects.forward_hud_object(self.packer, self.CAN.lkas, mux, tracks)
|
||||
hud_msg = self.dash_object_author.create(self.packer, self.CAN.lkas, lead, tracks, mux, now_nanos * 1e-9,
|
||||
extra_leads=leads[1:])
|
||||
can_sends.append(hud_msg)
|
||||
|
||||
# on CAN FD the camera (behind the relay) also consumes these; mirror the identical packed
|
||||
# bytes onto the camera bus (packed once, so the counter/checksum stay in lockstep)
|
||||
if self.CP.carFingerprint in HONDA_BOSCH_CANFD:
|
||||
for addr, dat, _ in (lane_msg, hud_msg):
|
||||
can_sends.append((addr, dat, self.CAN.camera))
|
||||
# the camera (behind the relay) also consumes these; mirror the identical packed bytes onto the
|
||||
# camera bus (packed once, so the counter/checksum stay in lockstep)
|
||||
for addr, dat, _ in (lane_msg, hud_msg):
|
||||
can_sends.append((addr, dat, self.CAN.camera))
|
||||
|
||||
if self.frame % 20 == 0 and self.CP.carFingerprint in HONDA_BOSCH_RADARLESS:
|
||||
# COUNTER_2 trails the packer's COUNTER (frame//20 % 4) by one
|
||||
rl = self.rendered_lane
|
||||
can_sends.append(dash_lane.create_lkas_hud_2(self.packer, self.CAN.lkas, (self.frame // 20 - 1) % 4,
|
||||
rl.reach, rl.lane_cross, rl.left_line, rl.right_line))
|
||||
|
||||
# Radarless + CAN FD: when stock LKAS is active, the touch-steering-wheel nag eventually forces an
|
||||
# ACC disengagement (on CAN FD it shows up as a brake tap from the VSA). Disable LKAS automatically
|
||||
# and block the driver's LKAS button by taking over SCM_BUTTONS on the camera bus while engaged
|
||||
# (panda blocks the forwarded stock SCM_BUTTONS while this stream flows)
|
||||
if self.CP.carFingerprint in (HONDA_BOSCH_RADARLESS | HONDA_BOSCH_CANFD) and CC.enabled and self.frame % 4 == 0 and \
|
||||
# CAN FD: when stock LKAS is active, the touch-steering-wheel nag eventually forces an ACC
|
||||
# disengagement (a brake tap from the VSA). Disable LKAS automatically and block the driver's LKAS
|
||||
# button by taking over SCM_BUTTONS on the camera bus while engaged (panda blocks the forwarded
|
||||
# stock SCM_BUTTONS while this stream flows). Radarless keeps the stock camera LKAS untouched
|
||||
if self.CP.carFingerprint in HONDA_BOSCH_CANFD 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
|
||||
|
||||
@@ -197,18 +197,19 @@ def create_lkas_hud(packer, bus, CP, hud_control, lat_active, steering_available
|
||||
|
||||
if CP.carFingerprint in (HONDA_BOSCH_RADARLESS | HONDA_BOSCH_CANFD):
|
||||
lkas_hud_values['LANE_LINES'] = 3
|
||||
lkas_hud_values['LKAS_PROBLEM'] = steer_fault_permanent
|
||||
lkas_hud_values['DASHED_LANES'] = lat_active
|
||||
|
||||
# car likely needs to see LKAS_PROBLEM fall within a specific time frame, so forward from camera
|
||||
if CP.carFingerprint in HONDA_BOSCH_RADARLESS:
|
||||
# gray lanes when disengaged
|
||||
lkas_hud_values['DASHED_LANES'] = 1
|
||||
else:
|
||||
lkas_hud_values['LKAS_PROBLEM'] = lkas_hud['LKAS_PROBLEM']
|
||||
|
||||
if CP.carFingerprint in HONDA_BOSCH_CANFD:
|
||||
lkas_hud_values['LKAS_PROBLEM'] = steer_fault_permanent
|
||||
# CAN FD: dashed lanes are the AOL armed indication (dashed_lanes is aol.enabled and not
|
||||
# latActive, which is not standstill-gated - so parked LKAS button presses produce cluster
|
||||
# feedback). ORed with lat_active so the engaged payload keeps SOLID and DASHED set together,
|
||||
# byte-matching the stock camera's lanes-on state
|
||||
lkas_hud_values['DASHED_LANES'] = dashed_lanes or lat_active
|
||||
|
||||
if CP.carFingerprint in HONDA_BOSCH_CANFD:
|
||||
# every payload change must coincide with an LKAS_STATE_CHANGE pulse (see carcontroller); keyed
|
||||
# on lat_active, not lanesVisible, so the dash LKAS indication follows AOL's lateral state
|
||||
lkas_hud_values['SOLID_LANES'] = lat_active
|
||||
|
||||
@@ -323,9 +323,9 @@ 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
|
||||
// On CAN FD and radarless, buttons are also sent to the camera (bus 2) to take over SCM_BUTTONS
|
||||
// while engaged, so the same check applies there
|
||||
const bool is_buttons_bus = (msg->bus == bus_buttons) || ((honda_bosch_canfd || honda_bosch_radarless) && (msg->bus == 2U));
|
||||
// On CAN FD, buttons are also sent to the camera (bus 2) to take over SCM_BUTTONS while engaged, so
|
||||
// the same check applies there (radarless already sends buttons on bus 2 via bus_buttons)
|
||||
const bool is_buttons_bus = (msg->bus == bus_buttons) || (honda_bosch_canfd && (msg->bus == 2U));
|
||||
if ((msg->addr == 0x296U) && !controls_allowed && is_buttons_bus) {
|
||||
if (((msg->data[0] >> 5) & 0x7U) != 2U) {
|
||||
tx = false;
|
||||
@@ -454,13 +454,10 @@ static safety_config honda_bosch_init(uint16_t param) {
|
||||
{0x33DA, 1, 5, .check_relay = true}, {0x33DB, 1, 8, .check_relay = true}, {0x39F, 1, 8, .check_relay = false},
|
||||
{0x18DAB0F1, 1, 8, .check_relay = false}}; // Bosch w/ gas and brakes
|
||||
|
||||
static CanMsg HONDA_RADARLESS_TX_MSGS[] = {{0xE4, 0, 5, .check_relay = true}, {0x296, 2, 4, .check_relay = false}, {0x33D, 0, 8, .check_relay = true},
|
||||
{0x6CD5554, 0, 8, .check_relay = true}, {0xF31AA54, 0, 8, .check_relay = true},
|
||||
{0x6CD5557, 0, 8, .check_relay = true}}; // Bosch radarless (LANE_PATH/LKAS_HUD_2/HUD_OBJECTS authored in stock ACC too)
|
||||
static CanMsg HONDA_RADARLESS_TX_MSGS[] = {{0xE4, 0, 5, .check_relay = true}, {0x296, 2, 4, .check_relay = false}, {0x33D, 0, 8, .check_relay = true}}; // Bosch radarless
|
||||
|
||||
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}, {0x296, 2, 4, .check_relay = false}, {0x6CD5554, 0, 8, .check_relay = true},
|
||||
{0xF31AA54, 0, 8, .check_relay = true}, {0x6CD5557, 0, 8, .check_relay = true}}; // Bosch radarless w/ gas and brakes
|
||||
{0x30C, 0, 8, .check_relay = true}}; // Bosch radarless w/ gas and brakes
|
||||
|
||||
// 0x296 on bus 2: OP takes over SCM_BUTTONS towards the camera to auto-disable stock LKAS and to block
|
||||
// the driver's LKAS button while engaged (the physical SCM_BUTTONS is blocked from forwarding, see fwd hook)
|
||||
@@ -585,7 +582,7 @@ static bool honda_bosch_fwd_hook(int bus_num, int addr) {
|
||||
// actually flowing (honda_op_buttons_fresh): the camera needs SCM_BUTTONS content beyond the buttons
|
||||
// (it raises an adaptive high beam error when the message goes missing), so a bare controls_allowed
|
||||
// gate would starve it whenever the panda allows controls but OP refuses to engage
|
||||
if ((honda_bosch_radarless || honda_bosch_canfd) && controls_allowed && (honda_op_buttons_fresh > 0) &&
|
||||
if (honda_bosch_canfd && controls_allowed && (honda_op_buttons_fresh > 0) &&
|
||||
(bus_num == 0) && (addr == 0x296)) {
|
||||
block_msg = true;
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
#define TOYOTA_COMMON_RX_CHECKS(lta) \
|
||||
{.msg = {{ 0xaa, 0, 8, 83U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, \
|
||||
{.msg = {{0x260, 0, 8, 50U, .ignore_counter = true, .ignore_quality_flag=!(lta)}, { 0 }, { 0 }}}, \
|
||||
{.msg = {{0x412, 2, 8, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true, .frequency = 1U}, { 0 }, { 0 }}}, \
|
||||
|
||||
#define TOYOTA_RX_CHECKS(lta) \
|
||||
TOYOTA_COMMON_RX_CHECKS(lta) \
|
||||
@@ -98,6 +99,15 @@ static int TOYOTA_GET_INTERCEPTOR(const CANPacket_t *msg) {
|
||||
}
|
||||
|
||||
static void toyota_rx_hook(const CANPacket_t *msg) {
|
||||
if (msg->bus == 2U) {
|
||||
// TSS2 LKAS/LDA button is only observable via the camera's LKAS_HUD; it reads 1 or 2 while
|
||||
// pressed and rests at 0, and without this edge AOL can never be granted lateral on Toyota.
|
||||
if (msg->addr == 0x412U) {
|
||||
unsigned int lda_on_message = (msg->data[3] >> 6U) & 0x3U;
|
||||
aol_button_press = (lda_on_message != 0U) ? AOL_BUTTON_PRESSED : AOL_BUTTON_NOT_PRESSED;
|
||||
}
|
||||
}
|
||||
|
||||
if (msg->bus == 0U) {
|
||||
|
||||
// get eps motor torque (0.66 factor in dbc)
|
||||
|
||||
@@ -609,41 +609,14 @@ class TestHondaBoschRadarlessSafetyBase(TestHondaBoschSafetyBase):
|
||||
STEER_BUS = 0
|
||||
BUTTONS_BUS = 2 # camera controls ACC, need to send buttons on bus 2
|
||||
|
||||
TX_MSGS = [[0xE4, 0], [0x296, 2], [0x33D, 0], [0x6CD5554, 0], [0xF31AA54, 0], [0x6CD5557, 0]]
|
||||
FWD_BLACKLISTED_ADDRS = {2: [0xE4, 0x33D, 0x6CD5554, 0xF31AA54, 0x6CD5557]}
|
||||
# STEERING_CONTROL, LANE_PATH, LKAS_HUD_2, HUD_OBJECTS
|
||||
RELAY_MALFUNCTION_ADDRS = {0: (0xE4, 0x33D, 0x6CD5554, 0xF31AA54, 0x6CD5557)}
|
||||
TX_MSGS = [[0xE4, 0], [0x296, 2], [0x33D, 0]]
|
||||
FWD_BLACKLISTED_ADDRS = {2: [0xE4, 0x33D]}
|
||||
RELAY_MALFUNCTION_ADDRS = {0: (0xE4, 0x33D)} # STEERING_CONTROL
|
||||
|
||||
def setUp(self):
|
||||
self.packer = CANPackerSafety("honda_bosch_radarless_generated")
|
||||
self.safety = libsafety_py.libsafety
|
||||
|
||||
def test_buttons_fwd(self):
|
||||
# SCM_BUTTONS (0x296) forwards to the camera unless OP's replacement button stream is flowing
|
||||
# (engaged + a recent OP SCM_BUTTONS tx on the camera bus). The camera needs the message content
|
||||
# beyond the buttons, so the block fails safe back to forwarding when OP stops sending
|
||||
self.safety.set_controls_allowed(False)
|
||||
self.assertEqual(2, self.safety.safety_fwd_hook(0, 0x296))
|
||||
|
||||
# engaged but OP not sending buttons: keep forwarding
|
||||
self.safety.set_controls_allowed(True)
|
||||
self.assertEqual(2, self.safety.safety_fwd_hook(0, 0x296))
|
||||
|
||||
# OP button stream flowing: block the stock buttons
|
||||
self.assertTrue(self._tx(self._button_msg(Btn.NONE, bus=2)))
|
||||
self.assertEqual(-1, self.safety.safety_fwd_hook(0, 0x296))
|
||||
|
||||
# never blocked while disengaged
|
||||
self.safety.set_controls_allowed(False)
|
||||
self.assertEqual(2, self.safety.safety_fwd_hook(0, 0x296))
|
||||
self.safety.set_controls_allowed(True)
|
||||
self.assertEqual(-1, self.safety.safety_fwd_hook(0, 0x296))
|
||||
|
||||
# freshness decays after 10 stock button frames without an OP tx
|
||||
for _ in range(10):
|
||||
self._rx(self._button_msg(Btn.NONE, main_on=True))
|
||||
self.assertEqual(2, self.safety.safety_fwd_hook(0, 0x296))
|
||||
|
||||
|
||||
class TestHondaBoschRadarlessSafety(HondaPcmEnableBase, TestHondaBoschRadarlessSafetyBase):
|
||||
"""
|
||||
@@ -672,9 +645,9 @@ class TestHondaBoschRadarlessLongSafety(common.LongitudinalAccelSafetyTest, Hond
|
||||
"""
|
||||
Covers the Honda Bosch Radarless safety mode with longitudinal control
|
||||
"""
|
||||
TX_MSGS = [[0xE4, 0], [0x33D, 0], [0x1C8, 0], [0x30C, 0], [0x296, 2], [0x6CD5554, 0], [0xF31AA54, 0], [0x6CD5557, 0]]
|
||||
FWD_BLACKLISTED_ADDRS = {2: [0xE4, 0x33D, 0x1C8, 0x30C, 0x6CD5554, 0xF31AA54, 0x6CD5557]}
|
||||
RELAY_MALFUNCTION_ADDRS = {0: (0xE4, 0x1C8, 0x30C, 0x33D, 0x6CD5554, 0xF31AA54, 0x6CD5557)}
|
||||
TX_MSGS = [[0xE4, 0], [0x33D, 0], [0x1C8, 0], [0x30C, 0]]
|
||||
FWD_BLACKLISTED_ADDRS = {2: [0xE4, 0x33D, 0x1C8, 0x30C]}
|
||||
RELAY_MALFUNCTION_ADDRS = {0: (0xE4, 0x1C8, 0x30C, 0x33D)}
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
|
||||
@@ -91,6 +91,35 @@ class TestToyotaSafetyBase(common.CarSafetyTest, common.LongitudinalAccelSafetyT
|
||||
values = {"MAIN_ON": enabled}
|
||||
return self.packer.make_can_msg_safety(msg, 0, values)
|
||||
|
||||
def _lkas_button_msg(self, lkas_button=False, lda_value=None):
|
||||
values = {"LDA_ON_MESSAGE": (1 if lkas_button else 0) if lda_value is None else lda_value}
|
||||
return self.packer.make_can_msg_safety("LKAS_HUD", 2, values)
|
||||
|
||||
def test_enable_control_allowed_with_aol_button(self):
|
||||
for enable_aol in (True, False):
|
||||
with self.subTest("enable_aol", aol_enabled=enable_aol):
|
||||
self.safety.set_aol_params(enable_aol, False, False)
|
||||
|
||||
self._rx(self._lkas_button_msg(False))
|
||||
self.assertEqual(0, self.safety.get_aol_button_press())
|
||||
self.assertFalse(self.safety.get_controls_allowed_lat())
|
||||
|
||||
self._rx(self._lkas_button_msg(True))
|
||||
self.assertEqual(1, self.safety.get_aol_button_press())
|
||||
self.assertEqual(enable_aol, self.safety.get_controls_allowed_lat())
|
||||
|
||||
self._rx(self._lkas_button_msg(False))
|
||||
self.assertEqual(0, self.safety.get_aol_button_press())
|
||||
self.assertEqual(enable_aol, self.safety.get_controls_allowed_lat())
|
||||
|
||||
self.safety.set_controls_allowed_lat(False)
|
||||
self._rx(self._lkas_button_msg(False, lda_value=2))
|
||||
self.assertEqual(1, self.safety.get_aol_button_press())
|
||||
self.assertEqual(enable_aol, self.safety.get_controls_allowed_lat())
|
||||
self._rx(self._lkas_button_msg(False))
|
||||
self.safety.set_controls_allowed_lat(False)
|
||||
self.safety.set_aol_params(False, False, False)
|
||||
|
||||
def test_diagnostics(self, stock_longitudinal: bool = False, ecu_disabled: bool = True):
|
||||
for should_tx, msg in ((False, b"\x6D\x02\x3E\x00\x00\x00\x00\x00"), # fwdCamera tester present
|
||||
(False, b"\x0F\x03\xAA\xAA\x00\x00\x00\x00"), # non-tester present
|
||||
|
||||
Reference in New Issue
Block a user