6 Commits

Author SHA1 Message Date
brianhansonxyz cea422b075 locationd: ignore GPS as Kalman input; expand park-cached-output to onroad consumers
locationd: ignore gpsLocation observations entirely (clearpilot_disable_gps
const at the top of handle_gps; falls through to determine_gps_mode's
no-GPS path). gpsd.py keeps publishing real GPS for UI / dashcam / clock
/ night-mode — only locationd ignores it. The previous gpsd.py path was
hard-coding vNED=[0,0,0] while the car was moving 28 m/s, feeding the
Kalman contradictory GPS-vs-IMU velocity observations that propagated into
latcontrol_torque through liveLocationKalman.angularVelocityCalibrated and
caused a real "drift right on straight roads" symptom.

controlsd: short-circuit state_control() while parked. Skips LaC/LoC PID,
MPC, model_v2 reads, lane-change logic — all wasted work when the car
isn't moving. Returns the same enabled=False/latActive=False/longActive=False
CC the original code would have produced, so publish_logs runs unchanged
and card.controls_update keeps the sendcan / tester-present heartbeat
flowing at 100Hz. controlsd CPU dropped from ~59% to ~3% in park.

controlsd: also wire self.FPCC.noLatLaneChange = True/False in the
existing lane-change suppression branch. The Hyundai carcontroller already
reads off frogpilot_variables.no_lat_lane_change for the no-steer signal,
but the UI's distinctive yellow CHANGE_LANE_PATH_COLOR (onroad.cc:901)
reads from frogpilotCarControl.NoLatLaneChange — which nobody was setting,
so the yellow line never appeared during lane-change suppression.

plannerd: skip longitudinal_planner.update + publish + publish_ui_plan
while parked. Downstream controlsd already short-circuits in park, so
longitudinalPlan / uiPlan staleness is fine.

frogpilot_process: same idea — skip frogpilot_planner.update + publish
while parked.

dmonitoringmodeld: mirror the cached-output trick from modeld. Add carState
to the SubMaster, cache the last (model_output, dsp_execution_time) tuple,
and serve it on every frame while gear is in park instead of running DSP
inference on the driver camera.

Together with the existing modeld park-cached-output, the heavy onroad
processing pipeline (modeld → plannerd → controlsd → carcontroller) now
all idles in park and only fires when the car leaves park.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 12:12:38 -05:00
brianhansonxyz dc7e0a2db7 controlsd+calibrationd: suppress commIssue from valid=False cascade
Two fixes that reinstate the pre-revert defenses against the "TAKE CONTROL
IMMEDIATELY / Communication Issue" banner that fires when self-driving
on the baseline modelrevert stack:

calibrationd: publish valid based on calStatus == calibrated, not
sm.all_checks(). Original gate cascaded upstream freq glitches into
liveCalibration.valid=False, which kept locationd.filterInitialized
False, which fed garbage into paramsd, which corrupted steerRatio
(erratic steering). "valid" here is a question about convergence, not
input freshness.

controlsd: narrow the commIssue trigger to genuine comm failures —
not_alive OR can_rcv_timeout. The `not sm.all_checks()` branch also
picked up valid=False, but paramsd / torqued / plannerd / frogpilot_planner
/ dmonitoringd all propagate their sm.all_checks() into msg.valid via
a polling-pattern artifact (freq_ok inside poll='...' subscribers
tracks gaps between drain bursts rather than the publish rate), so
the whole stack flaps valid and trips the banner during normal
driving. Content and rate are fine; just the flag.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 11:00:45 -05:00
brianhansonxyz f896dfe25a modeld: cached-output standby while gear is in park
Narrow re-introduction of the power-save mode: when carState reports
gearShifter == park, serve the last rendered model_output instead of
running GPU inference. First cycle (or before carState is flowing)
still runs one real inference so we have something to cache and serve.
Out-of-park returns to per-frame inference immediately.

