mazda: KE support — platform, foreign-radar vision-only, car picker fix - #10
Conversation
The KE chassis (2012-16 CX-5, incl. the 2016.5 mid-year refresh) with its stock G46L radar. The platform claims no radar bus: the G46L does not put the 0x361-0x366 tracks on bus 0, so the lead comes from vision and the radar DBC stays unset. EPS swaps are common on these bodies (the 2022 CX-5 EPS is what unlocks steer-to-zero), so the FW_VERSIONS entry carries no EPS firmware on purpose: swap firmware belongs to MAZDA_CX5_2022 and STEER_TO_ZERO_EPS_FW, not the chassis.
VIN years C-G name the platform, the 2016.5 firmware set exact-matches on the body ECUs alone, and dealer-updated ECUs still name by VIN through the donor EPS. The platform runs vision-only under a swap and never offers alpha long; docs build without firmware.
The pre-2022 CX-5 racks run the 2022's 18.1 ratio (same hardware), and the KE platform mass is 3433 lb from the platform-table research.
The CX-9 2021 entry is the pattern: seeds learned under a donor EPS apply only when the interface detects it, and requires_steer_to_zero withholds them on the stock EPS's flat 800-count scale. The KE table copies the CX-5 2022 values unchanged, since the donor EPS is the EPS those bins were learned under and no KE has its own fit yet; seed_version mirrors the source table.
The pre-2022 CX-5 racks now run the 2022's 18.1 steerRatio, so the ratio assertion no longer separates the platforms; mass and tireStiffnessFactor do.
… check A talking radar whose firmware no platform lists sends no tracks we can parse. Behind a platform bundle that claims a radar bus (an EPS-swapped older body carrying a forward bundle), radard starved on radarTracks and selfdrived raised commIssue for the whole drive. - radarUnavailable: platform claim OR foreign radar firmware; a silent radar keeps the claim - alpha availability decoupled from radarUnavailable: offered where the platform radar speaks the 2022 family dialect or the detected radar is the G46L whose replay exists - port the G46L teardown dialect from mazda-alpha-long-ke: flag, firmware set, static-only radar frames, safety capture - warn when a fixed platform bundle contradicts the VIN's platform (platform_from_vin over platform VIN metadata)
Docs mode runs with empty car_fw, so every Mazda outside the factory steer-to-zero pair resolved dashcamOnly, and the car-list generator skips dashcamOnly platforms: CX-5 KE, CX-5 2017-21, CX-9 2016-20 (and Mazda 3/6) were unselectable. dashcamOnly is a measured-hardware call, so docs mode now keeps the default and the on-device EPS check keeps the gate; regenerate car_list.json (380 -> 385 platforms).
The G46L facts were told at six production sites. The fw-set definition now carries the identity story and the null-strip matching, the detection and availability sites keep only their local why, the controller note drops, and the mazdacan constant's comment absorbs the lead-on-CRZ_CTRL clause so the branch note can go. The VIN swap rationale lives in platform_from_vin's docstring alone. No behavior change.
The G46L replay was a special case threaded through four files: a bare fw set, a flag bit, a hardcoded capture, and a g46l= boolean plumbed through the controller. REPLAY_RADAR_DIALECTS now registers each replayable radar in one place (name, firmware, flag, sends_tracks), mazdacan's capture table keys off the dialect object, and the interface resolves the detected radar through the registry. Adding a dialect is data plus captures; a consistency test pins that every dialect claims an unclaimed single bit, stays off the track set, and has its capture registered. That test forced a flag fix: rebasing onto the danger-unstable promotion had left LEGACY_FW_EPS and G46L_RADAR both on bit 4. Latent (the dialect bit is only read behind the steer-to-zero precondition), but every legacy-firmware car read as carrying the G46L dialect. G46L_RADAR moves to bit 8, and mazdaRadarVerdict names the resolved dialect instead of a boolean.
sends_tracks was decorative; the replay-shape test makes it the promise it names: every static-only dialect replays exactly its registered capture, whatever the lead. The consistency test also pins that dialect firmware sets stay pairwise disjoint — two dialects listing the same string would make resolution silently pick the first. And the safety capture test now iterates RADAR_STATIC_CAPTURES through mazda_rx_hook, so a dialect registered without its mazda.h mirror goes red by name.
One stale clause fixed: the registry recipe still told the reader to mirror captures in the safety tests, which the registry-driven test now does by itself. The G46L identity facts consolidate into the registry entry (the no-counter, no-checksum nature of its frame moves there), and the per-site comments shrink to their local why. Test names carry what test names can.
|
The three red checks are inherited from
AI UsageDisclaimer: GLM-5.3 by Z.ai was used to help develop, debug, and document this submission. All changes were reviewed and validated by a human. |
There was a problem hiding this comment.
Thanks for the detailed writeup and road data. I ran the branch from a clean build:
- Mazda + SP car/safety tests: 728 passed, 0 failed. The 5 failures you saw appear local.
- Remaining
opendbc/car/tests: 508 passed - MISRA: clean
- No new dash alerts on a listed 2022 CX-5.
- The steer ratio change looks good; 18.1 should remain for all CX-5s.
- The
mazda.hchange only widens the0x499whitelist.
Requesting changes on one regression and two simplifications.
1. Unknown radar firmware should not disable radar
The current foreign_radar logic treats any firmware missing from TRACK_RADAR_FW as track-less.
MAZDA_CX5_2022 only lists K131-67XK2-F, so a valid 2022-25 CX-5 with a newer radar revision can fuzzy-match or be manually selected and silently become vision-only.
I reproduced this with K131-67XK2-G:
radarUnavailable = TrueThat is especially risky because radar firmware is excluded from fuzzy matching.
The classification is also inconsistent: CX-9 2016-20 radar firmwares are in TRACK_RADAR_FW, even though that platform is documented as not publishing 0x361-0x366.
Please invert this: only special-case radars known not to provide the normal tracks.
ret.radarUnavailable = Bus.radar not in DBC[candidate] or g46lThen remove TRACK_RADAR_FW and update the unknown-radar test accordingly.
This also avoids relying on firmware discovered by another brand's query; the scan currently does not filter fw.brand.
2. The radar registry is too much abstraction for one case
RadarDialect, REPLAY_RADAR_DIALECTS, RADAR_STATIC_CAPTURES, sends_tracks, and the registry tests add a lot of structure for one special radar.
sends_tracks also does not currently affect production behavior.
I would go back to the simpler shape:
G46L_RADAR_FW = {...}
MazdaFlags.G46L_RADAR
create_radar_frames(..., g46l)If a second radar dialect appears later, that is the right time to introduce a registry.
3. Keep VIN matching inside Mazda
platform_from_vin in opendbc/car/values.py adds generic code for Mazda-specific behavior and duplicates the loop already in match_fw_to_car_fuzzy.
Please factor the shared VIN matching into mazda/values.py and reuse it from:
match_fw_to_car_fuzzy- Mazda
_get_params_spfor the selected-car/VIN mismatch warning
CP.carVin and CP.fingerprintSource are already available there, so car_helpers.py does not need to change.
This also fixes the current check missing the FINGERPRINT env path.
Minor
- Drop or downgrade
carlog.info("mazdaRadarVerdict"); it fires during tests/docs. - The
if not docs:dashcam gate looks good. car_list.jsononly adds the expected Mazda entries.
Looks good
The rest looks sound:
- KE follows the existing CX-9 2016-20 PT-only pattern.
RadarInterfacecorrectly honorsradarUnavailable.- Exact matching with a donor EPS works.
- A 2022 CX-5 cannot exact-match as KE.
- Flag bit 8 is unused.
- The KE torque table matches CX-5 2022 and is correctly gated by
requires_steer_to_zero.
|
Thanks for the review and the clean-build verification — 728/0 confirms my five failures were local.
AI UsageDisclaimer: GLM-5.3 by Z.ai was used to help develop, debug, and document this submission. All changes were reviewed and validated by a human. |
… in mazda Per review: an unlisted newer revision of a working radar must not silently lose its tracks, so radarUnavailable now keys on the platform's bus claim or the G46L alone, and TRACK_RADAR_FW is gone. The registry reverts to the simple G46L_RADAR_FW set, flag and g46l kwarg (bit 8 kept; a one-line test pins that no other single-bit flag shares it — that assertion caught the LEGACY_FW_EPS/bit-4 collision). VIN matching consolidates into mazda/values.py: platform_from_vin serves match_fw_to_car_fuzzy and the mismatch warning, which moves to _get_params_sp off carVin and fingerprintSource, covering the FINGERPRINT env path; the generic helper and the car_helpers hook are deleted. mazdaRadarVerdict downgraded to debug.
Both files are byte-identical to develop again; they leave the PR diff.
Bump opendbc to the zoompilot/opendbc#10 merge.
Summary
One support case drives this PR: a 2016 KE body (2012-16 CX-5, incl. the 2016.5 refresh) with a swapped 2022 EPS and its stock G46L radar, held on the CX-5 2022 platform by a carried-forward bundle. The G46L answers the firmware query but never puts the 0x361-0x366 tracks on bus 0, so radard starved behind a parser that never went valid and the device raised commIssue through whole drives.
MAZDA_CX5_2022andSTEER_TO_ZERO_EPS_FW, not the chassis. Includes the corrected steer ratio (the pre-2022 racks run the 2022's 18.1), torque seeds, and tests.radarUnavailablewhen the platform's DBC claims no radar bus, or the detected radar is the G46L: the one radar known never to publish 0x361-0x366 on bus 0. Any other radar keeps the platform's word, so an unlisted newer revision of a working radar (e.g. aK131-67XK2-Gon a 2022 CX-5) loses nothing — per review, this inverts the first draft's unlisted-implies-track-less rule. The G46L's own dialect is what the teardown replays.platform_from_vininmazda/values.py(shared withmatch_fw_to_car_fuzzy) cross-checks the selected bundle from_get_params_sp; a mismatch logsplatformBundleVinMismatch. Alpha-long availability: steer-to-zero EPS AND (a claimed radar bus OR the detected G46L).car_list.jsonis generated in docs mode with an empty firmware list, so every firmware-gated Mazda resolved dashcamOnly and the generator skipped it: ondeveloptoday the CX-5 2017-21, CX-9 2016-20, Mazda 3 and Mazda 6 are hidden from the picker. The fix gates the verdict withif not docs:and regenerates the JSON; on-device behavior is unchanged.Reviewer notes
Rebased across the danger-unstable promotion (
676fa14b). Its flag split —EPS_HW(measured envelope) /STEER_TO_ZERO_EPS(firmware scale + latch) /LEGACY_FW_EPS(floor) — is kept, withG46L_RADARadded alongside; the controller ends witheps_2022,steer_to_zeroandg46l. The promotion's set-based EPS detection with the empty-query fallback, and its unconditionalsteerActuatorDelay = 0.14, win over the branch's older versions.interface.pyis the union of the two; both new test classes are kept. During development a dialect registry briefly generalized the G46L replay; its uniqueness test caught a latent bug the rebase had introduced (LEGACY_FW_EPSandG46L_RADARboth on bit 4) before the registry itself was reverted per review — bit 8 and a one-line unshared-bit assertion are what remain, andmazdaRadarVerdictlogs at debug level.Follow-ups
This PR is independent and mergeable on its own. The zoompilot-side companion (the docs for the foreign-radar rule and the G46L dialect, the param-change logging, and the submodule bump) follows in zoompilot/zoompilot once this merges — it pins the merged submodule SHA, so it cannot open earlier.
Testing
Mazda suite +
test_car_listat the tip: 430 passed, 5 failed (the safety file separately: 268 passed, all capture tests included) — all the known local panda-version artifact, byte-identical to pristinedevelop. CI runs the real suite. Road-verified on the swapped car (dongle d057d702, this code at the fork'se9b94b2):radarUnavailabletrue, 1081 radarTracks messages where the broken build had zero, radarState valid from 108.6 s, commIssue gone except the two-second boot warmup. After the fix shipped in the fork, the picker on the support user's device listedMazda CX-5 2012-16.Alpha-long teardown, road-verified on the same car (separate drive, build
e9b94b2, 61 s with 11 s of standstill and resume): the param stuck across the cycle; the G46L was silenced by a single UDS session request at 13.4 s; tester-present held it silent at 2 Hz through route end (47 s, no gap near the 5 s S3 timeout); the synthetic replay ran at exact rates (0x499 at 10 Hz, CRZ frames at 50 Hz) in the G46L's own capture bytes on both buses, with the camera never seeing a frame gap through the handover.radarStatevalid from vision throughout, commIssue only in the boot-warmup window, and no camera or SCBS faults. The hand-back path (disable mid-drive) is the one remaining piece with unit tests only.AI Usage
Disclaimer: GLM-5.3 by Z.ai was used to help develop, debug, and document this submission. All changes were reviewed and validated by a human.