diff --git a/opendbc_repo/opendbc/car/toyota/radar_filter.py b/opendbc_repo/opendbc/car/toyota/radar_filter.py index 9379d0cdf3..9acb41f0de 100644 --- a/opendbc_repo/opendbc/car/toyota/radar_filter.py +++ b/opendbc_repo/opendbc/car/toyota/radar_filter.py @@ -13,11 +13,11 @@ PROFILES = { } -def _camry_radar_bus(candidate, bus, messages): - # The 2018–20 Camry exposes an independent eight-byte 2FF stream alongside +def _cluster_radar_bus(candidate, bus, messages): + # The 2018–20 Camry and 2017–20 C-HR expose an independent eight-byte 2FF stream alongside # its six cluster-radar frames on bus1 (cluster_radar.CLUSTERS). It is not # the four-byte filter advertisement or a bus0 smartDSU status source. - return (candidate == CAR.TOYOTA_CAMRY and bus == 1 and messages.get(0x2FF) == 8 and + return (candidate in (CAR.TOYOTA_CAMRY, CAR.TOYOTA_CHR) and bus == 1 and messages.get(0x2FF) == 8 and all(messages.get(address) == 8 for address in range(0x680, 0x686))) @@ -29,12 +29,12 @@ def hardware_supported(candidate, fingerprint): # Panda discovery may also expose its forwarded camera-bus copy. if (candidate in PROFILES and fingerprint.get(0, {}).get(0x2FF) == 4 and not any(address in messages for messages in fingerprint.values() for address in (0x201, 0x2AA)) and - all((bus in (0, 2) and messages[0x2FF] == 4) or _camry_radar_bus(candidate, bus, messages) + all((bus in (0, 2) and messages[0x2FF] == 4) or _cluster_radar_bus(candidate, bus, messages) for bus, messages in fingerprint.items() if 0x2FF in messages)): return True return (candidate in PROFILES and fingerprint.get(0, {}).get(0x2AA) == 8 and all(bus in (0, 2) and frames[0x2AA] == 8 for bus, frames in fingerprint.items() if 0x2AA in frames) and - not any(0x201 in frames or 0x2FF in frames and not _camry_radar_bus(candidate, bus, frames) + not any(0x201 in frames or 0x2FF in frames and not _cluster_radar_bus(candidate, bus, frames) for bus, frames in fingerprint.items())) diff --git a/openpilot/starpilot/car/toyota/tests/test_camry_chr_filter_callers.py b/openpilot/starpilot/car/toyota/tests/test_camry_chr_filter_callers.py index b86de9cf8f..2912ace919 100644 --- a/openpilot/starpilot/car/toyota/tests/test_camry_chr_filter_callers.py +++ b/openpilot/starpilot/car/toyota/tests/test_camry_chr_filter_callers.py @@ -11,3 +11,11 @@ daemon_gc_scope = helpers.daemon_gc_scope @pytest.mark.parametrize('aol', [False, True]) def test_camry_chr_filter_actual_callers(candidate, alpha, disable, aol, tmp_path): helpers.run_case(candidate, alpha, disable, 0, tmp_path, aol=aol) + + +@pytest.mark.parametrize('alpha,disable', [(False, False), (True, False), (True, True)]) +@pytest.mark.parametrize('aol', [False, True]) +def test_chr_filter_with_independent_cluster_radar_actual_callers(alpha, disable, aol, tmp_path): + advertisements = [(0x2FF, bytes(4), 0), (0x2FF, bytes(4), 2), (0x2FF, bytes(8), 1)] + advertisements.extend((address, bytes(8), 1) for address in range(0x680, 0x686)) + helpers.run_case(CAR.TOYOTA_CHR, alpha, disable, 0, tmp_path, aol=aol, filter_advertisements=advertisements) diff --git a/openpilot/starpilot/car/toyota/tests/test_camry_filter_radar_bus.py b/openpilot/starpilot/car/toyota/tests/test_camry_filter_radar_bus.py index f3889d1ed1..5c0a1252b8 100644 --- a/openpilot/starpilot/car/toyota/tests/test_camry_filter_radar_bus.py +++ b/openpilot/starpilot/car/toyota/tests/test_camry_filter_radar_bus.py @@ -1,4 +1,4 @@ -"""Camry cluster-radar traffic must not impersonate a bus-0 filter status.""" +"""Camry/C-HR cluster-radar traffic must not impersonate a bus-0 filter status.""" import pytest from opendbc.car import gen_empty_fingerprint from opendbc.car.toyota import radar_filter @@ -15,27 +15,28 @@ def observed(): return fp +@pytest.mark.parametrize('candidate', (CAR.TOYOTA_CAMRY, CAR.TOYOTA_CHR)) @pytest.mark.parametrize('alpha', (False, True)) @pytest.mark.parametrize('primary', (0x2FF, 0x2AA)) -def test_camry_radar_bus_preserves_exact_filter_owner(alpha, primary): +def test_camry_radar_bus_preserves_exact_filter_owner(candidate, alpha, primary): fp = observed() if primary == 0x2AA: fp[0] = fp[2] = {primary: 8} canonical = gen_empty_fingerprint() canonical[0][primary] = 4 if primary == 0x2FF else 8 - expected = CarInterface.get_params(CAR.TOYOTA_CAMRY, canonical, [], alpha, False, False) - actual = CarInterface.get_params(CAR.TOYOTA_CAMRY, fp, [], alpha, False, False) - assert radar_filter.hardware_supported(CAR.TOYOTA_CAMRY, fp) + expected = CarInterface.get_params(candidate, canonical, [], alpha, False, False) + actual = CarInterface.get_params(candidate, fp, [], alpha, False, False) + assert radar_filter.hardware_supported(candidate, fp) assert actual.to_dict() == expected.to_dict() assert actual.safetyConfigs[0].safetyParam == (0x1049 if alpha else 0x1249) assert actual.openpilotLongitudinalControl == alpha and qualified(actual) +@pytest.mark.parametrize('candidate', (CAR.TOYOTA_CAMRY, CAR.TOYOTA_CHR)) @pytest.mark.parametrize('bad', ('missing_filter', 'bus1_short', 'missing_cluster', 'bad_cluster', 'wrong_cluster_bus', 'wrong_model', 'bus1_advert', 'mixed_status', 'pedal')) -def test_camry_radar_bus_is_not_general_adapter_evidence(bad): +def test_camry_radar_bus_is_not_general_adapter_evidence(candidate, bad): fp = observed() - candidate = CAR.TOYOTA_CAMRY if bad == 'missing_filter': fp[0].clear() elif bad == 'bus1_short': @@ -47,7 +48,7 @@ def test_camry_radar_bus_is_not_general_adapter_evidence(bad): elif bad == 'wrong_cluster_bus': fp[3] = fp.pop(1) elif bad == 'wrong_model': - candidate = CAR.TOYOTA_CHR + candidate = CAR.TOYOTA_CHR_TSS2 elif bad == 'bus1_advert': fp[1][0x2FF] = 4 elif bad == 'mixed_status': diff --git a/prebuilt.json b/prebuilt.json index d4fd58bbcb..9745dd12e1 100644 --- a/prebuilt.json +++ b/prebuilt.json @@ -1 +1 @@ -{"protected_inventory_sha256": "dc0fc34a78b6ecec51ba5a4ecfd601088ed237535b321ef878019980d3b8b465", "schema_version": 1} +{"protected_inventory_sha256": "7769f133116304f49b7b3419263f618e02451e31af54f2dc3354feea9e76cb16", "schema_version": 1}