Ford: read TSR speed limit on Q3 (CAN) cars, not just Q4 (CAN FD)#160
Open
jrneulight wants to merge 1 commit into
Open
Ford: read TSR speed limit on Q3 (CAN) cars, not just Q4 (CAN FD)#160jrneulight wants to merge 1 commit into
jrneulight wants to merge 1 commit into
Conversation
Speed limit was gated behind FordFlags.CANFD in three places, so Q3 Fords (e.g. Explorer MK6) never populated carStateSP.speedLimit even though their IPMA camera broadcasts the same Traffic_RecognitnData message the CAN FD cars read. Confirmed on a 2021 Explorer over two rlog routes: msg 973 (Traffic_RecognitnData) is present on the camera bus, and its TsrVLim1MsgTxt_D_Rq / TsrVlUnitMsgTxt_D_Rq signals decode cleanly to 45 mph and 65 mph respectively, using the identical DBC (ford_lincoln_base_pt) both generations already share. Driving the real CarState.update() pipeline over both routes with this change yields speedLimit = 45 / 65 mph, matching the raw decode. Changes: - Register Traffic_RecognitnData on the Q3 camera bus. Marked non-critical (nan frequency, matching the BCM/HEV overlay convention) because TSR is an optional Co-Pilot360 camera feature: trims without it never send the message, and it must not invalidate the rest of carState. Its signals default to 0/255, which update_traffic_signals already maps to "no limit". - Drop the CANFD gate on the ret_sp.speedLimit assignment in carstate. - Drop the CANFD early-return in update_traffic_signals; the existing decode body (unit from TsrVlUnitMsgTxt_D_Rq within the message, skip on 0/255) works unchanged for both generations. IPMA_Data2 stays CAN FD-only and is not needed for the TSR path since the unit rides inside msg 973 itself. The speed-limit resolver reads sm['carStateSP'].speedLimit directly and is car-agnostic, so populating the field is sufficient to feed Speed Limit Assist.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Read the posted speed limit from the IPMA traffic-sign-recognition broadcast on Q3
(CAN) Fords, not just Q4 (CAN FD). No new signals, no DBC changes, no behavior change on
cars that don't broadcast it.
The evidence that motivated this
Speed limit never populated on a Q3 Ford (e.g. Explorer MK6):
carStateSP.speedLimitsat at 0 for an entire highway drive. The feature was gated behind
FordFlags.CANFDinthree places, so the whole TSR path was a dead branch on CAN cars — not a decode bug, no
implementation at all.
But the data is on the wire. Scanning rlogs from a 2021 Explorer,
Traffic_RecognitnData(CAN msg 973) is broadcast on the camera bus (bus 2, plus 0/128), and its speed-limit
signals decode cleanly with the DBC (
ford_lincoln_base_pt) both generations alreadyshare:
TsrVLim1MsgTxt_D_RqTsrVlUnitMsgTxt_D_Rq00000031--71********0000003b--f0********Two independent drives, two different posted limits, both mph, both sane against the ~54–64
mph vEgo — this is a live TSR feed the whole drive, not a stray frame. The IPMA camera
absolutely sends speed limit on Q3; only the code path refused to read it.
Why the fix is shaped this way
Traffic_RecognitnDatajoins the Q3 camera parser atfloat('nan')frequency — theBCM_Lamp_Stat_FD1/ HEV-overlay convention — because TSRis an optional Co-Pilot360 camera feature. Trims without it simply never broadcast the
message, and it must never invalidate the rest of
carState. Its signals default to0/255, which
update_traffic_signalsalready maps to "no limit", so absent hardwareyields 0 cleanly.
(
TsrVlUnitMsgTxt_D_Rq), so the CAN FD-onlyIPMA_Data2lookup isn't needed and staysCAN FD-only.
FordFlags.CANFDearly-return lets theexisting math (unit factor, skip on 0/255) run for both generations verbatim — the
identical logic that already ships for Q4.
The evidence afterwards
Driving the real
CarState.update()pipeline over both routes with this change:carStateSP.speedLimit(rounded)00000031--71********0000003b--f0********Matches the raw-CAN decode exactly. The speed-limit resolver reads
sm['carStateSP'].speedLimitdirectly and is car-agnostic, so populating the field issufficient to feed the
carsource for Speed Limit Assist.What each change is
opendbc/car/ford/carstate.py: registerTraffic_RecognitnDataon the non-CANFD camerabus (non-critical); drop the CANFD gate on the
ret_sp.speedLimitassignment.opendbc/sunnypilot/car/ford/carstate_ext.py: drop the CANFD early-return inupdate_traffic_signals; the decode body is unchanged. Docstring updated.Test it yourself
On a Q3 Ford with a Co-Pilot360 TSR camera: drive past a posted-limit sign and confirm
carStateSP.speedLimitreports the sign value; cross-check against raw CAN msg 973(
TsrVLim1MsgTxt_D_Rq× unit fromTsrVlUnitMsgTxt_D_Rq). Enable Speed Limit Assist with acar-source policy to see it consumed.
Risks / limits
carStateSP.speedLimitfeedsthe car-agnostic resolver (confirmed), but whether it renders also depends on Speed
Limit Mode / policy settings and the UI — untested here.
registration + the 0/255 default keep the path inert (no CAN-validity impact, speedLimit
stays 0). Verified in the DBC default handling, not yet on a non-TSR Q3 car.