Three independent changes bundled together.
Revert hyundai canfd steering torque limits to comma stock defaults
(270 / 2 / 3 / 112) in both panda safety and openpilot CarControllerParams.
The 270->324 bump caused overcorrection on turns and weaving on straights.
Web research turned up no public reports of any 4th gen Tucson NX4 owner
bumping STEER_MAX — the documented Tucson tuning effort is entirely on
lateralTuning (latAccelFactor ~2.9-3.1, friction ~0.095), not the cap.
hoomoose's EV6/Ioniq 5 PR #25723 is the canonical "raise STEER_MAX
without dropping latAccelFactor causes overcorrection" data point — and
even that change was reverted upstream. Right next move for this car is
to tune latAccelFactor / friction, not the torque ceiling.
plannerd: keep publishing longitudinalPlan at the normal cadence in park,
but skip update() compute. Skipping publishes entirely caused
longitudinalPlan to time out the alive flag at controlsd, which fired a
real commIssue ("not_alive") on park->drive. Stale published values are
fine because controlsd's own park short-circuit ignores the
longitudinalPlan content while parked. Also gate publish_ui_plan on
not-parked: it reads longitudinal_planner.a_desired_trajectory_full
which is only set inside update(), so calling it without a prior update
crashes plannerd with AttributeError (which fires "Process Not Running"
on screen). uiPlan is UI-only, not on controlsd's commIssue check list,
so going silent in park is fine.
frogpilot_process: same idea — keep publishing frogpilotPlan in park to
keep alive, skip the heavy update() compute.
dashcamd: close the trip immediately on gear shift to PARK (was: 10-min
idle timer before close). User wants the dashcam idle in park and a
fresh trip on every drive engagement; brief drive-thru / fuel-stop
across-trip continuity isn't valued.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Tucson (and other Hyundai CAN-FD HDA2 cars) get pinned to comma's
conservative steer ceiling of 270 in the CAN-FD branch of
selfdrive/car/hyundai/values.py and the matching panda safety limit
HYUNDAI_CANFD_STEERING_LIMITS. Comma's non-CAN-FD HKG default is 384;
PR commaai/openpilot#25723 merged 384 for HDA1 EV6/Ioniq 5 with
operator quote "max steer needed to be 384 to make basic turns."
Bumping to 324 (~+20%) keeps a safe margin under the proven 384
ceiling while giving enough headroom for moderate clover-style on-ramps
without the controller hitting the limit. Rate limits also nudged up
(2->3 up, 3->5 down) to match the slightly higher ceiling and reduce
ramp time / release lag; chose 5 instead of comma's 7 for delta_down to
keep release smoother. max_rt_delta scaled proportionally (112->134) so
the 250ms real-time check tracks the new ceiling.
Both files MUST stay in lockstep — panda safety enforces independently
and would reject larger commands if only one side was bumped. Panda
firmware re-flashes automatically on next pandad start because the
safety code hash changed.
References:
https://github.com/commaai/openpilot/pull/25723 (HDA1 270->384)
https://github.com/commaai/openpilot/issues/24122 (HKG torque blacklist)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replaces clearpilot's working state wholesale with the modelrevert branch's
tree (modelrevert tip cea422b). Discards the parked-controlsd manager-process
split and the two session READMEs that documented it; keeps the simpler
in-process park short-circuits (controlsd state_control, plannerd, frogpilot_process)
and the cached-output decimation (modeld, dmonitoringmodeld) that achieve
the same goal with less moving parts. Also brings in the locationd GPS
ignore, the calibrationd valid=calStatus gate, and the model-revert lineage's
controlsd / paramsd / torqued / events.py / carstate.py / interfaces.py.
This is a single new commit on clearpilot (no merge), so the branch advances
linearly while the file state matches modelrevert exactly.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Fan control rework (thermald → 4Hz):
- DT_TRML 0.5s → 0.25s (thermald loop + fan PID now at 4Hz)
- New clamp rules based on (gear, cruise_engaged, standstill):
parked → 0-100%
in drive + cruise engaged (any speed) → 30-100%
in drive + cruise off + standstill → 10-100%
in drive + cruise off + moving → 30-100%
- thermald now reads gearShifter (via carState) and controlsState.enabled,
passes them to fan_controller.update()
- Removed BENCH_MODE special case — new rules cover bench automatically
- Removed ignition-based branches — gear is the correct signal
System health overlay:
- Subscribed UI to peripheralState so we can read fanSpeedRpm
- Added FAN row: actual fan% (RPM / 65) to sit alongside LAG/DROP/TEMP/CPU/MEM.
Shows the real fan output vs. what the PID is asking for.
Migrate hot signals from paramsMemory to cereal (frogpilotCarControl):
- Added latRequested @3 and noLatLaneChange @4 to FrogPilotCarControl schema
- controlsd sets FPCC.latRequested / FPCC.noLatLaneChange (send-on-change
already gates the IPC)
- modeld reads from sm['frogpilotCarControl'] (added to its subscribers)
instead of paramsMemory (saves ~20 file-read syscalls/sec)
- carcontroller reads from frogpilot_variables (set in-process by controlsd)
instead of paramsMemory (saves ~100 file-read syscalls/sec in 100Hz path).
Dropped carcontroller's now-unused Params instance and import.
- UI (ui.cc, onroad.cc) reads from sm['frogpilotCarControl'].noLatLaneChange
- Removed LatRequested and no_lat_lane_change param registrations + defaults
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Audit of post-fork param additions found CarCruiseDisplayActual was
written every CAN cycle (gated) but only consumed by hyundaicanfd.py::
create_buttons_alt, which has `return` on line 1 and no active callers.
Write was pure waste. Removed registration, write path, cache field,
and the dead read.
Also dropped the now-unused `from openpilot.common.params import Params`
in hyundaicanfd.py.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
create_steering_messages was constructing a new Params("/dev/shm/params")
object and reading no_lat_lane_change on every CAN steering message build
— i.e. 100 allocations + 100 file reads per second. Now the Params
instance lives on CarController, and the value is read once per update()
cycle and passed as a parameter.
Audited all other hyundai CAN-FD integration code for similar patterns:
- carstate.py — already fixed (previous commit)
- carcontroller.py — other Params references are all in commented-out code
- hyundaicanfd.py::create_buttons_alt — dead code (early return), so the
Params read there never executes; left as-is
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
py-spy showed per-cycle atomic param writes were the dominant cost. Each
put() is mkstemp+fsync+flock+rename+fsync_dir — fine when rare, ruinous at
100Hz. At park with no state changes, these writes were running anyway and
the flock contention was poisoning the whole system.
carstate.py (update + update_canfd): CarSpeedLimit, CarIsMetric,
CarCruiseDisplayActual were written every CAN update. Now cached and
written only on change.
controlsd.py: same fix for LatRequested and no_lat_lane_change. Also
throttle the sentry crash-file stat() from 100Hz to 1Hz.
Also: suppress locationdTemporaryError/paramsdTemporaryError/posenetInvalid
on lat engage (same 2s window as commIssue), and tie suppression to the
LatRequested edge instead of CC.latActive (fires immediately, not after
the 250ms ramp-up delay).
Also: reset Ratekeeper when it falls >1s behind — the ~6s fingerprinting
stall at startup was poisoning the lag metric for the entire session.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New speed_logic.py module converts raw CAN speed limit and GPS speed
into display-ready params. Called from controlsd (live) and
bench_onroad (bench) at ~2Hz. UI reads params to render:
- Current speed (top center, hidden when 0 or no GPS)
- MUTCD speed limit sign (lower-left, normal + nightrider styles)
- Unit-aware display (mph/kph based on CAN DISTANCE_UNIT)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Comment out all tlog() calls in controlsd (100Hz) and carstate (100Hz)
— was causing controlsd to lag from JSON serialization + ZMQ overhead
- tlog() now checks TelemetryEnabled memory param (1/sec file read),
returns immediately when disabled — zero cost when telemetry is off
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Fix controlsd crash: self.state.name AttributeError when state is int
- Move telemetry tlog import to module level in carstate.py (was per-frame)
- Remove FrogPilot screen recorder from UI (was crashing OMX on init)
- Ready screen: boot logo background, 8-bit READY! sprite, error states
(panda not connected, car not recognized) with 10s startup grace period
- ClearPilot menu: always opens to General, QButtonGroup for sidebar,
System Status uses ButtonControl, VPN toggle with process control
- Sidebar hidden on construction (no flash before splash)
- Status window: threaded data collection (QtConcurrent), panda detection
via scene.pandaType (SPI, not USB), only refreshes when visible
- VPN: moved to system/clearpilot/, SIGTERM graceful shutdown, keepalive
ping through tunnel, killall openvpn on disable, launched from
launch_openpilot.sh instead of continue.sh
- Disable gpsd and dashcamd temporarily for perf testing
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Added brakePressed to cruise group, prev_cruise_button and
prev_main_button to buttons group in carstate telemetry. New "engage"
group in controlsd logs state machine state, enabled/active flags, and
stock cruise state every frame for tracing engagement desync bugs.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Logs high-value CAN bus data every frame in update_canfd():
- car: vEgo, aEgo, steering angle, gear, brake/gas, blinkers, standstill
- cruise: enabled, speed, ACCMode, VSetDis, aReq, distance setting, lead dist
- speed_limit: all 3 CLUSTER_SPEED_LIMIT values, school zone, chimes,
calculated speed limit, metric flag
- buttons: cruise buttons, main button, LKAS, main_enabled state
Data flows through the diff-based telemetry logger (only changed values
written to CSV) when TelemetryEnabled param is set.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>