Support shared Toyota pedal and brake hold paths

This commit is contained in:
firestar5683
2026-10-23 21:26:01 -05:00
parent d8a218b807
commit b6b820a275
28 changed files with 785 additions and 92 deletions
@@ -66,8 +66,13 @@ static bool ford_bp_configure(uint16_t param) {
static bool ford_bp_health(uint32_t now);
static bool ford_bp_permission(void) {
return ford_aol_enabled ? ((ford_aol_permission_mask() & 1U) != 0U) :
(lateral_controls_allowed() && controls_allowed && !brake_pressed && !gas_pressed);
bool permitted = false;
if (ford_aol_enabled) {
permitted = (ford_aol_permission_mask() & 1U) != 0U;
} else {
permitted = lateral_controls_allowed() && controls_allowed && !brake_pressed && !gas_pressed;
}
return permitted;
}
static void ford_bp_rx(const CANPacket_t *msg) {
@@ -57,6 +57,8 @@ def apply(cp, *, camera_twoaa=False):
def configured(cp):
from opendbc.car.toyota.pedal_composite import parent_cp
cp = parent_cp(cp)
from opendbc.car.toyota import camera_2aa_filter
if camera_2aa_filter.configured(cp):
return True
@@ -94,6 +96,9 @@ def enabled(cp):
def prepare_stock(cp):
from opendbc.car.toyota import pedal_composite
if pedal_composite.marked(cp):
return pedal_composite.prepare_stock(cp)
from opendbc.car.toyota import camera_2aa_filter
if camera_2aa_filter.configured(cp):
return camera_2aa_filter.prepare_stock(cp)
@@ -54,6 +54,8 @@ def apply(cp):
def configured(cp):
from opendbc.car.toyota.pedal_composite import parent_cp
cp = parent_cp(cp)
try:
if (cp is None or cp.brand != 'toyota' or cp.carFingerprint not in CARS or cp.notCar or cp.passive or cp.dashcamOnly or
cp.secOcRequired or not cp.pcmCruise or len(cp.safetyConfigs) != 1 or
@@ -74,6 +76,9 @@ def enabled(cp):
def prepare_stock(cp):
from opendbc.car.toyota import pedal_composite
if pedal_composite.marked(cp):
return pedal_composite.prepare_stock(cp)
if not configured(cp):
return False
cp.openpilotLongitudinalControl = False
@@ -74,7 +74,7 @@ class CarController(CarControllerBase):
self.door_locks = DoorLocks()
self.reverse_cruise_input = None
self.prius_filter_input = None
self.original_prius_sdsu = prius_sdsu.configured(CP)
self.original_prius_sdsu = prius_sdsu.configured(CP) or prius_longitudinal.eps73_status_configured(CP)
self.original_prius_filter = self.original_prius_sdsu or prius_advert_filter.configured(CP)
self.pedal_input = None
self.rav4h_filter_input = None
@@ -177,6 +177,20 @@ class CarController(CarControllerBase):
if guarded_advert:
filter_allowed = filter_allowed and legacy_advert_source_ready
pedal_owner = pedal.configured(self.CP)
hold_source_ready = filter_allowed and bool(
CS.out.canValid and not CS.out.canTimeout and CS.out.cruiseState.available and not CS.out.accFaulted and
not CS.out.stockAeb and not CS.out.steerFaultTemporary and not CS.out.steerFaultPermanent and not CS.out.doorOpen and
not CS.out.seatbeltUnlatched and CS.out.gearShifter in (structs.CarState.GearShifter.drive, structs.CarState.GearShifter.sport))
if pedal_owner:
hold_source_ready = hold_source_ready and bool(self.pedal_input is not None and self.pedal_input.update(now_nanos) and CS.pedal_ready)
if bypass_long:
hold_source_ready = hold_source_ready and bool(self.bypass_input is not None and self.bypass_input.update(now_nanos))
if pedal_composite.configured(self.CP):
filter_allowed = filter_allowed and bool(
CS.out.canValid and not CS.out.canTimeout and CS.out.cruiseState.available and not CS.out.accFaulted and not CS.out.stockAeb and
not CS.out.steerFaultTemporary and not CS.out.steerFaultPermanent and not CS.out.doorOpen and not CS.out.seatbeltUnlatched and
not CS.out.gasPressed and not CS.out.brakePressed and
CS.out.gearShifter in (structs.CarState.GearShifter.drive, structs.CarState.GearShifter.sport))
if pedal_owner:
filter_allowed = filter_allowed and bool(self.pedal_input is not None and self.pedal_input.update(now_nanos) and CS.pedal_ready)
if bypass_long:
@@ -304,7 +318,7 @@ class CarController(CarControllerBase):
lead = hud_control.leadVisible or CS.out.vEgo < 12. # at low speed we always assume the lead is present so ACC can be engaged
# *** gas and brake ***
if supports_toyota_auto_hold(self.CP) and CS.out.canValid and not CS.out.canTimeout and (not rav4h_long or filter_allowed):
if supports_toyota_auto_hold(self.CP) and CS.out.canValid and not CS.out.canTimeout and hold_source_ready:
self.update_auto_hold_state(CS, pcm_cancel_cmd if not uses_toyota_auto_hold_aeb(self.CP) else False)
if (uses_toyota_auto_hold_aeb(self.CP) and self.frame % 2 == 0 and
CS.out.standstill and CS.out.cruiseState.available and not CS.out.gasPressed):
@@ -432,7 +446,8 @@ class CarController(CarControllerBase):
self.permit_braking = True
self.standstill_req = True
if (bypass_long or rav4h_long or pedal_owner or advert_long or original_prius_long) and not long_active:
if ((bypass_long or rav4h_long or pedal_owner or advert_long or original_prius_long) and not long_active and
not (self.brake_hold_active and not uses_toyota_auto_hold_aeb(self.CP))):
pcm_accel_cmd = 0.
main_accel_cmd = 0. if self.CP.flags & ToyotaFlags.SECOC.value else pcm_accel_cmd
can_sends.append(toyotacan.create_accel_command(self.packer, main_accel_cmd, pcm_cancel_cmd, self.permit_braking, self.standstill_req, lead,
+10 -6
View File
@@ -2,7 +2,9 @@ import copy
import math
from opendbc.can import CANDefine, CANParser
from opendbc.car.toyota import dsu_bypass, pedal_composite, pedal, legacy_sdsu, advert_filter, legacy_advert_filter, prius_sdsu, prius_advert_filter
from opendbc.car.toyota import (
prius_longitudinal, dsu_bypass, pedal_composite, pedal, legacy_sdsu, advert_filter, legacy_advert_filter, prius_sdsu, prius_advert_filter
)
from opendbc.car.toyota.lexus_is import LexusIsCANParser
from opendbc.car import Bus, DT_CTRL, create_button_events, structs
from opendbc.car.common.conversions import Conversions as CV
@@ -291,7 +293,7 @@ class CarState(CarStateBase):
elif abs(ret.steeringAngleDeg - (zorro - self.zss_offset)) < 4.0:
ret.steeringAngleDeg = zorro - self.zss_offset
original_prius_sdsu = prius_sdsu.configured(self.CP)
original_prius_sdsu = prius_sdsu.configured(self.CP) or prius_longitudinal.eps73_status_configured(self.CP)
if rav4h_filter_configured(self.CP) or original_prius_sdsu:
self.sdsu_state = int(cp.vl["SDSU"]["STATE"])
source_ns, valid_until_ns = parser_expiry(cp, "SDSU", "STATE")
@@ -327,7 +329,8 @@ class CarState(CarStateBase):
def get_can_parsers(CP):
if pedal_composite.configured(CP):
parent = CarState.get_can_parsers(pedal_composite.parent_cp(CP))
parent[Bus.pt] = pedal_composite.ParentPedalParser(parent[Bus.pt])
for bus in parent:
parent[bus] = pedal_composite.ParentPedalParser(parent[bus])
parent[Bus.alt] = pedal.PedalCANParser(DBC[CP.carFingerprint][Bus.pt], [('GAS_SENSOR', 50)], 0)
return parent
if dsu_bypass.configured(CP):
@@ -356,9 +359,10 @@ class CarState(CarStateBase):
if CP.carFingerprint == CAR.LEXUS_IS or alternate_sdsu_main:
pt_messages.append(("DSU_CRUISE", 10))
if (advert_filter.configured(CP) and not alternate_sdsu_main) or prius_sdsu.configured(CP) or prius_advert_filter.configured(CP):
if ((advert_filter.configured(CP) and not alternate_sdsu_main) or prius_sdsu.configured(CP) or
prius_longitudinal.eps73_status_configured(CP) or prius_advert_filter.configured(CP)):
pt_messages.append(("PCM_CRUISE_2", 10))
if prius_sdsu.configured(CP) or prius_advert_filter.configured(CP):
if prius_sdsu.configured(CP) or prius_longitudinal.eps73_status_configured(CP) or prius_advert_filter.configured(CP):
pt_messages.append(("EPS_STATUS", 25))
if CP.flags & ToyotaFlags.LONG_FILTER and not prius_advert_filter.configured(CP):
pt_messages.append(("SDSU", 50))
@@ -368,7 +372,7 @@ class CarState(CarStateBase):
if pedal.configured(CP):
pt_messages.append(("GAS_SENSOR", 50))
pt_parser = (prius_advert_filter.PriusAdvertCANParser if prius_advert_filter.configured(CP) else
prius_sdsu.PriusSDSUCANParser if prius_sdsu.configured(CP) else
prius_sdsu.PriusSDSUCANParser if prius_sdsu.configured(CP) or prius_longitudinal.eps73_status_configured(CP) else
camera_2aa_filter.CameraTwoAACANParser if camera_twoaa else
legacy_advert_filter.LegacyAdvertCANParser if legacy_advert else
legacy_sdsu.AlternateMainSDSUCANParser if alternate_sdsu_main else
@@ -79,6 +79,8 @@ def apply(cp):
def configured(cp):
from opendbc.car.toyota.pedal_composite import parent_cp
cp = parent_cp(cp)
if (
cp is None
or cp.brand != 'toyota'
@@ -110,6 +112,9 @@ def enabled(cp):
def prepare_stock(cp):
from opendbc.car.toyota import pedal_composite
if pedal_composite.marked(cp):
return pedal_composite.prepare_stock(cp)
if not configured(cp):
return False
cp.openpilotLongitudinalControl = False
@@ -71,6 +71,8 @@ def apply(cp, alpha_long):
def configured(cp):
from opendbc.car.toyota.pedal_composite import parent_cp
cp = parent_cp(cp)
if (
cp is None
or cp.brand != "toyota"
@@ -101,6 +103,9 @@ def configured(cp):
def prepare_stock(cp):
from opendbc.car.toyota import pedal_composite
if pedal_composite.marked(cp):
return pedal_composite.prepare_stock(cp)
if not configured(cp):
return False
cp.openpilotLongitudinalControl = False
+12 -10
View File
@@ -12,15 +12,17 @@ SteerControlType = structs.CarParams.SteerControlType
def toyota_auto_hold_supported(CP) -> bool:
from opendbc.car.toyota.rav4h_filter import enabled as rav4h_filter_enabled
if CP.carFingerprint == CAR.TOYOTA_RAV4H and rav4h_filter_enabled(CP):
return True
return bool(CP.brand == "toyota" and CP.carFingerprint in TOYOTA_AUTO_HOLD_CARS and
CP.openpilotLongitudinalControl and not CP.flags & ToyotaFlags.SECOC and
not CP.notCar and not CP.dashcamOnly and not CP.passive and len(CP.safetyConfigs) == 1 and
CP.safetyConfigs[0].safetyModel == structs.CarParams.SafetyModel.toyota and
(CP.safetyConfigs[0].safetyParam & 0xFF) == EPS_SCALE[CP.carFingerprint] and
not CP.safetyConfigs[0].safetyParam & ~(0xFF | int(ToyotaSafetyFlags.ALT_BRAKE) | int(ToyotaSafetyFlags.LTA)))
from opendbc.car.toyota import pedal, pedal_composite
if not (CP.brand == "toyota" and CP.carFingerprint in TOYOTA_AUTO_HOLD_CARS and
CP.openpilotLongitudinalControl and not CP.flags & ToyotaFlags.SECOC and
not CP.notCar and not CP.dashcamOnly and not CP.passive and len(CP.safetyConfigs) == 1 and
CP.safetyConfigs[0].safetyModel == structs.CarParams.SafetyModel.toyota):
return False
parent = pedal_composite.parent_cp(CP)
return (any(module.configured(parent) for module in pedal_composite.parent_modules()) or
pedal.configured(CP) or
((parent.safetyConfigs[0].safetyParam & 0xFF) == EPS_SCALE[parent.carFingerprint] and
not parent.safetyConfigs[0].safetyParam & ~(0xFF | int(ToyotaSafetyFlags.ALT_BRAKE) | int(ToyotaSafetyFlags.LTA))))
def apply_toyota_auto_hold(CP, enabled: bool) -> bool:
@@ -184,7 +186,7 @@ class CarInterface(CarInterfaceBase):
if smart_dsu:
ret.flags |= int(ToyotaFlags.HYBRID | ToyotaFlags.LONG_FILTER)
ret.safetyConfigs[0].safetyParam = 4169
ret.safetyConfigs[0].safetyParam = 0x8049 # EPS73 status uses the existing EPS8 smartDSU receiver.
ret.openpilotLongitudinalControl = True
from opendbc.car.toyota import legacy_advert_filter
legacy_advert = legacy_advert_filter.hardware_supported(candidate, fingerprint, car_fw)
@@ -47,6 +47,8 @@ def apply(cp):
def configured(cp):
from opendbc.car.toyota.pedal_composite import parent_cp
cp = parent_cp(cp)
if cp is not None and cp.carFingerprint == CAR.TOYOTA_MATRIX_RETROFIT:
from opendbc.car.toyota import matrix_filter
return matrix_filter.configured(cp, length=4)
@@ -70,6 +72,9 @@ def enabled(cp):
def prepare_stock(cp):
from opendbc.car.toyota import pedal_composite
if pedal_composite.marked(cp):
return pedal_composite.prepare_stock(cp)
if not configured(cp):
return False
cp.openpilotLongitudinalControl = False
@@ -58,6 +58,8 @@ def apply(cp):
def configured(cp):
from opendbc.car.toyota.pedal_composite import parent_cp
cp = parent_cp(cp)
if cp is not None and cp.carFingerprint == CAR.TOYOTA_MATRIX_RETROFIT:
from opendbc.car.toyota import matrix_filter
return matrix_filter.configured(cp, length=8)
@@ -82,6 +84,9 @@ def configured(cp):
def prepare_stock(cp):
from opendbc.car.toyota import pedal_composite
if pedal_composite.marked(cp):
return pedal_composite.prepare_stock(cp)
if not configured(cp):
return False
cp.openpilotLongitudinalControl = False
+2
View File
@@ -58,6 +58,8 @@ def hardware_supported(candidate, fingerprint, car_fw):
def configured(cp):
from opendbc.car.toyota.pedal_composite import hold_base_cp
cp = hold_base_cp(cp)
from opendbc.car.toyota import pedal_composite
if pedal_composite.configured(cp):
return True
@@ -7,14 +7,70 @@ A valid pedal source supplements that parent; it cannot replace it.
from opendbc.car import structs
from opendbc.car.toyota.values import CAR, ToyotaFlags
PARENT_WORDS = {0xB049: 0x9049, 0xB249: 0x9249}
PARENT_WORDS = {
0x3049: 0x1049,
0x3249: 0x1249,
0x3449: 0x1449,
0x3649: 0x1649,
0xA042: 0x8042,
0xA049: 0x8049,
0xA242: 0x8242,
0xA249: 0x8249,
0xA449: 0x8449,
0xA649: 0x8649,
0xA849: 0x8849,
0xA949: 0x8949,
0xA958: 0x8958,
0xA964: 0x8964,
0xAA49: 0x8A49,
0xAB49: 0x8B49,
0xAB58: 0x8B58,
0xAB64: 0x8B64,
0xB049: 0x9049,
0xB149: 0x9149,
0xB158: 0x9158,
0xB164: 0x9164,
0xB249: 0x9249,
0xB349: 0x9349,
0xB358: 0x9358,
0xB364: 0x9364,
0xB449: 0x9449,
0xB549: 0x9549,
0xB558: 0x9558,
0xB564: 0x9564,
0xB649: 0x9649,
0xB749: 0x9749,
0xB758: 0x9758,
0xB764: 0x9764,
0xB842: 0x9842,
0xB849: 0x9849,
0xBA42: 0x9A42,
0xBA49: 0x9A49,
0xE042: 0xC042,
0xE049: 0xC049,
0xE242: 0xC242,
0xE249: 0xC249,
0xE84D: 0xC84D,
0xE949: 0xC949,
0xEA4D: 0xCA4D,
0xEB49: 0xCB49,
0xF049: 0xD049,
0xF04D: 0xD04D,
0xF149: 0xD149,
0xF249: 0xD249,
0xF24D: 0xD24D,
0xF349: 0xD349,
0xF44D: 0xD44D,
0xF549: 0xD549,
0xF64D: 0xD64D,
0xF749: 0xD749,
}
def marked(cp):
return bool(
cp is not None
and cp.brand == 'toyota'
and cp.carFingerprint == CAR.TOYOTA_RAV4H
and cp.flags & ToyotaFlags.GAS_INTERCEPTOR
and len(cp.safetyConfigs) == 1
and cp.safetyConfigs[0].safetyModel == structs.CarParams.SafetyModel.toyota
@@ -22,7 +78,24 @@ def marked(cp):
)
def hold_base_cp(cp):
"""Project an eligible, exactly requested hold setting onto its existing owner."""
from opendbc.car.toyota.values import TOYOTA_AUTO_HOLD_CARS, uses_toyota_auto_hold_aeb
if cp is None or not cp.flags & ToyotaFlags.AUTO_BRAKE_HOLD:
return cp
permission = 256 if uses_toyota_auto_hold_aeb(cp) else 128
if (cp.brand != 'toyota' or cp.carFingerprint not in TOYOTA_AUTO_HOLD_CARS or
not cp.openpilotLongitudinalControl or cp.secOcRequired or cp.notCar or cp.passive or cp.dashcamOnly or
cp.alternativeExperience not in (permission, permission | 32)):
return cp
parent = cp.as_reader().as_builder() if hasattr(cp, 'as_reader') else cp.as_builder()
parent.flags &= ~int(ToyotaFlags.AUTO_BRAKE_HOLD)
parent.alternativeExperience &= ~(128 | 256)
return parent
def parent_cp(cp):
cp = hold_base_cp(cp)
if not marked(cp):
return cp
parent = cp.as_reader().as_builder() if hasattr(cp, 'as_reader') else cp.as_builder()
@@ -31,45 +104,82 @@ def parent_cp(cp):
return parent
def configured(cp):
from opendbc.car.toyota import rav4h_filter
def parent_modules():
from opendbc.car.toyota import dsu_bypass, prius_longitudinal, advert_filter, rav4h_filter, radar_filter
return (dsu_bypass, prius_longitudinal, advert_filter, rav4h_filter, radar_filter)
return marked(cp) and not cp.secOcRequired and rav4h_filter.configured(parent_cp(cp))
def configured(cp):
return marked(cp) and not cp.secOcRequired and any(module.configured(parent_cp(cp)) for module in parent_modules())
def hardware_supported(candidate, fingerprint, car_fw):
from opendbc.car.toyota import rav4h_filter
if candidate != CAR.TOYOTA_RAV4H or fingerprint.get(0, {}).get(0x201) != 6 or any(0x201 in frames for bus, frames in fingerprint.items() if bus != 0):
from opendbc.car.toyota import dsu_bypass, rav4h_filter, eps8_sdsu, legacy_sdsu, advert_filter, prius_sdsu, prius_advert_filter, radar_filter
if fingerprint.get(0, {}).get(0x201) != 6 or any(0x201 in frames for bus, frames in fingerprint.items() if bus != 0):
return False
return rav4h_filter.hardware_supported(candidate, without_pedal(fingerprint), car_fw)
parent = without_pedal(fingerprint)
for module in (dsu_bypass, prius_advert_filter, prius_sdsu, advert_filter, legacy_sdsu, eps8_sdsu, rav4h_filter):
if module.hardware_supported(candidate, parent, car_fw):
return True
if prius_status_hardware(candidate, parent, car_fw):
return True
if not radar_filter.hardware_supported(candidate, parent):
return False
from opendbc.car.toyota.fingerprints import FW_VERSIONS
known = FW_VERSIONS[candidate]
for ecu in (structs.CarParams.Ecu.eps, structs.CarParams.Ecu.fwdCamera):
rows = [fw for fw in car_fw if fw.ecu == ecu]
if not rows or any(fw.logging or fw.bus != 0 or fw.brand != 'toyota' or
bytes(fw.fwVersion) not in known.get((ecu, fw.address, fw.subAddress or None), ()) for fw in rows):
return False
return True
def prius_status_hardware(candidate, fingerprint, car_fw):
from opendbc.car.toyota import prius_retrofit_advert
if (candidate not in prius_retrofit_advert.CARS or fingerprint.get(0, {}).get(0x2FF) != 8 or
any(0x2FF in frames and (bus not in (0, 2) or frames[0x2FF] != 8) for bus, frames in fingerprint.items()) or
any(address in frames for frames in fingerprint.values() for address in (0x201, 0x2AA))):
return False
from opendbc.car.toyota.fingerprints import FW_VERSIONS
known = FW_VERSIONS[CAR.TOYOTA_PRIUS]
eps = [fw for fw in car_fw if fw.ecu == structs.CarParams.Ecu.eps]
if not eps or any(fw.logging or fw.bus != 0 or fw.brand != 'toyota' or fw.address != 0x7A1 or fw.subAddress or
bytes(fw.fwVersion) != prius_retrofit_advert.EPS_FIRMWARE for fw in eps):
return False
for ecu in (structs.CarParams.Ecu.fwdCamera, structs.CarParams.Ecu.fwdRadar):
if any(fw.logging or fw.bus != 0 or fw.brand != 'toyota' or
bytes(fw.fwVersion) not in known.get((ecu, fw.address, fw.subAddress or None), ()) for fw in car_fw if fw.ecu == ecu):
return False
return True
def without_pedal(fingerprint):
return {bus: {address: size for address, size in frames.items() if address != 0x201} for bus, frames in fingerprint.items()}
def apply(cp):
from opendbc.car.toyota import rav4h_filter
def composite_word(cp):
return cp.safetyConfigs[0].safetyParam | 0x2000
if not rav4h_filter.configured(cp) or cp.carFingerprint != CAR.TOYOTA_RAV4H:
def apply(cp):
if not any(module.configured(cp) for module in parent_modules()) or composite_word(cp) not in PARENT_WORDS:
return False
cp.safetyConfigs[0].safetyParam = composite_word(cp)
cp.flags |= int(ToyotaFlags.GAS_INTERCEPTOR)
cp.safetyConfigs[0].safetyParam |= 0x2000
cp.minEnableSpeed = -1.
return True
def prepare_stock(cp):
from opendbc.car.toyota import rav4h_filter
if not configured(cp):
return False
parent = parent_cp(cp)
assert rav4h_filter.prepare_stock(parent)
assert any(module.prepare_stock(parent) for module in parent_modules())
cp.flags = parent.flags | int(ToyotaFlags.GAS_INTERCEPTOR)
cp.alternativeExperience = parent.alternativeExperience
cp.openpilotLongitudinalControl = False
cp.safetyConfigs[0].safetyParam = parent.safetyConfigs[0].safetyParam | 0x2000
cp.safetyConfigs[0].safetyParam = composite_word(parent)
cp.autoResumeSng = parent.autoResumeSng
return True
@@ -42,6 +42,8 @@ def apply(cp):
def configured(cp):
from opendbc.car.toyota.pedal_composite import parent_cp
cp = parent_cp(cp)
from opendbc.car.toyota import prius_retrofit_advert
if prius_retrofit_advert.configured(cp):
return True
@@ -57,6 +59,9 @@ def configured(cp):
def prepare_stock(cp):
from opendbc.car.toyota import pedal_composite
if pedal_composite.marked(cp):
return pedal_composite.prepare_stock(cp)
if not configured(cp):
return False
cp.openpilotLongitudinalControl = False
@@ -13,6 +13,8 @@ TOYOTA_NO_LEAD_CRUISE_SIGN_FLIP_MIN_SET_SPEED_ERROR = .35
def configured(cp):
from opendbc.car.toyota.pedal_composite import parent_cp
cp = parent_cp(cp)
from opendbc.car.toyota import prius_sdsu, prius_advert_filter
if prius_sdsu.configured(cp) or prius_advert_filter.configured(cp):
return True
@@ -21,8 +23,14 @@ def configured(cp):
not cp.passive and cp.steerControlType == structs.CarParams.SteerControlType.torque and
cp.flags & ~int(ToyotaFlags.ZSS) == int(ToyotaFlags.HYBRID | ToyotaFlags.LONG_FILTER | ToyotaFlags.RAISED_ACCEL_LIMIT) and
len(cp.safetyConfigs) == 1 and cp.safetyConfigs[0].safetyModel == structs.CarParams.SafetyModel.toyota and
cp.safetyConfigs[0].safetyParam in (4169, 4681) and
cp.openpilotLongitudinalControl == (cp.safetyConfigs[0].safetyParam == 4169))
cp.safetyConfigs[0].safetyParam in (0x8049, 0x8249) and
cp.openpilotLongitudinalControl == (cp.safetyConfigs[0].safetyParam == 0x8049))
def eps73_status_configured(cp):
from opendbc.car.toyota.pedal_composite import parent_cp
cp = parent_cp(cp)
return configured(cp) and cp.carFingerprint in (CAR.TOYOTA_PRIUS, CAR.TOYOTA_PRIUS_RETROFIT) and cp.safetyConfigs[0].safetyParam in (0x8049, 0x8249)
def enabled(cp):
@@ -34,13 +42,16 @@ def stopping_decel_rate(cp):
def prepare_stock(cp):
from opendbc.car.toyota import pedal_composite
if pedal_composite.marked(cp):
return pedal_composite.prepare_stock(cp)
from opendbc.car.toyota import prius_sdsu, prius_advert_filter
if prius_sdsu.prepare_stock(cp) or prius_advert_filter.prepare_stock(cp):
return True
if not configured(cp):
return False
cp.openpilotLongitudinalControl = False
cp.safetyConfigs[0].safetyParam = 4681
cp.safetyConfigs[0].safetyParam = 0x8249
cp.autoResumeSng = False
return True
@@ -32,6 +32,8 @@ def hardware_supported(candidate, fingerprint, car_fw):
def configured(cp):
from opendbc.car.toyota.pedal_composite import parent_cp
cp = parent_cp(cp)
if (cp is None or cp.brand != 'toyota' or cp.carFingerprint not in CARS or cp.notCar or cp.passive or cp.dashcamOnly or
cp.secOcRequired or not cp.pcmCruise or cp.steerControlType != structs.CarParams.SteerControlType.torque or
len(cp.safetyConfigs) != 1 or cp.alphaLongitudinalAvailable or cp.autoResumeSng):
@@ -40,6 +40,8 @@ def apply(cp):
def configured(cp):
from opendbc.car.toyota.pedal_composite import parent_cp
cp = parent_cp(cp)
if (cp is None or cp.brand != 'toyota' or cp.carFingerprint != CAR.TOYOTA_PRIUS or cp.notCar or cp.passive or
cp.dashcamOnly or cp.secOcRequired or not cp.pcmCruise or len(cp.safetyConfigs) != 1 or
cp.steerControlType != structs.CarParams.SteerControlType.torque):
@@ -52,6 +54,9 @@ def configured(cp):
def prepare_stock(cp):
from opendbc.car.toyota import pedal_composite
if pedal_composite.marked(cp):
return pedal_composite.prepare_stock(cp)
if not configured(cp):
return False
cp.openpilotLongitudinalControl = False
@@ -29,6 +29,8 @@ def hardware_supported(candidate, fingerprint):
def configured(cp):
from opendbc.car.toyota.pedal_composite import parent_cp
cp = parent_cp(cp)
profile = PROFILES.get(cp.carFingerprint) if cp is not None else None
return bool(profile is not None and cp.brand == 'toyota' and
cp.flags & ToyotaFlags.RADAR_CAN_FILTER and not cp.flags & ToyotaFlags.DISABLE_RADAR and
@@ -38,6 +40,9 @@ def configured(cp):
def prepare_stock(cp):
from opendbc.car.toyota import pedal_composite
if pedal_composite.marked(cp):
return pedal_composite.prepare_stock(cp)
if not configured(cp):
return False
cp.openpilotLongitudinalControl = False
+66 -28
View File
@@ -98,7 +98,8 @@ static bool toyota_legacy_main_current(void) {
bool ready = true;
if (toyota_legacy_sdsu && toyota_alt_cruise) {
ready = false;
if (current_safety_config.rx_checks_len == 6) {
if ((current_safety_config.rx_checks_len == 6) ||
(toyota_pedal_composite && (current_safety_config.rx_checks_len > 6))) {
const RxStatus *main_status = &current_safety_config.rx_checks[5].status;
ready = main_status->msg_seen && main_status->valid_checksum && main_status->valid_quality_flag &&
!main_status->lagging && (main_status->wrong_counters < MAX_WRONG_COUNTERS) && acc_main_on &&
@@ -126,7 +127,10 @@ static bool toyota_legacy_advert_ready(void) {
static bool toyota_hold_ready(int permission) {
const int hold_mask = ALT_EXP_TOYOTA_AUTO_HOLD | ALT_EXP_TOYOTA_AEB_HOLD;
const uint32_t now = microsecond_timer_get();
return toyota_rx_ready(now) && ((alternative_experience & hold_mask) == permission) && !toyota_stock_longitudinal && !toyota_secoc &&
return toyota_rx_ready(now) && toyota_legacy_main_current() && toyota_legacy_advert_ready() &&
(!(toyota_sdsu_status || toyota_pedal) || aol_rx_healthy()) && (!toyota_sdsu_status || toyota_sdsu_control) &&
(!toyota_dsu_bypass || (toyota_bypass_control && !toyota_bypass_aeb)) &&
((alternative_experience & hold_mask) == permission) && !toyota_stock_longitudinal && !toyota_secoc &&
toyota_hold_config_valid && !safety_rx_checks_invalid && !relay_malfunction && !vehicle_moving && !gas_pressed && toyota_hold_main_on &&
toyota_hold_main_seen && toyota_hold_speed_seen && toyota_hold_gas_seen &&
(safety_get_ts_elapsed(now, toyota_hold_main_ts) <= 1000000U) &&
@@ -192,6 +196,28 @@ static bool toyota_get_quality_flag_valid(const CANPacket_t *msg) {
return valid;
}
static void toyota_hold_observe(const CANPacket_t *msg) {
if ((msg->bus == 2U) && (msg->addr == 0x344U) && (GET_LEN(msg) == 8U) &&
(toyota_get_checksum(msg) == toyota_compute_checksum(msg))) {
toyota_hold_camera_seen = true;
toyota_hold_camera_ts = microsecond_timer_get();
for (uint8_t i = 0U; i < 7U; i++) {
toyota_hold_camera_data[i] = msg->data[i];
}
}
if (msg->bus == 0U) {
if ((msg->addr == 0x1D3U) && (GET_LEN(msg) == 8U)) {
if (toyota_get_checksum(msg) != toyota_compute_checksum(msg)) {
toyota_hold_main_seen = false;
} else {
toyota_hold_main_on = GET_BIT(msg, 15U);
toyota_hold_main_seen = true;
toyota_hold_main_ts = microsecond_timer_get();
}
}
}
}
static void toyota_optional_rx_hook(const CANPacket_t *msg) {
if (toyota_dsu_bypass) {
if (msg_matches(msg, 0x343U, 2U)) {
@@ -235,28 +261,11 @@ static void toyota_optional_rx_hook(const CANPacket_t *msg) {
toyota_aol_seen[index] = false;
} else {
}
if ((msg->bus == 2U) && (msg->addr == 0x344U) && (GET_LEN(msg) == 8U) &&
(toyota_get_checksum(msg) == toyota_compute_checksum(msg))) {
toyota_hold_camera_seen = true;
toyota_hold_camera_ts = microsecond_timer_get();
for (uint8_t i = 0U; i < 7U; i++) {
toyota_hold_camera_data[i] = msg->data[i];
}
}
if (msg->bus == 0U) {
if ((msg->addr == 0x1D3U) && (GET_LEN(msg) == 8U)) {
if (toyota_get_checksum(msg) != toyota_compute_checksum(msg)) {
toyota_hold_main_seen = false;
} else {
toyota_hold_main_on = GET_BIT(msg, 15U);
toyota_hold_main_seen = true;
toyota_hold_main_ts = microsecond_timer_get();
}
}
}
toyota_hold_observe(msg);
}
static void toyota_rx_hook(const CANPacket_t *msg) {
toyota_hold_observe(msg);
if (toyota_dsu_bypass && msg_matches(msg, 0x343U, 2U)) {
toyota_bypass_control = !GET_BIT(msg, 18U) && !GET_BIT(msg, 19U);
}
@@ -604,10 +613,11 @@ static bool toyota_tx_hook(const CANPacket_t *msg) {
}
static safety_config toyota_init(uint16_t param) {
const uint16_t base_param = toyota_bypass_base_param(toyota_pedal_parent_param(param));
toyota_dsu_bypass = toyota_bypass_param(param);
toyota_bypass_eps5 = toyota_dsu_bypass && ((param & 0x1000U) == 0U);
toyota_bypass_alt_main = toyota_dsu_bypass && ((param & 0x4000U) != 0U);
const uint16_t parent_param = toyota_pedal_parent_param(param);
const uint16_t base_param = toyota_bypass_base_param(parent_param);
toyota_dsu_bypass = toyota_bypass_param(parent_param);
toyota_bypass_eps5 = toyota_dsu_bypass && ((parent_param & 0x1000U) == 0U);
toyota_bypass_alt_main = toyota_dsu_bypass && ((parent_param & 0x4000U) != 0U);
toyota_bypass_ambiguous = false;
toyota_bypass_control = false;
toyota_bypass_aeb = false;
@@ -619,7 +629,9 @@ static safety_config toyota_init(uint16_t param) {
toyota_hold_main_on = false;
toyota_hold_host_seen = false;
toyota_hold_host_ts = 0U;
toyota_hold_config_valid = (((base_param & ~0x5FFU) == 0U) && ((base_param & 0xFFU) != 0U)) || (base_param == 0x9049U);
toyota_hold_config_valid = (((base_param & ~0x5FFU) == 0U) && ((base_param & 0xFFU) != 0U)) || toyota_aol_rav4h_filter || toyota_eps8_sdsu || toyota_legacy_sdsu ||
toyota_legacy_advert_param(base_param) || toyota_camera_2aa_param(base_param) ||
toyota_prius_filter_param(base_param) || toyota_pedal;
toyota_hold_camera_seen = false;
toyota_hold_camera_ts = 0U;
toyota_hold_main_seen = false;
@@ -760,7 +772,7 @@ static safety_config toyota_init(uint16_t param) {
ret.rx_checks_len = 7;
} else if ((toyota_legacy_sdsu && toyota_alt_cruise) || toyota_legacy_advert_param(base_param) || toyota_camera_2aa_param(base_param) || toyota_prius_advert_param(base_param) || (base_param == 856U)) {
ret.rx_checks_len = 6;
} else if (toyota_pedal || toyota_alt_cruise || toyota_sdsu_status) {
} else if (standalone_pedal || toyota_alt_cruise || toyota_sdsu_status) {
ret.rx_checks_len = 5;
} else {
ret.rx_checks_len = 4;
@@ -775,7 +787,7 @@ static safety_config toyota_init(uint16_t param) {
.ignore_counter = true, .ignore_quality_flag = true};
ret.rx_checks_len = 7;
}
if (toyota_pedal_composite) {
if ((param == 0xB049U) || (param == 0xB249U)) {
// Keep all parent checks, including smartDSU status, independently required.
toyota_rx_checks[5].msg[0] = (CanMsgCheck){.addr = 0x201, .bus = 0U, .len = 6, .frequency = 50U,
.max_counter = 15U, .ignore_quality_flag = false};
@@ -784,6 +796,32 @@ static safety_config toyota_init(uint16_t param) {
toyota_rx_checks[7].msg[0] = (CanMsgCheck){.addr = 0x1D3, .bus = 0U, .len = 8, .frequency = 10U,
.ignore_counter = true, .ignore_quality_flag = true};
ret.rx_checks_len = 8;
} else if (toyota_pedal_composite) {
// Append independent physical sources and pedal to the unchanged parent
// catalog. Eight rows cover the largest parent without shrinking buffers.
bool eps_required = false;
bool main_required = false;
for (int i = 0; i < ret.rx_checks_len; i++) {
eps_required |= toyota_rx_checks[i].msg[0].addr == 0x262;
main_required |= toyota_rx_checks[i].msg[0].addr == (toyota_alt_cruise ? 0x365 : 0x1D3);
}
if (!eps_required) {
const bool eps5 = (toyota_dsu_bypass && toyota_bypass_eps5) || toyota_aol_rav4h_filter ||
toyota_legacy_sdsu || toyota_legacy_advert();
toyota_rx_checks[ret.rx_checks_len].msg[0] = (CanMsgCheck){.addr = 0x262, .bus = 0U,
.len = eps5 ? 5 : 8, .frequency = 25U, .ignore_counter = true, .ignore_quality_flag = true};
ret.rx_checks_len++;
}
if (!main_required) {
toyota_rx_checks[ret.rx_checks_len].msg[0] = (CanMsgCheck){.addr = toyota_alt_cruise ? 0x365 : 0x1D3,
.bus = 0U, .len = toyota_alt_cruise ? 7 : 8, .frequency = 10U, .ignore_checksum = toyota_alt_cruise,
.ignore_counter = true, .ignore_quality_flag = true};
ret.rx_checks_len++;
}
toyota_rx_checks[ret.rx_checks_len].msg[0] = (CanMsgCheck){.addr = 0x201, .bus = 0U, .len = 6,
.frequency = 50U, .max_counter = 15U, .ignore_quality_flag = false};
ret.rx_checks_len++;
} else {
}
}
+14 -11
View File
@@ -1,5 +1,7 @@
#pragma once
static uint16_t toyota_pedal_parent_param(uint16_t param);
static bool toyota_dsu_bypass = false;
static bool toyota_bypass_eps5 = false;
static bool toyota_bypass_alt_main = false;
@@ -20,7 +22,7 @@ static bool toyota_prius_sdsu_param(uint16_t param) {
}
static bool toyota_prius_sdsu(void) {
return toyota_prius_sdsu_param(current_safety_param);
return toyota_prius_sdsu_param(toyota_pedal_parent_param(current_safety_param));
}
static bool toyota_prius_retrofit_advert_param(uint16_t param) {
@@ -32,7 +34,7 @@ static bool toyota_prius_advert_param(uint16_t param) {
}
static bool toyota_prius_advert(void) {
return toyota_prius_advert_param(current_safety_param);
return toyota_prius_advert_param(toyota_pedal_parent_param(current_safety_param));
}
static bool toyota_prius_filter_param(uint16_t param) {
@@ -40,7 +42,7 @@ static bool toyota_prius_filter_param(uint16_t param) {
}
static bool toyota_prius_filter(void) {
return toyota_prius_filter_param(current_safety_param);
return toyota_prius_filter_param(toyota_pedal_parent_param(current_safety_param));
}
// Disjoint original Prius owners share this sticky receiver identity latch.
@@ -51,7 +53,7 @@ static bool toyota_camera_2aa_param(uint16_t param) {
}
static bool toyota_camera_2aa(void) {
return toyota_camera_2aa_param(current_safety_param);
return toyota_camera_2aa_param(toyota_pedal_parent_param(current_safety_param));
}
static bool toyota_camera_2aa_ambiguous = false;
@@ -61,7 +63,7 @@ static bool toyota_legacy_advert_param(uint16_t param) {
}
static bool toyota_legacy_advert(void) {
return toyota_legacy_advert_param(current_safety_param);
return toyota_legacy_advert_param(toyota_pedal_parent_param(current_safety_param));
}
@@ -72,7 +74,7 @@ static bool toyota_composite_pcm_gas = false;
static bool toyota_composite_pedal_gas = false;
static bool toyota_pedal_composite_param(uint16_t param) {
return (param == 0xB049U) || (param == 0xB249U);
return (param == 0x3049U) || (param == 0x3249U) || (param == 0x3449U) || (param == 0x3649U) || (param == 0xA042U) || (param == 0xA049U) || (param == 0xA242U) || (param == 0xA249U) || (param == 0xA449U) || (param == 0xA649U) || (param == 0xA849U) || (param == 0xA949U) || (param == 0xA958U) || (param == 0xA964U) || (param == 0xAA49U) || (param == 0xAB49U) || (param == 0xAB58U) || (param == 0xAB64U) || (param == 0xB049U) || (param == 0xB149U) || (param == 0xB158U) || (param == 0xB164U) || (param == 0xB249U) || (param == 0xB349U) || (param == 0xB358U) || (param == 0xB364U) || (param == 0xB449U) || (param == 0xB549U) || (param == 0xB558U) || (param == 0xB564U) || (param == 0xB649U) || (param == 0xB749U) || (param == 0xB758U) || (param == 0xB764U) || (param == 0xB842U) || (param == 0xB849U) || (param == 0xBA42U) || (param == 0xBA49U) || (param == 0xE042U) || (param == 0xE049U) || (param == 0xE242U) || (param == 0xE249U) || (param == 0xE84DU) || (param == 0xE949U) || (param == 0xEA4DU) || (param == 0xEB49U) || (param == 0xF049U) || (param == 0xF04DU) || (param == 0xF149U) || (param == 0xF249U) || (param == 0xF24DU) || (param == 0xF349U) || (param == 0xF44DU) || (param == 0xF549U) || (param == 0xF64DU) || (param == 0xF749U);
}
static uint16_t toyota_pedal_parent_param(uint16_t param) {
@@ -204,6 +206,7 @@ static void toyota_aol_observe(const CANPacket_t *msg) {
}
static void toyota_aol_configure(uint16_t param) {
const bool aol_requested = (alternative_experience == 32) || (alternative_experience == 160) || (alternative_experience == 288);
toyota_aol_reset();
toyota_camera_2aa_ambiguous = false;
toyota_prius_sdsu_ambiguous = false;
@@ -220,14 +223,14 @@ static void toyota_aol_configure(uint16_t param) {
#else
toyota_aol_secoc = false;
#endif
toyota_aol_enabled = (toyota_dsu_bypass && (alternative_experience == 32)) || ((toyota_eps8_sdsu || toyota_legacy_sdsu || toyota_legacy_advert_param(param) || toyota_camera_2aa_param(param) || toyota_prius_filter_param(param)) && (alternative_experience == 32)) || (toyota_aol_lta && (alternative_experience == 32)) || (toyota_aol_stock && (alternative_experience == 32)) ||
toyota_aol_enabled = (toyota_dsu_bypass && aol_requested) || ((toyota_eps8_sdsu || toyota_legacy_sdsu || toyota_legacy_advert_param(param) || toyota_camera_2aa_param(param) || toyota_prius_filter_param(param)) && aol_requested) || (toyota_aol_lta && aol_requested) || (toyota_aol_stock && aol_requested) ||
#ifdef ALLOW_DEBUG
(toyota_aol_secoc && (alternative_experience == 32)) ||
#endif
((param == 0x9049U) && ((alternative_experience == 32) || (alternative_experience == 160))) ||
((param == 0x2049U) && (alternative_experience == 32)) ||
((param == 4169U) && (alternative_experience == 32)) ||
((param == 73U) && ((alternative_experience == 32) || (alternative_experience == 160) || (alternative_experience == 288)));
((param == 0x9049U) && (aol_requested || (alternative_experience == 160))) ||
((param == 0x2049U) && aol_requested) ||
((param == 4169U) && aol_requested) ||
((param == 73U) && (aol_requested || (alternative_experience == 160) || (alternative_experience == 288)));
if (toyota_aol_enabled) {
static const AolSafetyPolicy policy = {
.reset = toyota_aol_reset,
@@ -0,0 +1,46 @@
"""Every exact composite retains its parent's RX contracts and physical gates."""
import pytest
from opendbc.car import structs
from opendbc.car.toyota.pedal_composite import PARENT_WORDS
from opendbc.safety.tests.libsafety import libsafety_py
from openpilot.starpilot.car.toyota.tests import test_rav4h_caller_native as helpers
source_matched_native = helpers.source_matched_native
libsafety_py.ffi.cdef('extern safety_config current_safety_config;')
def rx_catalog(safety):
cfg = safety.current_safety_config
fields = ('addr', 'bus', 'len', 'frequency', 'ignore_checksum', 'ignore_counter', 'max_counter', 'ignore_quality_flag')
return [tuple(int(getattr(cfg.rx_checks[i].msg[0], key)) for key in fields) for i in range(cfg.rx_checks_len)]
@pytest.mark.parametrize('word,parent', sorted(PARENT_WORDS.items()))
def test_parent_catalog_and_warm_switch_are_exact(word, parent):
safety = libsafety_py.libsafety
safety.init_tests()
safety.set_alternative_experience(32)
try:
assert safety.set_safety_hooks(structs.CarParams.SafetyModel.toyota, parent) == 0
original = rx_catalog(safety)
assert safety.set_safety_hooks(structs.CarParams.SafetyModel.toyota, word) == 0
composite = rx_catalog(safety)
assert 5 <= len(composite) <= 8
assert composite[:len(original)] == original
extra_eps = not any(row[0] == 0x262 and row[1] == 0 for row in original)
extra_main = not any(row[0] in (0x1D3, 0x365) and row[1] == 0 for row in original)
assert len(composite) == len(original) + 1 + int(extra_eps) + int(extra_main)
assert sum(row[0] == 0x2FF for row in composite) == sum(row[0] == 0x2FF for row in original)
assert sum(row[:3] == (0x201, 0, 6) for row in composite) == 1
assert sum(row[0] == 0x262 and row[1] == 0 for row in composite) == 1
assert sum(row[0] in (0x1D3, 0x365) and row[1] == 0 for row in composite) == 1
pedal = next(row for row in composite if row[0] == 0x201)
assert pedal[3:] == (50, 0, 0, 15, 0)
assert not safety.safety_config_valid() and safety.aol_get_permission_mask() == 0
# A warm switch must not retain the pedal's extra catalog or authority.
assert safety.set_safety_hooks(structs.CarParams.SafetyModel.toyota, parent) == 0
assert rx_catalog(safety) == original
assert not safety.safety_config_valid() and safety.aol_get_permission_mask() == 0
finally:
safety.set_alternative_experience(0)
safety.set_safety_hooks(structs.CarParams.SafetyModel.noOutput, 0)
@@ -179,7 +179,7 @@ int main() {
}
for (uint32_t word = 0U; word <= 65535U; ++word) {
const bool expected = (word == 0x8949U) || (word == 0x8B49U) || (word == 0x8849U) || (word == 0x8A49U) || (word == 0x9849U) || (word == 0x9A49U) || (word == 0x9842U) || (word == 0x9A42U) || (word == 0x8958U) || (word == 0x8B58U) || (word == 0x8964U) || (word == 0x8B64U) || (word == 0xC84DU) || (word == 0xCA4DU) || (word == 0xC949U) || (word == 0xCB49U) || (word == 0xB049U) || (word == 0xB249U) || (word == 0xD049U) || (word == 0xD249U) || (word == 0xC042U) || (word == 0xC242U) || (word == 0x8042U) || (word == 0x8242U) || (word == 0xC049U) || (word == 0xC249U) || (word == 73U) || (word == 585U) || (word == 856U) || (word == 4169U) || (word == 4681U) || (word == 2121U) || (word == 0x9049U) || (word == 0x9249U) || (word == 0x2449U) || (word == 0x2649U) || (word == 0x2049U) || (word == 0x2249U) || (word == 0x424DU) || (word == 0x449U) || (word == 0x649U) || (word == 0x1449U) || (word == 0x1649U) || (word == 0x8049U) || (word == 0x8249U) || (word == 0x8449U) || (word == 0x8649U) || (word == 0x9158U) || (word == 0x9358U) || (word == 0x9149U) || (word == 0x9349U) || (word == 0x9164U) || (word == 0x9364U) || (word == 0xd149U) || (word == 0xd349U) || (word == 0xd04dU) || (word == 0xd24dU) || (word == 0x9449U) || (word == 0x9549U) || (word == 0x9558U) || (word == 0x9564U) || (word == 0x9649U) || (word == 0x9749U) || (word == 0x9758U) || (word == 0x9764U) || (word == 0xD44DU) || (word == 0xD549U) || (word == 0xD64DU) || (word == 0xD749U);
const bool expected = (word == 0x3049U) || (word == 0x3249U) || (word == 0x3449U) || (word == 0x3649U) || (word == 0xA042U) || (word == 0xA049U) || (word == 0xA242U) || (word == 0xA249U) || (word == 0xA449U) || (word == 0xA649U) || (word == 0xA849U) || (word == 0xA949U) || (word == 0xA958U) || (word == 0xA964U) || (word == 0xAA49U) || (word == 0xAB49U) || (word == 0xAB58U) || (word == 0xAB64U) || (word == 0xB149U) || (word == 0xB158U) || (word == 0xB164U) || (word == 0xB349U) || (word == 0xB358U) || (word == 0xB364U) || (word == 0xB449U) || (word == 0xB549U) || (word == 0xB558U) || (word == 0xB564U) || (word == 0xB649U) || (word == 0xB749U) || (word == 0xB758U) || (word == 0xB764U) || (word == 0xB842U) || (word == 0xB849U) || (word == 0xBA42U) || (word == 0xBA49U) || (word == 0xE042U) || (word == 0xE049U) || (word == 0xE242U) || (word == 0xE249U) || (word == 0xE84DU) || (word == 0xE949U) || (word == 0xEA4DU) || (word == 0xEB49U) || (word == 0xF049U) || (word == 0xF04DU) || (word == 0xF149U) || (word == 0xF249U) || (word == 0xF24DU) || (word == 0xF349U) || (word == 0xF44DU) || (word == 0xF549U) || (word == 0xF64DU) || (word == 0xF749U) || (word == 0x8949U) || (word == 0x8B49U) || (word == 0x8849U) || (word == 0x8A49U) || (word == 0x9849U) || (word == 0x9A49U) || (word == 0x9842U) || (word == 0x9A42U) || (word == 0x8958U) || (word == 0x8B58U) || (word == 0x8964U) || (word == 0x8B64U) || (word == 0xC84DU) || (word == 0xCA4DU) || (word == 0xC949U) || (word == 0xCB49U) || (word == 0xB049U) || (word == 0xB249U) || (word == 0xD049U) || (word == 0xD249U) || (word == 0xC042U) || (word == 0xC242U) || (word == 0x8042U) || (word == 0x8242U) || (word == 0xC049U) || (word == 0xC249U) || (word == 73U) || (word == 585U) || (word == 856U) || (word == 4169U) || (word == 4681U) || (word == 2121U) || (word == 0x9049U) || (word == 0x9249U) || (word == 0x2449U) || (word == 0x2649U) || (word == 0x2049U) || (word == 0x2249U) || (word == 0x424DU) || (word == 0x449U) || (word == 0x649U) || (word == 0x1449U) || (word == 0x1649U) || (word == 0x8049U) || (word == 0x8249U) || (word == 0x8449U) || (word == 0x8649U) || (word == 0x9158U) || (word == 0x9358U) || (word == 0x9149U) || (word == 0x9349U) || (word == 0x9164U) || (word == 0x9364U) || (word == 0xd149U) || (word == 0xd349U) || (word == 0xd04dU) || (word == 0xd24dU) || (word == 0x9449U) || (word == 0x9549U) || (word == 0x9558U) || (word == 0x9564U) || (word == 0x9649U) || (word == 0x9749U) || (word == 0x9758U) || (word == 0x9764U) || (word == 0xD44DU) || (word == 0xD549U) || (word == 0xD64DU) || (word == 0xD749U);
auto toyota = status();
toyota.safety_mode = 2U;
toyota.safety_param = static_cast<uint16_t>(word);
+11
View File
@@ -6,6 +6,12 @@ from openpilot.starpilot.aol.policy import AolVehiclePolicy
from openpilot.starpilot.aol.intent import AolCardIntent, AOL_TOGGLE
AOL_WORDS = frozenset((
0x3049, 0x3249, 0x3449, 0x3649, 0xA042, 0xA049, 0xA242, 0xA249, 0xA449, 0xA649,
0xA849, 0xA949, 0xA958, 0xA964, 0xAA49, 0xAB49, 0xAB58, 0xAB64, 0xB149, 0xB158,
0xB164, 0xB349, 0xB358, 0xB364, 0xB449, 0xB549, 0xB558, 0xB564, 0xB649, 0xB749,
0xB758, 0xB764, 0xB842, 0xB849, 0xBA42, 0xBA49, 0xE042, 0xE049, 0xE242, 0xE249,
0xE84D, 0xE949, 0xEA4D, 0xEB49, 0xF049, 0xF04D, 0xF149, 0xF249, 0xF24D, 0xF349,
0xF44D, 0xF549, 0xF64D, 0xF749,
0x8949, 0x8B49,
0x8849, 0x8A49, 0x9849, 0x9A49, 0x9842, 0x9A42, 0x8958, 0x8B58, 0x8964, 0x8B64, 0xC84D, 0xCA4D, 0xC949, 0xCB49,
0x8042, 0x8242, 0xC042, 0xC242, 0xD049, 0xD249,
@@ -99,6 +105,11 @@ def stock_prius_retrofit_qualified(cp, *, marked_only=False):
def qualified(cp, *, marked_only=False):
from opendbc.car.toyota.pedal_composite import hold_base_cp
base = hold_base_cp(cp)
if base is not cp:
from opendbc.car.toyota.interface import toyota_auto_hold_supported
return toyota_auto_hold_supported(cp) and qualified(base, marked_only=marked_only)
from opendbc.car.toyota import dsu_bypass
if dsu_bypass.configured(cp):
return cp.alternativeExperience in ((32,) if marked_only else (0, 32))
+1 -1
View File
@@ -3,7 +3,7 @@
#include "selfdrive/pandad/aol_protocol.h"
inline bool toyota_aol_param(uint16_t param) {
return (param == 0x8949U) || (param == 0x8B49U) || (param == 0x8849U) || (param == 0x8A49U) || (param == 0x9849U) || (param == 0x9A49U) || (param == 0x9842U) || (param == 0x9A42U) || (param == 0x8958U) || (param == 0x8B58U) || (param == 0x8964U) || (param == 0x8B64U) || (param == 0xC84DU) || (param == 0xCA4DU) || (param == 0xC949U) || (param == 0xCB49U) || (param == 0xB049U) || (param == 0xB249U) || (param == 0xD049U || param == 0xD249U || param == 0xC042U || param == 0xC242U || param == 0x8042U || param == 0x8242U || param == 0xC049U) || (param == 0xC249U) || (param == 73U) || (param == 585U) || (param == 856U) || (param == 4169U) || (param == 4681U) || (param == 2121U) || (param == 0x9049U) || (param == 0x9249U) || (param == 0x2449U) || (param == 0x2649U) || (param == 0x2049U) || (param == 0x2249U) || (param == 0x424DU) || (param == 0x449U) || (param == 0x649U) || (param == 0x1449U) || (param == 0x1649U) || (param == 0x8049U) || (param == 0x8249U) || (param == 0x8449U) || (param == 0x8649U) || (param == 0x9158U) || (param == 0x9358U) || (param == 0x9149U) || (param == 0x9349U) || (param == 0x9164U) || (param == 0x9364U) || (param == 0xd149U) || (param == 0xd349U) || (param == 0xd04dU) || (param == 0xd24dU) || (param == 0x9449U) || (param == 0x9549U) || (param == 0x9558U) || (param == 0x9564U) || (param == 0x9649U) || (param == 0x9749U) || (param == 0x9758U) || (param == 0x9764U) || (param == 0xD44DU) || (param == 0xD549U) || (param == 0xD64DU) || (param == 0xD749U);
return (param == 0x3049U) || (param == 0x3249U) || (param == 0x3449U) || (param == 0x3649U) || (param == 0xA042U) || (param == 0xA049U) || (param == 0xA242U) || (param == 0xA249U) || (param == 0xA449U) || (param == 0xA649U) || (param == 0xA849U) || (param == 0xA949U) || (param == 0xA958U) || (param == 0xA964U) || (param == 0xAA49U) || (param == 0xAB49U) || (param == 0xAB58U) || (param == 0xAB64U) || (param == 0xB149U) || (param == 0xB158U) || (param == 0xB164U) || (param == 0xB349U) || (param == 0xB358U) || (param == 0xB364U) || (param == 0xB449U) || (param == 0xB549U) || (param == 0xB558U) || (param == 0xB564U) || (param == 0xB649U) || (param == 0xB749U) || (param == 0xB758U) || (param == 0xB764U) || (param == 0xB842U) || (param == 0xB849U) || (param == 0xBA42U) || (param == 0xBA49U) || (param == 0xE042U) || (param == 0xE049U) || (param == 0xE242U) || (param == 0xE249U) || (param == 0xE84DU) || (param == 0xE949U) || (param == 0xEA4DU) || (param == 0xEB49U) || (param == 0xF049U) || (param == 0xF04DU) || (param == 0xF149U) || (param == 0xF249U) || (param == 0xF24DU) || (param == 0xF349U) || (param == 0xF44DU) || (param == 0xF549U) || (param == 0xF64DU) || (param == 0xF749U) || (param == 0x8949U) || (param == 0x8B49U) || (param == 0x8849U) || (param == 0x8A49U) || (param == 0x9849U) || (param == 0x9A49U) || (param == 0x9842U) || (param == 0x9A42U) || (param == 0x8958U) || (param == 0x8B58U) || (param == 0x8964U) || (param == 0x8B64U) || (param == 0xC84DU) || (param == 0xCA4DU) || (param == 0xC949U) || (param == 0xCB49U) || (param == 0xB049U) || (param == 0xB249U) || (param == 0xD049U || param == 0xD249U || param == 0xC042U || param == 0xC242U || param == 0x8042U || param == 0x8242U || param == 0xC049U) || (param == 0xC249U) || (param == 73U) || (param == 585U) || (param == 856U) || (param == 4169U) || (param == 4681U) || (param == 2121U) || (param == 0x9049U) || (param == 0x9249U) || (param == 0x2449U) || (param == 0x2649U) || (param == 0x2049U) || (param == 0x2249U) || (param == 0x424DU) || (param == 0x449U) || (param == 0x649U) || (param == 0x1449U) || (param == 0x1649U) || (param == 0x8049U) || (param == 0x8249U) || (param == 0x8449U) || (param == 0x8649U) || (param == 0x9158U) || (param == 0x9358U) || (param == 0x9149U) || (param == 0x9349U) || (param == 0x9164U) || (param == 0x9364U) || (param == 0xd149U) || (param == 0xd349U) || (param == 0xd04dU) || (param == 0xd24dU) || (param == 0x9449U) || (param == 0x9549U) || (param == 0x9558U) || (param == 0x9564U) || (param == 0x9649U) || (param == 0x9749U) || (param == 0x9758U) || (param == 0x9764U) || (param == 0xD44DU) || (param == 0xD549U) || (param == 0xD64DU) || (param == 0xD749U);
}
inline constexpr AolSafetyProfile TOYOTA_AOL_PROFILE{2U, toyota_aol_param, true};
@@ -0,0 +1,159 @@
"""Full production callers for every distinct parent parser/controller topology."""
import pytest
from opendbc.car.toyota import dsu_bypass, pedal
from opendbc.car.toyota.interface import CarInterface
from opendbc.car.toyota.values import CAR, ToyotaFlags
from openpilot.starpilot.car.toyota.tests import test_rav4h_caller_native as helpers
from openpilot.starpilot.car.toyota.tests.test_pedal_parent_configurations import sources
from openpilot.starpilot.car.toyota.tests.test_toyota_cpp_transport import host_heartbeat_bridge as host_heartbeat_bridge
source_matched_native = helpers.source_matched_native
daemon_gc_scope = helpers.daemon_gc_scope
PROFILES = (
('TOYOTA_RAV4H', '2FF8', 'catalog'),
('TOYOTA_CAMRY', '2FF8', 'catalog'),
('LEXUS_GS_F', '2FF8', 'catalog'),
('TOYOTA_PRIUS', '2FF8', 'catalog'),
('TOYOTA_RAV4_TSS2', '2FF4', 'catalog'),
('TOYOTA_COROLLA', '2FF4', 'catalog'),
('TOYOTA_RAV4_TSS2_2022', '2AA8', 'catalog'),
('TOYOTA_RAV4_TSS2', '2AA8', 'catalog'),
('TOYOTA_PRIUS', '2FF8', 'EPS73_8965B47070'),
('TOYOTA_PRIUS_RETROFIT', '2FF4', 'EPS73_8965B47070'),
('TOYOTA_CAMRY', 'camera343_or_4CB8', 'catalog'),
('LEXUS_GS_F', 'camera343_or_4CB8', 'catalog'),
('TOYOTA_RAV4_TSS2_2023', '2FF8', 'catalog'),
('TOYOTA_RAV4_TSS2_2023', '2AA8', 'catalog'),
)
@pytest.mark.parametrize('name,topology,rack', PROFILES)
@pytest.mark.parametrize('stock', (False, True))
def test_nominal_parent_pedal_full_callers(name, topology, rack, stock, host_heartbeat_bridge):
run(name, topology, rack, stock, host_heartbeat_bridge)
def run(name, topology, rack, stock, bridge, kind='nominal'):
identity = getattr(CAR, name)
fp, fw = sources(identity, topology, rack)
fp[0][0x201] = 6
cp = CarInterface.get_params(identity, fp, fw, True, False, False)
assert pedal.configured(cp) and cp.openpilotLongitudinalControl
long_word = cp.safetyConfigs[0].safetyParam
tick = 0
pedal_sent = False
def physical(packer, **fields):
nonlocal tick
tick += 1
if kind == 'hold' and 260 <= tick < 430:
fields.update(stopped=True, brake=tick < 400, cruise=False)
if kind == 'hold' and 430 <= tick < 445:
fields.update(gas=True, cruise=False)
parent_drop = kind == 'parent_drop' and 260 <= tick < 311
pedal_drop = kind == 'pedal_drop' and 260 <= tick < 311
if topology != '2FF8' or parent_drop:
fields['sdsu'] = None
frames = helpers.physical(packer, **fields)
if identity in dsu_bypass.ALT_MAIN_CARS:
frames += [packer.make_can_msg('DSU_CRUISE', 0, {'MAIN_ON': fields.get('main', True), 'SET_SPEED': 90}),
packer.make_can_msg('PCM_CRUISE_ALT', 0, {'UI_SET_SPEED': 90})]
if topology == '2FF4':
frames.append((0x2FF, bytes.fromhex('00000409'), 0))
if topology == '2AA8':
frames.append((0x2AA, bytes(8), 0))
if topology in ('2AA8', '2FF4', 'camera343_or_4CB8', 'standalone2016'):
frames += [packer.make_can_msg('ACC_CONTROL', 2, {'ACC_TYPE': 1}), packer.make_can_msg('PRE_COLLISION', 2, {})]
if topology == '2FF8':
frames.append(packer.make_can_msg('PRE_COLLISION', 2, {}))
if kind == 'hold' or topology == 'standalone2016':
frames.append(packer.make_can_msg('PRE_COLLISION', 2, {}))
frames.append(packer.make_can_msg('PRE_COLLISION_2', 2, {}))
frames.append(packer.make_can_msg('PCS_HUD', 0 if cp.flags & ToyotaFlags.RADAR_ACC else 2, {}))
if identity == CAR.TOYOTA_RAV4_TSS2_2023:
frames = [frame for frame in frames if frame[0] not in (0x260, 0x262)]
frames += [packer.make_can_msg('STEER_TORQUE_SENSOR', 0, {'STEER_ANGLE': .1, 'STEER_ANGLE_INITIALIZING': 0}),
packer.make_can_msg('EPS_STATUS', 0, {'LKA_STATE': fields.get('eps', 1), 'LTA_STATE': fields.get('eps', 1)})]
frames = [frame for frame in frames if frame[0] != 0xAA]
frames.append(packer.make_can_msg('WHEEL_SPEEDS', 0, {
'WHEEL_SPEED_' + wheel: 0.0 if fields.get('stopped') else 18.0 for wheel in ('FL', 'FR', 'RL', 'RR')}))
a, d, b = packer.make_can_msg('GAS_SENSOR', 0, {
'INTERCEPTOR_GAS': 806 if fields.get('gas') else 0,
'INTERCEPTOR_GAS2': 806 if fields.get('gas') else 0, 'COUNTER_PEDAL': tick & 15, 'STATE': 0})
data = bytearray(d)
data[-1] = pedal.checksum(data)
if not pedal_drop:
frames.append((a, bytes(data), b))
if parent_drop and topology != '2FF8':
frames = [frame for frame in frames if not (frame[0] == 0x262 and frame[2] == 0)]
return frames
def tx_check(tick, frame, cp, safety):
nonlocal pedal_sent
if frame.address == 0x200:
data = bytes(frame.dat)
assert len(data) == 6 and data[-1] == pedal.checksum(data)
if data[4] & 128:
assert not stock and safety.aol_get_permission_mask() & 2
assert not safety.get_gas_pressed_prev() and not safety.get_brake_pressed_prev()
pedal_sent = True
else:
assert data[:4] == bytes(4)
return True
def observe(tick, host, cs, cc, safety, native):
if kind == 'hold':
assert host.CP.flags & ToyotaFlags.AUTO_BRAKE_HOLD
if 380 <= tick < 425:
assert host.CI.CC.brake_hold_active, (tick, cs.to_dict())
if 431 <= tick < 445:
assert not host.CI.CC.brake_hold_active
if kind.endswith('_drop') and 301 <= tick < 308:
assert not cc.latActive and not cc.longActive
assert safety.aol_get_permission_mask() == 0
scenario = 'main_lease' if kind.endswith('_drop') else 'nominal' if kind == 'ordinary' else kind
helpers.run_case(
stock, scenario, candidate=identity, bridge=bridge, input_clock=True, alpha_long=True,
sdsu_words=(long_word, long_word | 0x200), firmware_override=fw,
fingerprint_frames=[(a, bytes(n), bus) for bus, messages in fp.items() for a, n in messages.items()],
physical_frames=physical, native_tx_expected=tx_check, brake_stop_check_start=355,
angle=identity == CAR.TOYOTA_RAV4_TSS2_2023,
manual_selection=rack == 'EPS73_8965B47070', manual_pedal=rack == 'EPS73_8965B47070',
auto_hold=kind == 'hold', aol=kind != 'ordinary', on_sample=observe, filter_advert=topology == '2FF4',
bypass_owner=topology == 'camera343_or_4CB8',
)
assert pedal_sent == (not stock)
@pytest.mark.parametrize('kind,name,topology,rack', [
('parent_drop', 'TOYOTA_CAMRY', '2FF8', 'catalog'),
('parent_drop', 'TOYOTA_COROLLA', '2FF4', 'catalog'),
('parent_drop', 'TOYOTA_RAV4_TSS2', '2FF4', 'catalog'),
('parent_drop', 'TOYOTA_RAV4_TSS2_2022', '2AA8', 'catalog'),
('parent_drop', 'TOYOTA_RAV4_TSS2', '2AA8', 'catalog'),
('parent_drop', 'TOYOTA_CAMRY', 'camera343_or_4CB8', 'catalog'),
('physical', 'TOYOTA_CAMRY', '2FF8', 'catalog'),
('off', 'TOYOTA_CAMRY', '2FF8', 'catalog'),
('ordinary', 'TOYOTA_CAMRY', '2FF8', 'catalog'),
('pedal_drop', 'TOYOTA_CAMRY', '2FF8', 'catalog'),
])
def test_parent_pedal_physical_withdrawal_and_saved_settings(name, topology, rack, kind, host_heartbeat_bridge):
run(name, topology, rack, False, host_heartbeat_bridge, kind)
HOLD_PROFILES = (
('TOYOTA_RAV4H', '2FF8', 'catalog'),
('TOYOTA_RAV4_TSS2', '2FF8', 'catalog'),
('TOYOTA_RAV4_TSS2', '2FF4', 'catalog'),
('TOYOTA_RAV4_TSS2', '2AA8', 'catalog'),
('TOYOTA_COROLLA_TSS2', 'standalone2016', 'catalog'),
('TOYOTA_RAV4_TSS2', 'standalone2016', 'catalog'),
('TOYOTA_CAMRY_TSS2', '2FF8', 'catalog'),
('TOYOTA_RAV4', 'camera343_or_4CB8', 'catalog'),
)
@pytest.mark.parametrize('name,topology,rack', HOLD_PROFILES)
def test_shared_hold_full_callers(name, topology, rack, host_heartbeat_bridge):
run(name, topology, rack, False, host_heartbeat_bridge, 'hold')
@@ -0,0 +1,222 @@
"""Every scoped Dom pedal/parent combination retains the exact current parent tune."""
import pytest
from opendbc.car import structs
from opendbc.car.toyota import dsu_bypass, pedal_composite
from opendbc.car.toyota.interface import CarInterface
from opendbc.car.toyota.values import CAR, ToyotaFlags
from openpilot.starpilot.car.toyota.aol import qualified
from openpilot.starpilot.car.toyota.tests.test_dsu_bypass import acquired, fingerprint as bypass_fingerprint
ROWS = [
('LEXUS_NX', '2FF8', 'catalog'),
('LEXUS_RX', '2FF8', 'catalog'),
('TOYOTA_AVALON', '2FF8', 'catalog'),
('TOYOTA_HIGHLANDER', '2FF8', 'catalog'),
('TOYOTA_RAV4H', '2FF8', 'catalog'),
('TOYOTA_SIENNA', '2FF8', 'catalog'),
('LEXUS_ES_TSS2', '2FF8', 'catalog'),
('LEXUS_IS_TSS2', '2FF8', 'catalog'),
('LEXUS_LC_TSS2', '2FF8', 'catalog'),
('LEXUS_LS', '2FF8', 'catalog'),
('LEXUS_NX_TSS2', '2FF8', 'catalog'),
('LEXUS_RC_TSS2', '2FF8', 'catalog'),
('LEXUS_RX_TSS2', '2FF8', 'catalog'),
('TOYOTA_ALPHARD_TSS2', '2FF8', 'catalog'),
('TOYOTA_AVALON_2019', '2FF8', 'catalog'),
('TOYOTA_AVALON_TSS2', '2FF8', 'catalog'),
('TOYOTA_CAMRY', '2FF8', 'catalog'),
('TOYOTA_CAMRY_TSS2', '2FF8', 'catalog'),
('TOYOTA_CHR', '2FF8', 'catalog'),
('TOYOTA_CHR_TSS2', '2FF8', 'catalog'),
('TOYOTA_COROLLA_TSS2', '2FF8', 'catalog'),
('TOYOTA_HIGHLANDER_TSS2', '2FF8', 'catalog'),
('TOYOTA_MIRAI', '2FF8', 'catalog'),
('TOYOTA_PRIUS_TSS2', '2FF8', 'catalog'),
('TOYOTA_RAV4_TSS2', '2FF8', 'catalog'),
('TOYOTA_RAV4_TSS2_2022', '2FF8', 'catalog'),
('TOYOTA_RAV4_TSS2_2023', '2FF8', 'catalog'),
('LEXUS_CTH', '2FF8', 'catalog'),
('LEXUS_ES', '2FF8', 'catalog'),
('LEXUS_GS_F', '2FF8', 'catalog'),
('LEXUS_IS', '2FF8', 'catalog'),
('LEXUS_RC', '2FF8', 'catalog'),
('TOYOTA_COROLLA', '2FF8', 'catalog'),
('TOYOTA_MATRIX_RETROFIT', '2FF8', 'catalog'),
('TOYOTA_PRIUS_V', '2FF8', 'catalog'),
('TOYOTA_RAV4', '2FF8', 'catalog'),
('TOYOTA_PRIUS', '2FF8', 'catalog'),
('LEXUS_CTH', '2FF4', 'catalog'),
('LEXUS_ES', '2FF4', 'catalog'),
('LEXUS_GS_F', '2FF4', 'catalog'),
('LEXUS_IS', '2FF4', 'catalog'),
('LEXUS_NX', '2FF4', 'catalog'),
('LEXUS_RC', '2FF4', 'catalog'),
('LEXUS_RX', '2FF4', 'catalog'),
('TOYOTA_AVALON', '2FF4', 'catalog'),
('TOYOTA_COROLLA', '2FF4', 'catalog'),
('TOYOTA_HIGHLANDER', '2FF4', 'catalog'),
('TOYOTA_MATRIX_RETROFIT', '2FF4', 'catalog'),
('TOYOTA_PRIUS_V', '2FF4', 'catalog'),
('TOYOTA_RAV4', '2FF4', 'catalog'),
('TOYOTA_RAV4H', '2FF4', 'catalog'),
('TOYOTA_SIENNA', '2FF4', 'catalog'),
('LEXUS_ES_TSS2', '2FF4', 'catalog'),
('LEXUS_IS_TSS2', '2FF4', 'catalog'),
('LEXUS_LC_TSS2', '2FF4', 'catalog'),
('LEXUS_LS', '2FF4', 'catalog'),
('LEXUS_NX_TSS2', '2FF4', 'catalog'),
('LEXUS_RC_TSS2', '2FF4', 'catalog'),
('LEXUS_RX_TSS2', '2FF4', 'catalog'),
('TOYOTA_ALPHARD_TSS2', '2FF4', 'catalog'),
('TOYOTA_AVALON_2019', '2FF4', 'catalog'),
('TOYOTA_AVALON_TSS2', '2FF4', 'catalog'),
('TOYOTA_CAMRY_TSS2', '2FF4', 'catalog'),
('TOYOTA_COROLLA_TSS2', '2FF4', 'catalog'),
('TOYOTA_HIGHLANDER_TSS2', '2FF4', 'catalog'),
('TOYOTA_MIRAI', '2FF4', 'catalog'),
('TOYOTA_PRIUS_TSS2', '2FF4', 'catalog'),
('TOYOTA_RAV4_TSS2', '2FF4', 'catalog'),
('TOYOTA_CAMRY', '2FF4', 'catalog'),
('TOYOTA_CHR', '2FF4', 'catalog'),
('TOYOTA_CHR_TSS2', '2FF4', 'catalog'),
('TOYOTA_RAV4_TSS2_2022', '2FF4', 'catalog'),
('TOYOTA_RAV4_TSS2_2023', '2FF4', 'catalog'),
('TOYOTA_PRIUS', '2FF4', 'catalog'),
('LEXUS_ES_TSS2', '2AA8', 'catalog'),
('LEXUS_IS_TSS2', '2AA8', 'catalog'),
('LEXUS_LC_TSS2', '2AA8', 'catalog'),
('LEXUS_NX_TSS2', '2AA8', 'catalog'),
('LEXUS_RC_TSS2', '2AA8', 'catalog'),
('LEXUS_RX_TSS2', '2AA8', 'catalog'),
('TOYOTA_ALPHARD_TSS2', '2AA8', 'catalog'),
('TOYOTA_AVALON_TSS2', '2AA8', 'catalog'),
('TOYOTA_CAMRY_TSS2', '2AA8', 'catalog'),
('TOYOTA_COROLLA_TSS2', '2AA8', 'catalog'),
('TOYOTA_HIGHLANDER_TSS2', '2AA8', 'catalog'),
('TOYOTA_MIRAI', '2AA8', 'catalog'),
('TOYOTA_PRIUS_TSS2', '2AA8', 'catalog'),
('TOYOTA_RAV4_TSS2', '2AA8', 'catalog'),
('TOYOTA_CAMRY', '2AA8', 'catalog'),
('TOYOTA_CHR', '2AA8', 'catalog'),
('TOYOTA_CHR_TSS2', '2AA8', 'catalog'),
('TOYOTA_RAV4_TSS2_2022', '2AA8', 'catalog'),
('TOYOTA_RAV4_TSS2_2023', '2AA8', 'catalog'),
('TOYOTA_PRIUS', '2FF8', 'EPS73_8965B47070'),
('TOYOTA_PRIUS_RETROFIT', '2FF8', 'EPS73_8965B47070'),
('TOYOTA_PRIUS', '2FF4', 'EPS73_8965B47070'),
('TOYOTA_PRIUS_RETROFIT', '2FF4', 'EPS73_8965B47070'),
('LEXUS_CTH', 'camera343_or_4CB8', 'catalog'),
('LEXUS_ES', 'camera343_or_4CB8', 'catalog'),
('LEXUS_GS_F', 'camera343_or_4CB8', 'catalog'),
('LEXUS_IS', 'camera343_or_4CB8', 'catalog'),
('LEXUS_LS', 'camera343_or_4CB8', 'catalog'),
('LEXUS_NX', 'camera343_or_4CB8', 'catalog'),
('LEXUS_RC', 'camera343_or_4CB8', 'catalog'),
('LEXUS_RX', 'camera343_or_4CB8', 'catalog'),
('TOYOTA_AVALON', 'camera343_or_4CB8', 'catalog'),
('TOYOTA_AVALON_2019', 'camera343_or_4CB8', 'catalog'),
('TOYOTA_CAMRY', 'camera343_or_4CB8', 'catalog'),
('TOYOTA_CHR', 'camera343_or_4CB8', 'catalog'),
('TOYOTA_COROLLA', 'camera343_or_4CB8', 'catalog'),
('TOYOTA_HIGHLANDER', 'camera343_or_4CB8', 'catalog'),
('TOYOTA_MATRIX_RETROFIT', 'camera343_or_4CB8', 'catalog'),
('TOYOTA_PRIUS', 'camera343_or_4CB8', 'catalog'),
('TOYOTA_PRIUS_RETROFIT', 'camera343_or_4CB8', 'catalog'),
('TOYOTA_PRIUS_V', 'camera343_or_4CB8', 'catalog'),
('TOYOTA_RAV4', 'camera343_or_4CB8', 'catalog'),
('TOYOTA_RAV4H', 'camera343_or_4CB8', 'catalog'),
('TOYOTA_SIENNA', 'camera343_or_4CB8', 'catalog'),
]
def sources(identity, topology, rack):
fp = bypass_fingerprint(identity) if topology == 'camera343_or_4CB8' else {0: {0x260: 8, 0x262: 8, 0x1D2: 8, 0x1D3: 8, 0x224: 8, 0x226: 8}, 1: {}, 2: {}}
if topology in ('2FF8', '2FF4', '2AA8'):
fp[0][0x2AA if topology == '2AA8' else 0x2FF] = 4 if topology == '2FF4' else 8
if identity in dsu_bypass.PROFILES:
fp[0][0x262] = 8 if identity in dsu_bypass.EPS8_CARS or identity == CAR.TOYOTA_PRIUS else 5
if rack == 'EPS73_8965B47070':
fp[0][0x262] = 8
fw = acquired(identity)
if rack == 'EPS73_8965B47070':
for row in fw:
if row.ecu == structs.CarParams.Ecu.eps:
row.fwVersion = b'8965B47070' + bytes(6)
return fp, fw
@pytest.mark.parametrize('name,topology,rack', ROWS)
@pytest.mark.parametrize('stock', (False, True))
@pytest.mark.parametrize('alpha_long', (False, True))
def test_all_parent_tunes_native_projection_and_stock_restore(name, topology, rack, stock, alpha_long):
identity = getattr(CAR, name)
fp, fw = sources(identity, topology, rack)
parent = CarInterface.get_params(identity, fp, fw, alpha_long, False, False)
child_fp = {bus: dict(frames) for bus, frames in fp.items()}
child_fp[0][0x201] = 6
cp = CarInterface.get_params(identity, child_fp, fw, alpha_long, False, False)
assert pedal_composite.configured(cp) and qualified(cp)
assert cp.flags & ToyotaFlags.GAS_INTERCEPTOR
assert cp.minEnableSpeed == -1.
projected = pedal_composite.parent_cp(cp)
assert projected.safetyConfigs[0].safetyParam == parent.safetyConfigs[0].safetyParam
for field in (
'lateralTuning', 'longitudinalTuning', 'steerActuatorDelay', 'steerLimitTimer', 'longitudinalActuatorDelay',
'minSteerSpeed', 'wheelSpeedFactor', 'mass', 'wheelbase', 'steerRatio', 'centerToFront', 'autoResumeSng',
):
assert cp.to_dict()[field] == parent.to_dict()[field], field
if stock:
assert pedal_composite.prepare_stock(cp)
assert pedal_composite.configured(cp) and qualified(cp) and not cp.openpilotLongitudinalControl
assert cp.safetyConfigs[0].safetyParam == (parent.safetyConfigs[0].safetyParam | 0x2200)
@pytest.mark.parametrize('name,topology,rack', ROWS)
def test_dom_low_speed_entry_requires_qualified_pedal(name, topology, rack):
identity = getattr(CAR, name)
fp, fw = sources(identity, topology, rack)
base = CarInterface.get_params(identity, fp, fw, True, False, False)
fp[0][0x201] = 6
cp = CarInterface.get_params(identity, fp, fw, True, False, False)
assert pedal_composite.configured(cp) and cp.minEnableSpeed == -1.
for field in ('lateralTuning', 'longitudinalTuning', 'longitudinalActuatorDelay', 'stopAccel'):
assert cp.to_dict()[field] == base.to_dict()[field], field
fp[0][0x201] = 7
rejected = CarInterface.get_params(identity, fp, fw, True, False, False)
assert not pedal_composite.configured(rejected)
assert not rejected.flags & ToyotaFlags.GAS_INTERCEPTOR
def test_shared_hold_car_mappings():
from opendbc.car.toyota.interface import apply_toyota_auto_hold
from opendbc.car.toyota.values import TOYOTA_AUTO_HOLD_CARS, uses_toyota_auto_hold_aeb
for name, topology, rack in ROWS:
identity = getattr(CAR, name)
if identity not in TOYOTA_AUTO_HOLD_CARS:
fp, fw = sources(identity, topology, rack)
fp[0][0x201] = 6
rejected = CarInterface.get_params(identity, fp, fw, True, False, False)
assert not apply_toyota_auto_hold(rejected, True)
continue
for has_pedal in (False, True):
fp, fw = sources(identity, topology, rack)
if has_pedal:
fp[0][0x201] = 6
cp = CarInterface.get_params(identity, fp, fw, True, False, False)
original = cp.to_dict()
assert apply_toyota_auto_hold(cp, True), (name, topology, has_pedal)
permission = 256 if uses_toyota_auto_hold_aeb(cp) else 128
assert cp.alternativeExperience & (128 | 256) == permission
assert qualified(cp)
for key in ('lateralTuning', 'longitudinalTuning', 'longitudinalActuatorDelay', 'stopAccel'):
assert cp.to_dict()[key] == original[key]
assert not apply_toyota_auto_hold(cp, False)
assert not cp.flags & ToyotaFlags.AUTO_BRAKE_HOLD
from opendbc.car.toyota.pedal import CAMERA_PEDAL_CARS
for identity in CAMERA_PEDAL_CARS & TOYOTA_AUTO_HOLD_CARS:
fp, fw = sources(identity, 'standalone2016', 'catalog')
fp[0][0x201] = 6
cp = CarInterface.get_params(identity, fp, fw, True, False, False)
assert apply_toyota_auto_hold(cp, True), identity
assert qualified(cp)
@@ -217,7 +217,7 @@ def control_inputs(controls, published, state, sd_events, native, now):
if name == 'modelV2':
v.from_dict(model().to_dict())
elif name == 'lateralManeuverPlan':
v.desiredCurvature = .00005
v.desiredCurvature = .0002 if controls.CP.steerControlType == structs.CarParams.SteerControlType.angle else .00005
elif name == 'vehicleParameters':
v.stiffnessFactor, v.steerRatio = 1.0, controls.CP.steerRatio
elif name == 'longitudinalPlan':
@@ -232,7 +232,7 @@ def run_case(stock, scenario='nominal', *, aol=True, candidate=CAR.TOYOTA_RAV4H,
sdsu_words=(0x9049, 0x9249), alpha_long=False, disable_setting=None, physical_frames=None, angle=False,
firmware_override=None, assert_hybrid_release=False, sdsu_mirror=False, on_sample=None, camera_messages=False, filter_advert=False,
brake_pause_mps=None, native_rx_expected=None, on_state=None, fingerprint_frames=None, manual_selection=False, native_tx_expected=None,
manual_filter_length=None, manual_bypass=False, bypass_owner=False):
manual_filter_length=None, manual_bypass=False, bypass_owner=False, manual_pedal=False, auto_hold=False):
SYNTHETIC_LAST.clear()
NATIVE_LAST.clear()
safety = libsafety_py.libsafety
@@ -245,14 +245,23 @@ def run_case(stock, scenario='nominal', *, aol=True, candidate=CAR.TOYOTA_RAV4H,
('AlwaysOnLateral', aol),
('DisableOpenpilotLongitudinal', stock if disable_setting is None else disable_setting),
('AlphaLongitudinalEnabled', alpha_long),
('ToyotaAutoHold', False),
('ToyotaAutoHold', auto_hold),
):
params.put_bool(k, v, block=True)
if brake_pause_mps is not None:
params.put('AolBrakePauseSpeedMps', float(brake_pause_mps), block=True)
fw = firmware(candidate) if firmware_override is None else firmware_override
if manual_selection:
if manual_bypass:
if manual_pedal:
from opendbc.car.toyota import pedal_composite
assert candidate in (CAR.TOYOTA_PRIUS, CAR.TOYOTA_PRIUS_RETROFIT, CAR.TOYOTA_MATRIX_RETROFIT)
assert fingerprint_frames is not None
acquired_fp = gen_empty_fingerprint()
for address, data, bus in fingerprint_frames:
acquired_fp[bus][address] = len(data)
assert acquired_fp[0].get(0x201) == 6
assert pedal_composite.hardware_supported(candidate, acquired_fp, fw)
elif manual_bypass:
assert fingerprint_frames is not None
assert candidate in (CAR.TOYOTA_MATRIX_RETROFIT, CAR.TOYOTA_PRIUS_RETROFIT) and bypass_owner
assert any(bus == 2 and address in (0x343, 0x4CB) and len(data) == 8 for address, data, bus in fingerprint_frames)
@@ -302,7 +311,8 @@ def run_case(stock, scenario='nominal', *, aol=True, candidate=CAR.TOYOTA_RAV4H,
host = card_module.Car()
assert host.CP.openpilotLongitudinalControl == (not stock)
assert host.CP.safetyConfigs[0].safetyParam == sdsu_words[stock]
assert host.CP.alternativeExperience == 32
from opendbc.car.toyota.values import uses_toyota_auto_hold_aeb
assert host.CP.alternativeExperience == (32 | ((256 if uses_toyota_auto_hold_aeb(host.CP) else 128) if auto_hold else 0))
controls, sd = Controls(), sd_module.SelfdriveD(CP=host.CP)
assert controls.CP.to_dict() == host.CP.to_dict()
safety.init_tests()
@@ -357,7 +367,7 @@ def run_case(stock, scenario='nominal', *, aol=True, candidate=CAR.TOYOTA_RAV4H,
)
try:
duration = {
'nominal': 251, 'physical': 601, 'faults': 801, 'bad_dlc': 801,
'hold': 501, 'nominal': 251, 'physical': 601, 'faults': 801, 'bad_dlc': 801,
'off': 401, 'cold_low': 251, 'hybrid_stop': 251, 'main_lease': 501, 'identity_refusal': 501,
}[scenario]
for tick in range(1, duration):
@@ -541,7 +551,7 @@ def run_case(stock, scenario='nominal', *, aol=True, candidate=CAR.TOYOTA_RAV4H,
}
)
nominal = tick >= 220 and (
scenario in ('nominal', 'cold_low', 'hybrid_stop')
scenario in ('nominal', 'cold_low', 'hybrid_stop') or scenario == 'hold' and tick < 250
or scenario == 'identity_refusal' and tick < 250
or scenario == 'main_lease' and (tick < 250 or tick >= 480)
or scenario == 'off'
@@ -583,9 +593,11 @@ def run_case(stock, scenario='nominal', *, aol=True, candidate=CAR.TOYOTA_RAV4H,
assert not host.CP.openpilotLongitudinalControl and not cc.longActive
assert host.CP.safetyConfigs[0].safetyParam == sdsu_words[1]
else:
preference = host.CI.CC.bypass_input if bypass_owner else host.CI.CC.prius_filter_input if candidate == CAR.TOYOTA_PRIUS else (
from opendbc.car.toyota import pedal_composite
preference = (host.CI.CC.pedal_input if pedal_composite.configured(host.CP) else
host.CI.CC.bypass_input if bypass_owner else host.CI.CC.prius_filter_input if candidate == CAR.TOYOTA_PRIUS else (
host.CI.CC.advert_filter_input if filter_advert or fingerprint_frames is not None and any(
address == 0x2AA for address, _, _ in fingerprint_frames) else host.CI.CC.rav4h_filter_input)
address == 0x2AA for address, _, _ in fingerprint_frames) else host.CI.CC.rav4h_filter_input))
assert preference is not None and not preference.update(time.monotonic_ns())
for f in outgoing_frames:
if f.address == 0x343:
+1 -1
View File
@@ -1 +1 @@
{"protected_inventory_sha256": "2ee01a31422021061a0529083c7b434e52f1f6dd44d684ec0921074808613513", "schema_version": 1}
{"protected_inventory_sha256": "6b9f162e57c2f68775793717e2f9e4a44f209169384c47a934c2033cd898668a", "schema_version": 1}
+6
View File
@@ -45,6 +45,9 @@ AOL_LIFECYCLE_TARGETS = (
'openpilot/starpilot/car/toyota/tests/test_dsu_bypass.py',
'openpilot/starpilot/car/toyota/tests/test_dsu_bypass_callers.py',
'opendbc_repo/opendbc/safety/tests/test_toyota_dsu_bypass.py',
'openpilot/starpilot/car/toyota/tests/test_pedal_parent_configurations.py',
'openpilot/starpilot/car/toyota/tests/test_pedal_parent_callers.py',
'opendbc_repo/opendbc/safety/tests/test_toyota_pedal_parent.py',
'opendbc_repo/opendbc/safety/tests/test_toyota_radar_lta_pedal.py',
'opendbc_repo/opendbc/safety/tests/test_toyota_prius_retrofit_advert.py',
'openpilot/starpilot/aol/tests/test_crossmake_native_admission.py',
@@ -252,6 +255,9 @@ RELEASE_TARGETS = (
'openpilot/starpilot/car/toyota/tests/test_dsu_bypass.py',
'openpilot/starpilot/car/toyota/tests/test_dsu_bypass_callers.py',
'opendbc_repo/opendbc/safety/tests/test_toyota_dsu_bypass.py',
'openpilot/starpilot/car/toyota/tests/test_pedal_parent_configurations.py',
'openpilot/starpilot/car/toyota/tests/test_pedal_parent_callers.py',
'opendbc_repo/opendbc/safety/tests/test_toyota_pedal_parent.py',
'opendbc_repo/opendbc/safety/tests/test_toyota_radar_lta_pedal.py',
'opendbc_repo/opendbc/safety/tests/test_toyota_prius_retrofit_advert.py',
'opendbc_repo/opendbc/car/hyundai/tests/test_long_cp_copy.py',