Avoids the pitfall of the earlier variable-rate path: this doesn't
change the publish rate on modelV2/cameraOdometry (we still publish
every frame), so downstream freq_ok / valid checks in calibrationd /
locationd / paramsd stay happy. Only the GPU inference is skipped.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 10:49:44 -05:00
brianhansonxyz 2ce6e8fe0c modelrevert: boot fixes + strip remaining variable-rate cruft
controlsd:
- stop writing the removed 'no_lat_lane_change' persistent param
  (key isn't in the whitelist anymore). Write to
  frogpilot_variables.no_lat_lane_change instead so the carcontroller
  read still works and the lane-change-disengage feature is preserved.
- initialize self.driving_gear = False in __init__; it's set at the
  end of step() in update_frogpilot_variables but clearpilot_state_control
  reads it on the first iteration before that's run.

modeld:
- remove the remaining CLEARPILOT variable-rate / standby code path
  that was baked into the initial-import commit (the one our first
  commit captured). Constant 20fps, no ModelStandby/ModelStandbyTs
  writes, no params_memory reads for 'no_lat_lane_change' (which
  isn't registered anymore).
- drop now-unused locals (model_standby, last_standby_ts_write,
  params_memory).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 10:42:11 -05:00
brianhansonxyz 3bd0c942e8 controlsd: re-apply QoL hooks on top of reverted baseline
Re-adds the non-self-drive controlsd integrations that the UI and
memory-param pipeline need:

- import SpeedState from clearpilot.speed_logic
- self.speed_state, speed_state_frame, was_driving_gear init
- subscribe to gpsLocation (ignored in alive/freq_ok/valid gates — OK if
  the GPS daemon isn't publishing)
- clearpilot_state_control:
  - auto-reset ScreenDisplayMode 3→0 on park→drive transition
  - ~2Hz speed-state update driving the speed-limit sign and cruise
    over/under warning sign via ClearpilotCruiseWarning /
    ClearpilotSpeedLimitDisplay memory params

The debug-button (LFA) ScreenDisplayMode cycling already lived in the
reverted baseline (it was in the first commit), so it's preserved.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 13:31:51 -05:00
brianhansonxyz 12da9acfdd revert modeld/controlsd/plannerd/locationd to first-commit baseline
Starting point for rebuilding self-drive from a known-good baseline.
Reverts the following to their state at f46339c:
- selfdrive/modeld/modeld.py (constant 20fps, no variable-rate / standby skip)
- selfdrive/modeld/dmonitoringmodeld.py (no carState sub, no standstill skip)
- selfdrive/controls/controlsd.py (no parked-cycle skip, no FPCC hoisting, no MDPS split)
- selfdrive/controls/lib/longitudinal_planner.py
- selfdrive/locationd/calibrationd.py (valid = sm.all_checks again)
- selfdrive/locationd/paramsd.py
- selfdrive/locationd/torqued.py

All non-self-drive features (thermald fan control, speed limit controller,
cruise warning signs, UI state transitions, GPS fixes, ClearPilot menu,
dashcamd, telemetry, etc.) remain as-is on this branch — only the 4 core
self-drive processes are reverted.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 13:26:36 -05:00
4 changed files with 8 additions and 197 deletions
+4 -9
View File
@@ -1,16 +1,11 @@
#include "safety_hyundai_common.h"
const SteeringLimits HYUNDAI_CANFD_STEERING_LIMITS = {
// CLEARPILOT: bumped from comma defaults (270/2/3/112) by ~20% so this Tucson HDA2
// can hold modest curvature in place. Mirrors the rate-limit shape comma uses for
// its non-CAN-FD high-torque HKG default (384/3/7). Must stay in lockstep with
// STEER_MAX in selfdrive/car/hyundai/values.py — panda enforces independently and
// will reject larger commands if openpilot's value exceeds this.
.max_steer = 324,
.max_rt_delta = 134,
.max_steer = 270,
.max_rt_delta = 112,
.max_rt_interval = 250000,
.max_rate_up = 3,
.max_rate_down = 5,
.max_rate_up = 2,
.max_rate_down = 3,
.driver_torque_allowance = 250,
.driver_torque_factor = 2,
.type = TorqueDriverLimited,
+3 -5
View File
@@ -27,14 +27,12 @@ class CarControllerParams:
self.STEER_STEP = 1 # 100 Hz
if CP.carFingerprint in CANFD_CAR:
# CLEARPILOT: bumped from comma defaults (270/2/3) by ~20% — must stay in
# lockstep with HYUNDAI_CANFD_STEERING_LIMITS in panda/board/safety/safety_hyundai_canfd.h.
self.STEER_MAX = 324
self.STEER_MAX = 270
self.STEER_DRIVER_ALLOWANCE = 250
self.STEER_DRIVER_MULTIPLIER = 2
self.STEER_THRESHOLD = 250
self.STEER_DELTA_UP = 3
self.STEER_DELTA_DOWN = 5
self.STEER_DELTA_UP = 2
self.STEER_DELTA_DOWN = 3
# To determine the limit for your car, find the maximum value that the stock LKAS will request.
# If the max stock LKAS request is <384, add your car to this list.
+1 -6
View File
@@ -681,12 +681,7 @@ class Controls:
self.LoC.reset(v_pid=CS.vEgo)
self.frogpilot_variables.no_lat_lane_change = False
self.FPCC.noLatLaneChange = False
# Call LaC.update with active=False so we get the right lac_log subtype
# for this car's lateralTuning (torque vs pid vs angle). Internally it
# early-returns when active is False — cheap.
lp = self.sm['liveParameters']
_, _, lac_log = self.LaC.update(False, CS, self.VM, lp, self.steer_limited, 0.0,
self.sm['liveLocationKalman'], model_data=self.sm['modelV2'])
lac_log = log.ControlsState.LateralDebugState.new_message()
return CC, lac_log
# Update VehicleModel
@@ -1,177 +0,0 @@
# Session: 2026-04-26 — Hyundai CAN-FD steering torque bump
Documentation for commit `4058269` on `clearpilot`. Reference for any
future re-tuning.
## What changed
Bumped this Tucson HDA2 (CAN-FD platform) from comma's conservative
steer ceiling to a value that gives more headroom on tighter on-ramp
clovers, plus a small rate-limit nudge so the controller can actually
reach the new ceiling within reasonable transient time.
| Constant | Before (comma default for CAN-FD) | After (this commit) | Comma's non-CAN-FD HKG default |
|---|---:|---:|---:|
| `max_steer` / `STEER_MAX` | 270 | **324** | 384 |
| `max_rate_up` / `STEER_DELTA_UP` | 2 | **3** | 3 |
| `max_rate_down` / `STEER_DELTA_DOWN` | 3 | **5** | 7 |
| `max_rt_delta` | 112 | **134** | ~150 |
## Where the change lives — TWO files in lockstep
The panda safety firmware enforces these limits **independently** of
openpilot. If only one side is bumped, panda rejects the larger
commands and you get cut-out / `commIssue` behavior. **Always change
both, always to the same numbers, in the same commit.**
1. **`panda/board/safety/safety_hyundai_canfd.h`** (lines 3-19)
- `HYUNDAI_CANFD_STEERING_LIMITS` struct: `max_steer`, `max_rate_up`,
`max_rate_down`, `max_rt_delta`.
- This is C; modifying it changes the panda firmware hash, which
forces an automatic re-flash on next `pandad` start. No manual
panda flash command needed.
2. **`selfdrive/car/hyundai/values.py`** (CAN-FD branch of
`CarControllerParams.__init__`, lines 29-36)
- `STEER_MAX`, `STEER_DELTA_UP`, `STEER_DELTA_DOWN`.
- Pure Python; picked up on next `controlsd` start.
## What each constant does
- **`max_steer` / `STEER_MAX`** — peak torque magnitude the controller
can request. Hard ceiling. Going past this is the headline "more
torque" knob.
- **`max_rate_up` / `STEER_DELTA_UP`** — per-100Hz-cycle upward slew
cap. Higher = faster ramp into a turn. With `max_rate_up = 3` and
`max_steer = 324`, time from 0 to ceiling is 324 / 3 = 108 cycles =
1.08 s.
- **`max_rate_down` / `STEER_DELTA_DOWN`** — per-cycle downward slew
cap. Higher = faster release back toward straight. We chose 5 (vs
comma's 7) for a smoother release feel.
- **`max_rt_delta`** — cumulative torque change allowed across a
rolling 250 ms window (`max_rt_interval`). It's a long-window
envelope check, separate from the per-cycle rate. Should scale with
`max_steer` — we used `max_steer × ~0.41` to mirror comma's ratio.
- **`driver_torque_allowance` / `STEER_DRIVER_ALLOWANCE`** — driver
wheel torque (Nm read off the wheel) that's tolerated before the
system starts derating its own command. Left at 250.
- **`driver_torque_factor` / `STEER_DRIVER_MULTIPLIER`** — how
aggressively the system fights driver input above the allowance.
Left at 2.
## How to go higher (path to 384)
`384` is the community-consensus safe ceiling for HKG. Comma uses it
as the default for every non-CAN-FD HKG that isn't on the explicit
255-blacklist, and they merged it for HDA1 CAN-FD (EV6 / Ioniq 5) in
[openpilot PR #25723](https://github.com/commaai/openpilot/pull/25723).
The PR author noted "max steer needed to be 384 to make basic turns."
Tucson NX4 HDA2 is **not** on the 255-blacklist (see
[issue #24122](https://github.com/commaai/openpilot/issues/24122) for
the verified blacklist).
To go from 324 → 384:
```c
// panda/board/safety/safety_hyundai_canfd.h
.max_steer = 384,
.max_rt_delta = 158, // ~max_steer × 0.41
.max_rate_up = 3,
.max_rate_down = 5, // or 7 for comma-matched aggressive release
```
```python
# selfdrive/car/hyundai/values.py CAN-FD branch
self.STEER_MAX = 384
self.STEER_DELTA_UP = 3
self.STEER_DELTA_DOWN = 5 # or 7
```
Beyond 384 is uncharted for HKG — comma has not tested past it. Some
forks (sunnypilot has discussions) try higher for very heavy vehicles
but with mixed results. Don't go past 384 without an explicit reason.
## Things to watch for / community-flagged risks at higher values
1. **EPS time-out cut every ~90 frames.** The CAN-FD safety already
forces a brief torque cut to stop the EPS from faulting (the
`min_valid_request_frames = 89`, `max_invalid_request_frames = 2`,
`min_valid_request_rt_interval = 810000` block of
`HYUNDAI_CANFD_STEERING_LIMITS`). This is independent of
`max_steer`. Bumping the ceiling does not lengthen the cut-free
window — you just hold the higher torque for the same ~890 ms before
the brief cut. If you're getting `Steering Temporarily Unavailable`
*during sustained turns*, the issue is this cut, not the ceiling,
and it can't be tuned without risking a real EPS fault.
2. **`steerTempUnavailable` / "Cruise Fault: Restart the Car".** Has
been reported on cars in the 255-blacklist when pushed to 384.
Tucson NX4 is not blacklisted, so 324384 is normally safe — but if
you see this alert during slow sweeping turns, that's the symptom.
Roll back to 270 and confirm.
3. **Lateral accel retune.** Higher torque headroom can cause the
torque controller to overshoot if `latAccelFactor` was tuned for
the old ceiling. EV6/Ioniq 5 testing in PR #25723 had to drop
lateral accel to 2.5 m/s² when bumping from 270 to 384. Watch for
over-correction (zig-zag in lane center) after a bump and retune
`latAccelFactor` in `selfdrive/locationd/torqued.py` or via the
torque-tune Params if needed.
4. **Driver-fight feel.** `driver_torque_allowance = 250` /
`driver_torque_factor = 2` is the blending knob. Most "openpilot
fights my hands" complaints come from people who lowered allowance
or raised factor. Don't touch these without a specific reason.
5. **Panda safety hash mismatch.** Changing
`safety_hyundai_canfd.h` regenerates the panda firmware binary with
a different signed hash. On the next `pandad` start, pandad detects
the mismatch and re-flashes the panda automatically (see
`pandad.log`: "Panda firmware out of date" → "flash: flashing" →
"Done flashing"). Takes ~10 s. No manual action needed; just expect
a brief delay before controls come up.
## Verifying the change took effect
```bash
# 1. Confirm the rebuild happened and panda firmware was re-signed.
grep "panda/board/obj/panda_h7" /tmp/build_only.log 2>/dev/null # or run build_only.sh and watch for "signing N bytes"
# 2. Watch for re-flash on launch.
tail -f /data/log2/current/pandad.log
# Should see: "Panda firmware out of date, update required"
# "flash: flashing"
# "Done flashing"
# 3. Confirm the openpilot side is using the new value.
su - comma -c 'PYTHONPATH=/data/openpilot python3 -c "
from cereal import car
from openpilot.common.params import Params
cp_bytes = Params().get(\"CarParams\")
with car.CarParams.from_bytes(cp_bytes) as cp:
print(\"safetyConfig safetyParam:\", [c.safetyParam for c in cp.safetyConfigs])
"'
# 4. Live-check the actual commanded torque ceiling (drive a moderate turn).
# carControl.actuators.steer should now be able to peak above 0.79 (270/255 normalized)
# but stay under 1.0 (full saturation at the new ceiling).
```
## Rollback
If anything misbehaves, revert just the two-file commit:
```bash
git revert 4058269
chown -R comma:comma /data/openpilot
su - comma -c "bash /data/openpilot/build_only.sh"
# Next pandad launch will re-flash back to 270.
```
## Sources
- [openpilot PR #25723 — HDA1 EV6/Ioniq 5 270 → 384](https://github.com/commaai/openpilot/pull/25723)
- [openpilot issue #24122 — HKG torque blacklist verification](https://github.com/commaai/openpilot/issues/24122)
- [openpilot PR #26427 — Hyundai Tucson 2023 support](https://github.com/commaai/openpilot/pull/26427)
- [sunnypilot — increasing torque help](https://community.sunnypilot.ai/t/increasing-torque-help-needed/2082)
- [sunnypilot — raising torque for heavier vehicles](https://community.sunnypilot.ai/t/raising-the-torque-for-heavier-vehicles/862)